2 #include <lunaix/exec.h>
4 #include <lunaix/load.h>
5 #include <lunaix/mm/mmap.h>
6 #include <lunaix/mm/valloc.h>
7 #include <lunaix/mm/vmm.h>
8 #include <lunaix/process.h>
9 #include <lunaix/spike.h>
10 #include <lunaix/status.h>
11 #include <lunaix/syscall.h>
12 #include <lunaix/syscall_utils.h>
14 #include <klibc/string.h>
17 exec_container(struct exec_container* param,
18 struct proc_info* proc,
23 *param = (struct exec_container){ .proc = proc,
25 .exe = { .container = param },
32 args_ptr_size(const char** paramv)
40 return (sz + 1) * sizeof(ptr_t);
44 copy_to_ustack(ptr_t stack_top, ptr_t* paramv)
49 while ((ptr = *paramv)) {
50 sz = strlen((const char*)ptr) + 1;
53 memcpy((void*)stack_top, (const void*)ptr, sz);
62 // externed from mm/dmm.c
64 create_heap(struct proc_mm* pvms, ptr_t addr);
67 exec_load(struct exec_container* container, struct v_file* executable)
71 const char **argv = container->argv, **envp = container->envp;
72 const char** argv_extra = container->argv_pp;
74 argv_extra[0] = executable->dnode->name.value;
76 if ((errno = load_executable(&container->exe, executable))) {
80 struct proc_mm* pvms = &container->proc->mm;
83 mem_unmap_region(container->vms_mnt, pvms->heap);
88 // If loading a statically linked file, then heap remapping we can do,
90 create_heap(&container->proc->mm, PG_ALIGN(container->exe.end));
93 if (container->vms_mnt == VMS_SELF) {
94 // we are loading executable into current addr space
96 ptr_t ustack = USTACK_TOP;
97 size_t argv_len = 0, envp_len = 0;
98 ptr_t argv_ptr = 0, envp_ptr = 0;
101 argv_len = args_ptr_size(envp);
105 memcpy((void*)ustack, (const void*)envp, envp_len);
106 ustack = copy_to_ustack(ustack, (ptr_t*)ustack);
110 argv_len = args_ptr_size(argv);
113 memcpy((void*)ustack, (const void**)argv, argv_len);
114 for (size_t i = 0; i < 2 && argv_extra[i]; i++) {
115 ustack -= sizeof(ptr_t);
116 *((ptr_t*)ustack) = (ptr_t)argv_extra[i];
117 argv_len += sizeof(ptr_t);
121 ustack = copy_to_ustack(ustack, (ptr_t*)ustack);
124 // four args (arg{c|v}, env{c|p}) for main
125 struct uexec_param* exec_param = &((struct uexec_param*)ustack)[-1];
127 container->stack_top = (ptr_t)exec_param;
130 (struct uexec_param){ .argc = (argv_len - 1) / sizeof(ptr_t),
131 .argv = (char**)argv_ptr,
132 .envc = (envp_len - 1) / sizeof(ptr_t),
133 .envp = (char**)envp_ptr };
136 TODO need to find a way to inject argv and envp remotely
137 this is for the support of kernel level implementation of
141 1. Allocate a orphaned physical page (i.e., do not belong to any
143 2. Mounted to a temporary mount point in current VMA, (i.e.,
146 4. Unmount then mounted to the foreign VMA as the first stack
149 fail("not implemented");
157 exec_load_byname(struct exec_container* container, const char* filename)
160 struct v_dnode* dnode;
163 if ((errno = vfs_walk_proc(filename, &dnode, NULL, 0))) {
167 if ((errno = vfs_open(dnode, &file))) {
171 errno = exec_load(container, file);
178 exec_kexecve(const char* filename, const char* argv[], const char* envp[])
181 struct exec_container container;
184 &container, (struct proc_info*)__current, VMS_SELF, argv, envp);
186 errno = exec_load_byname(&container, filename);
192 ptr_t entry = container.exe.entry;
195 j_usr(container.stack_top, entry);
202 __DEFINE_LXSYSCALL3(int,
212 struct exec_container container;
215 &container, (struct proc_info*)__current, VMS_SELF, argv, envp);
217 if ((errno = exec_load_byname(&container, filename))) {
221 // we will jump to new entry point (_u_start) upon syscall's
222 // return so execve 'will not return' from the perspective of it's invoker
223 volatile struct exec_param* execp = __current->intr_ctx.execp;
224 execp->esp = container.stack_top;
225 execp->eip = container.exe.entry;
229 store_retval(DO_STATUS(errno));
231 // Always yield the process that want execve!
234 // this will never get executed!