summaryrefslogtreecommitdiff
path: root/linker/linker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r--linker/linker.cpp11
1 files changed, 11 insertions, 0 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 531cd1908..1382a9cdc 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -948,6 +948,17 @@ static const ElfW(Sym)* dlsym_handle_lookup(soinfo* root, soinfo* skip_until,
// This is used by dlsym(3). It performs symbol lookup only within the
// specified soinfo object and its dependencies in breadth first order.
const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name) {
+ // According to man dlopen(3) and posix docs in the case when si is handle
+ // of the main executable we need to search not only in the executable and its
+ // dependencies but also in all libraries loaded with RTLD_GLOBAL.
+ //
+ // Since RTLD_GLOBAL is always set for the main executable and all dt_needed shared
+ // libraries and they are loaded in breath-first (correct) order we can just execute
+ // dlsym(RTLD_DEFAULT, ...); instead of doing two stage lookup.
+ if (si == somain) {
+ return dlsym_linear_lookup(name, found, nullptr, RTLD_DEFAULT);
+ }
+
SymbolName symbol_name(name);
return dlsym_handle_lookup(si, nullptr, found, symbol_name);
}