Browse Source

LibELF: Implement x86_64 relocation support

There are definitely some relocations missing and this is untested
for now.
Gunnar Beutner 4 years ago
parent
commit
a050b43290

+ 6 - 0
Userland/Libraries/LibC/elf.h

@@ -791,3 +791,9 @@ struct elf_args {
 #define R_386_RELATIVE 8   /* Base address + Addned */
 #define R_386_RELATIVE 8   /* Base address + Addned */
 #define R_386_TLS_TPOFF 14 /* Negative offset into the static TLS storage */
 #define R_386_TLS_TPOFF 14 /* Negative offset into the static TLS storage */
 #define R_386_TLS_TPOFF32 37
 #define R_386_TLS_TPOFF32 37
+
+#define R_X86_64_NONE 0
+#define R_X86_64_64 1
+#define R_X86_64_GLOB_DAT 6
+#define R_X86_64_JUMP_SLOT 7
+#define R_X86_64_RELATIVE 8

+ 12 - 0
Userland/Libraries/LibELF/Arch/x86_64/plt_trampoline.S

@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+    .align 4
+    .globl _plt_trampoline
+    .hidden _plt_trampoline
+    .type _plt_trampoline,@function
+_plt_trampoline:
+    int3

+ 20 - 0
Userland/Libraries/LibELF/DynamicLoader.cpp

@@ -398,11 +398,19 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO
         patch_ptr = (FlatPtr*)(FlatPtr)relocation.offset();
         patch_ptr = (FlatPtr*)(FlatPtr)relocation.offset();
 
 
     switch (relocation.type()) {
     switch (relocation.type()) {
+#ifndef __LP64__
     case R_386_NONE:
     case R_386_NONE:
+#else
+    case R_X86_64_NONE:
+#endif
         // Apparently most loaders will just skip these?
         // Apparently most loaders will just skip these?
         // Seems if the 'link editor' generates one something is funky with your code
         // Seems if the 'link editor' generates one something is funky with your code
         break;
         break;
+#ifndef __LP64__
     case R_386_32: {
     case R_386_32: {
+#else
+    case R_X86_64_64: {
+#endif
         auto symbol = relocation.symbol();
         auto symbol = relocation.symbol();
         auto res = lookup_symbol(symbol);
         auto res = lookup_symbol(symbol);
         if (!res.has_value()) {
         if (!res.has_value()) {
@@ -415,6 +423,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO
         *patch_ptr += symbol_address.get();
         *patch_ptr += symbol_address.get();
         break;
         break;
     }
     }
+#ifndef __LP64__
     case R_386_PC32: {
     case R_386_PC32: {
         auto symbol = relocation.symbol();
         auto symbol = relocation.symbol();
         auto result = lookup_symbol(symbol);
         auto result = lookup_symbol(symbol);
@@ -425,6 +434,9 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO
         break;
         break;
     }
     }
     case R_386_GLOB_DAT: {
     case R_386_GLOB_DAT: {
+#else
+    case R_X86_64_GLOB_DAT: {
+#endif
         auto symbol = relocation.symbol();
         auto symbol = relocation.symbol();
         auto res = lookup_symbol(symbol);
         auto res = lookup_symbol(symbol);
         VirtualAddress symbol_location;
         VirtualAddress symbol_location;
@@ -444,13 +456,18 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO
         *patch_ptr = symbol_location.get();
         *patch_ptr = symbol_location.get();
         break;
         break;
     }
     }
+#ifndef __LP64__
     case R_386_RELATIVE: {
     case R_386_RELATIVE: {
+#else
+    case R_X86_64_RELATIVE: {
+#endif
         // FIXME: According to the spec, R_386_relative ones must be done first.
         // FIXME: According to the spec, R_386_relative ones must be done first.
         //     We could explicitly do them first using m_number_of_relocations from DT_RELCOUNT
         //     We could explicitly do them first using m_number_of_relocations from DT_RELCOUNT
         //     However, our compiler is nice enough to put them at the front of the relocations for us :)
         //     However, our compiler is nice enough to put them at the front of the relocations for us :)
         *patch_ptr += (FlatPtr)m_dynamic_object->base_address().as_ptr(); // + addend for RelA (addend for Rel is stored at addr)
         *patch_ptr += (FlatPtr)m_dynamic_object->base_address().as_ptr(); // + addend for RelA (addend for Rel is stored at addr)
         break;
         break;
     }
     }
+#ifndef __LP64__
     case R_386_TLS_TPOFF32:
     case R_386_TLS_TPOFF32:
     case R_386_TLS_TPOFF: {
     case R_386_TLS_TPOFF: {
         auto symbol = relocation.symbol();
         auto symbol = relocation.symbol();
@@ -466,6 +483,9 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO
         break;
         break;
     }
     }
     case R_386_JMP_SLOT: {
     case R_386_JMP_SLOT: {
+#else
+    case R_X86_64_JUMP_SLOT: {
+#endif
         // FIXME: Or BIND_NOW flag passed in?
         // FIXME: Or BIND_NOW flag passed in?
         if (m_dynamic_object->must_bind_now()) {
         if (m_dynamic_object->must_bind_now()) {
             // Eagerly BIND_NOW the PLT entries, doing all the symbol looking goodness
             // Eagerly BIND_NOW the PLT entries, doing all the symbol looking goodness