syscalls: implement basic execve syscall, no argc, argv, envp support yet

This commit is contained in:
2025-09-14 17:17:42 +03:00
parent 4c26652ee2
commit 91e0379fc9
9 changed files with 192 additions and 38 deletions
+87
View File
@@ -247,6 +247,89 @@ int sys_close(TrapFrame *tf)
return -1;
}
#include "../include/exec_from_file.h"
extern void execve_return(TrapFrame *tf);
int sys_execve(TrapFrame *tf) {
const char* filename = (const char*)tf->ebx;
uint8_t* file_buffer;
int err = vsf_read_file_by_path(filename, &file_buffer, root_dir);
if (err != 0) {
debug_log("execve: failed to read file '%s'\n", filename);
return -1;
}
Elf32_Ehdr *elf_header = (Elf32_Ehdr*)file_buffer;
if (memcmp(elf_header->e_ident, "\x7F" "ELF", 4) != 0) {
debug_log("execve: '%s' is not a valid ELF file\n", filename);
free(file_buffer);
return -1;
}
uint32_t* new_page_dir = create_page_dir();
if (!new_page_dir) {
free(file_buffer);
return -1;
}
uint32_t new_page_dir_phys = (uint32_t)get_physaddr((void*)new_page_dir);
uint32_t* old_page_dir_to_free = current->pagedir;
set_page_dir(new_page_dir_phys);
current->pagedir = new_page_dir;
void* kstack_phys = get_physaddr(current->kstack);
map_page(kstack_phys, current->kstack, PAGE_PRESENT | PAGE_RW);
uint32_t highest_vaddr = 0;
for (int i = 0; i < elf_header->e_phnum; i++) {
Elf32_Phdr *p_header = (Elf32_Phdr *)(file_buffer + elf_header->e_phoff + i * elf_header->e_phentsize);
if (p_header->p_type == PT_LOAD) {
for (uint32_t vaddr = p_header->p_vaddr; vaddr < p_header->p_vaddr + p_header->p_memsz; vaddr += PAGE_SIZE) {
void* phys_addr = alloc_page();
map_page(phys_addr, (void*)(vaddr & ~0xFFF), PAGE_PRESENT | PAGE_RW | PAGE_USER);
}
memcpy((void*)p_header->p_vaddr, file_buffer + p_header->p_offset, p_header->p_filesz);
if (p_header->p_memsz > p_header->p_filesz) {
memset((void*)(p_header->p_vaddr + p_header->p_filesz), 0, p_header->p_memsz - p_header->p_filesz);
}
if (p_header->p_vaddr + p_header->p_memsz > highest_vaddr) {
highest_vaddr = p_header->p_vaddr + p_header->p_memsz;
}
}
}
for (uint32_t vaddr = USER_STACK_BOTTOM; vaddr <= USER_STACK_TOP; vaddr += PAGE_SIZE) {
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
current->brk = (void*)(DivRoundUp(highest_vaddr, PAGE_SIZE) * PAGE_SIZE);
free(file_buffer);
destroy_page_dir(old_page_dir_to_free);
tf->gs = SEG_UDATA | DPL_USER;
tf->fs = SEG_UDATA | DPL_USER;
tf->es = SEG_UDATA | DPL_USER;
tf->ds = SEG_UDATA | DPL_USER;
tf->eax = 0; tf->ecx = 0; tf->edx = 0; tf->ebx = 0;
tf->ebp = 0; tf->esi = 0; tf->edi = 0;
tf->eip = elf_header->e_entry;
tf->cs = SEG_UCODE | DPL_USER;
tf->eflags = FL_IF;
tf->usermode_esp = user_esp;
tf->usermode_ss = SEG_UDATA | DPL_USER;
execve_return(tf);
return 0;
}
int sys_chdir(TrapFrame *tf)
{
//strcat(current->cwd->fat->path, "/");
@@ -355,6 +438,10 @@ void handle_syscall(TrapFrame *tf)
case 6://close
tf->eax = sys_close(tf);
break;
case 11://execve
tf->eax = sys_execve(tf);
break;
case 12://chdir
tf->eax = sys_chdir(tf);