X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/b6ff3c7dbab3f40d03389808d95ac27d416c35e3..69777bdcab284335651a8002e2896f3862fa423d:/lunaix-os/kernel/exe/exec.c diff --git a/lunaix-os/kernel/exe/exec.c b/lunaix-os/kernel/exe/exec.c index 535f659..6f2962e 100644 --- a/lunaix-os/kernel/exe/exec.c +++ b/lunaix-os/kernel/exe/exec.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -6,48 +5,90 @@ #include #include #include +#include #include #include #include #include +#include +#include + #include void -exec_container(struct exec_container* param, - struct proc_info* proc, +exec_init_container(struct exec_container* param, + struct thread* thread, ptr_t vms, const char** argv, const char** envp) { - *param = (struct exec_container){ .proc = proc, + assert(thread->ustack); + ptr_t ustack_top = align_stack(thread->ustack->end - 1); + *param = (struct exec_container){ .proc = thread->process, .vms_mnt = vms, .exe = { .container = param }, .argv_pp = { 0, 0 }, .argv = argv, - .envp = envp }; + .envp = envp, + .stack_top = ustack_top }; } size_t -exec_str_size(const char** str_arr, size_t* length) +args_ptr_size(const char** paramv) +{ + size_t sz = 0; + while (*paramv) { + sz++; + paramv++; + } + + return (sz + 1) * sizeof(ptr_t); +} + +static ptr_t +copy_to_ustack(ptr_t stack_top, ptr_t* paramv) { - if (!str_arr) { - *length = 0; - return 0; + ptr_t ptr; + size_t sz = 0; + + while ((ptr = *paramv)) { + sz = strlen((const char*)ptr) + 1; + + stack_top -= sz; + memcpy((void*)stack_top, (const void*)ptr, sz); + *paramv = stack_top; + + paramv++; } - const char* chr = *str_arr; - size_t sz = 0, len = 0; + return stack_top; +} - while (chr) { - sz += strlen(chr); - len++; +static void +save_process_cmd(struct proc_info* proc, ptr_t* argv) +{ + ptr_t ptr, *_argv = argv; + size_t total_sz = 0; + while ((ptr = *_argv)) { + total_sz += strlen((const char*)ptr) + 1; + _argv++; + } - chr = *(str_arr++); + if (proc->cmd) { + vfree(proc->cmd); } - *length = len; - return sz + sizeof(char*); + char* cmd_ = (char*)valloc(total_sz); + proc->cmd = cmd_; + proc->cmd_len = total_sz; + + while ((ptr = *argv)) { + cmd_ = strcpy(cmd_, (const char*)ptr); + cmd_[-1] = ' '; + argv++; + } + cmd_[-1] = '\0'; } // externed from mm/dmm.c @@ -60,34 +101,16 @@ exec_load(struct exec_container* container, struct v_file* executable) int errno = 0; const char **argv = container->argv, **envp = container->envp; - size_t argv_len, envp_len; - size_t sz_argv = exec_str_size(argv, &argv_len); - size_t sz_envp = exec_str_size(envp, &envp_len); - size_t var_sz = ROUNDUP(sz_envp, PG_SIZE); - char** argv_extra = container->argv_pp; + const char** argv_extra = container->argv_pp; argv_extra[0] = executable->dnode->name.value; - if (var_sz / PG_SIZE > MAX_VAR_PAGES) { - errno = E2BIG; - goto done; - } - if ((errno = load_executable(&container->exe, executable))) { goto done; } - struct proc_mm* pvms = &container->proc->mm; - - // A dedicated place for process variables (e.g. envp) - struct mmap_param map_vars = { .pvms = pvms, - .vms_mnt = container->vms_mnt, - .flags = MAP_ANON | MAP_PRIVATE | MAP_FIXED, - .type = REGION_TYPE_VARS, - .proct = PROT_READ, - .mlen = MAX_VAR_PAGES * PG_SIZE }; - - void* mapped; + struct proc_info* proc = container->proc; + struct proc_mm* pvms = vmspace(proc); if (pvms->heap) { mem_unmap_region(container->vms_mnt, pvms->heap); @@ -97,60 +120,60 @@ exec_load(struct exec_container* container, struct v_file* executable) if (!argv_extra[1]) { // If loading a statically linked file, then heap remapping we can do, // otherwise delayed. - create_heap(&container->proc->mm, PG_ALIGN(container->exe.end)); - } - - if ((errno = mem_map(&mapped, NULL, UMMAP_END, NULL, &map_vars))) { - goto done; + create_heap(vmspace(proc), va_align(container->exe.end)); } if (container->vms_mnt == VMS_SELF) { // we are loading executable into current addr space - // make some handy infos available to user space - if (envp) - memcpy(mapped, (void*)envp, sz_envp); + ptr_t ustack = container->stack_top; + size_t argv_len = 0, envp_len = 0; + ptr_t argv_ptr = 0, envp_ptr = 0; - void* ustack = (void*)USTACK_TOP; + if (envp) { + argv_len = args_ptr_size(envp); + ustack -= envp_len; + envp_ptr = ustack; - if (argv) { - ustack = (void*)((ptr_t)ustack - sz_argv); - memcpy(ustack, (void*)argv, sz_argv); + memcpy((void*)ustack, (const void*)envp, envp_len); + ustack = copy_to_ustack(ustack, (ptr_t*)ustack); } - for (size_t i = 0; i < 2 && argv_extra[i]; i++, argv_len++) { - char* extra_arg = argv_extra[i]; - size_t str_len = strlen(extra_arg); + if (argv) { + argv_len = args_ptr_size(argv); + ustack -= argv_len; + + memcpy((void*)ustack, (const void**)argv, argv_len); + } - ustack = (void*)((ptr_t)ustack - str_len); - memcpy(ustack, (void*)extra_arg, str_len); + for (size_t i = 0; i < 2 && argv_extra[i]; i++) { + ustack -= sizeof(ptr_t); + *((ptr_t*)ustack) = (ptr_t)argv_extra[i]; + argv_len += sizeof(ptr_t); } + argv_ptr = ustack; + ustack = copy_to_ustack(ustack, (ptr_t*)ustack); + + save_process_cmd(proc, (ptr_t*)argv_ptr); + // four args (arg{c|v}, env{c|p}) for main struct uexec_param* exec_param = &((struct uexec_param*)ustack)[-1]; container->stack_top = (ptr_t)exec_param; - *exec_param = (struct uexec_param){ - .argc = argv_len, .argv = ustack, .envc = envp_len, .envp = mapped - }; - + *exec_param = + (struct uexec_param){ .argc = (argv_len - 1) / sizeof(ptr_t), + .argv = (char**)argv_ptr, + .envc = (envp_len - 1) / sizeof(ptr_t), + .envp = (char**)envp_ptr }; } else { /* - TODO need to find a way to inject argv and envp remotely - this is for the support of kernel level implementation of - posix_spawn - - IDEA - 1. Allocate a orphaned physical page (i.e., do not belong to any - VMA) - 2. Mounted to a temporary mount point in current VMA, (i.e., - PG_MOUNT_*) - 3. Do setup there. - 4. Unmount then mounted to the foreign VMA as the first stack - page. + TODO Inject to remote user stack with our procvm_remote toolsets + Need a better way to factorise the argv/envp length calculating */ fail("not implemented"); + } done: @@ -174,6 +197,12 @@ exec_load_byname(struct exec_container* container, const char* filename) errno = exec_load(container, file); + // It shouldn't matter which pid we passed. As the only reader is + // in current context and we must finish read at this point, + // therefore the dead-lock condition will not exist and the pid + // for arbitration has no use. + vfs_pclose(file, container->proc->pid); + done: return errno; } @@ -183,7 +212,8 @@ exec_kexecve(const char* filename, const char* argv[], const char* envp[]) { int errno = 0; struct exec_container container; - exec_container(&container, __current, VMS_SELF, argv, envp); + + exec_init_container(&container, current_thread, VMS_SELF, argv, envp); errno = exec_load_byname(&container, filename); @@ -212,7 +242,9 @@ __DEFINE_LXSYSCALL3(int, { int errno = 0; struct exec_container container; - exec_container(&container, __current, VMS_SELF, argv, envp); + + exec_init_container( + &container, current_thread, VMS_SELF, argv, envp); if ((errno = exec_load_byname(&container, filename))) { goto done; @@ -220,9 +252,13 @@ __DEFINE_LXSYSCALL3(int, // we will jump to new entry point (_u_start) upon syscall's // return so execve 'will not return' from the perspective of it's invoker - volatile struct exec_param* execp = __current->intr_ctx.execp; - execp->esp = container.stack_top; - execp->eip = container.exe.entry; + eret_target(current_thread) = container.exe.entry; + eret_stack(current_thread) = container.stack_top; + + // these become meaningless once execved! + current_thread->ustack_top = 0; + signal_reset_context(¤t_thread->sigctx); + signal_reset_register(__current->sigreg); done: // set return value