Mercurial > hg > Members > anatofuz > CbC_xv6
comparison src/exec.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children | 397e74cbf14e |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:83c23a36980d |
---|---|
1 #include "types.h" | |
2 #include "param.h" | |
3 #include "defs.h" | |
4 #include "memlayout.h" | |
5 #include "mmu.h" | |
6 #include "proc.h" | |
7 #include "elf.h" | |
8 #include "arm.h" | |
9 | |
10 // load a user program for execution | |
11 int exec (char *path, char **argv) | |
12 { | |
13 struct elfhdr elf; | |
14 struct inode *ip; | |
15 struct proghdr ph; | |
16 pde_t *pgdir; | |
17 pde_t *oldpgdir; | |
18 char *s; | |
19 char *last; | |
20 int i; | |
21 int off; | |
22 uint argc; | |
23 uint sz; | |
24 uint sp; | |
25 uint ustack[3 + MAXARG + 1]; | |
26 | |
27 if ((ip = namei(path)) == 0) { | |
28 return -1; | |
29 } | |
30 | |
31 ilock(ip); | |
32 | |
33 // Check ELF header | |
34 if (readi(ip, (char*) &elf, 0, sizeof(elf)) < sizeof(elf)) { | |
35 goto bad; | |
36 } | |
37 | |
38 if (elf.magic != ELF_MAGIC) { | |
39 goto bad; | |
40 } | |
41 | |
42 pgdir = 0; | |
43 | |
44 if ((pgdir = kpt_alloc()) == 0) { | |
45 goto bad; | |
46 } | |
47 | |
48 // Load program into memory. | |
49 sz = 0; | |
50 | |
51 for (i = 0, off = elf.phoff; i < elf.phnum; i++, off += sizeof(ph)) { | |
52 if (readi(ip, (char*) &ph, off, sizeof(ph)) != sizeof(ph)) { | |
53 goto bad; | |
54 } | |
55 | |
56 if (ph.type != ELF_PROG_LOAD) { | |
57 continue; | |
58 } | |
59 | |
60 if (ph.memsz < ph.filesz) { | |
61 goto bad; | |
62 } | |
63 | |
64 if ((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) { | |
65 goto bad; | |
66 } | |
67 | |
68 if (loaduvm(pgdir, (char*) ph.vaddr, ip, ph.off, ph.filesz) < 0) { | |
69 goto bad; | |
70 } | |
71 } | |
72 | |
73 iunlockput(ip); | |
74 ip = 0; | |
75 | |
76 // Allocate two pages at the next page boundary. | |
77 // Make the first inaccessible. Use the second as the user stack. | |
78 sz = align_up (sz, PTE_SZ); | |
79 | |
80 if ((sz = allocuvm(pgdir, sz, sz + 2 * PTE_SZ)) == 0) { | |
81 goto bad; | |
82 } | |
83 | |
84 clearpteu(pgdir, (char*) (sz - 2 * PTE_SZ)); | |
85 | |
86 sp = sz; | |
87 | |
88 // Push argument strings, prepare rest of stack in ustack. | |
89 for (argc = 0; argv[argc]; argc++) { | |
90 if (argc >= MAXARG) { | |
91 goto bad; | |
92 } | |
93 | |
94 sp = (sp - (strlen(argv[argc]) + 1)) & ~3; | |
95 | |
96 if (copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) { | |
97 goto bad; | |
98 } | |
99 | |
100 ustack[argc] = sp; | |
101 } | |
102 | |
103 ustack[argc] = 0; | |
104 | |
105 // in ARM, parameters are passed in r0 and r1 | |
106 proc->tf->r0 = argc; | |
107 proc->tf->r1 = sp - (argc + 1) * 4; | |
108 | |
109 sp -= (argc + 1) * 4; | |
110 | |
111 if (copyout(pgdir, sp, ustack, (argc + 1) * 4) < 0) { | |
112 goto bad; | |
113 } | |
114 | |
115 // Save program name for debugging. | |
116 for (last = s = path; *s; s++) { | |
117 if (*s == '/') { | |
118 last = s + 1; | |
119 } | |
120 } | |
121 | |
122 safestrcpy(proc->name, last, sizeof(proc->name)); | |
123 | |
124 // Commit to the user image. | |
125 oldpgdir = proc->pgdir; | |
126 proc->pgdir = pgdir; | |
127 proc->sz = sz; | |
128 proc->tf->pc = elf.entry; | |
129 proc->tf->sp_usr = sp; | |
130 | |
131 switchuvm(proc); | |
132 freevm(oldpgdir); | |
133 return 0; | |
134 | |
135 bad: if (pgdir) { | |
136 freevm(pgdir); | |
137 } | |
138 | |
139 if (ip) { | |
140 iunlockput(ip); | |
141 } | |
142 return -1; | |
143 } |