summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-07-04 00:05:59 +0200
committerAndreas Kling <kling@serenityos.org>2021-07-04 01:07:28 +0200
commit251eaad8f0136cf7d24f7e1b174008c37349c76e (patch)
tree053c4892d9e0d2c570d7623a00cedf6a75328091
parent5f6ee4c539b4ca93b1266b542e83d629e6b9d26c (diff)
downloadserenity-251eaad8f0136cf7d24f7e1b174008c37349c76e.zip
LibELF: Fix relocation support for 'static __thread' variables
-rw-r--r--Userland/Libraries/LibELF/DynamicLoader.cpp22
1 files changed, 14 insertions, 8 deletions
diff --git a/Userland/Libraries/LibELF/DynamicLoader.cpp b/Userland/Libraries/LibELF/DynamicLoader.cpp
index 53fa8fab0e..f802395aa9 100644
--- a/Userland/Libraries/LibELF/DynamicLoader.cpp
+++ b/Userland/Libraries/LibELF/DynamicLoader.cpp
@@ -482,15 +482,21 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO
case R_X86_64_TPOFF64: {
#endif
auto symbol = relocation.symbol();
- // For some reason, LibC has a R_386_TLS_TPOFF that refers to the undefined symbol.. huh
- if (relocation.symbol_index() == 0)
- break;
- auto res = lookup_symbol(symbol);
- if (!res.has_value())
- break;
- auto* dynamic_object_of_symbol = res.value().dynamic_object;
+ FlatPtr symbol_value;
+ DynamicObject const* dynamic_object_of_symbol;
+ if (relocation.symbol_index() != 0) {
+ auto res = lookup_symbol(symbol);
+ if (!res.has_value())
+ break;
+ symbol_value = res.value().value;
+ dynamic_object_of_symbol = res.value().dynamic_object;
+ } else {
+ symbol_value = 0;
+ dynamic_object_of_symbol = &relocation.dynamic_object();
+ }
VERIFY(dynamic_object_of_symbol);
- *patch_ptr = negative_offset_from_tls_block_end(res.value().value, dynamic_object_of_symbol->tls_offset().value());
+ size_t addend = relocation.addend_used() ? relocation.addend() : *patch_ptr;
+ *patch_ptr = negative_offset_from_tls_block_end(symbol_value + addend, dynamic_object_of_symbol->tls_offset().value());
break;
}
#ifndef __LP64__