summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2012-03-27 17:41:50 +0200
committermanuel <manuel@mausz.at>2012-03-27 17:41:50 +0200
commit9dad8ab2c72b9696ddd1324557eb5373f4f56b0a (patch)
tree152a4b3fce48fc075f404b5caaf691d569f54f31
parent958397c44b1dc388ad23bf6b8599062c66bb142a (diff)
downloadprogos-9dad8ab2c72b9696ddd1324557eb5373f4f56b0a.tar.gz
progos-9dad8ab2c72b9696ddd1324557eb5373f4f56b0a.tar.bz2
progos-9dad8ab2c72b9696ddd1324557eb5373f4f56b0a.zip
parse the arguments and populate the argv entries accordingly
-rw-r--r--userprog/process.c86
1 files 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,
591static bool 591static bool
592setup_stack (void **esp, const char *args) 592setup_stack (void **esp, const char *args)
593{ 593{
594 uint8_t *kpage = NULL, stack_total; 594 uint8_t *kpage = NULL;
595 const char *name = thread_current ()->name; 595 const char *name = thread_current ()->name;
596 uint8_t *argv_cur, *argv_end = PHYS_BASE;
597 int argc = 0;
598 unsigned argslen = strlen(args);
596 599
597 kpage = palloc_get_page (PAL_USER | PAL_ZERO); 600 kpage = palloc_get_page (PAL_USER | PAL_ZERO);
598 if (kpage == NULL) 601 if (kpage == NULL)
@@ -602,31 +605,82 @@ setup_stack (void **esp, const char *args)
602 palloc_free_page (kpage); 605 palloc_free_page (kpage);
603 return false; 606 return false;
604 } 607 }
605 printf("cmd=%s\n", name);
606 printf("args=%s\n", args);
607 608
608 *esp = PHYS_BASE; 609 *esp = PHYS_BASE;
609 printf("esp=%p\n", *esp);
610 610
611 /* copy arguments to stack */ 611 /* copy arguments to stack */
612 *esp -= strlen(args) + 1; 612 if (argslen > 0)
613 memcpy(*esp, args, strlen(args) + 1); 613 {
614 printf("esp=%p, off=%d\n", *esp, strlen(args) + 1); 614 argslen += 1; /* add the trailing \0 */
615 *esp -= argslen;
616 memcpy(*esp, args, argslen);
617 argv_end = *esp;
618 }
615 619
616 /* copy executable name to stack */ 620 /* copy executable name to stack */
617 *esp -= strlen(name) + 1; 621 *esp -= strlen(name) + 1;
618 memcpy(*esp, name, strlen(name) + 1); 622 memcpy(*esp, name, strlen(name) + 1);
619 printf("esp=%p, off=%d\n", *esp, strlen(name) + 1);
620 623
621 /* word align our stack so far */ 624 /* align our stack so far by word-size */
622 stack_total = PHYS_BASE - *esp; 625 *esp -= (sizeof(uint32_t) - (PHYS_BASE - *esp) % sizeof(uint32_t)); /* thanks to thomas & edy */
623 printf("stack_total=%u\n", stack_total); 626
624 printf("unaligned=%p off=%d\n", *esp, PHYS_BASE - *esp); 627 /* terminate argv[] array by NULL ptr */
625 *esp -= (4 - stack_total % sizeof(char *)); /* thanks to thomas */ 628 *esp -= sizeof(uint32_t);
626 printf("aligned=%p off=%d\n", *esp, PHYS_BASE - *esp); 629 *(uint32_t *) *esp = '\0';
630
631 /* push the argv[] entries */
632 if (argslen > 0)
633 {
634 /* we walk through our already pushed arguments in reverse order and
635 replace every occurrence of the space-character with '\0'-character
636 due to the fact we we walk in reverse order we can easily populate
637 the pointers to the elements of argv[] too */
638 for(argv_cur = PHYS_BASE - 1; argv_cur >= argv_end; argv_cur--)
639 {
640 /* check for space-character and replace if necessary */
641 if (*argv_cur == ' ')
642 {
643 *argv_cur = '\0';
644
645 /* since we walk in reverse order and already have replaced a
646 character we simply check the preceding character. if it's
647 a non-'\0'-character we know an argument starts here */
648 if (*(argv_cur + 1) != '\0')
649 {
650 /* push pointer to argument */
651 *esp -= sizeof(uint32_t);
652 *(uint32_t *) *esp = (uint32_t) argv_cur + 1;
653 argc++;
654 }
655 }
656 }
657
658 /* our loop above doesn't check/push the first argument as it's the
659 end of the loop. so let's do that */
660 if (*(argv_cur + 1) != '\0')
661 {
662 *esp -= sizeof(uint32_t);
663 *(uint32_t *) *esp = (uint32_t) argv_cur + 1;
664 argc++;
665 }
666 }
667
668 /* push argv[0] (executable name) */
669 *esp -= sizeof(uint32_t);
670 *(uint32_t *) *esp = (uint32_t) (PHYS_BASE - (argslen + strlen(name) + 1));
671 argc++;
672
673 /* push pointer to argv[]. this is simple as it's our current address */
674 *(uint32_t *) (*esp - 4) = *(uint32_t *) esp;
675 *esp -= sizeof(uint32_t);
676
677 /* push argc */
678 *esp -= sizeof(uint32_t);
679 *(uint32_t *) *esp = argc;
627 680
628 /* Currently we assume that 'argc = 0' */ 681 /* push fake return address */
629 *esp = PHYS_BASE - 12; 682 *esp -= sizeof(uint32_t);
683 *(uint32_t *) *esp = 0;
630 684
631 return true; 685 return true;
632} 686}