summaryrefslogtreecommitdiff
path: root/src/user/lib
diff options
context:
space:
mode:
authordzwdz2022-07-18 18:06:20 +0200
committerdzwdz2022-07-18 18:06:20 +0200
commit9a41e57c2edeb32ae3cd530e761133883d491075 (patch)
tree93ceacff188cf382e8c2a8c61ddf99b82a21d0d3 /src/user/lib
parentd43c1af88b1834a00f8b5f09aa0af1a5e4f5b4aa (diff)
user: basic elf relocations, PIE support
Diffstat (limited to 'src/user/lib')
-rw-r--r--src/user/lib/elfload.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/src/user/lib/elfload.c b/src/user/lib/elfload.c
index 67cef68..deb7b44 100644
--- a/src/user/lib/elfload.c
+++ b/src/user/lib/elfload.c
@@ -26,14 +26,15 @@ static bool valid_ehdr(const struct Elf64_Ehdr *h) {
&& h->e_ident[1] == 'E'
&& h->e_ident[2] == 'L'
&& h->e_ident[3] == 'F'
- && h->e_type == ET_EXEC
&& h->e_machine == EM_X86_64
&& h->e_version == 1;
}
-static bool load_phdr(const void *base, size_t idx) {
- const struct Elf64_Ehdr *ehdr = base;
- const struct Elf64_Phdr *phdr = base + ehdr->e_phoff + idx * ehdr->e_phentsize;
+static bool load_phdr(const void *elf, void *exebase, size_t idx) {
+ const struct Elf64_Ehdr *ehdr = elf;
+ const struct Elf64_Phdr *phdr = elf + ehdr->e_phoff + idx * ehdr->e_phentsize;
+
+ if (phdr->p_type == PT_DYNAMIC) return true;
if (phdr->p_type != PT_LOAD) {
printf("unknown type %x\n", phdr->p_type);
@@ -41,19 +42,30 @@ static bool load_phdr(const void *base, size_t idx) {
}
// TODO overlap check
// TODO don't ignore flags
- _syscall_memflag((void*)phdr->p_vaddr, phdr->p_memsz, MEMFLAG_PRESENT);
+ _syscall_memflag(exebase + phdr->p_vaddr, phdr->p_memsz, MEMFLAG_PRESENT);
// TODO check that filesz <= memsz
- memcpy((void*)phdr->p_vaddr, base + phdr->p_offset, phdr->p_filesz);
+ memcpy(exebase + phdr->p_vaddr, elf + phdr->p_offset, phdr->p_filesz);
return true;
}
void elf_exec(void *base) {
struct Elf64_Ehdr *ehdr = base;
+ void *exebase;
if (!valid_ehdr(ehdr)) return;
+ switch (ehdr->e_type) {
+ case ET_EXEC:
+ exebase = (void*)0;
+ break;
+ case ET_DYN:
+ exebase = (void*)0x800000; // TODO search for free memory
+ break;
+ default:
+ return;
+ }
for (size_t phi = 0; phi < ehdr->e_phnum; phi++) {
- if (!load_phdr(base, phi))
+ if (!load_phdr(base, exebase, phi))
return;
}
- ((void(*)())ehdr->e_entry)();
+ ((void(*)())exebase + ehdr->e_entry)();
_syscall_exit(1);
}