|
@@ -54,6 +54,7 @@ static bool s_do_breakpoint_trap_before_entry { false };
|
|
static Result<void, DlErrorMessage> __dlclose(void* handle);
|
|
static Result<void, DlErrorMessage> __dlclose(void* handle);
|
|
static Result<void*, DlErrorMessage> __dlopen(const char* filename, int flags);
|
|
static Result<void*, DlErrorMessage> __dlopen(const char* filename, int flags);
|
|
static Result<void*, DlErrorMessage> __dlsym(void* handle, const char* symbol_name);
|
|
static Result<void*, DlErrorMessage> __dlsym(void* handle, const char* symbol_name);
|
|
|
|
+static Result<void, DlErrorMessage> __dladdr(void* addr, Dl_info* info);
|
|
|
|
|
|
Optional<DynamicObject::SymbolLookupResult> DynamicLinker::lookup_global_symbol(const StringView& name)
|
|
Optional<DynamicObject::SymbolLookupResult> DynamicLinker::lookup_global_symbol(const StringView& name)
|
|
{
|
|
{
|
|
@@ -237,6 +238,10 @@ static void initialize_libc(DynamicObject& libc)
|
|
VERIFY(res.has_value());
|
|
VERIFY(res.has_value());
|
|
*((DlSymFunction*)res.value().address.as_ptr()) = __dlsym;
|
|
*((DlSymFunction*)res.value().address.as_ptr()) = __dlsym;
|
|
|
|
|
|
|
|
+ res = libc.lookup_symbol("__dladdr"sv);
|
|
|
|
+ VERIFY(res.has_value());
|
|
|
|
+ *((DlAddrFunction*)res.value().address.as_ptr()) = __dladdr;
|
|
|
|
+
|
|
res = libc.lookup_symbol("__libc_init"sv);
|
|
res = libc.lookup_symbol("__libc_init"sv);
|
|
VERIFY(res.has_value());
|
|
VERIFY(res.has_value());
|
|
typedef void libc_init_func();
|
|
typedef void libc_init_func();
|
|
@@ -430,6 +435,48 @@ static Result<void*, DlErrorMessage> __dlsym(void* handle, const char* symbol_na
|
|
return symbol.value().address.as_ptr();
|
|
return symbol.value().address.as_ptr();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static Result<void, DlErrorMessage> __dladdr(void* addr, Dl_info* info)
|
|
|
|
+{
|
|
|
|
+ VirtualAddress user_addr { addr };
|
|
|
|
+ __pthread_mutex_lock(&s_loader_lock);
|
|
|
|
+ ScopeGuard unlock_guard = [] { __pthread_mutex_unlock(&s_loader_lock); };
|
|
|
|
+
|
|
|
|
+ RefPtr<DynamicObject> best_matching_library;
|
|
|
|
+ VirtualAddress best_library_offset;
|
|
|
|
+ for (auto& lib : s_global_objects) {
|
|
|
|
+ if (user_addr < lib.value->base_address())
|
|
|
|
+ continue;
|
|
|
|
+ auto offset = user_addr - lib.value->base_address();
|
|
|
|
+ if (!best_matching_library || offset < best_library_offset) {
|
|
|
|
+ best_matching_library = lib.value;
|
|
|
|
+ best_library_offset = offset;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!best_matching_library) {
|
|
|
|
+ return DlErrorMessage { "No library found which contains the specified address" };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Optional<DynamicObject::Symbol> best_matching_symbol;
|
|
|
|
+ best_matching_library->for_each_symbol([&](auto const& symbol) {
|
|
|
|
+ if (user_addr < symbol.address() || user_addr > symbol.address().offset(symbol.size()))
|
|
|
|
+ return;
|
|
|
|
+ best_matching_symbol = symbol;
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ info->dli_fbase = best_matching_library->base_address().as_ptr();
|
|
|
|
+ // This works because we don't support unloading objects.
|
|
|
|
+ info->dli_fname = best_matching_library->filename().characters();
|
|
|
|
+ if (best_matching_symbol.has_value()) {
|
|
|
|
+ info->dli_saddr = best_matching_symbol.value().address().as_ptr();
|
|
|
|
+ info->dli_sname = best_matching_symbol.value().raw_name();
|
|
|
|
+ } else {
|
|
|
|
+ info->dli_saddr = nullptr;
|
|
|
|
+ info->dli_sname = nullptr;
|
|
|
|
+ }
|
|
|
|
+ return {};
|
|
|
|
+}
|
|
|
|
+
|
|
static void read_environment_variables()
|
|
static void read_environment_variables()
|
|
{
|
|
{
|
|
for (char** env = s_envp; *env; ++env) {
|
|
for (char** env = s_envp; *env; ++env) {
|