Files
TheRock/rocm-systems/projects/rocprofiler-systems/external/dyninst/patchAPI/h/PatchCFG.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

459 lines
14 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
*/
/* Public Interface */
#ifndef _PATCHAPI_DYNINST_CFG_H_
#define _PATCHAPI_DYNINST_CFG_H_
#include <assert.h>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "CFG.h"
#include "PatchCommon.h"
#include "PatchObject.h"
#include "Point.h"
namespace Dyninst {
namespace PatchAPI {
class PatchParseCallback;
class PatchEdge;
class PatchBlock;
class PatchFunction;
class PatchCallback;
class PATCHAPI_EXPORT PatchEdge {
friend class PatchBlock;
friend class PatchFunction;
friend class PatchObject;
friend class Callback;
friend class PatchParseCallback;
public:
static PatchEdge *create(ParseAPI::Edge *,
PatchBlock *src,
PatchBlock *trg);
PatchEdge(ParseAPI::Edge *internalEdge,
PatchBlock *source,
PatchBlock *target);
PatchEdge(const PatchEdge *parent,
PatchBlock *child_src,
PatchBlock *child_trg);
virtual ~PatchEdge();
// Getters
ParseAPI::Edge *edge() const;
PatchBlock *src();
PatchBlock *trg();
ParseAPI::EdgeTypeEnum type() const;
bool sinkEdge() const;
bool interproc() const;
bool intraproc() const { return !interproc(); }
void remove(Point *);
PatchCallback *cb() const;
bool consistency() const;
std::string format() const;
protected:
ParseAPI::Edge *edge_;
PatchBlock *src_;
PatchBlock *trg_;
EdgePoints points_;
};
class PATCHAPI_EXPORT PatchBlock {
friend class PatchEdge;
friend class PatchFunction;
friend class PatchObject;
friend class PatchParseCallback;
public:
typedef std::map<Address, InstructionAPI::Instruction> Insns;
typedef std::vector<PatchEdge*> edgelist;
static PatchBlock *create(ParseAPI::Block *, PatchFunction *);
PatchBlock(const PatchBlock *parblk, PatchObject *child);
PatchBlock(ParseAPI::Block *block, PatchObject *obj);
virtual ~PatchBlock();
// Getters
Address start() const;
Address end() const;
Address last() const;
Address size() const;
PatchFunction* getFunction(ParseAPI::Function*);
bool isShared();
int containingFuncs() const;
void getInsns(Insns &insns) const;
InstructionAPI::Instruction getInsn(Address a) const;
std::string disassemble() const;
bool containsCall() const { return 0 < numCallEdges(); }
bool containsDynamicCall();
std::string format() const;
std::string long_format() const;
PatchFunction* getCallee();
ParseAPI::Block *block() const;
PatchObject* object() const;
PatchObject *obj() const { return object(); }
const edgelist &sources();
const edgelist &targets();
PatchEdge *findSource(ParseAPI::EdgeTypeEnum type);
PatchEdge *findTarget(ParseAPI::EdgeTypeEnum type);
template <class OutputIterator>
void getFuncs(OutputIterator result);
Point *findPoint(Location loc, Point::Type type, bool create = true);
void remove(Point *);
PatchCallback *cb() const;
bool consistency() const;
bool wasUserAdded() const;
virtual void markModified() {}
protected:
typedef enum {
backwards,
forwards } Direction;
void removeSourceEdge(PatchEdge *e);
void removeTargetEdge(PatchEdge *e);
void destroyPoints();
void addSourceEdge(PatchEdge *e, bool addIfEmpty = true);
void addTargetEdge(PatchEdge *e, bool addIfEmpty = true);
void splitBlock(PatchBlock *succ);
int numRetEdges() const;
int numCallEdges() const;
ParseAPI::Block *block_;
edgelist srclist_;
edgelist trglist_;
PatchObject* obj_;
BlockPoints points_;
};
class PatchLoop;
class PatchLoopTreeNode;
class PATCHAPI_EXPORT PatchFunction {
friend class PatchEdge;
friend class PatchBlock;
friend class PatchObject;
friend class PatchParseCallback;
friend class PatchModifier;
public:
struct compare {
bool operator()(PatchBlock * const &b1,
PatchBlock * const &b2) const {
if(b1->start() < b2->start())
return true;
else
return false;
}
};
typedef std::set<PatchBlock *, compare> Blockset;
static PatchFunction *create(ParseAPI::Function *, PatchObject*);
PatchFunction(ParseAPI::Function *f, PatchObject* o);
PatchFunction(const PatchFunction* parFunc, PatchObject* child);
virtual ~PatchFunction();
const std::string &name() const { return func_->name(); }
Address addr() const { return addr_; }
ParseAPI::Function *function() const { return func_; }
PatchObject *obj() const { return obj_; }
PatchBlock *entry();
const Blockset &blocks();
const Blockset &callBlocks();
//const Blockset &returnBlocks();
const Blockset &exitBlocks();
Point *findPoint(Location loc, Point::Type type, bool create = true);
// Moved to source code because we treat non-returning calls as exits
bool verifyExit(PatchBlock *block) { return exitBlocks().find(block) != exitBlocks().end(); }
bool verifyCall(PatchBlock *block) { return callBlocks().find(block) != callBlocks().end(); }
// Const : no building the exit/call sets (returns true if set is empty)
bool verifyExitConst(const PatchBlock *block) const {
return exit_blocks_.empty() ||
exit_blocks_.find(const_cast<PatchBlock *>(block)) != exit_blocks_.end();
}
bool verifyCallConst(const PatchBlock *block) const {
return call_blocks_.empty() ||
call_blocks_.find(const_cast<PatchBlock *>(block)) != call_blocks_.end();
}
// Fast access to a range of instruction points
bool findInsnPoints(Point::Type type, PatchBlock *block,
InsnPoints::const_iterator &start,
InsnPoints::const_iterator &end);
void remove(Point *);
PatchCallback *cb() const;
bool consistency() const;
virtual void markModified() {}
/* Loops */
PatchLoopTreeNode* getLoopTree();
PatchLoop* findLoop(const char *name);
bool getLoops(vector<PatchLoop*> &loops);
bool getOuterLoops(vector<PatchLoop*> &loops);
/* Dominator info */
/* Return true if A dominates B in this function */
bool dominates(PatchBlock* A, PatchBlock *B);
PatchBlock* getImmediateDominator(PatchBlock *A);
void getImmediateDominates(PatchBlock *A, set<PatchBlock*> &);
void getAllDominates(PatchBlock *A, set<PatchBlock*> &);
/* Post-dominator info */
/* Return true if A post-dominates B in this function */
bool postDominates(PatchBlock* A, PatchBlock *B);
PatchBlock* getImmediatePostDominator(PatchBlock *A);
void getImmediatePostDominates(PatchBlock *A, set<PatchBlock*> &);
void getAllPostDominates(PatchBlock *A, set<PatchBlock*> &);
protected:
// For callbacks from ParseAPI to PatchAPI
void removeBlock(PatchBlock *);
void addBlock(PatchBlock *);
void splitBlock(PatchBlock *first, PatchBlock *second);
void destroyPoints();
void destroyBlockPoints(PatchBlock *block);
void invalidateBlocks();
ParseAPI::Function *func_;
PatchObject* obj_;
Address addr_;
Blockset all_blocks_;
Blockset call_blocks_;
Blockset return_blocks_;
Blockset exit_blocks_;
FuncPoints points_;
// For context-specific
std::map<PatchBlock *, BlockPoints> blockPoints_;
std::map<PatchEdge *, EdgePoints> edgePoints_;
/* Loop details*/
bool _loop_analyzed; // true if loops in the function have been found and stored in _loops
std::set<PatchLoop*> _loops;
map<ParseAPI::Loop*, PatchLoop*> _loop_map;
PatchLoopTreeNode *_loop_root; // NULL if the tree structure has not be calculated
void getLoopsByNestingLevel(vector<PatchLoop*>& lbb, bool outerMostOnly);
void createLoops();
void createLoopHierarchy();
/* Dominator and post-dominator info details */
bool isDominatorInfoReady;
bool isPostDominatorInfoReady;
void fillDominatorInfo();
void fillPostDominatorInfo();
/** set of basic blocks that this basicblock dominates immediately*/
std::map<PatchBlock*, std::set<PatchBlock*>*> immediateDominates;
/** basic block which is the immediate dominator of the basic block */
std::map<PatchBlock*, PatchBlock*> immediateDominator;
/** same as previous two fields, but for postdominator tree */
std::map<PatchBlock*, std::set<PatchBlock*>*> immediatePostDominates;
std::map<PatchBlock*, PatchBlock*> immediatePostDominator;
};
class PATCHAPI_EXPORT PatchLoop
{
friend class PatchFunction;
private:
std::set<PatchEdge*> backEdges;
// The entries of the loop
std::set<PatchBlock*> entries;
// the function this loop is part of
PatchFunction * func;
/** set of loops that are contained (nested) in this loop. */
std::set<PatchLoop*> containedLoops;
/** the basic blocks in the loop */
std::set<PatchBlock*> basicBlocks;
ParseAPI::Loop *loop_;
public:
PatchLoop* parent;
bool containsAddress(Address addr);
bool containsAddressInclusive(Address addr);
/** Sets edges to the set of back edges that define this loop,
returns the number of back edges that define this loop */
int getBackEdges(vector<PatchEdge*> &edges);
/* returns the entry blocks of the loop.
* A natural loop has a single entry block
* and an irreducible loop has mulbile entry blocks
* */
int getLoopEntries(vector<PatchBlock*>&);
/** returns vector of contained loops */
bool getContainedLoops(vector<PatchLoop*> &loops);
/** returns vector of outer contained loops */
bool getOuterLoops(vector<PatchLoop*> &loops);
/** returns all basic blocks in the loop */
bool getLoopBasicBlocks(vector<PatchBlock*> &blocks);
/** returns all basic blocks in this loop, exluding the blocks
of its sub loops. */
bool getLoopBasicBlocksExclusive(vector<PatchBlock*> &blocks);
/** does this loop or its subloops contain the given block? */
bool hasBlock(PatchBlock *b);
/** does this loop contain the given block? */
bool hasBlockExclusive(PatchBlock *b);
/** returns true if this loop is a descendant of the given loop */
bool hasAncestor(PatchLoop *loop);
/** returns the function this loop is in */
PatchFunction * getFunction();
~PatchLoop() { }
std::string format() const;
private:
/** constructor of class */
PatchLoop(PatchObject* obj, ParseAPI::Loop *);
/** get either contained or outer loops, determined by outerMostOnly */
bool getLoops(vector<PatchLoop*>&, bool outerMostOnly) const;
}; // class PatchLoop
class PATCHAPI_EXPORT PatchLoopTreeNode {
public:
// A loop node contains a single Loop instance
PatchLoop *loop;
// The LoopTreeNode instances nested within this loop.
vector<PatchLoopTreeNode *> children;
// LoopTreeNode::LoopTreeNode
// Create a loop tree node for Loop with name n
PatchLoopTreeNode(PatchObject *obj, ParseAPI::LoopTreeNode *l, std::map<ParseAPI::Loop*, PatchLoop*>&);
// Destructor
~PatchLoopTreeNode();
// LoopTreeNode::name
// Return the name of this loop.
const char * name();
// LoopTreeNode::getCalleeName
// Return the function name of the ith callee.
const char * getCalleeName(unsigned int i);
// LoopTreeNode::numCallees
// Return the number of callees contained in this loop's body.
unsigned int numCallees();
//Returns a vector of the functions called by this loop.
bool getCallees(vector<PatchFunction *> &v);
// find loop by hierarchical name
PatchLoop * findLoop(const char *name);
private:
/** name which indicates this loop's relative nesting */
char *hierarchicalName;
// A vector of functions called within the body of this loop (and
// not the body of sub loops).
vector<PatchFunction *> callees;
}; // class LoopTreeNode
template <class OutputIterator>
void PatchBlock::getFuncs(OutputIterator result) {
std::vector<ParseAPI::Function *> pFuncs;
block()->getFuncs(pFuncs);
for (unsigned i = 0; i < pFuncs.size(); ++i) {
PatchFunction *func = getFunction(pFuncs[i]);
*result = func;
++result;
}
}
#define ASSERT_CONSISTENCY_FAILURE 1
#define CONSIST_FAIL {if (ASSERT_CONSISTENCY_FAILURE) assert(0); return false;}
}
}
#endif /* _PATCHAPI_DYNINST_CFG_H_ */