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
497 lines
11 KiB
C++
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 *> ¶ms_)
|
|
{
|
|
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_;
|
|
}
|