mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-12 21:56:54 +00:00
formatting: force pointers/references with the type
This commit is contained in:
parent
2e74fa357a
commit
d2caaf22e8
@ -6,3 +6,5 @@ AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
|
@ -16,9 +16,9 @@
|
||||
#include "Metrics.h"
|
||||
|
||||
namespace Metrics {
|
||||
std::atomic<Metrics *> Metrics::singleton = nullptr;
|
||||
std::atomic<Metrics*> Metrics::singleton = nullptr;
|
||||
|
||||
const char *to_string(ArgTiming t) {
|
||||
const char* to_string(ArgTiming t) {
|
||||
switch (t) {
|
||||
case ENTRY:
|
||||
return "entry";
|
||||
@ -29,7 +29,7 @@ const char *to_string(ArgTiming t) {
|
||||
}
|
||||
}
|
||||
|
||||
Metrics::Metrics(ObjectIntrospection::options opts, const std::string &savePath)
|
||||
Metrics::Metrics(ObjectIntrospection::options opts, const std::string& savePath)
|
||||
: opts(opts) {
|
||||
writer = std::fstream(savePath, std::ios_base::out);
|
||||
writer << "{ \"metrics\": [" << std::endl;
|
||||
@ -43,7 +43,7 @@ Metrics::~Metrics() {
|
||||
}
|
||||
|
||||
void Metrics::save(std::string object) {
|
||||
Metrics *m = singleton.load();
|
||||
Metrics* m = singleton.load();
|
||||
std::lock_guard<std::mutex> guard(m->writerLock);
|
||||
|
||||
if (m->hasWritten) {
|
||||
@ -54,7 +54,7 @@ void Metrics::save(std::string object) {
|
||||
}
|
||||
}
|
||||
|
||||
void Metrics::saveArg(const char *name, const char *argName, ArgTiming timing,
|
||||
void Metrics::saveArg(const char* name, const char* argName, ArgTiming timing,
|
||||
size_t size) {
|
||||
std::string out = "{\"type\": \"size\", \"traceName\": \"";
|
||||
out += name;
|
||||
@ -69,7 +69,7 @@ void Metrics::saveArg(const char *name, const char *argName, ArgTiming timing,
|
||||
save(out);
|
||||
}
|
||||
|
||||
void Metrics::saveDuration(const char *name,
|
||||
void Metrics::saveDuration(const char* name,
|
||||
std::chrono::milliseconds duration) {
|
||||
std::string out = "{\"type\": \"duration\", \"traceName\": \"";
|
||||
out += name;
|
||||
@ -80,7 +80,7 @@ void Metrics::saveDuration(const char *name,
|
||||
save(out);
|
||||
}
|
||||
|
||||
Tracing::Tracing(const char *name, bool enabled)
|
||||
Tracing::Tracing(const char* name, bool enabled)
|
||||
: name(name), enabled(enabled) {
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ Tracing::~Tracing() {
|
||||
saveDuration(duration);
|
||||
}
|
||||
|
||||
for (auto const &exitFunc : exitFuncs)
|
||||
for (auto const& exitFunc : exitFuncs)
|
||||
exitFunc();
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ bool Tracing::isTimingEnabled() {
|
||||
return enabled || Metrics::isEnabled();
|
||||
}
|
||||
|
||||
bool Tracing::isArgEnabled(const char *argName, ArgTiming timing) {
|
||||
bool Tracing::isArgEnabled(const char* argName, ArgTiming timing) {
|
||||
return enabled || Metrics::isEnabled();
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ void Tracing::start() {
|
||||
}
|
||||
}
|
||||
|
||||
void Tracing::saveArg(const char *argName, ArgTiming timing, size_t size) {
|
||||
void Tracing::saveArg(const char* argName, ArgTiming timing, size_t size) {
|
||||
Metrics::saveArg(name, argName, timing, size);
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ class Metrics {
|
||||
friend class Tracing;
|
||||
|
||||
public:
|
||||
Metrics(ObjectIntrospection::options opts, const std::string &savePath);
|
||||
Metrics(ObjectIntrospection::options opts, const std::string& savePath);
|
||||
~Metrics();
|
||||
|
||||
void enable() {
|
||||
@ -41,7 +41,7 @@ class Metrics {
|
||||
}
|
||||
|
||||
private:
|
||||
static std::atomic<Metrics *> singleton;
|
||||
static std::atomic<Metrics*> singleton;
|
||||
|
||||
ObjectIntrospection::options opts;
|
||||
std::fstream writer;
|
||||
@ -49,7 +49,7 @@ class Metrics {
|
||||
bool hasWritten = false;
|
||||
bool enableAll = false;
|
||||
|
||||
static ObjectIntrospection::options &getOptions() {
|
||||
static ObjectIntrospection::options& getOptions() {
|
||||
return singleton.load()->opts;
|
||||
}
|
||||
|
||||
@ -58,39 +58,39 @@ class Metrics {
|
||||
}
|
||||
|
||||
static void save(std::string object);
|
||||
static void saveArg(const char *name, const char *argName, ArgTiming timing,
|
||||
static void saveArg(const char* name, const char* argName, ArgTiming timing,
|
||||
size_t size);
|
||||
static void saveDuration(const char *name,
|
||||
static void saveDuration(const char* name,
|
||||
std::chrono::milliseconds duration);
|
||||
};
|
||||
|
||||
class Tracing {
|
||||
public:
|
||||
Tracing(const char *name, bool enabled = false);
|
||||
Tracing(const char* name, bool enabled = false);
|
||||
~Tracing();
|
||||
|
||||
void start();
|
||||
|
||||
template <class T>
|
||||
void registerArg(const char *argName, T *value);
|
||||
void registerArg(const char* argName, T* value);
|
||||
|
||||
private:
|
||||
bool isTimingEnabled();
|
||||
bool isArgEnabled(const char *argName, ArgTiming timing);
|
||||
void saveArg(const char *argName, ArgTiming timing, size_t size);
|
||||
bool isArgEnabled(const char* argName, ArgTiming timing);
|
||||
void saveArg(const char* argName, ArgTiming timing, size_t size);
|
||||
void saveDuration(std::chrono::milliseconds duration);
|
||||
|
||||
template <class T>
|
||||
void inspectArg(const char *argName, ArgTiming timing, T *value);
|
||||
void inspectArg(const char* argName, ArgTiming timing, T* value);
|
||||
|
||||
const char *name;
|
||||
const char* name;
|
||||
bool enabled;
|
||||
std::chrono::high_resolution_clock::time_point startTime;
|
||||
std::vector<std::function<void()>> exitFuncs;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void Tracing::registerArg(const char *argName, T *value) {
|
||||
void Tracing::registerArg(const char* argName, T* value) {
|
||||
if (isArgEnabled(argName, ArgTiming::ENTRY)) {
|
||||
inspectArg(argName, ArgTiming::ENTRY, value);
|
||||
}
|
||||
@ -108,7 +108,7 @@ void Tracing::registerArg(const char *argName, T *value) {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Tracing::inspectArg(const char *argName, ArgTiming timing, T *value) {
|
||||
void Tracing::inspectArg(const char* argName, ArgTiming timing, T* value) {
|
||||
size_t size;
|
||||
if (int responseCode = ObjectIntrospection::getObjectSize(
|
||||
value, &size, Metrics::getOptions(), false);
|
||||
|
@ -92,8 +92,8 @@ struct options {
|
||||
bool chaseRawPointers = false;
|
||||
bool generateJitDebugInfo = false;
|
||||
|
||||
friend bool operator==(const options &lhs, const options &rhs);
|
||||
friend bool operator!=(const options &lhs, const options &rhs);
|
||||
friend bool operator==(const options& lhs, const options& rhs);
|
||||
friend bool operator!=(const options& lhs, const options& rhs);
|
||||
};
|
||||
|
||||
constexpr std::string_view OI_SECTION_PREFIX = ".oi.";
|
||||
@ -102,29 +102,29 @@ class OILibrary {
|
||||
friend class OILibraryImpl;
|
||||
|
||||
public:
|
||||
OILibrary(void *TemplateFunc, options opt);
|
||||
OILibrary(void* TemplateFunc, options opt);
|
||||
~OILibrary();
|
||||
int init();
|
||||
int getObjectSize(void *objectAddr, size_t &size);
|
||||
int getObjectSize(void* objectAddr, size_t& size);
|
||||
|
||||
options opts;
|
||||
|
||||
private:
|
||||
class OILibraryImpl *pimpl_;
|
||||
class OILibraryImpl* pimpl_;
|
||||
|
||||
size_t (*fp)(const void *) = nullptr;
|
||||
size_t (*fp)(const void*) = nullptr;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class CodegenHandler {
|
||||
public:
|
||||
static int init(const options &opts = {}, bool checkOptions = true) {
|
||||
OILibrary *lib;
|
||||
static int init(const options& opts = {}, bool checkOptions = true) {
|
||||
OILibrary* lib;
|
||||
return getLibrary(lib, opts, checkOptions);
|
||||
}
|
||||
|
||||
static void teardown() {
|
||||
OILibrary *lib;
|
||||
OILibrary* lib;
|
||||
if (int responseCode = getLibrary(lib);
|
||||
responseCode != Response::OIL_SUCCESS) {
|
||||
return;
|
||||
@ -135,44 +135,44 @@ class CodegenHandler {
|
||||
delete lib;
|
||||
}
|
||||
|
||||
static int getObjectSize(const T &objectAddr, size_t &objectSize) {
|
||||
OILibrary *lib;
|
||||
static int getObjectSize(const T& objectAddr, size_t& objectSize) {
|
||||
OILibrary* lib;
|
||||
if (int responseCode = getLibrary(lib);
|
||||
responseCode != Response::OIL_SUCCESS) {
|
||||
return responseCode;
|
||||
}
|
||||
|
||||
return lib->getObjectSize((void *)&objectAddr, objectSize);
|
||||
return lib->getObjectSize((void*)&objectAddr, objectSize);
|
||||
}
|
||||
|
||||
static int getObjectSize(const T &objectAddr, size_t &objectSize,
|
||||
const options &opts, bool checkOptions = true) {
|
||||
OILibrary *lib;
|
||||
static int getObjectSize(const T& objectAddr, size_t& objectSize,
|
||||
const options& opts, bool checkOptions = true) {
|
||||
OILibrary* lib;
|
||||
if (int responseCode = getLibrary(lib, opts, checkOptions);
|
||||
responseCode != Response::OIL_SUCCESS) {
|
||||
return responseCode;
|
||||
}
|
||||
|
||||
return lib->getObjectSize((void *)&objectAddr, objectSize);
|
||||
return lib->getObjectSize((void*)&objectAddr, objectSize);
|
||||
}
|
||||
|
||||
private:
|
||||
static std::atomic<OILibrary *> *getLib() {
|
||||
static std::atomic<OILibrary *> lib = nullptr;
|
||||
static std::atomic<OILibrary*>* getLib() {
|
||||
static std::atomic<OILibrary*> lib = nullptr;
|
||||
return &lib;
|
||||
}
|
||||
|
||||
static std::atomic<std::atomic<OILibrary *> *> *getBoxedLib() {
|
||||
static std::atomic<std::atomic<OILibrary *> *> boxedLib = nullptr;
|
||||
static std::atomic<std::atomic<OILibrary*>*>* getBoxedLib() {
|
||||
static std::atomic<std::atomic<OILibrary*>*> boxedLib = nullptr;
|
||||
return &boxedLib;
|
||||
}
|
||||
|
||||
static int getLibrary(OILibrary *&result) {
|
||||
std::atomic<OILibrary *> *curBoxedLib = getBoxedLib()->load();
|
||||
static int getLibrary(OILibrary*& result) {
|
||||
std::atomic<OILibrary*>* curBoxedLib = getBoxedLib()->load();
|
||||
if (curBoxedLib == nullptr)
|
||||
return Response::OIL_UNINITIALISED;
|
||||
|
||||
OILibrary *curLib = curBoxedLib->load();
|
||||
OILibrary* curLib = curBoxedLib->load();
|
||||
if (curLib == nullptr)
|
||||
return Response::OIL_UNINITIALISED;
|
||||
|
||||
@ -180,9 +180,9 @@ class CodegenHandler {
|
||||
return Response::OIL_SUCCESS;
|
||||
}
|
||||
|
||||
static int getLibrary(OILibrary *&result, const options &opts,
|
||||
static int getLibrary(OILibrary*& result, const options& opts,
|
||||
bool checkOptions) {
|
||||
std::atomic<OILibrary *> *curBoxedLib = getBoxedLib()->load();
|
||||
std::atomic<OILibrary*>* curBoxedLib = getBoxedLib()->load();
|
||||
|
||||
if (curBoxedLib == nullptr) {
|
||||
if (!getBoxedLib()->compare_exchange_strong(curBoxedLib, getLib())) {
|
||||
@ -190,9 +190,9 @@ class CodegenHandler {
|
||||
}
|
||||
curBoxedLib = getLib();
|
||||
|
||||
int (*sizeFp)(const T &, size_t &) = &getObjectSize;
|
||||
void *typedFp = reinterpret_cast<void *>(sizeFp);
|
||||
OILibrary *newLib = new OILibrary(typedFp, opts);
|
||||
int (*sizeFp)(const T&, size_t&) = &getObjectSize;
|
||||
void* typedFp = reinterpret_cast<void*>(sizeFp);
|
||||
OILibrary* newLib = new OILibrary(typedFp, opts);
|
||||
|
||||
if (int initCode = newLib->init(); initCode != Response::OIL_SUCCESS) {
|
||||
delete newLib;
|
||||
@ -203,7 +203,7 @@ class CodegenHandler {
|
||||
getLib()->store(newLib);
|
||||
}
|
||||
|
||||
OILibrary *curLib = curBoxedLib->load();
|
||||
OILibrary* curLib = curBoxedLib->load();
|
||||
if (curLib == nullptr) {
|
||||
return Response::OIL_INITIALISING;
|
||||
}
|
||||
@ -224,7 +224,7 @@ class CodegenHandler {
|
||||
* Ahead-Of-Time (AOT) compilation.
|
||||
*/
|
||||
template <class T>
|
||||
int getObjectSize(const T &objectAddr, size_t &objectSize, const options &opts,
|
||||
int getObjectSize(const T& objectAddr, size_t& objectSize, const options& opts,
|
||||
bool checkOptions = true) {
|
||||
return CodegenHandler<T>::getObjectSize(objectAddr, objectSize, opts,
|
||||
checkOptions);
|
||||
@ -234,7 +234,7 @@ int getObjectSize(const T &objectAddr, size_t &objectSize, const options &opts,
|
||||
|
||||
template <class T>
|
||||
int __attribute__((weak))
|
||||
getObjectSizeImpl(const T &objectAddr, size_t &objectSize);
|
||||
getObjectSizeImpl(const T& objectAddr, size_t& objectSize);
|
||||
|
||||
#endif
|
||||
|
||||
@ -249,7 +249,7 @@ getObjectSizeImpl(const T &objectAddr, size_t &objectSize);
|
||||
*/
|
||||
template <class T>
|
||||
int __attribute__((noinline))
|
||||
getObjectSize(const T &objectAddr, size_t &objectSize) {
|
||||
getObjectSize(const T& objectAddr, size_t& objectSize) {
|
||||
#ifdef OIL_AOT_COMPILATION
|
||||
if (!getObjectSizeImpl<T>) {
|
||||
return Response::OIL_UNINITIALISED;
|
||||
|
18
src/Common.h
18
src/Common.h
@ -38,7 +38,7 @@ struct ClassMember {
|
||||
};
|
||||
|
||||
struct DrgnClassMemberInfo {
|
||||
struct drgn_type *type;
|
||||
struct drgn_type* type;
|
||||
std::string member_name;
|
||||
uint64_t bit_offset;
|
||||
uint64_t bit_field_size;
|
||||
@ -46,16 +46,14 @@ struct DrgnClassMemberInfo {
|
||||
};
|
||||
|
||||
struct TypeHierarchy {
|
||||
std::map<struct drgn_type *, std::vector<DrgnClassMemberInfo>>
|
||||
classMembersMap;
|
||||
std::map<struct drgn_type *,
|
||||
std::map<struct drgn_type*, std::vector<DrgnClassMemberInfo>> classMembersMap;
|
||||
std::map<struct drgn_type*,
|
||||
std::pair<ContainerInfo, std::vector<struct drgn_qualified_type>>>
|
||||
containerTypeMap;
|
||||
std::map<struct drgn_type *, struct drgn_type *> typedefMap;
|
||||
std::map<struct drgn_type*, struct drgn_type*> typedefMap;
|
||||
std::map<std::string, size_t> sizeMap;
|
||||
std::set<struct drgn_type *> knownDummyTypeList;
|
||||
std::map<struct drgn_type *, struct drgn_type *> pointerToTypeMap;
|
||||
std::set<struct drgn_type *> thriftIssetStructTypes;
|
||||
std::map<struct drgn_type *, std::vector<struct drgn_type *>>
|
||||
descendantClasses;
|
||||
std::set<struct drgn_type*> knownDummyTypeList;
|
||||
std::map<struct drgn_type*, struct drgn_type*> pointerToTypeMap;
|
||||
std::set<struct drgn_type*> thriftIssetStructTypes;
|
||||
std::map<struct drgn_type*, std::vector<struct drgn_type*>> descendantClasses;
|
||||
};
|
||||
|
@ -69,8 +69,8 @@ enum ContainerTypeEnum {
|
||||
LIST_OF_CONTAINER_TYPES
|
||||
#undef X
|
||||
};
|
||||
ContainerTypeEnum containerTypeEnumFromStr(std::string &str);
|
||||
const char *containerTypeEnumToStr(ContainerTypeEnum ty);
|
||||
ContainerTypeEnum containerTypeEnumFromStr(std::string& str);
|
||||
const char* containerTypeEnumToStr(ContainerTypeEnum ty);
|
||||
|
||||
struct ContainerInfo {
|
||||
std::string typeName;
|
||||
@ -85,9 +85,9 @@ struct ContainerInfo {
|
||||
// adapter
|
||||
std::optional<size_t> underlyingContainerIndex{};
|
||||
|
||||
static std::unique_ptr<ContainerInfo> loadFromFile(const fs::path &path);
|
||||
static std::unique_ptr<ContainerInfo> loadFromFile(const fs::path& path);
|
||||
|
||||
bool operator<(const ContainerInfo &rhs) const {
|
||||
bool operator<(const ContainerInfo& rhs) const {
|
||||
return (typeName < rhs.typeName);
|
||||
}
|
||||
};
|
||||
|
@ -28,8 +28,8 @@ extern "C" {
|
||||
#include <sys/user.h>
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const FuncDesc::Range &r) {
|
||||
return os << (void *)r.start << ':' << (void *)r.end;
|
||||
std::ostream& operator<<(std::ostream& os, const FuncDesc::Range& r) {
|
||||
return os << (void*)r.start << ':' << (void*)r.end;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -38,7 +38,7 @@ std::ostream &operator<<(std::ostream &os, const FuncDesc::Range &r) {
|
||||
* location?).
|
||||
*/
|
||||
std::optional<uintptr_t> FuncDesc::Arg::findAddress(
|
||||
struct user_regs_struct *regs, uintptr_t pc) const {
|
||||
struct user_regs_struct* regs, uintptr_t pc) const {
|
||||
auto prevRip = std::exchange(regs->rip, pc);
|
||||
BOOST_SCOPE_EXIT_ALL(&) {
|
||||
regs->rip = prevRip;
|
||||
@ -49,7 +49,7 @@ std::optional<uintptr_t> FuncDesc::Arg::findAddress(
|
||||
drgn_object_deinit(&object);
|
||||
};
|
||||
|
||||
if (auto *err = drgn_object_locate(&locator, regs, &object)) {
|
||||
if (auto* err = drgn_object_locate(&locator, regs, &object)) {
|
||||
LOG(ERROR) << "Error while finding address of argument: " << err->message;
|
||||
drgn_error_destroy(err);
|
||||
return std::nullopt;
|
||||
@ -58,7 +58,7 @@ std::optional<uintptr_t> FuncDesc::Arg::findAddress(
|
||||
return object.address;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> FuncDesc::getArgumentIndex(const std::string &arg,
|
||||
std::optional<uint8_t> FuncDesc::getArgumentIndex(const std::string& arg,
|
||||
bool validateIndex) const {
|
||||
if (arg == "retval") {
|
||||
return std::nullopt;
|
||||
@ -79,8 +79,8 @@ std::optional<uint8_t> FuncDesc::getArgumentIndex(const std::string &arg,
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto *argIdxBegin = arg.data() + it;
|
||||
const auto *argIdxEnd = arg.data() + arg.size();
|
||||
const auto* argIdxBegin = arg.data() + it;
|
||||
const auto* argIdxEnd = arg.data() + arg.size();
|
||||
|
||||
uint8_t argIdx = 0;
|
||||
if (auto res = std::from_chars(argIdxBegin, argIdxEnd, argIdx);
|
||||
@ -105,7 +105,7 @@ std::optional<uint8_t> FuncDesc::getArgumentIndex(const std::string &arg,
|
||||
}
|
||||
|
||||
std::shared_ptr<FuncDesc::TargetObject> FuncDesc::getArgument(
|
||||
const std::string &arg) {
|
||||
const std::string& arg) {
|
||||
std::shared_ptr<FuncDesc::TargetObject> outArg;
|
||||
|
||||
if (arg == "retval") {
|
||||
|
14
src/Descs.h
14
src/Descs.h
@ -72,8 +72,8 @@ struct FuncDesc {
|
||||
return arguments[argPos];
|
||||
}
|
||||
|
||||
std::shared_ptr<FuncDesc::TargetObject> getArgument(const std::string &);
|
||||
std::optional<uint8_t> getArgumentIndex(const std::string &,
|
||||
std::shared_ptr<FuncDesc::TargetObject> getArgument(const std::string&);
|
||||
std::optional<uint8_t> getArgumentIndex(const std::string&,
|
||||
bool = true) const;
|
||||
|
||||
size_t numArgs() const {
|
||||
@ -84,7 +84,7 @@ struct FuncDesc {
|
||||
}
|
||||
|
||||
std::optional<Range> getRange(uintptr_t addr) {
|
||||
for (const auto &range : ranges) {
|
||||
for (const auto& range : ranges) {
|
||||
if (addr >= range.start && addr < range.end) {
|
||||
return range;
|
||||
}
|
||||
@ -103,7 +103,7 @@ struct FuncDesc {
|
||||
* can be found at the given pc (what about if we don't have this
|
||||
* location?).
|
||||
*/
|
||||
virtual std::optional<uintptr_t> findAddress(struct user_regs_struct *regs,
|
||||
virtual std::optional<uintptr_t> findAddress(struct user_regs_struct* regs,
|
||||
uintptr_t pc) const = 0;
|
||||
};
|
||||
|
||||
@ -114,21 +114,21 @@ struct FuncDesc {
|
||||
drgn_object_locator_deinit(&locator);
|
||||
}
|
||||
|
||||
std::optional<uintptr_t> findAddress(struct user_regs_struct *regs,
|
||||
std::optional<uintptr_t> findAddress(struct user_regs_struct* regs,
|
||||
uintptr_t pc) const final;
|
||||
};
|
||||
|
||||
struct Retval final : virtual TargetObject {
|
||||
~Retval() final = default;
|
||||
|
||||
std::optional<uintptr_t> findAddress(struct user_regs_struct *regs,
|
||||
std::optional<uintptr_t> findAddress(struct user_regs_struct* regs,
|
||||
uintptr_t /* pc */) const final {
|
||||
return regs->rax;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const FuncDesc::Range &r);
|
||||
std::ostream& operator<<(std::ostream& os, const FuncDesc::Range& r);
|
||||
|
||||
class GlobalDesc {
|
||||
public:
|
||||
|
@ -31,25 +31,25 @@
|
||||
#endif
|
||||
|
||||
static std::optional<std::reference_wrapper<const std::string>> getEntName(
|
||||
SymbolService &symbols, const irequest &req, OICache::Entity ent) {
|
||||
SymbolService& symbols, const irequest& req, OICache::Entity ent) {
|
||||
if (ent == OICache::Entity::FuncDescs ||
|
||||
ent == OICache::Entity::GlobalDescs) {
|
||||
return req.func;
|
||||
} else {
|
||||
if (req.type == "global") {
|
||||
const auto &globalDesc = symbols.findGlobalDesc(req.func);
|
||||
const auto& globalDesc = symbols.findGlobalDesc(req.func);
|
||||
if (!globalDesc) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return globalDesc->typeName;
|
||||
} else {
|
||||
const auto &funcDesc = symbols.findFuncDesc(req);
|
||||
const auto& funcDesc = symbols.findFuncDesc(req);
|
||||
if (!funcDesc) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto &arg = funcDesc->getArgument(req.arg);
|
||||
const auto& arg = funcDesc->getArgument(req.arg);
|
||||
if (!arg) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@ -59,15 +59,15 @@ static std::optional<std::reference_wrapper<const std::string>> getEntName(
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<fs::path> OICache::getPath(const irequest &req,
|
||||
std::optional<fs::path> OICache::getPath(const irequest& req,
|
||||
Entity ent) const {
|
||||
auto hash = [](const std::string &str) {
|
||||
auto hash = [](const std::string& str) {
|
||||
return std::to_string(std::hash<std::string>{}(str));
|
||||
};
|
||||
|
||||
auto ext = extensions[static_cast<size_t>(ent)];
|
||||
|
||||
const auto &entName = getEntName(*symbols, req, ent);
|
||||
const auto& entName = getEntName(*symbols, req, ent);
|
||||
if (!entName.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@ -76,7 +76,7 @@ std::optional<fs::path> OICache::getPath(const irequest &req,
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool OICache::load(const irequest &req, Entity ent, T &data) {
|
||||
bool OICache::load(const irequest& req, Entity ent, T& data) {
|
||||
if (!isEnabled())
|
||||
return false;
|
||||
try {
|
||||
@ -109,14 +109,14 @@ bool OICache::load(const irequest &req, Entity ent, T &data) {
|
||||
|
||||
ia >> data;
|
||||
return true;
|
||||
} catch (const std::exception &e) {
|
||||
} catch (const std::exception& e) {
|
||||
LOG(WARNING) << "Failed to load from cache: " << e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool OICache::store(const irequest &req, Entity ent, const T &data) {
|
||||
bool OICache::store(const irequest& req, Entity ent, const T& data) {
|
||||
if (!isEnabled())
|
||||
return false;
|
||||
try {
|
||||
@ -141,15 +141,15 @@ bool OICache::store(const irequest &req, Entity ent, const T &data) {
|
||||
oa << *buildID;
|
||||
oa << data;
|
||||
return true;
|
||||
} catch (const std::exception &e) {
|
||||
} catch (const std::exception& e) {
|
||||
LOG(WARNING) << "Failed to write to cache: " << e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define INSTANTIATE_ARCHIVE(...) \
|
||||
template bool OICache::load(const irequest &, Entity, __VA_ARGS__ &); \
|
||||
template bool OICache::store(const irequest &, Entity, const __VA_ARGS__ &);
|
||||
#define INSTANTIATE_ARCHIVE(...) \
|
||||
template bool OICache::load(const irequest&, Entity, __VA_ARGS__&); \
|
||||
template bool OICache::store(const irequest&, Entity, const __VA_ARGS__&);
|
||||
|
||||
INSTANTIATE_ARCHIVE(std::pair<RootInfo, TypeHierarchy>)
|
||||
INSTANTIATE_ARCHIVE(std::unordered_map<std::string, std::shared_ptr<FuncDesc>>)
|
||||
@ -160,7 +160,7 @@ INSTANTIATE_ARCHIVE(std::map<std::string, PaddingInfo>)
|
||||
#undef INSTANTIATE_ARCHIVE
|
||||
|
||||
// Upload all contents of cache for this request
|
||||
bool OICache::upload([[maybe_unused]] const irequest &req) {
|
||||
bool OICache::upload([[maybe_unused]] const irequest& req) {
|
||||
#ifndef OSS_ENABLE
|
||||
if (!isEnabled() || downloadedRemote || !enableUpload)
|
||||
return true;
|
||||
@ -194,7 +194,7 @@ bool OICache::upload([[maybe_unused]] const irequest &req) {
|
||||
}
|
||||
|
||||
// Try to fetch contents of cache
|
||||
bool OICache::download([[maybe_unused]] const irequest &req) {
|
||||
bool OICache::download([[maybe_unused]] const irequest& req) {
|
||||
#ifndef OSS_ENABLE
|
||||
if (!isEnabled() || !enableDownload)
|
||||
return true;
|
||||
@ -233,7 +233,7 @@ bool OICache::download([[maybe_unused]] const irequest &req) {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string OICache::generateRemoteHash(const irequest &req) {
|
||||
std::string OICache::generateRemoteHash(const irequest& req) {
|
||||
auto buildID = symbols->locateBuildID();
|
||||
if (!buildID) {
|
||||
LOG(ERROR) << "Failed to locate buildID";
|
||||
|
@ -50,21 +50,21 @@ class OICache {
|
||||
PaddingInfo,
|
||||
MAX
|
||||
};
|
||||
static constexpr std::array<const char *, static_cast<size_t>(Entity::MAX)>
|
||||
static constexpr std::array<const char*, static_cast<size_t>(Entity::MAX)>
|
||||
extensions{".cc", ".o", ".fd", ".gd", ".th", ".pd"};
|
||||
|
||||
bool isEnabled() const {
|
||||
return !basePath.empty();
|
||||
}
|
||||
std::optional<fs::path> getPath(const irequest &, Entity) const;
|
||||
std::optional<fs::path> getPath(const irequest&, Entity) const;
|
||||
template <typename T>
|
||||
bool store(const irequest &, Entity, const T &);
|
||||
bool store(const irequest&, Entity, const T&);
|
||||
template <typename T>
|
||||
bool load(const irequest &, Entity, T &);
|
||||
bool load(const irequest&, Entity, T&);
|
||||
|
||||
bool upload(const irequest &req);
|
||||
bool download(const irequest &req);
|
||||
bool upload(const irequest& req);
|
||||
bool download(const irequest& req);
|
||||
|
||||
private:
|
||||
std::string generateRemoteHash(const irequest &);
|
||||
std::string generateRemoteHash(const irequest&);
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
274
src/OICodeGen.h
274
src/OICodeGen.h
@ -38,10 +38,10 @@ extern "C" {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
struct ParentMember {
|
||||
drgn_type *type;
|
||||
drgn_type* type;
|
||||
uint64_t bit_offset;
|
||||
|
||||
bool operator<(const ParentMember &parent) const {
|
||||
bool operator<(const ParentMember& parent) const {
|
||||
return (bit_offset < parent.bit_offset);
|
||||
}
|
||||
};
|
||||
@ -72,19 +72,19 @@ class OICodeGen {
|
||||
private:
|
||||
// Private constructor. Please use the fallible `OICodeGen::buildFromConfig`
|
||||
// for the expected behaviour.
|
||||
OICodeGen(const Config &, SymbolService &);
|
||||
OICodeGen(const Config&, SymbolService&);
|
||||
|
||||
public:
|
||||
static std::unique_ptr<OICodeGen> buildFromConfig(const Config &,
|
||||
SymbolService &);
|
||||
bool generate(std::string &code);
|
||||
static std::unique_ptr<OICodeGen> buildFromConfig(const Config&,
|
||||
SymbolService&);
|
||||
bool generate(std::string& code);
|
||||
|
||||
[[deprecated("Use generate(std::string&) instead.")]] bool
|
||||
generateFunctionsForTypesDrgn(std::string &code) {
|
||||
generateFunctionsForTypesDrgn(std::string& code) {
|
||||
return generate(code);
|
||||
}
|
||||
|
||||
bool registerContainer(const fs::path &);
|
||||
bool registerContainer(const fs::path&);
|
||||
|
||||
// TODO: remove me once all the callsites are gone
|
||||
static void initializeCodeGen();
|
||||
@ -97,18 +97,18 @@ class OICodeGen {
|
||||
TypeHierarchy getTypeHierarchy();
|
||||
std::map<std::string, PaddingInfo> getPaddingInfo();
|
||||
|
||||
bool isContainer(drgn_type *type);
|
||||
bool isContainer(drgn_type* type);
|
||||
|
||||
static drgn_type *drgnUnderlyingType(drgn_type *type);
|
||||
static drgn_type* drgnUnderlyingType(drgn_type* type);
|
||||
|
||||
bool buildName(drgn_type *type, std::string &text, std::string &outName);
|
||||
bool buildName(drgn_type* type, std::string& text, std::string& outName);
|
||||
|
||||
std::string typeToTransformedName(drgn_type *type);
|
||||
std::string typeToTransformedName(drgn_type* type);
|
||||
|
||||
bool enumerateTypesRecurse(drgn_type *type);
|
||||
static std::string_view drgnKindStr(drgn_type *type);
|
||||
std::set<drgn_type *> processedTypes;
|
||||
bool isDynamic(drgn_type *type) const;
|
||||
bool enumerateTypesRecurse(drgn_type* type);
|
||||
static std::string_view drgnKindStr(drgn_type* type);
|
||||
std::set<drgn_type*> processedTypes;
|
||||
bool isDynamic(drgn_type* type) const;
|
||||
|
||||
private:
|
||||
Config config{};
|
||||
@ -120,57 +120,57 @@ class OICodeGen {
|
||||
using TemplateParamList =
|
||||
std::vector<std::pair<drgn_qualified_type, std::string>>;
|
||||
|
||||
using SortedTypeDefMap = std::vector<std::pair<drgn_type *, drgn_type *>>;
|
||||
using SortedTypeDefMap = std::vector<std::pair<drgn_type*, drgn_type*>>;
|
||||
|
||||
std::string rootTypeStr;
|
||||
std::string linkageName;
|
||||
std::map<drgn_type *, std::string> unnamedUnion;
|
||||
std::map<drgn_type*, std::string> unnamedUnion;
|
||||
std::map<std::string, size_t> sizeMap;
|
||||
std::map<drgn_type *, ContainerTypeMap> containerTypeMapDrgn;
|
||||
std::map<drgn_type*, ContainerTypeMap> containerTypeMapDrgn;
|
||||
std::vector<std::unique_ptr<ContainerInfo>> containerInfoList;
|
||||
std::vector<drgn_type *> enumTypes;
|
||||
std::vector<drgn_type*> enumTypes;
|
||||
std::vector<std::string> knownTypes;
|
||||
drgn_qualified_type rootType;
|
||||
drgn_qualified_type rootTypeToIntrospect;
|
||||
|
||||
std::map<std::string, std::string> typedefMap;
|
||||
std::map<drgn_type *, std::vector<ParentMember>> parentClasses;
|
||||
std::map<std::string, std::vector<drgn_type *>> childClasses;
|
||||
std::map<drgn_type *, std::vector<drgn_type *>> descendantClasses;
|
||||
std::map<drgn_type*, std::vector<ParentMember>> parentClasses;
|
||||
std::map<std::string, std::vector<drgn_type*>> childClasses;
|
||||
std::map<drgn_type*, std::vector<drgn_type*>> descendantClasses;
|
||||
|
||||
SymbolService &symbols;
|
||||
SymbolService& symbols;
|
||||
|
||||
size_t pad_index = 0;
|
||||
std::unordered_map<drgn_type *, std::pair<size_t, size_t>> paddingIndexMap;
|
||||
std::unordered_map<drgn_type*, std::pair<size_t, size_t>> paddingIndexMap;
|
||||
|
||||
std::map<drgn_type *, drgn_type *> typedefTypes;
|
||||
std::map<drgn_type *, std::vector<DrgnClassMemberInfo>> classMembersMap;
|
||||
std::map<drgn_type *, std::vector<DrgnClassMemberInfo>> classMembersMapCopy;
|
||||
std::map<drgn_type *, std::string> typeToNameMap;
|
||||
std::map<std::string, drgn_type *> nameToTypeMap;
|
||||
std::set<drgn_type *> funcDefTypeList;
|
||||
std::vector<drgn_type *> structDefType;
|
||||
std::set<drgn_type *> knownDummyTypeList;
|
||||
std::map<drgn_type *, drgn_type *> pointerToTypeMap;
|
||||
std::set<drgn_type *> thriftIssetStructTypes;
|
||||
std::vector<drgn_type *> topoSortedStructTypes;
|
||||
std::map<drgn_type*, drgn_type*> typedefTypes;
|
||||
std::map<drgn_type*, std::vector<DrgnClassMemberInfo>> classMembersMap;
|
||||
std::map<drgn_type*, std::vector<DrgnClassMemberInfo>> classMembersMapCopy;
|
||||
std::map<drgn_type*, std::string> typeToNameMap;
|
||||
std::map<std::string, drgn_type*> nameToTypeMap;
|
||||
std::set<drgn_type*> funcDefTypeList;
|
||||
std::vector<drgn_type*> structDefType;
|
||||
std::set<drgn_type*> knownDummyTypeList;
|
||||
std::map<drgn_type*, drgn_type*> pointerToTypeMap;
|
||||
std::set<drgn_type*> thriftIssetStructTypes;
|
||||
std::vector<drgn_type*> topoSortedStructTypes;
|
||||
|
||||
std::set<ContainerInfo> containerTypesFuncDef;
|
||||
|
||||
std::map<std::string, PaddingInfo> paddedStructs;
|
||||
|
||||
std::map<drgn_type *, std::vector<DrgnClassMemberInfo>> &getClassMembersMap();
|
||||
std::map<drgn_type*, std::vector<DrgnClassMemberInfo>>& getClassMembersMap();
|
||||
|
||||
class DrgnString {
|
||||
struct FreeDeleter {
|
||||
void operator()(void *allocated) {
|
||||
void operator()(void* allocated) {
|
||||
free(allocated);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
std::string_view contents;
|
||||
DrgnString(char *data, size_t length)
|
||||
DrgnString(char* data, size_t length)
|
||||
: contents{data, length}, _data{data} {
|
||||
}
|
||||
DrgnString() = delete;
|
||||
@ -179,142 +179,142 @@ class OICodeGen {
|
||||
std::unique_ptr<char, FreeDeleter> _data;
|
||||
};
|
||||
|
||||
static void prependQualifiers(enum drgn_qualifiers, std::string &sb);
|
||||
static void prependQualifiers(enum drgn_qualifiers, std::string& sb);
|
||||
static std::string stripFullyQualifiedName(
|
||||
const std::string &fullyQualifiedName);
|
||||
const std::string& fullyQualifiedName);
|
||||
std::string stripFullyQualifiedNameWithSeparators(
|
||||
const std::string &fullyQualifiedname);
|
||||
static void removeTemplateParamAtIndex(std::vector<std::string> ¶ms,
|
||||
const std::string& fullyQualifiedname);
|
||||
static void removeTemplateParamAtIndex(std::vector<std::string>& params,
|
||||
const size_t index);
|
||||
std::unordered_map<drgn_type *, DrgnString> fullyQualifiedNames;
|
||||
std::optional<const std::string_view> fullyQualifiedName(drgn_type *type);
|
||||
std::unordered_map<drgn_type*, DrgnString> fullyQualifiedNames;
|
||||
std::optional<const std::string_view> fullyQualifiedName(drgn_type* type);
|
||||
static SortedTypeDefMap getSortedTypeDefMap(
|
||||
const std::map<drgn_type *, drgn_type *> &typedefTypeMap);
|
||||
const std::map<drgn_type*, drgn_type*>& typedefTypeMap);
|
||||
|
||||
std::optional<ContainerInfo> getContainerInfo(drgn_type *type);
|
||||
std::optional<ContainerInfo> getContainerInfo(drgn_type* type);
|
||||
void printAllTypes();
|
||||
void printAllTypeNames();
|
||||
|
||||
static void addPaddingForBaseClass(drgn_type *type,
|
||||
std::vector<std::string> &def);
|
||||
void addTypeToName(drgn_type *type, std::string name);
|
||||
static void addPaddingForBaseClass(drgn_type* type,
|
||||
std::vector<std::string>& def);
|
||||
void addTypeToName(drgn_type* type, std::string name);
|
||||
bool generateNamesForTypes();
|
||||
bool generateJitCode(std::string &code);
|
||||
bool generateStructDefs(std::string &code);
|
||||
bool generateStructDef(drgn_type *e, std::string &code);
|
||||
bool getDrgnTypeName(drgn_type *type, std::string &outName);
|
||||
bool generateJitCode(std::string& code);
|
||||
bool generateStructDefs(std::string& code);
|
||||
bool generateStructDef(drgn_type* e, std::string& code);
|
||||
bool getDrgnTypeName(drgn_type* type, std::string& outName);
|
||||
|
||||
bool getDrgnTypeNameInt(drgn_type *type, std::string &outName);
|
||||
bool recordChildren(drgn_type *type);
|
||||
bool getDrgnTypeNameInt(drgn_type* type, std::string& outName);
|
||||
bool recordChildren(drgn_type* type);
|
||||
bool enumerateChildClasses();
|
||||
bool populateDefsAndDecls();
|
||||
static void memberTransformName(
|
||||
std::map<std::string, std::string> &templateTransformMap,
|
||||
std::string &typeName);
|
||||
std::map<std::string, std::string>& templateTransformMap,
|
||||
std::string& typeName);
|
||||
|
||||
bool getMemberDefinition(drgn_type *type);
|
||||
bool isKnownType(const std::string &type);
|
||||
bool isKnownType(const std::string &type, std::string &matched);
|
||||
bool getMemberDefinition(drgn_type* type);
|
||||
bool isKnownType(const std::string& type);
|
||||
bool isKnownType(const std::string& type, std::string& matched);
|
||||
|
||||
static bool getTemplateParams(
|
||||
drgn_type *type, size_t numTemplateParams,
|
||||
std::vector<std::pair<drgn_qualified_type, std::string>> &v);
|
||||
drgn_type* type, size_t numTemplateParams,
|
||||
std::vector<std::pair<drgn_qualified_type, std::string>>& v);
|
||||
|
||||
bool enumerateTemplateParamIdxs(drgn_type *type,
|
||||
const ContainerInfo &containerInfo,
|
||||
const std::vector<size_t> ¶mIdxs,
|
||||
bool &ifStub);
|
||||
bool getContainerTemplateParams(drgn_type *type, bool &ifStub);
|
||||
void enumerateDescendants(drgn_type *type, drgn_type *baseType);
|
||||
void getFuncDefinitionStr(std::string &code, drgn_type *type,
|
||||
const std::string &typeName);
|
||||
std::optional<uint64_t> getDrgnTypeSize(drgn_type *type);
|
||||
bool enumerateTemplateParamIdxs(drgn_type* type,
|
||||
const ContainerInfo& containerInfo,
|
||||
const std::vector<size_t>& paramIdxs,
|
||||
bool& ifStub);
|
||||
bool getContainerTemplateParams(drgn_type* type, bool& ifStub);
|
||||
void enumerateDescendants(drgn_type* type, drgn_type* baseType);
|
||||
void getFuncDefinitionStr(std::string& code, drgn_type* type,
|
||||
const std::string& typeName);
|
||||
std::optional<uint64_t> getDrgnTypeSize(drgn_type* type);
|
||||
|
||||
std::optional<std::string> getNameForType(drgn_type *type);
|
||||
std::optional<std::string> getNameForType(drgn_type* type);
|
||||
|
||||
static std::string preProcessUniquePtr(drgn_type *type, std::string name);
|
||||
std::string transformTypeName(drgn_type *type, std::string &text);
|
||||
static std::string templateTransformType(const std::string &typeName);
|
||||
static std::string structNameTransformType(const std::string &typeName);
|
||||
static std::string preProcessUniquePtr(drgn_type* type, std::string name);
|
||||
std::string transformTypeName(drgn_type* type, std::string& text);
|
||||
static std::string templateTransformType(const std::string& typeName);
|
||||
static std::string structNameTransformType(const std::string& typeName);
|
||||
|
||||
bool addPadding(uint64_t padding_bits, std::string &code);
|
||||
bool addPadding(uint64_t padding_bits, std::string& code);
|
||||
static void deduplicateMemberName(
|
||||
std::unordered_map<std::string, int> &memberNames,
|
||||
std::string &memberName);
|
||||
std::unordered_map<std::string, int>& memberNames,
|
||||
std::string& memberName);
|
||||
std::optional<uint64_t> generateMember(
|
||||
const DrgnClassMemberInfo &m,
|
||||
std::unordered_map<std::string, int> &memberNames,
|
||||
uint64_t currOffsetBits, std::string &code, bool isInUnion);
|
||||
bool generateParent(drgn_type *p,
|
||||
std::unordered_map<std::string, int> &memberNames,
|
||||
uint64_t &currOffsetBits, std::string &code,
|
||||
const DrgnClassMemberInfo& m,
|
||||
std::unordered_map<std::string, int>& memberNames,
|
||||
uint64_t currOffsetBits, std::string& code, bool isInUnion);
|
||||
bool generateParent(drgn_type* p,
|
||||
std::unordered_map<std::string, int>& memberNames,
|
||||
uint64_t& currOffsetBits, std::string& code,
|
||||
size_t offsetToNextMember);
|
||||
std::optional<uint64_t> getAlignmentRequirements(drgn_type *e);
|
||||
bool generateStructMembers(drgn_type *e,
|
||||
std::unordered_map<std::string, int> &memberNames,
|
||||
std::string &code, uint64_t &out_offset_bits,
|
||||
PaddingInfo &paddingInfo,
|
||||
bool &violatesAlignmentRequirement,
|
||||
std::optional<uint64_t> getAlignmentRequirements(drgn_type* e);
|
||||
bool generateStructMembers(drgn_type* e,
|
||||
std::unordered_map<std::string, int>& memberNames,
|
||||
std::string& code, uint64_t& out_offset_bits,
|
||||
PaddingInfo& paddingInfo,
|
||||
bool& violatesAlignmentRequirement,
|
||||
size_t offsetToNextMember);
|
||||
void getFuncDefClassMembers(std::string &code, drgn_type *type,
|
||||
std::unordered_map<std::string, int> &memberNames,
|
||||
void getFuncDefClassMembers(std::string& code, drgn_type* type,
|
||||
std::unordered_map<std::string, int>& memberNames,
|
||||
bool skipPadding = false);
|
||||
bool isDrgnSizeComplete(drgn_type *type);
|
||||
bool isDrgnSizeComplete(drgn_type* type);
|
||||
|
||||
static bool getEnumUnderlyingTypeStr(drgn_type *e,
|
||||
std::string &enumUnderlyingTypeStr);
|
||||
static bool getEnumUnderlyingTypeStr(drgn_type* e,
|
||||
std::string& enumUnderlyingTypeStr);
|
||||
|
||||
bool ifEnumerateClass(const std::string &typeName);
|
||||
bool ifEnumerateClass(const std::string& typeName);
|
||||
|
||||
bool enumerateClassParents(drgn_type *type, const std::string &typeName);
|
||||
bool enumerateClassMembers(drgn_type *type, const std::string &typeName,
|
||||
bool &isStubbed);
|
||||
bool enumerateClassTemplateParams(drgn_type *type,
|
||||
const std::string &typeName,
|
||||
bool &isStubbed);
|
||||
bool ifGenerateMemberDefinition(const std::string &typeName);
|
||||
bool generateMemberDefinition(drgn_type *type, std::string &typeName);
|
||||
bool enumerateClassParents(drgn_type* type, const std::string& typeName);
|
||||
bool enumerateClassMembers(drgn_type* type, const std::string& typeName,
|
||||
bool& isStubbed);
|
||||
bool enumerateClassTemplateParams(drgn_type* type,
|
||||
const std::string& typeName,
|
||||
bool& isStubbed);
|
||||
bool ifGenerateMemberDefinition(const std::string& typeName);
|
||||
bool generateMemberDefinition(drgn_type* type, std::string& typeName);
|
||||
std::optional<std::pair<std::string_view, std::string_view>> isMemberToStub(
|
||||
const std::string &type, const std::string &member);
|
||||
std::optional<std::string_view> isTypeToStub(const std::string &typeName);
|
||||
bool isTypeToStub(drgn_type *type, const std::string &typeName);
|
||||
bool isEmptyClassOrFunctionType(drgn_type *type, const std::string &typeName);
|
||||
bool enumerateClassType(drgn_type *type);
|
||||
bool enumerateTypeDefType(drgn_type *type);
|
||||
bool enumerateEnumType(drgn_type *type);
|
||||
bool enumeratePointerType(drgn_type *type);
|
||||
bool enumeratePrimitiveType(drgn_type *type);
|
||||
bool enumerateArrayType(drgn_type *type);
|
||||
const std::string& type, const std::string& member);
|
||||
std::optional<std::string_view> isTypeToStub(const std::string& typeName);
|
||||
bool isTypeToStub(drgn_type* type, const std::string& typeName);
|
||||
bool isEmptyClassOrFunctionType(drgn_type* type, const std::string& typeName);
|
||||
bool enumerateClassType(drgn_type* type);
|
||||
bool enumerateTypeDefType(drgn_type* type);
|
||||
bool enumerateEnumType(drgn_type* type);
|
||||
bool enumeratePointerType(drgn_type* type);
|
||||
bool enumeratePrimitiveType(drgn_type* type);
|
||||
bool enumerateArrayType(drgn_type* type);
|
||||
|
||||
bool isUnnamedStruct(drgn_type *type);
|
||||
bool isUnnamedStruct(drgn_type* type);
|
||||
|
||||
std::string getAnonName(drgn_type *, const char *);
|
||||
std::string getStructName(drgn_type *type) {
|
||||
std::string getAnonName(drgn_type*, const char*);
|
||||
std::string getStructName(drgn_type* type) {
|
||||
return getAnonName(type, "__anon_struct_");
|
||||
}
|
||||
std::string getUnionName(drgn_type *type) {
|
||||
std::string getUnionName(drgn_type* type) {
|
||||
return getAnonName(type, "__anon_union_");
|
||||
}
|
||||
static void declareThriftStruct(std::string &code, std::string_view name);
|
||||
static void declareThriftStruct(std::string& code, std::string_view name);
|
||||
|
||||
bool isNumMemberGreaterThanZero(drgn_type *type);
|
||||
void getClassMembersIncludingParent(drgn_type *type,
|
||||
std::vector<DrgnClassMemberInfo> &out);
|
||||
bool isNumMemberGreaterThanZero(drgn_type* type);
|
||||
void getClassMembersIncludingParent(drgn_type* type,
|
||||
std::vector<DrgnClassMemberInfo>& out);
|
||||
bool staticAssertMemberOffsets(
|
||||
const std::string &struct_name, drgn_type *struct_type,
|
||||
std::string &assert_str,
|
||||
std::unordered_map<std::string, int> &member_names,
|
||||
const std::string& struct_name, drgn_type* struct_type,
|
||||
std::string& assert_str,
|
||||
std::unordered_map<std::string, int>& member_names,
|
||||
uint64_t base_offset = 0);
|
||||
bool addStaticAssertsForType(drgn_type *type, bool generateAssertsForOffsets,
|
||||
std::string &code);
|
||||
bool buildNameInt(drgn_type *type, std::string &nameWithoutTemplate,
|
||||
std::string &outName);
|
||||
bool addStaticAssertsForType(drgn_type* type, bool generateAssertsForOffsets,
|
||||
std::string& code);
|
||||
bool buildNameInt(drgn_type* type, std::string& nameWithoutTemplate,
|
||||
std::string& outName);
|
||||
void replaceTemplateOperator(
|
||||
std::vector<std::pair<drgn_qualified_type, std::string>> &template_params,
|
||||
std::vector<std::string> &template_params_strings, size_t index);
|
||||
std::vector<std::pair<drgn_qualified_type, std::string>>& template_params,
|
||||
std::vector<std::string>& template_params_strings, size_t index);
|
||||
void replaceTemplateParameters(
|
||||
drgn_type *type,
|
||||
std::vector<std::pair<drgn_qualified_type, std::string>> &template_params,
|
||||
std::vector<std::string> &template_params_strings,
|
||||
const std::string &nameWithoutTemplate);
|
||||
drgn_type* type,
|
||||
std::vector<std::pair<drgn_qualified_type, std::string>>& template_params,
|
||||
std::vector<std::string>& template_params_strings,
|
||||
const std::string& nameWithoutTemplate);
|
||||
};
|
||||
|
@ -52,10 +52,10 @@ using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
using namespace ObjectIntrospection;
|
||||
|
||||
static const char *symbolLookupCallback(
|
||||
[[maybe_unused]] void *disInfo, [[maybe_unused]] uint64_t referenceValue,
|
||||
uint64_t *referenceType, [[maybe_unused]] uint64_t referencePC,
|
||||
[[maybe_unused]] const char **referenceName) {
|
||||
static const char* symbolLookupCallback(
|
||||
[[maybe_unused]] void* disInfo, [[maybe_unused]] uint64_t referenceValue,
|
||||
uint64_t* referenceType, [[maybe_unused]] uint64_t referencePC,
|
||||
[[maybe_unused]] const char** referenceName) {
|
||||
*referenceType = LLVMDisassembler_ReferenceType_InOut_None;
|
||||
return nullptr;
|
||||
}
|
||||
@ -101,7 +101,7 @@ OICompiler::Disassembler::operator()() {
|
||||
}
|
||||
|
||||
size_t instSize = LLVMDisasmInstruction(
|
||||
disassemblerContext, const_cast<uint8_t *>(std::data(funcText)),
|
||||
disassemblerContext, const_cast<uint8_t*>(std::data(funcText)),
|
||||
std::size(funcText), 0, std::data(disassemblyBuffer),
|
||||
std::size(disassemblyBuffer));
|
||||
if (instSize == 0) {
|
||||
@ -192,8 +192,8 @@ class OIMemoryManager : public RTDyldMemoryManager {
|
||||
uintptr_t dataSegBase = 0;
|
||||
const uintptr_t dataSegLimit = 0;
|
||||
|
||||
uint8_t *allocate(uintptr_t Size, unsigned Alignment, bool isCode) {
|
||||
auto *allocOffset = isCode ? &textSegBase : &dataSegBase;
|
||||
uint8_t* allocate(uintptr_t Size, unsigned Alignment, bool isCode) {
|
||||
auto* allocOffset = isCode ? &textSegBase : &dataSegBase;
|
||||
auto allocLimit = isCode ? textSegLimit : dataSegLimit;
|
||||
|
||||
VLOG(1) << "allocateFromSlab " << (isCode ? "Code " : "Data ") << " Size "
|
||||
@ -211,19 +211,19 @@ class OIMemoryManager : public RTDyldMemoryManager {
|
||||
report_fatal_error("Can't allocate enough memory from slab");
|
||||
}
|
||||
|
||||
auto §ions = isCode ? functionSections : dataSections;
|
||||
sections.emplace_back((void *)allocAddr, Size);
|
||||
auto& sections = isCode ? functionSections : dataSections;
|
||||
sections.emplace_back((void*)allocAddr, Size);
|
||||
|
||||
*allocOffset = newAllocOffset;
|
||||
|
||||
VLOG(1) << "allocateFromSlab return: " << std::hex << allocAddr;
|
||||
return (uint8_t *)allocAddr;
|
||||
return (uint8_t*)allocAddr;
|
||||
}
|
||||
};
|
||||
|
||||
SmallVector<Slab, 4> Slabs{};
|
||||
OIMemoryManager(std::shared_ptr<SymbolService> ss,
|
||||
const std::unordered_map<std::string, uintptr_t> &synths)
|
||||
const std::unordered_map<std::string, uintptr_t>& synths)
|
||||
: RTDyldMemoryManager{},
|
||||
symbols{std::move(ss)},
|
||||
syntheticSymbols{synths} {
|
||||
@ -236,33 +236,33 @@ class OIMemoryManager : public RTDyldMemoryManager {
|
||||
void reserveAllocationSpace(uintptr_t, uint32_t, uintptr_t, uint32_t,
|
||||
uintptr_t, uint32_t) override;
|
||||
|
||||
uint8_t *allocateCodeSection(uintptr_t, unsigned, unsigned,
|
||||
uint8_t* allocateCodeSection(uintptr_t, unsigned, unsigned,
|
||||
StringRef) override;
|
||||
uint8_t *allocateDataSection(uintptr_t, unsigned, unsigned, StringRef,
|
||||
uint8_t* allocateDataSection(uintptr_t, unsigned, unsigned, StringRef,
|
||||
bool) override;
|
||||
|
||||
/* Hook to set up proper memory permission. We don't handle that */
|
||||
bool finalizeMemory(std::string *) override {
|
||||
bool finalizeMemory(std::string*) override {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Hook to locate symbols in the remote process */
|
||||
JITSymbol findSymbol(const std::string &) override;
|
||||
JITSymbol findSymbol(const std::string&) override;
|
||||
|
||||
/*
|
||||
* We don't use EH frames in this context, as we generate then copy to another
|
||||
* process, and enabling them causes issues with folly crashing on oid exit.
|
||||
*/
|
||||
void registerEHFrames(uint8_t *, uint64_t, size_t) override {
|
||||
void registerEHFrames(uint8_t*, uint64_t, size_t) override {
|
||||
}
|
||||
void deregisterEHFrames() override {
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<SymbolService> symbols;
|
||||
const std::unordered_map<std::string, uintptr_t> &syntheticSymbols;
|
||||
const std::unordered_map<std::string, uintptr_t>& syntheticSymbols;
|
||||
|
||||
Slab ¤tSlab() {
|
||||
Slab& currentSlab() {
|
||||
assert(!Slabs.empty());
|
||||
return Slabs.back();
|
||||
}
|
||||
@ -285,7 +285,7 @@ void OIMemoryManager::reserveAllocationSpace(
|
||||
|
||||
Slabs.emplace_back(totalSz, codeSize, roDataSize + rwDataSize + 128);
|
||||
|
||||
const auto &currSlab = currentSlab();
|
||||
const auto& currSlab = currentSlab();
|
||||
VLOG(1) << "reserveAllocationSpace: " << std::hex << "SlabBase "
|
||||
<< currSlab.memBlock.base() << " textSegBaseAlloc "
|
||||
<< currSlab.textSegBase << " textSegLimit " << currSlab.textSegLimit
|
||||
@ -293,7 +293,7 @@ void OIMemoryManager::reserveAllocationSpace(
|
||||
<< currSlab.dataSegLimit;
|
||||
}
|
||||
|
||||
uint8_t *OIMemoryManager::allocateCodeSection(
|
||||
uint8_t* OIMemoryManager::allocateCodeSection(
|
||||
uintptr_t size, unsigned alignment, [[maybe_unused]] unsigned sectionID,
|
||||
StringRef sectionName) {
|
||||
VLOG(1) << "allocateCodeSection(Size = " << size
|
||||
@ -303,7 +303,7 @@ uint8_t *OIMemoryManager::allocateCodeSection(
|
||||
return currentSlab().allocate(size, alignment, true /* isCode */);
|
||||
}
|
||||
|
||||
uint8_t *OIMemoryManager::allocateDataSection(
|
||||
uint8_t* OIMemoryManager::allocateDataSection(
|
||||
uintptr_t size, unsigned alignment, [[maybe_unused]] unsigned sectionID,
|
||||
StringRef sectionName, [[maybe_unused]] bool isReadOnly) {
|
||||
VLOG(1) << "allocateDataSection(Size = " << size
|
||||
@ -321,7 +321,7 @@ uint8_t *OIMemoryManager::allocateDataSection(
|
||||
* We can't rely on LLVM to do this job because we are resolving symbols of a
|
||||
* remote process. LLVM only handles resolving symbols for the current process.
|
||||
*/
|
||||
JITSymbol OIMemoryManager::findSymbol(const std::string &name) {
|
||||
JITSymbol OIMemoryManager::findSymbol(const std::string& name) {
|
||||
if (auto synth = syntheticSymbols.find(name);
|
||||
synth != end(syntheticSymbols)) {
|
||||
VLOG(1) << "findSymbol(" << name << ") = Synth " << std::hex
|
||||
@ -365,8 +365,8 @@ JITSymbol OIMemoryManager::findSymbol(const std::string &name) {
|
||||
}
|
||||
|
||||
std::optional<std::string> OICompiler::decodeInst(
|
||||
const std::vector<std::byte> &funcText, uintptr_t offset) {
|
||||
auto disassembler = Disassembler((const uint8_t *)funcText.data() + offset,
|
||||
const std::vector<std::byte>& funcText, uintptr_t offset) {
|
||||
auto disassembler = Disassembler((const uint8_t*)funcText.data() + offset,
|
||||
funcText.size() - offset);
|
||||
|
||||
auto inst = disassembler();
|
||||
@ -398,17 +398,17 @@ OICompiler::~OICompiler() = default;
|
||||
static constexpr size_t kMaxInterFuncInstrPadding = 16;
|
||||
|
||||
static void debugDisAsm(
|
||||
const SmallVector<OIMemoryManager::Slab, 4> &Slabs,
|
||||
const OICompiler::RelocResult::RelocInfos &ObjectRelocInfos) {
|
||||
const SmallVector<OIMemoryManager::Slab, 4>& Slabs,
|
||||
const OICompiler::RelocResult::RelocInfos& ObjectRelocInfos) {
|
||||
VLOG(1) << "\nDisassembled Code";
|
||||
|
||||
/* Outer loop on each Object files that has been loaded */
|
||||
assert(Slabs.size() == ObjectRelocInfos.size());
|
||||
for (const auto &S : boost::combine(Slabs, ObjectRelocInfos)) {
|
||||
const auto &[ObjFile, ObjRelInfo] = std::tie(S.get<0>(), S.get<1>());
|
||||
for (const auto& S : boost::combine(Slabs, ObjectRelocInfos)) {
|
||||
const auto& [ObjFile, ObjRelInfo] = std::tie(S.get<0>(), S.get<1>());
|
||||
|
||||
/* Inner loop on each Function Section of a given Object file */
|
||||
for (const auto &textSec : ObjFile.functionSections) {
|
||||
for (const auto& textSec : ObjFile.functionSections) {
|
||||
const auto offset =
|
||||
(uintptr_t)textSec.base() - (uintptr_t)ObjFile.memBlock.base();
|
||||
const auto baseRelocAddress = ObjRelInfo.RelocAddr + offset;
|
||||
@ -416,7 +416,7 @@ static void debugDisAsm(
|
||||
size_t instrCnt = 0;
|
||||
size_t byteCnt = 0;
|
||||
size_t consNop = 0;
|
||||
auto dg = OICompiler::Disassembler((uint8_t *)textSec.base(),
|
||||
auto dg = OICompiler::Disassembler((uint8_t*)textSec.base(),
|
||||
textSec.allocatedSize());
|
||||
while (auto inst = dg()) {
|
||||
instrCnt++;
|
||||
@ -451,8 +451,8 @@ static void debugDisAsm(
|
||||
}
|
||||
}
|
||||
|
||||
bool OICompiler::compile(const std::string &code, const fs::path &sourcePath,
|
||||
const fs::path &objectPath) {
|
||||
bool OICompiler::compile(const std::string& code, const fs::path& sourcePath,
|
||||
const fs::path& objectPath) {
|
||||
Metrics::Tracing _("compile");
|
||||
|
||||
/*
|
||||
@ -488,15 +488,15 @@ bool OICompiler::compile(const std::string &code, const fs::path &sourcePath,
|
||||
compInv->getFrontendOpts().OutputFile = objectPath.string();
|
||||
compInv->getFrontendOpts().ProgramAction = clang::frontend::EmitObj;
|
||||
|
||||
auto &headerSearchOptions = compInv->getHeaderSearchOpts();
|
||||
auto& headerSearchOptions = compInv->getHeaderSearchOpts();
|
||||
|
||||
for (const auto &path : config.userHeaderPaths) {
|
||||
for (const auto& path : config.userHeaderPaths) {
|
||||
headerSearchOptions.AddPath(
|
||||
path.c_str(), clang::frontend::IncludeDirGroup::IndexHeaderMap, false,
|
||||
false);
|
||||
}
|
||||
|
||||
for (const auto &path : config.sysHeaderPaths) {
|
||||
for (const auto& path : config.sysHeaderPaths) {
|
||||
headerSearchOptions.AddPath(
|
||||
path.c_str(), clang::frontend::IncludeDirGroup::System, false, false);
|
||||
}
|
||||
@ -554,15 +554,15 @@ bool OICompiler::compile(const std::string &code, const fs::path &sourcePath,
|
||||
}
|
||||
|
||||
std::optional<OICompiler::RelocResult> OICompiler::applyRelocs(
|
||||
uintptr_t baseRelocAddress, const std::set<fs::path> &objectFiles,
|
||||
const std::unordered_map<std::string, uintptr_t> &syntheticSymbols) {
|
||||
uintptr_t baseRelocAddress, const std::set<fs::path>& objectFiles,
|
||||
const std::unordered_map<std::string, uintptr_t>& syntheticSymbols) {
|
||||
Metrics::Tracing relocationTracing("relocation");
|
||||
|
||||
memMgr = std::make_unique<OIMemoryManager>(symbols, syntheticSymbols);
|
||||
RuntimeDyld dyld(*memMgr, *memMgr);
|
||||
|
||||
/* Load all the object files into the MemoryManager */
|
||||
for (const auto &objPath : objectFiles) {
|
||||
for (const auto& objPath : objectFiles) {
|
||||
VLOG(1) << "Loading object file " << objPath;
|
||||
auto objFile = ObjectFile::createObjectFile(objPath.c_str());
|
||||
if (!objFile) {
|
||||
@ -583,8 +583,8 @@ std::optional<OICompiler::RelocResult> OICompiler::applyRelocs(
|
||||
|
||||
/* Provides mapping addresses to the MemoryManager */
|
||||
uintptr_t currentRelocAddress = baseRelocAddress;
|
||||
for (const auto &slab : memMgr->Slabs) {
|
||||
for (const auto &funcSection : slab.functionSections) {
|
||||
for (const auto& slab : memMgr->Slabs) {
|
||||
for (const auto& funcSection : slab.functionSections) {
|
||||
auto offset =
|
||||
(uintptr_t)funcSection.base() - (uintptr_t)slab.memBlock.base();
|
||||
dyld.mapSectionAddress(funcSection.base(), currentRelocAddress + offset);
|
||||
@ -593,7 +593,7 @@ std::optional<OICompiler::RelocResult> OICompiler::applyRelocs(
|
||||
<< currentRelocAddress + offset;
|
||||
}
|
||||
|
||||
for (const auto &dataSection : slab.dataSections) {
|
||||
for (const auto& dataSection : slab.dataSections) {
|
||||
auto offset =
|
||||
(uintptr_t)dataSection.base() - (uintptr_t)slab.memBlock.base();
|
||||
dyld.mapSectionAddress(dataSection.base(), currentRelocAddress + offset);
|
||||
@ -622,7 +622,7 @@ std::optional<OICompiler::RelocResult> OICompiler::applyRelocs(
|
||||
/* Copy symbol table into `res` */
|
||||
auto symbolTable = dyld.getSymbolTable();
|
||||
res.symbols.reserve(symbolTable.size());
|
||||
for (const auto &[symName, sym] : symbolTable) {
|
||||
for (const auto& [symName, sym] : symbolTable) {
|
||||
res.symbols.emplace(symName.str(), sym.getAddress());
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ class OICompiler {
|
||||
* Create a disassembler from anything that resemble a std::span.
|
||||
*/
|
||||
template <typename... Args>
|
||||
Disassembler(Args &&...args) : funcText(std::forward<Args>(args)...) {
|
||||
Disassembler(Args&&... args) : funcText(std::forward<Args>(args)...) {
|
||||
}
|
||||
|
||||
/*
|
||||
@ -137,7 +137,7 @@ class OICompiler {
|
||||
*
|
||||
* @return true if the compilation succeeded, false otherwise.
|
||||
*/
|
||||
bool compile(const std::string &, const fs::path &, const fs::path &);
|
||||
bool compile(const std::string&, const fs::path&, const fs::path&);
|
||||
|
||||
/**
|
||||
* Load the @param objectFiles in memory and apply relocation at
|
||||
@ -157,8 +157,8 @@ class OICompiler {
|
||||
* another call.
|
||||
*/
|
||||
std::optional<RelocResult> applyRelocs(
|
||||
uintptr_t, const std::set<fs::path> &,
|
||||
const std::unordered_map<std::string, uintptr_t> &);
|
||||
uintptr_t, const std::set<fs::path>&,
|
||||
const std::unordered_map<std::string, uintptr_t>&);
|
||||
|
||||
/**
|
||||
* Locates all the offsets of the given @param insts opcodes
|
||||
@ -173,13 +173,13 @@ class OICompiler {
|
||||
*/
|
||||
template <class FuncTextRange, class NeedlesRange>
|
||||
static std::optional<std::vector<uintptr_t>> locateOpcodes(
|
||||
const FuncTextRange &funcText, const NeedlesRange &needles);
|
||||
const FuncTextRange& funcText, const NeedlesRange& needles);
|
||||
|
||||
/**
|
||||
* @return a string representation of the opcode(s) of the instruction found
|
||||
* at @param offset within function's binary instructions @param funcText.
|
||||
*/
|
||||
static std::optional<std::string> decodeInst(const std::vector<std::byte> &,
|
||||
static std::optional<std::string> decodeInst(const std::vector<std::byte>&,
|
||||
uintptr_t);
|
||||
|
||||
private:
|
||||
@ -200,13 +200,13 @@ class OICompiler {
|
||||
|
||||
template <class FuncTextRange, class NeedlesRange>
|
||||
std::optional<std::vector<uintptr_t>> OICompiler::locateOpcodes(
|
||||
const FuncTextRange &funcText, const NeedlesRange &needles) {
|
||||
auto DG = Disassembler((uint8_t *)std::data(funcText), std::size(funcText));
|
||||
const FuncTextRange& funcText, const NeedlesRange& needles) {
|
||||
auto DG = Disassembler((uint8_t*)std::data(funcText), std::size(funcText));
|
||||
|
||||
std::vector<uintptr_t> locs;
|
||||
while (auto inst = DG()) {
|
||||
auto it = std::find_if(
|
||||
std::begin(needles), std::end(needles), [&](const auto &needle) {
|
||||
std::begin(needles), std::end(needles), [&](const auto& needle) {
|
||||
// Inst->opcodes.starts_with(needle);
|
||||
return 0 ==
|
||||
inst->opcodes.find(OICompiler::Disassembler::Span<uint8_t>(
|
||||
|
16
src/OID.cpp
16
src/OID.cpp
@ -206,9 +206,9 @@ void installSigHandlers(void) {
|
||||
sigaction(SIGALRM, &nact, nullptr);
|
||||
}
|
||||
|
||||
std::optional<long> strunittol(const char *str) {
|
||||
std::optional<long> strunittol(const char* str) {
|
||||
errno = 0;
|
||||
char *strend = nullptr;
|
||||
char* strend = nullptr;
|
||||
long retval = strtol(str, &strend, 10);
|
||||
if (errno != 0) {
|
||||
return std::nullopt;
|
||||
@ -266,11 +266,11 @@ struct Config {
|
||||
|
||||
} // namespace Oid
|
||||
|
||||
static ExitStatus::ExitStatus runScript(const std::string &fileName,
|
||||
std::istream &script,
|
||||
const Oid::Config &oidConfig,
|
||||
const OICodeGen::Config &codeGenConfig,
|
||||
const TreeBuilder::Config &tbConfig) {
|
||||
static ExitStatus::ExitStatus runScript(const std::string& fileName,
|
||||
std::istream& script,
|
||||
const Oid::Config& oidConfig,
|
||||
const OICodeGen::Config& codeGenConfig,
|
||||
const TreeBuilder::Config& tbConfig) {
|
||||
if (!fileName.empty()) {
|
||||
VLOG(1) << "SCR FILE: " << fileName;
|
||||
}
|
||||
@ -452,7 +452,7 @@ static ExitStatus::ExitStatus runScript(const std::string &fileName,
|
||||
return ExitStatus::Success;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
int debugLevel = 1;
|
||||
Oid::Config oidConfig = {};
|
||||
std::string scriptFile;
|
||||
|
@ -60,10 +60,10 @@ using namespace ObjectIntrospection;
|
||||
|
||||
bool OIDebugger::isGlobalDataProbeEnabled(void) const {
|
||||
return std::any_of(cbegin(pdata), cend(pdata),
|
||||
[](const auto &r) { return r.type == "global"; });
|
||||
[](const auto& r) { return r.type == "global"; });
|
||||
}
|
||||
|
||||
bool OIDebugger::parseScript(std::istream &script) {
|
||||
bool OIDebugger::parseScript(std::istream& script) {
|
||||
Metrics::Tracing _("parse_script");
|
||||
|
||||
OIScanner scanner(&script);
|
||||
@ -92,7 +92,7 @@ bool OIDebugger::patchFunctions(void) {
|
||||
assert(pdata.numReqs() != 0);
|
||||
Metrics::Tracing _("patch_functions");
|
||||
|
||||
for (const auto &preq : pdata) {
|
||||
for (const auto& preq : pdata) {
|
||||
VLOG(1) << "Type " << preq.type << " Func " << preq.func
|
||||
<< " Args: " << boost::join(preq.args, ",");
|
||||
|
||||
@ -117,7 +117,7 @@ bool OIDebugger::patchFunctions(void) {
|
||||
* Single step an instruction in the target process 'pid' and leave the target
|
||||
* thread stopped. Returns the current rip.
|
||||
*/
|
||||
uint64_t OIDebugger::singlestepInst(pid_t pid, struct user_regs_struct ®s) {
|
||||
uint64_t OIDebugger::singlestepInst(pid_t pid, struct user_regs_struct& regs) {
|
||||
int status = 0;
|
||||
|
||||
Metrics::Tracing _("single_step_inst");
|
||||
@ -143,8 +143,8 @@ uint64_t OIDebugger::singlestepInst(pid_t pid, struct user_regs_struct ®s) {
|
||||
return regs.rip;
|
||||
}
|
||||
|
||||
void OIDebugger::dumpRegs(const char *text, pid_t pid,
|
||||
struct user_regs_struct *regs) {
|
||||
void OIDebugger::dumpRegs(const char* text, pid_t pid,
|
||||
struct user_regs_struct* regs) {
|
||||
VLOG(1) << "(" << text << ")"
|
||||
<< " dumpRegs: pid: " << std::dec << pid << std::hex << " rip "
|
||||
<< regs->rip << " rbp: " << regs->rbp << " rsp " << regs->rsp
|
||||
@ -204,8 +204,8 @@ bool OIDebugger::setupLogFile(void) {
|
||||
* Using the text segment to store the path in the remote process' memory.
|
||||
* The memory will be re-used anyway and the path will get overwritten.
|
||||
*/
|
||||
if (!writeTargetMemory((void *)logFilePath.c_str(),
|
||||
(void *)segConfig.textSegBase, logFilePathLen)) {
|
||||
if (!writeTargetMemory((void*)logFilePath.c_str(),
|
||||
(void*)segConfig.textSegBase, logFilePathLen)) {
|
||||
LOG(ERROR) << "Failed to write Log File's path into target process";
|
||||
return false;
|
||||
}
|
||||
@ -267,7 +267,7 @@ bool OIDebugger::segmentInit(void) {
|
||||
|
||||
segConfig.existingConfig = true;
|
||||
segmentConfigFile.seekg(0);
|
||||
segmentConfigFile.write((char *)&segConfig, sizeof(segConfig));
|
||||
segmentConfigFile.write((char*)&segConfig, sizeof(segConfig));
|
||||
|
||||
VLOG(1) << "segConfig size " << sizeof(segConfig);
|
||||
|
||||
@ -318,7 +318,7 @@ void OIDebugger::createSegmentConfigFile(void) {
|
||||
/* Read config */
|
||||
segmentConfigFile =
|
||||
std::fstream(segConfigFilePath, ios::in | ios::out | ios::binary);
|
||||
segmentConfigFile.read((char *)&segConfig, sizeof(c));
|
||||
segmentConfigFile.read((char*)&segConfig, sizeof(c));
|
||||
|
||||
if (segmentConfigFile.fail()) {
|
||||
LOG(ERROR) << "createSegmentConfigFile: failed to read from "
|
||||
@ -423,7 +423,7 @@ OIDebugger::StatusType OIDebugger::getTaskState(pid_t pid) {
|
||||
/* For debug - do not remove */
|
||||
void OIDebugger::dumpAlltaskStates(void) {
|
||||
VLOG(1) << "Task State Dump";
|
||||
for (auto const &p : threadList) {
|
||||
for (auto const& p : threadList) {
|
||||
auto state = getTaskState(p);
|
||||
VLOG(1) << "Task " << p << " state: " << taskStateToString(state) << " ("
|
||||
<< static_cast<int>(state) << ")";
|
||||
@ -457,9 +457,9 @@ bool OIDebugger::contTargetThread(bool detach) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OIDebugger::replayTrappedInstr(const trapInfo &t, pid_t pid,
|
||||
struct user_regs_struct ®s,
|
||||
struct user_fpregs_struct &fpregs) const {
|
||||
bool OIDebugger::replayTrappedInstr(const trapInfo& t, pid_t pid,
|
||||
struct user_regs_struct& regs,
|
||||
struct user_fpregs_struct& fpregs) const {
|
||||
/*
|
||||
* Single step the original instruction which has been patched over
|
||||
* with a breakpoint trap. The original instruction now resides in
|
||||
@ -524,13 +524,13 @@ bool OIDebugger::replayTrappedInstr(const trapInfo &t, pid_t pid,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OIDebugger::locateObjectsAddresses(const trapInfo &tInfo,
|
||||
struct user_regs_struct ®s) {
|
||||
bool OIDebugger::locateObjectsAddresses(const trapInfo& tInfo,
|
||||
struct user_regs_struct& regs) {
|
||||
/*
|
||||
* Write objects into prologue in target.
|
||||
*/
|
||||
bool ret = true;
|
||||
for (const auto &arg : tInfo.args) {
|
||||
for (const auto& arg : tInfo.args) {
|
||||
auto remoteObjAddr = remoteObjAddrs.find(arg);
|
||||
if (remoteObjAddr == remoteObjAddrs.end()) {
|
||||
LOG(ERROR) << "Entry: failed to find remoteObjAddr! Skipping...";
|
||||
@ -546,8 +546,8 @@ bool OIDebugger::locateObjectsAddresses(const trapInfo &tInfo,
|
||||
}
|
||||
|
||||
VLOG(4) << "Entry: arg addr: " << std::hex << *addr;
|
||||
if (!writeTargetMemory((void *)(&addr.value()),
|
||||
(void *)remoteObjAddr->second, sizeof(*addr))) {
|
||||
if (!writeTargetMemory((void*)(&addr.value()), (void*)remoteObjAddr->second,
|
||||
sizeof(*addr))) {
|
||||
LOG(ERROR) << "Entry: writeTargetMemory remoteObjAddr failed!";
|
||||
ret = false;
|
||||
continue;
|
||||
@ -558,8 +558,8 @@ bool OIDebugger::locateObjectsAddresses(const trapInfo &tInfo,
|
||||
}
|
||||
|
||||
OIDebugger::processTrapRet OIDebugger::processFuncTrap(
|
||||
const trapInfo &tInfo, pid_t pid, struct user_regs_struct ®s,
|
||||
struct user_fpregs_struct &fpregs) {
|
||||
const trapInfo& tInfo, pid_t pid, struct user_regs_struct& regs,
|
||||
struct user_fpregs_struct& fpregs) {
|
||||
assert(tInfo.trapKind != OID_TRAP_JITCODERET);
|
||||
|
||||
processTrapRet ret = OID_CONT;
|
||||
@ -570,10 +570,10 @@ OIDebugger::processTrapRet OIDebugger::processFuncTrap(
|
||||
auto t = std::make_shared<trapInfo>(tInfo);
|
||||
|
||||
/* Save interrupted registers into trap information */
|
||||
memcpy((void *)&t->savedRegs, (void *)®s, sizeof(t->savedRegs));
|
||||
memcpy((void*)&t->savedRegs, (void*)®s, sizeof(t->savedRegs));
|
||||
|
||||
/* Save fpregs into trap information */
|
||||
memcpy((void *)&t->savedFPregs, (void *)&fpregs, sizeof(t->savedFPregs));
|
||||
memcpy((void*)&t->savedFPregs, (void*)&fpregs, sizeof(t->savedFPregs));
|
||||
|
||||
/* Start by locating each Target Object's address */
|
||||
if (!locateObjectsAddresses(*t, regs)) {
|
||||
@ -664,7 +664,7 @@ OIDebugger::processTrapRet OIDebugger::processFuncTrap(
|
||||
t->fromVect = true;
|
||||
|
||||
VLOG(4) << "processTrap: redirect pid " << std::dec << pid << " to address "
|
||||
<< std::hex << (void *)tInfo.prologueObjAddr << " tInfo: " << tInfo
|
||||
<< std::hex << (void*)tInfo.prologueObjAddr << " tInfo: " << tInfo
|
||||
<< " " << tInfo.prologueObjAddr << " " << tInfo.fromVect;
|
||||
|
||||
errno = 0;
|
||||
@ -689,7 +689,7 @@ OIDebugger::processTrapRet OIDebugger::processFuncTrap(
|
||||
}
|
||||
|
||||
OIDebugger::processTrapRet OIDebugger::processJitCodeRet(
|
||||
const trapInfo &tInfo __attribute__((unused)), pid_t pid) {
|
||||
const trapInfo& tInfo __attribute__((unused)), pid_t pid) {
|
||||
OIDebugger::processTrapRet ret = OIDebugger::OID_CONT;
|
||||
|
||||
assert(tInfo.trapKind == OID_TRAP_JITCODERET);
|
||||
@ -784,7 +784,7 @@ OIDebugger::processTrapRet OIDebugger::processJitCodeRet(
|
||||
* in this case) and introspect the global data. It would be good if we had
|
||||
* a cheap way of asserting that the global thread is stopped.
|
||||
*/
|
||||
bool OIDebugger::processGlobal(const std::string &varName) {
|
||||
bool OIDebugger::processGlobal(const std::string& varName) {
|
||||
assert(mode == OID_MODE_THREAD);
|
||||
|
||||
VLOG(1) << "Introspecting global variable: " << varName;
|
||||
@ -827,10 +827,10 @@ bool OIDebugger::processGlobal(const std::string &varName) {
|
||||
|
||||
regs.rip -= 2;
|
||||
/* Save interrupted registers into trap information */
|
||||
memcpy((void *)&t->savedRegs, (void *)®s, sizeof(t->savedRegs));
|
||||
memcpy((void*)&t->savedRegs, (void*)®s, sizeof(t->savedRegs));
|
||||
|
||||
/* Save fpregs into trap information */
|
||||
memcpy((void *)&t->savedFPregs, (void *)&fpregs, sizeof(t->savedFPregs));
|
||||
memcpy((void*)&t->savedFPregs, (void*)&fpregs, sizeof(t->savedFPregs));
|
||||
regs.rip = segConfig.textSegBase;
|
||||
|
||||
dumpRegs("processGlobal2", traceePid, ®s);
|
||||
@ -858,7 +858,7 @@ bool OIDebugger::processGlobal(const std::string &varName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!writeTargetMemory((void *)&addr, (void *)remoteObjAddr->second,
|
||||
if (!writeTargetMemory((void*)&addr, (void*)remoteObjAddr->second,
|
||||
sizeof(addr))) {
|
||||
LOG(ERROR) << "processGlobal: writeTargetMemory remoteObjAddr failed!";
|
||||
}
|
||||
@ -1241,14 +1241,14 @@ OIDebugger::processTrapRet OIDebugger::processTrap(pid_t pid, bool blocking,
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::optional<std::vector<uintptr_t>> OIDebugger::findRetLocs(FuncDesc &fd) {
|
||||
std::optional<std::vector<uintptr_t>> OIDebugger::findRetLocs(FuncDesc& fd) {
|
||||
size_t maxSize = std::accumulate(
|
||||
fd.ranges.begin(), fd.ranges.end(), size_t(0),
|
||||
[](auto currMax, auto &r) { return std::max(currMax, r.size()); });
|
||||
[](auto currMax, auto& r) { return std::max(currMax, r.size()); });
|
||||
|
||||
std::vector<uintptr_t> retLocs;
|
||||
std::vector<std::byte> text(maxSize);
|
||||
for (const auto &range : fd.ranges) {
|
||||
for (const auto& range : fd.ranges) {
|
||||
/*
|
||||
* We already have enough capacity to accomodate any range from the function
|
||||
* But we must ensure the actual `size` of the vector matches what is being
|
||||
@ -1260,7 +1260,7 @@ std::optional<std::vector<uintptr_t>> OIDebugger::findRetLocs(FuncDesc &fd) {
|
||||
text.resize(range.size());
|
||||
|
||||
/* Copy the range of instruction into the text vector to be disassembled */
|
||||
if (!readTargetMemory((void *)range.start, text.data(), text.size())) {
|
||||
if (!readTargetMemory((void*)range.start, text.data(), text.size())) {
|
||||
LOG(ERROR) << "Could not read function range " << fd.symName << "@"
|
||||
<< range;
|
||||
return std::nullopt;
|
||||
@ -1310,10 +1310,10 @@ std::optional<std::vector<uintptr_t>> OIDebugger::findRetLocs(FuncDesc &fd) {
|
||||
* If it's not in the replayInstMap, return the address to the next free entry
|
||||
* in the cache and put the entry in the map.
|
||||
*/
|
||||
std::optional<uintptr_t> OIDebugger::nextReplayInstrAddr(const trapInfo &t) {
|
||||
std::optional<uintptr_t> OIDebugger::nextReplayInstrAddr(const trapInfo& t) {
|
||||
if (auto it = replayInstMap.find(t.trapAddr); it != end(replayInstMap)) {
|
||||
VLOG(1) << "Found instruction for trap " << (void *)t.trapAddr
|
||||
<< " at address " << (void *)it->second;
|
||||
VLOG(1) << "Found instruction for trap " << (void*)t.trapAddr
|
||||
<< " at address " << (void*)it->second;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
@ -1330,8 +1330,8 @@ std::optional<uintptr_t> OIDebugger::nextReplayInstrAddr(const trapInfo &t) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
VLOG(1) << "Orig instructions for trap " << (void *)t.trapAddr
|
||||
<< " will get saved at " << (void *)newInstrAddr;
|
||||
VLOG(1) << "Orig instructions for trap " << (void*)t.trapAddr
|
||||
<< " will get saved at " << (void*)newInstrAddr;
|
||||
replayInstMap.emplace(t.trapAddr, newInstrAddr);
|
||||
|
||||
return newInstrAddr;
|
||||
@ -1374,7 +1374,7 @@ std::optional<uintptr_t> OIDebugger::nextReplayInstrAddr(const trapInfo &t) {
|
||||
* instrumentation much be done as a single unit.
|
||||
*/
|
||||
|
||||
bool OIDebugger::functionPatch(const prequest &req) {
|
||||
bool OIDebugger::functionPatch(const prequest& req) {
|
||||
assert(req.type != "global");
|
||||
|
||||
auto fd = symbols->findFuncDesc(req.getReqForArg(0));
|
||||
@ -1398,15 +1398,15 @@ bool OIDebugger::functionPatch(const prequest &req) {
|
||||
/* 1. Locate all TRAP points and create a corresponding empty trapInfo in
|
||||
* tiVec */
|
||||
bool hasArg = std::any_of(begin(req.args), end(req.args),
|
||||
[](auto &arg) { return arg != "retval"; });
|
||||
[](auto& arg) { return arg != "retval"; });
|
||||
|
||||
if (req.type == "entry" || hasArg) {
|
||||
trapType tType =
|
||||
req.type == "return" ? OID_TRAP_VECT_ENTRYRET : OID_TRAP_VECT_ENTRY;
|
||||
uintptr_t trapAddr = fd->ranges[0].start;
|
||||
if (req.args[0].starts_with("arg") || req.args[0] == "this") {
|
||||
auto *argument =
|
||||
dynamic_cast<FuncDesc::Arg *>(fd->getArgument(req.args[0]).get());
|
||||
auto* argument =
|
||||
dynamic_cast<FuncDesc::Arg*>(fd->getArgument(req.args[0]).get());
|
||||
if (argument->locator.locations_size > 0) {
|
||||
/*
|
||||
* The `std::max` is necessary because sometimes when a binary is
|
||||
@ -1440,9 +1440,9 @@ bool OIDebugger::functionPatch(const prequest &req) {
|
||||
localIov.reserve(tiVec.size());
|
||||
remoteIov.reserve(tiVec.size());
|
||||
|
||||
for (auto &ti : tiVec) {
|
||||
localIov.push_back({(void *)ti->origTextBytes, sizeof(ti->origTextBytes)});
|
||||
remoteIov.push_back({(void *)ti->trapAddr, sizeof(ti->origTextBytes)});
|
||||
for (auto& ti : tiVec) {
|
||||
localIov.push_back({(void*)ti->origTextBytes, sizeof(ti->origTextBytes)});
|
||||
remoteIov.push_back({(void*)ti->trapAddr, sizeof(ti->origTextBytes)});
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
@ -1463,7 +1463,7 @@ bool OIDebugger::functionPatch(const prequest &req) {
|
||||
/* Re-use remoteIov to write the original instructions in our textSegment */
|
||||
remoteIov.clear();
|
||||
|
||||
for (auto &trap : tiVec) {
|
||||
for (auto& trap : tiVec) {
|
||||
trap->patchedText = trap->origText;
|
||||
trap->patchedTextBytes[0] = int3Inst;
|
||||
|
||||
@ -1476,13 +1476,13 @@ bool OIDebugger::functionPatch(const prequest &req) {
|
||||
|
||||
trap->replayInstAddr = *replayInstrAddr;
|
||||
remoteIov.push_back(
|
||||
{(void *)trap->replayInstAddr, sizeof(trap->origTextBytes)});
|
||||
{(void*)trap->replayInstAddr, sizeof(trap->origTextBytes)});
|
||||
|
||||
if (trap->trapKind == OID_TRAP_VECT_ENTRY ||
|
||||
trap->trapKind == OID_TRAP_VECT_ENTRYRET) {
|
||||
/* Capture the arguments to probe */
|
||||
trap->args.reserve(req.args.size());
|
||||
for (const auto &arg : req.args) {
|
||||
for (const auto& arg : req.args) {
|
||||
if (auto targetObj = fd->getArgument(arg)) {
|
||||
trap->args.push_back(std::move(targetObj));
|
||||
} else {
|
||||
@ -1517,9 +1517,9 @@ bool OIDebugger::functionPatch(const prequest &req) {
|
||||
}
|
||||
|
||||
/* 5. Insert the traps in the target process */
|
||||
for (const auto &trap : tiVec) {
|
||||
for (const auto& trap : tiVec) {
|
||||
VLOG(1) << "Patching function " << req.func << " @"
|
||||
<< (void *)trap->trapAddr;
|
||||
<< (void*)trap->trapAddr;
|
||||
activeTraps.emplace(trap->trapAddr, trap);
|
||||
|
||||
errno = 0;
|
||||
@ -1551,7 +1551,7 @@ std::optional<typename Sys::RetType> OIDebugger::remoteSyscall(Args... _args) {
|
||||
}
|
||||
|
||||
uint64_t patchAddr = sym->addr;
|
||||
VLOG(1) << "Address of main: " << (void *)patchAddr;
|
||||
VLOG(1) << "Address of main: " << (void*)patchAddr;
|
||||
|
||||
/* Saving current registers states */
|
||||
errno = 0;
|
||||
@ -1600,7 +1600,7 @@ std::optional<typename Sys::RetType> OIDebugger::remoteSyscall(Args... _args) {
|
||||
* arch/ABI arg1 arg2 arg3 arg4 arg5 arg6 arg7
|
||||
* x86-64 rdi rsi rdx r10 r8 r9 -
|
||||
*/
|
||||
const std::array<unsigned long long *, 6> argToReg = {
|
||||
const std::array<unsigned long long*, 6> argToReg = {
|
||||
&newregs.rdi, &newregs.rsi, &newregs.rdx,
|
||||
&newregs.r10, &newregs.r8, &newregs.r9,
|
||||
};
|
||||
@ -1692,7 +1692,7 @@ std::optional<typename Sys::RetType> OIDebugger::remoteSyscall(Args... _args) {
|
||||
bool OIDebugger::setupSegment(SegType seg) {
|
||||
Metrics::Tracing _("setup_segment");
|
||||
|
||||
std::optional<void *> segAddr;
|
||||
std::optional<void*> segAddr;
|
||||
if (seg == SegType::text) {
|
||||
segAddr =
|
||||
remoteSyscall<SysMmap>(nullptr, textSegSize, // addr & size
|
||||
@ -1796,7 +1796,7 @@ bool OIDebugger::removeTraps(pid_t pid) {
|
||||
}
|
||||
|
||||
for (auto it = activeTraps.begin(); it != activeTraps.end();) {
|
||||
const auto &tInfo = it->second;
|
||||
const auto& tInfo = it->second;
|
||||
|
||||
/* We don't care about our own traps */
|
||||
if (tInfo->trapKind == OID_TRAP_JITCODERET) {
|
||||
@ -1833,7 +1833,7 @@ bool OIDebugger::removeTraps(pid_t pid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OIDebugger::removeTrap(pid_t pid, const trapInfo &t) {
|
||||
bool OIDebugger::removeTrap(pid_t pid, const trapInfo& t) {
|
||||
std::array<std::byte, 8> repatchedBytes{};
|
||||
memcpy(repatchedBytes.data(), t.origTextBytes, repatchedBytes.size());
|
||||
|
||||
@ -1858,7 +1858,7 @@ bool OIDebugger::removeTrap(pid_t pid, const trapInfo &t) {
|
||||
|
||||
VLOG(4) << "removeTrap removing int3 at " << std::hex << t.trapAddr;
|
||||
if (ptrace(PTRACE_POKETEXT, (!pid ? traceePid : pid), t.trapAddr,
|
||||
*reinterpret_cast<uintptr_t *>(repatchedBytes.data())) < 0) {
|
||||
*reinterpret_cast<uintptr_t*>(repatchedBytes.data())) < 0) {
|
||||
LOG(ERROR) << "Execute: Couldn't poke text: " << strerror(errno);
|
||||
return false;
|
||||
}
|
||||
@ -1917,7 +1917,7 @@ OIDebugger::OIDebugger(fs::path debugInfo, std::string configFile,
|
||||
* @param[in] target_addr - target address where new data are to be written
|
||||
* @param[in] bufsz - length of 'target_addr' buffer in bytes
|
||||
*/
|
||||
bool OIDebugger::writeTargetMemory(void *local_buffer, void *target_addr,
|
||||
bool OIDebugger::writeTargetMemory(void* local_buffer, void* target_addr,
|
||||
size_t bufsz) const {
|
||||
VLOG(1) << "Writing buffer " << std::hex << local_buffer << ", bufsz "
|
||||
<< std::dec << bufsz << " into target " << std::hex << target_addr;
|
||||
@ -1960,7 +1960,7 @@ bool OIDebugger::writeTargetMemory(void *local_buffer, void *target_addr,
|
||||
* @param[in] local_addr - local address where new data are to be written
|
||||
* @param[in] bufsz - length of 'local_addr' buffer in bytes
|
||||
*/
|
||||
bool OIDebugger::readTargetMemory(void *remote_buffer, void *local_addr,
|
||||
bool OIDebugger::readTargetMemory(void* remote_buffer, void* local_addr,
|
||||
size_t bufsz) const {
|
||||
VLOG(1) << "Reading buffer " << std::hex << remote_buffer << ", bufsz "
|
||||
<< std::dec << bufsz << " into local " << std::hex << local_addr;
|
||||
@ -1996,11 +1996,11 @@ bool OIDebugger::readTargetMemory(void *remote_buffer, void *local_addr,
|
||||
|
||||
std::optional<std::pair<OIDebugger::ObjectAddrMap::key_type, uintptr_t>>
|
||||
OIDebugger::locateJitCodeStart(
|
||||
const irequest &req, const OICompiler::RelocResult::SymTable &jitSymbols) {
|
||||
const irequest& req, const OICompiler::RelocResult::SymTable& jitSymbols) {
|
||||
// Get type of probed object to locate the JIT code start
|
||||
OIDebugger::ObjectAddrMap::key_type targetObj;
|
||||
if (req.type == "global") {
|
||||
const auto &gd = symbols->findGlobalDesc(req.func);
|
||||
const auto& gd = symbols->findGlobalDesc(req.func);
|
||||
if (!gd) {
|
||||
LOG(ERROR) << "Failed to find GlobalDesc for " << req.func;
|
||||
return std::nullopt;
|
||||
@ -2008,13 +2008,13 @@ OIDebugger::locateJitCodeStart(
|
||||
|
||||
targetObj = gd;
|
||||
} else {
|
||||
const auto &fd = symbols->findFuncDesc(req);
|
||||
const auto& fd = symbols->findFuncDesc(req);
|
||||
if (!fd) {
|
||||
LOG(ERROR) << "Failed to find FuncDesc for " << req.func;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto &farg = fd->getArgument(req.arg);
|
||||
const auto& farg = fd->getArgument(req.arg);
|
||||
if (!farg) {
|
||||
LOG(ERROR) << "Failed to get argument for " << req.func << ':' << req.arg;
|
||||
return std::nullopt;
|
||||
@ -2023,13 +2023,13 @@ OIDebugger::locateJitCodeStart(
|
||||
targetObj = farg;
|
||||
}
|
||||
|
||||
auto &typeName = std::visit(
|
||||
[](auto &&obj) -> std::string & { return obj->typeName; }, targetObj);
|
||||
auto& typeName = std::visit(
|
||||
[](auto&& obj) -> std::string& { return obj->typeName; }, targetObj);
|
||||
auto typeHash = std::hash<std::string_view>{}(typeName);
|
||||
auto jitCodeName = (boost::format("_Z24getSize_%016x") % typeHash).str();
|
||||
|
||||
uintptr_t jitCodeStart = 0;
|
||||
for (const auto &[symName, symAddr] : jitSymbols) {
|
||||
for (const auto& [symName, symAddr] : jitSymbols) {
|
||||
if (symName.starts_with(jitCodeName)) {
|
||||
jitCodeStart = symAddr;
|
||||
break;
|
||||
@ -2078,7 +2078,7 @@ OIDebugger::locateJitCodeStart(
|
||||
*/
|
||||
|
||||
bool OIDebugger::writePrologue(
|
||||
const prequest &preq, const OICompiler::RelocResult::SymTable &jitSymbols) {
|
||||
const prequest& preq, const OICompiler::RelocResult::SymTable& jitSymbols) {
|
||||
size_t off = 0;
|
||||
uint8_t newInsts[prologueLength];
|
||||
|
||||
@ -2091,7 +2091,7 @@ bool OIDebugger::writePrologue(
|
||||
size_t argCount = preq.type == "global" ? 1 : preq.args.size();
|
||||
|
||||
for (size_t i = 0; i < argCount; i++) {
|
||||
const auto &req = preq.getReqForArg(i);
|
||||
const auto& req = preq.getReqForArg(i);
|
||||
|
||||
auto jitCodeStart = locateJitCodeStart(req, jitSymbols);
|
||||
if (!jitCodeStart.has_value()) {
|
||||
@ -2101,13 +2101,13 @@ bool OIDebugger::writePrologue(
|
||||
}
|
||||
|
||||
VLOG(1) << "Generating prologue for argument '" << req.arg
|
||||
<< "', using probe at " << (void *)jitCodeStart->second;
|
||||
<< "', using probe at " << (void*)jitCodeStart->second;
|
||||
|
||||
newInsts[off++] = movabsrdi0Inst;
|
||||
newInsts[off++] = movabsrdi1Inst;
|
||||
remoteObjAddrs.emplace(std::move(jitCodeStart->first),
|
||||
segConfig.textSegBase + off);
|
||||
std::visit([](auto &&obj) { obj = nullptr; },
|
||||
std::visit([](auto&& obj) { obj = nullptr; },
|
||||
jitCodeStart->first); // Invalidate ptr after move
|
||||
memcpy(newInsts + off, &objectAddr, sizeof(objectAddr));
|
||||
off += sizeof(objectAddr);
|
||||
@ -2140,7 +2140,7 @@ bool OIDebugger::writePrologue(
|
||||
|
||||
assert(off <= prologueLength);
|
||||
|
||||
return writeTargetMemory(&newInsts, (void *)segConfig.textSegBase,
|
||||
return writeTargetMemory(&newInsts, (void*)segConfig.textSegBase,
|
||||
prologueLength);
|
||||
}
|
||||
|
||||
@ -2150,7 +2150,7 @@ bool OIDebugger::writePrologue(
|
||||
*/
|
||||
bool OIDebugger::compileCode() {
|
||||
assert(pdata.numReqs() == 1);
|
||||
const auto &preq = pdata.getReq();
|
||||
const auto& preq = pdata.getReq();
|
||||
|
||||
OICompiler compiler{symbols, compilerConfig};
|
||||
std::set<fs::path> objectFiles{};
|
||||
@ -2163,7 +2163,7 @@ bool OIDebugger::compileCode() {
|
||||
*/
|
||||
size_t argCount = preq.type == "global" ? 1 : preq.args.size();
|
||||
for (size_t i = 0; i < argCount; i++) {
|
||||
const auto &req = preq.getReqForArg(i);
|
||||
const auto& req = preq.getReqForArg(i);
|
||||
|
||||
if (cache.isEnabled()) {
|
||||
// try to download cache artifacts if present
|
||||
@ -2255,7 +2255,7 @@ bool OIDebugger::compileCode() {
|
||||
cache.store(req, OICache::Entity::FuncDescs, symbols->funcDescs);
|
||||
}
|
||||
|
||||
const auto &[rootType, typeHierarchy, paddingInfo] = typeInfos.at(req);
|
||||
const auto& [rootType, typeHierarchy, paddingInfo] = typeInfos.at(req);
|
||||
cache.store(req, OICache::Entity::TypeHierarchy,
|
||||
std::make_pair(rootType, typeHierarchy));
|
||||
cache.store(req, OICache::Entity::PaddingInfo, paddingInfo);
|
||||
@ -2273,7 +2273,7 @@ bool OIDebugger::compileCode() {
|
||||
};
|
||||
|
||||
VLOG(2) << "Relocating...";
|
||||
for (const auto &o : objectFiles) {
|
||||
for (const auto& o : objectFiles) {
|
||||
VLOG(2) << " * " << o;
|
||||
}
|
||||
auto relocRes = compiler.applyRelocs(segConfig.jitCodeStart, objectFiles,
|
||||
@ -2283,12 +2283,12 @@ bool OIDebugger::compileCode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto &[_, segments, jitSymbols] = relocRes.value();
|
||||
for (const auto &[symName, symAddr] : jitSymbols) {
|
||||
const auto& [_, segments, jitSymbols] = relocRes.value();
|
||||
for (const auto& [symName, symAddr] : jitSymbols) {
|
||||
VLOG(2) << "sym " << symName << '@' << std::hex << symAddr;
|
||||
}
|
||||
|
||||
const auto &lastSeg = segments.back();
|
||||
const auto& lastSeg = segments.back();
|
||||
auto segmentsLimit = lastSeg.RelocAddr + lastSeg.Size;
|
||||
auto remoteSegmentLimit = segConfig.textSegBase + segConfig.textSegSize;
|
||||
if (segmentsLimit > remoteSegmentLimit) {
|
||||
@ -2299,34 +2299,34 @@ bool OIDebugger::compileCode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto &[BaseAddr, RelocAddr, Size] : segments) {
|
||||
if (!writeTargetMemory((void *)BaseAddr, (void *)RelocAddr, Size)) {
|
||||
for (const auto& [BaseAddr, RelocAddr, Size] : segments) {
|
||||
if (!writeTargetMemory((void*)BaseAddr, (void*)RelocAddr, Size)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!writeTargetMemory(&segConfig.dataSegBase,
|
||||
(void *)syntheticSymbols["dataBase"],
|
||||
(void*)syntheticSymbols["dataBase"],
|
||||
sizeof(segConfig.dataSegBase))) {
|
||||
LOG(ERROR) << "Failed to write dataSegBase in probe's dataBase";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!writeTargetMemory(&dataSegSize, (void *)syntheticSymbols["dataSize"],
|
||||
if (!writeTargetMemory(&dataSegSize, (void*)syntheticSymbols["dataSize"],
|
||||
sizeof(dataSegSize))) {
|
||||
LOG(ERROR) << "Failed to write dataSegSize in probe's dataSize";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!writeTargetMemory(&segConfig.cookie,
|
||||
(void *)syntheticSymbols["cookieValue"],
|
||||
(void*)syntheticSymbols["cookieValue"],
|
||||
sizeof(segConfig.cookie))) {
|
||||
LOG(ERROR) << "Failed to write cookie in probe's cookieValue";
|
||||
return false;
|
||||
}
|
||||
|
||||
int logFile = enableJitLogging ? segConfig.logFile : 0;
|
||||
if (!writeTargetMemory(&logFile, (void *)syntheticSymbols["logFile"],
|
||||
if (!writeTargetMemory(&logFile, (void*)syntheticSymbols["logFile"],
|
||||
sizeof(logFile))) {
|
||||
LOG(ERROR) << "Failed to write logFile in probe's cookieValue";
|
||||
return false;
|
||||
@ -2349,7 +2349,7 @@ void OIDebugger::restoreState(void) {
|
||||
*/
|
||||
const size_t activeTrapsCount = std::count_if(
|
||||
activeTraps.cbegin(), activeTraps.cend(),
|
||||
[](const auto &t) { return t.second->trapKind != OID_TRAP_JITCODERET; });
|
||||
[](const auto& t) { return t.second->trapKind != OID_TRAP_JITCODERET; });
|
||||
VLOG(1) << "Active traps still within the target process: "
|
||||
<< activeTrapsCount;
|
||||
assert(activeTrapsCount == 0);
|
||||
@ -2367,7 +2367,7 @@ void OIDebugger::restoreState(void) {
|
||||
* thread could still be in oid JIT code here or trapping in from it normal
|
||||
* execution path.
|
||||
*/
|
||||
for (auto const &p : threadList) {
|
||||
for (auto const& p : threadList) {
|
||||
auto state = getTaskState(p);
|
||||
VLOG(1) << "Task " << p << " state: " << taskStateToString(state) << " ("
|
||||
<< static_cast<int>(state) << ")";
|
||||
@ -2465,8 +2465,8 @@ void OIDebugger::restoreState(void) {
|
||||
dumpRegs("Before1", p, ®s);
|
||||
}
|
||||
|
||||
memcpy((void *)®s, (void *)&t->savedRegs, sizeof(regs));
|
||||
memcpy((void *)&fpregs, (void *)&t->savedFPregs, sizeof(fpregs));
|
||||
memcpy((void*)®s, (void*)&t->savedRegs, sizeof(regs));
|
||||
memcpy((void*)&fpregs, (void*)&t->savedFPregs, sizeof(fpregs));
|
||||
|
||||
/*
|
||||
* Note that we need to rewind the original %rip as it has trapped
|
||||
@ -2568,7 +2568,7 @@ bool OIDebugger::targetAttach() {
|
||||
/* TODO - Handle exceptions */
|
||||
auto pidPath = fs::path("/proc") / std::to_string(traceePid) / "task";
|
||||
try {
|
||||
for (const auto &entry : fs::directory_iterator(pidPath)) {
|
||||
for (const auto& entry : fs::directory_iterator(pidPath)) {
|
||||
auto file = entry.path().filename().string();
|
||||
auto pid = std::stoi(file);
|
||||
|
||||
@ -2590,7 +2590,7 @@ bool OIDebugger::targetAttach() {
|
||||
threadList.push_back(pid);
|
||||
}
|
||||
}
|
||||
} catch (std::filesystem::filesystem_error const &ex) {
|
||||
} catch (std::filesystem::filesystem_error const& ex) {
|
||||
LOG(ERROR) << "directory_iterator exception: " << ex.path1()
|
||||
<< ex.code().message();
|
||||
|
||||
@ -2695,8 +2695,8 @@ void OIDebugger::setDataSegmentSize(size_t size) {
|
||||
VLOG(1) << "setDataSegmentSize: segment size: " << dataSegSize;
|
||||
}
|
||||
|
||||
bool OIDebugger::decodeTargetData(const DataHeader &dataHeader,
|
||||
std::vector<uint64_t> &outVec) const {
|
||||
bool OIDebugger::decodeTargetData(const DataHeader& dataHeader,
|
||||
std::vector<uint64_t>& outVec) const {
|
||||
VLOG(1) << "== magicId: " << std::hex << dataHeader.magicId;
|
||||
VLOG(1) << "== cookie: " << std::hex << dataHeader.cookie;
|
||||
VLOG(1) << "== size: " << dataHeader.size;
|
||||
@ -2763,8 +2763,8 @@ bool OIDebugger::decodeTargetData(const DataHeader &dataHeader,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dumpDataSegment(const irequest &req,
|
||||
const std::vector<uint64_t> &dataSeg) {
|
||||
static bool dumpDataSegment(const irequest& req,
|
||||
const std::vector<uint64_t>& dataSeg) {
|
||||
char dumpPath[PATH_MAX] = {0};
|
||||
auto dumpPathSize =
|
||||
snprintf(dumpPath, sizeof(dumpPath), "/tmp/dataseg.%d.%s.dump", getpid(),
|
||||
@ -2782,7 +2782,7 @@ static bool dumpDataSegment(const irequest &req,
|
||||
}
|
||||
|
||||
const auto outVecBytes = std::as_bytes(std::span{dataSeg});
|
||||
dumpFile.write((const char *)outVecBytes.data(), outVecBytes.size());
|
||||
dumpFile.write((const char*)outVecBytes.data(), outVecBytes.size());
|
||||
if (!dumpFile) {
|
||||
LOG(ERROR) << "Failed to write to data-segment file '" << dumpPath
|
||||
<< "': " << strerror(errno);
|
||||
@ -2796,7 +2796,7 @@ bool OIDebugger::processTargetData() {
|
||||
Metrics::Tracing _("process_target_data");
|
||||
|
||||
std::vector<std::byte> buf{dataSegSize};
|
||||
if (!readTargetMemory(reinterpret_cast<void *>(segConfig.dataSegBase),
|
||||
if (!readTargetMemory(reinterpret_cast<void*>(segConfig.dataSegBase),
|
||||
buf.data(), dataSegSize)) {
|
||||
LOG(ERROR) << "Failed to read data segment from target process";
|
||||
return false;
|
||||
@ -2805,7 +2805,7 @@ bool OIDebugger::processTargetData() {
|
||||
auto res = reinterpret_cast<uintptr_t>(buf.data());
|
||||
|
||||
assert(pdata.numReqs() == 1);
|
||||
const auto &preq = pdata.getReq();
|
||||
const auto& preq = pdata.getReq();
|
||||
|
||||
PaddingHunter paddingHunter{};
|
||||
TreeBuilder typeTree(treeBuilderConfig);
|
||||
@ -2820,10 +2820,10 @@ bool OIDebugger::processTargetData() {
|
||||
|
||||
std::vector<uint64_t> outVec{};
|
||||
for (size_t i = 0; i < argCount; i++) {
|
||||
const auto &req = preq.getReqForArg(i);
|
||||
const auto& req = preq.getReqForArg(i);
|
||||
LOG(INFO) << "Processing data for argument: " << req.arg;
|
||||
|
||||
const auto &dataHeader = *reinterpret_cast<DataHeader *>(res);
|
||||
const auto& dataHeader = *reinterpret_cast<DataHeader*>(res);
|
||||
res += dataHeader.size;
|
||||
|
||||
outVec.clear();
|
||||
@ -2845,8 +2845,8 @@ bool OIDebugger::processTargetData() {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto &[rootType, typeHierarchy, paddingInfos] = typeInfo->second;
|
||||
VLOG(1) << "Root type addr: " << (void *)rootType.type.type;
|
||||
const auto& [rootType, typeHierarchy, paddingInfos] = typeInfo->second;
|
||||
VLOG(1) << "Root type addr: " << (void*)rootType.type.type;
|
||||
|
||||
if (treeBuilderConfig.genPaddingStats) {
|
||||
paddingHunter.localPaddedStructs = paddingInfos;
|
||||
@ -2856,7 +2856,7 @@ bool OIDebugger::processTargetData() {
|
||||
try {
|
||||
typeTree.build(outVec, rootType.varName, rootType.type.type,
|
||||
typeHierarchy);
|
||||
} catch (std::exception &e) {
|
||||
} catch (std::exception& e) {
|
||||
LOG(ERROR) << "Failed to run TreeBuilder for " << req.arg;
|
||||
LOG(ERROR) << e.what();
|
||||
|
||||
@ -2893,7 +2893,7 @@ bool OIDebugger::processTargetData() {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<std::string> OIDebugger::generateCode(const irequest &req) {
|
||||
std::optional<std::string> OIDebugger::generateCode(const irequest& req) {
|
||||
auto root = symbols->getRootType(req);
|
||||
if (!root.has_value()) {
|
||||
return std::nullopt;
|
||||
|
@ -58,13 +58,13 @@ class OIDebugger {
|
||||
OIDebugger::processTrapRet processTrap(pid_t, bool = true, bool = true);
|
||||
bool contTargetThread(bool detach = true) const;
|
||||
bool isGlobalDataProbeEnabled(void) const;
|
||||
static uint64_t singlestepInst(pid_t, struct user_regs_struct &);
|
||||
static uint64_t singlestepInst(pid_t, struct user_regs_struct&);
|
||||
static bool singleStepFunc(pid_t, uint64_t);
|
||||
bool parseScript(std::istream &script);
|
||||
bool parseScript(std::istream& script);
|
||||
bool patchFunctions();
|
||||
void stopAll();
|
||||
bool removeTraps(pid_t);
|
||||
bool removeTrap(pid_t, const trapInfo &);
|
||||
bool removeTrap(pid_t, const trapInfo&);
|
||||
void enableDrgn();
|
||||
bool unmapSegments(bool deleteSegConf = false);
|
||||
bool isInterrupted(void) const {
|
||||
@ -92,20 +92,20 @@ class OIDebugger {
|
||||
|
||||
bool uploadCache() {
|
||||
return std::all_of(
|
||||
std::begin(pdata), std::end(pdata), [this](const auto &req) {
|
||||
std::begin(pdata), std::end(pdata), [this](const auto& req) {
|
||||
return std::all_of(
|
||||
std::begin(req.args), std::end(req.args),
|
||||
[this, &req](const auto &arg) {
|
||||
[this, &req](const auto& arg) {
|
||||
return cache.upload(irequest{req.type, req.func, arg});
|
||||
});
|
||||
});
|
||||
}
|
||||
bool downloadCache() {
|
||||
return std::all_of(
|
||||
std::begin(pdata), std::end(pdata), [this](const auto &req) {
|
||||
std::begin(pdata), std::end(pdata), [this](const auto& req) {
|
||||
return std::all_of(
|
||||
std::begin(req.args), std::end(req.args),
|
||||
[this, &req](const auto &arg) {
|
||||
[this, &req](const auto& arg) {
|
||||
return cache.download(irequest{req.type, req.func, arg});
|
||||
});
|
||||
});
|
||||
@ -192,40 +192,38 @@ class OIDebugger {
|
||||
|
||||
bool setupSegment(SegType);
|
||||
bool unmapSegment(SegType);
|
||||
bool writeTargetMemory(void *, void *, size_t) const;
|
||||
bool readTargetMemory(void *, void *, size_t) const;
|
||||
bool writeTargetMemory(void*, void*, size_t) const;
|
||||
bool readTargetMemory(void*, void*, size_t) const;
|
||||
std::optional<std::pair<OIDebugger::ObjectAddrMap::key_type, uintptr_t>>
|
||||
locateJitCodeStart(const irequest &,
|
||||
const OICompiler::RelocResult::SymTable &);
|
||||
bool writePrologue(const prequest &,
|
||||
const OICompiler::RelocResult::SymTable &);
|
||||
bool readInstFromTarget(uintptr_t, uint8_t *, size_t);
|
||||
locateJitCodeStart(const irequest&, const OICompiler::RelocResult::SymTable&);
|
||||
bool writePrologue(const prequest&, const OICompiler::RelocResult::SymTable&);
|
||||
bool readInstFromTarget(uintptr_t, uint8_t*, size_t);
|
||||
void createSegmentConfigFile(void);
|
||||
void deleteSegmentConfig(bool);
|
||||
std::optional<std::shared_ptr<trapInfo>> makeTrapInfo(const prequest &,
|
||||
std::optional<std::shared_ptr<trapInfo>> makeTrapInfo(const prequest&,
|
||||
const trapType,
|
||||
const uint64_t);
|
||||
bool functionPatch(const prequest &);
|
||||
bool functionPatch(const prequest&);
|
||||
bool canProcessTrapForThread(pid_t) const;
|
||||
bool replayTrappedInstr(const trapInfo &, pid_t, struct user_regs_struct &,
|
||||
struct user_fpregs_struct &) const;
|
||||
bool locateObjectsAddresses(const trapInfo &, struct user_regs_struct &);
|
||||
processTrapRet processFuncTrap(const trapInfo &, pid_t,
|
||||
struct user_regs_struct &,
|
||||
struct user_fpregs_struct &);
|
||||
processTrapRet processJitCodeRet(const trapInfo &, pid_t);
|
||||
bool processGlobal(const std::string &);
|
||||
static void dumpRegs(const char *, pid_t, struct user_regs_struct *);
|
||||
std::optional<uintptr_t> nextReplayInstrAddr(const trapInfo &);
|
||||
bool replayTrappedInstr(const trapInfo&, pid_t, struct user_regs_struct&,
|
||||
struct user_fpregs_struct&) const;
|
||||
bool locateObjectsAddresses(const trapInfo&, struct user_regs_struct&);
|
||||
processTrapRet processFuncTrap(const trapInfo&, pid_t,
|
||||
struct user_regs_struct&,
|
||||
struct user_fpregs_struct&);
|
||||
processTrapRet processJitCodeRet(const trapInfo&, pid_t);
|
||||
bool processGlobal(const std::string&);
|
||||
static void dumpRegs(const char*, pid_t, struct user_regs_struct*);
|
||||
std::optional<uintptr_t> nextReplayInstrAddr(const trapInfo&);
|
||||
static int getExtendedWaitEventType(int);
|
||||
static bool isExtendedWait(int);
|
||||
void dumpAlltaskStates(void);
|
||||
std::optional<std::vector<uintptr_t>> findRetLocs(FuncDesc &);
|
||||
std::optional<std::vector<uintptr_t>> findRetLocs(FuncDesc&);
|
||||
|
||||
OICompiler::Config compilerConfig{};
|
||||
OICodeGen::Config generatorConfig{};
|
||||
TreeBuilder::Config treeBuilderConfig{};
|
||||
std::optional<std::string> generateCode(const irequest &);
|
||||
std::optional<std::string> generateCode(const irequest&);
|
||||
|
||||
std::fstream segmentConfigFile;
|
||||
fs::path segConfigFilePath;
|
||||
@ -272,7 +270,7 @@ class OIDebugger {
|
||||
#pragma GCC diagnostic pop
|
||||
};
|
||||
|
||||
bool decodeTargetData(const DataHeader &, std::vector<uint64_t> &) const;
|
||||
bool decodeTargetData(const DataHeader&, std::vector<uint64_t>&) const;
|
||||
|
||||
static constexpr size_t prologueLength = 64;
|
||||
static constexpr size_t constLength = 64;
|
||||
|
@ -31,21 +31,21 @@ namespace ObjectIntrospection {
|
||||
|
||||
class OIScanner : public yyFlexLexer {
|
||||
public:
|
||||
OIScanner(std::istream *in) : yyFlexLexer(in){};
|
||||
OIScanner(std::istream* in) : yyFlexLexer(in){};
|
||||
|
||||
virtual ~OIScanner(){};
|
||||
|
||||
// get rid of override virtual function warning
|
||||
using FlexLexer::yylex;
|
||||
|
||||
virtual int yylex(OIParser::semantic_type *const lval,
|
||||
OIParser::location_type *location);
|
||||
virtual int yylex(OIParser::semantic_type* const lval,
|
||||
OIParser::location_type* location);
|
||||
// YY_DECL defined in OILexer.l
|
||||
// Method body created by flex in OILexer.yy.cc
|
||||
|
||||
private:
|
||||
/* yyval ptr */
|
||||
OIParser::semantic_type *yylval = nullptr;
|
||||
OIParser::semantic_type* yylval = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ObjectIntrospection
|
||||
|
@ -34,7 +34,7 @@ extern "C" {
|
||||
|
||||
namespace ObjectIntrospection {
|
||||
|
||||
OILibraryImpl::OILibraryImpl(OILibrary *self, void *TemplateFunc)
|
||||
OILibraryImpl::OILibraryImpl(OILibrary* self, void* TemplateFunc)
|
||||
: _self(self), _TemplateFunc(TemplateFunc) {
|
||||
if (_self->opts.debugLevel != 0) {
|
||||
google::LogToStderr();
|
||||
@ -54,7 +54,7 @@ OILibraryImpl::~OILibraryImpl() {
|
||||
}
|
||||
|
||||
bool OILibraryImpl::mapSegment() {
|
||||
void *textSeg =
|
||||
void* textSeg =
|
||||
mmap(NULL, segConfig.textSegSize, PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (textSeg == MAP_FAILED) {
|
||||
@ -105,7 +105,7 @@ class Cleanup {
|
||||
}
|
||||
};
|
||||
|
||||
void close_file(std::FILE *fp) {
|
||||
void close_file(std::FILE* fp) {
|
||||
std::fclose(fp);
|
||||
}
|
||||
|
||||
@ -131,11 +131,11 @@ int OILibraryImpl::compileCode() {
|
||||
auto objectPath =
|
||||
fs::path((boost::format("/dev/fd/%1%") % objectMemfd).str());
|
||||
|
||||
struct drgn_program *prog = symbols->getDrgnProgram();
|
||||
struct drgn_program* prog = symbols->getDrgnProgram();
|
||||
if (!prog) {
|
||||
return Response::OIL_COMPILATION_FAILURE;
|
||||
}
|
||||
struct drgn_symbol *sym;
|
||||
struct drgn_symbol* sym;
|
||||
if (auto err = drgn_program_find_symbol_by_address(
|
||||
prog, (uintptr_t)_TemplateFunc, &sym)) {
|
||||
LOG(ERROR) << "Error when finding symbol by address " << err->code << " "
|
||||
@ -143,7 +143,7 @@ int OILibraryImpl::compileCode() {
|
||||
drgn_error_destroy(err);
|
||||
return Response::OIL_COMPILATION_FAILURE;
|
||||
}
|
||||
const char *name = drgn_symbol_name(sym);
|
||||
const char* name = drgn_symbol_name(sym);
|
||||
drgn_symbol_destroy(sym);
|
||||
|
||||
// TODO: change this to the new drgn interface from symbol -> type
|
||||
@ -187,13 +187,13 @@ int OILibraryImpl::compileCode() {
|
||||
return Response::OIL_RELOCATION_FAILURE;
|
||||
}
|
||||
|
||||
const auto &[_, segments, jitSymbols] = relocRes.value();
|
||||
const auto& [_, segments, jitSymbols] = relocRes.value();
|
||||
|
||||
// Locate the probe's entry point
|
||||
_self->fp = nullptr;
|
||||
for (const auto &[symName, symAddr] : jitSymbols) {
|
||||
for (const auto& [symName, symAddr] : jitSymbols) {
|
||||
if (symName.starts_with("_Z7getSize")) {
|
||||
_self->fp = (size_t(*)(const void *))symAddr;
|
||||
_self->fp = (size_t(*)(const void*))symAddr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -202,8 +202,8 @@ int OILibraryImpl::compileCode() {
|
||||
}
|
||||
|
||||
// Copy relocated segments in their final destination
|
||||
for (const auto &[BaseAddr, RelocAddr, Size] : segments)
|
||||
memcpy((void *)RelocAddr, (void *)BaseAddr, Size);
|
||||
for (const auto& [BaseAddr, RelocAddr, Size] : segments)
|
||||
memcpy((void*)RelocAddr, (void*)BaseAddr, Size);
|
||||
|
||||
return Response::OIL_SUCCESS;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ namespace ObjectIntrospection {
|
||||
|
||||
class OILibraryImpl {
|
||||
public:
|
||||
OILibraryImpl(OILibrary *, void *);
|
||||
OILibraryImpl(OILibrary*, void*);
|
||||
~OILibraryImpl();
|
||||
|
||||
bool mapSegment();
|
||||
@ -35,16 +35,16 @@ class OILibraryImpl {
|
||||
void enableLayoutAnalysis();
|
||||
|
||||
private:
|
||||
class OILibrary *_self;
|
||||
class OILibrary* _self;
|
||||
|
||||
void *_TemplateFunc;
|
||||
void* _TemplateFunc;
|
||||
|
||||
OICompiler::Config compilerConfig{};
|
||||
OICodeGen::Config generatorConfig{};
|
||||
std::shared_ptr<SymbolService> symbols{};
|
||||
|
||||
struct c {
|
||||
void *textSegBase = nullptr;
|
||||
void* textSegBase = nullptr;
|
||||
size_t textSegSize = 1u << 22;
|
||||
} segConfig;
|
||||
};
|
||||
|
24
src/OIOpts.h
24
src/OIOpts.h
@ -26,21 +26,21 @@ extern "C" {
|
||||
|
||||
struct OIOpt {
|
||||
char shortName;
|
||||
const char *longName;
|
||||
const char* longName;
|
||||
int has_arg;
|
||||
const char *argName;
|
||||
const char *usage;
|
||||
const char* argName;
|
||||
const char* usage;
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
class OIOpts {
|
||||
public:
|
||||
template <typename... Opts>
|
||||
constexpr explicit OIOpts(Opts &&...options)
|
||||
constexpr explicit OIOpts(Opts&&... options)
|
||||
: _opts{std::forward<decltype(options)>(options)...} {
|
||||
// Create the short opts string
|
||||
size_t shortOptIndex = 0;
|
||||
for (const auto &opt : _opts) {
|
||||
for (const auto& opt : _opts) {
|
||||
_shortOpts[shortOptIndex++] = opt.shortName;
|
||||
for (int i = 0; i < opt.has_arg; ++i)
|
||||
_shortOpts[shortOptIndex++] = ':';
|
||||
@ -52,7 +52,7 @@ class OIOpts {
|
||||
|
||||
// Create the array of long opts
|
||||
for (size_t i = 0; i < _opts.size(); ++i) {
|
||||
const auto &opt = _opts[i];
|
||||
const auto& opt = _opts[i];
|
||||
_longOpts[i] = {opt.longName, opt.has_arg, nullptr, opt.shortName};
|
||||
}
|
||||
|
||||
@ -60,15 +60,15 @@ class OIOpts {
|
||||
_longOpts[_opts.size()] = {nullptr, no_argument, nullptr, '\0'};
|
||||
}
|
||||
|
||||
constexpr const char *shortOpts() const {
|
||||
constexpr const char* shortOpts() const {
|
||||
return _shortOpts.data();
|
||||
}
|
||||
constexpr const struct option *longOpts() const {
|
||||
constexpr const struct option* longOpts() const {
|
||||
return _longOpts.data();
|
||||
}
|
||||
|
||||
template <size_t M>
|
||||
friend std::ostream &operator<<(std::ostream &os, const OIOpts<M> &opts);
|
||||
friend std::ostream& operator<<(std::ostream& os, const OIOpts<M>& opts);
|
||||
|
||||
private:
|
||||
std::array<OIOpt, N> _opts;
|
||||
@ -77,16 +77,16 @@ class OIOpts {
|
||||
};
|
||||
|
||||
template <size_t M>
|
||||
std::ostream &operator<<(std::ostream &os, const OIOpts<M> &opts) {
|
||||
std::ostream& operator<<(std::ostream& os, const OIOpts<M>& opts) {
|
||||
int maxLongName = 0;
|
||||
for (const auto &opt : opts._opts) {
|
||||
for (const auto& opt : opts._opts) {
|
||||
size_t longNameWidth = strlen(opt.longName);
|
||||
if (opt.argName)
|
||||
longNameWidth += 1 + strlen(opt.argName);
|
||||
maxLongName = std::max(maxLongName, (int)longNameWidth);
|
||||
}
|
||||
|
||||
for (const auto &opt : opts._opts) {
|
||||
for (const auto& opt : opts._opts) {
|
||||
auto fullName = std::string(opt.longName);
|
||||
if (opt.argName) {
|
||||
fullName += ' ';
|
||||
|
@ -40,7 +40,7 @@ namespace std {
|
||||
|
||||
template <>
|
||||
struct hash<irequest> {
|
||||
std::size_t operator()(const irequest &req) const noexcept {
|
||||
std::size_t operator()(const irequest& req) const noexcept {
|
||||
auto h = hash<std::string>();
|
||||
return h(req.type) ^ h(req.func) ^ h(req.arg);
|
||||
}
|
||||
@ -48,7 +48,7 @@ struct hash<irequest> {
|
||||
|
||||
template <>
|
||||
struct equal_to<irequest> {
|
||||
bool operator()(const irequest &lhs, const irequest &rhs) const noexcept {
|
||||
bool operator()(const irequest& lhs, const irequest& rhs) const noexcept {
|
||||
return lhs.type == rhs.type && lhs.func == rhs.func && lhs.arg == rhs.arg;
|
||||
}
|
||||
};
|
||||
@ -89,7 +89,7 @@ class ParseData {
|
||||
return reqs.size();
|
||||
}
|
||||
|
||||
[[nodiscard]] const prequest &getReq(size_t idx = 0) const noexcept {
|
||||
[[nodiscard]] const prequest& getReq(size_t idx = 0) const noexcept {
|
||||
assert(idx < reqs.size());
|
||||
return reqs[idx];
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <fstream>
|
||||
|
||||
void PaddingHunter::processLocalPaddingInfo() {
|
||||
for (auto &lPS : localPaddedStructs) {
|
||||
for (auto& lPS : localPaddedStructs) {
|
||||
if (paddedStructs.find(lPS.first) != paddedStructs.end()) {
|
||||
if (localPaddedStructs[lPS.first].instancesCnt >
|
||||
paddedStructs[lPS.first].instancesCnt) {
|
||||
@ -38,24 +38,24 @@ void PaddingHunter::outputPaddingInfo() {
|
||||
uint64_t sum = 0;
|
||||
|
||||
std::vector<std::pair<std::string, PaddingInfo>> paddedStructsVec;
|
||||
for (auto &paddedStruct : paddedStructs) {
|
||||
for (auto& paddedStruct : paddedStructs) {
|
||||
paddedStructsVec.push_back({paddedStruct.first, paddedStruct.second});
|
||||
}
|
||||
|
||||
for (auto &paddedStruct : paddedStructsVec) {
|
||||
for (auto& paddedStruct : paddedStructsVec) {
|
||||
sum += paddedStruct.second.paddingSize * paddedStruct.second.instancesCnt;
|
||||
}
|
||||
|
||||
paddingStatsFile << "Total Saving Opportunity: " << sum << "\n\n\n";
|
||||
|
||||
std::sort(paddedStructsVec.begin(), paddedStructsVec.end(),
|
||||
[](const std::pair<std::string, PaddingInfo> &left,
|
||||
const std::pair<std::string, PaddingInfo> &right) {
|
||||
[](const std::pair<std::string, PaddingInfo>& left,
|
||||
const std::pair<std::string, PaddingInfo>& right) {
|
||||
return left.second.instancesCnt * left.second.savingSize >
|
||||
right.second.instancesCnt * right.second.savingSize;
|
||||
});
|
||||
|
||||
for (auto &paddedStruct : paddedStructsVec) {
|
||||
for (auto& paddedStruct : paddedStructsVec) {
|
||||
paddingStatsFile << "Name: " << paddedStruct.first
|
||||
<< ", object size: " << paddedStruct.second.structSize
|
||||
<< ", saving size: " << paddedStruct.second.savingSize
|
||||
|
@ -51,25 +51,25 @@ using oarchive = boost::archive::text_oarchive;
|
||||
"No class version was defined for type `" #Type \
|
||||
"`, please add an invocation of `DEFINE_TYPE_VERSION` for this " \
|
||||
"type."); \
|
||||
template void serialize(iarchive &, Type &, const unsigned int); \
|
||||
template void serialize(oarchive &, Type &, const unsigned int);
|
||||
template void serialize(iarchive&, Type&, const unsigned int); \
|
||||
template void serialize(oarchive&, Type&, const unsigned int);
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, PaddingInfo &p, const unsigned int version) {
|
||||
void serialize(Archive& ar, PaddingInfo& p, const unsigned int version) {
|
||||
verify_version<PaddingInfo>(version);
|
||||
ar &p.structSize;
|
||||
ar &p.paddingSize;
|
||||
ar &p.definition;
|
||||
ar &p.instancesCnt;
|
||||
ar &p.savingSize;
|
||||
ar& p.structSize;
|
||||
ar& p.paddingSize;
|
||||
ar& p.definition;
|
||||
ar& p.instancesCnt;
|
||||
ar& p.savingSize;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(PaddingInfo)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, ContainerInfo &info, const unsigned int version) {
|
||||
void serialize(Archive& ar, ContainerInfo& info, const unsigned int version) {
|
||||
verify_version<ContainerInfo>(version);
|
||||
ar &info.typeName;
|
||||
ar& info.typeName;
|
||||
// Unfortunately boost serialization doesn't support `std::optional`,
|
||||
// so we have to do this ourselves
|
||||
size_t numTemplateParams = 0;
|
||||
@ -77,7 +77,7 @@ void serialize(Archive &ar, ContainerInfo &info, const unsigned int version) {
|
||||
numTemplateParams =
|
||||
info.numTemplateParams.value_or(std::numeric_limits<size_t>::max());
|
||||
}
|
||||
ar &numTemplateParams;
|
||||
ar& numTemplateParams;
|
||||
if (Archive::is_loading::value) {
|
||||
if (numTemplateParams == std::numeric_limits<size_t>::max()) {
|
||||
info.numTemplateParams = std::nullopt;
|
||||
@ -85,124 +85,124 @@ void serialize(Archive &ar, ContainerInfo &info, const unsigned int version) {
|
||||
info.numTemplateParams = numTemplateParams;
|
||||
}
|
||||
}
|
||||
ar &info.ctype;
|
||||
ar &info.header;
|
||||
ar &info.ns;
|
||||
ar& info.ctype;
|
||||
ar& info.header;
|
||||
ar& info.ns;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(ContainerInfo)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, struct drgn_location_description &location,
|
||||
void serialize(Archive& ar, struct drgn_location_description& location,
|
||||
const unsigned int version) {
|
||||
verify_version<struct drgn_location_description>(version);
|
||||
ar &location.start;
|
||||
ar &location.end;
|
||||
ar &location.expr_size;
|
||||
ar& location.start;
|
||||
ar& location.end;
|
||||
ar& location.expr_size;
|
||||
if (Archive::is_loading::value) {
|
||||
// It is important to call `malloc` here instead of allocating with `new`
|
||||
// since these structs are usually allocated and deallocated directly by
|
||||
// `drgn`, which is written in C.
|
||||
location.expr =
|
||||
(const char *)malloc(sizeof(*location.expr) * location.expr_size);
|
||||
(const char*)malloc(sizeof(*location.expr) * location.expr_size);
|
||||
}
|
||||
ar &make_array<char>(const_cast<char *>(location.expr), location.expr_size);
|
||||
ar& make_array<char>(const_cast<char*>(location.expr), location.expr_size);
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(struct drgn_location_description)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, struct drgn_object_locator &locator,
|
||||
void serialize(Archive& ar, struct drgn_object_locator& locator,
|
||||
const unsigned int version) {
|
||||
verify_version<struct drgn_object_locator>(version);
|
||||
ar &locator.module_start;
|
||||
ar &locator.module_end;
|
||||
ar &locator.module_bias;
|
||||
ar &locator.locations_size;
|
||||
ar &locator.frame_base_locations_size;
|
||||
ar& locator.module_start;
|
||||
ar& locator.module_end;
|
||||
ar& locator.module_bias;
|
||||
ar& locator.locations_size;
|
||||
ar& locator.frame_base_locations_size;
|
||||
if (Archive::is_loading::value) {
|
||||
// It is important to call `malloc` here instead of allocating with `new`
|
||||
// since these structs are usually allocated and deallocated directly by
|
||||
// `drgn`, which is written in C.
|
||||
locator.locations = (struct drgn_location_description *)malloc(
|
||||
locator.locations = (struct drgn_location_description*)malloc(
|
||||
sizeof(*locator.locations) * locator.locations_size);
|
||||
locator.frame_base_locations = (struct drgn_location_description *)malloc(
|
||||
locator.frame_base_locations = (struct drgn_location_description*)malloc(
|
||||
sizeof(*locator.frame_base_locations) *
|
||||
locator.frame_base_locations_size);
|
||||
}
|
||||
ar &make_array<struct drgn_location_description>(locator.locations,
|
||||
ar& make_array<struct drgn_location_description>(locator.locations,
|
||||
locator.locations_size);
|
||||
ar &make_array<struct drgn_location_description>(
|
||||
ar& make_array<struct drgn_location_description>(
|
||||
locator.frame_base_locations, locator.frame_base_locations_size);
|
||||
ar &locator.qualified_type;
|
||||
ar& locator.qualified_type;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(struct drgn_object_locator)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, FuncDesc::Arg &arg, const unsigned int version) {
|
||||
void serialize(Archive& ar, FuncDesc::Arg& arg, const unsigned int version) {
|
||||
verify_version<FuncDesc::Arg>(version);
|
||||
ar &arg.typeName;
|
||||
ar &arg.valid;
|
||||
ar &arg.locator;
|
||||
ar& arg.typeName;
|
||||
ar& arg.valid;
|
||||
ar& arg.locator;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(FuncDesc::Arg)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, FuncDesc::Retval &retval,
|
||||
void serialize(Archive& ar, FuncDesc::Retval& retval,
|
||||
const unsigned int version) {
|
||||
verify_version<FuncDesc::Retval>(version);
|
||||
ar &retval.typeName;
|
||||
ar &retval.valid;
|
||||
ar& retval.typeName;
|
||||
ar& retval.valid;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(FuncDesc::Retval)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, FuncDesc::Range &range,
|
||||
void serialize(Archive& ar, FuncDesc::Range& range,
|
||||
const unsigned int version) {
|
||||
verify_version<FuncDesc::Range>(version);
|
||||
ar &range.start;
|
||||
ar &range.end;
|
||||
ar& range.start;
|
||||
ar& range.end;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(FuncDesc::Range)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, FuncDesc &fd, const unsigned int version) {
|
||||
void serialize(Archive& ar, FuncDesc& fd, const unsigned int version) {
|
||||
verify_version<FuncDesc>(version);
|
||||
ar &fd.symName;
|
||||
ar &fd.ranges;
|
||||
ar &fd.isMethod;
|
||||
ar &fd.arguments;
|
||||
ar &fd.retval;
|
||||
ar& fd.symName;
|
||||
ar& fd.ranges;
|
||||
ar& fd.isMethod;
|
||||
ar& fd.arguments;
|
||||
ar& fd.retval;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(FuncDesc)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, GlobalDesc &gd, const unsigned int version) {
|
||||
void serialize(Archive& ar, GlobalDesc& gd, const unsigned int version) {
|
||||
verify_version<GlobalDesc>(version);
|
||||
ar &gd.symName;
|
||||
ar &gd.typeName;
|
||||
ar &gd.baseAddr;
|
||||
ar& gd.symName;
|
||||
ar& gd.typeName;
|
||||
ar& gd.baseAddr;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(GlobalDesc)
|
||||
|
||||
template <class Archive>
|
||||
static void serialize_c_string(Archive &ar, char **string) {
|
||||
static void serialize_c_string(Archive& ar, char** string) {
|
||||
size_t length;
|
||||
if (Archive::is_saving::value) {
|
||||
length = *string ? strlen(*string) : 0;
|
||||
}
|
||||
ar &length;
|
||||
ar& length;
|
||||
if (Archive::is_loading::value) {
|
||||
*string = length ? (char *)malloc(sizeof(char) * (length + 1)) : NULL;
|
||||
*string = length ? (char*)malloc(sizeof(char) * (length + 1)) : NULL;
|
||||
}
|
||||
if (length > 0) {
|
||||
ar &make_array<char>(*string, length + 1);
|
||||
ar& make_array<char>(*string, length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,7 +214,7 @@ static void serialize_c_string(Archive &ar, char **string) {
|
||||
// what you're doing (or ask someone who does) before touching anything.
|
||||
// ###########################################################################
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, struct drgn_type &type,
|
||||
void serialize(Archive& ar, struct drgn_type& type,
|
||||
const unsigned int version) {
|
||||
#define assert_in_same_union(member_1, member_2) \
|
||||
do { \
|
||||
@ -239,10 +239,10 @@ void serialize(Archive &ar, struct drgn_type &type,
|
||||
// `.kind` MUST be serialized first, not just because it's declared first,
|
||||
// but because all of the `drgn_type_has_*` functions rely on the value of
|
||||
// `.kind`
|
||||
ar &type._private.kind;
|
||||
ar &type._private.is_complete;
|
||||
ar &type._private.primitive;
|
||||
ar &type._private.qualifiers;
|
||||
ar& type._private.kind;
|
||||
ar& type._private.is_complete;
|
||||
ar& type._private.primitive;
|
||||
ar& type._private.qualifiers;
|
||||
// `.program` is NULL, per the initial `memset`
|
||||
|
||||
if (Archive::is_loading::value) {
|
||||
@ -258,9 +258,9 @@ void serialize(Archive &ar, struct drgn_type &type,
|
||||
// First union: `name`, `tag`
|
||||
assert_in_same_union(name, tag);
|
||||
if (drgn_type_has_name(&type)) {
|
||||
serialize_c_string(ar, const_cast<char **>(&type._private.name));
|
||||
serialize_c_string(ar, const_cast<char**>(&type._private.name));
|
||||
} else if (drgn_type_has_tag(&type)) {
|
||||
serialize_c_string(ar, const_cast<char **>(&type._private.tag));
|
||||
serialize_c_string(ar, const_cast<char**>(&type._private.tag));
|
||||
}
|
||||
|
||||
// Second union: `size`, `length`, `num_enumerators`, `is_variadic`
|
||||
@ -268,13 +268,13 @@ void serialize(Archive &ar, struct drgn_type &type,
|
||||
assert_in_same_union(size, num_enumerators);
|
||||
assert_in_same_union(size, is_variadic);
|
||||
if (drgn_type_has_size(&type)) {
|
||||
ar &type._private.size;
|
||||
ar& type._private.size;
|
||||
} else if (drgn_type_has_length(&type)) {
|
||||
ar &type._private.length;
|
||||
ar& type._private.length;
|
||||
} else if (drgn_type_has_enumerators(&type)) {
|
||||
ar &type._private.num_enumerators;
|
||||
ar& type._private.num_enumerators;
|
||||
} else if (drgn_type_has_is_variadic(&type)) {
|
||||
ar &type._private.is_variadic;
|
||||
ar& type._private.is_variadic;
|
||||
}
|
||||
|
||||
// Third union: `is_signed`, `num_members`, `num_paramters`
|
||||
@ -286,7 +286,7 @@ void serialize(Archive &ar, struct drgn_type &type,
|
||||
assert_in_same_union(little_endian, enumerators);
|
||||
assert_in_same_union(little_endian, parameters);
|
||||
if (drgn_type_has_little_endian(&type)) {
|
||||
ar &type._private.little_endian;
|
||||
ar& type._private.little_endian;
|
||||
} else if (drgn_type_has_members(&type)) {
|
||||
// Leave `members` set to NULL per the initial `memset`,
|
||||
// see "AVOIDING OVERSERIALIZATION" comment above
|
||||
@ -302,17 +302,17 @@ void serialize(Archive &ar, struct drgn_type &type,
|
||||
// and `num_parents` set to NULL/0 per the initial `memset`, see
|
||||
// "AVOIDING OVERSERIALIZATION" comment above
|
||||
|
||||
ar &type._private.die_addr;
|
||||
ar& type._private.die_addr;
|
||||
// `.module` is NULL, per the initial `memset`
|
||||
if (Archive::is_saving::value) {
|
||||
struct drgn_error *err = drgn_type_sizeof(&type, &type._private.oi_size);
|
||||
struct drgn_error* err = drgn_type_sizeof(&type, &type._private.oi_size);
|
||||
if (err) {
|
||||
drgn_error_destroy(err);
|
||||
type._private.oi_size =
|
||||
std::numeric_limits<decltype(type._private.oi_size)>::max();
|
||||
}
|
||||
}
|
||||
ar &type._private.oi_size;
|
||||
ar& type._private.oi_size;
|
||||
|
||||
// It's important that `oi_name` is declared here and not inside the
|
||||
// if statement so that its data isn't freed when we call
|
||||
@ -322,10 +322,10 @@ void serialize(Archive &ar, struct drgn_type &type,
|
||||
oi_name = drgn_utils::typeToName(&type);
|
||||
type._private.oi_name = oi_name.c_str();
|
||||
}
|
||||
serialize_c_string(ar, const_cast<char **>(&type._private.oi_name));
|
||||
serialize_c_string(ar, const_cast<char**>(&type._private.oi_name));
|
||||
|
||||
if (drgn_type_kind(&type) == DRGN_TYPE_ARRAY) {
|
||||
ar &type._private.type;
|
||||
ar& type._private.type;
|
||||
}
|
||||
#undef assert_in_same_union
|
||||
}
|
||||
@ -333,48 +333,48 @@ void serialize(Archive &ar, struct drgn_type &type,
|
||||
INSTANCIATE_SERIALIZE(struct drgn_type)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, struct DrgnClassMemberInfo &m,
|
||||
void serialize(Archive& ar, struct DrgnClassMemberInfo& m,
|
||||
const unsigned int version) {
|
||||
verify_version<struct DrgnClassMemberInfo>(version);
|
||||
ar &m.type;
|
||||
ar &m.member_name;
|
||||
ar &m.bit_offset;
|
||||
ar &m.bit_field_size;
|
||||
ar& m.type;
|
||||
ar& m.member_name;
|
||||
ar& m.bit_offset;
|
||||
ar& m.bit_field_size;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(DrgnClassMemberInfo)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, struct drgn_qualified_type &type,
|
||||
void serialize(Archive& ar, struct drgn_qualified_type& type,
|
||||
const unsigned int version) {
|
||||
verify_version<struct drgn_qualified_type>(version);
|
||||
ar &type.type;
|
||||
ar &type.qualifiers;
|
||||
ar& type.type;
|
||||
ar& type.qualifiers;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(struct drgn_qualified_type)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, RootInfo &rootInfo, const unsigned int version) {
|
||||
void serialize(Archive& ar, RootInfo& rootInfo, const unsigned int version) {
|
||||
verify_version<RootInfo>(version);
|
||||
ar &rootInfo.varName;
|
||||
ar &rootInfo.type;
|
||||
ar& rootInfo.varName;
|
||||
ar& rootInfo.type;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(RootInfo)
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar, struct TypeHierarchy &th,
|
||||
void serialize(Archive& ar, struct TypeHierarchy& th,
|
||||
const unsigned int version) {
|
||||
verify_version<TypeHierarchy>(version);
|
||||
ar &th.classMembersMap;
|
||||
ar &th.containerTypeMap;
|
||||
ar &th.typedefMap;
|
||||
ar &th.sizeMap;
|
||||
ar &th.knownDummyTypeList;
|
||||
ar &th.pointerToTypeMap;
|
||||
ar &th.thriftIssetStructTypes;
|
||||
ar &th.descendantClasses;
|
||||
ar& th.classMembersMap;
|
||||
ar& th.containerTypeMap;
|
||||
ar& th.typedefMap;
|
||||
ar& th.sizeMap;
|
||||
ar& th.knownDummyTypeList;
|
||||
ar& th.pointerToTypeMap;
|
||||
ar& th.thriftIssetStructTypes;
|
||||
ar& th.descendantClasses;
|
||||
}
|
||||
|
||||
INSTANCIATE_SERIALIZE(struct TypeHierarchy)
|
||||
|
@ -59,7 +59,7 @@ namespace boost::serialization {
|
||||
|
||||
#define DECL_SERIALIZE(Type) \
|
||||
template <class Archive> \
|
||||
void serialize(Archive &, Type &, const unsigned int)
|
||||
void serialize(Archive&, Type&, const unsigned int)
|
||||
|
||||
DECL_SERIALIZE(PaddingInfo);
|
||||
DECL_SERIALIZE(ContainerInfo);
|
||||
|
@ -35,7 +35,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
static bool LoadExecutableAddressRange(
|
||||
pid_t pid, std::vector<std::pair<uint64_t, uint64_t>> &exeAddrs) {
|
||||
pid_t pid, std::vector<std::pair<uint64_t, uint64_t>>& exeAddrs) {
|
||||
std::ifstream f("/proc/" + std::to_string(pid) + "/maps");
|
||||
|
||||
if (f.is_open()) {
|
||||
@ -74,13 +74,13 @@ static bool LoadExecutableAddressRange(
|
||||
#undef PREMISSIONS_LEN
|
||||
|
||||
static bool isExecutableAddr(
|
||||
uint64_t addr, const std::vector<std::pair<uint64_t, uint64_t>> &exeAddrs) {
|
||||
uint64_t addr, const std::vector<std::pair<uint64_t, uint64_t>>& exeAddrs) {
|
||||
assert(std::is_sorted(begin(exeAddrs), end(exeAddrs)));
|
||||
|
||||
// Find the smallest exeAddrs range where addr < range.end
|
||||
auto it = std::upper_bound(
|
||||
begin(exeAddrs), end(exeAddrs), std::make_pair(addr, addr),
|
||||
[](const auto &r1, const auto &r2) { return r1.second < r2.second; });
|
||||
[](const auto& r1, const auto& r2) { return r1.second < r2.second; });
|
||||
|
||||
return it != end(exeAddrs) && addr >= it->first;
|
||||
}
|
||||
@ -104,7 +104,7 @@ struct ModParams {
|
||||
std::string_view symName;
|
||||
GElf_Sym sym;
|
||||
GElf_Addr value;
|
||||
std::vector<std::pair<uint64_t, uint64_t>> &exeAddrs;
|
||||
std::vector<std::pair<uint64_t, uint64_t>>& exeAddrs;
|
||||
bool demangle;
|
||||
};
|
||||
|
||||
@ -119,9 +119,9 @@ struct ModParams {
|
||||
*
|
||||
*/
|
||||
|
||||
static int moduleCallback(Dwfl_Module *mod, void ** /* userData */,
|
||||
const char *name, Dwarf_Addr /* start */, void *arg) {
|
||||
ModParams *m = (ModParams *)arg;
|
||||
static int moduleCallback(Dwfl_Module* mod, void** /* userData */,
|
||||
const char* name, Dwarf_Addr /* start */, void* arg) {
|
||||
ModParams* m = (ModParams*)arg;
|
||||
|
||||
int nsym = dwfl_module_getsymtab(mod);
|
||||
VLOG(1) << "mod name: " << name << " "
|
||||
@ -144,10 +144,10 @@ static int moduleCallback(Dwfl_Module *mod, void ** /* userData */,
|
||||
|
||||
/* I think the first entry is always UNDEF */
|
||||
for (int i = 1; i < nsym; ++i) {
|
||||
Elf *elf = nullptr;
|
||||
Elf* elf = nullptr;
|
||||
GElf_Word shndxp = 0;
|
||||
|
||||
const char *lookupResult = dwfl_module_getsym_info(
|
||||
const char* lookupResult = dwfl_module_getsym_info(
|
||||
mod, i, &m->sym, &m->value, &shndxp, &elf, nullptr);
|
||||
if (lookupResult == nullptr || lookupResult[0] == '\0') {
|
||||
continue;
|
||||
@ -204,8 +204,8 @@ static int moduleCallback(Dwfl_Module *mod, void ** /* userData */,
|
||||
* @return - A std::optional with the symbol's information
|
||||
*/
|
||||
std::optional<SymbolInfo> SymbolService::locateSymbol(
|
||||
const std::string &symName, bool demangle) {
|
||||
static char *debuginfo_path;
|
||||
const std::string& symName, bool demangle) {
|
||||
static char* debuginfo_path;
|
||||
static const Dwfl_Callbacks proc_callbacks{
|
||||
.find_elf = dwfl_linux_proc_find_elf,
|
||||
.find_debuginfo = dwfl_standard_find_debuginfo,
|
||||
@ -213,7 +213,7 @@ std::optional<SymbolInfo> SymbolService::locateSymbol(
|
||||
.debuginfo_path = &debuginfo_path,
|
||||
};
|
||||
|
||||
Dwfl *dwfl = dwfl_begin(&proc_callbacks);
|
||||
Dwfl* dwfl = dwfl_begin(&proc_callbacks);
|
||||
if (dwfl == nullptr) {
|
||||
LOG(ERROR) << "dwfl_begin: " << dwfl_errmsg(dwfl_errno());
|
||||
return std::nullopt;
|
||||
@ -232,8 +232,8 @@ std::optional<SymbolInfo> SymbolService::locateSymbol(
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
const auto &exe = std::get<fs::path>(target);
|
||||
Dwfl_Module *mod =
|
||||
const auto& exe = std::get<fs::path>(target);
|
||||
Dwfl_Module* mod =
|
||||
dwfl_report_offline(dwfl, exe.c_str(), exe.c_str(), -1);
|
||||
if (mod == nullptr) {
|
||||
LOG(ERROR) << "dwfl_report_offline: " << dwfl_errmsg(dwfl_errno());
|
||||
@ -268,7 +268,7 @@ std::optional<SymbolInfo> SymbolService::locateSymbol(
|
||||
.exeAddrs = executableAddrs,
|
||||
.demangle = demangle};
|
||||
|
||||
dwfl_getmodules(dwfl, moduleCallback, (void *)&m, 0);
|
||||
dwfl_getmodules(dwfl, moduleCallback, (void*)&m, 0);
|
||||
|
||||
if (m.value == 0) {
|
||||
return std::nullopt;
|
||||
@ -276,7 +276,7 @@ std::optional<SymbolInfo> SymbolService::locateSymbol(
|
||||
return SymbolInfo{m.value, m.sym.st_size};
|
||||
}
|
||||
|
||||
static std::string bytesToHexString(const unsigned char *bytes, int nbbytes) {
|
||||
static std::string bytesToHexString(const unsigned char* bytes, int nbbytes) {
|
||||
static const char characters[] = "0123456789abcdef";
|
||||
|
||||
std::string ret(nbbytes * 2, 0);
|
||||
@ -296,21 +296,21 @@ static std::string bytesToHexString(const unsigned char *bytes, int nbbytes) {
|
||||
* to this callback. So we always return DWARF_CB_ABORT, as this is
|
||||
* the only build ID we are interested in.
|
||||
*/
|
||||
static int buildIDCallback(Dwfl_Module *mod, void ** /* userData */,
|
||||
const char *name, Dwarf_Addr /* start */,
|
||||
void *arg) {
|
||||
auto *buildID = static_cast<std::optional<std::string> *>(arg);
|
||||
static int buildIDCallback(Dwfl_Module* mod, void** /* userData */,
|
||||
const char* name, Dwarf_Addr /* start */,
|
||||
void* arg) {
|
||||
auto* buildID = static_cast<std::optional<std::string>*>(arg);
|
||||
|
||||
// We must call dwfl_module_getelf before using dwfl_module_build_id
|
||||
GElf_Addr bias = 0;
|
||||
Elf *elf = dwfl_module_getelf(mod, &bias);
|
||||
Elf* elf = dwfl_module_getelf(mod, &bias);
|
||||
if (elf == nullptr) {
|
||||
LOG(ERROR) << "Failed to getelf for " << name << ": " << dwfl_errmsg(-1);
|
||||
return DWARF_CB_ABORT;
|
||||
}
|
||||
|
||||
GElf_Addr vaddr = 0;
|
||||
const unsigned char *bytes = nullptr;
|
||||
const unsigned char* bytes = nullptr;
|
||||
|
||||
int nbbytes = dwfl_module_build_id(mod, &bytes, &vaddr);
|
||||
if (nbbytes <= 0) {
|
||||
@ -326,7 +326,7 @@ static int buildIDCallback(Dwfl_Module *mod, void ** /* userData */,
|
||||
}
|
||||
|
||||
std::optional<std::string> SymbolService::locateBuildID() {
|
||||
static char *debuginfoPath;
|
||||
static char* debuginfoPath;
|
||||
static const Dwfl_Callbacks procCallbacks = {
|
||||
.find_elf = dwfl_linux_proc_find_elf,
|
||||
.find_debuginfo = dwfl_standard_find_debuginfo,
|
||||
@ -334,7 +334,7 @@ std::optional<std::string> SymbolService::locateBuildID() {
|
||||
.debuginfo_path = &debuginfoPath,
|
||||
};
|
||||
|
||||
Dwfl *dwfl = dwfl_begin(&procCallbacks);
|
||||
Dwfl* dwfl = dwfl_begin(&procCallbacks);
|
||||
if (dwfl == nullptr) {
|
||||
LOG(ERROR) << "dwfl_begin: " << dwfl_errmsg(dwfl_errno());
|
||||
return std::nullopt;
|
||||
@ -353,7 +353,7 @@ std::optional<std::string> SymbolService::locateBuildID() {
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
const auto &exe = std::get<fs::path>(target);
|
||||
const auto& exe = std::get<fs::path>(target);
|
||||
if (dwfl_report_offline(dwfl, exe.c_str(), exe.c_str(), -1) == nullptr) {
|
||||
LOG(ERROR) << "dwfl_report_offline: " << dwfl_errmsg(dwfl_errno());
|
||||
return std::nullopt;
|
||||
@ -367,12 +367,12 @@ std::optional<std::string> SymbolService::locateBuildID() {
|
||||
}
|
||||
|
||||
std::optional<std::string> buildID;
|
||||
dwfl_getmodules(dwfl, buildIDCallback, (void *)&buildID, 0);
|
||||
dwfl_getmodules(dwfl, buildIDCallback, (void*)&buildID, 0);
|
||||
|
||||
return buildID;
|
||||
}
|
||||
|
||||
struct drgn_program *SymbolService::getDrgnProgram() {
|
||||
struct drgn_program* SymbolService::getDrgnProgram() {
|
||||
if (hardDisableDrgn) {
|
||||
LOG(ERROR) << "drgn is disabled, refusing to initialize";
|
||||
return nullptr;
|
||||
@ -385,15 +385,15 @@ struct drgn_program *SymbolService::getDrgnProgram() {
|
||||
LOG(INFO) << "Initialising drgn. This might take a while";
|
||||
switch (target.index()) {
|
||||
case 0: {
|
||||
if (auto *err = drgn_program_from_pid(std::get<pid_t>(target), &prog)) {
|
||||
if (auto* err = drgn_program_from_pid(std::get<pid_t>(target), &prog)) {
|
||||
LOG(ERROR) << "Failed to initialize drgn: " << err->code << " "
|
||||
<< err->message;
|
||||
return nullptr;
|
||||
}
|
||||
auto executable = fs::read_symlink(
|
||||
"/proc/" + std::to_string(std::get<pid_t>(target)) + "/exe");
|
||||
const auto *executableCStr = executable.c_str();
|
||||
if (auto *err = drgn_program_load_debug_info(prog, &executableCStr, 1,
|
||||
const auto* executableCStr = executable.c_str();
|
||||
if (auto* err = drgn_program_load_debug_info(prog, &executableCStr, 1,
|
||||
false, false)) {
|
||||
LOG(ERROR) << "Error loading debug info: " << err->message;
|
||||
return nullptr;
|
||||
@ -401,14 +401,14 @@ struct drgn_program *SymbolService::getDrgnProgram() {
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
if (auto *err = drgn_program_create(nullptr, &prog)) {
|
||||
if (auto* err = drgn_program_create(nullptr, &prog)) {
|
||||
LOG(ERROR) << "Failed to create empty drgn program: " << err->code
|
||||
<< " " << err->message;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *path = std::get<fs::path>(target).c_str();
|
||||
if (auto *err =
|
||||
const char* path = std::get<fs::path>(target).c_str();
|
||||
if (auto* err =
|
||||
drgn_program_load_debug_info(prog, &path, 1, false, false)) {
|
||||
LOG(ERROR) << "Failed to read debug info: " << err->code << " "
|
||||
<< err->message;
|
||||
@ -430,9 +430,9 @@ struct drgn_program *SymbolService::getDrgnProgram() {
|
||||
* Although 'parseFormalParam' has an all-encompassing sounding name, its sole
|
||||
* task is to extract the location information for this parameter if any exist.
|
||||
*/
|
||||
static void parseFormalParam(Dwarf_Die ¶m, struct drgn_module *module,
|
||||
struct drgn_program *prog, Dwarf_Die &funcDie,
|
||||
std::shared_ptr<FuncDesc> &fd) {
|
||||
static void parseFormalParam(Dwarf_Die& param, struct drgn_module* module,
|
||||
struct drgn_program* prog, Dwarf_Die& funcDie,
|
||||
std::shared_ptr<FuncDesc>& fd) {
|
||||
/*
|
||||
* NOTE: It is vital that the function descriptors list of arguments
|
||||
* are in order and that an entry exists for each argument position
|
||||
@ -441,7 +441,7 @@ static void parseFormalParam(Dwarf_Die ¶m, struct drgn_module *module,
|
||||
* any new error handling.
|
||||
*/
|
||||
auto farg = fd->addArgument();
|
||||
auto *err =
|
||||
auto* err =
|
||||
drgn_object_locator_init(prog, module, &funcDie, ¶m, &farg->locator);
|
||||
if (err) {
|
||||
LOG(ERROR) << "Could not initialize drgn_object_locator for parameter: "
|
||||
@ -450,7 +450,7 @@ static void parseFormalParam(Dwarf_Die ¶m, struct drgn_module *module,
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = nullptr;
|
||||
const char* name = nullptr;
|
||||
Dwarf_Attribute attr;
|
||||
if (dwarf_attr_integrate(¶m, DW_AT_name, &attr)) {
|
||||
if (!(name = dwarf_formstring(&attr))) {
|
||||
@ -473,14 +473,14 @@ static void parseFormalParam(Dwarf_Die ¶m, struct drgn_module *module,
|
||||
VLOG(1) << "Adding function arg address: " << farg;
|
||||
}
|
||||
|
||||
static bool handleInlinedFunction(const irequest &request,
|
||||
static bool handleInlinedFunction(const irequest& request,
|
||||
std::shared_ptr<FuncDesc> funcDesc,
|
||||
struct drgn_qualified_type &funcType,
|
||||
Dwarf_Die &funcDie,
|
||||
struct drgn_module *&module) {
|
||||
struct drgn_qualified_type& funcType,
|
||||
Dwarf_Die& funcDie,
|
||||
struct drgn_module*& module) {
|
||||
VLOG(1) << "Function '" << funcDesc->symName << "' has been inlined";
|
||||
struct drgn_type_inlined_instances_iterator *iter = nullptr;
|
||||
auto *err = drgn_type_inlined_instances_iterator_init(funcType.type, &iter);
|
||||
struct drgn_type_inlined_instances_iterator* iter = nullptr;
|
||||
auto* err = drgn_type_inlined_instances_iterator_init(funcType.type, &iter);
|
||||
if (err) {
|
||||
LOG(ERROR) << "Error creating inlined instances iterator: " << err->message;
|
||||
return false;
|
||||
@ -492,8 +492,8 @@ static bool handleInlinedFunction(const irequest &request,
|
||||
if (!index.has_value()) {
|
||||
return false;
|
||||
}
|
||||
auto *argumentName = drgn_type_parameters(funcType.type)[index.value()].name;
|
||||
struct drgn_type *inlinedInstance = nullptr;
|
||||
auto* argumentName = drgn_type_parameters(funcType.type)[index.value()].name;
|
||||
struct drgn_type* inlinedInstance = nullptr;
|
||||
bool foundInstance = false;
|
||||
// The index at which the parameter was actually found in the inlined
|
||||
// instance. This may differ from the index of the parameter in the function
|
||||
@ -515,7 +515,7 @@ static bool handleInlinedFunction(const irequest &request,
|
||||
}
|
||||
|
||||
auto numParameters = drgn_type_num_parameters(inlinedInstance);
|
||||
auto *parameters = drgn_type_parameters(inlinedInstance);
|
||||
auto* parameters = drgn_type_parameters(inlinedInstance);
|
||||
for (size_t i = 0; i < numParameters; i++) {
|
||||
if (strcmp(argumentName, parameters[i].name) == 0) {
|
||||
foundInstance = true;
|
||||
@ -535,7 +535,7 @@ static bool handleInlinedFunction(const irequest &request,
|
||||
drgn_type_num_parameters(funcType.type);
|
||||
// Allocating with `calloc` since `drgn` manages the lifetimes of its
|
||||
// own structures, and it is written in C.
|
||||
inlinedInstance->_private.parameters = (struct drgn_type_parameter *)calloc(
|
||||
inlinedInstance->_private.parameters = (struct drgn_type_parameter*)calloc(
|
||||
inlinedInstance->_private.num_parameters,
|
||||
sizeof(*inlinedInstance->_private.parameters));
|
||||
inlinedInstance->_private.parameters[index.value()] = targetParameter;
|
||||
@ -552,14 +552,14 @@ static bool handleInlinedFunction(const irequest &request,
|
||||
}
|
||||
|
||||
static std::optional<std::shared_ptr<FuncDesc>> createFuncDesc(
|
||||
struct drgn_program *prog, const irequest &request) {
|
||||
struct drgn_program* prog, const irequest& request) {
|
||||
VLOG(1) << "Creating function description for: " << request.func;
|
||||
|
||||
Dwarf_Die funcDie;
|
||||
struct drgn_qualified_type ft {};
|
||||
struct drgn_module *module = nullptr;
|
||||
struct drgn_module* module = nullptr;
|
||||
|
||||
if (auto *err = drgn_program_find_type_by_symbol_name(
|
||||
if (auto* err = drgn_program_find_type_by_symbol_name(
|
||||
prog, request.func.c_str(), &ft, &funcDie, &module)) {
|
||||
LOG(ERROR) << "Error when finding type by symbol: " << err->code << " "
|
||||
<< err->message;
|
||||
@ -662,13 +662,13 @@ static std::optional<std::shared_ptr<FuncDesc>> createFuncDesc(
|
||||
* one if it doesn't exist. Just take the
|
||||
* up front hit of looking everything up now.
|
||||
*/
|
||||
std::shared_ptr<FuncDesc> SymbolService::findFuncDesc(const irequest &request) {
|
||||
std::shared_ptr<FuncDesc> SymbolService::findFuncDesc(const irequest& request) {
|
||||
if (auto it = funcDescs.find(request.func); it != end(funcDescs)) {
|
||||
VLOG(1) << "Found funcDesc for " << request.func;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
struct drgn_program *drgnProg = getDrgnProgram();
|
||||
struct drgn_program* drgnProg = getDrgnProgram();
|
||||
if (drgnProg == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -685,7 +685,7 @@ std::shared_ptr<FuncDesc> SymbolService::findFuncDesc(const irequest &request) {
|
||||
}
|
||||
|
||||
std::shared_ptr<GlobalDesc> SymbolService::findGlobalDesc(
|
||||
const std::string &global) {
|
||||
const std::string& global) {
|
||||
if (auto it = globalDescs.find(global); it != end(globalDescs)) {
|
||||
VLOG(1) << "Found globalDesc for " << global;
|
||||
return it->second;
|
||||
@ -700,7 +700,7 @@ std::shared_ptr<GlobalDesc> SymbolService::findGlobalDesc(
|
||||
VLOG(1) << "locateGlobal: address of " << global << " " << std::hex
|
||||
<< sym->addr;
|
||||
|
||||
struct drgn_program *drgnProg = getDrgnProgram();
|
||||
struct drgn_program* drgnProg = getDrgnProgram();
|
||||
if (drgnProg == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -713,7 +713,7 @@ std::shared_ptr<GlobalDesc> SymbolService::findGlobalDesc(
|
||||
drgn_object_deinit(&globalObj);
|
||||
};
|
||||
|
||||
if (auto *err = drgn_program_find_object(drgnProg, global.c_str(), nullptr,
|
||||
if (auto* err = drgn_program_find_object(drgnProg, global.c_str(), nullptr,
|
||||
DRGN_FIND_OBJECT_ANY, &globalObj)) {
|
||||
LOG(ERROR) << "Failed to lookup global variable '" << global
|
||||
<< "': " << err->code << " " << err->message;
|
||||
@ -729,14 +729,14 @@ std::shared_ptr<GlobalDesc> SymbolService::findGlobalDesc(
|
||||
return gd;
|
||||
}
|
||||
|
||||
std::string SymbolService::getTypeName(struct drgn_type *type) {
|
||||
std::string SymbolService::getTypeName(struct drgn_type* type) {
|
||||
if (drgn_type_kind(type) == DRGN_TYPE_POINTER) {
|
||||
type = drgn_type_type(type).type;
|
||||
}
|
||||
return drgn_utils::typeToName(type);
|
||||
}
|
||||
|
||||
std::optional<RootInfo> SymbolService::getRootType(const irequest &req) {
|
||||
std::optional<RootInfo> SymbolService::getRootType(const irequest& req) {
|
||||
if (req.type == "global") {
|
||||
/*
|
||||
* This is super simple as all we have to do is locate assign the
|
||||
@ -749,14 +749,14 @@ std::optional<RootInfo> SymbolService::getRootType(const irequest &req) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto *prog = getDrgnProgram();
|
||||
auto* prog = getDrgnProgram();
|
||||
if (prog == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
drgn_object global{};
|
||||
drgn_object_init(&global, prog);
|
||||
if (auto *err = drgn_program_find_object(prog, req.func.c_str(), nullptr,
|
||||
if (auto* err = drgn_program_find_object(prog, req.func.c_str(), nullptr,
|
||||
DRGN_FIND_OBJECT_ANY, &global);
|
||||
err != nullptr) {
|
||||
LOG(ERROR) << "Failed to lookup global variable '" << req.func
|
||||
@ -781,13 +781,13 @@ std::optional<RootInfo> SymbolService::getRootType(const irequest &req) {
|
||||
// auto tmp = boost::core::demangle(req->func.c_str());
|
||||
// auto demangledName = tmp.substr(0, tmp.find("("));
|
||||
|
||||
auto *prog = getDrgnProgram();
|
||||
auto* prog = getDrgnProgram();
|
||||
if (prog == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
drgn_qualified_type ft{};
|
||||
if (auto *err = drgn_program_find_type_by_symbol_name(prog, req.func.c_str(),
|
||||
if (auto* err = drgn_program_find_type_by_symbol_name(prog, req.func.c_str(),
|
||||
&ft, nullptr, nullptr);
|
||||
err != nullptr) {
|
||||
LOG(ERROR) << "Error when finding type by symbol " << err->code << " "
|
||||
@ -806,7 +806,7 @@ std::optional<RootInfo> SymbolService::getRootType(const irequest &req) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto *params = drgn_type_parameters(ft.type);
|
||||
auto* params = drgn_type_parameters(ft.type);
|
||||
auto paramsCount = drgn_type_num_parameters(ft.type);
|
||||
if (paramsCount == 0) {
|
||||
LOG(ERROR) << "Function " << req.func << " has no parameters";
|
||||
@ -833,7 +833,7 @@ std::optional<RootInfo> SymbolService::getRootType(const irequest &req) {
|
||||
}
|
||||
|
||||
drgn_qualified_type paramType{};
|
||||
if (auto *err = drgn_parameter_type(¶ms[argIdx], ¶mType);
|
||||
if (auto* err = drgn_parameter_type(¶ms[argIdx], ¶mType);
|
||||
err != nullptr) {
|
||||
LOG(ERROR) << "Failed to get params: " << err->code << " " << err->message;
|
||||
drgn_error_destroy(err);
|
||||
|
@ -41,16 +41,16 @@ class SymbolService {
|
||||
SymbolService(std::variant<pid_t, fs::path>);
|
||||
~SymbolService();
|
||||
|
||||
struct drgn_program *getDrgnProgram();
|
||||
struct drgn_program* getDrgnProgram();
|
||||
|
||||
std::optional<std::string> locateBuildID();
|
||||
std::optional<SymbolInfo> locateSymbol(const std::string &,
|
||||
std::optional<SymbolInfo> locateSymbol(const std::string&,
|
||||
bool demangle = false);
|
||||
|
||||
std::shared_ptr<FuncDesc> findFuncDesc(const irequest &);
|
||||
std::shared_ptr<GlobalDesc> findGlobalDesc(const std::string &);
|
||||
static std::string getTypeName(struct drgn_type *);
|
||||
std::optional<RootInfo> getRootType(const irequest &);
|
||||
std::shared_ptr<FuncDesc> findFuncDesc(const irequest&);
|
||||
std::shared_ptr<GlobalDesc> findGlobalDesc(const std::string&);
|
||||
static std::string getTypeName(struct drgn_type*);
|
||||
std::optional<RootInfo> getRootType(const irequest&);
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<FuncDesc>> funcDescs;
|
||||
std::unordered_map<std::string, std::shared_ptr<GlobalDesc>> globalDescs;
|
||||
@ -61,7 +61,7 @@ class SymbolService {
|
||||
|
||||
private:
|
||||
std::variant<pid_t, fs::path> target{0};
|
||||
struct drgn_program *prog{nullptr};
|
||||
struct drgn_program* prog{nullptr};
|
||||
|
||||
std::vector<std::pair<uint64_t, uint64_t>> executableAddrs{};
|
||||
bool hardDisableDrgn = false;
|
||||
|
@ -66,10 +66,10 @@ struct Syscall {
|
||||
* The types passed to `struct Syscall` come directly from `man 2 <SYSCALL>`.
|
||||
* Don't hesitate to expand this list if you need more syscalls!
|
||||
*/
|
||||
using SysOpen = Syscall<"open", SYS_open, int, const char *, int, mode_t>;
|
||||
using SysOpen = Syscall<"open", SYS_open, int, const char*, int, mode_t>;
|
||||
using SysClose = Syscall<"close", SYS_close, int, int>;
|
||||
using SysFsync = Syscall<"fsync", SYS_fsync, int, int>;
|
||||
|
||||
using SysMmap =
|
||||
Syscall<"mmap", SYS_mmap, void *, void *, size_t, int, int, int, off_t>;
|
||||
using SysMunmap = Syscall<"munmap", SYS_munmap, int, void *, size_t>;
|
||||
Syscall<"mmap", SYS_mmap, void*, void*, size_t, int, int, int, off_t>;
|
||||
using SysMunmap = Syscall<"munmap", SYS_munmap, int, void*, size_t>;
|
||||
|
@ -19,6 +19,6 @@
|
||||
using time_hr = std::chrono::high_resolution_clock;
|
||||
|
||||
template <typename Duration>
|
||||
auto time_ns(Duration const &d) {
|
||||
auto time_ns(Duration const& d) {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(d).count();
|
||||
}
|
||||
|
@ -122,13 +122,13 @@ class trapInfo {
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &out, const trapInfo &t) {
|
||||
static const char *trapTypeDescs[] = {
|
||||
inline std::ostream& operator<<(std::ostream& out, const trapInfo& t) {
|
||||
static const char* trapTypeDescs[] = {
|
||||
"JIT Code Return", // OID_TRAP_JITCODERET
|
||||
"Vector Entry", // OID_TRAP_VECT_ENTRY
|
||||
"Vector Entry Return", // OID_TRAP_VECT_ENTRYRET
|
||||
"Vector Return", // OID_TRAP_VECT_RET
|
||||
};
|
||||
return out << "Trap " << trapTypeDescs[t.trapKind] << " @"
|
||||
<< (void *)t.trapAddr;
|
||||
<< (void*)t.trapAddr;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ TreeBuilder::TreeBuilder(Config c) : config{std::move(c)} {
|
||||
}
|
||||
|
||||
struct TreeBuilder::Variable {
|
||||
struct drgn_type *type;
|
||||
struct drgn_type* type;
|
||||
std::string_view name;
|
||||
std::string typePath;
|
||||
std::optional<bool> isset = std::nullopt;
|
||||
@ -196,12 +196,12 @@ TreeBuilder::~TreeBuilder() {
|
||||
|
||||
bool TreeBuilder::emptyOutput() const {
|
||||
return std::ranges::all_of(rootIDs,
|
||||
[](auto &id) { return id == ERROR_NODE_ID; });
|
||||
[](auto& id) { return id == ERROR_NODE_ID; });
|
||||
}
|
||||
|
||||
void TreeBuilder::build(const std::vector<uint64_t> &data,
|
||||
const std::string &argName, struct drgn_type *type,
|
||||
const TypeHierarchy &typeHierarchy) {
|
||||
void TreeBuilder::build(const std::vector<uint64_t>& data,
|
||||
const std::string& argName, struct drgn_type* type,
|
||||
const TypeHierarchy& typeHierarchy) {
|
||||
th = &typeHierarchy;
|
||||
oidData = &data;
|
||||
|
||||
@ -212,7 +212,7 @@ void TreeBuilder::build(const std::vector<uint64_t> &data,
|
||||
VLOG(1) << "Building tree...";
|
||||
|
||||
{
|
||||
auto &rootID = rootIDs.emplace_back(nextNodeID++);
|
||||
auto& rootID = rootIDs.emplace_back(nextNodeID++);
|
||||
|
||||
try {
|
||||
// The first value is the address of the root object
|
||||
@ -276,11 +276,11 @@ void TreeBuilder::dumpJson() {
|
||||
}
|
||||
|
||||
void TreeBuilder::setPaddedStructs(
|
||||
std::map<std::string, PaddingInfo> *_paddedStructs) {
|
||||
std::map<std::string, PaddingInfo>* _paddedStructs) {
|
||||
this->paddedStructs = _paddedStructs;
|
||||
}
|
||||
|
||||
static std::string drgnTypeToName(struct drgn_type *type) {
|
||||
static std::string drgnTypeToName(struct drgn_type* type) {
|
||||
if (type->_private.program != nullptr) {
|
||||
return drgn_utils::typeToName(type);
|
||||
}
|
||||
@ -288,15 +288,15 @@ static std::string drgnTypeToName(struct drgn_type *type) {
|
||||
return type->_private.oi_name ? type->_private.oi_name : "";
|
||||
}
|
||||
|
||||
static struct drgn_error *drgnTypeSizeof(struct drgn_type *type,
|
||||
uint64_t *ret) {
|
||||
static struct drgn_error* drgnTypeSizeof(struct drgn_type* type,
|
||||
uint64_t* ret) {
|
||||
static struct drgn_error incompleteTypeError = {
|
||||
.code = DRGN_ERROR_TYPE,
|
||||
.needs_destroy = false,
|
||||
.errnum = 0,
|
||||
.path = NULL,
|
||||
.address = 0,
|
||||
.message = (char *)"cannot get size of incomplete type",
|
||||
.message = (char*)"cannot get size of incomplete type",
|
||||
};
|
||||
|
||||
if (drgn_type_kind(type) == DRGN_TYPE_FUNCTION) {
|
||||
@ -318,9 +318,9 @@ static struct drgn_error *drgnTypeSizeof(struct drgn_type *type,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint64_t TreeBuilder::getDrgnTypeSize(struct drgn_type *type) {
|
||||
uint64_t TreeBuilder::getDrgnTypeSize(struct drgn_type* type) {
|
||||
uint64_t size = 0;
|
||||
struct drgn_error *err = drgnTypeSizeof(type, &size);
|
||||
struct drgn_error* err = drgnTypeSizeof(type, &size);
|
||||
BOOST_SCOPE_EXIT(err) {
|
||||
drgn_error_destroy(err);
|
||||
}
|
||||
@ -330,7 +330,7 @@ uint64_t TreeBuilder::getDrgnTypeSize(struct drgn_type *type) {
|
||||
}
|
||||
|
||||
std::string typeName = drgnTypeToName(type);
|
||||
for (auto &[typeName2, size2] : th->sizeMap)
|
||||
for (auto& [typeName2, size2] : th->sizeMap)
|
||||
if (typeName.starts_with(typeName2))
|
||||
return size2;
|
||||
|
||||
@ -347,17 +347,17 @@ uint64_t TreeBuilder::next() {
|
||||
if (oidDataIndex >= oidData->size()) {
|
||||
throw std::runtime_error("Unexpected end of data");
|
||||
}
|
||||
VLOG(3) << "next = " << (void *)(*oidData)[oidDataIndex];
|
||||
VLOG(3) << "next = " << (void*)(*oidData)[oidDataIndex];
|
||||
return (*oidData)[oidDataIndex++];
|
||||
}
|
||||
|
||||
bool TreeBuilder::isContainer(const Variable &variable) {
|
||||
bool TreeBuilder::isContainer(const Variable& variable) {
|
||||
return th->containerTypeMap.contains(variable.type) ||
|
||||
(drgn_type_kind(variable.type) == DRGN_TYPE_ARRAY &&
|
||||
drgn_type_length(variable.type) > 0);
|
||||
}
|
||||
|
||||
bool TreeBuilder::isPrimitive(struct drgn_type *type) {
|
||||
bool TreeBuilder::isPrimitive(struct drgn_type* type) {
|
||||
while (drgn_type_kind(type) == DRGN_TYPE_TYPEDEF) {
|
||||
auto entry = th->typedefMap.find(type);
|
||||
if (entry == th->typedefMap.end())
|
||||
@ -376,14 +376,14 @@ bool TreeBuilder::shouldProcess(uintptr_t pointer) {
|
||||
return unprocessed;
|
||||
}
|
||||
|
||||
static std::string_view drgnKindStr(struct drgn_type *type) {
|
||||
static std::string_view drgnKindStr(struct drgn_type* type) {
|
||||
auto kind = OICodeGen::drgnKindStr(type);
|
||||
// -1 is for the null terminator
|
||||
kind.remove_prefix(sizeof("DRGN_TYPE_") - 1);
|
||||
return kind;
|
||||
}
|
||||
|
||||
void TreeBuilder::setSize(TreeBuilder::Node &node, uint64_t dynamicSize,
|
||||
void TreeBuilder::setSize(TreeBuilder::Node& node, uint64_t dynamicSize,
|
||||
uint64_t memberSizes) {
|
||||
node.dynamicSize = dynamicSize;
|
||||
if (memberSizes > node.staticSize + node.dynamicSize) {
|
||||
@ -469,14 +469,14 @@ TreeBuilder::Node TreeBuilder::process(NodeID id, Variable variable) {
|
||||
} else if (isContainer(variable)) {
|
||||
processContainer(variable, node);
|
||||
} else {
|
||||
drgn_type *objectType = variable.type;
|
||||
drgn_type* objectType = variable.type;
|
||||
if (auto it = th->descendantClasses.find(objectType);
|
||||
it != th->descendantClasses.end()) {
|
||||
// The first item of data in dynamic classes identifies which
|
||||
// concrete type we should process it as, represented as an index
|
||||
// into the vector of child classes, or -1 to processes this type
|
||||
// as itself.
|
||||
const auto &descendants = it->second;
|
||||
const auto& descendants = it->second;
|
||||
auto val = next();
|
||||
if (val != (uint64_t)-1) {
|
||||
objectType = descendants[val];
|
||||
@ -490,7 +490,7 @@ TreeBuilder::Node TreeBuilder::process(NodeID id, Variable variable) {
|
||||
break;
|
||||
}
|
||||
|
||||
const auto &members = entry->second;
|
||||
const auto& members = entry->second;
|
||||
node.children = {nextNodeID, nextNodeID + members.size()};
|
||||
nextNodeID += members.size();
|
||||
auto childID = node.children->first;
|
||||
@ -511,7 +511,7 @@ TreeBuilder::Node TreeBuilder::process(NodeID id, Variable variable) {
|
||||
isset = val;
|
||||
}
|
||||
}
|
||||
const auto &member = members[i];
|
||||
const auto& member = members[i];
|
||||
auto child =
|
||||
process(childID++,
|
||||
Variable{member.type, member.member_name,
|
||||
@ -548,7 +548,7 @@ TreeBuilder::Node TreeBuilder::process(NodeID id, Variable variable) {
|
||||
return node;
|
||||
}
|
||||
|
||||
void TreeBuilder::processContainer(const Variable &variable, Node &node) {
|
||||
void TreeBuilder::processContainer(const Variable& variable, Node& node) {
|
||||
VLOG(1) << "Processing container [" << node.id << "] of type '"
|
||||
<< node.typeName << "'";
|
||||
ContainerTypeEnum kind = UNKNOWN_TYPE;
|
||||
@ -556,7 +556,7 @@ void TreeBuilder::processContainer(const Variable &variable, Node &node) {
|
||||
|
||||
if (drgn_type_kind(variable.type) == DRGN_TYPE_ARRAY) {
|
||||
kind = ARRAY_TYPE;
|
||||
struct drgn_type *arrayElementType = nullptr;
|
||||
struct drgn_type* arrayElementType = nullptr;
|
||||
size_t numElems = 0;
|
||||
drgn_utils::getDrgnArrayElementType(variable.type, &arrayElementType,
|
||||
numElems);
|
||||
@ -571,9 +571,9 @@ void TreeBuilder::processContainer(const Variable &variable, Node &node) {
|
||||
node.typeName + "'");
|
||||
}
|
||||
|
||||
auto &[containerInfo, templateTypes] = entry->second;
|
||||
auto& [containerInfo, templateTypes] = entry->second;
|
||||
kind = containerInfo.ctype;
|
||||
for (const auto &tt : templateTypes) {
|
||||
for (const auto& tt : templateTypes) {
|
||||
elementTypes.push_back(tt);
|
||||
}
|
||||
}
|
||||
@ -591,10 +591,10 @@ void TreeBuilder::processContainer(const Variable &variable, Node &node) {
|
||||
// Initialize, then take a reference to the underlying value for convenience
|
||||
// so that we don't have to dereference the optional every time we want to use
|
||||
// it.
|
||||
auto &containerStats =
|
||||
auto& containerStats =
|
||||
node.containerStats.emplace(Node::ContainerStats{0, 0, 0});
|
||||
|
||||
for (auto &type : elementTypes) {
|
||||
for (auto& type : elementTypes) {
|
||||
containerStats.elementStaticSize += getDrgnTypeSize(type.type);
|
||||
}
|
||||
|
||||
@ -659,7 +659,7 @@ void TreeBuilder::processContainer(const Variable &variable, Node &node) {
|
||||
case STD_VARIANT_TYPE: {
|
||||
containerStats.length = containerStats.capacity = 1;
|
||||
containerStats.elementStaticSize = 0;
|
||||
for (auto &type : elementTypes) {
|
||||
for (auto& type : elementTypes) {
|
||||
auto paramSize = getDrgnTypeSize(type.type);
|
||||
containerStats.elementStaticSize =
|
||||
std::max(containerStats.elementStaticSize, paramSize);
|
||||
@ -797,7 +797,7 @@ void TreeBuilder::processContainer(const Variable &variable, Node &node) {
|
||||
containerStats.elementStaticSize += next();
|
||||
size_t bucketCount = next();
|
||||
// Both libc++ and libstdc++ define buckets as an array of raw pointers
|
||||
setSize(node, node.dynamicSize + bucketCount * sizeof(void *), 0);
|
||||
setSize(node, node.dynamicSize + bucketCount * sizeof(void*), 0);
|
||||
containerStats.length = containerStats.capacity = next();
|
||||
} break;
|
||||
case F14_MAP:
|
||||
@ -846,7 +846,7 @@ void TreeBuilder::processContainer(const Variable &variable, Node &node) {
|
||||
}
|
||||
if (std::ranges::all_of(
|
||||
elementTypes.cbegin(), elementTypes.cend(),
|
||||
[this](auto &type) { return isPrimitive(type.type); })) {
|
||||
[this](auto& type) { return isPrimitive(type.type); })) {
|
||||
VLOG(1)
|
||||
<< "Container [" << node.id
|
||||
<< "] contains only primitive types, skipping processing its members";
|
||||
@ -865,7 +865,7 @@ void TreeBuilder::processContainer(const Variable &variable, Node &node) {
|
||||
auto childID = node.children->first;
|
||||
uint64_t memberSizes = 0;
|
||||
for (size_t i = 0; i < containerStats.length; i++) {
|
||||
for (auto &type : elementTypes) {
|
||||
for (auto& type : elementTypes) {
|
||||
auto child =
|
||||
process(childID++, {.type = type.type,
|
||||
.name = "",
|
||||
@ -878,7 +878,7 @@ void TreeBuilder::processContainer(const Variable &variable, Node &node) {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::string_view TreeBuilder::serialize(const T &data) {
|
||||
std::string_view TreeBuilder::serialize(const T& data) {
|
||||
buffer->clear();
|
||||
msgpack::pack(*buffer, data);
|
||||
// It is *very* important that we construct the `std::string_view` with an
|
||||
@ -886,7 +886,7 @@ std::string_view TreeBuilder::serialize(const T &data) {
|
||||
return std::string_view(buffer->data(), buffer->size());
|
||||
}
|
||||
|
||||
void TreeBuilder::JSON(NodeID id, std::ofstream &output) {
|
||||
void TreeBuilder::JSON(NodeID id, std::ofstream& output) {
|
||||
std::string data;
|
||||
auto status = db->Get(rocksdb::ReadOptions(), std::to_string(id), &data);
|
||||
if (!status.ok()) {
|
||||
|
@ -49,10 +49,10 @@ class TreeBuilder {
|
||||
TreeBuilder(Config);
|
||||
~TreeBuilder();
|
||||
|
||||
void build(const std::vector<uint64_t> &, const std::string &,
|
||||
struct drgn_type *, const TypeHierarchy &);
|
||||
void build(const std::vector<uint64_t>&, const std::string&,
|
||||
struct drgn_type*, const TypeHierarchy&);
|
||||
void dumpJson();
|
||||
void setPaddedStructs(std::map<std::string, PaddingInfo> *paddedStructs);
|
||||
void setPaddedStructs(std::map<std::string, PaddingInfo>* paddedStructs);
|
||||
bool emptyOutput() const;
|
||||
|
||||
private:
|
||||
@ -62,9 +62,9 @@ class TreeBuilder {
|
||||
struct Node;
|
||||
struct Variable;
|
||||
|
||||
const TypeHierarchy *th = nullptr;
|
||||
const std::vector<uint64_t> *oidData = nullptr;
|
||||
std::map<std::string, PaddingInfo> *paddedStructs = nullptr;
|
||||
const TypeHierarchy* th = nullptr;
|
||||
const std::vector<uint64_t>* oidData = nullptr;
|
||||
std::map<std::string, PaddingInfo>* paddedStructs = nullptr;
|
||||
|
||||
/*
|
||||
* The RocksDB output needs versioning so they are imported correctly in
|
||||
@ -98,20 +98,20 @@ class TreeBuilder {
|
||||
* to allocate a new buffer every time we serialize a `Node`.
|
||||
*/
|
||||
std::unique_ptr<msgpack::sbuffer> buffer;
|
||||
rocksdb::DB *db = nullptr;
|
||||
rocksdb::DB* db = nullptr;
|
||||
std::unordered_set<uintptr_t> pointers{};
|
||||
|
||||
uint64_t getDrgnTypeSize(struct drgn_type *type);
|
||||
uint64_t getDrgnTypeSize(struct drgn_type* type);
|
||||
uint64_t next();
|
||||
bool isContainer(const Variable &variable);
|
||||
bool isPrimitive(struct drgn_type *type);
|
||||
bool isContainer(const Variable& variable);
|
||||
bool isPrimitive(struct drgn_type* type);
|
||||
bool shouldProcess(uintptr_t pointer);
|
||||
Node process(NodeID id, Variable variable);
|
||||
void processContainer(const Variable &variable, Node &node);
|
||||
void processContainer(const Variable& variable, Node& node);
|
||||
template <class T>
|
||||
std::string_view serialize(const T &);
|
||||
void JSON(NodeID id, std::ofstream &output);
|
||||
std::string_view serialize(const T&);
|
||||
void JSON(NodeID id, std::ofstream& output);
|
||||
|
||||
static void setSize(TreeBuilder::Node &node, uint64_t dynamicSize,
|
||||
static void setSize(TreeBuilder::Node& node, uint64_t dynamicSize,
|
||||
uint64_t memberSizes);
|
||||
};
|
||||
|
@ -49,7 +49,7 @@ void usage(std::string_view progname) {
|
||||
std::cout << opts;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
int c;
|
||||
@ -86,7 +86,7 @@ int main(int argc, char *argv[]) {
|
||||
void IntegrationBase::SetUp() {
|
||||
// Move into a temporary directory to run the test in an isolated environment
|
||||
auto tmp_dir = TmpDirStr();
|
||||
char *res = mkdtemp(&tmp_dir[0]);
|
||||
char* res = mkdtemp(&tmp_dir[0]);
|
||||
if (!res)
|
||||
abort();
|
||||
workingDir = std::move(tmp_dir);
|
||||
@ -94,7 +94,7 @@ void IntegrationBase::SetUp() {
|
||||
}
|
||||
|
||||
void IntegrationBase::TearDown() {
|
||||
const ::testing::TestInfo *const test_info =
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
if (preserve || (preserve_on_failure && test_info->result()->Failed())) {
|
||||
std::cerr << "Working directory preserved at: " << workingDir << std::endl;
|
||||
@ -103,7 +103,7 @@ void IntegrationBase::TearDown() {
|
||||
}
|
||||
}
|
||||
|
||||
int IntegrationBase::exit_code(Proc &proc) {
|
||||
int IntegrationBase::exit_code(Proc& proc) {
|
||||
proc.ctx.run();
|
||||
proc.proc.wait();
|
||||
|
||||
@ -122,7 +122,7 @@ int IntegrationBase::exit_code(Proc &proc) {
|
||||
return proc.proc.exit_code();
|
||||
}
|
||||
|
||||
fs::path IntegrationBase::createCustomConfig(const std::string &extraConfig) {
|
||||
fs::path IntegrationBase::createCustomConfig(const std::string& extraConfig) {
|
||||
// If no extra config provided, return the config path unaltered.
|
||||
if (extraConfig.empty()) {
|
||||
return configFile;
|
||||
@ -135,19 +135,19 @@ fs::path IntegrationBase::createCustomConfig(const std::string &extraConfig) {
|
||||
// moving the file to the temporary directory.
|
||||
fs::path configDirectory = fs::path(configFile).remove_filename();
|
||||
|
||||
if (toml::table *types = config["types"].as_table()) {
|
||||
if (toml::array *arr = (*types)["containers"].as_array()) {
|
||||
arr->for_each([&](auto &&el) {
|
||||
if (toml::table* types = config["types"].as_table()) {
|
||||
if (toml::array* arr = (*types)["containers"].as_array()) {
|
||||
arr->for_each([&](auto&& el) {
|
||||
if constexpr (toml::is_string<decltype(el)>) {
|
||||
el = configDirectory / el.get();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (toml::table *headers = config["headers"].as_table()) {
|
||||
for (auto &path : {"user_paths", "system_paths"}) {
|
||||
if (toml::array *arr = (*headers)[path].as_array()) {
|
||||
arr->for_each([&](auto &&el) {
|
||||
if (toml::table* headers = config["headers"].as_table()) {
|
||||
for (auto& path : {"user_paths", "system_paths"}) {
|
||||
if (toml::array* arr = (*headers)[path].as_array()) {
|
||||
arr->for_each([&](auto&& el) {
|
||||
if constexpr (toml::is_string<decltype(el)>) {
|
||||
el = configDirectory / el.get();
|
||||
}
|
||||
@ -215,7 +215,7 @@ OidProc OidIntegration::runOidOnProcess(OidOpts opts,
|
||||
if (verbose) {
|
||||
std::cerr << "Running: " << targetExe << "\n";
|
||||
std::cerr << "Running: " << oidExe << " ";
|
||||
for (const auto &arg : oid_args) {
|
||||
for (const auto& arg : oid_args) {
|
||||
std::cerr << arg << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
@ -272,9 +272,9 @@ OidProc OidIntegration::runOidOnProcess(OidOpts opts,
|
||||
};
|
||||
}
|
||||
|
||||
void OidIntegration::compare_json(const bpt::ptree &expected_json,
|
||||
const bpt::ptree &actual_json,
|
||||
const std::string &full_key, bool expect_eq) {
|
||||
void OidIntegration::compare_json(const bpt::ptree& expected_json,
|
||||
const bpt::ptree& actual_json,
|
||||
const std::string& full_key, bool expect_eq) {
|
||||
if (expected_json.empty()) {
|
||||
if (expect_eq) {
|
||||
ASSERT_EQ(expected_json.data(), actual_json.data())
|
||||
@ -303,14 +303,14 @@ void OidIntegration::compare_json(const bpt::ptree &expected_json,
|
||||
}
|
||||
|
||||
// Compare as Key-Value pairs
|
||||
for (const auto &[key, val] : expected_json) {
|
||||
for (const auto& [key, val] : expected_json) {
|
||||
if (key == "NOT") {
|
||||
auto curr_key = full_key + ".NOT";
|
||||
ASSERT_EQ(true, expect_eq) << "Invalid expected data: " << curr_key
|
||||
<< " - Can not use nested \"NOT\" expressions";
|
||||
if (val.empty()) {
|
||||
// Check that a given single key does not exist
|
||||
const auto &key_to_check = val.data();
|
||||
const auto& key_to_check = val.data();
|
||||
auto actual_it = actual_json.find(key_to_check);
|
||||
auto curr_key = full_key + "." + key_to_check;
|
||||
if (actual_it != actual_json.not_found()) {
|
||||
|
@ -11,14 +11,14 @@
|
||||
#include <string>
|
||||
|
||||
struct OidOpts {
|
||||
boost::asio::io_context &ctx;
|
||||
boost::asio::io_context& ctx;
|
||||
std::string targetArgs;
|
||||
std::string script;
|
||||
std::string scriptSource;
|
||||
};
|
||||
|
||||
struct Proc {
|
||||
boost::asio::io_context &ctx;
|
||||
boost::asio::io_context& ctx;
|
||||
boost::process::child proc;
|
||||
boost::process::child tee_stdout;
|
||||
boost::process::child tee_stderr;
|
||||
@ -37,8 +37,8 @@ class IntegrationBase : public ::testing::Test {
|
||||
|
||||
void TearDown() override;
|
||||
void SetUp() override;
|
||||
int exit_code(Proc &proc);
|
||||
std::filesystem::path createCustomConfig(const std::string &extra);
|
||||
int exit_code(Proc& proc);
|
||||
std::filesystem::path createCustomConfig(const std::string& extra);
|
||||
|
||||
std::filesystem::path workingDir;
|
||||
|
||||
@ -59,9 +59,9 @@ class OidIntegration : public IntegrationBase {
|
||||
* Compares two JSON objects for equality if "expect_eq" is true, or for
|
||||
* inequality if "expect_eq" is false.
|
||||
*/
|
||||
void compare_json(const boost::property_tree::ptree &expected_json,
|
||||
const boost::property_tree::ptree &actual_json,
|
||||
const std::string &full_key = "root",
|
||||
void compare_json(const boost::property_tree::ptree& expected_json,
|
||||
const boost::property_tree::ptree& actual_json,
|
||||
const std::string& full_key = "root",
|
||||
bool expect_eq = true);
|
||||
};
|
||||
|
||||
|
@ -26,7 +26,7 @@ typedef union {
|
||||
float f;
|
||||
char c;
|
||||
struct {
|
||||
int *myArray[3];
|
||||
int* myArray[3];
|
||||
float myArray2[2][2][3];
|
||||
} myStruct;
|
||||
double array[10][20];
|
||||
@ -50,20 +50,20 @@ typedef ST ST2;
|
||||
std::string bar;
|
||||
};*/
|
||||
|
||||
using Deleter1 = void (*)(int *);
|
||||
using Deleter2 = std::function<void(int *)>;
|
||||
using Deleter1 = void (*)(int*);
|
||||
using Deleter2 = std::function<void(int*)>;
|
||||
|
||||
int *create() {
|
||||
int *i = new int;
|
||||
int* create() {
|
||||
int* i = new int;
|
||||
*i = 10;
|
||||
return i;
|
||||
}
|
||||
void destroy(int *i) {
|
||||
void destroy(int* i) {
|
||||
delete i;
|
||||
}
|
||||
|
||||
struct Destroyer {
|
||||
void operator()(int *i) const {
|
||||
void operator()(int* i) const {
|
||||
delete i;
|
||||
}
|
||||
};
|
||||
@ -146,25 +146,25 @@ Foo myGlobalFoo;
|
||||
// std::unique_ptr<Foo> myGlobalFoo;
|
||||
|
||||
// pass in the loop counter in the args
|
||||
std::vector<int> doStuff(Foo &foo,
|
||||
std::vector<std::map<std::string, std::string>> &m,
|
||||
std::vector<std::string> &f,
|
||||
std::vector<std::pair<std::string, double>> &p) {
|
||||
std::vector<int> doStuff(Foo& foo,
|
||||
std::vector<std::map<std::string, std::string>>& m,
|
||||
std::vector<std::string>& f,
|
||||
std::vector<std::pair<std::string, double>>& p) {
|
||||
std::vector<int> altvect = {1, 3, 5, 7};
|
||||
foo.inc();
|
||||
foo.incN(altvect.size());
|
||||
foo.incVectSize(altvect);
|
||||
|
||||
std::cout << " doStuff entries: " << f.size() << std::endl;
|
||||
std::cout << " addr of f = " << reinterpret_cast<void *>(&f) << std::endl;
|
||||
std::cout << " addr of m = " << reinterpret_cast<void *>(&m) << std::endl;
|
||||
std::cout << " addr of p = " << reinterpret_cast<void *>(&p) << std::endl;
|
||||
std::cout << " addr of f = " << reinterpret_cast<void*>(&f) << std::endl;
|
||||
std::cout << " addr of m = " << reinterpret_cast<void*>(&m) << std::endl;
|
||||
std::cout << " addr of p = " << reinterpret_cast<void*>(&p) << std::endl;
|
||||
std::cout << " addr of myGlobalFoo = "
|
||||
<< reinterpret_cast<void *>(&myGlobalFoo) << std::endl;
|
||||
<< reinterpret_cast<void*>(&myGlobalFoo) << std::endl;
|
||||
|
||||
std::vector<int> newvect(altvect);
|
||||
|
||||
std::cout << " addr of newvect = " << reinterpret_cast<void *>(&newvect)
|
||||
std::cout << " addr of newvect = " << reinterpret_cast<void*>(&newvect)
|
||||
<< std::endl;
|
||||
|
||||
/*
|
||||
@ -179,7 +179,7 @@ std::vector<int> doStuff(Foo &foo,
|
||||
return newvect;
|
||||
}
|
||||
|
||||
void doStuff(std::vector<int> &f, int i) {
|
||||
void doStuff(std::vector<int>& f, int i) {
|
||||
f.push_back(i);
|
||||
std::cout << "Entries in f: " << f.size() << std::endl;
|
||||
}
|
||||
@ -188,9 +188,9 @@ void doNothing() {
|
||||
std::cout << "I do nothing, the function does nothing" << std::endl;
|
||||
}
|
||||
|
||||
void *doit(void *arg) {
|
||||
void* doit(void* arg) {
|
||||
doNothing();
|
||||
int *loopcnt = reinterpret_cast<int *>(arg);
|
||||
int* loopcnt = reinterpret_cast<int*>(arg);
|
||||
std::vector<std::string> f;
|
||||
f.reserve(200);
|
||||
std::vector<std::unordered_map<std::string, std::string>> mv;
|
||||
@ -277,11 +277,11 @@ void *doit(void *arg) {
|
||||
pthread_exit(arg);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
int i = 0;
|
||||
int err;
|
||||
pthread_t tid[2];
|
||||
char *b;
|
||||
char* b;
|
||||
|
||||
// facebook::initFacebook(&argc, &argv);
|
||||
|
||||
@ -323,7 +323,7 @@ int main(int argc, char *argv[]) {
|
||||
std::cout << "nameList vector addr = " << &nameList << std::endl;
|
||||
|
||||
for (int i = 0; i < 1; ++i) {
|
||||
err = pthread_create(&(tid[i]), NULL, &doit, (void **)&loopcnt);
|
||||
err = pthread_create(&(tid[i]), NULL, &doit, (void**)&loopcnt);
|
||||
|
||||
if (err != 0) {
|
||||
std::cout << "Failed to create thread:[ " << strerror(err) << " ]"
|
||||
@ -337,7 +337,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1; ++i) {
|
||||
pthread_join(tid[i], (void **)&b);
|
||||
pthread_join(tid[i], (void**)&b);
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
|
@ -77,31 +77,31 @@ Foo myGlobalFoo;
|
||||
// std::unique_ptr<Foo> myGlobalFoo;
|
||||
|
||||
// pass in the loop counter in the args
|
||||
std::vector<int> doStuff(Foo &foo,
|
||||
std::vector<std::map<std::string, std::string>> &m,
|
||||
std::vector<std::string> &f,
|
||||
std::vector<std::pair<std::string, double>> &p) {
|
||||
std::vector<int> doStuff(Foo& foo,
|
||||
std::vector<std::map<std::string, std::string>>& m,
|
||||
std::vector<std::string>& f,
|
||||
std::vector<std::pair<std::string, double>>& p) {
|
||||
std::vector<int> altvect = {1, 3, 5, 7};
|
||||
foo.inc();
|
||||
foo.incVectSize(altvect);
|
||||
myGlobalFoo.vectorOfStr.push_back(std::string("Test String"));
|
||||
|
||||
std::cout << " doStuff entries: " << f.size() << std::endl;
|
||||
std::cout << " addr of f = " << reinterpret_cast<void *>(&f) << std::endl;
|
||||
std::cout << " addr of m = " << reinterpret_cast<void *>(&m) << std::endl;
|
||||
std::cout << " addr of p = " << reinterpret_cast<void *>(&p) << std::endl;
|
||||
std::cout << " addr of f = " << reinterpret_cast<void*>(&f) << std::endl;
|
||||
std::cout << " addr of m = " << reinterpret_cast<void*>(&m) << std::endl;
|
||||
std::cout << " addr of p = " << reinterpret_cast<void*>(&p) << std::endl;
|
||||
std::cout << " addr of myGlobalFoo = "
|
||||
<< reinterpret_cast<void *>(&myGlobalFoo) << std::endl;
|
||||
<< reinterpret_cast<void*>(&myGlobalFoo) << std::endl;
|
||||
|
||||
std::vector<int> newvect(altvect);
|
||||
|
||||
std::cout << " addr of newvect = " << reinterpret_cast<void *>(&newvect)
|
||||
std::cout << " addr of newvect = " << reinterpret_cast<void*>(&newvect)
|
||||
<< std::endl;
|
||||
|
||||
return newvect;
|
||||
}
|
||||
|
||||
void doStuff(std::vector<int> &f, int i) {
|
||||
void doStuff(std::vector<int>& f, int i) {
|
||||
f.push_back(i);
|
||||
std::cout << "Entries in f: " << f.size() << std::endl;
|
||||
}
|
||||
@ -110,9 +110,9 @@ void doNothing() {
|
||||
std::cout << "I do nothing, the function does nothing" << std::endl;
|
||||
}
|
||||
|
||||
void *doit(void *arg) {
|
||||
void* doit(void* arg) {
|
||||
doNothing();
|
||||
int *loopcnt = reinterpret_cast<int *>(arg);
|
||||
int* loopcnt = reinterpret_cast<int*>(arg);
|
||||
std::vector<std::string> f;
|
||||
f.reserve(200);
|
||||
std::vector<std::unordered_map<std::string, std::string>> mv;
|
||||
@ -199,11 +199,11 @@ void *doit(void *arg) {
|
||||
pthread_exit(arg);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
int i = 0;
|
||||
int err;
|
||||
pthread_t tid[2];
|
||||
char *b;
|
||||
char* b;
|
||||
|
||||
// facebook::initFacebook(&argc, &argv);
|
||||
|
||||
@ -245,7 +245,7 @@ int main(int argc, char *argv[]) {
|
||||
std::cout << "nameList vector addr = " << &nameList << std::endl;
|
||||
|
||||
for (int i = 0; i < 1; ++i) {
|
||||
err = pthread_create(&(tid[i]), NULL, &doit, (void **)&loopcnt);
|
||||
err = pthread_create(&(tid[i]), NULL, &doit, (void**)&loopcnt);
|
||||
|
||||
if (err != 0) {
|
||||
std::cout << "Failed to create thread:[ " << strerror(err) << " ]"
|
||||
@ -259,7 +259,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1; ++i) {
|
||||
pthread_join(tid[i], (void **)&b);
|
||||
pthread_join(tid[i], (void**)&b);
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
|
@ -12,13 +12,13 @@ struct OIDTestingTwoString {
|
||||
};
|
||||
|
||||
struct customTwoStringEq {
|
||||
bool operator()(const OIDTestingTwoString &a, const OIDTestingTwoString &b) {
|
||||
bool operator()(const OIDTestingTwoString& a, const OIDTestingTwoString& b) {
|
||||
return (a.first == a.first && a.second == b.second);
|
||||
}
|
||||
};
|
||||
|
||||
struct customHash {
|
||||
std::size_t operator()(const OIDTestingTwoString &two) const {
|
||||
std::size_t operator()(const OIDTestingTwoString& two) const {
|
||||
return ((std::hash<std::string>()(two.first) ^
|
||||
(std::hash<std::string>()(two.second))));
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ TEST(CompilerTest, CompileAndRelocate) {
|
||||
)";
|
||||
|
||||
auto tmpdir = fs::temp_directory_path() / "test-XXXXXX";
|
||||
EXPECT_NE(mkdtemp(const_cast<char *>(tmpdir.c_str())), nullptr);
|
||||
EXPECT_NE(mkdtemp(const_cast<char*>(tmpdir.c_str())), nullptr);
|
||||
|
||||
auto sourcePath = tmpdir / "src.cpp";
|
||||
auto objectPath = tmpdir / "obj.o";
|
||||
@ -48,7 +48,7 @@ TEST(CompilerTest, CompileAndRelocate) {
|
||||
EXPECT_TRUE(compiler.compile(code, sourcePath, objectPath));
|
||||
|
||||
const size_t relocSlabSize = 4096;
|
||||
void *relocSlab =
|
||||
void* relocSlab =
|
||||
mmap(nullptr, relocSlabSize, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
EXPECT_NE(relocSlab, nullptr);
|
||||
@ -57,20 +57,20 @@ TEST(CompilerTest, CompileAndRelocate) {
|
||||
compiler.applyRelocs((uintptr_t)relocSlab, {objectPath}, {});
|
||||
EXPECT_TRUE(relocResult.has_value());
|
||||
|
||||
auto &[_, segs, jitSymbols] = relocResult.value();
|
||||
auto& [_, segs, jitSymbols] = relocResult.value();
|
||||
|
||||
EXPECT_EQ(segs.size(), 1);
|
||||
EXPECT_EQ(jitSymbols.size(), 3); // 2 functions + 1 static array
|
||||
|
||||
{
|
||||
const auto &lastSeg = segs.back();
|
||||
const auto& lastSeg = segs.back();
|
||||
auto lastSegLimit = lastSeg.RelocAddr + lastSeg.Size;
|
||||
auto relocLimit = (uintptr_t)relocSlab + relocSlabSize;
|
||||
EXPECT_LE(lastSegLimit, relocLimit);
|
||||
}
|
||||
|
||||
for (const auto &[Base, Reloc, Size] : segs)
|
||||
std::memcpy((void *)Reloc, (void *)Base, Size);
|
||||
for (const auto& [Base, Reloc, Size] : segs)
|
||||
std::memcpy((void*)Reloc, (void*)Base, Size);
|
||||
|
||||
{
|
||||
auto symAddr = jitSymbols.at("constant");
|
||||
@ -113,7 +113,7 @@ TEST(CompilerTest, CompileAndRelocateMultipleObjs) {
|
||||
)";
|
||||
|
||||
auto tmpdir = fs::temp_directory_path() / "test-XXXXXX";
|
||||
EXPECT_NE(mkdtemp(const_cast<char *>(tmpdir.c_str())), nullptr);
|
||||
EXPECT_NE(mkdtemp(const_cast<char*>(tmpdir.c_str())), nullptr);
|
||||
|
||||
auto sourceXPath = tmpdir / "srcX.cpp";
|
||||
auto objectXPath = tmpdir / "objX.o";
|
||||
@ -126,7 +126,7 @@ TEST(CompilerTest, CompileAndRelocateMultipleObjs) {
|
||||
EXPECT_TRUE(compiler.compile(codeY, sourceYPath, objectYPath));
|
||||
|
||||
const size_t relocSlabSize = 8192;
|
||||
void *relocSlab =
|
||||
void* relocSlab =
|
||||
mmap(nullptr, relocSlabSize, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
EXPECT_NE(relocSlab, nullptr);
|
||||
@ -135,20 +135,20 @@ TEST(CompilerTest, CompileAndRelocateMultipleObjs) {
|
||||
{objectXPath, objectYPath}, {});
|
||||
EXPECT_TRUE(relocResult.has_value());
|
||||
|
||||
auto &[_, segs, jitSymbols] = relocResult.value();
|
||||
auto& [_, segs, jitSymbols] = relocResult.value();
|
||||
|
||||
EXPECT_EQ(segs.size(), 2);
|
||||
EXPECT_EQ(jitSymbols.size(), 4); // 2 functions + 2 static array
|
||||
|
||||
{
|
||||
const auto &lastSeg = segs.back();
|
||||
const auto& lastSeg = segs.back();
|
||||
auto lastSegLimit = lastSeg.RelocAddr + lastSeg.Size;
|
||||
auto relocLimit = (uintptr_t)relocSlab + relocSlabSize;
|
||||
EXPECT_LE(lastSegLimit, relocLimit);
|
||||
}
|
||||
|
||||
for (const auto &[Base, Reloc, Size] : segs)
|
||||
std::memcpy((void *)Reloc, (void *)Base, Size);
|
||||
for (const auto& [Base, Reloc, Size] : segs)
|
||||
std::memcpy((void*)Reloc, (void*)Base, Size);
|
||||
|
||||
{
|
||||
auto symAddr = jitSymbols.at("sumXs");
|
||||
|
@ -12,7 +12,7 @@ using ::testing::HasSubstr;
|
||||
using namespace ObjectIntrospection;
|
||||
|
||||
// Utilities
|
||||
static ParseData parseString(const std::string &script) {
|
||||
static ParseData parseString(const std::string& script) {
|
||||
ParseData pdata;
|
||||
std::istringstream input{script};
|
||||
OIScanner scanner{&input};
|
||||
@ -23,7 +23,7 @@ static ParseData parseString(const std::string &script) {
|
||||
return pdata;
|
||||
}
|
||||
|
||||
static std::string parseBadString(const std::string &script) {
|
||||
static std::string parseBadString(const std::string& script) {
|
||||
ParseData pdata;
|
||||
std::istringstream input{script};
|
||||
OIScanner scanner{&input};
|
||||
@ -34,9 +34,9 @@ static std::string parseBadString(const std::string &script) {
|
||||
return testing::internal::GetCapturedStderr();
|
||||
}
|
||||
|
||||
static void EXPECT_REQ_EQ(const prequest &req, const std::string &type,
|
||||
const std::string &func,
|
||||
const std::vector<std::string> &args) {
|
||||
static void EXPECT_REQ_EQ(const prequest& req, const std::string& type,
|
||||
const std::string& func,
|
||||
const std::vector<std::string>& args) {
|
||||
EXPECT_EQ(req.type, type);
|
||||
EXPECT_EQ(req.func, func);
|
||||
EXPECT_EQ(req.args, args);
|
||||
|
@ -44,7 +44,7 @@ constexpr static OIOpts opts{
|
||||
"(in addition to the default RocksDB output)"},
|
||||
};
|
||||
|
||||
static void usage(std::ostream &out) {
|
||||
static void usage(std::ostream& out) {
|
||||
out << "Run TreeBuilder on the given data-segment dump.\n";
|
||||
out << "oitb aims to facilitate debugging issues from TreeBuilder, by "
|
||||
"allowing local iterations and debugging.\n";
|
||||
@ -59,7 +59,7 @@ static void usage(std::ostream &out) {
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
[[noreturn]] static void fatal_error(Args &&...args) {
|
||||
[[noreturn]] static void fatal_error(Args&&... args) {
|
||||
std::cerr << "error: ";
|
||||
(std::cerr << ... << args);
|
||||
std::cerr << "\n\n";
|
||||
@ -107,15 +107,15 @@ static auto loadDatasegDump(fs::path datasegDumpPath) {
|
||||
|
||||
{ /* Read the dump into the dataseg vector */
|
||||
auto datasegBytes = std::as_writable_bytes(std::span{dataseg});
|
||||
dump.read((char *)datasegBytes.data(), datasegBytes.size_bytes());
|
||||
dump.read((char*)datasegBytes.data(), datasegBytes.size_bytes());
|
||||
}
|
||||
|
||||
return dataseg;
|
||||
}
|
||||
|
||||
[[maybe_unused]] /* For debugging... */
|
||||
static std::ostream &
|
||||
operator<<(std::ostream &out, TreeBuilder::Config tbc) {
|
||||
static std::ostream&
|
||||
operator<<(std::ostream& out, TreeBuilder::Config tbc) {
|
||||
out << "TreeBuilde::Config = [";
|
||||
out << "\n logAllStructs = " << tbc.logAllStructs;
|
||||
out << "\n chaseRawPointers = " << tbc.chaseRawPointers;
|
||||
@ -126,7 +126,7 @@ operator<<(std::ostream &out, TreeBuilder::Config tbc) {
|
||||
return out;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
google::InitGoogleLogging(*argv);
|
||||
google::LogToStderr();
|
||||
google::SetStderrLogging(google::INFO);
|
||||
|
Loading…
Reference in New Issue
Block a user