diff options
| -rw-r--r-- | exec.c | 136 | 
1 files changed, 59 insertions, 77 deletions
@@ -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;  }  | 
