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