summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibELF/DynamicLoader.cpp11
-rw-r--r--Userland/Libraries/LibELF/DynamicLoader.h3
2 files changed, 11 insertions, 3 deletions
diff --git a/Userland/Libraries/LibELF/DynamicLoader.cpp b/Userland/Libraries/LibELF/DynamicLoader.cpp
index 8a8fc78732..fc3f3c361b 100644
--- a/Userland/Libraries/LibELF/DynamicLoader.cpp
+++ b/Userland/Libraries/LibELF/DynamicLoader.cpp
@@ -460,10 +460,9 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_si
auto res = lookup_symbol(symbol);
if (!res.has_value())
break;
- u32 symbol_value = res.value().value;
auto* dynamic_object_of_symbol = res.value().dynamic_object;
VERIFY(dynamic_object_of_symbol);
- *patch_ptr = dynamic_object_of_symbol->tls_offset().value() + symbol_value - total_tls_size;
+ *patch_ptr = negative_offset_from_tls_block_end(res.value().value, dynamic_object_of_symbol->tls_offset().value(), total_tls_size);
break;
}
case R_386_JMP_SLOT: {
@@ -488,6 +487,14 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_si
return RelocationResult::Success;
}
+ssize_t DynamicLoader::negative_offset_from_tls_block_end(size_t value_of_symbol, size_t tls_offset, size_t total_tls_size) const
+{
+ auto negative_offset = static_cast<ssize_t>(tls_offset + value_of_symbol - total_tls_size);
+ // Offset has to be strictly negative. Otherwise we'd collide with the thread's ThreadSpecificData structure.
+ VERIFY(negative_offset < 0);
+ return negative_offset;
+}
+
// Defined in <arch>/plt_trampoline.S
extern "C" void _plt_trampoline(void) __attribute__((visibility("hidden")));
diff --git a/Userland/Libraries/LibELF/DynamicLoader.h b/Userland/Libraries/LibELF/DynamicLoader.h
index e39db15416..6c3b136477 100644
--- a/Userland/Libraries/LibELF/DynamicLoader.h
+++ b/Userland/Libraries/LibELF/DynamicLoader.h
@@ -130,6 +130,7 @@ private:
};
RelocationResult do_relocation(size_t total_tls_size, const DynamicObject::Relocation&, ShouldInitializeWeak should_initialize_weak);
size_t calculate_tls_size() const;
+ ssize_t negative_offset_from_tls_block_end(size_t value_of_symbol, size_t tls_offset, size_t total_tls_size) const;
String m_filename;
String m_program_interpreter;
@@ -150,7 +151,7 @@ private:
VirtualAddress m_dynamic_section_address;
size_t m_tls_offset { 0 };
- size_t m_tls_size { 0 };
+ size_t m_tls_size { 0 }; // TLS size of the current object
Vector<DynamicObject::Relocation> m_unresolved_relocations;