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:
parent
2c3f284b06
commit
0c0127dc3f
6 changed files with 36 additions and 41 deletions
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue