This source file includes following definitions.
- flags2perm
- exec
- loadseg
1 #include "types.h"
2 #include "param.h"
3 #include "memlayout.h"
4 #include "riscv.h"
5 #include "spinlock.h"
6 #include "proc.h"
7 #include "defs.h"
8 #include "elf.h"
9
10 static int loadseg(pde_t *, uint64, struct inode *, uint, uint);
11
12 int flags2perm(int flags)
13 {
14 int perm = 0;
15 if(flags & 0x1)
16 perm = PTE_X;
17 if(flags & 0x2)
18 perm |= PTE_W;
19 return perm;
20 }
21
22 int
23 exec(char *path, char **argv)
24 {
25 char *s, *last;
26 int i, off;
27 uint64 argc, sz = 0, sp, ustack[MAXARG], stackbase;
28 struct elfhdr elf;
29 struct inode *ip;
30 struct proghdr ph;
31 pagetable_t pagetable = 0, oldpagetable;
32 struct proc *p = myproc();
33
34 begin_op();
35
36 if((ip = namei(path)) == 0){
37 end_op();
38 return -1;
39 }
40 ilock(ip);
41
42
43 if(readi(ip, 0, (uint64)&elf, 0, sizeof(elf)) != sizeof(elf))
44 goto bad;
45
46 if(elf.magic != ELF_MAGIC)
47 goto bad;
48
49 if((pagetable = proc_pagetable(p)) == 0)
50 goto bad;
51
52
53 for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
54 if(readi(ip, 0, (uint64)&ph, off, sizeof(ph)) != sizeof(ph))
55 goto bad;
56 if(ph.type != ELF_PROG_LOAD)
57 continue;
58 if(ph.memsz < ph.filesz)
59 goto bad;
60 if(ph.vaddr + ph.memsz < ph.vaddr)
61 goto bad;
62 if(ph.vaddr % PGSIZE != 0)
63 goto bad;
64 uint64 sz1;
65 if((sz1 = uvmalloc(pagetable, sz, ph.vaddr + ph.memsz, flags2perm(ph.flags))) == 0)
66 goto bad;
67 sz = sz1;
68 if(loadseg(pagetable, ph.vaddr, ip, ph.off, ph.filesz) < 0)
69 goto bad;
70 }
71 iunlockput(ip);
72 end_op();
73 ip = 0;
74
75 p = myproc();
76 uint64 oldsz = p->sz;
77
78
79
80
81 sz = PGROUNDUP(sz);
82 uint64 sz1;
83 if((sz1 = uvmalloc(pagetable, sz, sz + (USERSTACK+1)*PGSIZE, PTE_W)) == 0)
84 goto bad;
85 sz = sz1;
86 uvmclear(pagetable, sz-(USERSTACK+1)*PGSIZE);
87 sp = sz;
88 stackbase = sp - USERSTACK*PGSIZE;
89
90
91 for(argc = 0; argv[argc]; argc++) {
92 if(argc >= MAXARG)
93 goto bad;
94 sp -= strlen(argv[argc]) + 1;
95 sp -= sp % 16;
96 if(sp < stackbase)
97 goto bad;
98 if(copyout(pagetable, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
99 goto bad;
100 ustack[argc] = sp;
101 }
102 ustack[argc] = 0;
103
104
105 sp -= (argc+1) * sizeof(uint64);
106 sp -= sp % 16;
107 if(sp < stackbase)
108 goto bad;
109 if(copyout(pagetable, sp, (char *)ustack, (argc+1)*sizeof(uint64)) < 0)
110 goto bad;
111
112
113
114
115 p->trapframe->a1 = sp;
116
117
118 for(last=s=path; *s; s++)
119 if(*s == '/')
120 last = s+1;
121 safestrcpy(p->name, last, sizeof(p->name));
122
123
124 oldpagetable = p->pagetable;
125 p->pagetable = pagetable;
126 p->sz = sz;
127 p->trapframe->epc = elf.entry;
128 p->trapframe->sp = sp;
129 proc_freepagetable(oldpagetable, oldsz);
130
131 return argc;
132
133 bad:
134 if(pagetable)
135 proc_freepagetable(pagetable, sz);
136 if(ip){
137 iunlockput(ip);
138 end_op();
139 }
140 return -1;
141 }
142
143
144
145
146
147 static int
148 loadseg(pagetable_t pagetable, uint64 va, struct inode *ip, uint offset, uint sz)
149 {
150 uint i, n;
151 uint64 pa;
152
153 for(i = 0; i < sz; i += PGSIZE){
154 pa = walkaddr(pagetable, va + i);
155 if(pa == 0)
156 panic("loadseg: address should exist");
157 if(sz - i < PGSIZE)
158 n = sz - i;
159 else
160 n = PGSIZE;
161 if(readi(ip, 0, (uint64)pa, offset+i, n) != n)
162 return -1;
163 }
164
165 return 0;
166 }