diff options
| author | manuel <manuel@mausz.at> | 2012-03-27 17:41:50 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-03-27 17:41:50 +0200 |
| commit | 9dad8ab2c72b9696ddd1324557eb5373f4f56b0a (patch) | |
| tree | 152a4b3fce48fc075f404b5caaf691d569f54f31 /userprog | |
| parent | 958397c44b1dc388ad23bf6b8599062c66bb142a (diff) | |
| download | progos-9dad8ab2c72b9696ddd1324557eb5373f4f56b0a.tar.gz progos-9dad8ab2c72b9696ddd1324557eb5373f4f56b0a.tar.bz2 progos-9dad8ab2c72b9696ddd1324557eb5373f4f56b0a.zip | |
parse the arguments and populate the argv entries accordingly
Diffstat (limited to 'userprog')
| -rw-r--r-- | userprog/process.c | 86 |
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, | |||
| 591 | static bool | 591 | static bool |
| 592 | setup_stack (void **esp, const char *args) | 592 | setup_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 | } |
