diff --git a/Userland/Libraries/LibELF/DynamicLinker.cpp b/Userland/Libraries/LibELF/DynamicLinker.cpp index 9927889482..4e7842de3f 100644 --- a/Userland/Libraries/LibELF/DynamicLinker.cpp +++ b/Userland/Libraries/LibELF/DynamicLinker.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -64,8 +65,12 @@ bool g_do_breakpoint_trap_before_entry { false }; Optional DynamicLinker::lookup_global_symbol(const StringView& symbol) { Optional weak_result; + + auto gnu_hash = compute_gnu_hash(symbol); + auto sysv_hash = compute_sysv_hash(symbol); + for (auto& lib : g_global_objects) { - auto res = lib->lookup_symbol(symbol); + auto res = lib->lookup_symbol(symbol, gnu_hash, sysv_hash); if (!res.has_value()) continue; if (res.value().bind == STB_GLOBAL) diff --git a/Userland/Libraries/LibELF/DynamicLoader.cpp b/Userland/Libraries/LibELF/DynamicLoader.cpp index 23ed13b3f2..d81a410221 100644 --- a/Userland/Libraries/LibELF/DynamicLoader.cpp +++ b/Userland/Libraries/LibELF/DynamicLoader.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -142,7 +143,7 @@ bool DynamicLoader::validate() void* DynamicLoader::symbol_for_name(const StringView& name) { - auto result = m_dynamic_object->hash_section().lookup_symbol(name); + auto result = m_dynamic_object->hash_section().lookup_symbol(name, compute_gnu_hash(name), compute_sysv_hash(name)); if (!result.has_value()) return nullptr; auto symbol = result.value(); diff --git a/Userland/Libraries/LibELF/DynamicObject.cpp b/Userland/Libraries/LibELF/DynamicObject.cpp index 2d0c48acaf..47ff8606b0 100644 --- a/Userland/Libraries/LibELF/DynamicObject.cpp +++ b/Userland/Libraries/LibELF/DynamicObject.cpp @@ -249,14 +249,8 @@ DynamicObject::RelocationSection DynamicObject::plt_relocation_section() const return RelocationSection(Section(*this, m_plt_relocation_offset_location, m_size_of_plt_relocation_entry_list, m_size_of_relocation_entry, "DT_JMPREL")); } -auto DynamicObject::HashSection::lookup_symbol(const StringView& name) const -> Optional +auto DynamicObject::HashSection::lookup_elf_symbol(const StringView& name, u32 hash_value) const -> Optional { - return (this->*(m_lookup_function))(name); -} - -auto DynamicObject::HashSection::lookup_elf_symbol(const StringView& name) const -> Optional -{ - u32 hash_value = compute_sysv_hash(name); u32* hash_table_begin = (u32*)address().as_ptr(); size_t num_buckets = hash_table_begin[0]; @@ -279,7 +273,7 @@ auto DynamicObject::HashSection::lookup_elf_symbol(const StringView& name) const return {}; } -auto DynamicObject::HashSection::lookup_gnu_symbol(const StringView& name) const -> Optional +auto DynamicObject::HashSection::lookup_gnu_symbol(const StringView& name, u32 hash_value) const -> Optional { // Algorithm reference: https://ent-voy.blogspot.com/2011/02/ // TODO: Handle 64bit bloomwords for ELF_CLASS64 @@ -299,7 +293,7 @@ auto DynamicObject::HashSection::lookup_gnu_symbol(const StringView& name) const const u32* const buckets = &bloom_words[num_maskwords]; const u32* const chains = &buckets[num_buckets]; - BloomWord hash1 = compute_gnu_hash(name); + BloomWord hash1 = hash_value; BloomWord hash2 = hash1 >> shift2; const BloomWord bitmask = (1 << (hash1 % bloom_word_size)) | (1 << (hash2 % bloom_word_size)); @@ -431,7 +425,12 @@ static const char* name_for_dtag(Elf32_Sword d_tag) auto DynamicObject::lookup_symbol(const StringView& name) const -> Optional { - auto result = hash_section().lookup_symbol(name); + return lookup_symbol(name, compute_gnu_hash(name), compute_sysv_hash(name)); +} + +auto DynamicObject::lookup_symbol(const StringView& name, u32 gnu_hash, u32 sysv_hash) const -> Optional +{ + auto result = hash_section().lookup_symbol(name, gnu_hash, sysv_hash); if (!result.has_value()) return {}; auto symbol = result.value(); diff --git a/Userland/Libraries/LibELF/DynamicObject.h b/Userland/Libraries/LibELF/DynamicObject.h index dd6d039cfc..ee881ac716 100644 --- a/Userland/Libraries/LibELF/DynamicObject.h +++ b/Userland/Libraries/LibELF/DynamicObject.h @@ -184,27 +184,22 @@ public: public: HashSection(const Section& section, HashType hash_type) : Section(section.m_dynamic, section.m_section_offset, section.m_section_size_bytes, section.m_entry_size, section.m_name) + , m_hash_type(hash_type) { - switch (hash_type) { - case HashType::SYSV: - m_lookup_function = &HashSection::lookup_elf_symbol; - break; - case HashType::GNU: - m_lookup_function = &HashSection::lookup_gnu_symbol; - break; - default: - ASSERT_NOT_REACHED(); - } } - Optional lookup_symbol(const StringView& name) const; + Optional lookup_symbol(const StringView& name, u32 gnu_hash, u32 sysv_hash) const + { + if (m_hash_type == HashType::SYSV) + return lookup_elf_symbol(name, sysv_hash); + return lookup_gnu_symbol(name, gnu_hash); + } private: - Optional lookup_elf_symbol(const StringView& name) const; - Optional lookup_gnu_symbol(const StringView& name) const; + Optional lookup_elf_symbol(const StringView& name, u32 hash) const; + Optional lookup_gnu_symbol(const StringView& name, u32 hash) const; - typedef Optional (HashSection::*LookupFunction)(const StringView&) const; - LookupFunction m_lookup_function {}; + HashType m_hash_type {}; }; unsigned symbol_count() const { return m_symbol_count; } @@ -256,7 +251,9 @@ public: unsigned bind { STB_LOCAL }; const ELF::DynamicObject* dynamic_object { nullptr }; // The object in which the symbol is defined }; + Optional lookup_symbol(const StringView& name) const; + Optional lookup_symbol(const StringView& name, u32 gnu_hash, u32 sysv_hash) const; // Will be called from _fixup_plt_entry, as part of the PLT trampoline VirtualAddress patch_plt_entry(u32 relocation_offset);