#include "getResource.h" #include "unaligned.h" #include #include #include std::string_view getResource(std::string_view name) { // Convert the resource file name into the form generated by `ld -r -b binary`. std::string name_replaced(name); std::replace(name_replaced.begin(), name_replaced.end(), '/', '_'); std::replace(name_replaced.begin(), name_replaced.end(), '-', '_'); std::replace(name_replaced.begin(), name_replaced.end(), '.', '_'); boost::replace_all(name_replaced, "+", "_PLUS_"); // In most `dlsym(3)` APIs, one passes the symbol name as it appears via // something like `nm` or `objdump -t`. For example, a symbol `_foo` would be // looked up with the string `"_foo"`. // // Apple's linker is confusingly different. The NOTES on the man page for // `dlsym(3)` claim that one looks up the symbol with "the name used in C // source code". In this example, that would mean using the string `"foo"`. // This apparently applies even in the case where the symbol did not originate // from C source, such as the embedded binary resource files used here. So // the symbol name must not have a leading `_` on Apple platforms. It's not // clear how this applies to other symbols, such as those which _have_ a leading // underscore in them by design, many leading underscores, etc. #if defined OS_DARWIN std::string prefix = "binary_"; #else std::string prefix = "_binary_"; #endif std::string symbol_name_start = prefix + name_replaced + "_start"; std::string symbol_name_end = prefix + name_replaced + "_end"; const char* sym_start = reinterpret_cast(dlsym(RTLD_DEFAULT, symbol_name_start.c_str())); const char* sym_end = reinterpret_cast(dlsym(RTLD_DEFAULT, symbol_name_end.c_str())); if (sym_start && sym_end) { auto resource_size = static_cast(std::distance(sym_start, sym_end)); return { sym_start, resource_size }; } return {}; }