root/exec.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. exec

   1 #include "types.h"
   2 #include "param.h"
   3 #include "memlayout.h"
   4 #include "mmu.h"
   5 #include "proc.h"
   6 #include "defs.h"
   7 #include "x86.h"
   8 #include "elf.h"
   9 
  10 int
  11 exec(char *path, char **argv)
  12 {
  13   char *s, *last;
  14   int i, off;
  15   uint argc, sz, sp, ustack[3+MAXARG+1];
  16   struct elfhdr elf;
  17   struct inode *ip;
  18   struct proghdr ph;
  19   pde_t *pgdir, *oldpgdir;
  20 
  21   begin_op();
  22   if((ip = namei(path)) == 0){
  23     end_op();
  24     return -1;
  25   }
  26   ilock(ip);
  27   pgdir = 0;
  28 
  29   // Check ELF header
  30   if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
  31     goto bad;
  32   if(elf.magic != ELF_MAGIC)
  33     goto bad;
  34 
  35   if((pgdir = setupkvm()) == 0)
  36     goto bad;
  37 
  38   // Load program into memory.
  39   sz = 0;
  40   for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
  41     if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
  42       goto bad;
  43     if(ph.type != ELF_PROG_LOAD)
  44       continue;
  45     if(ph.memsz < ph.filesz)
  46       goto bad;
  47     if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0)
  48       goto bad;
  49     if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0)
  50       goto bad;
  51   }
  52   iunlockput(ip);
  53   end_op();
  54   ip = 0;
  55 
  56   // Allocate two pages at the next page boundary.
  57   // Make the first inaccessible.  Use the second as the user stack.
  58   sz = PGROUNDUP(sz);
  59   if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0)
  60     goto bad;
  61   clearpteu(pgdir, (char*)(sz - 2*PGSIZE));
  62   sp = sz;
  63 
  64   // Push argument strings, prepare rest of stack in ustack.
  65   for(argc = 0; argv[argc]; argc++) {
  66     if(argc >= MAXARG)
  67       goto bad;
  68     sp = (sp - (strlen(argv[argc]) + 1)) & ~3;
  69     if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
  70       goto bad;
  71     ustack[3+argc] = sp;
  72   }
  73   ustack[3+argc] = 0;
  74 
  75   ustack[0] = 0xffffffff;  // fake return PC
  76   ustack[1] = argc;
  77   ustack[2] = sp - (argc+1)*4;  // argv pointer
  78 
  79   sp -= (3+argc+1) * 4;
  80   if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0)
  81     goto bad;
  82 
  83   // Save program name for debugging.
  84   for(last=s=path; *s; s++)
  85     if(*s == '/')
  86       last = s+1;
  87   safestrcpy(proc->name, last, sizeof(proc->name));
  88 
  89   // Commit to the user image.
  90   oldpgdir = proc->pgdir;
  91   proc->pgdir = pgdir;
  92   proc->sz = sz;
  93   proc->tf->eip = elf.entry;  // main
  94   proc->tf->esp = sp;
  95   switchuvm(proc);
  96   freevm(oldpgdir);
  97   return 0;
  98 
  99  bad:
 100   if(pgdir)
 101     freevm(pgdir);
 102   if(ip){
 103     iunlockput(ip);
 104     end_op();
 105   }
 106   return -1;
 107 }

/* [<][>][^][v][top][bottom][index][help] */