diff --git a/pintos-env/pintos/userprog/process.c b/pintos-env/pintos/userprog/process.c index 92990d1..9b14740 100755 --- a/pintos-env/pintos/userprog/process.c +++ b/pintos-env/pintos/userprog/process.c @@ -17,6 +17,18 @@ #include "threads/palloc.h" #include "threads/thread.h" #include "threads/vaddr.h" +#include "lib/kernel/list.h" + +static struct arg { + struct list_elem elem; + char* data; + void* addr; +}; + +struct arguments { + int argc; + char** argv; +}; static thread_func start_process NO_RETURN; static bool load (const char *cmdline, void (**eip) (void), void **esp); @@ -50,22 +62,99 @@ process_execute (const char *file_name) static void start_process (void *file_name_) { - char *file_name = file_name_; + char *cmdline = file_name_; + struct intr_frame if_; bool success; + // Populate the stack + struct list arg_list; + list_init(&arg_list); + + char *token, *save_ptr; + + // tokenize cmdline + for (token = strtok_r(cmdline, " ", &save_ptr); token != NULL; + token = strtok_r(NULL, " ", &save_ptr)) { + struct arg* it = malloc(sizeof(struct arg)); + it->data = token; + printf("list_elem pushed: %s\n", token); + list_push_back(&arg_list, it); + } + + list_reverse(&arg_list); + + printf("ciao mamma!\n"); + struct list_elem* e; + for (e = list_begin(&arg_list); e != list_end(&arg_list); e = list_next(e)) { + struct arg* i = list_entry(e, struct arg, elem); + printf("list_elem: %s\n", i->data); + } + + // put argv[i][...] on stack and keep track of addresses + char* program_name; + for (e = list_begin(&arg_list); e != list_end(&arg_list); e = list_next(e)) { + struct arg* i = list_entry(e, struct arg, elem); + size_t bytes = strlen(i->data) + 1; + if_.esp -= bytes; + i->addr = if_.esp; + memcpy(&(if_.esp), i->data, bytes); + } + + // put terminator of argv[] (argv[4] in example) + size_t bytes = sizeof(void*); // size of pointers on stack + if_.esp -= bytes; + printf("bytes: %d %X\n", bytes, if_.esp); + + { + uint32_t write[1] = {0}; + memcpy(&(if_.esp), write, sizeof(uint32_t)); + } + + // put addresses of argv[i] on stack + for (e = list_begin(&arg_list); e != list_end(&arg_list);) { + struct arg* i = list_entry(e, struct arg, elem); + if_.esp -= bytes; + { + uint32_t write[1] = {i->addr}; + memcpy(&(if_.esp), write, sizeof(uint32_t)); + } + e = list_next(e); + + } + + //put argv + if_.esp -= bytes; + { + uint32_t write[1] = {if_.esp + bytes}; + memcpy(&(if_.esp), write, sizeof(uint32_t)); + } + //put argc + if_.esp -= bytes; + { + uint32_t write[1] = {list_size(&arg_list) - 1}; + memcpy(&(if_.esp), write, sizeof(uint32_t)); + } + + //put return address + if_.esp -= bytes; + { + uint32_t write[1] = {0}; + memcpy(&(if_.esp), write, sizeof(uint32_t)); + } + /* Initialize interrupt frame and load executable. */ memset (&if_, 0, sizeof if_); if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; if_.cs = SEL_UCSEG; if_.eflags = FLAG_IF | FLAG_MBS; - success = load (file_name, &if_.eip, &if_.esp); + success = load (program_name, &if_.eip, &if_.esp); /* If load failed, quit. */ - palloc_free_page (file_name); + palloc_free_page (program_name); if (!success) thread_exit (); - + /* Start the user process by simulating a return from an interrupt, implemented by intr_exit (in threads/intr-stubs.S). Because intr_exit takes all of its