DynamicLoader: Resolve missing weak absolute symbols to null

Weak symbols can be left unresolved, and code is supposed to check if
they're null at runtime before using them. Handle them appropriately
instead of refusing to load.
This commit is contained in:
Idan Horowitz 2024-04-22 22:37:50 +03:00 committed by Daniel Bertalan
parent 28fcf64835
commit 0d8064fafc
Notes: sideshowbarker 2024-07-17 09:49:33 +09:00

View file

@ -520,7 +520,7 @@ void DynamicLoader::load_program_headers()
DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObject::Relocation const& relocation, DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObject::Relocation const& relocation,
Optional<DynamicLoader::CachedLookupResult>& cached_result, Optional<DynamicLoader::CachedLookupResult>& cached_result,
[[maybe_unused]] ShouldInitializeWeak should_initialize_weak, ShouldInitializeWeak should_initialize_weak,
ShouldCallIfuncResolver should_call_ifunc_resolver) ShouldCallIfuncResolver should_call_ifunc_resolver)
{ {
FlatPtr* patch_ptr = nullptr; FlatPtr* patch_ptr = nullptr;
@ -569,21 +569,26 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
case ABSOLUTE: { case ABSOLUTE: {
auto symbol = relocation.symbol(); auto symbol = relocation.symbol();
auto res = lookup_symbol(symbol); auto res = lookup_symbol(symbol);
VirtualAddress symbol_address;
if (!res.has_value()) { if (!res.has_value()) {
if (symbol.bind() == STB_WEAK) if (symbol.bind() == STB_WEAK) {
return RelocationResult::ResolveLater; if (should_initialize_weak == ShouldInitializeWeak::No)
dbgln("ERROR: symbol not found: {}.", symbol.name()); return RelocationResult::ResolveLater;
return RelocationResult::Failed; } else {
dbgln("ERROR: symbol not found: {}.", symbol.name());
return RelocationResult::Failed;
}
symbol_address = VirtualAddress { (FlatPtr)0 };
} else {
if (res.value().type == STT_GNU_IFUNC && should_call_ifunc_resolver == ShouldCallIfuncResolver::No)
return RelocationResult::CallIfuncResolver;
symbol_address = res.value().address;
} }
if (res.value().type == STT_GNU_IFUNC && should_call_ifunc_resolver == ShouldCallIfuncResolver::No)
return RelocationResult::CallIfuncResolver;
auto symbol_address = res.value().address;
if (relocation.addend_used()) if (relocation.addend_used())
*patch_ptr = symbol_address.get() + relocation.addend(); *patch_ptr = symbol_address.get() + relocation.addend();
else else
*patch_ptr += symbol_address.get(); *patch_ptr += symbol_address.get();
if (res.value().type == STT_GNU_IFUNC) if (res.has_value() && res.value().type == STT_GNU_IFUNC)
*patch_ptr = call_ifunc_resolver(VirtualAddress { *patch_ptr }).get(); *patch_ptr = call_ifunc_resolver(VirtualAddress { *patch_ptr }).get();
break; break;
} }