diff options
author | dzwdz | 2023-08-14 18:51:07 +0200 |
---|---|---|
committer | dzwdz | 2023-08-14 18:51:07 +0200 |
commit | 642b5fb0007b64c77d186fcb018d571152ee1d47 (patch) | |
tree | 1c466461f3602d306be309a053edae558ef2568e /src/libc/elfreloc.c | |
parent | 8050069c57b729c18c19b1a03ab6e4bf63b4735e (diff) |
reorganization: first steps
Diffstat (limited to 'src/libc/elfreloc.c')
-rw-r--r-- | src/libc/elfreloc.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/libc/elfreloc.c b/src/libc/elfreloc.c new file mode 100644 index 0000000..aab2a2a --- /dev/null +++ b/src/libc/elfreloc.c @@ -0,0 +1,39 @@ +#include <stdio.h> +#include "elf.h" + +__attribute__((visibility("hidden"))) +extern struct Elf64_Dyn _DYNAMIC[]; + +__attribute__((visibility("hidden"))) +extern char __executable_start[]; + +static struct Elf64_Dyn *dyn_gettag(Elf64_Xword tag) { + for (size_t i = 0;; i++) { + if (_DYNAMIC[i].d_tag == tag) return &_DYNAMIC[i]; + if (_DYNAMIC[i].d_tag == DT_NULL) return NULL; + } +} + +void elf_selfreloc(void) { + // TODO DT_REL, DT_JMPREL + + struct Elf64_Dyn *rela_tag = dyn_gettag(DT_RELA); + if (rela_tag) { + /* not checking pointer validity, + * crashing on an invalid elf is fine */ + size_t relasz = dyn_gettag(DT_RELASZ)->d_val; + size_t relaent = dyn_gettag(DT_RELAENT)->d_val; + for (size_t o = 0; o < relasz; o += relaent) { + struct Elf64_Rela *r = (void*)__executable_start + rela_tag->d_ptr + o; + uintptr_t *target = (void*)__executable_start + r->r_offset; + + switch (ELF64_R_TYPE(r->r_info)) { + case R_X86_64_RELATIVE: + *target = (uintptr_t)&__executable_start + r->r_addend; + break; + default: + _klogf("elf: unsupported relocation type\n"); + } + } + } +} |