syscalls: implement argv and envp handling in execve

This commit is contained in:
2025-09-16 22:41:32 +03:00
parent 7c2f3735bf
commit 2c8b5d4752
2 changed files with 72 additions and 5 deletions
+2 -2
View File
@@ -9,10 +9,10 @@ int main() {
// Arguments for the new program
// The first argument is conventionally the program name
char *argv[] = {NULL}; //{ "./callee", "first_arg", "second_arg", NULL };
char *argv[] = { "./callee", "first_arg", "second_arg", NULL };
// Environment variables for the new program
char *envp[] = {NULL}; //{ "CUSTOM_VAR=Hello from caller!", "ANOTHER_VAR=123", NULL };
char *envp[] = { "CUSTOM_VAR=Hello from caller!", "ANOTHER_VAR=123", NULL };
// The execve system call
// The first argument is the path to the executable
+70 -3
View File
@@ -18,6 +18,8 @@ extern void switchProcess(Process* next);
#define EBADF 9
#define EXECVE_MAX_ARGUMENT_SIZE 255
const char* flags_to_mode_str(int flags) {
static char mode[4] = {0};
int accmode = flags & 3;
@@ -251,9 +253,44 @@ int sys_close(TrapFrame *tf)
extern void execve_return(TrapFrame *tf);
/**
* this might be a not really good implementation as it only supports
* up to EXECVE_MAX_ARGUMENT_SIZE characters in each argument or environment
* string and for some reason I was unable to use malloc for kernel_argv and
* kernel_envp
*/
int sys_execve(TrapFrame *tf) {
const char* filename = (const char*)tf->ebx;
char **argv = (char**)tf->ecx;
char **envp = (char**)tf->edx;
int argc = 0;
int envc = 0;
while(argv[argc] != NULL)
{
argc++;
}
while(envp[envc] != NULL)
{
envc++;
}
//TODO: check why was there a triple fault when I tried using malloc
char kernel_argv[argc][EXECVE_MAX_ARGUMENT_SIZE];
char kernel_envp[envc][EXECVE_MAX_ARGUMENT_SIZE];
for(int i = 0; i < argc; i++)
{
strcpy(kernel_argv[i], argv[i]);
}
for(int i = 0; i < envc; i++)
{
strcpy(kernel_envp[i], envp[i]);
}
uint8_t* file_buffer;
int err = vsf_read_file_by_path(filename, &file_buffer, root_dir);
if (err != 0) {
@@ -304,10 +341,40 @@ int sys_execve(TrapFrame *tf) {
void* phys_addr = alloc_page();
map_page(phys_addr, (void*)(vaddr & ~0xFFF), PAGE_PRESENT | PAGE_RW | PAGE_USER);
}
uint32_t user_esp = USER_STACK_TOP;
user_esp -= 4; *(uint32_t*)user_esp = 0; // envp
user_esp -= 4; *(uint32_t*)user_esp = 0; // argv
user_esp -= 4; *(uint32_t*)user_esp = 0; // argc
//push environment strings
uint32_t envp_pointers[envc + 1];
for (int i = envc - 1; i >= 0; i--) {
size_t len = strlen(kernel_envp[i]) + 1;
user_esp -= len;
memcpy((void*)user_esp, kernel_envp[i], len);
envp_pointers[i] = user_esp;
}
envp_pointers[envc] = 0;//null terminator
//push argument strings
uint32_t argv_pointers[argc + 1];
for (int i = argc - 1; i >= 0; i--) {
size_t len = strlen(kernel_argv[i]) + 1;
user_esp -= len;
memcpy((void*)user_esp, kernel_argv[i], len);
argv_pointers[i] = user_esp;
}
argv_pointers[argc] = 0;//null terminator
//push envp pointers
user_esp -= (envc + 1) * sizeof(uint32_t);
memcpy((void*)user_esp, envp_pointers, (envc + 1) * sizeof(uint32_t));
//push argv pointers
user_esp -= (argc + 1) * sizeof(uint32_t);
memcpy((void*)user_esp, argv_pointers, (argc + 1) * sizeof(uint32_t));
//push argc
user_esp -= sizeof(uint32_t);
*((uint32_t*)user_esp) = argc;
current->brk = (void*)(DivRoundUp(highest_vaddr, PAGE_SIZE) * PAGE_SIZE);
free(file_buffer);