From 8956ca5522b9ddacb9c1a90356d2daddb51d6e68 Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Thu, 2 Feb 2023 11:15:11 +0000 Subject: [PATCH] oil: switch to using an impl function with no default implementation (#46) --- include/ObjectIntrospection.h | 30 +++++++---- src/DrgnUtils.cpp | 23 +++++++++ src/DrgnUtils.h | 15 +++++- src/OIGenerator.cpp | 95 ++++++++++++++++++++++++----------- src/OIGenerator.h | 4 ++ 5 files changed, 125 insertions(+), 42 deletions(-) diff --git a/include/ObjectIntrospection.h b/include/ObjectIntrospection.h index 58cd4647..54b790b8 100644 --- a/include/ObjectIntrospection.h +++ b/include/ObjectIntrospection.h @@ -111,7 +111,7 @@ class OILibrary { OILibrary(void *TemplateFunc, options opt); ~OILibrary(); int init(); - int getObjectSize(void *ObjectAddr, size_t &size); + int getObjectSize(void *objectAddr, size_t &size); options opts; @@ -141,17 +141,17 @@ class CodegenHandler { delete lib; } - static int getObjectSize(const T &ObjectAddr, size_t &ObjectSize) { + 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, + static int getObjectSize(const T &objectAddr, size_t &objectSize, const options &opts, bool checkOptions = true) { OILibrary *lib; if (int responseCode = getLibrary(lib, opts, checkOptions); @@ -159,7 +159,7 @@ class CodegenHandler { return responseCode; } - return lib->getObjectSize((void *)&ObjectAddr, ObjectSize); + return lib->getObjectSize((void *)&objectAddr, objectSize); } private: @@ -230,12 +230,18 @@ class CodegenHandler { * Ahead-Of-Time (AOT) compilation. */ template -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::getObjectSize(ObjectAddr, ObjectSize, opts, + return CodegenHandler::getObjectSize(objectAddr, objectSize, opts, checkOptions); } +#else + +template +int __attribute__((weak)) +getObjectSizeImpl(const T &objectAddr, size_t &objectSize); + #endif /* @@ -248,12 +254,14 @@ int getObjectSize(const T &ObjectAddr, size_t &ObjectSize, const options &opts, * production system. */ template -int __attribute__((weak)) -getObjectSize(const T &ObjectAddr, size_t &ObjectSize) { +int getObjectSize(const T &objectAddr, size_t &objectSize) { #ifdef OIL_AOT_COMPILATION - return Response::OIL_UNINITIALISED; + if (!getObjectSizeImpl) { + return Response::OIL_UNINITIALISED; + } + return getObjectSizeImpl(objectAddr, objectSize); #else - return CodegenHandler::getObjectSize(ObjectAddr, ObjectSize); + return CodegenHandler::getObjectSize(objectAddr, objectSize); #endif } diff --git a/src/DrgnUtils.cpp b/src/DrgnUtils.cpp index 0562897c..0bd02524 100644 --- a/src/DrgnUtils.cpp +++ b/src/DrgnUtils.cpp @@ -69,4 +69,27 @@ func_iterator& func_iterator::operator++() { return *this; } +void SymbolsDeleter::operator()(std::span* syms) noexcept { + drgn_symbols_destroy(syms->data(), syms->size()); + delete syms; +} + +symbols program::find_symbols_by_name(const char* name) { + drgn_symbol** syms; + size_t count; + + if (error err( + drgn_program_find_symbols_by_name(ptr.get(), nullptr, &syms, &count)); + err) { + throw err; + } + + return std::unique_ptr, SymbolsDeleter>( + new std::span(syms, count)); +} + +const char* symbol::name(drgn_symbol* sym) { + return drgn_symbol_name(sym); +} + } // namespace drgnplusplus diff --git a/src/DrgnUtils.h b/src/DrgnUtils.h index 001253d4..ad2ba450 100644 --- a/src/DrgnUtils.h +++ b/src/DrgnUtils.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -26,9 +27,10 @@ extern "C" { // Declare drgn structs and only refer to them by pointers to avoid exposing // drgn.h. struct drgn_error; -struct drgn_program; struct drgn_func_iterator; +struct drgn_program; struct drgn_qualified_type; +struct drgn_symbol; } namespace drgnplusplus { @@ -50,6 +52,11 @@ class error : public std::exception { std::unique_ptr ptr; }; +struct SymbolsDeleter { + void operator()(std::span*) noexcept; +}; +using symbols = std::unique_ptr, SymbolsDeleter>; + class program { public: struct Deleter { @@ -59,6 +66,8 @@ class program { program(); program(drgn_program* prog) : ptr(prog){}; + symbols find_symbols_by_name(const char* name); + drgn_program* get() { return ptr.get(); } @@ -111,4 +120,8 @@ class func_iterator { pointer current = nullptr; }; +namespace symbol { +const char* name(drgn_symbol*); +} + } // namespace drgnplusplus diff --git a/src/OIGenerator.cpp b/src/OIGenerator.cpp index 3f98d288..97ce78f0 100644 --- a/src/OIGenerator.cpp +++ b/src/OIGenerator.cpp @@ -18,7 +18,9 @@ #include +#include #include +#include #include #include "DrgnUtils.h" @@ -26,32 +28,77 @@ namespace ObjectIntrospection { +std::unordered_map +OIGenerator::oilStrongToWeakSymbolsMap(drgnplusplus::program& prog) { + static constexpr std::string_view strongSymbolPrefix = + "int ObjectIntrospection::getObjectSize<"; + static constexpr std::string_view weakSymbolPrefix = + "int ObjectIntrospection::getObjectSizeImpl<"; + + std::unordered_map> + templateArgsToSymbolsMap; + + auto symbols = prog.find_symbols_by_name(nullptr); + for (drgn_symbol* sym : *symbols) { + auto symName = drgnplusplus::symbol::name(sym); + auto demangled = boost::core::demangle(symName); + + if (demangled.starts_with(strongSymbolPrefix)) { + auto& matchedSyms = templateArgsToSymbolsMap[demangled.substr( + strongSymbolPrefix.length())]; + if (!matchedSyms.first.empty()) { + LOG(WARNING) << "non-unique symbols found: `" << matchedSyms.first + << "` and `" << symName << "`"; + } + matchedSyms.first = symName; + } else if (demangled.starts_with(weakSymbolPrefix)) { + auto& matchedSyms = + templateArgsToSymbolsMap[demangled.substr(weakSymbolPrefix.length())]; + if (!matchedSyms.second.empty()) { + LOG(WARNING) << "non-unique symbols found: `" << matchedSyms.first + << "` and `" << symName << "`"; + } + matchedSyms.second = symName; + } + } + + std::unordered_map strongToWeakSymbols; + for (auto& [_, val] : templateArgsToSymbolsMap) { + if (val.first.empty() || val.second.empty()) { + continue; + } + strongToWeakSymbols[std::move(val.first)] = std::move(val.second); + } + + return strongToWeakSymbols; +} + std::vector> OIGenerator::findOilTypesAndNames(drgnplusplus::program& prog) { + auto strongToWeakSymbols = oilStrongToWeakSymbolsMap(prog); + std::vector> out; + // TODO: Clean up this loop when switching to + // drgn_program_find_function_by_address. for (auto& func : drgnplusplus::func_iterator(prog)) { - std::string fqdn; + std::string strongLinkageName; { - char* fqdnChars; - size_t fqdnLen; - if (drgnplusplus::error err( - drgn_type_fully_qualified_name(func.type, &fqdnChars, &fqdnLen)); - err) { - LOG(ERROR) << "error getting drgn type fully qualified name: " << err; - throw err; + char* linkageNameCstr; + if (auto err = drgnplusplus::error( + drgn_type_linkage_name(func.type, &linkageNameCstr))) { + // throw err; + continue; } - fqdn = std::string(fqdnChars, fqdnLen); + strongLinkageName = linkageNameCstr; } - if (!fqdn.starts_with("ObjectIntrospection::getObjectSize<")) { - continue; - } - if (drgn_type_num_parameters(func.type) != 2) { - continue; - } - if (drgn_type_num_template_parameters(func.type) != 1) { - continue; + std::string weakLinkageName; + if (auto search = strongToWeakSymbols.find(strongLinkageName); + search != strongToWeakSymbols.end()) { + weakLinkageName = search->second; + } else { + continue; // not an oil strong symbol } auto templateParameters = drgn_type_template_parameters(func.type); @@ -65,19 +112,7 @@ OIGenerator::findOilTypesAndNames(drgnplusplus::program& prog) { } LOG(INFO) << "found OIL type: " << drgn_type_name(paramType.type); - - std::string linkageName; - { - char* linkageNameCstr; - if (auto err = drgnplusplus::error( - drgn_type_linkage_name(func.type, &linkageNameCstr))) { - throw err; - } - linkageName = linkageNameCstr; - } - - LOG(INFO) << "found linkage name: " << linkageName; - out.push_back({paramType, linkageName}); + out.push_back({paramType, std::move(weakLinkageName)}); } return out; diff --git a/src/OIGenerator.h b/src/OIGenerator.h index ea437a23..6b040ee1 100644 --- a/src/OIGenerator.h +++ b/src/OIGenerator.h @@ -45,8 +45,12 @@ class OIGenerator { fs::path configFilePath; fs::path sourceFileDumpPath; + std::unordered_map oilStrongToWeakSymbolsMap( + drgnplusplus::program& prog); + std::vector> findOilTypesAndNames(drgnplusplus::program& prog); + bool generateForType(const OICodeGen::Config& generatorConfig, const OICompiler::Config& compilerConfig, const drgn_qualified_type& type,