mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-15 10:52:30 +00:00
46 lines
2.0 KiB
C++
46 lines
2.0 KiB
C++
#include "getResource.h"
|
|
#include "unaligned.h"
|
|
#include <dlfcn.h>
|
|
#include <string>
|
|
#include <boost/algorithm/string/replace.hpp>
|
|
|
|
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<const char*>(dlsym(RTLD_DEFAULT, symbol_name_start.c_str()));
|
|
const char* sym_end = reinterpret_cast<const char*>(dlsym(RTLD_DEFAULT, symbol_name_end.c_str()));
|
|
|
|
if (sym_start && sym_end)
|
|
{
|
|
auto resource_size = static_cast<size_t>(std::distance(sym_start, sym_end));
|
|
return { sym_start, resource_size };
|
|
}
|
|
return {};
|
|
}
|