syscalls: implement basic execve syscall, no argc, argv, envp support yet
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
// callee.c
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[], char *envp[]) {
|
||||
printf("--- In callee.c ---\n");
|
||||
printf("This program has taken over the process.\n");
|
||||
|
||||
printf("argc: %d\n", argc);
|
||||
|
||||
printf("\nArguments (argv):\n");
|
||||
for (int i = 0; argv[i] != NULL; i++) {
|
||||
printf(" argv[%d]: %s\n", i, argv[i]);
|
||||
}
|
||||
|
||||
printf("\nEnvironment Variables (envp):\n");
|
||||
for (int i = 0; envp[i] != NULL; i++) {
|
||||
printf(" %s\n", envp[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// caller.c
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
printf("--- In caller.c ---\n");
|
||||
printf("This message is from the original program.\n");
|
||||
printf("Calling execve to run './callee'...\n\n");
|
||||
|
||||
// Arguments for the new program
|
||||
// The first argument is conventionally the program name
|
||||
char *argv[] = {NULL}; //{ "./callee", "first_arg", "second_arg", NULL };
|
||||
|
||||
// Environment variables for the new program
|
||||
char *envp[] = {NULL}; //{ "CUSTOM_VAR=Hello from caller!", "ANOTHER_VAR=123", NULL };
|
||||
|
||||
// The execve system call
|
||||
// The first argument is the path to the executable
|
||||
// The second is the array of arguments
|
||||
// The third is the array of environment variables
|
||||
execve("callee.", argv, envp);
|
||||
|
||||
// This part of the code will only be reached if execve fails
|
||||
perror("execve failed");
|
||||
return 1;
|
||||
}
|
||||
@@ -3,4 +3,10 @@
|
||||
#include "../include/vfs.h"
|
||||
#include "../include/lib9660.h"
|
||||
|
||||
#define DivRoundUp(number, divisor) ((number + divisor - 1) / divisor)
|
||||
|
||||
#define USER_STACK_TOP 0xBFFFFFF0 // Top of user space memory
|
||||
#define USER_STACK_SIZE 0x4000 // 16KB stack (4 pages)
|
||||
#define USER_STACK_BOTTOM (USER_STACK_TOP - USER_STACK_SIZE)
|
||||
|
||||
void exec_from_file(const char* filename, const char* dirname);
|
||||
@@ -19,4 +19,6 @@ size_t vfs_read_file_length(l9660_file *file, uint8_t* buffer, size_t length);
|
||||
|
||||
void test_iso9660();
|
||||
|
||||
int vsf_read_file_by_path(const char* path, uint8_t** buffer, l9660_dir* dir);
|
||||
|
||||
#endif
|
||||
@@ -190,3 +190,35 @@ void test_iso9660()
|
||||
printf("0x%X\n", total_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
int vsf_read_file_by_path(const char* path, uint8_t** buffer, l9660_dir* dir)
|
||||
{
|
||||
l9660_file* file = (l9660_file*)malloc(sizeof(l9660_file));
|
||||
|
||||
l9660_status err;
|
||||
|
||||
err = l9660_openat(file, dir, path);
|
||||
if (err != L9660_OK)
|
||||
{
|
||||
debug_log("read_file: err: 0x%X\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
debug_log("HEHE %s\n", path);
|
||||
|
||||
l9660_seek(file, L9660_SEEK_END, 0);
|
||||
uint32_t file_size = l9660_tell(file);
|
||||
debug_log("file_size: %X\n", file_size);
|
||||
l9660_seek(file, L9660_SEEK_SET, 0);
|
||||
|
||||
*buffer = (uint8_t*)malloc(file_size);
|
||||
debug_log("eeee\n");
|
||||
|
||||
size_t read;
|
||||
|
||||
read = vfs_read_file(file, *buffer);
|
||||
free(file);
|
||||
debug_log("bytes read: 0x%X\n", read);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -131,7 +131,7 @@ void kmain(unsigned int magic, unsigned int info)
|
||||
|
||||
mount_fs();
|
||||
|
||||
exec_from_file("main.", ".");
|
||||
exec_from_file("caller.", ".");
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
||||
@@ -6,42 +6,6 @@
|
||||
#include "../include/paging.h"
|
||||
#include "../include/task.h"
|
||||
|
||||
#define DivRoundUp(number, divisor) ((number + divisor - 1) / divisor)
|
||||
|
||||
#define USER_STACK_TOP 0xBFFFFFF0 // Top of user space memory
|
||||
#define USER_STACK_SIZE 0x4000 // 16KB stack (4 pages)
|
||||
#define USER_STACK_BOTTOM (USER_STACK_TOP - USER_STACK_SIZE)
|
||||
|
||||
int read_file(const char* path, uint8_t** buffer, l9660_dir* dir)
|
||||
{
|
||||
l9660_file* file = (l9660_file*)malloc(sizeof(l9660_file));
|
||||
|
||||
l9660_status err;
|
||||
|
||||
err = l9660_openat(file, dir, path);
|
||||
if (err != L9660_OK)
|
||||
{
|
||||
debug_log("read_file: err: 0x%X\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
l9660_seek(file, L9660_SEEK_END, 0);
|
||||
uint32_t file_size = l9660_tell(file);
|
||||
debug_log("file_size: %X\n", file_size);
|
||||
l9660_seek(file, L9660_SEEK_SET, 0);
|
||||
|
||||
*buffer = (uint8_t*)malloc(file_size);
|
||||
debug_log("eeee\n");
|
||||
|
||||
size_t read;
|
||||
|
||||
read = vfs_read_file(file, *buffer);
|
||||
free(file);
|
||||
debug_log("bytes read: 0x%X\n", read);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void exec_from_file(const char* filename, const char* dirname)
|
||||
{
|
||||
asm volatile("cli");
|
||||
@@ -58,7 +22,7 @@ void exec_from_file(const char* filename, const char* dirname)
|
||||
|
||||
uint32_t bss_start, bss_end;
|
||||
|
||||
err = read_file(filename, &file, &dir);
|
||||
err = vsf_read_file_by_path(filename, &file, &dir);
|
||||
|
||||
if(err != 0)
|
||||
{
|
||||
|
||||
@@ -31,5 +31,20 @@ sys_exit_handler:
|
||||
; Возвращаемся в Ring 3
|
||||
iret
|
||||
|
||||
global execve_return
|
||||
|
||||
execve_return:
|
||||
mov esp, [esp+4]
|
||||
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
popa
|
||||
|
||||
add esp, 8
|
||||
|
||||
iret
|
||||
|
||||
section .data
|
||||
sys_exit_msg: db "Returned from Ring 3", 0
|
||||
@@ -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, "/");
|
||||
@@ -356,6 +439,10 @@ void handle_syscall(TrapFrame *tf)
|
||||
tf->eax = sys_close(tf);
|
||||
break;
|
||||
|
||||
case 11://execve
|
||||
tf->eax = sys_execve(tf);
|
||||
break;
|
||||
|
||||
case 12://chdir
|
||||
tf->eax = sys_chdir(tf);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user