Signed-off-by: Zhiting Zhu <zhiti...@cs.utexas.edu> --- core/elf.cc | 33 +++++++++++++++++++++++++++++++++ include/osv/elf.hh | 1 + libc/dlfcn.cc | 4 ++-- tests/tst-dlfcn.cc | 2 +- 4 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/core/elf.cc b/core/elf.cc index 882b4d49..badbb7b0 100644 --- a/core/elf.cc +++ b/core/elf.cc @@ -41,6 +41,7 @@ TRACEPOINT(trace_elf_load, "%s", const char *); TRACEPOINT(trace_elf_unload, "%s", const char *); TRACEPOINT(trace_elf_lookup, "%s", const char *); +TRACEPOINT(trace_elf_lookup_next, "%s", const char *); TRACEPOINT(trace_elf_lookup_addr, "%p", const void *); extern void* elf_start; @@ -1496,6 +1497,38 @@ symbol_module program::lookup(const char* name) return ret; } +symbol_module program::lookup_next(const char* name, const void* retaddr) +{ + trace_elf_lookup_next(name); + symbol_module ret(nullptr,nullptr); + if (retaddr == nullptr) { + return ret; + } + with_modules([&](const elf::program::modules_list &ml) + { + auto start = ml.objects.begin(); + for (auto it = ml.objects.begin(), end = ml.objects.end(); it != end; ++it) { + auto module = *it; + if (module->contains_addr(retaddr)) { + start = it; + break; + } + } + if (start == ml.objects.begin()) { + return; + } + start = ++start; + for (auto it = start, end = ml.objects.end(); it != end; ++it) { + auto module = *it; + if (auto sym = module->lookup_symbol(name)) { + ret = symbol_module(sym, module); + break; + } + } + }); + return ret; +} + void* program::do_lookup_function(const char* name) { auto sym = lookup(name); diff --git a/include/osv/elf.hh b/include/osv/elf.hh index ededb75a..247d9c58 100644 --- a/include/osv/elf.hh +++ b/include/osv/elf.hh @@ -576,6 +576,7 @@ public: void set_search_path(std::initializer_list<std::string> path); symbol_module lookup(const char* symbol); + symbol_module lookup_next(const char* name, const void* retaddr); template <typename T> T* lookup_function(const char* symbol); diff --git a/libc/dlfcn.cc b/libc/dlfcn.cc index 1cad7ffd..3d228bbf 100644 --- a/libc/dlfcn.cc +++ b/libc/dlfcn.cc @@ -70,8 +70,8 @@ void* dlsym(void* handle, const char* name) if ((program == handle) || (handle == RTLD_DEFAULT)) { sym = program->lookup(name); } else if (handle == RTLD_NEXT) { - // FIXME: implement - abort(); + auto retaddr = __builtin_extract_return_addr(__builtin_return_address(0)); + sym = program->lookup_next(name, retaddr); } else { auto obj = *reinterpret_cast<std::shared_ptr<elf::object>*>(handle); sym = obj->lookup_symbol_deep(name); diff --git a/tests/tst-dlfcn.cc b/tests/tst-dlfcn.cc index 6d91fb93..6188236f 100644 --- a/tests/tst-dlfcn.cc +++ b/tests/tst-dlfcn.cc @@ -12,7 +12,7 @@ #include <boost/test/unit_test.hpp> namespace utf = boost::unit_test; -const bool rtld_next = false; +const bool rtld_next = true; const bool deep_lookup = true; static bool called = false; -- 2.17.1 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to osv-dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20200113181034.11368-1-zhitingz%40cs.utexas.edu.