1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 13:57:35 +00:00

LibELF: Use StringView instead of "const char*" in dynamic linker code

There's no reason to use C strings more than absolutely necessary.
This commit is contained in:
Andreas Kling 2021-02-20 19:20:08 +01:00
parent 2c3f284b06
commit 0c0127dc3f
6 changed files with 36 additions and 41 deletions

View file

@ -65,11 +65,11 @@ bool g_allowed_to_check_environment_variables { false };
bool g_do_breakpoint_trap_before_entry { false }; bool g_do_breakpoint_trap_before_entry { false };
} }
Optional<DynamicObject::SymbolLookupResult> DynamicLinker::lookup_global_symbol(const char* symbol_name) Optional<DynamicObject::SymbolLookupResult> DynamicLinker::lookup_global_symbol(const StringView& symbol)
{ {
Optional<DynamicObject::SymbolLookupResult> weak_result; Optional<DynamicObject::SymbolLookupResult> weak_result;
for (auto& lib : g_global_objects) { for (auto& lib : g_global_objects) {
auto res = lib->lookup_symbol(symbol_name); auto res = lib->lookup_symbol(symbol);
if (!res.has_value()) if (!res.has_value())
continue; continue;
if (res.value().bind == STB_GLOBAL) if (res.value().bind == STB_GLOBAL)

View file

@ -34,7 +34,7 @@ namespace ELF {
class DynamicLinker { class DynamicLinker {
public: public:
static Optional<DynamicObject::SymbolLookupResult> lookup_global_symbol(const char* symbol); static Optional<DynamicObject::SymbolLookupResult> lookup_global_symbol(const StringView& symbol);
[[noreturn]] static void linker_main(String&& main_program_name, int fd, bool is_secure, int argc, char** argv, char** envp); [[noreturn]] static void linker_main(String&& main_program_name, int fd, bool is_secure, int argc, char** argv, char** envp);
private: private:

View file

@ -140,7 +140,7 @@ bool DynamicLoader::validate()
return true; return true;
} }
void* DynamicLoader::symbol_for_name(const char* name) void* DynamicLoader::symbol_for_name(const StringView& name)
{ {
auto symbol = m_dynamic_object->hash_section().lookup_symbol(name); auto symbol = m_dynamic_object->hash_section().lookup_symbol(name);
@ -445,10 +445,8 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_si
// We do not support these // We do not support these
// TODO: Can we tell gcc not to generate the piece of code that uses these? // TODO: Can we tell gcc not to generate the piece of code that uses these?
// (--disable-tm-clone-registry flag in gcc conifugraion?) // (--disable-tm-clone-registry flag in gcc conifugraion?)
if (!strcmp(symbol.name(), "__deregister_frame_info") || !strcmp(symbol.name(), "_ITM_registerTMCloneTable") if (symbol.name().is_one_of("__deregister_frame_info", "_ITM_registerTMCloneTable", "_ITM_deregisterTMCloneTable", "__register_frame_info"))
|| !strcmp(symbol.name(), "_ITM_deregisterTMCloneTable") || !strcmp(symbol.name(), "__register_frame_info")) {
break; break;
}
if (symbol.bind() == STB_WEAK) if (symbol.bind() == STB_WEAK)
return RelocationResult::ResolveLater; return RelocationResult::ResolveLater;

View file

@ -60,7 +60,7 @@ public:
// Stage 3 of loading: lazy relocations and initializers // Stage 3 of loading: lazy relocations and initializers
RefPtr<DynamicObject> load_stage_3(unsigned flags, size_t total_tls_size); RefPtr<DynamicObject> load_stage_3(unsigned flags, size_t total_tls_size);
// Intended for use by dlsym or other internal methods // Intended for use by dlsym or other internal methods
void* symbol_for_name(const char*); void* symbol_for_name(const StringView&);
void dump(); void dump();

View file

@ -31,7 +31,6 @@
#include <LibELF/DynamicLinker.h> #include <LibELF/DynamicLinker.h>
#include <LibELF/DynamicObject.h> #include <LibELF/DynamicObject.h>
#include <LibELF/exec_elf.h> #include <LibELF/exec_elf.h>
#include <stdio.h>
#include <string.h> #include <string.h>
namespace ELF { namespace ELF {
@ -71,7 +70,7 @@ void DynamicObject::dump() const
}); });
if (m_has_soname) if (m_has_soname)
builder.appendf("DT_SONAME: %s\n", soname()); // FIXME: Valdidate that this string is null terminated? builder.appendff("DT_SONAME: {}\n", soname()); // FIXME: Valdidate that this string is null terminated?
dbgln_if(DYNAMIC_LOAD_DEBUG, "Dynamic section at address {} contains {} entries:", m_dynamic_address.as_ptr(), num_dynamic_sections); dbgln_if(DYNAMIC_LOAD_DEBUG, "Dynamic section at address {} contains {} entries:", m_dynamic_address.as_ptr(), num_dynamic_sections);
dbgln_if(DYNAMIC_LOAD_DEBUG, "{}", builder.string_view()); dbgln_if(DYNAMIC_LOAD_DEBUG, "{}", builder.string_view());
@ -249,17 +248,16 @@ const DynamicObject::RelocationSection DynamicObject::plt_relocation_section() c
return RelocationSection(Section(*this, m_plt_relocation_offset_location, m_size_of_plt_relocation_entry_list, m_size_of_relocation_entry, "DT_JMPREL")); return RelocationSection(Section(*this, m_plt_relocation_offset_location, m_size_of_plt_relocation_entry_list, m_size_of_relocation_entry, "DT_JMPREL"));
} }
u32 DynamicObject::HashSection::calculate_elf_hash(const char* name) const u32 DynamicObject::HashSection::calculate_elf_hash(const StringView& name) const
{ {
// SYSV ELF hash algorithm // SYSV ELF hash algorithm
// Note that the GNU HASH algorithm has less collisions // Note that the GNU HASH algorithm has less collisions
uint32_t hash = 0; uint32_t hash = 0;
while (*name != '\0') { for (auto ch : name) {
hash = hash << 4; hash = hash << 4;
hash += *name; hash += ch;
name++;
const uint32_t top_nibble_of_hash = hash & 0xF0000000U; const uint32_t top_nibble_of_hash = hash & 0xF0000000U;
hash ^= top_nibble_of_hash >> 24; hash ^= top_nibble_of_hash >> 24;
@ -269,24 +267,23 @@ u32 DynamicObject::HashSection::calculate_elf_hash(const char* name) const
return hash; return hash;
} }
u32 DynamicObject::HashSection::calculate_gnu_hash(const char* name) const u32 DynamicObject::HashSection::calculate_gnu_hash(const StringView& name) const
{ {
// GNU ELF hash algorithm // GNU ELF hash algorithm
u32 hash = 5381; u32 hash = 5381;
for (; *name != '\0'; ++name) { for (auto ch : name)
hash = hash * 33 + *name; hash = hash * 33 + ch;
}
return hash; return hash;
} }
const DynamicObject::Symbol DynamicObject::HashSection::lookup_symbol(const char* name) const auto DynamicObject::HashSection::lookup_symbol(const StringView& name) const -> Symbol
{ {
return (this->*(m_lookup_function))(name); return (this->*(m_lookup_function))(name);
} }
const DynamicObject::Symbol DynamicObject::HashSection::lookup_elf_symbol(const char* name) const const DynamicObject::Symbol DynamicObject::HashSection::lookup_elf_symbol(const StringView& name) const
{ {
u32 hash_value = calculate_elf_hash(name); u32 hash_value = calculate_elf_hash(name);
@ -305,7 +302,7 @@ const DynamicObject::Symbol DynamicObject::HashSection::lookup_elf_symbol(const
for (u32 i = buckets[hash_value % num_buckets]; i; i = chains[i]) { for (u32 i = buckets[hash_value % num_buckets]; i; i = chains[i]) {
auto symbol = m_dynamic.symbol(i); auto symbol = m_dynamic.symbol(i);
if (strcmp(name, symbol.name()) == 0) { if (name == symbol.name()) {
dbgln_if(DYNAMIC_LOAD_DEBUG, "Returning SYSV dynamic symbol with index {} for {}: {}", i, symbol.name(), symbol.address().as_ptr()); dbgln_if(DYNAMIC_LOAD_DEBUG, "Returning SYSV dynamic symbol with index {} for {}: {}", i, symbol.name(), symbol.address().as_ptr());
return symbol; return symbol;
} }
@ -313,7 +310,7 @@ const DynamicObject::Symbol DynamicObject::HashSection::lookup_elf_symbol(const
return Symbol::create_undefined(m_dynamic); return Symbol::create_undefined(m_dynamic);
} }
const DynamicObject::Symbol DynamicObject::HashSection::lookup_gnu_symbol(const char* name) const const DynamicObject::Symbol DynamicObject::HashSection::lookup_gnu_symbol(const StringView& name) const
{ {
// Algorithm reference: https://ent-voy.blogspot.com/2011/02/ // Algorithm reference: https://ent-voy.blogspot.com/2011/02/
// TODO: Handle 64bit bloomwords for ELF_CLASS64 // TODO: Handle 64bit bloomwords for ELF_CLASS64
@ -350,7 +347,7 @@ const DynamicObject::Symbol DynamicObject::HashSection::lookup_gnu_symbol(const
for (hash1 &= ~1;; ++current_sym) { for (hash1 &= ~1;; ++current_sym) {
hash2 = *(current_chain++); hash2 = *(current_chain++);
const auto symbol = m_dynamic.symbol(current_sym); const auto symbol = m_dynamic.symbol(current_sym);
if ((hash1 == (hash2 & ~1)) && strcmp(name, symbol.name()) == 0) { if ((hash1 == (hash2 & ~1)) && name == symbol.name()) {
dbgln_if(DYNAMIC_LOAD_DEBUG, "Returning GNU dynamic symbol with index {} for {}: {}", current_sym, symbol.name(), symbol.address().as_ptr()); dbgln_if(DYNAMIC_LOAD_DEBUG, "Returning GNU dynamic symbol with index {} for {}: {}", current_sym, symbol.name(), symbol.address().as_ptr());
return symbol; return symbol;
} }
@ -362,9 +359,9 @@ const DynamicObject::Symbol DynamicObject::HashSection::lookup_gnu_symbol(const
return Symbol::create_undefined(m_dynamic); return Symbol::create_undefined(m_dynamic);
} }
const char* DynamicObject::symbol_string_table_string(Elf32_Word index) const StringView DynamicObject::symbol_string_table_string(Elf32_Word index) const
{ {
return (const char*)base_address().offset(m_string_table_offset + index).as_ptr(); return StringView { (const char*)base_address().offset(m_string_table_offset + index).as_ptr() };
} }
DynamicObject::InitializationFunction DynamicObject::init_section_function() const DynamicObject::InitializationFunction DynamicObject::init_section_function() const
@ -465,7 +462,7 @@ static const char* name_for_dtag(Elf32_Sword d_tag)
} }
} }
Optional<DynamicObject::SymbolLookupResult> DynamicObject::lookup_symbol(const char* name) const Optional<DynamicObject::SymbolLookupResult> DynamicObject::lookup_symbol(const StringView& name) const
{ {
auto res = hash_section().lookup_symbol(name); auto res = hash_section().lookup_symbol(name);
if (res.is_undefined()) if (res.is_undefined())

View file

@ -93,7 +93,7 @@ public:
~Symbol() { } ~Symbol() { }
const char* name() const { return m_dynamic.symbol_string_table_string(m_sym.st_name); } StringView name() const { return m_dynamic.symbol_string_table_string(m_sym.st_name); }
unsigned section_index() const { return m_sym.st_shndx; } unsigned section_index() const { return m_sym.st_shndx; }
unsigned value() const { return m_sym.st_value; } unsigned value() const { return m_sym.st_value; }
unsigned size() const { return m_sym.st_size; } unsigned size() const { return m_sym.st_size; }
@ -122,7 +122,7 @@ public:
class Section { class Section {
public: public:
Section(const DynamicObject& dynamic, unsigned section_offset, unsigned section_size_bytes, unsigned entry_size, const char* name) Section(const DynamicObject& dynamic, unsigned section_offset, unsigned section_size_bytes, unsigned entry_size, const StringView& name)
: m_dynamic(dynamic) : m_dynamic(dynamic)
, m_section_offset(section_offset) , m_section_offset(section_offset)
, m_section_size_bytes(section_size_bytes) , m_section_size_bytes(section_size_bytes)
@ -132,7 +132,7 @@ public:
} }
~Section() { } ~Section() { }
const char* name() const { return m_name; } StringView name() const { return m_name; }
unsigned offset() const { return m_section_offset; } unsigned offset() const { return m_section_offset; }
unsigned size() const { return m_section_size_bytes; } unsigned size() const { return m_section_size_bytes; }
unsigned entry_size() const { return m_entry_size; } unsigned entry_size() const { return m_entry_size; }
@ -152,7 +152,7 @@ public:
unsigned m_section_offset; unsigned m_section_offset;
unsigned m_section_size_bytes; unsigned m_section_size_bytes;
unsigned m_entry_size; unsigned m_entry_size;
const char* m_name { nullptr }; StringView m_name;
}; };
class RelocationSection : public Section { class RelocationSection : public Section {
@ -220,17 +220,17 @@ public:
} }
} }
const Symbol lookup_symbol(const char*) const; Symbol lookup_symbol(const StringView& name) const;
private: private:
u32 calculate_elf_hash(const char* name) const; u32 calculate_elf_hash(const StringView& name) const;
u32 calculate_gnu_hash(const char* name) const; u32 calculate_gnu_hash(const StringView& name) const;
const DynamicObject::Symbol lookup_elf_symbol(const char* name) const; const DynamicObject::Symbol lookup_elf_symbol(const StringView& name) const;
const DynamicObject::Symbol lookup_gnu_symbol(const char* name) const; const DynamicObject::Symbol lookup_gnu_symbol(const StringView& name) const;
typedef const DynamicObject::Symbol (HashSection::*LookupFunction)(const char*) const; typedef const DynamicObject::Symbol (HashSection::*LookupFunction)(const StringView&) const;
LookupFunction m_lookup_function; LookupFunction m_lookup_function {};
}; };
unsigned symbol_count() const { return m_symbol_count; } unsigned symbol_count() const { return m_symbol_count; }
@ -263,7 +263,7 @@ public:
VirtualAddress plt_got_base_address() const { return m_base_address.offset(m_procedure_linkage_table_offset.value()); } VirtualAddress plt_got_base_address() const { return m_base_address.offset(m_procedure_linkage_table_offset.value()); }
VirtualAddress base_address() const { return m_base_address; } VirtualAddress base_address() const { return m_base_address; }
const char* soname() const { return m_has_soname ? symbol_string_table_string(m_soname_index) : nullptr; } StringView soname() const { return m_has_soname ? symbol_string_table_string(m_soname_index) : StringView {}; }
Optional<FlatPtr> tls_offset() const { return m_tls_offset; } Optional<FlatPtr> tls_offset() const { return m_tls_offset; }
Optional<FlatPtr> tls_size() const { return m_tls_size; } Optional<FlatPtr> tls_size() const { return m_tls_size; }
@ -282,7 +282,7 @@ public:
unsigned bind { STB_LOCAL }; unsigned bind { STB_LOCAL };
const ELF::DynamicObject* dynamic_object { nullptr }; // The object in which the symbol is defined const ELF::DynamicObject* dynamic_object { nullptr }; // The object in which the symbol is defined
}; };
Optional<SymbolLookupResult> lookup_symbol(const char* name) const; Optional<SymbolLookupResult> lookup_symbol(const StringView& name) const;
// Will be called from _fixup_plt_entry, as part of the PLT trampoline // Will be called from _fixup_plt_entry, as part of the PLT trampoline
Elf32_Addr patch_plt_entry(u32 relocation_offset); Elf32_Addr patch_plt_entry(u32 relocation_offset);
@ -294,7 +294,7 @@ public:
private: private:
explicit DynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_address); explicit DynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_address);
const char* symbol_string_table_string(Elf32_Word) const; StringView symbol_string_table_string(Elf32_Word) const;
void parse(); void parse();
template<typename F> template<typename F>
@ -390,7 +390,7 @@ inline void DynamicObject::for_each_needed_library(F func) const
if (entry.tag() != DT_NEEDED) if (entry.tag() != DT_NEEDED)
return IterationDecision::Continue; return IterationDecision::Continue;
Elf32_Word offset = entry.val(); Elf32_Word offset = entry.val();
const char* name = (const char*)(m_base_address.offset(m_string_table_offset).offset(offset)).as_ptr(); StringView name { (const char*)(m_base_address.offset(m_string_table_offset).offset(offset)).as_ptr() };
if (func(StringView(name)) == IterationDecision::Break) if (func(StringView(name)) == IterationDecision::Break)
return IterationDecision::Break; return IterationDecision::Break;
return IterationDecision::Continue; return IterationDecision::Continue;