Signed-off-by: Zhiting Zhu <[email protected]>
---
 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 26a25c43..69dbd7ed 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;
@@ -1532,6 +1533,38 @@ symbol_module program::lookup(const char* name, object* 
seeker)
     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.end();
+        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.end()) {
+            return;
+        }
+        start = ++start;
+        for (auto it = start, end = ml.objects.end(); it != end; ++it) {
+            auto module = *it;
+            if (auto sym = module->lookup_symbol(name, false)) {
+                ret = symbol_module(sym, module);
+                break;
+            }
+        }
+    });
+    return ret;
+}
+
 void* program::do_lookup_function(const char* name)
 {
     auto sym = lookup(name, nullptr);
diff --git a/include/osv/elf.hh b/include/osv/elf.hh
index 8cd7b37a..edcec7ff 100644
--- a/include/osv/elf.hh
+++ b/include/osv/elf.hh
@@ -584,6 +584,7 @@ public:
     void set_search_path(std::initializer_list<std::string> path);
 
     symbol_module lookup(const char* symbol, object* seeker);
+    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 e3a4a577..108a78ed 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, nullptr);
     } 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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/20200115173946.76109-2-zhitingz%40cs.utexas.edu.

Reply via email to