X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/69777bdcab284335651a8002e2896f3862fa423d..34f6af4f61e0eec9c96113e07f140b609b4113c8:/lunaix-os/kernel/exe/exec.c diff --git a/lunaix-os/kernel/exe/exec.c b/lunaix-os/kernel/exe/exec.c index 6f2962e..0dace13 100644 --- a/lunaix-os/kernel/exe/exec.c +++ b/lunaix-os/kernel/exe/exec.c @@ -11,13 +11,77 @@ #include #include -#include -#include +#include +#include #include +#define _push(ptr, type, val) \ + do { \ + ptr = __ptr(&((type*)ptr)[-1]); \ + *((type*)ptr) = (val); \ + } while(0) + +static int +__place_arrayptrs(struct exec_host* container, struct exec_arrptr* param) +{ + int len; + ptr_t usp, usp_top; + ptr_t* ptrs; + unsigned int* reloc_off; + + usp_top = container->stack_top; + usp = usp_top; + ptrs = (ptr_t*)param->raw; + + if (!param->len) { + _push(usp, unsigned int, 0); + + goto done; + } + + len = param->len; + reloc_off = valloc(len * sizeof(unsigned int)); + + char* el; + size_t el_sz, sz_acc = 0; + for (int i = 0; i < len; i++) + { + el= (char*)ptrs[i]; + el_sz = strnlen(el, MAX_PARAM_SIZE) + 1; + + usp -= el_sz; + sz_acc += el_sz; + strncpy((char*)usp, el, el_sz); + + reloc_off[i] = sz_acc; + } + + param->size = sz_acc; + + ptr_t* toc = (ptr_t*)(usp) - 1; + toc[0] = 0; + + toc = &toc[-1]; + for (int i = 0, j = len - 1; i < len; i++, j--) + { + toc[-i] = usp_top - (ptr_t)reloc_off[j]; + } + + toc[-len] = (ptr_t)len; + + usp = __ptr(&toc[-len]); + param->copied = __ptr(&toc[-len + 1]); + + vfree(reloc_off); + +done: + container->stack_top = usp; + return 0; +} + void -exec_init_container(struct exec_container* param, +exec_init_container(struct exec_host* param, struct thread* thread, ptr_t vms, const char** argv, @@ -25,90 +89,89 @@ exec_init_container(struct exec_container* param, { 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, - .stack_top = ustack_top }; + *param = (struct exec_host) + { + .proc = thread->process, + .vms_mnt = vms, + .exe = { + .container = param + }, + .argv = { + .raw = __ptr(argv) + }, + .envp = { + .raw = __ptr(envp) + }, + .stack_top = ustack_top + }; } -size_t -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) +int +count_length(struct exec_arrptr* param) { - ptr_t ptr; - size_t sz = 0; - - while ((ptr = *paramv)) { - sz = strlen((const char*)ptr) + 1; + int i = 0; + ptr_t* arr = (ptr_t*)param->raw; - stack_top -= sz; - memcpy((void*)stack_top, (const void*)ptr, sz); - *paramv = stack_top; - - paramv++; + if (!arr) { + param->len = 0; + return 0; } - return stack_top; + for (; i < MAX_PARAM_LEN && arr[i]; i++); + + param->len = i; + return i > 0 && arr[i] ? E2BIG : 0; } static void -save_process_cmd(struct proc_info* proc, ptr_t* argv) +save_process_cmd(struct proc_info* proc, struct exec_arrptr* argv) { - ptr_t ptr, *_argv = argv; - size_t total_sz = 0; - while ((ptr = *_argv)) { - total_sz += strlen((const char*)ptr) + 1; - _argv++; - } + ptr_t ptr, *argv_ptrs; + char* cmd_; if (proc->cmd) { vfree(proc->cmd); } - char* cmd_ = (char*)valloc(total_sz); - proc->cmd = cmd_; - proc->cmd_len = total_sz; + argv_ptrs = (ptr_t*)argv->copied; + cmd_ = (char*)valloc(argv->size); - while ((ptr = *argv)) { + proc->cmd = cmd_; + while ((ptr = *argv_ptrs)) { cmd_ = strcpy(cmd_, (const char*)ptr); cmd_[-1] = ' '; - argv++; + argv_ptrs++; } cmd_[-1] = '\0'; + + proc->cmd_len = argv->size; } -// externed from mm/dmm.c -extern int -create_heap(struct proc_mm* pvms, ptr_t addr); -int -exec_load(struct exec_container* container, struct v_file* executable) +static int +__place_params(struct exec_host* container) { int errno = 0; - const char **argv = container->argv, **envp = container->envp; - const char** argv_extra = container->argv_pp; - - argv_extra[0] = executable->dnode->name.value; - - if ((errno = load_executable(&container->exe, executable))) { + errno = __place_arrayptrs(container, &container->envp); + if (errno) { goto done; } + errno = __place_arrayptrs(container, &container->argv); + +done: + return errno; +} + +int +exec_load(struct exec_host* container, struct v_file* executable) +{ + int errno = 0; + + struct exec_arrptr* argv = &container->argv; + struct exec_arrptr* envp = &container->envp; + struct proc_info* proc = container->proc; struct proc_mm* pvms = vmspace(proc); @@ -117,63 +180,32 @@ exec_load(struct exec_container* container, struct v_file* executable) pvms->heap = NULL; } - if (!argv_extra[1]) { - // If loading a statically linked file, then heap remapping we can do, - // otherwise delayed. - create_heap(vmspace(proc), va_align(container->exe.end)); - } - - if (container->vms_mnt == VMS_SELF) { - // we are loading executable into current addr space - - ptr_t ustack = container->stack_top; - size_t argv_len = 0, envp_len = 0; - ptr_t argv_ptr = 0, envp_ptr = 0; - - if (envp) { - argv_len = args_ptr_size(envp); - ustack -= envp_len; - envp_ptr = ustack; - - memcpy((void*)ustack, (const void*)envp, envp_len); - ustack = copy_to_ustack(ustack, (ptr_t*)ustack); - } - - 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); - } - - argv_ptr = ustack; - ustack = copy_to_ustack(ustack, (ptr_t*)ustack); + if (!active_vms(container->vms_mnt)) { + /* + TODO Setup remote mapping of user stack for later use + */ + fail("not implemented"); - 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]; + if ((errno = count_length(argv))) { + goto done; + } - container->stack_top = (ptr_t)exec_param; + if ((errno = count_length(envp))) { + goto done; + } - *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 Inject to remote user stack with our procvm_remote toolsets - Need a better way to factorise the argv/envp length calculating - */ - fail("not implemented"); + errno = __place_params(container); + if (errno) { + goto done; + } + save_process_cmd(proc, argv); + + errno = load_executable(&container->exe, executable); + if (errno) { + goto done; } done: @@ -181,7 +213,7 @@ done: } int -exec_load_byname(struct exec_container* container, const char* filename) +exec_load_byname(struct exec_host* container, const char* filename) { int errno = 0; struct v_dnode* dnode; @@ -195,6 +227,11 @@ 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 @@ -211,7 +248,9 @@ int exec_kexecve(const char* filename, const char* argv[], const char* envp[]) { int errno = 0; - struct exec_container container; + struct exec_host container; + + assert(argv && envp); exec_init_container(&container, current_thread, VMS_SELF, argv, envp); @@ -241,7 +280,12 @@ __DEFINE_LXSYSCALL3(int, envp[]) { int errno = 0; - struct exec_container container; + struct exec_host container; + + if (!argv || !envp) { + errno = EINVAL; + goto done; + } exec_init_container( &container, current_thread, VMS_SELF, argv, envp); @@ -252,13 +296,12 @@ __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 - eret_target(current_thread) = container.exe.entry; - eret_stack(current_thread) = container.stack_top; + exec_arch_prepare_entry(current_thread, &container); // these become meaningless once execved! current_thread->ustack_top = 0; signal_reset_context(¤t_thread->sigctx); - signal_reset_register(__current->sigreg); + signal_reset_registry(__current->sigreg); done: // set return value