From 74804c5bd9b99c54844e0819eec0052e7a0aae92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Fri, 27 Dec 2024 21:24:56 +0100 Subject: [PATCH] rtld: add rudimentary support for procedure linkage tables (plt) --- crt/elf.h | 14 ++++++++------ crt/rtld_payload.c | 27 ++++++++++++++++++++++++++- crt/rtld_so.c | 24 ++++++++++++++++++++++++ host/bin/prospero-clang | 2 +- host/bin/prospero-clang++ | 2 +- host/elf_x86_64.x | 8 +++++++- 6 files changed, 67 insertions(+), 10 deletions(-) diff --git a/crt/elf.h b/crt/elf.h index bbafc42..a8b1ceb 100644 --- a/crt/elf.h +++ b/crt/elf.h @@ -20,12 +20,14 @@ along with this program; see the file COPYING. If not, see #define PT_LOAD 1 #define PT_DYNAMIC 2 -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_JMPREL 23 #define DT_GNU_HASH 0x6ffffef5 #define R_X86_64_64 1 diff --git a/crt/rtld_payload.c b/crt/rtld_payload.c index a390d53..015a025 100644 --- a/crt/rtld_payload.c +++ b/crt/rtld_payload.c @@ -244,8 +244,10 @@ dynsym_count(unsigned int *gnu_hash) { static int payload_load(void) { unsigned int *gnu_hash = 0; + unsigned long relasz = 0; + unsigned long pltsz = 0; Elf64_Rela* rela = 0; - long relasz = 0; + Elf64_Rela* plt = 0; // find lookup tables for(int i=0; _DYNAMIC[i].d_tag!=DT_NULL; i++) { @@ -269,6 +271,14 @@ payload_load(void) { case DT_RELASZ: relasz = _DYNAMIC[i].d_un.d_val; break; + + case DT_JMPREL: + plt = (Elf64_Rela*)(__image_start + _DYNAMIC[i].d_un.d_ptr); + break; + + case DT_PLTRELSZ: + pltsz = _DYNAMIC[i].d_un.d_val; + break; } } @@ -322,6 +332,21 @@ payload_load(void) { } } + for(int i=0; istrtab = (char*)(lib->image + lib->phdr->p_offset + dyn[i].d_un.d_ptr); break; + + case DT_JMPREL: + lib->plt = (Elf64_Rela*)(lib->image + lib->phdr->p_offset + + dyn[i].d_un.d_ptr); + break; + + case DT_PLTRELSZ: + lib->plt_size = dyn[i].d_un.d_val; + break; } } @@ -643,6 +652,21 @@ so_load(rtld_so_lib_t* lib, const char* path) { } } + for(int i=0; iplt_size/sizeof(Elf64_Rela); i++) { + switch(lib->plt[i].r_info & 0xffffffffl) { + case R_X86_64_JMP_SLOT: + if(r_jmp_slot(lib, &lib->plt[i])) { + return -1; + } + break; + + default: + klog_printf("Unsupported plt relocation type %x\n", + lib->plt[i].r_info); + break; + } + } + // set protection bits on mapped memory for(int i=0; iehdr->e_phnum && !error; i++) { if(lib->phdr[i].p_type != PT_LOAD || lib->phdr[i].p_memsz == 0) { diff --git a/host/bin/prospero-clang b/host/bin/prospero-clang index f5afe07..8eb7e8b 100755 --- a/host/bin/prospero-clang +++ b/host/bin/prospero-clang @@ -67,7 +67,7 @@ exec -a "${SCRIPT_NAME}" "${SCRIPT_DIR}/clang" \ -isystem "${PS5_PAYLOAD_SDK}/target/include" \ -L "${PS5_PAYLOAD_SDK}/target/lib" \ -L "${PS5_PAYLOAD_HBROOT}/lib" \ - -fno-stack-protector -fno-plt -femulated-tls \ + -fno-stack-protector -femulated-tls \ $LIBS_C \ --end-no-unused-arguments \ "$@" \ diff --git a/host/bin/prospero-clang++ b/host/bin/prospero-clang++ index 3a93c5b..6722de6 100755 --- a/host/bin/prospero-clang++ +++ b/host/bin/prospero-clang++ @@ -73,7 +73,7 @@ exec -a "${SCRIPT_NAME}" "${SCRIPT_DIR}/clang++" \ -stdlib++-isystem "${PS5_PAYLOAD_SDK}/target/include/c++/v1" \ -L "${PS5_PAYLOAD_SDK}/target/lib" \ -L "${PS5_PAYLOAD_HBROOT}/lib" \ - -fno-stack-protector -fno-plt -femulated-tls \ + -fno-stack-protector -femulated-tls \ -frtti -fexceptions \ $LIBS_CXX $LIBS_C \ --end-no-unused-arguments \ diff --git a/host/elf_x86_64.x b/host/elf_x86_64.x index 500ba80..10c357d 100644 --- a/host/elf_x86_64.x +++ b/host/elf_x86_64.x @@ -33,6 +33,8 @@ SECTIONS { PROVIDE_HIDDEN (__text_end = .); } : ph_text + .plt : { *(.plt) } + .rodata : ALIGN(CONSTANT(MAXPAGESIZE)) { *(.rodata .rodata.*) @@ -47,6 +49,8 @@ SECTIONS { PROVIDE_HIDDEN(__fini_array_end = .); } : ph_rodata + .gcc_except_table : { *(.gcc_except_table*) } + .eh_frame_hdr : ALIGN(CONSTANT(MAXPAGESIZE)) { PROVIDE_HIDDEN(__eh_frame_hdr_start = .); KEEP(*(.eh_frame_hdr)) @@ -59,7 +63,9 @@ SECTIONS { PROVIDE_HIDDEN(__eh_frame_end = .); } - .rela : { *(.rela *.rela.*) } + .data.rel.ro : { *(.data.rel.ro .data.rel.ro.*); } + .got : { *(.got) } + .got.plt : { *(.got.plt) } .data : ALIGN(CONSTANT(MAXPAGESIZE)) { *(.data .data.*)