diff --git a/src/elfs/elfload_dump.c b/src/elfs/elfload_dump.c index 2a8189b58..62cedcf63 100644 --- a/src/elfs/elfload_dump.c +++ b/src/elfs/elfload_dump.c @@ -367,6 +367,18 @@ void DumpRelATable(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name) } } +void DumpRelRTable(elfheader_t *h, int cnt, Elf64_Relr *relr, const char *name) +{ + if(box64_dump && h->relr) { + const char* elfname = ElfName(h); + printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, relr); + for (int i = 0; idelta); + printf_dump(LOG_NEVER, "Apply (even) RELR %p -> %p\n", *where, *where + head->delta); + *where++ += head->delta; + } else { + for (long j = 0; (p >>= 1) != 0; j++) + if ((p & 1) != 0) { + printf_dump(LOG_NEVER, "Apply (odd) RELR %p -> %p\n", where[j], where[j] + head->delta); + where[j] += head->delta; + } + where += CHAR_BIT * sizeof(Elf64_Relr) - 1; + } + } + return 0; +} + int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbind, elfheader_t* head) { if((head->flags&DF_BIND_NOW) && !bindnow) { bindnow = 1; printf_log(LOG_DEBUG, "Forcing %s to Bind Now\n", head->name); } + if(head->relr) { + int cnt = head->relrsz / head->relrent; + DumpRelRTable(head, cnt, (Elf64_Relr *)(head->relr + head->delta), "RelR"); + printf_dump(LOG_DEBUG, "Applying %d Relocation(s) without Addend for %s bindnow=%d, deepbind=%d\n", cnt, head->name, bindnow, deepbind); + if(RelocateElfRELR(head, cnt, (Elf64_Relr *)(head->relr + head->delta))) + return -1; + } if(head->rel) { int cnt = head->relsz / head->relent; DumpRelTable(head, cnt, (Elf64_Rel *)(head->rel + head->delta), "Rel"); diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h index 91b3b5108..d813488ca 100644 --- a/src/elfs/elfloader_private.h +++ b/src/elfs/elfloader_private.h @@ -68,6 +68,9 @@ typedef struct elfheader_s { uintptr_t rela; size_t relasz; int relaent; + uintptr_t relr; + size_t relrsz; + int relrent; uintptr_t jmprel; size_t pltsz; int pltent; diff --git a/src/elfs/elfparser.c b/src/elfs/elfparser.c index fb6e4637f..545503c98 100644 --- a/src/elfs/elfparser.c +++ b/src/elfs/elfparser.c @@ -219,6 +219,15 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec) case DT_RELAENT: h->relaent = val; break; + case DT_RELR: + h->relr = ptr; + break; + case DT_RELRSZ: + h->relrsz = val; + break; + case DT_RELRENT: + h->relrent = val; + break; case DT_PLTGOT: h->pltgot = ptr; break; diff --git a/src/emu/x64int3.c b/src/emu/x64int3.c index b407848c9..836366aa3 100644 --- a/src/emu/x64int3.c +++ b/src/emu/x64int3.c @@ -26,12 +26,12 @@ #include "wrapper.h" #include "box64context.h" #include "librarian.h" -#include "elfload_dump.h" #include "signals.h" #include "tools/bridge_private.h" #include #include "elfloader.h" +#include "elfload_dump.h" #include "elfs/elfloader_private.h" typedef int32_t (*iFpppp_t)(void*, void*, void*, void*); diff --git a/src/include/elfload_dump.h b/src/include/elfload_dump.h index ce0e9c1b1..ad2ecd713 100644 --- a/src/include/elfload_dump.h +++ b/src/include/elfload_dump.h @@ -18,6 +18,7 @@ void DumpDynamicRPath(elfheader_t *h); void DumpDynSym(elfheader_t *h); void DumpRelTable(elfheader_t *h, int cnt, Elf64_Rel *rel, const char* name); void DumpRelATable(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name); +void DumpRelRTable(elfheader_t *h, int cnt, Elf64_Relr *relr, const char *name); void DumpBinary(char* p, int sz); diff --git a/src/include/elfloader.h b/src/include/elfloader.h index ea0928b14..770709c82 100644 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -1,6 +1,7 @@ #ifndef __ELF_LOADER_H_ #define __ELF_LOADER_H_ #include +#include typedef struct elfheader_s elfheader_t; typedef struct lib_s lib_t; @@ -14,6 +15,24 @@ typedef struct kh_defaultversion_s kh_defaultversion_t; typedef struct dynablock_s dynablock_t; #endif +// Define for handling .relr.dyn section (since glibc 2.36) +// See Also https://lists.gnu.org/archive/html/info-gnu/2022-08/msg00000.html +// +// if glibc 2.36 is widely used in the future, this part can be removed +#ifndef DT_RELR + +// Copy from (glibc 2.36) elf.h + +#define SHT_RELR 19 /* RELR relative relocations */ + +typedef Elf32_Word Elf32_Relr; +typedef Elf64_Xword Elf64_Relr; + +#define DT_RELRSZ 35 /* Total size of RELR relative relocations */ +#define DT_RELR 36 /* Address of RELR relative relocations */ +#define DT_RELRENT 37 /* Size of one RELR relative relocaction */ +#endif // DT_RELR + // Open an elfheader. Transfert control of f to elfheader also! elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec void FreeElfHeader(elfheader_t** head);