summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/user/lib/elfload.c28
-rw-r--r--src/usertestelf.c64
-rw-r--r--src/usertestelf.ld2
3 files changed, 84 insertions, 10 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);
}
diff --git a/src/usertestelf.c b/src/usertestelf.c
index 19f0096..c3ab289 100644
--- a/src/usertestelf.c
+++ b/src/usertestelf.c
@@ -1,6 +1,68 @@
+#include <shared/printf.h>
+#include <user/lib/elf.h>
#include <user/lib/syscall.c>
+const char *str = "Hello!\n", *str2 = "World.\n";
+
+__attribute__((visibility("hidden")))
+extern struct Elf64_Dyn _DYNAMIC[];
+
+__attribute__((visibility("hidden")))
+extern char _image_base;
+
+static void printf_backend(void *arg, const char *buf, size_t len) {
+ (void)arg;
+ _syscall_write(1, buf, len, -1);
+}
+
+int printf(const char *fmt, ...) {
+ int ret = 0;
+ va_list argp;
+ va_start(argp, fmt);
+ ret = __printf_internal(fmt, argp, printf_backend, 0);
+ va_end(argp);
+ return ret;
+}
+
+
+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;
+ }
+}
+
+static void reloc(void) {
+ printf("hi?\n");
+ // TODO DT_REL
+ if (dyn_gettag(DT_PLTGOT) || dyn_gettag(DT_JMPREL)) {
+ printf("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 = &_image_base + rela_tag->d_ptr + o;
+ uintptr_t *target = &_image_base + r->r_offset;
+
+ switch (ELF64_R_TYPE(r->r_info)) {
+ case R_X86_64_RELATIVE:
+ *target = &_image_base + r->r_addend;
+ break;
+ default:
+ printf("elf: unsupported relocation type\n");
+ }
+ }
+ }
+}
+
int main(void) {
- _syscall_write(1, "Hello!", 6, 0);
+ reloc();
+ printf(str);
+ printf(str2);
_syscall_exit(0);
}
diff --git a/src/usertestelf.ld b/src/usertestelf.ld
index 2567f77..fcb5fc8 100644
--- a/src/usertestelf.ld
+++ b/src/usertestelf.ld
@@ -2,7 +2,7 @@ ENTRY(main)
SECTIONS
{
- . = 8M;
+ _image_base = .;
.text BLOCK(4K) : ALIGN(4K)
{
*(.text)