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 }