X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/bb793d5c6918efee6a86de442463a7c9aaa4ecdd..aa67abb537f22db097db632d98212fa951bfeef0:/lunaix-os/kernel/exe/exec.c diff --git a/lunaix-os/kernel/exe/exec.c b/lunaix-os/kernel/exe/exec.c index 21814d1..813d5c3 100644 --- a/lunaix-os/kernel/exe/exec.c +++ b/lunaix-os/kernel/exe/exec.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -6,26 +5,33 @@ #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 @@ -40,7 +46,7 @@ args_ptr_size(const char** paramv) return (sz + 1) * sizeof(ptr_t); } -ptr_t +static ptr_t copy_to_ustack(ptr_t stack_top, ptr_t* paramv) { ptr_t ptr; @@ -59,6 +65,32 @@ copy_to_ustack(ptr_t stack_top, ptr_t* paramv) return stack_top; } +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++; + } + + if (proc->cmd) { + vfree(proc->cmd); + } + + 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 extern int create_heap(struct proc_mm* pvms, ptr_t addr); @@ -77,7 +109,8 @@ exec_load(struct exec_container* container, struct v_file* executable) goto done; } - struct proc_mm* pvms = &container->proc->mm; + struct proc_info* proc = container->proc; + struct proc_mm* pvms = vmspace(proc); if (pvms->heap) { mem_unmap_region(container->vms_mnt, pvms->heap); @@ -87,13 +120,13 @@ 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)); + create_heap(vmspace(proc), page_aligned(container->exe.end)); } if (container->vms_mnt == VMS_SELF) { // we are loading executable into current addr space - ptr_t ustack = USTACK_TOP; + ptr_t ustack = container->stack_top; size_t argv_len = 0, envp_len = 0; ptr_t argv_ptr = 0, envp_ptr = 0; @@ -104,23 +137,32 @@ exec_load(struct exec_container* container, struct v_file* executable) memcpy((void*)ustack, (const void*)envp, envp_len); ustack = copy_to_ustack(ustack, (ptr_t*)ustack); + } else { + ustack -= sizeof(ptr_t); + *((ptr_t*)ustack) = 0; } - if (argv) { + if (argv) { argv_len = args_ptr_size(argv); ustack -= argv_len; memcpy((void*)ustack, (const void**)argv, argv_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); - } + } else { + ustack -= sizeof(ptr_t); + *((ptr_t*)ustack) = 0; + } - argv_ptr = ustack; - ustack = copy_to_ustack(ustack, (ptr_t*)ustack); + 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]; @@ -133,20 +175,11 @@ exec_load(struct exec_container* container, struct v_file* executable) .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: @@ -168,8 +201,19 @@ exec_load_byname(struct exec_container* container, const char* filename) goto done; } + if (!check_itype_any(dnode->inode, F_FILE)) { + errno = EISDIR; + goto done; + } + 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; } @@ -180,8 +224,7 @@ exec_kexecve(const char* filename, const char* argv[], const char* envp[]) int errno = 0; struct exec_container container; - exec_container( - &container, (struct proc_info*)__current, VMS_SELF, argv, envp); + exec_init_container(&container, current_thread, VMS_SELF, argv, envp); errno = exec_load_byname(&container, filename); @@ -211,8 +254,8 @@ __DEFINE_LXSYSCALL3(int, int errno = 0; struct exec_container container; - exec_container( - &container, (struct proc_info*)__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,13 +263,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->ustack_top = 0; - proc_clear_signal(__current); + current_thread->ustack_top = 0; + signal_reset_context(¤t_thread->sigctx); + signal_reset_register(__current->sigreg); done: // set return value