Browse Source

LibELF: Extract TLS offset calculation logic to separate function

Itamar 4 years ago
parent
commit
1c24388d74

+ 9 - 2
Userland/Libraries/LibELF/DynamicLoader.cpp

@@ -460,10 +460,9 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_si
         auto res = lookup_symbol(symbol);
         auto res = lookup_symbol(symbol);
         if (!res.has_value())
         if (!res.has_value())
             break;
             break;
-        u32 symbol_value = res.value().value;
         auto* dynamic_object_of_symbol = res.value().dynamic_object;
         auto* dynamic_object_of_symbol = res.value().dynamic_object;
         VERIFY(dynamic_object_of_symbol);
         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;
         break;
     }
     }
     case R_386_JMP_SLOT: {
     case R_386_JMP_SLOT: {
@@ -488,6 +487,14 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(size_t total_tls_si
     return RelocationResult::Success;
     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
 // Defined in <arch>/plt_trampoline.S
 extern "C" void _plt_trampoline(void) __attribute__((visibility("hidden")));
 extern "C" void _plt_trampoline(void) __attribute__((visibility("hidden")));
 
 

+ 2 - 1
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);
     RelocationResult do_relocation(size_t total_tls_size, const DynamicObject::Relocation&, ShouldInitializeWeak should_initialize_weak);
     size_t calculate_tls_size() const;
     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_filename;
     String m_program_interpreter;
     String m_program_interpreter;
@@ -150,7 +151,7 @@ private:
     VirtualAddress m_dynamic_section_address;
     VirtualAddress m_dynamic_section_address;
 
 
     size_t m_tls_offset { 0 };
     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;
     Vector<DynamicObject::Relocation> m_unresolved_relocations;