oil: switch to using an impl function with no default implementation (#46)

This commit is contained in:
Jake Hillion 2023-02-02 11:15:11 +00:00 committed by GitHub
parent 6f786b4348
commit 8956ca5522
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 125 additions and 42 deletions

View File

@ -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 <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,
return CodegenHandler<T>::getObjectSize(objectAddr, objectSize, opts,
checkOptions);
}
#else
template <class T>
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 <class T>
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<T>) {
return Response::OIL_UNINITIALISED;
}
return getObjectSizeImpl(objectAddr, objectSize);
#else
return CodegenHandler<T>::getObjectSize(ObjectAddr, ObjectSize);
return CodegenHandler<T>::getObjectSize(objectAddr, objectSize);
#endif
}

View File

@ -69,4 +69,27 @@ func_iterator& func_iterator::operator++() {
return *this;
}
void SymbolsDeleter::operator()(std::span<drgn_symbol*>* 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<std::span<drgn_symbol*>, SymbolsDeleter>(
new std::span(syms, count));
}
const char* symbol::name(drgn_symbol* sym) {
return drgn_symbol_name(sym);
}
} // namespace drgnplusplus

View File

@ -19,6 +19,7 @@
#include <exception>
#include <iterator>
#include <memory>
#include <span>
#include <sstream>
#include <variant>
@ -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<drgn_error, Deleter> ptr;
};
struct SymbolsDeleter {
void operator()(std::span<drgn_symbol*>*) noexcept;
};
using symbols = std::unique_ptr<std::span<drgn_symbol*>, 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

View File

@ -18,7 +18,9 @@
#include <glog/logging.h>
#include <boost/core/demangle.hpp>
#include <fstream>
#include <unordered_map>
#include <variant>
#include "DrgnUtils.h"
@ -26,32 +28,77 @@
namespace ObjectIntrospection {
std::unordered_map<std::string, std::string>
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<std::string, std::pair<std::string, std::string>>
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<std::string, std::string> 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<std::tuple<drgn_qualified_type, std::string>>
OIGenerator::findOilTypesAndNames(drgnplusplus::program& prog) {
auto strongToWeakSymbols = oilStrongToWeakSymbolsMap(prog);
std::vector<std::tuple<drgn_qualified_type, std::string>> 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;

View File

@ -45,8 +45,12 @@ class OIGenerator {
fs::path configFilePath;
fs::path sourceFileDumpPath;
std::unordered_map<std::string, std::string> oilStrongToWeakSymbolsMap(
drgnplusplus::program& prog);
std::vector<std::tuple<drgn_qualified_type, std::string>>
findOilTypesAndNames(drgnplusplus::program& prog);
bool generateForType(const OICodeGen::Config& generatorConfig,
const OICompiler::Config& compilerConfig,
const drgn_qualified_type& type,