Files
TheRock/rocm-systems/projects/rocprofiler-systems/external/dyninst/stackwalk/h/local_var.h
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

293 lines
7.8 KiB
C++

/*
* See the dyninst/COPYRIGHT file for copyright information.
*
* We provide the Paradyn Tools (below described as "Paradyn")
* on an AS IS basis, and do not warrant its validity or performance.
* We reserve the right to update, modify, or discontinue this
* software at any time. We shall have no obligation to supply such
* updates or modifications or any other form of support to you.
*
* By your use of Paradyn, you understand and agree that we (or any
* other person or entity with proprietary rights in Paradyn) are
* under no obligation to provide either maintenance services,
* update services, notices of latent defects, or correction of
* defects for Paradyn.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined (local_var_h_)
#define local_var_h_
#include <string.h>
#include <vector>
#include "Symbol.h"
#include "Symtab.h"
#include "Type.h"
#include "Function.h"
#include "Architecture.h"
#include "registers/MachRegister.h"
#include "registers/abstract_regs.h"
#include "frame.h"
#include "procstate.h"
#include "walker.h"
#include <string>
#include <map>
using namespace Dyninst;
using namespace SymtabAPI;
using namespace Stackwalker;
static Symtab *getSymtabForName(std::string name)
{
static std::map<std::string, Symtab *> symtabs;
std::map<std::string, Symtab *>::iterator i;
i = symtabs.find(name);
if (i != symtabs.end()) {
return i->second;
}
Symtab *obj = NULL;
Symtab::openFile(obj, name);
symtabs[name] = obj;
return obj;
}
class LVReader : public MemRegReader
{
private:
ProcessState *proc;
int current_depth;
std::vector<Frame> *swalk;
Dyninst::THR_ID thrd;
bool isFrameRegister(MachRegister reg)
{
return reg.isFramePointer();
}
bool isStackRegister(MachRegister reg)
{
return reg.isStackPointer();
}
public:
LVReader(ProcessState *p, int f, std::vector<Frame> *s, Dyninst::THR_ID t) :
proc(p),
current_depth(f),
swalk(s),
thrd(t)
{
}
virtual bool ReadMem(Address addr, void *buffer, unsigned size)
{
return proc->readMem(buffer, addr, size);
}
virtual bool GetReg(MachRegister reg, MachRegisterVal &val)
{
Frame &f = (*swalk)[current_depth];
if (isFrameRegister(reg)) {
val = static_cast<MachRegisterVal>(f.getFP());
return true;
}
if (isStackRegister(reg)) {
val = static_cast<MachRegisterVal>(f.getSP());
return true;
}
if (reg.isPC() || reg == Dyninst::ReturnAddr) {
val = static_cast<MachRegisterVal>(f.getRA());
return true;
}
if (!current_depth) {
return proc->getRegValue(reg, thrd, val);
}
current_depth--;
Frame &g = (*swalk)[current_depth];
Offset offset;
void *symtab_v;
std::string lib;
g.getLibOffset(lib, offset, symtab_v);
Symtab *symtab = getSymtabForName(lib);
if (!symtab)
return false;
bool result = symtab->getRegValueAtFrame(offset, reg, val, this);
current_depth++;
return result;
}
virtual bool start() {
return true;
}
virtual bool done() {
return true;
}
virtual ~LVReader() {}
};
/**
* Given a StackwalkerAPI frame, return the SymtabAPI function
* that created the frame.
**/
static Dyninst::SymtabAPI::Function *getFunctionForFrame(Frame f)
{
Offset offset;
void *symtab_v;
std::string lib_name;
bool result = f.getLibOffset(lib_name, offset, symtab_v);
if (!result)
return NULL;
Symtab *symtab = NULL;
if (symtab_v) {
symtab = (Symtab *) symtab_v;
}
else {
symtab = getSymtabForName(lib_name);
}
Function *func;
result = symtab->getContainingFunction(offset, func);
if (!result)
return NULL;
return func;
}
/**
* Given a frame in a stackwalk, and a local variable, get the value
* of that local variable in the frame.
*
* 'localVar' is the variable that we're getting the value of.
* 'swalk' is a stackwalk from StackwalkerAPI
* 'frame' is an index into swalk and notes the frame that we'll be reading
* the variable from. localVar should be part of the frame defined by
* swalk[frame]
* 'out_buffer' is a buffer where we will write the value of the local variable.
* out_buffer_size should be the size of out_buffer, used to prevent buffer overflows
*
* getLocalVariableValue will return one of the following on success or error
**/
static int glvv_Success = 0;
static int glvv_EParam = -1;
static int glvv_EOutOfScope = -2;
static int glvv_EBufferSize = -3;
static int glvv_EUnknown = -4;
static int getLocalVariableValue(localVar *var,
std::vector<Frame> &swalk, unsigned frame,
void *out_buffer, unsigned out_buffer_size)
{
bool result;
if (!var || frame < 0 || frame >= swalk.size() || !out_buffer) {
return glvv_EParam;
}
/**
* Find the SymtabAPI object for this frame
* Find the offset for this frame's RA()
**/
std::string lib_name;
Offset offset;
void *symtab_v;
swalk[frame].getLibOffset(lib_name, offset, symtab_v);
THR_ID thrd = swalk[frame].getThread();
ProcessState *proc = swalk[frame].getWalker()->getProcessState();
/**
* Find the variable location that is valid at this point.
**/
bool deref;
std::vector<VariableLocation> &locs = var->getLocationLists();
std::vector<VariableLocation>::iterator i;
for (i = locs.begin(); i != locs.end(); i++) {
if (i->lowPC <= offset && offset < i->hiPC) {
break;
}
}
if (i == locs.end()) {
return glvv_EOutOfScope;
}
VariableLocation &loc = *i;
/**
* Interpret the variable location
**/
Address var_addr = 0;
deref = (loc.refClass == storageRef);
switch (loc.stClass) {
case storageAddr:
var_addr = loc.frameOffset;
break;
case storageReg:
case storageRegOffset: {
MachRegisterVal reg_value;
MachRegister reg = loc.mr_reg;
if (loc.stClass == storageRegOffset && reg == -1) {
reg = MachRegister::getFramePointer(proc->getAddressWidth() == 4 ? Arch_x86 : Arch_x86_64);
}
LVReader r(proc, frame, &swalk, thrd);
result = r.GetReg(reg, reg_value);
if (loc.stClass == storageReg) {
var_addr = reg_value;
}
else {
deref = true;
var_addr = reg_value + loc.frameOffset;
}
break;
}
}
/**
* Get the size of the variable
**/
unsigned size = out_buffer_size;
Type *var_type = var->getType();
if (var_type) {
size = var_type->getSize();
}
if (size > out_buffer_size) {
return glvv_EBufferSize;
}
/**
* Read the resulting value
**/
if (deref) {
result = proc->readMem(out_buffer, var_addr, size);
if (!result) {
return glvv_EUnknown;
}
return glvv_Success;
}
if (size > sizeof(var_addr)) {
//Value stored in register, but larger than a register?
return glvv_EBufferSize;
}
memcpy(out_buffer, &var_addr, size);
return glvv_Success;
}
#endif