-#include <arch/abi.h>
#include <lunaix/exec.h>
#include <lunaix/fs.h>
#include <lunaix/load.h>
#include <lunaix/syscall.h>
#include <lunaix/syscall_utils.h>
+#include <sys/abi.h>
+#include <sys/mm/mempart.h>
+
#include <klibc/string.h>
void
}
size_t
-exec_str_size(const char** str_arr, size_t* length)
+args_ptr_size(const char** paramv)
{
- if (!str_arr) {
- *length = 0;
- return 0;
+ size_t sz = 0;
+ while (*paramv) {
+ sz++;
+ paramv++;
}
- const char* chr = *str_arr;
- size_t sz = 0, len = 0;
+ return (sz + 1) * sizeof(ptr_t);
+}
+
+ptr_t
+copy_to_ustack(ptr_t stack_top, ptr_t* paramv)
+{
+ ptr_t ptr;
+ size_t sz = 0;
+
+ while ((ptr = *paramv)) {
+ sz = strlen((const char*)ptr) + 1;
- while (chr) {
- sz += strlen(chr);
- len++;
+ stack_top -= sz;
+ memcpy((void*)stack_top, (const void*)ptr, sz);
+ *paramv = stack_top;
- chr = *(str_arr++);
+ paramv++;
}
- *length = len;
- return sz + sizeof(char*);
+ return stack_top;
}
// externed from mm/dmm.c
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);
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;
-
if (pvms->heap) {
mem_unmap_region(container->vms_mnt, pvms->heap);
pvms->heap = NULL;
create_heap(&container->proc->mm, PG_ALIGN(container->exe.end));
}
- if ((errno = mem_map(&mapped, NULL, UMMAP_END, NULL, &map_vars))) {
- goto done;
- }
-
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 = USR_STACK_END;
+ 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++) {
- const char* extra_arg = argv_extra[i];
- size_t str_len = strlen(extra_arg);
-
- ustack = (void*)((ptr_t)ustack - str_len);
- memcpy(ustack, (const void*)extra_arg, str_len);
+ 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);
}
// four args (arg{c|v}, env{c|p}) for main
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
// 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) = container.exe.entry;
+ eret_stack(__current) = container.stack_top;
+
+ // these become meaningless once execved!
+ __current->ustack_top = 0;
+ proc_clear_signal(__current);
done:
// set return value