1 #include <lunaix/elf.h>
4 #include <lunaix/mm/mmap.h>
5 #include <lunaix/mm/vmm.h>
6 #include <lunaix/process.h>
7 #include <lunaix/spike.h>
8 #include <lunaix/status.h>
9 #include <lunaix/syscall.h>
11 #include <klibc/string.h>
14 exec_str_size(const char** str_arr, size_t* length)
21 const char* chr = *str_arr;
22 size_t sz = 0, len = 0;
28 chr = *(str_arr + sz);
36 __heap_copied(struct mm_region* region)
38 mm_index((void**)®ion->proc_vms->heap, region);
42 __exec_remap_heap(struct ld_param* param, struct proc_mm* pvms)
45 mem_unmap_region(param->vms_mnt, pvms->heap);
48 struct mmap_param map_param = { .pvms = pvms,
49 .vms_mnt = param->vms_mnt,
50 .flags = MAP_ANON | MAP_PRIVATE | MAP_FIXED,
51 .type = REGION_TYPE_HEAP,
52 .proct = PROT_READ | PROT_WRITE,
53 .mlen = DEFAULT_HEAP_PAGES * PG_SIZE };
55 struct mm_region* heap;
56 if ((status = mem_map(NULL, &heap, param->info.end, NULL, &map_param))) {
57 param->status |= LD_STAT_FKUP;
61 heap->region_copied = __heap_copied;
62 mm_index((void**)&pvms->heap, heap);
68 exec_load(struct ld_param* param,
69 struct v_file* executable,
75 size_t argv_len, envp_len;
76 size_t sz_argv = exec_str_size(argv, &argv_len);
77 size_t sz_envp = exec_str_size(envp, &envp_len);
78 size_t total_sz = ROUNDUP(sz_argv + sz_envp, PG_SIZE);
80 if (total_sz / PG_SIZE > MAX_VAR_PAGES) {
85 if ((errno = elf_load(param, executable))) {
89 struct proc_mm* pvms = ¶m->proc->mm;
90 struct mmap_param map_vars = { .pvms = pvms,
91 .vms_mnt = param->vms_mnt,
92 .flags = MAP_ANON | MAP_PRIVATE | MAP_FIXED,
93 .type = REGION_TYPE_VARS,
95 .mlen = MAX_VAR_PAGES * PG_SIZE };
99 if ((errno = __exec_remap_heap(param, pvms))) {
103 if ((errno = mem_map(&mapped, NULL, UMMAP_END, NULL, &map_vars))) {
107 if (param->vms_mnt == VMS_SELF) {
108 // we are loading executable into current addr space
110 // make some handy infos available to user space
111 ptr_t arg_start = mapped + sizeof(struct usr_exec_param);
113 memcpy(arg_start, (void*)argv, sz_argv);
115 memcpy(arg_start + sz_argv, (void*)envp, sz_envp);
117 ptr_t* ustack = (ptr_t*)USTACK_TOP;
118 struct usr_exec_param* exec_param = mapped;
120 ustack[-1] = (ptr_t)mapped;
121 param->info.stack_top = &ustack[-1];
123 *exec_param = (struct usr_exec_param){ .argc = argv_len,
126 .envp = arg_start + sz_argv,
127 .info = param->info };
129 // TODO need to find a way to inject argv and envp remotely
130 fail("not implemented");
133 param->info.entry = param->info.ehdr_out.e_entry;
139 exec_load_byname(struct ld_param* param,
140 const char* filename,
145 struct v_dnode* dnode;
148 if ((errno = vfs_walk_proc(filename, &dnode, NULL, 0))) {
152 if ((errno = vfs_open(dnode, &file))) {
156 if ((errno = exec_load(param, file, argv, envp))) {
157 vfs_pclose(file, __current->pid);
164 __DEFINE_LXSYSCALL3(int,
174 struct ld_param ldparam;
175 ld_create_param(&ldparam, __current, VMS_SELF);
177 if ((errno = exec_load_byname(&ldparam, filename, argv, envp))) {
178 if ((ldparam.status & LD_STAT_FKUP)) {
179 // we fucked up our address space.
180 terminate_proc(11451);
182 fail("should not reach");
186 isr_param* intr_ctx = &__current->intr_ctx;
187 intr_ctx->esp = ldparam.info.stack_top;
188 intr_ctx->eip = ldparam.info.entry;
190 // we will jump to new entry point (_u_start) upon syscall's
191 // return so execve 'will not return' from the perspective of it's invoker