ソースを参照

LibELF: Fix support for relocating weak symbols

Having unresolved weak symbols is allowed and we should initialize
them to zero.
Gunnar Beutner 4 年 前
コミット
1dab5ca5fd

+ 14 - 9
Userland/Libraries/LibELF/DynamicLoader.cpp

@@ -211,7 +211,7 @@ bool DynamicLoader::load_stage_2(unsigned flags, size_t total_tls_size)
 void DynamicLoader::do_main_relocations(size_t total_tls_size)
 void DynamicLoader::do_main_relocations(size_t total_tls_size)
 {
 {
     auto do_single_relocation = [&](const ELF::DynamicObject::Relocation& relocation) {
     auto do_single_relocation = [&](const ELF::DynamicObject::Relocation& relocation) {
-        switch (do_relocation(total_tls_size, relocation)) {
+        switch (do_relocation(total_tls_size, relocation, ShouldInitializeWeak::No)) {
         case RelocationResult::Failed:
         case RelocationResult::Failed:
             dbgln("Loader.so: {} unresolved symbol '{}'", m_filename, relocation.symbol().name());
             dbgln("Loader.so: {} unresolved symbol '{}'", m_filename, relocation.symbol().name());
             VERIFY_NOT_REACHED();
             VERIFY_NOT_REACHED();
@@ -267,7 +267,7 @@ void DynamicLoader::load_stage_4()
 void DynamicLoader::do_lazy_relocations(size_t total_tls_size)
 void DynamicLoader::do_lazy_relocations(size_t total_tls_size)
 {
 {
     for (const auto& relocation : m_unresolved_relocations) {
     for (const auto& relocation : m_unresolved_relocations) {
-        if (auto res = do_relocation(total_tls_size, relocation); res != RelocationResult::Success) {
+        if (auto res = do_relocation(total_tls_size, relocation, ShouldInitializeWeak::Yes); res != RelocationResult::Success) {
             dbgln("Loader.so: {} unresolved symbol '{}'", m_filename, relocation.symbol().name());
             dbgln("Loader.so: {} unresolved symbol '{}'", m_filename, relocation.symbol().name());
             VERIFY_NOT_REACHED();
             VERIFY_NOT_REACHED();
         }
         }
@@ -424,7 +424,7 @@ void DynamicLoader::load_program_headers()
     // FIXME: Initialize the values in the TLS section. Currently, it is zeroed.
     // FIXME: Initialize the values in the TLS section. Currently, it is zeroed.
 }
 }
 
 
-DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_size, const ELF::DynamicObject::Relocation& relocation)
+DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_size, const ELF::DynamicObject::Relocation& relocation, ShouldInitializeWeak should_initialize_weak)
 {
 {
     FlatPtr* patch_ptr = nullptr;
     FlatPtr* patch_ptr = nullptr;
     if (is_dynamic())
     if (is_dynamic())
@@ -462,14 +462,19 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_si
     case R_386_GLOB_DAT: {
     case R_386_GLOB_DAT: {
         auto symbol = relocation.symbol();
         auto symbol = relocation.symbol();
         auto res = lookup_symbol(symbol);
         auto res = lookup_symbol(symbol);
+        VirtualAddress symbol_location;
         if (!res.has_value()) {
         if (!res.has_value()) {
-            if (symbol.bind() == STB_WEAK)
-                return RelocationResult::ResolveLater;
+            if (symbol.bind() == STB_WEAK) {
+                if (should_initialize_weak == ShouldInitializeWeak::No)
+                    return RelocationResult::ResolveLater;
+            } else {
+                // Symbol not found
+                return RelocationResult::Failed;
+            }
 
 
-            // Symbol not found
-            return RelocationResult::Failed;
-        }
-        auto symbol_location = res.value().address;
+            symbol_location = VirtualAddress { (FlatPtr)0 };
+        } else
+            symbol_location = res.value().address;
         VERIFY(symbol_location != m_dynamic_object->base_address());
         VERIFY(symbol_location != m_dynamic_object->base_address());
         *patch_ptr = symbol_location.get();
         *patch_ptr = symbol_location.get();
         break;
         break;

+ 6 - 1
Userland/Libraries/LibELF/DynamicLoader.h

@@ -54,6 +54,11 @@ private:
     size_t m_size;
     size_t m_size;
 };
 };
 
 
+enum class ShouldInitializeWeak {
+    Yes,
+    No
+};
+
 class DynamicLoader : public RefCounted<DynamicLoader> {
 class DynamicLoader : public RefCounted<DynamicLoader> {
 public:
 public:
     static RefPtr<DynamicLoader> try_create(int fd, String filename);
     static RefPtr<DynamicLoader> try_create(int fd, String filename);
@@ -145,7 +150,7 @@ private:
         Success = 1,
         Success = 1,
         ResolveLater = 2,
         ResolveLater = 2,
     };
     };
-    RelocationResult do_relocation(size_t total_tls_size, const DynamicObject::Relocation&);
+    RelocationResult do_relocation(size_t total_tls_size, const DynamicObject::Relocation&, ShouldInitializeWeak should_initialize_weak);
     size_t calculate_tls_size() const;
     size_t calculate_tls_size() const;
 
 
     String m_filename;
     String m_filename;