From 9dad8ab2c72b9696ddd1324557eb5373f4f56b0a Mon Sep 17 00:00:00 2001 From: manuel Date: Tue, 27 Mar 2012 17:41:50 +0200 Subject: parse the arguments and populate the argv entries accordingly --- userprog/process.c | 86 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/userprog/process.c b/userprog/process.c index bd4f6b0..bc8a1a9 100644 --- a/userprog/process.c +++ b/userprog/process.c @@ -591,8 +591,11 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage, static bool setup_stack (void **esp, const char *args) { - uint8_t *kpage = NULL, stack_total; + uint8_t *kpage = NULL; const char *name = thread_current ()->name; + uint8_t *argv_cur, *argv_end = PHYS_BASE; + int argc = 0; + unsigned argslen = strlen(args); kpage = palloc_get_page (PAL_USER | PAL_ZERO); if (kpage == NULL) @@ -602,31 +605,82 @@ setup_stack (void **esp, const char *args) palloc_free_page (kpage); return false; } - printf("cmd=%s\n", name); - printf("args=%s\n", args); *esp = PHYS_BASE; - printf("esp=%p\n", *esp); /* copy arguments to stack */ - *esp -= strlen(args) + 1; - memcpy(*esp, args, strlen(args) + 1); - printf("esp=%p, off=%d\n", *esp, strlen(args) + 1); + if (argslen > 0) + { + argslen += 1; /* add the trailing \0 */ + *esp -= argslen; + memcpy(*esp, args, argslen); + argv_end = *esp; + } /* copy executable name to stack */ *esp -= strlen(name) + 1; memcpy(*esp, name, strlen(name) + 1); - printf("esp=%p, off=%d\n", *esp, strlen(name) + 1); - /* word align our stack so far */ - stack_total = PHYS_BASE - *esp; - printf("stack_total=%u\n", stack_total); - printf("unaligned=%p off=%d\n", *esp, PHYS_BASE - *esp); - *esp -= (4 - stack_total % sizeof(char *)); /* thanks to thomas */ - printf("aligned=%p off=%d\n", *esp, PHYS_BASE - *esp); + /* align our stack so far by word-size */ + *esp -= (sizeof(uint32_t) - (PHYS_BASE - *esp) % sizeof(uint32_t)); /* thanks to thomas & edy */ + + /* terminate argv[] array by NULL ptr */ + *esp -= sizeof(uint32_t); + *(uint32_t *) *esp = '\0'; + + /* push the argv[] entries */ + if (argslen > 0) + { + /* we walk through our already pushed arguments in reverse order and + replace every occurrence of the space-character with '\0'-character + due to the fact we we walk in reverse order we can easily populate + the pointers to the elements of argv[] too */ + for(argv_cur = PHYS_BASE - 1; argv_cur >= argv_end; argv_cur--) + { + /* check for space-character and replace if necessary */ + if (*argv_cur == ' ') + { + *argv_cur = '\0'; + + /* since we walk in reverse order and already have replaced a + character we simply check the preceding character. if it's + a non-'\0'-character we know an argument starts here */ + if (*(argv_cur + 1) != '\0') + { + /* push pointer to argument */ + *esp -= sizeof(uint32_t); + *(uint32_t *) *esp = (uint32_t) argv_cur + 1; + argc++; + } + } + } + + /* our loop above doesn't check/push the first argument as it's the + end of the loop. so let's do that */ + if (*(argv_cur + 1) != '\0') + { + *esp -= sizeof(uint32_t); + *(uint32_t *) *esp = (uint32_t) argv_cur + 1; + argc++; + } + } + + /* push argv[0] (executable name) */ + *esp -= sizeof(uint32_t); + *(uint32_t *) *esp = (uint32_t) (PHYS_BASE - (argslen + strlen(name) + 1)); + argc++; + + /* push pointer to argv[]. this is simple as it's our current address */ + *(uint32_t *) (*esp - 4) = *(uint32_t *) esp; + *esp -= sizeof(uint32_t); + + /* push argc */ + *esp -= sizeof(uint32_t); + *(uint32_t *) *esp = argc; - /* Currently we assume that 'argc = 0' */ - *esp = PHYS_BASE - 12; + /* push fake return address */ + *esp -= sizeof(uint32_t); + *(uint32_t *) *esp = 0; return true; } -- cgit v1.2.3