Skip to content

Commit

Permalink
LibELF: Fix support for relocating weak symbols
Browse files Browse the repository at this point in the history
Having unresolved weak symbols is allowed and we should initialize
them to zero.
  • Loading branch information
gunnarbeutner authored and awesomekling committed Apr 19, 2021
1 parent 97d7450 commit 1dab5ca
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 10 deletions.
23 changes: 14 additions & 9 deletions Userland/Libraries/LibELF/DynamicLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ bool DynamicLoader::load_stage_2(unsigned flags, size_t total_tls_size)
void DynamicLoader::do_main_relocations(size_t total_tls_size)
{
auto do_single_relocation = [&](const ELF::DynamicObject::Relocation& relocation) {
switch (do_relocation(total_tls_size, relocation)) {
switch (do_relocation(total_tls_size, relocation, ShouldInitializeWeak::No)) {
case RelocationResult::Failed:
dbgln("Loader.so: {} unresolved symbol '{}'", m_filename, relocation.symbol().name());
VERIFY_NOT_REACHED();
Expand Down Expand Up @@ -267,7 +267,7 @@ void DynamicLoader::load_stage_4()
void DynamicLoader::do_lazy_relocations(size_t total_tls_size)
{
for (const auto& relocation : m_unresolved_relocations) {
if (auto res = do_relocation(total_tls_size, relocation); res != RelocationResult::Success) {
if (auto res = do_relocation(total_tls_size, relocation, ShouldInitializeWeak::Yes); res != RelocationResult::Success) {
dbgln("Loader.so: {} unresolved symbol '{}'", m_filename, relocation.symbol().name());
VERIFY_NOT_REACHED();
}
Expand Down Expand Up @@ -424,7 +424,7 @@ void DynamicLoader::load_program_headers()
// FIXME: Initialize the values in the TLS section. Currently, it is zeroed.
}

DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_size, const ELF::DynamicObject::Relocation& relocation)
DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_size, const ELF::DynamicObject::Relocation& relocation, ShouldInitializeWeak should_initialize_weak)
{
FlatPtr* patch_ptr = nullptr;
if (is_dynamic())
Expand Down Expand Up @@ -462,14 +462,19 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_si
case R_386_GLOB_DAT: {
auto symbol = relocation.symbol();
auto res = lookup_symbol(symbol);
VirtualAddress symbol_location;
if (!res.has_value()) {
if (symbol.bind() == STB_WEAK)
return RelocationResult::ResolveLater;
if (symbol.bind() == STB_WEAK) {
if (should_initialize_weak == ShouldInitializeWeak::No)
return RelocationResult::ResolveLater;
} else {
// Symbol not found
return RelocationResult::Failed;
}

// Symbol not found
return RelocationResult::Failed;
}
auto symbol_location = res.value().address;
symbol_location = VirtualAddress { (FlatPtr)0 };
} else
symbol_location = res.value().address;
VERIFY(symbol_location != m_dynamic_object->base_address());
*patch_ptr = symbol_location.get();
break;
Expand Down
7 changes: 6 additions & 1 deletion Userland/Libraries/LibELF/DynamicLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ class LoadedSegment {
size_t m_size;
};

enum class ShouldInitializeWeak {
Yes,
No
};

class DynamicLoader : public RefCounted<DynamicLoader> {
public:
static RefPtr<DynamicLoader> try_create(int fd, String filename);
Expand Down Expand Up @@ -145,7 +150,7 @@ class DynamicLoader : public RefCounted<DynamicLoader> {
Success = 1,
ResolveLater = 2,
};
RelocationResult do_relocation(size_t total_tls_size, const DynamicObject::Relocation&);
RelocationResult do_relocation(size_t total_tls_size, const DynamicObject::Relocation&, ShouldInitializeWeak should_initialize_weak);
size_t calculate_tls_size() const;

String m_filename;
Expand Down

0 comments on commit 1dab5ca

Please sign in to comment.