X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/b8d37199feb1369c445e3b0fe1fb9171218a0e14..b6ff3c7dbab3f40d03389808d95ac27d416c35e3:/lunaix-os/kernel/exe/elf32/ldelf32.c diff --git a/lunaix-os/kernel/exe/elf32/ldelf32.c b/lunaix-os/kernel/exe/elf32/ldelf32.c new file mode 100644 index 0000000..1204be4 --- /dev/null +++ b/lunaix-os/kernel/exe/elf32/ldelf32.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include + +int +elf32_smap(struct load_context* ldctx, + const struct elf32* elf, + struct elf32_phdr* phdre) +{ + struct v_file* elfile = (struct v_file*)elf->elf_file; + + assert(PG_ALIGNED(phdre->p_offset)); + + int proct = 0; + if ((phdre->p_flags & PF_R)) { + proct |= PROT_READ; + } + if ((phdre->p_flags & PF_W)) { + proct |= PROT_WRITE; + } + if ((phdre->p_flags & PF_X)) { + proct |= PROT_EXEC; + } + + struct exec_container* container = ldctx->container; + struct mmap_param param = { .vms_mnt = container->vms_mnt, + .pvms = &container->proc->mm, + .proct = proct, + .offset = PG_ALIGN(phdre->p_offset), + .mlen = ROUNDUP(phdre->p_memsz, PG_SIZE), + .flen = phdre->p_filesz + PG_MOD(phdre->p_va), + .flags = MAP_FIXED | MAP_PRIVATE, + .type = REGION_TYPE_CODE }; + + struct mm_region* seg_reg; + int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdre->p_va), elfile, ¶m); + + if (!status) { + size_t next_addr = phdre->p_memsz + phdre->p_va; + ldctx->end = MAX(ldctx->end, ROUNDUP(next_addr, PG_SIZE)); + ldctx->mem_sz += phdre->p_memsz; + } else { + // we probably fucked up our process + terminate_proc(-1); + } + + return status; +} + +int +load_executable(struct load_context* context, const struct v_file* exefile) +{ + int errno = 0; + + char* ldpath = NULL; + struct elf32 elf; + struct exec_container* container = context->container; + + if ((errno = elf32_openat(&elf, exefile))) { + goto done; + } + + if (!elf32_check_exec(&elf)) { + errno = ENOEXEC; + goto done; + } + + ldpath = valloc(512); + errno = elf32_find_loader(&elf, ldpath, 512); + + if (errno < 0) { + goto done; + } + + if (errno != NO_LOADER) { + container->argv_pp[1] = ldpath; + + // close old elf + if ((errno = elf32_close(&elf))) { + goto done; + } + + // open the loader instead + if ((errno = elf32_open(&elf, ldpath))) { + goto done; + } + + // Is this the valid loader? + if (!elf32_static_linked(&elf) || !elf32_check_exec(&elf)) { + errno = ELIBBAD; + goto done_close_elf32; + } + + // TODO: relocate loader + } else { + context->entry = elf.eheader.e_entry; + } + + struct v_file* elfile = (struct v_file*)elf.elf_file; + + for (size_t i = 0; i < elf.eheader.e_phnum && !errno; i++) { + struct elf32_phdr* phdr = &elf.pheaders[i]; + + if (phdr->p_type == PT_LOAD) { + if (phdr->p_align != PG_SIZE) { + // surprising alignment! + errno = ENOEXEC; + continue; + } + + errno = elf32_smap(context, &elf, phdr); + } + // TODO Handle relocation + } + +done_close_elf32: + elf32_close(&elf); +done: + vfree_safe(ldpath); + return errno; +}