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

437 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_H_POINT_H_
#define PATCHAPI_H_POINT_H_
#include <list>
#include <map>
#include <stddef.h>
#include "PatchCommon.h"
#include "Snippet.h"
#include "util.h"
#include "dyntypes.h"
namespace Dyninst {
namespace PatchAPI {
class PatchCallback;
struct EntrySite_t {
PatchFunction *func;
PatchBlock *block;
EntrySite_t(PatchFunction *f, PatchBlock *b) : func(f), block(b) {}
};
struct CallSite_t {
PatchFunction *func;
PatchBlock *block;
CallSite_t(PatchFunction *f, PatchBlock *b) : func(f), block(b) {}
};
struct ExitSite_t {
PatchFunction *func;
PatchBlock *block;
ExitSite_t(PatchFunction *f, PatchBlock *b) : func(f), block(b) {}
};
struct InsnLoc_t {
PatchBlock *block;
Dyninst::Address addr;
InstructionAPI::Instruction insn;
InsnLoc_t(PatchBlock *b, Dyninst::Address a, InstructionAPI::Instruction i) :
block(b), addr(a), insn(i) {}
};
// Uniquely identify the location of a point; this + a type
// uniquely identifies a point.
struct Location {
static Location Function(PatchFunction *f) {
return Location(f, NULL, 0, InstructionAPI::Instruction(), NULL, true, Function_);
}
static Location Block(PatchBlock *b) {
return Location(NULL, b, 0, InstructionAPI::Instruction(), NULL, true, Block_);
}
static Location BlockInstance(PatchFunction *f, PatchBlock *b, bool trusted = false) {
return Location(f, b, 0, InstructionAPI::Instruction(), NULL, trusted, BlockInstance_);
}
static Location Instruction(InsnLoc_t l) {
return Location(NULL, l.block, l.addr, l.insn, NULL, true, Instruction_);
}
static Location Instruction(PatchBlock *b, Dyninst::Address a) {
return Location(NULL, b, a, InstructionAPI::Instruction(), NULL, false, Instruction_);
}
static Location InstructionInstance(PatchFunction *f, InsnLoc_t l, bool trusted = false) {
return Location(f, l.block, l.addr, l.insn, NULL, trusted, InstructionInstance_);
}
static Location InstructionInstance(PatchFunction *f, PatchBlock *b, Dyninst::Address a) {
return Location(f, b, a, InstructionAPI::Instruction(), NULL, false, InstructionInstance_);
}
static Location InstructionInstance(PatchFunction *f, PatchBlock *b, Dyninst::Address a,
InstructionAPI::Instruction i, bool trusted = false) {
return Location(f, b, a, i, NULL, trusted, InstructionInstance_);
}
static Location Edge(PatchEdge *e) {
return Location(NULL, NULL, 0, InstructionAPI::Instruction(), e, true, Edge_);
}
static Location EdgeInstance(PatchFunction *f, PatchEdge *e) {
return Location(f, NULL, 0, InstructionAPI::Instruction(), e, false, EdgeInstance_);
}
static Location EntrySite(EntrySite_t e) {
return Location(e.func, e.block, 0, InstructionAPI::Instruction(), NULL, true, Entry_);
}
static Location EntrySite(PatchFunction *f, PatchBlock *b, bool trusted = false) {
return Location(f, b, 0, InstructionAPI::Instruction(), NULL, trusted, Entry_);
}
static Location CallSite(CallSite_t c) {
return Location(c.func, c.block, 0, InstructionAPI::Instruction(), NULL, true, Call_);
}
static Location CallSite(PatchFunction *f, PatchBlock *b) {
return Location(f, b, 0, InstructionAPI::Instruction(), NULL, false, Call_);
}
static Location ExitSite(ExitSite_t e) {
return Location(e.func, e.block, 0, InstructionAPI::Instruction(), NULL, true, Exit_);
}
static Location ExitSite(PatchFunction *f, PatchBlock *b) {
return Location(f, b, 0, InstructionAPI::Instruction(), NULL, false, Exit_); }
typedef enum {
Function_,
Block_,
BlockInstance_,
Instruction_,
InstructionInstance_,
Edge_,
EdgeInstance_,
Entry_,
Call_,
Exit_,
Illegal_ } type_t;
bool legal(type_t t) { return t == type; }
InsnLoc_t insnLoc() { return InsnLoc_t(block, addr, insn); }
PatchFunction *func;
PatchBlock *block;
Dyninst::Address addr;
InstructionAPI::Instruction insn;
PatchEdge *edge;
bool trusted;
type_t type;
private:
Location(PatchFunction *f, PatchBlock *b, Dyninst::Address a, InstructionAPI::Instruction i, PatchEdge *e, bool u, type_t t) :
func(f), block(b), addr(a), insn(i), edge(e), trusted(u), type(t) {}
};
// Used in PointType definition
#define type_val(seq) (0x00000001u << seq)
/* A location on the CFG that acts as a container of inserted instances. Points
of different types are distinct even the underlying code relocation and
generation engine happens to put instrumentation from them at the same
place */
class PATCHAPI_EXPORT Point {
friend class PatchMgr;
friend class PatchBlock;
friend class PatchFunction;
public:
// If you want to extend Type, please increment the argument passed
// to type_val.
enum Type {
PreInsn = type_val(0),
PostInsn = type_val(1),
//InsnTaken = type_val(2), // This should be edge instrumentation? bernat, 25JUN11
BlockEntry = type_val(3),
BlockExit = type_val(4),
BlockDuring = type_val(5),
FuncEntry = type_val(6),
FuncExit = type_val(7),
FuncDuring = type_val(8),
EdgeDuring = type_val(9),
LoopStart = type_val(10), // TODO(wenbin)
LoopEnd = type_val(11), // TODO(wenbin)
LoopIterStart = type_val(12), // TODO(wenbin)
LoopIterEnd = type_val(13), // TODO(wenbin)
PreCall = type_val(14),
PostCall = type_val(15),
OtherPoint = type_val(30),
None = type_val(31),
InsnTypes = PreInsn | PostInsn,
BlockTypes = BlockEntry | BlockExit | BlockDuring,
FuncTypes = FuncEntry | FuncExit | FuncDuring,
EdgeTypes = EdgeDuring,
LoopTypes = LoopStart | LoopEnd | LoopIterStart | LoopIterEnd, // TODO(wenbin)
CallTypes = PreCall | PostCall
};
template <class Scope>
static Point* create(Dyninst::Address addr,
Point::Type type,
PatchMgrPtr mgr,
Scope* scope) {
Point* ret = new Point(addr, type, mgr, scope);
return ret;
}
Point() {}
// Block instrumentation /w/ optional function context
Point(Point::Type t, PatchMgrPtr mgr, PatchBlock *, PatchFunction * = NULL);
// Insn instrumentation /w/ optional function context
Point(Point::Type t, PatchMgrPtr mgr, PatchBlock *, Dyninst::Address, InstructionAPI::Instruction, PatchFunction * = NULL);
// Function entry or during
Point(Point::Type t, PatchMgrPtr mgr, PatchFunction *);
// Function call or exit site
Point(Point::Type t, PatchMgrPtr mgr, PatchFunction *, PatchBlock *);
// Edge
Point(Point::Type t, PatchMgrPtr mgr, PatchEdge *, PatchFunction * = NULL);
virtual ~Point();
// Point as a snippet container
typedef std::list<InstancePtr>::iterator instance_iter;
instance_iter begin() { return instanceList_.begin();}
instance_iter end() { return instanceList_.end();}
virtual InstancePtr pushBack(SnippetPtr);
virtual InstancePtr pushFront(SnippetPtr);
bool remove(InstancePtr);
// Remove all snippets in this point
void clear();
// Getters
size_t size();
Dyninst::Address addr() const { return addr_; }
Type type() const {return type_;}
bool empty() const { return instanceList_.empty();}
PatchFunction* getCallee();
PatchObject* obj() const;
const InstructionAPI::Instruction& insn() const { return insn_; }
PatchFunction *func() const { return the_func_; }
PatchBlock *block() const { return the_block_; }
PatchEdge *edge() const { return the_edge_; }
PatchMgrPtr mgr() const { return mgr_; }
// Point type utilities
// Test whether the type contains a specific type.
static bool TestType(Point::Type types, Point::Type trg);
// Add a specific type to a set of types
static void AddType(Point::Type& types, Point::Type trg);
// Remove a specific type from a set of types
static void RemoveType(Point::Type& types, Point::Type trg);
PatchCallback *cb() const;
bool consistency() const;
protected:
bool destroy();
void initCodeStructure();
void changeBlock(PatchBlock *newBlock);
InstanceList instanceList_;
Dyninst::Address addr_{};
Type type_{};
PatchMgrPtr mgr_;
PatchBlock* the_block_{};
PatchEdge* the_edge_{};
PatchFunction* the_func_{};
InstructionAPI::Instruction insn_;
};
inline Point::Type operator|(Point::Type a, Point::Type b) {
Point::Type types = a;
Point::AddType(types, b);
return types;
}
// Type: enum => string
inline const char* type_str(Point::Type type) {
if (type&Point::PreInsn) return "PreInsn ";
if (type&Point::PostInsn) return "PostInsn ";
//if (type&Point::InsnTaken) return "InsnTaken ";
if (type&Point::BlockEntry) return "BlockEntry ";
if (type&Point::BlockExit) return "BlockExit ";
if (type&Point::BlockDuring) return "BlockDuring ";
if (type&Point::FuncEntry) return "FuncEntry ";
if (type&Point::FuncExit) return "FuncExit ";
if (type&Point::FuncDuring) return "FuncDuring ";
if (type&Point::EdgeDuring) return "EdgeDuring ";
if (type&Point::LoopStart) return "LoopStart ";
if (type&Point::LoopEnd) return "LoopEnd ";
if (type&Point::LoopIterStart) return "LoopIterStart ";
if (type&Point::LoopIterEnd) return "LoopIterEnd ";
if (type&Point::PreCall) return "PreCall ";
if (type&Point::PostCall) return "PostCall ";
return "Unknown";
}
enum SnippetType {
SYSTEM,
USER
};
enum SnippetState {
FAILED,
PENDING,
INSERTED
};
/* A representation of a particular snippet inserted at a
particular point */
class PATCHAPI_EXPORT Instance : public dyncompat::enable_shared_from_this<Instance> {
public:
typedef dyncompat::shared_ptr<Instance> Ptr;
Instance(Point* point, SnippetPtr snippet)
: point_(point), snippet_(snippet), state_(PENDING), type_(SYSTEM), guarded_(true) { }
virtual ~Instance() {}
static InstancePtr create(Point*, SnippetPtr,
SnippetType type = SYSTEM, SnippetState state = PENDING);
// Getters and Setters
SnippetState state() const { return state_;}
SnippetType type() const {return type_;}
Point* point() const {return point_;}
SnippetPtr snippet() const {return snippet_;}
void set_state(SnippetState state) { state_ = state; }
void disableRecursiveGuard() { guarded_ = false; }
bool recursiveGuardEnabled() const { return guarded_; }
// Destroy itself
// return false if this snipet instance is not associated with a point
bool destroy();
protected:
Point* point_;
SnippetPtr snippet_;
SnippetState state_;
SnippetType type_;
bool guarded_;
};
/* Factory class for creating a point that could be either PatchAPI::Point or
the subclass of PatchAPI::Point. */
class PATCHAPI_EXPORT PointMaker {
friend class PatchMgr;
public:
PointMaker(PatchMgrPtr mgr) : mgr_(mgr) {}
PointMaker() {}
virtual ~PointMaker() {}
// Location bundles what we need to know.
Point *createPoint(Location loc, Point::Type type);
void setMgr(PatchMgrPtr mgr) { mgr_ = mgr; }
protected:
// User override
virtual Point *mkFuncPoint(Point::Type t, PatchMgrPtr m, PatchFunction *);
virtual Point *mkFuncSitePoint(Point::Type t, PatchMgrPtr m, PatchFunction *, PatchBlock *);
virtual Point *mkBlockPoint(Point::Type t, PatchMgrPtr m, PatchBlock *, PatchFunction *context);
virtual Point *mkInsnPoint(Point::Type t, PatchMgrPtr m, PatchBlock *, Dyninst::Address, InstructionAPI::Instruction,
PatchFunction *context);
virtual Point *mkEdgePoint(Point::Type t, PatchMgrPtr m, PatchEdge *, PatchFunction *context);
PatchMgrPtr mgr_;
};
// Collection classes
typedef std::map<Dyninst::Address, Point *> InsnPoints;
struct BlockPoints {
Point *entry{};
Point *during{};
Point *exit{};
InsnPoints preInsn;
InsnPoints postInsn;
BlockPoints() = default;
BlockPoints(const BlockPoints&) = delete;
BlockPoints(BlockPoints&& other)
{
*this = other;
other.entry = nullptr;
other.during = nullptr;
other.exit = nullptr;
}
bool consistency(const PatchBlock *block, const PatchFunction *func) const;
~BlockPoints();
private:
// used by move constructor to default copy members
BlockPoints& operator=(const BlockPoints&) = default;
};
struct EdgePoints {
Point *during{};
EdgePoints() = default;
EdgePoints(EdgePoints&& other) { during = other.during; other.during = nullptr; }
~EdgePoints() { if (during) delete during; }
bool consistency(const PatchEdge *edge, const PatchFunction *func) const;
EdgePoints(const EdgePoints&) = delete;
};
struct FuncPoints {
Point *entry{};
Point *during{};
std::map<PatchBlock *, Point *> exits;
std::map<PatchBlock *, Point *> preCalls;
std::map<PatchBlock *, Point *> postCalls;
FuncPoints() = default;
FuncPoints(const FuncPoints&) = delete;
~FuncPoints();
bool consistency(const PatchFunction *func) const;
};
}
}
#endif // PATCHAPI_H_POINT_H_