diff --git a/core/elf.cc b/core/elf.cc
index d89954e598ce05da2324a07646338c6da101a14e..6427f86701d9869f0a80963c755072ccc869db01 100644
--- a/core/elf.cc
+++ b/core/elf.cc
@@ -27,6 +27,12 @@ namespace elf {
 
     }
 
+    symbol_module::symbol_module()
+        : symbol()
+        , object()
+    {
+    }
+
     symbol_module::symbol_module(Elf64_Sym* _sym, elf_object* _obj)
         : symbol(_sym)
         , object(_obj)
diff --git a/include/elf.hh b/include/elf.hh
index b973f6a494995406737480494fe7930fd3d8fa83..a6c5eee9260863dfda42ec83f580dc8e90953098 100644
--- a/include/elf.hh
+++ b/include/elf.hh
@@ -315,6 +315,7 @@ namespace elf {
 
     struct symbol_module {
     public:
+        symbol_module();
         symbol_module(Elf64_Sym* sym, elf_object* object);
         void* relocated_addr() const;
         Elf64_Sym* symbol;
diff --git a/libc/dlfcn.cc b/libc/dlfcn.cc
index 1aeac527d7b0915431442dbbed516314f2e51fd9..d3a1cbc54305847d204f3178972357012bd252b0 100644
--- a/libc/dlfcn.cc
+++ b/libc/dlfcn.cc
@@ -12,9 +12,17 @@ void* dlopen(const char* filename, int flags)
 
 void* dlsym(void* handle, const char* name)
 {
-    // FIXME: don't ignore handle
-    auto sym = elf::get_program()->lookup(name);
-    if (!sym.object) {
+    elf::symbol_module sym;
+    if (handle == RTLD_DEFAULT) {
+        sym = elf::get_program()->lookup(name);
+    } else if (handle == RTLD_NEXT) {
+        // FIXME: implement
+        abort();
+    } else {
+        auto obj = reinterpret_cast<elf::elf_object*>(handle);
+        sym = { obj->lookup_symbol(name), obj };
+    }
+    if (!sym.object || !sym.symbol) {
         return nullptr;
     }
     return sym.relocated_addr();