From d98ec57128628b81fcd32269a92742a037b7f713 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 26 Dec 2021 17:50:11 +0200 Subject: First useful jump to userspace! --- common/elf.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 7 deletions(-) (limited to 'common/elf.c') diff --git a/common/elf.c b/common/elf.c index c6a37e0..c73d56c 100644 --- a/common/elf.c +++ b/common/elf.c @@ -1,12 +1,83 @@ #include #include +#include +#include -vm_t bin_entry(vm_t bin) +static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart, size_t phnum, size_t phsize) { - struct elf_header *e = (struct elf_header *)bin; - /* TODO: check that address points to a valid ELF executable */ - /* oh yeah, this only works for DYN objects, fuck */ - /* eh, fuck it, I'll fix this later, today has been a decently - * productive day as is */ - return ((vm_t)e->e_entry) + bin; + /* TODO: take alignment into consideration? */ + vm_t runner = phstart; + for(size_t i = 0; i < phnum; ++i, runner += phsize){ + if(program_header_prop(ei_c, runner, p_type) != PT_LOAD) + continue; + + vm_t va = program_header_prop(ei_c, runner, p_vaddr); + size_t vsz = program_header_prop(ei_c, runner, p_memsz); + + vm_t start = 0; + if(!(start = alloc_fixed_region(&t->sp_r, va, vsz, 0))) + return; /* out of memory or something */ + + uint8_t vflags = VM_V | VM_U; + uint8_t bflags = program_header_prop(ei_c, runner, p_flags); + if(bflags & PF_X) + vflags |= VM_X; + + if(bflags & PF_W) + vflags |= VM_W; + + if(bflags & PF_R) + vflags |= VM_R; + + map_fill_region(t->b_r, start, vsz, VM_V | VM_X | VM_R | VM_W | VM_U); + + vm_t vo = bin + program_header_prop(ei_c, runner, p_offset); + vm_t vfz = program_header_prop(ei_c, runner, p_filesz); + memcpy((void *)va, (void *)vo, vfz); + + /* skip while testing + pm_t paddr = 0; + stat_vmem(t->b_r, va, &paddr, 0, 0); + mod_vmem(t->b_r, va, paddr, vflags); + */ + } +} + +static vm_t __map_dyn(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart, size_t phnum, size_t phsize) +{ + /* TODO */ +} + +static vm_t __prepare_proc(struct tcb *t, uint8_t ei_c, vm_t elf) +{ + short e_type = elf_header_prop(ei_c, elf, e_type); + if(e_type != ET_DYN && e_type != ET_EXEC) + return 0; + + vm_t phstart = ptradd(elf, elf_header_prop(ei_c, elf, e_phoff)); + size_t phnum = elf_header_prop(ei_c, elf, e_phnum); + size_t phsize = elf_header_prop(ei_c, elf, e_phentsize); + + vm_t entry = elf_header_prop(ei_c, elf, e_entry); + if(e_type == ET_EXEC){ + __map_exec(t, elf, ei_c, phstart, phnum, phsize); + return entry; + } else { + vm_t o = __map_dyn(t, elf, ei_c, phstart, phnum, phsize); + return o + entry; + } +} + +/* sets up all memory regions etc, returns the entry address */ +vm_t prepare_proc(struct tcb *t, vm_t p) +{ + struct elf_ident *i = (struct elf_ident *)p; + if(i->ei_magic != cpu_to_be32(EI_MAGIC)) + return 0; + + if(i->ei_class != ELFCLASS32 && i->ei_class != ELFCLASS64) + return 0; + + /* more sanity checks? */ + return __prepare_proc(t, i->ei_class, p); } -- cgit v1.3