diff options
| author | Ada Christine <adachristine18@gmail.com> | 2021-12-19 22:41:15 +0000 |
|---|---|---|
| committer | Ada Christine <adachristine18@gmail.com> | 2021-12-19 22:41:15 +0000 |
| commit | e303a03e7c96bc5bf7fa93f7b46ce63196893d7a (patch) | |
| tree | f187b374feec85015d6df1f94db618a3f5cc893f /kc/reloc_x86_64.c | |
| parent | bff63a4337eb3388617d230970c5eb2684d6a215 (diff) | |
moving files around
Diffstat (limited to 'kc/reloc_x86_64.c')
| -rw-r--r-- | kc/reloc_x86_64.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/kc/reloc_x86_64.c b/kc/reloc_x86_64.c new file mode 100644 index 0000000..0204700 --- /dev/null +++ b/kc/reloc_x86_64.c @@ -0,0 +1,69 @@ +#include <kernel/component.h> + +#include <elf/elf64.h> + +#include <stddef.h> + +#define STARTCODE __attribute__((section(".text.start"))) + +STARTCODE +static void do_rela(Elf64_Rela *rela, void *base) +{ + union + { + Elf_Byte word8; + Elf64_Half word16; + Elf64_Word word32; + Elf64_Xword word64; + } + *fixup; + + switch (ELF64_R_TYPE(rela->r_info)) + { + case R_AMD64_RELATIVE: + fixup = (void *)(rela->r_offset + (uintptr_t)base); + fixup->word64 = (rela->r_addend + (uintptr_t)base); + break; + default: + break; + } +} + +STARTCODE +void kc_reloc(Elf64_Dyn *dyn, void *base) +{ + struct + { + Elf64_Rela *entries; + size_t *size; + size_t *entsize; + } + rela = {NULL, NULL, NULL}; + + // parse the dynamic segment + while (dyn && dyn++->d_tag != DT_NULL) + { + switch (dyn->d_tag) + { + case DT_RELA: + rela.entries = (Elf64_Rela *)(dyn->d_ptr + (uintptr_t)base); + break; + case DT_RELASZ: + rela.size = &dyn->d_val; + break; + case DT_RELAENT: + rela.entsize = &dyn->d_val; + break; + default: + break; + } + } + + // perform the actual relocation + + for (size_t i = 0; rela.entries && (i < *rela.size / *rela.entsize); i++) + { + do_rela(&rela.entries[i], base); + } +} + |
