xref: /inferno-os/libinterp/loader.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 #include "lib9.h"
2 #include "isa.h"
3 #include "interp.h"
4 #include "runt.h"
5 #include "loadermod.h"
6 #include "raise.h"
7 #include <kernel.h>
8 
9 static uchar	Instmap[] = Loader_Inst_map;
10 static Type*	Tinst;
11 static uchar	Tdescmap[] = Loader_Typedesc_map;
12 static Type*	Tdesc;
13 static uchar	Tlinkmap[] = Loader_Link_map;
14 static Type*	Tlink;
15 
16 void
loadermodinit(void)17 loadermodinit(void)
18 {
19 	sysinit();
20 	builtinmod("$Loader", Loadermodtab, Loadermodlen);
21 	Tinst = dtype(freeheap, sizeof(Loader_Inst), Instmap, sizeof(Instmap));
22 	Tdesc = dtype(freeheap, sizeof(Loader_Typedesc), Tdescmap, sizeof(Tdescmap));
23 	Tlink = dtype(freeheap, sizeof(Loader_Link), Tlinkmap, sizeof(Tlinkmap));
24 }
25 
26 static void
brunpatch(Loader_Inst * ip,Module * m)27 brunpatch(Loader_Inst *ip, Module *m)
28 {
29 	switch(ip->op) {
30 	case ICALL:
31 	case IJMP:
32 	case IBEQW:
33 	case IBNEW:
34 	case IBLTW:
35 	case IBLEW:
36 	case IBGTW:
37 	case IBGEW:
38 	case IBEQB:
39 	case IBNEB:
40 	case IBLTB:
41 	case IBLEB:
42 	case IBGTB:
43 	case IBGEB:
44 	case IBEQF:
45 	case IBNEF:
46 	case IBLTF:
47 	case IBLEF:
48 	case IBGTF:
49 	case IBGEF:
50 	case IBEQC:
51 	case IBNEC:
52 	case IBLTC:
53 	case IBLEC:
54 	case IBGTC:
55 	case IBGEC:
56 	case IBEQL:
57 	case IBNEL:
58 	case IBLTL:
59 	case IBLEL:
60 	case IBGTL:
61 	case IBGEL:
62 	case ISPAWN:
63 		ip->dst = (Inst*)ip->dst - m->prog;
64 		break;
65 	}
66 }
67 
68 void
Loader_ifetch(void * a)69 Loader_ifetch(void *a)
70 {
71 	Heap *h;
72 	Array *ar;
73 	Module *m;
74 	Inst *i, *ie;
75 	Loader_Inst *li;
76 	F_Loader_ifetch *f;
77 
78 	f = a;
79 	destroy(*f->ret);
80 	*f->ret = H;
81 
82 	if(f->mp == H)
83 		return;
84 	m = f->mp->m;
85 	if(m == H)
86 		return;
87 	if(m->compiled) {
88 		kwerrstr("compiled module");
89 		return;
90 	}
91 
92 	h = nheap(sizeof(Array)+m->nprog*sizeof(Loader_Inst));
93 	h->t = &Tarray;
94 	h->t->ref++;
95 	ar = H2D(Array*, h);
96 	ar->t = Tinst;
97 	Tinst->ref++;
98 	ar->len = m->nprog;
99 	ar->root = H;
100 	ar->data = (uchar*)ar+sizeof(Array);
101 
102 	li = (Loader_Inst*)ar->data;
103 	i = m->prog;
104 	ie = i + m->nprog;
105 	while(i < ie) {
106 		li->op = i->op;
107 		li->addr = i->add;
108 		li->src = i->s.imm;
109 		li->dst = i->d.imm;
110 		li->mid = i->reg;
111 		if(UDST(i->add) == AIMM)
112 			brunpatch(li, m);
113 		li++;
114 		i++;
115 	}
116 
117 	*f->ret = ar;
118 }
119 
120 void
Loader_link(void * a)121 Loader_link(void *a)
122 {
123 	Link *p;
124 	Heap *h;
125 	Type **t;
126 	int nlink;
127 	Module *m;
128 	Array *ar;
129 	Loader_Link *ll;
130 	F_Loader_link *f;
131 
132 	f = a;
133 	destroy(*f->ret);
134 	*f->ret = H;
135 
136 	if(f->mp == H)
137 		return;
138 	m = f->mp->m;
139 	if(m == H)
140 		return;
141 
142 	nlink = 0;
143 	for(p = m->ext; p->name; p++)
144 		nlink++;
145 
146 	h = nheap(sizeof(Array)+nlink*sizeof(Loader_Link));
147 	h->t = &Tarray;
148 	h->t->ref++;
149 	ar = H2D(Array*, h);
150 	ar->t = Tlink;
151 	Tlink->ref++;
152 	ar->len = nlink;
153 	ar->root = H;
154 	ar->data = (uchar*)ar+sizeof(Array);
155 
156 	ll = (Loader_Link*)ar->data + nlink;
157 	for(p = m->ext; p->name; p++) {
158 		ll--;
159 		ll->name = c2string(p->name, strlen(p->name));
160 		ll->sig = p->sig;
161 		if(m->prog == nil) {
162 			ll->pc = -1;
163 			ll->tdesc = -1;
164 		} else {
165 			ll->pc = p->u.pc - m->prog;
166 			ll->tdesc = 0;
167 			for(t = m->type; *t != p->frame; t++)
168 				ll->tdesc++;
169 		}
170 	}
171 
172 	*f->ret = ar;
173 }
174 
175 void
Loader_tdesc(void * a)176 Loader_tdesc(void *a)
177 {
178 	int i;
179 	Heap *h;
180 	Type *t;
181 	Array *ar;
182 	Module *m;
183 	F_Loader_tdesc *f;
184 	Loader_Typedesc *lt;
185 
186 	f = a;
187 	destroy(*f->ret);
188 	*f->ret = H;
189 
190 	if(f->mp == H)
191 		return;
192 	m = f->mp->m;
193 	if(m == H)
194 		return;
195 
196 	h = nheap(sizeof(Array)+m->ntype*sizeof(Loader_Typedesc));
197 	h->t = &Tarray;
198 	h->t->ref++;
199 	ar = H2D(Array*, h);
200 	ar->t = Tdesc;
201 	Tdesc->ref++;
202 	ar->len = m->ntype;
203 	ar->root = H;
204 	ar->data = (uchar*)ar+sizeof(Array);
205 
206 	lt = (Loader_Typedesc*)ar->data;
207 	for(i = 0; i < m->ntype; i++) {
208 		t = m->type[i];
209 		lt->size = t->size;
210 		lt->map = H;
211 		if(t->np != 0)
212 			lt->map = mem2array(t->map, t->np);
213 		lt++;
214 	}
215 
216 	*f->ret = ar;
217 }
218 
219 void
Loader_newmod(void * a)220 Loader_newmod(void *a)
221 {
222 	Heap *h;
223 	Module *m;
224 	Array *ia;
225 	Modlink *ml;
226 	Inst *i, *ie;
227 	Loader_Inst *li;
228 	F_Loader_newmod *f;
229 
230 	f = a;
231 	destroy(*f->ret);
232 	*f->ret = H;
233 
234 	if(f->inst == H || f->data == H) {
235 		kwerrstr("nil parameters");
236 		return;
237 	}
238 	if(f->nlink < 0) {
239 		kwerrstr("bad nlink");
240 		return;
241 	}
242 
243 	m = malloc(sizeof(Module));
244 	if(m == nil) {
245 		kwerrstr(exNomem);
246 		return;
247 	}
248 	m->origmp = H;
249 	m->ref = 1;
250 	m->ss = f->ss;
251 	m->name = strdup(string2c(f->name));
252 	m->path = strdup(m->name);
253 	m->ntype = 1;
254 	m->type = malloc(sizeof(Type*));
255 	if(m->name == nil || m->path == nil || m->type == nil) {
256 		kwerrstr(exNomem);
257 		goto bad;
258 	}
259 	m->origmp = (uchar*)f->data;
260 	h = D2H(f->data);
261 	h->ref++;
262 	Setmark(h);
263 	m->type[0] = h->t;
264 	h->t->ref++;
265 
266 	ia = f->inst;
267 	m->nprog = ia->len;
268 	m->prog = malloc(m->nprog*sizeof(Inst));
269 	if(m->prog == nil)
270 		goto bad;
271 	i = m->prog;
272 	ie = i + m->nprog;
273 	li = (Loader_Inst*)ia->data;
274 	while(i < ie) {
275 		i->op = li->op;
276 		i->add = li->addr;
277 		i->reg = li->mid;
278 		i->s.imm = li->src;
279 		i->d.imm = li->dst;
280 		if(brpatch(i, m) == 0) {
281 			kwerrstr("bad branch addr");
282 			goto bad;
283 		}
284 		i++;
285 		li++;
286 	}
287 	m->entryt = nil;
288 	m->entry = m->prog;
289 
290 	ml = mklinkmod(m, f->nlink);
291 	ml->MP = m->origmp;
292 	m->origmp = H;
293 	m->pctab = nil;
294 	*f->ret = ml;
295 	return;
296 bad:
297 	destroy(m->origmp);
298 	freemod(m);
299 }
300 
301 void
Loader_tnew(void * a)302 Loader_tnew(void *a)
303 {
304 	int mem;
305 	Module *m;
306 	Type *t, **nt;
307 	Array *ar, az;
308 	F_Loader_tnew *f;
309 
310 	f = a;
311 	*f->ret = -1;
312 	if(f->mp == H)
313 		return;
314 	m = f->mp->m;
315 	if(m == H)
316 		return;
317 	if(m->origmp != H){
318 		kwerrstr("need newmod");
319 		return;
320 	}
321 
322 	ar = f->map;
323 	if(ar == H) {
324 		ar = &az;
325 		ar->len = 0;
326 		ar->data = nil;
327 	}
328 
329 	t = dtype(freeheap, f->size, ar->data, ar->len);
330 	if(t == nil)
331 		return;
332 
333 	mem = (m->ntype+1)*sizeof(Type*);
334 	if(msize(m->type) > mem) {
335 		*f->ret = m->ntype;
336 		m->type[m->ntype++] = t;
337 		return;
338 	}
339 	nt = realloc(m->type, mem);
340 	if(nt == nil) {
341 		kwerrstr(exNomem);
342 		return;
343 	}
344 	m->type = nt;
345 	f->mp->type = nt;
346 	*f->ret = m->ntype;
347 	m->type[m->ntype++] = t;
348 }
349 
350 void
Loader_ext(void * a)351 Loader_ext(void *a)
352 {
353 	Modl *l;
354 	Module *m;
355 	Modlink *ml;
356 	F_Loader_ext *f;
357 
358 	f = a;
359 	*f->ret = -1;
360 	if(f->mp == H) {
361 		kwerrstr("nil mp");
362 		return;
363 	}
364 	ml = f->mp;
365 	m = ml->m;
366 	if(f->tdesc < 0 || f->tdesc >= m->ntype) {
367 		kwerrstr("bad tdesc");
368 		return;
369 	}
370 	if(f->pc < 0 || f->pc >= m->nprog) {
371 		kwerrstr("bad pc");
372 		return;
373 	}
374 	if(f->idx < 0 || f->idx >= ml->nlinks) {
375 		kwerrstr("bad idx");
376 		return;
377 	}
378 	l = &ml->links[f->idx];
379 	l->u.pc = m->prog + f->pc;
380 	l->frame = m->type[f->tdesc];
381 	*f->ret = 0;
382 }
383 
384 void
Loader_dnew(void * a)385 Loader_dnew(void *a)
386 {
387 	F_Loader_dnew *f;
388 	Heap *h;
389 	Array *ar, az;
390 	Type *t;
391 
392         f = a;
393         *f->ret = H;
394         if(f->map == H)
395                 return;
396         ar = f->map;
397         if(ar == H) {
398                 ar = &az;
399                 ar->len = 0;
400                 ar->data = nil;
401         }
402         t = dtype(freeheap, f->size, ar->data, ar->len);
403         if(t == nil) {
404                 kwerrstr(exNomem);
405                 return;
406         }
407 
408 	h=heapz(t);
409 	if(h == nil) {
410 		freetype(t);
411 		kwerrstr(exNomem);
412 		return;
413         }
414 
415 	*f->ret=H2D(Loader_Niladt*, h);
416 }
417 
418 void
Loader_compile(void * a)419 Loader_compile(void *a)
420 {
421 	Module *m;
422 	F_Loader_compile *f;
423 
424 	f = a;
425 	*f->ret = -1;
426 	if(f->mp == H) {
427 		kwerrstr("nil mp");
428 		return;
429 	}
430 	m = f->mp->m;
431 	if(m->compiled) {
432 		kwerrstr("compiled module");
433 		return;
434 	}
435 	*f->ret = 0;
436 	m->origmp = f->mp->MP;
437 	if(cflag || f->flag)
438 	if(compile(m, m->nprog, f->mp)) {
439 		f->mp->prog = m->prog;
440 		f->mp->compiled = 1;
441 	} else
442 		*f->ret = -1;
443 	m->origmp = H;
444 }
445