[elf] Separate exec and system
This commit is contained in:
parent
3e3c7fb544
commit
7cf04ad13e
@ -35,69 +35,79 @@ exec(
|
||||
int argc, /* Argument count (ie, /bin/echo hello world = 3) */
|
||||
char ** argv /* Argument strings (including executable path) */
|
||||
) {
|
||||
/* This is technically system(), so we're forking */
|
||||
int child = fork();
|
||||
if (child == 0) {
|
||||
/* Open the file */
|
||||
fs_node_t * file = kopen(path,0);
|
||||
if (!file) {
|
||||
/* Command not found */
|
||||
kexit(127);
|
||||
}
|
||||
/* Read in the binary contents */
|
||||
Elf32_Header * header = (Elf32_Header *)malloc(file->length + 100);
|
||||
read_fs(file, 0, file->length, (uint8_t *)header);
|
||||
/* Open the file */
|
||||
fs_node_t * file = kopen(path,0);
|
||||
if (!file) {
|
||||
/* Command not found */
|
||||
kexit(127);
|
||||
}
|
||||
/* Read in the binary contents */
|
||||
Elf32_Header * header = (Elf32_Header *)malloc(file->length + 100);
|
||||
read_fs(file, 0, file->length, (uint8_t *)header);
|
||||
|
||||
/* Alright, we've read the binary, time to load the loadable sections */
|
||||
/* Verify the magic */
|
||||
if ( header->e_ident[0] != ELFMAG0 ||
|
||||
header->e_ident[1] != ELFMAG1 ||
|
||||
header->e_ident[2] != ELFMAG2 ||
|
||||
header->e_ident[3] != ELFMAG3) {
|
||||
/* What? This isn't an ELF... */
|
||||
kprintf("Fatal: Not a valid ELF executable.\n");
|
||||
free(header);
|
||||
close_fs(file);
|
||||
kexit(127);
|
||||
}
|
||||
|
||||
/* Load the loadable segments from the binary */
|
||||
for (uintptr_t x = 0; x < header->e_shentsize * header->e_shnum; x += header->e_shentsize) {
|
||||
/* read a section header */
|
||||
Elf32_Shdr * shdr = (Elf32_Shdr *)((uintptr_t)header + (header->e_shoff + x));
|
||||
if (shdr->sh_addr) {
|
||||
/* If this is a loadable section, load it up. */
|
||||
if (shdr->sh_addr < current_task->entry) {
|
||||
/* If this is the lowest entry point, store it for memory reasons */
|
||||
current_task->entry = shdr->sh_addr;
|
||||
}
|
||||
if (shdr->sh_addr + shdr->sh_size - current_task->entry > current_task->image_size) {
|
||||
/* We also store the total size of the memory region used by the application */
|
||||
current_task->image_size = shdr->sh_addr + shdr->sh_size - current_task->entry;
|
||||
}
|
||||
for (uintptr_t i = 0; i < shdr->sh_size; i += 0x1000) {
|
||||
/* This doesn't care if we already allocated this page */
|
||||
alloc_frame(get_page(shdr->sh_addr + i, 1, current_directory), 0, 1);
|
||||
}
|
||||
/* Copy the section into memory */
|
||||
memcpy((void *)(shdr->sh_addr), (void *)((uintptr_t)header + shdr->sh_offset), shdr->sh_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the entry point to the code segment */
|
||||
uintptr_t entry = (uintptr_t)header->e_entry;
|
||||
|
||||
/* Free the space we used for the ELF headers and files */
|
||||
/* Alright, we've read the binary, time to load the loadable sections */
|
||||
/* Verify the magic */
|
||||
if ( header->e_ident[0] != ELFMAG0 ||
|
||||
header->e_ident[1] != ELFMAG1 ||
|
||||
header->e_ident[2] != ELFMAG2 ||
|
||||
header->e_ident[3] != ELFMAG3) {
|
||||
/* What? This isn't an ELF... */
|
||||
kprintf("Fatal: Not a valid ELF executable.\n");
|
||||
free(header);
|
||||
close_fs(file);
|
||||
kexit(127);
|
||||
}
|
||||
|
||||
/* Go go go */
|
||||
enter_user_jmp(entry, argc, argv);
|
||||
/* Load the loadable segments from the binary */
|
||||
for (uintptr_t x = 0; x < header->e_shentsize * header->e_shnum; x += header->e_shentsize) {
|
||||
/* read a section header */
|
||||
Elf32_Shdr * shdr = (Elf32_Shdr *)((uintptr_t)header + (header->e_shoff + x));
|
||||
if (shdr->sh_addr) {
|
||||
/* If this is a loadable section, load it up. */
|
||||
if (shdr->sh_addr < current_task->entry) {
|
||||
/* If this is the lowest entry point, store it for memory reasons */
|
||||
current_task->entry = shdr->sh_addr;
|
||||
}
|
||||
if (shdr->sh_addr + shdr->sh_size - current_task->entry > current_task->image_size) {
|
||||
/* We also store the total size of the memory region used by the application */
|
||||
current_task->image_size = shdr->sh_addr + shdr->sh_size - current_task->entry;
|
||||
}
|
||||
for (uintptr_t i = 0; i < shdr->sh_size; i += 0x1000) {
|
||||
/* This doesn't care if we already allocated this page */
|
||||
alloc_frame(get_page(shdr->sh_addr + i, 1, current_directory), 0, 1);
|
||||
}
|
||||
/* Copy the section into memory */
|
||||
memcpy((void *)(shdr->sh_addr), (void *)((uintptr_t)header + shdr->sh_offset), shdr->sh_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the entry point to the code segment */
|
||||
uintptr_t entry = (uintptr_t)header->e_entry;
|
||||
|
||||
/* Free the space we used for the ELF headers and files */
|
||||
free(header);
|
||||
close_fs(file);
|
||||
|
||||
/* Go go go */
|
||||
enter_user_jmp(entry, argc, argv);
|
||||
|
||||
/* We should never reach this code */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
system(
|
||||
char * path, /* Path to the executable to run */
|
||||
int argc, /* Argument count (ie, /bin/echo hello world = 3) */
|
||||
char ** argv /* Argument strings (including executable path) */
|
||||
) {
|
||||
int child = fork();
|
||||
if (child == 0) {
|
||||
exec(path,argc,argv);
|
||||
kexit(0x5ADFACE);
|
||||
return -1;
|
||||
} else {
|
||||
/* We are emulating system(), so we need to wait for the child
|
||||
/* We are system(), so we need to wait for the child
|
||||
* application to exit before we can continue. */
|
||||
/* Get the child task. */
|
||||
task_t * volatile child_task = gettask(child);
|
||||
@ -112,8 +122,6 @@ exec(
|
||||
/* Grab the child's return value */
|
||||
return child_task->retval;
|
||||
}
|
||||
/* Something went terribly wrong. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -213,7 +213,7 @@ start_shell() {
|
||||
if (tokenid < 2) {
|
||||
continue;
|
||||
}
|
||||
int ret = exec(argv[1],tokenid - 1, &argv[1]);
|
||||
int ret = system(argv[1],tokenid - 1, &argv[1]);
|
||||
kprintf("Returned %d\n", ret);
|
||||
} else if (!strcmp(cmd, "boredom")) {
|
||||
int x = 30;
|
||||
@ -263,7 +263,7 @@ start_shell() {
|
||||
kprintf("Unrecognized command: %s\n", cmd);
|
||||
} else {
|
||||
close_fs(chd);
|
||||
exec(filename, tokenid, argv);
|
||||
system(filename, tokenid, argv);
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
|
@ -283,6 +283,7 @@ void enable_fpu();
|
||||
|
||||
/* ELF */
|
||||
int exec( char *, int, char **);
|
||||
int system( char *, int, char **);
|
||||
|
||||
/* Sytem Calls */
|
||||
void syscalls_install();
|
||||
|
@ -157,5 +157,21 @@ int main(struct multiboot *mboot, uint32_t mboot_mag, uintptr_t esp)
|
||||
|
||||
start_shell();
|
||||
|
||||
fork();
|
||||
|
||||
if (getpid() == 0) {
|
||||
char * args[] = {
|
||||
"/bin/yes",
|
||||
"\033[1;32mA\033[0m"
|
||||
};
|
||||
exec("/bin/yes",2,args);
|
||||
} else {
|
||||
char * args[] = {
|
||||
"/bin/yes",
|
||||
"\033[1;31mB\033[0m"
|
||||
};
|
||||
exec("/bin/yes",2,args);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user