diff options
| author | Yip Coekjan <69834864+Coekjan@users.noreply.github.com> | 2024-07-02 19:47:48 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-02 13:47:48 +0200 |
| commit | 9cd8812d8b2b1648a40c05e02787c375d5ce5cd4 (patch) | |
| tree | c9be3f2f7692387ec8e28d6eb5f0bfd0afb6a3ca /src/elfs | |
| parent | 4b0b3fc98ae4a1e848765e0cd48f958a13fc683d (diff) | |
| download | box64-9cd8812d8b2b1648a40c05e02787c375d5ce5cd4.tar.gz box64-9cd8812d8b2b1648a40c05e02787c375d5ce5cd4.zip | |
Handle `.relr.dyn` section (#1626)
Diffstat (limited to 'src/elfs')
| -rw-r--r-- | src/elfs/elfload_dump.c | 12 | ||||
| -rw-r--r-- | src/elfs/elfloader.c | 28 | ||||
| -rw-r--r-- | src/elfs/elfloader_private.h | 3 | ||||
| -rw-r--r-- | src/elfs/elfparser.c | 9 |
4 files changed, 52 insertions, 0 deletions
diff --git a/src/elfs/elfload_dump.c b/src/elfs/elfload_dump.c index 2a8189b5..62cedcf6 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; i<cnt; ++i) + printf_dump(LOG_NEVER, " %s:%s[%d] = %p\n", elfname, name, + i, (void*)relr[i]); + printf_dump(LOG_NEVER, "ELF Dump %s Table=====\n", name); + } +} + void DumpBinary(char* p, int sz) { // dump p as diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index efb0ef57..fab47ad6 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -784,12 +784,40 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, int deepbin } return bindnow?ret_ok:0; } + +int RelocateElfRELR(elfheader_t *head, int cnt, Elf64_Relr *relr) { + Elf64_Addr *where = NULL; + for (int i = 0; i < cnt; i++) { + Elf64_Relr p = relr[i]; + if ((p & 1) == 0) { + where = (Elf64_Addr *)(p + head->delta); + 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 91b3b510..d813488c 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 fb6e4637..545503c9 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; |