summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibELF
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-02-23 18:44:09 +0100
committerAndreas Kling <kling@serenityos.org>2021-02-23 19:43:44 +0100
commitd6af3302e8426a61d20e42936103490a2b4ca2d8 (patch)
treeb3589e29915d87d334751e95d29f8eb6470ecc96 /Userland/Libraries/LibELF
parentaf6a6334683c299b736ee1112aa763d0edd6a0e3 (diff)
downloadserenity-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.cpp7
-rw-r--r--Userland/Libraries/LibELF/DynamicLoader.cpp3
-rw-r--r--Userland/Libraries/LibELF/DynamicObject.cpp19
-rw-r--r--Userland/Libraries/LibELF/DynamicObject.h27
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);