* more re-work
[mascara-docs.git] / i386 / junos / MIT / src.xv6 / exec.c
blob312a5c3dd64924b9553245ede10e409ae5783fca
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"
10 int
11 exec(char *path, char **argv)
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;
21 if((ip = namei(path)) == 0)
22 return -1;
23 ilock(ip);
24 pgdir = 0;
26 // Check ELF header
27 if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
28 goto bad;
29 if(elf.magic != ELF_MAGIC)
30 goto bad;
32 if((pgdir = setupkvm(kalloc)) == 0)
33 goto bad;
35 // Load program into memory.
36 sz = 0;
37 for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
38 if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
39 goto bad;
40 if(ph.type != ELF_PROG_LOAD)
41 continue;
42 if(ph.memsz < ph.filesz)
43 goto bad;
44 if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0)
45 goto bad;
46 if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0)
47 goto bad;
49 iunlockput(ip);
50 ip = 0;
52 // Allocate two pages at the next page boundary.
53 // Make the first inaccessible. Use the second as the user stack.
54 sz = PGROUNDUP(sz);
55 if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0)
56 goto bad;
57 clearpteu(pgdir, (char*)(sz - 2*PGSIZE));
58 sp = sz;
60 // Push argument strings, prepare rest of stack in ustack.
61 for(argc = 0; argv[argc]; argc++) {
62 if(argc >= MAXARG)
63 goto bad;
64 sp = (sp - (strlen(argv[argc]) + 1)) & ~3;
65 if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
66 goto bad;
67 ustack[3+argc] = sp;
69 ustack[3+argc] = 0;
71 ustack[0] = 0xffffffff; // fake return PC
72 ustack[1] = argc;
73 ustack[2] = sp - (argc+1)*4; // argv pointer
75 sp -= (3+argc+1) * 4;
76 if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0)
77 goto bad;
79 // Save program name for debugging.
80 for(last=s=path; *s; s++)
81 if(*s == '/')
82 last = s+1;
83 safestrcpy(proc->name, last, sizeof(proc->name));
85 // Commit to the user image.
86 oldpgdir = proc->pgdir;
87 proc->pgdir = pgdir;
88 proc->sz = sz;
89 proc->tf->eip = elf.entry; // main
90 proc->tf->esp = sp;
91 switchuvm(proc);
92 freevm(oldpgdir);
93 return 0;
95 bad:
96 if(pgdir)
97 freevm(pgdir);
98 if(ip)
99 iunlockput(ip);
100 return -1;