]> Devi Nivas Git - cs3210-lab0.git/commitdiff
Edit exec.
authorrsc <rsc>
Mon, 27 Aug 2007 15:17:40 +0000 (15:17 +0000)
committerrsc <rsc>
Mon, 27 Aug 2007 15:17:40 +0000 (15:17 +0000)
Do not commit to new memory image until
nothing can go wrong, avoiding bad2 case.

Be sure to allocate enough stack space for argv.

Load executable before initializing stack, to
keep ELF loops together.

Make argv loop clearer.

exec.c

diff --git a/exec.c b/exec.c
index 4da73b26767971ac42c1040e895ef201b5a194fd..9f06605e5ae6114780474b5851eb407fd1ed0e74 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -1,44 +1,35 @@
 #include "types.h"
-#include "stat.h"
 #include "param.h"
 #include "mmu.h"
 #include "proc.h"
 #include "defs.h"
 #include "x86.h"
-#include "traps.h"
-#include "syscall.h"
-#include "spinlock.h"
-#include "buf.h"
 #include "fs.h"
-#include "fsvar.h"
 #include "elf.h"
-#include "file.h"
-#include "fcntl.h"
 
 int
 exec(char *path, char **argv)
 {
-  uint sz, sp, p1, p2;
-  int i, nargs, argbytes, len, off;
-  struct inode *ip;
+  char *mem, *s, *last;
+  int i, argc, arglen, len, off;
+  uint sz, sp, argp;
   struct elfhdr elf;
+  struct inode *ip;
   struct proghdr ph;
-  char *mem;
-  char *s, *last;
-
-  sz = 0;
-  mem = 0;
 
   if((ip = namei(path)) == 0)
     return -1;
   ilock(ip);
 
+  // Compute memory size of new process.
+  mem = 0;
+  sz = 0;
+
+  // Program segments.
   if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
     goto bad;
-
   if(elf.magic != ELF_MAGIC)
     goto bad;
-
   for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
     if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
       goto bad;
@@ -48,77 +39,73 @@ exec(char *path, char **argv)
       goto bad;
     sz += ph.memsz;
   }
-
-  sz += 4096 - (sz % 4096);
-  sz += 4096;
-
+  
+  // Arguments.
+  arglen = 0;
+  for(argc=0; argv[argc]; argc++)
+    arglen += strlen(argv[i]) + 1;
+  arglen = (arglen+3) & ~3;
+  sz += arglen + 4*(argc+1);
+
+  // Stack.
+  sz += PAGE;
+  
+  // Allocate program memory.
+  sz = (sz+PAGE-1) & ~(PAGE-1);
   mem = kalloc(sz);
   if(mem == 0)
     goto bad;
   memset(mem, 0, sz);
 
-  argbytes = 0;
-  for(i = 0; argv[i]; i++){
-    len = strlen(argv[i]);
-    argbytes += len + 1;
+  // Load program into memory.
+  for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
+    if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
+      goto bad;
+    if(ph.type != ELF_PROG_LOAD)
+      continue;
+    if(ph.va + ph.memsz > sz)
+      goto bad;
+    if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
+      goto bad;
+    memset(mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
   }
-  nargs = i;
-
-  // argn\0
-  // ...
-  // arg0\0
-  // 0
-  // ptr to argn
-  // ...
-  // 12: ptr to arg0
-  //  8: argv (points to ptr to arg0)
-  //  4: argc
-  //  0: fake return pc
-  sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4;
-  *(uint*)(mem + sp) = 0xffffffff;
-  *(uint*)(mem + sp + 4) = nargs;
-  *(uint*)(mem + sp + 8) = (uint)(sp + 12);
-
-  p1 = sp + 12;
-  p2 = sp + 12 + (nargs + 1) * 4;
-  for(i = 0; i < nargs; i++){
-    len = strlen(argv[i]);
-    memmove(mem + p2, argv[i], len + 1);
-    *(uint*)(mem + p1) = p2;
-    p1 += 4;
-    p2 += len + 1;
+  iunlockput(ip);
+  
+  // Initialize stack.
+  sp = sz;
+  argp = sz - arglen;
+
+  // Copy argv strings and pointers to stack.
+  *(uint*)(mem+argp + 4*argc) = 0;  // argv[argc]
+  for(i=argc-1; i>=0; i--){
+    len = strlen(argv[i]) + 1;
+    sp -= len;
+    memmove(mem+sp, argv[i], len);
+    *(uint*)(mem+argp + 4*i) = sp;  // argv[i]
   }
-  *(uint*)(mem + p1) = 0;
 
-  // Save name for debugging.
+  // Stack frame for main(argc, argv), below arguments.
+  sp = argp;
+  sp -= 4;
+  *(uint*)(mem+sp) = argp;
+  sp -= 4;
+  *(uint*)(mem+sp) = argc;
+  sp -= 4;
+  *(uint*)(mem+sp) = 0xffffffff;   // fake return pc
+
+  // Save program name for debugging.
   for(last=s=path; *s; s++)
     if(*s == '/')
       last = s+1;
   safestrcpy(cp->name, last, sizeof(cp->name));
 
-  // commit to the new image.
+  // Commit to the new image.
   kfree(cp->mem, cp->sz);
-  cp->sz = sz;
   cp->mem = mem;
-  mem = 0;
-
-  for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
-    if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
-      goto bad2;
-    if(ph.type != ELF_PROG_LOAD)
-      continue;
-    if(ph.va + ph.memsz > sz)
-      goto bad2;
-    if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
-      goto bad2;
-    memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
-  }
-  iunlockput(ip);
-  
-  cp->tf->eip = elf.entry;
+  cp->sz = sz;
+  cp->tf->eip = elf.entry;  // main
   cp->tf->esp = sp;
   setupsegs(cp);
-
   return 0;
 
  bad:
@@ -126,9 +113,4 @@ exec(char *path, char **argv)
     kfree(mem, sz);
   iunlockput(ip);
   return -1;
-
- bad2:
-  iunlockput(ip);
-  proc_exit();
-  return 0;
 }