Files
TheRock/rocm-systems/projects/rocprofiler-systems/external/dyninst/symtabAPI/src/Function.C
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

497 lines
11 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
*/
// $Id: Object.C,v 1.31 2008/11/03 15:19:25 jaw Exp $
#include "Symtab.h"
#include "symutil.h"
#include "Module.h"
#include "Collections.h"
#include "Function.h"
#include "VariableLocation.h"
#include "Object.h"
#include "registers/abstract_regs.h"
#if !defined(os_windows)
#include "dwarfFrameParser.h"
#endif
#include <iterator>
#include <algorithm>
#include <iostream>
using namespace std;
using namespace Dyninst;
using namespace Dyninst::SymtabAPI;
FunctionBase::FunctionBase() :
locals(NULL),
params(NULL),
functionSize_(0),
retType_(NULL),
inline_parent(NULL),
frameBaseExpanded_(false),
data(NULL)
{
}
dyncompat::shared_ptr<Type> FunctionBase::getReturnType(Type::do_share_t) const
{
getModule()->exec()->parseTypesNow();
return retType_;
}
bool FunctionBase::setReturnType(dyncompat::shared_ptr<Type> newType)
{
retType_ = newType;
return true;
}
bool FunctionBase::findLocalVariable(std::vector<localVar *> &vars, std::string name)
{
getModule()->exec()->parseTypesNow();
unsigned origSize = vars.size();
if (locals) {
localVar *var = locals->findLocalVar(name);
if (var)
vars.push_back(var);
}
if (params) {
localVar *var = params->findLocalVar(name);
if (var)
vars.push_back(var);
}
if (vars.size() > origSize)
return true;
return false;
}
const FuncRangeCollection &FunctionBase::getRanges()
{
return ranges;
}
bool FunctionBase::getLocalVariables(std::vector<localVar *> &vars)
{
getModule()->exec()->parseTypesNow();
if (!locals)
return false;
auto p = locals->getAllVars();
std::copy(p.begin(), p.end(), back_inserter(vars));
if (p.empty())
return false;
return true;
}
bool FunctionBase::getParams(std::vector<localVar *> &params_)
{
getModule()->exec()->parseTypesNow();
if (!params)
return false;
auto p = params->getAllVars();
std::copy(p.begin(), p.end(), back_inserter(params_));
if (p.empty())
return false;
return true;
}
bool FunctionBase::addLocalVar(localVar *locVar)
{
if (!locals) {
locals = new localVarCollection();
}
locals->addLocalVar(locVar);
return true;
}
bool FunctionBase::addParam(localVar *param)
{
if (!params) {
params = new localVarCollection();
}
params->addLocalVar(param);
return true;
}
FunctionBase *FunctionBase::getInlinedParent()
{
getModule()->exec()->parseTypesNow();
return inline_parent;
}
const InlineCollection &FunctionBase::getInlines()
{
getModule()->exec()->parseTypesNow();
return inlines;
}
FunctionBase::~FunctionBase()
{
if (locals) {
delete locals;
locals = NULL;
}
if (params) {
delete params;
params = NULL;
}
}
std::vector<Dyninst::VariableLocation> &FunctionBase::getFramePtrRefForInit() {
if (inline_parent)
return inline_parent->getFramePtr();
return frameBase_;
}
dyn_mutex &FunctionBase::getFramePtrLock()
{
if (inline_parent)
return inline_parent->getFramePtrLock();
return frameBaseLock_;
}
std::vector<Dyninst::VariableLocation> &FunctionBase::getFramePtr()
{
if (inline_parent)
return inline_parent->getFramePtr();
if (frameBaseExpanded_)
return frameBase_;
frameBaseExpanded_ = true;
std::vector<VariableLocation> orig;
orig.swap(frameBase_);
for (unsigned i = 0; i < orig.size(); ++i) {
expandLocation(orig[i], frameBase_);
}
return frameBase_;
}
bool FunctionBase::setFramePtr(vector<VariableLocation> *locs)
{
frameBase_.clear();
std::copy(locs->begin(), locs->end(), std::back_inserter(frameBase_));
return true;
}
std::pair<std::string, Dyninst::Offset> InlinedFunction::getCallsite()
{
std::string callsite_file = "<unknown>";
if(callsite_file_number > 0 && callsite_file_number < module_->getStrings()->size()) {
callsite_file = (*module_->getStrings())[callsite_file_number].str;
}
return make_pair(callsite_file, callsite_line);
}
void FunctionBase::expandLocation(const VariableLocation &loc,
std::vector<VariableLocation> &ret) {
// We are the frame base, so... WTF?
assert(loc.mr_reg != Dyninst::FrameBase);
#if defined(os_windows)
ret.push_back(loc);
return;
#else
if (loc.mr_reg != Dyninst::CFA) {
ret.push_back(loc);
return;
}
using namespace Dyninst::DwarfDyninst;
auto obj = getModule()->exec()->getObject();
DwarfFrameParser::Ptr frameParser =
DwarfFrameParser::create(*obj->dwarf->frame_dbg(), obj->dwarf->origFile()->e_elfp(), obj->getArch());
std::vector<VariableLocation> FDEs;
Dyninst::DwarfDyninst::FrameErrors_t err;
if(!frameParser) return;
frameParser->getRegsForFunction(std::make_pair(loc.lowPC, loc.hiPC), Dyninst::CFA, FDEs, err);
if (FDEs.empty()) {
// Odd, but happens
return;
}
// This looks surprisingly similar to localVar's version...
// Perhaps we should unify.
std::vector<VariableLocation>::iterator i;
for (i = FDEs.begin(); i != FDEs.end(); i++)
{
Offset fdelowPC = i->lowPC;
Offset fdehiPC = i->hiPC;
Offset frame_lowPC = loc.lowPC;
Offset frame_hiPC = loc.hiPC;
if (frame_hiPC < fdehiPC) {
// We're done since the variable proceeds the frame
// base
break;
}
// low is MAX(frame_lowPC, fdelowPC)
Offset low = (frame_lowPC < fdelowPC) ? fdelowPC : frame_lowPC;
// high is MIN(frame_hiPC, fdehiPC)
Offset high = (frame_hiPC < fdehiPC) ? frame_hiPC : fdehiPC;
VariableLocation newloc;
newloc.stClass = loc.stClass;
newloc.refClass = loc.refClass;
newloc.mr_reg = i->mr_reg;
newloc.frameOffset = loc.frameOffset + i->frameOffset;
newloc.lowPC = low;
newloc.hiPC = high;
/*
cerr << "Created frame pointer ["
<< hex << newloc.lowPC << ".." << newloc.hiPC
<< "], reg " << newloc.mr_reg.name()
<< " /w/ offset " << newloc.frameOffset
<< " = (" << loc.frameOffset
<< "+" << i->frameOffset << ")"
<< ", "
<< storageClass2Str(newloc.stClass)
<< ", "
<< storageRefClass2Str(newloc.refClass) << endl;
*/
ret.push_back(newloc);
}
return;
#endif
}
void *FunctionBase::getData()
{
return data;
}
void FunctionBase::setData(void *d)
{
data = d;
}
Function::Function(Symbol *sym)
: FunctionBase(), Aggregate(sym)
{}
Function::Function()
: FunctionBase()
{}
int Function::getFramePtrRegnum() const
{
return 0;
}
bool Function::setFramePtrRegnum(int)
{
return false;
}
Offset Function::getPtrOffset() const
{
Offset retval = 0;
for (unsigned i = 0; i < symbols_.size(); ++i) {
Offset tmp_off = symbols_[i]->getPtrOffset();
if (tmp_off) {
if (retval == 0) retval = tmp_off;
assert(retval == tmp_off);
}
}
return retval;
}
Offset Function::getTOCOffset() const
{
Offset retval = 0;
for (unsigned i = 0; i < symbols_.size(); ++i) {
Offset tmp_toc = symbols_[i]->getLocalTOC();
if (tmp_toc) {
if (retval == 0) retval = tmp_toc;
assert(retval == tmp_toc);
}
}
return retval;
}
Function::~Function()
{
}
bool Function::removeSymbol(Symbol *sym)
{
removeSymbolInt(sym);
if (symbols_.empty()) {
getModule()->exec()->deleteFunction(this);
}
return true;
}
std::ostream &operator<<(std::ostream &os, const Dyninst::VariableLocation &l)
{
const char *stc = storageClass2Str(l.stClass);
const char *strc = storageRefClass2Str(l.refClass);
os << "{"
<< "storageClass=" << stc
<< " storageRefClass=" << strc
<< " reg=" << l.mr_reg.name()
<< " frameOffset=" << l.frameOffset
<< " lowPC=" << l.lowPC
<< " hiPC=" << l.hiPC
<< "}";
return os;
}
std::ostream &operator<<(std::ostream &os, const Dyninst::SymtabAPI::Function &f)
{
dyncompat::shared_ptr<Type> retType = (const_cast<Function &>(f)).getReturnType(Type::share);
std::string tname(retType ? retType->getName() : "no_type");
const Aggregate *ag = dynamic_cast<const Aggregate *>(&f);
assert(ag);
os << "Function{"
<< " type=" << tname
<< " framePtrRegNum_=" << f.getFramePtrRegnum()
<< " FramePtrLocationList=[";
#if 0
for (unsigned int i = 0; i < f.frameBase_.size(); ++i)
{
os << f.frameBase_[i];
if ( (i + 1) < f.frameBase_.size())
os << ", ";
}
#endif
os << "] ";
os << *ag;
os << "}";
return os;
}
std::string Function::getName() const
{
return getFirstSymbol()->getMangledName();
}
bool FunctionBase::operator==(const FunctionBase &f)
{
if (retType_ && !f.retType_)
return false;
if (!retType_ && f.retType_)
return false;
if (retType_)
if (retType_->getID() != f.retType_->getID())
{
return false;
}
return ((Aggregate &)(*this)) == ((const Aggregate &)f);
}
InlinedFunction::InlinedFunction(FunctionBase *parent) :
FunctionBase(),
callsite_file_number(0),
callsite_line(0),
module_(parent->getModule())
{
inline_parent = parent;
offset_ = parent->getOffset();
dyncompat::unique_lock<dyn_mutex> l(parent->inlines_lock);
parent->inlines.push_back(this);
}
InlinedFunction::~InlinedFunction()
{
}
bool InlinedFunction::removeSymbol(Symbol *)
{
return false;
}
bool InlinedFunction::addMangledName(std::string name, bool /*isPrimary*/, bool /*isDebug*/)
{
name_ = name;
return true;
}
bool InlinedFunction::addPrettyName(std::string name, bool /*isPrimary*/, bool /*isDebug*/)
{
name_ = name;
return true;
}
std::string InlinedFunction::getName() const
{
return name_;
}
Offset InlinedFunction::getOffset() const
{
return offset_;
}
unsigned InlinedFunction::getSize() const
{
return functionSize_;//inline_parent->getSize();
}
void InlinedFunction::setFile(string filename) {
StringTablePtr strs = module_->getStrings();
dyncompat::unique_lock<dyn_mutex> l(strs->lock);
callsite_file_number = strs->ensure(std::move(filename));
}
Module* Function::getModule() const {
return module_;
}