diff options
author | dzwdz | 2022-07-23 18:20:06 +0200 |
---|---|---|
committer | dzwdz | 2022-07-23 18:20:06 +0200 |
commit | 3badc5ac30fcc0836a2604146788158b16b64f2d (patch) | |
tree | a05a6c7501119b779191414a2a6265382574732d /src/user/lib | |
parent | cd12cbc75564fafd9c2519cdf1085e651c9d7cfd (diff) |
init: compile as an elf
Diffstat (limited to 'src/user/lib')
-rw-r--r-- | src/user/lib/elfload.c | 1 | ||||
-rw-r--r-- | src/user/lib/elfload.h | 2 | ||||
-rw-r--r-- | src/user/lib/elfreloc.c | 42 |
3 files changed, 45 insertions, 0 deletions
diff --git a/src/user/lib/elfload.c b/src/user/lib/elfload.c index c32232e..6c75268 100644 --- a/src/user/lib/elfload.c +++ b/src/user/lib/elfload.c @@ -76,6 +76,7 @@ void elf_exec(void *base) { struct Elf64_Ehdr *ehdr = base; void *exebase; if (!valid_ehdr(ehdr)) return; + _syscall_debug_klog("here", 4); size_t spread = elf_spread(base); switch (ehdr->e_type) { case ET_EXEC: diff --git a/src/user/lib/elfload.h b/src/user/lib/elfload.h index c6afbdd..f79be6e 100644 --- a/src/user/lib/elfload.h +++ b/src/user/lib/elfload.h @@ -3,3 +3,5 @@ void elf_execf(libc_file *f); void elf_exec(void *elf); + +void elf_selfreloc(void); // elfreloc.c diff --git a/src/user/lib/elfreloc.c b/src/user/lib/elfreloc.c new file mode 100644 index 0000000..550fe97 --- /dev/null +++ b/src/user/lib/elfreloc.c @@ -0,0 +1,42 @@ +#include <user/lib/elf.h> +#include <user/lib/stdlib.h> + +__attribute__((visibility("hidden"))) +extern struct Elf64_Dyn _DYNAMIC[]; + +__attribute__((visibility("hidden"))) +extern char _image_base[]; + +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 + if (dyn_gettag(DT_PLTGOT) || dyn_gettag(DT_JMPREL)) { + _klogf("elf: unimplemented tag in _DYNAMIC\n"); + } + + 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*)_image_base + rela_tag->d_ptr + o; + uintptr_t *target = (void*)_image_base + r->r_offset; + + switch (ELF64_R_TYPE(r->r_info)) { + case R_X86_64_RELATIVE: + *target = (uintptr_t)&_image_base + r->r_addend; + break; + default: + _klogf("elf: unsupported relocation type\n"); + } + } + } +} |