diff --git a/userprog/argument_parsing.h b/userprog/argument_parsing.h index 585efe1b65621145e6316efb3b7ecfcc35c470d7..b84be707d1c4adb0e17dfeb8f92c75ce4908e8e7 100644 --- a/userprog/argument_parsing.h +++ b/userprog/argument_parsing.h @@ -25,9 +25,10 @@ int parse_arguments(const char* command_line, char**argv); /* * Given stack pointer `esp`, argument count `argc` and arguments array `argv`, * Populates the stack pointed to by the stack pointer with the given arguments. - * TODO: clarify what, if anything, `esp` stands for and rename it to something - * clearer if possible. + * esp is the initial stack pointer from process.c, + * I have used stackPointer as the name as that makes sense inside, + * populate_stack, in process.c esp has been renamed to initial_stack_pointer */ -void populate_stack(void* esp, int argc, char** argv); +void populate_stack(void** stack_pointer, int argc, char** argv); #endif /* userprog/argument_parsing.h */ diff --git a/userprog/populate_stack.c b/userprog/populate_stack.c index 6a7bb2e4897aa6e05b7cd050e2ebff4e41445525..d82e18fb72b85a3ac7546f23e393812534d1f83a 100644 --- a/userprog/populate_stack.c +++ b/userprog/populate_stack.c @@ -1,6 +1,55 @@ -#include "userprog/argument_parsing.h" +/* + * populates_stack.c --implements function for populating the program stack + * + * + * Authored by Alex Stratford + */ +#include <string.h> +#include "threads/vaddr.h" +#include "userprog/argument_parsing.h" -void populate_stack(void* esp, int argc, char** argv) { - #warning "Implement me" + // Adds the move value to the stack pointer +static void move_stack_pointer(void** stack_pointer, int move_value) { + *stack_pointer = *stack_pointer + move_value; } + +void populate_stack(void** stack_pointer, int argc, char** argv) { + *stack_pointer = PHYS_BASE; + int i = argc; + + uint32_t * arr[argc]; // Creates an array to hold arguments in the stack + + while (--i >= 0) + { + *stack_pointer = *stack_pointer - (strlen(argv[i]) + 1) * sizeof(char); + + arr[i] = (uint32_t *)*stack_pointer; // Assigns the current reference of the stack pointer to the array + + memcpy(*stack_pointer, argv[i], strlen(argv[i]) + 1); + } + + move_stack_pointer(stack_pointer, -4); //Moves the stack pointer back 4 + + (*(int *)(*stack_pointer)) = 0;//sentinel + i = argc; + + while (--i >= 0) + { + move_stack_pointer(stack_pointer, -4); //32bit Moves the stack pointer back 4 + + (*(uint32_t **)(*stack_pointer)) = arr[i]; + } + + move_stack_pointer(stack_pointer, -4); + move_stack_pointer(stack_pointer, 4); //Moves the stack pointer forwards 4 + // TODO: Test if still required in later version + + (*(uintptr_t **)(*stack_pointer)) = *stack_pointer; + move_stack_pointer(stack_pointer, -4); //Moves the stack pointer back 4 + + *(int *)(*stack_pointer) = argc; + move_stack_pointer(stack_pointer, -4); //Moves the stack pointer back 4 + + (*(int *)(*stack_pointer)) = 0; +} \ No newline at end of file diff --git a/userprog/process.c b/userprog/process.c index 5fbfb38e05f7d429a994a2e87d71221068c56531..6577694d14e487db6c346888600c65ef9e9427a0 100644 --- a/userprog/process.c +++ b/userprog/process.c @@ -20,8 +20,7 @@ #include "threads/vaddr.h" static thread_func start_process NO_RETURN; -static bool load (const char *command, void (**eip) (void), void **esp); - +static bool load (const char *cmdline, void (**eip) (void), void **initial_stack_pointer); /* Starts a new thread running a user program loaded by parsing COMMAND. The new thread may be scheduled (and may even exit) before process_execute() returns. Returns the new process's @@ -78,7 +77,7 @@ start_process (void *file_name_) interrupt, implemented by intr_exit (in threads/intr-stubs.S). Because intr_exit takes all of its arguments on the stack in the form of a `struct intr_frame', - we just point the stack pointer (%esp) to our stack frame + we just point the stack pointer (%initial_stack_pointer) to our stack frame and jump to it. */ asm volatile ("movl %0, %%esp; jmp intr_exit" : : "g" (&if_) : "memory"); NOT_REACHED (); @@ -211,7 +210,7 @@ struct Elf32_Phdr #define PF_W 2 /* Writable. */ #define PF_R 4 /* Readable. */ -static bool setup_stack (void **esp, char **argv, int argc); +static bool setup_stack(void **initial_stack_pointer, char **argv, int argc); static bool validate_segment (const struct Elf32_Phdr *, struct file *); static bool load_segment (struct file *file, off_t ofs, uint8_t *upage, uint32_t read_bytes, uint32_t zero_bytes, @@ -219,10 +218,10 @@ static bool load_segment (struct file *file, off_t ofs, uint8_t *upage, /* Loads an ELF executable from COMMAND into the current thread. Stores the executable's entry point into *EIP - and its initial stack pointer into *ESP. + and its initial stack pointer into *initial_stack_pointer. Returns true if successful, false otherwise. */ bool -load (const char *command, void (**eip) (void), void **esp) +load (const char *cmdline, void (**eip) (void), void **initial_stack_pointer) { struct thread *t = thread_current (); struct Elf32_Ehdr ehdr; @@ -235,7 +234,7 @@ load (const char *command, void (**eip) (void), void **esp) char* argv[USERPROG_ARGV_COUNT]; // copy the command string so we have a separate copy to manipulate char command_copy[USERPROG_RAW_ARGV_LENGTH]; - strlcpy(command_copy, command, USERPROG_RAW_ARGV_LENGTH); + strlcpy(command_copy, cmdline, USERPROG_RAW_ARGV_LENGTH); int argc = parse_arguments(command_copy, argv); char* file_name = argv[0]; // file name is always argument 0 @@ -250,12 +249,12 @@ load (const char *command, void (**eip) (void), void **esp) if (file == NULL) { - printf ("load: %s: open failed\n", file_name); + printf ("load: %s: open failed\n", cmdline); goto done; } /* Read and verify executable header. */ - if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr + if (file_read(file, &ehdr, sizeof ehdr) != sizeof ehdr || memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7) || ehdr.e_type != 2 || ehdr.e_machine != 3 @@ -263,7 +262,7 @@ load (const char *command, void (**eip) (void), void **esp) || ehdr.e_phentsize != sizeof (struct Elf32_Phdr) || ehdr.e_phnum > 1024) { - printf ("load: %s: error loading executable\n", file_name); + printf ("load: %s: error loading executable\n", cmdline); goto done; } @@ -327,7 +326,7 @@ load (const char *command, void (**eip) (void), void **esp) } /* Set up stack. */ - if (!setup_stack (esp, argv, argc)) + if (!setup_stack (initial_stack_pointer, argv, argc)) goto done; /* Start address. */ @@ -452,7 +451,7 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage, /* Create a minimal stack by mapping a zeroed page at the top of user virtual memory. */ static bool -setup_stack (void **esp, char **argv, int argc) +setup_stack (void **initial_stack_pointer, char **argv, int argc) { uint8_t *kpage; bool success = false; @@ -462,8 +461,8 @@ setup_stack (void **esp, char **argv, int argc) { success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true); if (success) { - *esp = PHYS_BASE - 12; - populate_stack(esp, argc, argv); + *initial_stack_pointer = PHYS_BASE - 12; + populate_stack(initial_stack_pointer, argc, argv); } else palloc_free_page (kpage); } diff --git a/utils/pintos b/utils/pintos index 16a725a9ef4dd44351f9b82e911eca1841cd50b1..53942f2427d78512a635eef98ffef3adb9293f56 100755 --- a/utils/pintos +++ b/utils/pintos @@ -929,15 +929,18 @@ sub exec_setitimer { exit (1); } -sub SIGVTALRM { - use Config; - my $i = 0; - foreach my $name (split(' ', $Config{sig_name})) { - return $i if $name eq 'VTALRM'; - $i++; - } - return 0; -} +# This subroutine has been commented out because otherwise if it is not then +# Pintos will refuse to run at all once the code for putting arguments into +# the stack is added +#sub SIGVTALRM { +# use Config; +# my $i = 0; +# foreach my $name (split(' ', $Config{sig_name})) { +# return $i if $name eq 'VTALRM'; +# $i++; +# } +# return 0; +#} # find_in_path ($program) #