From d3127efc014baf2417b83a3298c155fd8b9da029 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 29 Jun 2021 17:43:08 +0200 Subject: [PATCH] LibELF: Implement PLT relocations for x86_64 --- .../LibELF/Arch/x86_64/plt_trampoline.S | 41 ++++++++++++++++++- Userland/Libraries/LibELF/DynamicLoader.cpp | 2 +- Userland/Libraries/LibELF/DynamicObject.cpp | 4 ++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibELF/Arch/x86_64/plt_trampoline.S b/Userland/Libraries/LibELF/Arch/x86_64/plt_trampoline.S index b3d3125ca96..5d3c12b1841 100644 --- a/Userland/Libraries/LibELF/Arch/x86_64/plt_trampoline.S +++ b/Userland/Libraries/LibELF/Arch/x86_64/plt_trampoline.S @@ -8,5 +8,42 @@ .globl _plt_trampoline .hidden _plt_trampoline .type _plt_trampoline,@function -_plt_trampoline: - int3 +_plt_trampoline: # (object, relocation_index) + # save flags/registers (https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call) + pushfq + pushq %rax + pushq %rcx + pushq %rdx + pushq %rsi + pushq %rdi + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + + movq 80(%rsp), %rdi # object + movq 88(%rsp), %rsi # relocation_index + + # offset = index * sizeof(Elf64_Rela) + shlq $3, %rsi + leaq (%rsi, %rsi, 2), %rsi + + call _fixup_plt_entry@PLT + + movq %rax, 88(%rsp) # replace object argument with symbol address + + # restore flags/registers + popq %r11 + popq %r10 + popq %r9 + popq %r8 + popq %rdi + popq %rsi + popq %rdx + popq %rcx + popq %rax + popfq + + addq $8, %rsp # remove relocation_index argument + + retq diff --git a/Userland/Libraries/LibELF/DynamicLoader.cpp b/Userland/Libraries/LibELF/DynamicLoader.cpp index e471f941b36..9aa2c7f8f10 100644 --- a/Userland/Libraries/LibELF/DynamicLoader.cpp +++ b/Userland/Libraries/LibELF/DynamicLoader.cpp @@ -506,7 +506,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO u8* relocation_address = relocation.address().as_ptr(); if (m_elf_image.is_dynamic()) - *(u32*)relocation_address += (FlatPtr)m_dynamic_object->base_address().as_ptr(); + *(FlatPtr*)relocation_address += (FlatPtr)m_dynamic_object->base_address().as_ptr(); } break; } diff --git a/Userland/Libraries/LibELF/DynamicObject.cpp b/Userland/Libraries/LibELF/DynamicObject.cpp index 1f2bc7d015e..65b10d7bab8 100644 --- a/Userland/Libraries/LibELF/DynamicObject.cpp +++ b/Userland/Libraries/LibELF/DynamicObject.cpp @@ -449,7 +449,11 @@ NonnullRefPtr DynamicObject::create(const String& filename, Virtu VirtualAddress DynamicObject::patch_plt_entry(u32 relocation_offset) { auto relocation = plt_relocation_section().relocation_at_offset(relocation_offset); +#if ARCH(I386) VERIFY(relocation.type() == R_386_JMP_SLOT); +#else + VERIFY(relocation.type() == R_X86_64_JUMP_SLOT); +#endif auto symbol = relocation.symbol(); u8* relocation_address = relocation.address().as_ptr();