Skip to content

Commit 3ffc18a

Browse files
photoszztnyh
authored andcommitted
Lookup symbol deeper
dlsym function doesn't seem to lookup symbol deep enough. This patch includes a bfs version of collect dependencies. It fixes test_dlsym_from_sofile_with_preload and dlsym_with_dependencies. Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com> Signed-off-by: Zhiting Zhu <zhitingz@cs.utexas.edu> Message-Id: <20200120011727.1736-1-zhitingz@cs.utexas.edu>
1 parent 8c8e0b3 commit 3ffc18a

File tree

4 files changed

+43
-2
lines changed

4 files changed

+43
-2
lines changed

core/elf.cc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <sys/utsname.h>
2828
#include <osv/demangle.hh>
2929
#include <boost/version.hpp>
30+
#include <deque>
3031

3132
#include "arch.hh"
3233

@@ -950,6 +951,22 @@ Elf64_Sym* object::lookup_symbol(const char* name, bool self_lookup)
950951
return sym;
951952
}
952953

954+
symbol_module object::lookup_symbol_deep(const char* name)
955+
{
956+
symbol_module sym = { lookup_symbol(name, false), this };
957+
if (!sym.symbol) {
958+
auto deps = this->collect_dependencies_bfs();
959+
for (auto&& _obj : deps) {
960+
auto symbol = _obj->lookup_symbol(name, false);
961+
if (symbol) {
962+
sym = { symbol, _obj };
963+
break;
964+
}
965+
}
966+
}
967+
return sym;
968+
}
969+
953970
unsigned object::symtab_len()
954971
{
955972
if (dynamic_exists(DT_HASH)) {
@@ -1089,6 +1106,28 @@ void object::collect_dependencies(std::unordered_set<elf::object*>& ds)
10891106
}
10901107
}
10911108

1109+
std::deque<elf::object*> object::collect_dependencies_bfs()
1110+
{
1111+
std::unordered_set<object*> deps_set;
1112+
std::deque<object*> operate_queue;
1113+
std::deque<object*> deps;
1114+
operate_queue.push_back(this);
1115+
deps_set.insert(this);
1116+
1117+
while (!operate_queue.empty()) {
1118+
object* obj = operate_queue.front();
1119+
operate_queue.pop_front();
1120+
deps.push_back(obj);
1121+
for (auto&& d : obj->_needed) {
1122+
if (!deps_set.count(d.get())) {
1123+
deps_set.insert(d.get());
1124+
operate_queue.push_back(d.get());
1125+
}
1126+
}
1127+
}
1128+
return deps;
1129+
}
1130+
10921131
std::string object::soname()
10931132
{
10941133
return dynamic_exists(DT_SONAME) ? dynamic_str(DT_SONAME) : std::string();

include/osv/elf.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ public:
347347
void* base() const;
348348
void* end() const;
349349
Elf64_Sym* lookup_symbol(const char* name, bool self_lookup);
350+
symbol_module lookup_symbol_deep(const char* name);
350351
void load_segments();
351352
void process_headers();
352353
void unload_segments();
@@ -405,6 +406,7 @@ private:
405406
void relocate_pltgot();
406407
unsigned symtab_len();
407408
void collect_dependencies(std::unordered_set<elf::object*>& ds);
409+
std::deque<elf::object*> collect_dependencies_bfs();
408410
void prepare_initial_tls(void* buffer, size_t size, std::vector<ptrdiff_t>& offsets);
409411
void prepare_local_tls(std::vector<ptrdiff_t>& offsets);
410412
void alloc_static_tls();

libc/dlfcn.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ void* dlsym(void* handle, const char* name)
7474
abort();
7575
} else {
7676
auto obj = *reinterpret_cast<std::shared_ptr<elf::object>*>(handle);
77-
sym = { obj->lookup_symbol(name, false), obj.get() };
77+
sym = obj->lookup_symbol_deep(name);
7878
}
7979
if (!sym.obj || !sym.symbol) {
8080
dlerror_fmt("dlsym: symbol %s not found", name);

tests/tst-dlfcn.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
namespace utf = boost::unit_test;
1414

1515
const bool rtld_next = false;
16-
const bool deep_lookup = false;
16+
const bool deep_lookup = true;
1717

1818
static bool called = false;
1919
extern "C" void DlSymTestFunction()

0 commit comments

Comments
 (0)