diff --git a/src/userprog/process.c b/src/userprog/process.c index d51339a4aff8ec7aae340ae87035ef64358853fd..890165a8d922983315e45ae0a1c500acfa327f27 100644 --- a/src/userprog/process.c +++ b/src/userprog/process.c @@ -1,3 +1,571 @@ +Skip to content +GitLab +Menu + +sa2-alarjani +P +Pintos_Student +Project information +Repository +Issues +0 +Security & Compliance +Deployments +Packages & Registries +Analytics +Wiki +Settings + +Close sidebar +Open sidebar +sa2-alarjani +Pintos_Student +master +pintos_student +src +userprog +process.c + + + + +Update src/userprog/process.c +sa2-alarjani authored 1 day ago +a984983a +process.c +15.67 KiB +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 #include "userprog/process.h" #include <debug.h> #include <inttypes.h> @@ -17,10 +585,8 @@ #include "threads/palloc.h" #include "threads/thread.h" #include "threads/vaddr.h" - static thread_func start_process NO_RETURN; static bool load (const char *cmdline, void (**eip) (void), void **esp); - /* Starts a new thread running a user program loaded from FILENAME. The new thread may be scheduled (and may even exit) before process_execute() returns. Returns the new process's @@ -28,24 +594,24 @@ static bool load (const char *cmdline, void (**eip) (void), void **esp); tid_t process_execute (const char *file_name) { - char *fn_copy; + char *fn_copy, *filename_, *args; tid_t tid; - /* Make a copy of FILE_NAME. Otherwise there's a race between the caller and load(). */ fn_copy = palloc_get_page (0); if (fn_copy == NULL) return TID_ERROR; strlcpy (fn_copy, file_name, PGSIZE); - + int len = strlen(file_name) + 1; + char file_copy[len]; + strlcpy(file_copy, file_name, len); + filename_ = strtok_r(file_copy, " ", &args); /* Create a new thread to execute FILE_NAME. */ - tid = thread_create (file_name, PRI_DEFAULT, start_process, fn_copy); - + tid = thread_create (filename_, PRI_DEFAULT, start_process, fn_copy); if (tid == TID_ERROR) palloc_free_page (fn_copy); return tid; } - /* A thread function that loads a user process and starts it running. */ static void @@ -54,20 +620,17 @@ start_process (void *file_name_) char *file_name = file_name_; struct intr_frame if_; bool success; - /* 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); /* If load failed, quit. */ palloc_free_page (file_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 @@ -77,14 +640,12 @@ start_process (void *file_name_) asm volatile ("movl %0, %%esp; jmp intr_exit" : : "g" (&if_) : "memory"); NOT_REACHED (); } - /* Waits for thread TID to die and returns its exit status. If it was terminated by the kernel (i.e. killed due to an exception), returns -1. If TID is invalid or if it was not a child of the calling process, or if process_wait() has already been successfully called for the given TID, returns -1 immediately, without waiting. - This function will be implemented in problem 2-2. For now, it does nothing. */ int @@ -95,14 +656,13 @@ process_wait (tid_t child_tid UNUSED) return -1; } - /* Free the current process's resources. */ void process_exit (void) { struct thread *cur = thread_current (); uint32_t *pd; - + printf("%s: exit_code(%d)\n",cur->name,cur->exit_code); /* Destroy the current process's page directory and switch back to the kernel-only page directory. */ pd = cur->pagedir; @@ -120,7 +680,6 @@ process_exit (void) pagedir_destroy (pd); } } - /* Sets up the CPU for running user code in the current thread. This function is called on every context switch. */ @@ -128,10 +687,8 @@ void process_activate (void) { struct thread *t = thread_current (); - /* Activate thread's page tables. */ pagedir_activate (t->pagedir); - /* Set thread's kernel stack for use in processing interrupts. */ tss_update (); @@ -139,17 +696,14 @@ process_activate (void) /* We load ELF binaries. The following definitions are taken from the ELF specification, [ELF1], more-or-less verbatim. */ - /* ELF types. See [ELF1] 1-2. */ typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off; typedef uint16_t Elf32_Half; - /* For use with ELF types in printf(). */ #define PE32Wx PRIx32 /* Print Elf32_Word in hexadecimal. */ #define PE32Ax PRIx32 /* Print Elf32_Addr in hexadecimal. */ #define PE32Ox PRIx32 /* Print Elf32_Off in hexadecimal. */ #define PE32Hx PRIx16 /* Print Elf32_Half in hexadecimal. */ - /* Executable header. See [ELF1] 1-4 to 1-8. This appears at the very beginning of an ELF binary. */ struct Elf32_Ehdr @@ -169,7 +723,6 @@ struct Elf32_Ehdr Elf32_Half e_shnum; Elf32_Half e_shstrndx; }; - /* Program header. See [ELF1] 2-2 to 2-4. There are e_phnum of these, starting at file offset e_phoff (see [ELF1] 1-6). */ @@ -184,7 +737,6 @@ struct Elf32_Phdr Elf32_Word p_flags; Elf32_Word p_align; }; - /* Values for p_type. See [ELF1] 2-3. */ #define PT_NULL 0 /* Ignore. */ #define PT_LOAD 1 /* Loadable segment. */ @@ -194,18 +746,16 @@ struct Elf32_Phdr #define PT_SHLIB 5 /* Reserved. */ #define PT_PHDR 6 /* Program header table. */ #define PT_STACK 0x6474e551 /* Stack segment. */ - /* Flags for p_flags. See [ELF3] 2-3 and 2-4. */ #define PF_X 1 /* Executable. */ #define PF_W 2 /* Writable. */ #define PF_R 4 /* Readable. */ - -static bool setup_stack (void **esp); +static bool setup_stack (void **esp, char *filename, char *argu); 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, bool writable); - +void handle_argsinstack(void **esp, char *file_name, char *args); /* Loads an ELF executable from FILE_NAME into the current thread. Stores the executable's entry point into *EIP and its initial stack pointer into *ESP. @@ -219,22 +769,23 @@ load (const char *file_name, void (**eip) (void), void **esp) off_t file_ofs; bool success = false; int i; - + int len = strlen(file_name) + 1; + char file_copy[len]; + strlcpy(file_copy, file_name, len); + char *args, *file_name_; + file_name_ = strtok_r(file_copy, " ", &args); /* Allocate and activate page directory. */ t->pagedir = pagedir_create (); if (t->pagedir == NULL) goto done; process_activate (); - /* Open executable file. */ - file = filesys_open (file_name); - + file = filesys_open (file_name_); if (file == NULL) { - printf ("load: %s: open failed\n", file_name); + printf ("load: %s: open failed\n", file_name_); goto done; } - /* Read and verify executable header. */ if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr || memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7) @@ -244,20 +795,17 @@ load (const char *file_name, 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", file_name_); goto done; } - /* Read program headers. */ file_ofs = ehdr.e_phoff; for (i = 0; i < ehdr.e_phnum; i++) { struct Elf32_Phdr phdr; - if (file_ofs < 0 || file_ofs > file_length (file)) goto done; file_seek (file, file_ofs); - if (file_read (file, &phdr, sizeof phdr) != sizeof phdr) goto done; file_ofs += sizeof phdr; @@ -306,16 +854,12 @@ load (const char *file_name, void (**eip) (void), void **esp) break; } } - /* Set up stack. */ - if (!setup_stack (esp)) + if (!setup_stack (esp, file_name_, args)) goto done; - /* Start address. */ *eip = (void (*) (void)) ehdr.e_entry; - success = true; - done: /* We arrive here whether the load is successful or not. */ file_close (file); @@ -323,9 +867,7 @@ load (const char *file_name, void (**eip) (void), void **esp) } /* load() helpers. */ - static bool install_page (void *upage, void *kpage, bool writable); - /* Checks whether PHDR describes a valid, loadable segment in FILE and returns true if so, false otherwise. */ static bool @@ -334,15 +876,12 @@ validate_segment (const struct Elf32_Phdr *phdr, struct file *file) /* p_offset and p_vaddr must have the same page offset. */ if ((phdr->p_offset & PGMASK) != (phdr->p_vaddr & PGMASK)) return false; - /* p_offset must point within FILE. */ if (phdr->p_offset > (Elf32_Off) file_length (file)) return false; - /* p_memsz must be at least as big as p_filesz. */ if (phdr->p_memsz < phdr->p_filesz) return false; - /* The segment must not be empty. */ if (phdr->p_memsz == 0) return false; @@ -353,12 +892,10 @@ validate_segment (const struct Elf32_Phdr *phdr, struct file *file) return false; if (!is_user_vaddr ((void *) (phdr->p_vaddr + phdr->p_memsz))) return false; - /* The region cannot "wrap around" across the kernel virtual address space. */ if (phdr->p_vaddr + phdr->p_memsz < phdr->p_vaddr) return false; - /* Disallow mapping page 0. Not only is it a bad idea to map page 0, but if we allowed it then user code that passed a null pointer to system calls @@ -366,23 +903,17 @@ validate_segment (const struct Elf32_Phdr *phdr, struct file *file) assertions in memcpy(), etc. */ if (phdr->p_vaddr < PGSIZE) return false; - /* It's okay. */ return true; } - /* Loads a segment starting at offset OFS in FILE at address UPAGE. In total, READ_BYTES + ZERO_BYTES bytes of virtual memory are initialized, as follows: - - READ_BYTES bytes at UPAGE must be read from FILE starting at offset OFS. - - ZERO_BYTES bytes at UPAGE + READ_BYTES must be zeroed. - The pages initialized by this function must be writable by the user process if WRITABLE is true, read-only otherwise. - Return true if successful, false if a memory allocation error or disk read error occurs. */ static bool @@ -392,7 +923,6 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage, ASSERT ((read_bytes + zero_bytes) % PGSIZE == 0); ASSERT (pg_ofs (upage) == 0); ASSERT (ofs % PGSIZE == 0); - file_seek (file, ofs); while (read_bytes > 0 || zero_bytes > 0) { @@ -401,12 +931,10 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage, and zero the final PAGE_ZERO_BYTES bytes. */ size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE; size_t page_zero_bytes = PGSIZE - page_read_bytes; - /* Get a page of memory. */ uint8_t *kpage = palloc_get_page (PAL_USER); if (kpage == NULL) return false; - /* Load this page. */ if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes) { @@ -414,14 +942,12 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage, return false; } memset (kpage + page_read_bytes, 0, page_zero_bytes); - /* Add the page to the process's address space. */ if (!install_page (upage, kpage, writable)) { palloc_free_page (kpage); return false; } - /* Advance. */ read_bytes -= page_read_bytes; zero_bytes -= page_zero_bytes; @@ -429,27 +955,28 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage, } return true; } - /* Create a minimal stack by mapping a zeroed page at the top of user virtual memory. */ static bool -setup_stack (void **esp) +setup_stack (void **esp, char *filename, char *argu) { uint8_t *kpage; bool success = false; - kpage = palloc_get_page (PAL_USER | PAL_ZERO); if (kpage != NULL) { success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true); if (success) { *esp = PHYS_BASE; + //push the arguments on stack + handle_argsinstack(esp, filename, argu); + //print stack + hex_dump((uintptr_t)*esp, *esp, sizeof(char) * 50, true); } else palloc_free_page (kpage); } return success; } - /* Adds a mapping from user virtual address UPAGE to kernel virtual address KPAGE to the page table. If WRITABLE is true, the user process may modify the page; @@ -463,11 +990,49 @@ static bool install_page (void *upage, void *kpage, bool writable) { struct thread *t = thread_current (); - /* Verify that there's not already a page at that virtual address, then map our page there. */ return (pagedir_get_page (t->pagedir, upage) == NULL && pagedir_set_page (t->pagedir, upage, kpage, writable)); } - +/*Helper function push name of file and arguments on esp stack*/ +void +handle_argsinstack(void **esp, char *file_name, char *args) +{ + int arg_c = 0, t_arg_s = 0; + char* argu_arr[25]; + for(char *arg = strtok_r(NULL," ",&args) ; arg != NULL ; + arg = strtok_r(NULL," ",&args)) + { + argu_arr[++arg_c]=arg; + } + int arg_len = 0; + char* argus[arg_c + 1]; + + //push the argument on esp stack + for (int i = arg_c; i > 0; i--) + { + arg_len = strlen(argu_arr[i]) + 1; + t_arg_s += arg_len; + *esp -= arg_len; + memcpy(*esp,argu_arr[i],arg_len); + argus[arg_c - i + 1] = *esp; + } + //push the name of file on esp stack + int size = strlen(file_name) + 1; + *esp -= size; + memcpy(*esp,file_name,size); + argus[0] = *esp; + + argus[arg_c + 1] = NULL; + //Add Padding to align the esp stack + int pad = 4 * ((t_arg_s) / 4); + *esp -= pad; + memset(*esp,0,pad); + + // push the pointer array on esp stack + *esp -= 4*(arg_c + 3); + memcpy(*esp,argus,4*(arg_c + 1)); + +} //--------------------------------------------------------------------