Files
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

396 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
*/
// Base representations for locations in program memory and registers
// We use a two-layered model consisting of AbsLocs (abstract locations)
// and AbsRegions (abstract regions).
//
// An Absloc defines a unique location in memory or a register. We
// consider the stack to be a separate, indexed-from-zero memory location.
//
// An AbsRegion is a set of Abslocs. In essence it is a set, though we
// may be able to use a more efficient internal representation than a
// set. As a TODO, we wish to provide shortcuts for comparing one type
// of AbsRegion to another type more efficiently than the fallback
// point-wise comparison.
#if !defined(ABSLOC_H)
#define ABSLOC_H
#if !defined(_MSC_VER) && !defined(os_freebsd)
#include <values.h>
#endif
#include <assert.h>
#include <ostream>
#include <set>
#include <stddef.h>
#include <string>
#include <vector>
#include "Instruction.h"
#include "DynAST.h"
namespace Dyninst {
namespace ParseAPI {
class Function;
class Block;
}
class Absloc {
public:
typedef enum {
Register,
Stack,
Heap,
PredicatedRegister,
Unknown } Type;
DATAFLOW_EXPORT static Absloc makePC(Dyninst::Architecture arch);
DATAFLOW_EXPORT static Absloc makeSP(Dyninst::Architecture arch);
DATAFLOW_EXPORT static Absloc makeFP(Dyninst::Architecture arch);
// Some static functions for "well-known" Abslocs
DATAFLOW_EXPORT bool isPC() const;
DATAFLOW_EXPORT bool isSPR() const;
DATAFLOW_EXPORT bool isSP() const;
DATAFLOW_EXPORT bool isFP() const;
DATAFLOW_EXPORT Absloc() :
type_(Unknown),
reg_(),
off_(-1),
region_(-1),
func_(NULL),
addr_(-1),
preg_(),
trueCond_(false) {}
DATAFLOW_EXPORT Absloc(MachRegister reg) :
type_(Register),
reg_(reg),
off_(-1),
region_(-1),
func_(NULL),
addr_(-1),
preg_(),
trueCond_(false)
{}
DATAFLOW_EXPORT Absloc(Address addr) :
type_(Heap),
reg_(),
off_(-1),
region_(-1),
func_(NULL),
addr_(addr),
preg_(),
trueCond_(false)
{}
DATAFLOW_EXPORT Absloc(int o,
int r,
ParseAPI::Function *f) :
type_(Stack),
reg_(),
off_(o),
region_(r),
func_(f),
addr_(-1),
preg_(),
trueCond_(false)
{}
DATAFLOW_EXPORT Absloc(MachRegister r, MachRegister p, bool c):
type_(PredicatedRegister),
reg_(r),
off_(-1),
region_(-1),
func_(NULL),
addr_(-1),
preg_(p),
trueCond_(c) {}
DATAFLOW_EXPORT std::string format() const;
DATAFLOW_EXPORT const Type &type() const { return type_; }
DATAFLOW_EXPORT bool isValid() const { return type_ != Unknown; }
DATAFLOW_EXPORT const MachRegister &reg() const { assert(type_ == Register || type_ == PredicatedRegister); return reg_; }
DATAFLOW_EXPORT int off() const { assert(type_ == Stack); return off_; }
DATAFLOW_EXPORT int region() const { assert(type_ == Stack); return region_; }
DATAFLOW_EXPORT ParseAPI::Function *func() const { assert(type_ == Stack); return func_; }
DATAFLOW_EXPORT Address addr() const { assert(type_ == Heap); return addr_; }
DATAFLOW_EXPORT const MachRegister &predReg() const { assert(type_ == PredicatedRegister); return preg_;}
DATAFLOW_EXPORT bool isTrueCondition() const { assert(type_ == PredicatedRegister); return trueCond_;}
DATAFLOW_EXPORT void flipPredicateCondition() { assert(type_ == PredicatedRegister); trueCond_ = !trueCond_; }
DATAFLOW_EXPORT bool operator<(const Absloc &rhs) const;
DATAFLOW_EXPORT bool operator==(const Absloc &rhs) const;
DATAFLOW_EXPORT bool operator!=(const Absloc &rhs) const {
return !(*this == rhs);
}
DATAFLOW_EXPORT static char typeToChar(const Type t) {
switch(t) {
case Register:
return 'r';
case Stack:
return 's';
case Heap:
return 'h';
case PredicatedRegister:
return 'p';
default:
return 'u';
}
}
friend std::ostream &operator<<(std::ostream &os, const Absloc &a) {
os << a.format();
return os;
}
private:
Type type_;
MachRegister reg_;
int off_;
int region_;
ParseAPI::Function *func_;
Address addr_;
MachRegister preg_;
bool trueCond_;
};
class AbsRegion {
public:
// Set operations get included here? Or third-party
// functions?
DATAFLOW_EXPORT bool contains(const Absloc::Type t) const;
DATAFLOW_EXPORT bool contains(const Absloc &abs) const;
DATAFLOW_EXPORT bool contains(const AbsRegion &rhs) const;
// Logically, "intersect(rhs) != 0"
//bool overlaps(const AbsRegion &rhs) const;
DATAFLOW_EXPORT bool containsOfType(Absloc::Type t) const;
//iterator &begin();
//iterator &end();
DATAFLOW_EXPORT bool operator==(const AbsRegion &rhs) const;
DATAFLOW_EXPORT bool operator!=(const AbsRegion &rhs) const;
DATAFLOW_EXPORT bool operator<(const AbsRegion &rhs) const;
DATAFLOW_EXPORT const std::string format() const;
DATAFLOW_EXPORT void insert(const Absloc &abs);
DATAFLOW_EXPORT void insert(const AbsRegion &reg);
DATAFLOW_EXPORT void erase(const Absloc &abs);
DATAFLOW_EXPORT void erase(const AbsRegion &reg);
DATAFLOW_EXPORT AbsRegion() :
type_(Absloc::Unknown),
size_(0) {}
DATAFLOW_EXPORT AbsRegion(Absloc::Type t) :
type_(t),
size_(0) {}
DATAFLOW_EXPORT AbsRegion(Absloc a) :
type_(Absloc::Unknown),
absloc_(a),
size_(0) {}
DATAFLOW_EXPORT void setGenerator(AST::Ptr generator) {
generator_ = generator;
}
DATAFLOW_EXPORT void setSize(size_t size) {
size_ = size;
}
DATAFLOW_EXPORT static bool equivalent(const AbsRegion &lhs,
const AbsRegion &rhs,
Address addr,
ParseAPI::Function *caller,
ParseAPI::Function *callee);
DATAFLOW_EXPORT Absloc absloc() const { return absloc_; }
DATAFLOW_EXPORT Absloc::Type type() const { return type_; }
DATAFLOW_EXPORT size_t size() const { return size_; }
DATAFLOW_EXPORT AST::Ptr generator() const { return generator_; }
DATAFLOW_EXPORT bool isImprecise() const { return type_ != Absloc::Unknown; }
DATAFLOW_EXPORT void flipPredicateCondition() { absloc_.flipPredicateCondition(); }
friend std::ostream &operator<<(std::ostream &os, const AbsRegion &a) {
os << a.format();
return os;
}
private:
// Type is for "we're on the stack but we don't know where".
// Effectively, it's a wildcard.
Absloc::Type type_;
// For specific knowledge.
Absloc absloc_;
// And the AST that gave rise to this Absloc. We use this
// as a generating function (if present and not overridden)
AST::Ptr generator_;
// Size in bits
size_t size_;
};
class Assignment {
public:
typedef dyncompat::shared_ptr<Assignment> Ptr;
struct AssignmentPtrHasher {
size_t operator() (const Ptr& ap) const noexcept {
return (size_t)ap.get();
}
};
typedef std::set<AbsRegion> Aliases;
DATAFLOW_EXPORT const std::vector<AbsRegion> &inputs() const { return inputs_; }
DATAFLOW_EXPORT std::vector<AbsRegion> &inputs() { return inputs_; }
DATAFLOW_EXPORT const InstructionAPI::Instruction &insn() const { return insn_; }
DATAFLOW_EXPORT InstructionAPI::Instruction &insn() { return insn_; }
DATAFLOW_EXPORT Address addr() const { return addr_; }
DATAFLOW_EXPORT const AbsRegion &out() const { return out_; }
DATAFLOW_EXPORT AbsRegion &out() { return out_; }
DATAFLOW_EXPORT const std::string format() const;
// FIXME
Aliases aliases;
// Factory functions.
DATAFLOW_EXPORT static std::set<Assignment::Ptr> create(InstructionAPI::Instruction insn,
Address addr);
DATAFLOW_EXPORT Assignment(const InstructionAPI::Instruction& i,
const Address a,
ParseAPI::Function *f,
ParseAPI::Block *b,
const std::vector<AbsRegion> &ins,
const AbsRegion &o) :
insn_(i),
addr_(a),
func_(f),
block_(b),
inputs_(ins),
out_(o) {}
DATAFLOW_EXPORT Assignment(const InstructionAPI::Instruction& i,
const Address a,
ParseAPI::Function *f,
ParseAPI::Block *b,
const AbsRegion &o) :
insn_(i),
addr_(a),
func_(f),
block_(b),
out_(o) {}
DATAFLOW_EXPORT static Assignment::Ptr makeAssignment(const InstructionAPI::Instruction& i,
const Address a,
ParseAPI::Function *f,
ParseAPI::Block *b,
const std::vector<AbsRegion> &ins,
const AbsRegion &o);
DATAFLOW_EXPORT static Assignment::Ptr makeAssignment(const InstructionAPI::Instruction& i,
const Address a,
ParseAPI::Function *f,
ParseAPI::Block *b,
const AbsRegion &o);
// Internally used method; add a dependence on
// a new abstract region. If this is a new region
// we'll add it to the dependence list. Otherwise
// we'll join the provided input set to the known
// inputs.
DATAFLOW_EXPORT void addInput(const AbsRegion &reg);
DATAFLOW_EXPORT void addInputs(const std::vector<AbsRegion> &regions);
DATAFLOW_EXPORT ParseAPI::Function *func() const { return func_; }
DATAFLOW_EXPORT ParseAPI::Block *block() const { return block_; }
friend std::ostream &operator<<(std::ostream &os, const Assignment::Ptr &a) {
os << a->format();
return os;
}
private:
InstructionAPI::Instruction insn_;
Address addr_;
ParseAPI::Function *func_;
ParseAPI::Block *block_;
std::vector<AbsRegion> inputs_;
AbsRegion out_;
};
// compare assignments by value.
// note this is a fast comparison--it checks output and address only.
struct AssignmentPtrValueComp {
bool operator()(const Assignment::Ptr& a, const Assignment::Ptr& b) const {
if (a->addr() < b->addr()) { return true; }
if (b->addr() < a->addr()) { return false; }
if (a->out() < b->out()) { return true; }
return false;
}
};
// Dyninst namespace
}
#endif