mirror of
https://github.com/fergalmoran/ladybird.git
synced 2026-01-03 23:25:20 +00:00
LibELF: Add support for IFUNCs
IFUNC is a GNU extension to the ELF standard that allows a function to have multiple implementations. A resolver function has to be called at load time to choose the right one to use. The PLT will contain the entry to the resolved function, so branching and more indirect jumps can be avoided at run-time. This mechanism is usually used when a routine can be made faster using CPU features that are available in only some models, and a fallback implementation has to exist for others. We will use this feature to have two separate memset implementations for CPUs with and without ERMS (Enhanced REP MOVSB/STOSB) support.
This commit is contained in:
committed by
Andreas Kling
parent
4d5965bd2c
commit
08c459e495
@@ -471,7 +471,7 @@ auto DynamicObject::lookup_symbol(HashSymbol const& symbol) const -> Optional<Sy
|
||||
auto symbol_result = result.value();
|
||||
if (symbol_result.is_undefined())
|
||||
return {};
|
||||
return SymbolLookupResult { symbol_result.value(), symbol_result.size(), symbol_result.address(), symbol_result.bind(), this };
|
||||
return SymbolLookupResult { symbol_result.value(), symbol_result.size(), symbol_result.address(), symbol_result.bind(), symbol_result.type(), this };
|
||||
}
|
||||
|
||||
NonnullRefPtr<DynamicObject> DynamicObject::create(String const& filename, VirtualAddress base_address, VirtualAddress dynamic_section_address)
|
||||
@@ -495,6 +495,9 @@ VirtualAddress DynamicObject::patch_plt_entry(u32 relocation_offset)
|
||||
auto result = DynamicLoader::lookup_symbol(symbol);
|
||||
if (result.has_value()) {
|
||||
symbol_location = result.value().address;
|
||||
|
||||
if (result.value().type == STT_GNU_IFUNC)
|
||||
symbol_location = VirtualAddress { reinterpret_cast<IfuncResolver>(symbol_location.get())() };
|
||||
} else if (symbol.bind() != STB_WEAK) {
|
||||
dbgln("did not find symbol while doing relocations for library {}: {}", m_filename, symbol.name());
|
||||
VERIFY_NOT_REACHED();
|
||||
|
||||
Reference in New Issue
Block a user