From 9b9cc76b1d0389dc24f278044bbbe8fb6d83a766 Mon Sep 17 00:00:00 2001 From: Daniel Bertalan Date: Sat, 22 Apr 2023 14:57:30 +0200 Subject: [PATCH] LibELF: Add AArch64 PLT trampoline This is used for lazy symbol binding, which is used by e.g. ports that are not linked with `-z now`. --- .../LibELF/Arch/aarch64/plt_trampoline.S | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibELF/Arch/aarch64/plt_trampoline.S b/Userland/Libraries/LibELF/Arch/aarch64/plt_trampoline.S index 016266f2c8..b2c5dfd35b 100644 --- a/Userland/Libraries/LibELF/Arch/aarch64/plt_trampoline.S +++ b/Userland/Libraries/LibELF/Arch/aarch64/plt_trampoline.S @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Nico Weber + * Copyright (c) 2023, Daniel Bertalan * * SPDX-License-Identifier: BSD-2-Clause */ @@ -8,6 +9,63 @@ .globl _plt_trampoline .hidden _plt_trampoline .type _plt_trampoline,@function -_plt_trampoline: # (object, relocation_index) - # FIXME: Possibly incomplete. - ret + +// This function is called by the PLT stub to resolve functions lazily at runtime. +// It saves off any argument registers that might be clobbered by the symbol +// resolution code, calls that, and then jumps to the resolved function. +// +// See section 9.3 "Procedure Linkage Table" of the AArch64 ELF ABI. +// https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst +// +// The calling convention is: +// x16 = &got.plt[2] +// x17 = &_plt_trampoline +// [sp, #0] = &got.plt[relocation_index + 3] +// [sp, #8] = return address +_plt_trampoline: + mov x17, sp + + // Save argument registers: x0-x7, v0-v7. + stp x0, x1, [sp, #-16]! + stp x2, x3, [sp, #-16]! + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + stp q0, q1, [sp, #-32]! + stp q2, q3, [sp, #-32]! + stp q4, q5, [sp, #-32]! + stp q6, q7, [sp, #-32]! + + // Load DynamicObject* from got.plt[1]. + ldr x0, [x16, #-8] + + // Calculate the rela.plt relocation offset. + ldr x2, [x17] + sub x1, x2, x16 + sub x1, x1, #8 + // GOT entries are 8 bytes, but sizeof(Elf64_Rela) == 24, so multiply + // by 3 to get the relocation offset. + add x1, x1, x1, lsl #1 + + bl _fixup_plt_entry + + // Save the resolved function's address. + mov x16, x0 + + // Restore argument registers. + ldp q6, q7, [sp], #32 + ldp q4, q5, [sp], #32 + ldp q2, q3, [sp], #32 + ldp q0, q1, [sp], #32 + + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + ldp x2, x3, [sp], #16 + ldp x0, x1, [sp], #16 + + // Restore link register saved by the PLT stub. + ldp xzr, x30, [sp], #16 + + // Jump to the resolved function. + br x16 +