1 #include <klibc/string.h>
2 #include <lunaix/common.h>
3 #include <lunaix/elf.h>
4 #include <lunaix/exec.h>
6 #include <lunaix/mm/mmap.h>
7 #include <lunaix/mm/valloc.h>
8 #include <lunaix/mm/vmm.h>
9 #include <lunaix/spike.h>
12 elf32_read(struct v_file* elf, void* data, size_t off, size_t len)
14 // it is wise to do cached read
15 return pcache_read(elf->inode, data, len, off);
19 elf32_map_segment(struct load_context* ldctx,
20 const struct elf32* elf,
21 struct elf32_phdr* phdre)
23 struct v_file* elfile = (struct v_file*)elf->elf_file;
25 assert(PG_ALIGNED(phdre->p_offset));
28 if ((phdre->p_flags & PF_R)) {
31 if ((phdre->p_flags & PF_W)) {
34 if ((phdre->p_flags & PF_X)) {
38 struct exec_container* container = ldctx->container;
39 struct mmap_param param = { .vms_mnt = container->vms_mnt,
40 .pvms = &container->proc->mm,
42 .offset = PG_ALIGN(phdre->p_offset),
43 .mlen = ROUNDUP(phdre->p_memsz, PG_SIZE),
44 .flen = phdre->p_filesz + PG_MOD(phdre->p_va),
45 .flags = MAP_FIXED | MAP_PRIVATE,
46 .type = REGION_TYPE_CODE };
48 struct mm_region* seg_reg;
49 int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdre->p_va), elfile, ¶m);
52 size_t next_addr = phdre->p_memsz + phdre->p_va;
53 ldctx->end = MAX(ldctx->end, ROUNDUP(next_addr, PG_SIZE));
54 ldctx->mem_sz += phdre->p_memsz;
56 // we probably fucked up our process
64 elf32_open(struct elf32* elf, const char* path)
66 struct v_dnode* elfdn;
67 struct v_inode* elfin;
68 struct v_file* elffile;
71 if ((error = vfs_walk_proc(path, &elfdn, NULL, 0))) {
75 if ((error = vfs_open(elfdn, &elffile))) {
79 return elf32_openat(elf, elffile);
83 elf32_openat(struct elf32* elf, void* elf_vfile)
87 elf->elf_file = elf_vfile;
89 if ((status = elf32_read_ehdr(elf)) < 0) {
94 if ((status = elf32_read_phdr(elf)) < 0) {
103 elf32_close(struct elf32* elf)
106 vfree(elf->pheaders);
110 vfs_close((struct v_file*)elf->elf_file);
113 memset(elf, 0, sizeof(*elf));
117 elf32_static_linked(const struct elf32* elf)
119 for (size_t i = 0; i < elf->eheader.e_phnum; i++) {
120 struct elf32_phdr* phdre = &elf->pheaders[i];
121 if (phdre->p_type == PT_INTERP) {
129 elf32_loadable_memsz(const struct elf32* elf)
131 // XXX: Hmmmm, I am not sure if we need this. This is designed to be handy
132 // if we decided to map the heap region before transfer to loader. As
133 // currently, we push *everything* to user-space loader, thus we modify the
134 // brk syscall to do the initial heap mapping.
137 for (size_t i = 0; i < elf->eheader.e_phnum; i++) {
138 struct elf32_phdr* phdre = &elf->pheaders[i];
139 if (phdre->p_type == PT_LOAD) {
140 sz += phdre->p_memsz;
148 elf32_find_loader(const struct elf32* elf, char* path_out, size_t len)
150 int retval = NO_LOADER;
152 assert_msg(len >= sizeof(DEFAULT_LOADER), "path_out: too small");
154 struct v_file* elfile = (struct v_file*)elf->elf_file;
156 for (size_t i = 0; i < elf->eheader.e_phnum; i++) {
157 struct elf32_phdr* phdre = &elf->pheaders[i];
158 if (phdre->p_type == PT_INTERP) {
159 assert_msg(len >= phdre->p_filesz, "path_out: too small");
161 elf_read(elfile, path_out, phdre->p_offset, phdre->p_filesz);
175 elf32_read_ehdr(struct elf32* elf)
177 struct v_file* elfile = (struct v_file*)elf->elf_file;
178 int status = elf_read(elfile, (void*)&elf->eheader, 0, SIZE_EHDR);
186 elf32_read_phdr(struct elf32* elf)
190 struct v_file* elfile = (struct v_file*)elf->elf_file;
192 size_t entries = elf->eheader.e_phnum;
193 size_t tbl_sz = entries * SIZE_PHDR;
195 struct elf32_phdr* phdrs = valloc(tbl_sz);
201 status = elf_read(elfile, phdrs, elf->eheader.e_phoff, tbl_sz);
208 elf->pheaders = phdrs;
213 elf32_check_exec(const struct elf32* elf)
215 struct elf32_ehdr* ehdr = elf->pheaders;
217 return *(u32_t*)(ehdr->e_ident) == ELFMAGIC &&
218 ehdr->e_ident[EI_CLASS] == ELFCLASS32 &&
219 ehdr->e_ident[EI_DATA] == ELFDATA2LSB && ehdr->e_type == ET_EXEC &&
220 ehdr->e_machine == EM_386;
224 elf32_load(struct load_context* ldctx, const struct elf32* elf)
228 struct v_file* elfile = (struct v_file*)elf->elf_file;
230 for (size_t i = 0; i < elf->eheader.e_phnum && !err; i++) {
231 struct elf32_phdr* phdr = &elf->pheaders[i];
233 if (phdr->p_type == PT_LOAD) {
234 if (phdr->p_align != PG_SIZE) {
235 // surprising alignment!
240 err = elf_map_segment(ldctx, elf, phdr);
242 // TODO Handle relocation