1 #include <lunaix/common.h>
2 #include <lunaix/elf.h>
5 #include <lunaix/mm/mmap.h>
6 #include <lunaix/mm/valloc.h>
7 #include <lunaix/mm/vmm.h>
8 #include <lunaix/spike.h>
11 __elf_populate_mapped(struct mm_region* region, void* pg, off_t segfoff)
13 size_t segsz = region->flen;
14 size_t segmoff = segfoff - region->foff;
16 if (segmoff >= segsz) {
20 struct v_file* file = region->mfile;
21 size_t rdlen = MIN(segsz - segmoff, PG_SIZE);
23 if (rdlen == PG_SIZE) {
24 // This is because we want to exploit any optimization on read_page
25 return file->ops->read_page(file->inode, pg, PG_SIZE, segfoff);
27 // we don't want to over-read the segment!
28 return file->ops->read(file->inode, pg, rdlen, segfoff);
33 elf_map_segment(struct ld_param* ldparam,
34 struct v_file* elfile,
35 struct elf32_phdr* phdr)
38 if ((phdr->p_flags & PF_R)) {
41 if ((phdr->p_flags & PF_W)) {
44 if ((phdr->p_flags & PF_X)) {
48 struct mm_region* seg_reg;
49 struct mmap_param param = { .vms_mnt = ldparam->vms_mnt,
50 .pvms = &ldparam->proc->mm,
52 .offset = phdr->p_offset,
53 .mlen = ROUNDUP(phdr->p_memsz, PG_SIZE),
54 .flen = phdr->p_filesz,
55 .flags = MAP_FIXED | MAP_PRIVATE,
56 .type = REGION_TYPE_CODE };
58 int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdr->p_va), elfile, ¶m);
61 seg_reg->init_page = __elf_populate_mapped;
63 size_t next_addr = phdr->p_memsz + phdr->p_va;
64 ldparam->info.end = MAX(ldparam->info.end, ROUNDUP(next_addr, PG_SIZE));
65 ldparam->info.mem_sz += phdr->p_memsz;
72 elf_setup_mapping(struct ld_param* ldparam,
73 struct v_file* elfile,
74 struct elf32_ehdr* ehdr)
77 size_t tbl_sz = ehdr->e_phnum * SIZE_PHDR;
78 struct elf32_phdr* phdrs = valloc(tbl_sz);
85 tbl_sz = 1 << ILOG2(tbl_sz);
86 status = elfile->ops->read(elfile->inode, phdrs, tbl_sz, ehdr->e_phoff);
92 if (PG_ALIGN(phdrs[0].p_va) != USER_START) {
97 size_t entries = tbl_sz / SIZE_PHDR;
98 for (size_t i = 0; i < entries; i++) {
99 struct elf32_phdr* phdr = &phdrs[i];
101 if (phdr->p_type == PT_LOAD) {
102 if (phdr->p_align == PG_SIZE) {
103 status = elf_map_segment(ldparam, elfile, phdr);
105 // surprising alignment!
109 // TODO process other types of segments
112 // errno in the middle of mapping restructuring, it is impossible
114 ldparam->status |= LD_STAT_FKUP;
125 elf_load(struct ld_param* ldparam, struct v_file* elfile)
127 struct elf32_ehdr* ehdr = valloc(SIZE_EHDR);
128 int status = elfile->ops->read(elfile->inode, ehdr, SIZE_EHDR, 0);
134 if (!elf_check_exec(ehdr)) {
139 if ((status = elf_setup_mapping(ldparam, elfile, ehdr))) {
143 ldparam->info.ehdr_out = *ehdr;