Browse Source

LibELF: Avoid calculating symbol hashes when we don't need them

Gunnar Beutner 4 years ago
parent
commit
f74b8a2d1f

+ 3 - 4
Userland/Libraries/LibELF/DynamicLinker.cpp

@@ -45,15 +45,14 @@ bool g_allowed_to_check_environment_variables { false };
 bool g_do_breakpoint_trap_before_entry { false };
 }
 
-Optional<DynamicObject::SymbolLookupResult> DynamicLinker::lookup_global_symbol(const StringView& symbol)
+Optional<DynamicObject::SymbolLookupResult> DynamicLinker::lookup_global_symbol(const StringView& name)
 {
     Optional<DynamicObject::SymbolLookupResult> weak_result;
 
-    auto gnu_hash = compute_gnu_hash(symbol);
-    auto sysv_hash = compute_sysv_hash(symbol);
+    auto symbol = DynamicObject::HashSymbol { name };
 
     for (auto& lib : g_global_objects) {
-        auto res = lib->lookup_symbol(symbol, gnu_hash, sysv_hash);
+        auto res = lib->lookup_symbol(symbol);
         if (!res.has_value())
             continue;
         if (res.value().bind == STB_GLOBAL)

+ 1 - 1
Userland/Libraries/LibELF/DynamicLoader.cpp

@@ -125,7 +125,7 @@ bool DynamicLoader::validate()
 
 void* DynamicLoader::symbol_for_name(const StringView& name)
 {
-    auto result = m_dynamic_object->hash_section().lookup_symbol(name, compute_gnu_hash(name), compute_sysv_hash(name));
+    auto result = m_dynamic_object->hash_section().lookup_symbol(name);
     if (!result.has_value())
         return nullptr;
     auto symbol = result.value();

+ 19 - 6
Userland/Libraries/LibELF/DynamicObject.cpp

@@ -428,18 +428,18 @@ static const char* name_for_dtag(Elf32_Sword d_tag)
 
 auto DynamicObject::lookup_symbol(const StringView& name) const -> Optional<SymbolLookupResult>
 {
-    return lookup_symbol(name, compute_gnu_hash(name), compute_sysv_hash(name));
+    return lookup_symbol(HashSymbol { name });
 }
 
-auto DynamicObject::lookup_symbol(const StringView& name, u32 gnu_hash, u32 sysv_hash) const -> Optional<SymbolLookupResult>
+auto DynamicObject::lookup_symbol(const HashSymbol& symbol) const -> Optional<SymbolLookupResult>
 {
-    auto result = hash_section().lookup_symbol(name, gnu_hash, sysv_hash);
+    auto result = hash_section().lookup_symbol(symbol);
     if (!result.has_value())
         return {};
-    auto symbol = result.value();
-    if (symbol.is_undefined())
+    auto symbol_result = result.value();
+    if (symbol_result.is_undefined())
         return {};
-    return SymbolLookupResult { symbol.value(), symbol.address(), symbol.bind(), this };
+    return SymbolLookupResult { symbol_result.value(), symbol_result.address(), symbol_result.bind(), this };
 }
 
 NonnullRefPtr<DynamicObject> DynamicObject::create(const String& filename, VirtualAddress base_address, VirtualAddress dynamic_section_address)
@@ -469,4 +469,17 @@ VirtualAddress DynamicObject::patch_plt_entry(u32 relocation_offset)
     return symbol_location;
 }
 
+u32 DynamicObject::HashSymbol::gnu_hash() const
+{
+    if (!m_gnu_hash.has_value())
+        m_gnu_hash = compute_gnu_hash(m_name);
+    return m_gnu_hash.value();
+}
+
+u32 DynamicObject::HashSymbol::sysv_hash() const
+{
+    if (!m_sysv_hash.has_value())
+        m_sysv_hash = compute_sysv_hash(m_name);
+    return m_sysv_hash.value();
+}
 } // end namespace ELF

+ 21 - 4
Userland/Libraries/LibELF/DynamicObject.h

@@ -162,6 +162,23 @@ public:
         GNU
     };
 
+    class HashSymbol {
+    public:
+        HashSymbol(const StringView& name)
+            : m_name(name)
+        {
+        }
+
+        StringView name() const { return m_name; }
+        u32 gnu_hash() const;
+        u32 sysv_hash() const;
+
+    private:
+        StringView m_name;
+        mutable Optional<u32> m_gnu_hash;
+        mutable Optional<u32> m_sysv_hash;
+    };
+
     class HashSection : public Section {
     public:
         HashSection(const Section& section, HashType hash_type)
@@ -170,11 +187,11 @@ public:
         {
         }
 
-        Optional<Symbol> lookup_symbol(const StringView& name, u32 gnu_hash, u32 sysv_hash) const
+        Optional<Symbol> lookup_symbol(const HashSymbol& symbol) const
         {
             if (m_hash_type == HashType::SYSV)
-                return lookup_sysv_symbol(name, sysv_hash);
-            return lookup_gnu_symbol(name, gnu_hash);
+                return lookup_sysv_symbol(symbol.name(), symbol.sysv_hash());
+            return lookup_gnu_symbol(symbol.name(), symbol.gnu_hash());
         }
 
     private:
@@ -253,7 +270,7 @@ public:
     };
 
     Optional<SymbolLookupResult> lookup_symbol(const StringView& name) const;
-    Optional<SymbolLookupResult> lookup_symbol(const StringView& name, u32 gnu_hash, u32 sysv_hash) const;
+    Optional<SymbolLookupResult> lookup_symbol(const HashSymbol& symbol) const;
 
     // Will be called from _fixup_plt_entry, as part of the PLT trampoline
     VirtualAddress patch_plt_entry(u32 relocation_offset);