diff options
author | Andreas Kling <kling@serenityos.org> | 2021-02-23 18:44:09 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-02-23 19:43:44 +0100 |
commit | d6af3302e8426a61d20e42936103490a2b4ca2d8 (patch) | |
tree | b3589e29915d87d334751e95d29f8eb6470ecc96 /Userland/Libraries/LibELF | |
parent | af6a6334683c299b736ee1112aa763d0edd6a0e3 (diff) | |
download | serenity-d6af3302e8426a61d20e42936103490a2b4ca2d8.zip |
LibELF: Don't recompute the same ELF hashes over and over
When performing a global symbol lookup, we were recomputing the symbol
hashes once for every dynamic object searched. The hash function was
at the very top of a profile (15%) of program startup.
With this change, the hash function is no longer visible among the top
stacks in the profile. :^)
Diffstat (limited to 'Userland/Libraries/LibELF')
-rw-r--r-- | Userland/Libraries/LibELF/DynamicLinker.cpp | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibELF/DynamicLoader.cpp | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibELF/DynamicObject.cpp | 19 | ||||
-rw-r--r-- | Userland/Libraries/LibELF/DynamicObject.h | 27 |
4 files changed, 29 insertions, 27 deletions
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 <LibELF/DynamicLinker.h> #include <LibELF/DynamicLoader.h> #include <LibELF/DynamicObject.h> +#include <LibELF/Hashes.h> #include <dlfcn.h> #include <fcntl.h> #include <sys/types.h> @@ -64,8 +65,12 @@ bool g_do_breakpoint_trap_before_entry { false }; Optional<DynamicObject::SymbolLookupResult> DynamicLinker::lookup_global_symbol(const StringView& symbol) { Optional<DynamicObject::SymbolLookupResult> 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 <AK/StringBuilder.h> #include <LibELF/DynamicLinker.h> #include <LibELF/DynamicLoader.h> +#include <LibELF/Hashes.h> #include <LibELF/Validation.h> #include <assert.h> #include <dlfcn.h> @@ -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<Symbol> +auto DynamicObject::HashSection::lookup_elf_symbol(const StringView& name, u32 hash_value) const -> Optional<Symbol> { - return (this->*(m_lookup_function))(name); -} - -auto DynamicObject::HashSection::lookup_elf_symbol(const StringView& name) const -> Optional<Symbol> -{ - 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<Symbol> +auto DynamicObject::HashSection::lookup_gnu_symbol(const StringView& name, u32 hash_value) const -> Optional<Symbol> { // 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<SymbolLookupResult> { - 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<SymbolLookupResult> +{ + 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<Symbol> lookup_symbol(const StringView& name) const; + Optional<Symbol> 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<Symbol> lookup_elf_symbol(const StringView& name) const; - Optional<Symbol> lookup_gnu_symbol(const StringView& name) const; + Optional<Symbol> lookup_elf_symbol(const StringView& name, u32 hash) const; + Optional<Symbol> lookup_gnu_symbol(const StringView& name, u32 hash) const; - typedef Optional<Symbol> (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<SymbolLookupResult> lookup_symbol(const StringView& name) const; + Optional<SymbolLookupResult> 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); |