[elf] Separate exec and system

This commit is contained in:
Kevin Lange 2011-04-15 17:33:19 -05:00
parent 3e3c7fb544
commit 7cf04ad13e
4 changed files with 84 additions and 59 deletions

View File

@ -35,69 +35,79 @@ exec(
int argc, /* Argument count (ie, /bin/echo hello world = 3) */ int argc, /* Argument count (ie, /bin/echo hello world = 3) */
char ** argv /* Argument strings (including executable path) */ char ** argv /* Argument strings (including executable path) */
) { ) {
/* This is technically system(), so we're forking */ /* Open the file */
int child = fork(); fs_node_t * file = kopen(path,0);
if (child == 0) { if (!file) {
/* Open the file */ /* Command not found */
fs_node_t * file = kopen(path,0); kexit(127);
if (!file) { }
/* Command not found */ /* Read in the binary contents */
kexit(127); Elf32_Header * header = (Elf32_Header *)malloc(file->length + 100);
} read_fs(file, 0, file->length, (uint8_t *)header);
/* 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 */ /* Alright, we've read the binary, time to load the loadable sections */
/* Verify the magic */ /* Verify the magic */
if ( header->e_ident[0] != ELFMAG0 || if ( header->e_ident[0] != ELFMAG0 ||
header->e_ident[1] != ELFMAG1 || header->e_ident[1] != ELFMAG1 ||
header->e_ident[2] != ELFMAG2 || header->e_ident[2] != ELFMAG2 ||
header->e_ident[3] != ELFMAG3) { header->e_ident[3] != ELFMAG3) {
/* What? This isn't an ELF... */ /* What? This isn't an ELF... */
kprintf("Fatal: Not a valid ELF executable.\n"); 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 */
free(header); free(header);
close_fs(file); close_fs(file);
kexit(127);
}
/* Go go go */ /* Load the loadable segments from the binary */
enter_user_jmp(entry, argc, argv); 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 */ /* 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); kexit(0x5ADFACE);
return -1;
} else { } 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. */ * application to exit before we can continue. */
/* Get the child task. */ /* Get the child task. */
task_t * volatile child_task = gettask(child); task_t * volatile child_task = gettask(child);
@ -112,8 +122,6 @@ exec(
/* Grab the child's return value */ /* Grab the child's return value */
return child_task->retval; return child_task->retval;
} }
/* Something went terribly wrong. */
return -1;
} }
/* /*

View File

@ -213,7 +213,7 @@ start_shell() {
if (tokenid < 2) { if (tokenid < 2) {
continue; continue;
} }
int ret = exec(argv[1],tokenid - 1, &argv[1]); int ret = system(argv[1],tokenid - 1, &argv[1]);
kprintf("Returned %d\n", ret); kprintf("Returned %d\n", ret);
} else if (!strcmp(cmd, "boredom")) { } else if (!strcmp(cmd, "boredom")) {
int x = 30; int x = 30;
@ -263,7 +263,7 @@ start_shell() {
kprintf("Unrecognized command: %s\n", cmd); kprintf("Unrecognized command: %s\n", cmd);
} else { } else {
close_fs(chd); close_fs(chd);
exec(filename, tokenid, argv); system(filename, tokenid, argv);
} }
free(filename); free(filename);
} }

View File

@ -283,6 +283,7 @@ void enable_fpu();
/* ELF */ /* ELF */
int exec( char *, int, char **); int exec( char *, int, char **);
int system( char *, int, char **);
/* Sytem Calls */ /* Sytem Calls */
void syscalls_install(); void syscalls_install();

View File

@ -157,5 +157,21 @@ int main(struct multiboot *mboot, uint32_t mboot_mag, uintptr_t esp)
start_shell(); 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; return 0;
} }