1 #include "lib9.h"
2 #include "isa.h"
3 #include "interp.h"
4 #include "raise.h"
5 #include <kernel.h>
6
7 #define A(r) *((Array**)(r))
8
9 Module* modules;
10 int dontcompile;
11
12 static int
operand(uchar ** p)13 operand(uchar **p)
14 {
15 int c;
16 uchar *cp;
17
18 cp = *p;
19 c = cp[0];
20 switch(c & 0xC0) {
21 case 0x00:
22 *p = cp+1;
23 return c;
24 case 0x40:
25 *p = cp+1;
26 return c|~0x7F;
27 case 0x80:
28 *p = cp+2;
29 if(c & 0x20)
30 c |= ~0x3F;
31 else
32 c &= 0x3F;
33 return (c<<8)|cp[1];
34 case 0xC0:
35 *p = cp+4;
36 if(c & 0x20)
37 c |= ~0x3F;
38 else
39 c &= 0x3F;
40 return (c<<24)|(cp[1]<<16)|(cp[2]<<8)|cp[3];
41 }
42 return 0;
43 }
44
45 static ulong
disw(uchar ** p)46 disw(uchar **p)
47 {
48 ulong v;
49 uchar *c;
50
51 c = *p;
52 v = c[0] << 24;
53 v |= c[1] << 16;
54 v |= c[2] << 8;
55 v |= c[3];
56 *p = c + 4;
57 return v;
58 }
59
60 double
canontod(ulong v[2])61 canontod(ulong v[2])
62 {
63 union { double d; unsigned long ul[2]; } a;
64 a.d = 1.;
65 if(a.ul[0]) {
66 a.ul[0] = v[0];
67 a.ul[1] = v[1];
68 }
69 else {
70 a.ul[1] = v[0];
71 a.ul[0] = v[1];
72 }
73 return a.d;
74 }
75
76 Module*
load(char * path)77 load(char *path)
78 {
79 return readmod(path, nil, 0);
80 }
81
82 int
brpatch(Inst * ip,Module * m)83 brpatch(Inst *ip, Module *m)
84 {
85 switch(ip->op) {
86 case ICALL:
87 case IJMP:
88 case IBEQW:
89 case IBNEW:
90 case IBLTW:
91 case IBLEW:
92 case IBGTW:
93 case IBGEW:
94 case IBEQB:
95 case IBNEB:
96 case IBLTB:
97 case IBLEB:
98 case IBGTB:
99 case IBGEB:
100 case IBEQF:
101 case IBNEF:
102 case IBLTF:
103 case IBLEF:
104 case IBGTF:
105 case IBGEF:
106 case IBEQC:
107 case IBNEC:
108 case IBLTC:
109 case IBLEC:
110 case IBGTC:
111 case IBGEC:
112 case IBEQL:
113 case IBNEL:
114 case IBLTL:
115 case IBLEL:
116 case IBGTL:
117 case IBGEL:
118 case ISPAWN:
119 if(ip->d.imm < 0 || ip->d.imm >= m->nprog)
120 return 0;
121 ip->d.imm = (WORD)&m->prog[ip->d.imm];
122 break;
123 }
124 return 1;
125 }
126
127 Module*
parsemod(char * path,uchar * code,ulong length,Dir * dir)128 parsemod(char *path, uchar *code, ulong length, Dir *dir)
129 {
130 Heap *h;
131 Inst *ip;
132 Type *pt;
133 String *s;
134 Module *m;
135 Array *ary;
136 ulong ul[2];
137 WORD lo, hi;
138 int lsize, id, v, entry, entryt, tnp, tsz, siglen;
139 int de, pc, i, n, isize, dsize, hsize, dasp;
140 uchar *mod, sm, *istream, **isp, *si, *addr, *dastack[DADEPTH];
141 Link *l;
142
143 istream = code;
144 isp = &istream;
145
146 m = malloc(sizeof(Module));
147 if(m == nil)
148 return nil;
149
150 m->dev = dir->dev;
151 m->dtype = dir->type;
152 m->qid = dir->qid;
153 m->mtime = dir->mtime;
154 m->origmp = H;
155 m->pctab = nil;
156
157 switch(operand(isp)) {
158 default:
159 kwerrstr("bad magic");
160 goto bad;
161 case SMAGIC:
162 siglen = operand(isp);
163 n = length-(*isp-code);
164 if(n < 0 || siglen > n){
165 kwerrstr("corrupt signature");
166 goto bad;
167 }
168 if(verifysigner(*isp, siglen, *isp+siglen, n-siglen) == 0) {
169 kwerrstr("security violation");
170 goto bad;
171 }
172 *isp += siglen;
173 break;
174 case XMAGIC:
175 if(mustbesigned(path, code, length, dir)){
176 kwerrstr("security violation: not signed");
177 goto bad;
178 }
179 break;
180 }
181
182 m->rt = operand(isp);
183 m->ss = operand(isp);
184 isize = operand(isp);
185 dsize = operand(isp);
186 hsize = operand(isp);
187 lsize = operand(isp);
188 entry = operand(isp);
189 entryt = operand(isp);
190
191 if(isize < 0 || dsize < 0 || hsize < 0 || lsize < 0) {
192 kwerrstr("implausible Dis file");
193 goto bad;
194 }
195
196 m->nprog = isize;
197 m->prog = mallocz(isize*sizeof(Inst), 0);
198 if(m->prog == nil) {
199 kwerrstr(exNomem);
200 goto bad;
201 }
202
203 m->ref = 1;
204
205 ip = m->prog;
206 for(i = 0; i < isize; i++) {
207 ip->op = *istream++;
208 ip->add = *istream++;
209 ip->reg = 0;
210 ip->s.imm = 0;
211 ip->d.imm = 0;
212 switch(ip->add & ARM) {
213 case AXIMM:
214 case AXINF:
215 case AXINM:
216 ip->reg = operand(isp);
217 break;
218 }
219 switch(UXSRC(ip->add)) {
220 case SRC(AFP):
221 case SRC(AMP):
222 case SRC(AIMM):
223 ip->s.ind = operand(isp);
224 break;
225 case SRC(AIND|AFP):
226 case SRC(AIND|AMP):
227 ip->s.i.f = operand(isp);
228 ip->s.i.s = operand(isp);
229 break;
230 }
231 switch(UXDST(ip->add)) {
232 case DST(AFP):
233 case DST(AMP):
234 ip->d.ind = operand(isp);
235 break;
236 case DST(AIMM):
237 ip->d.ind = operand(isp);
238 if(brpatch(ip, m) == 0) {
239 kwerrstr("bad branch addr");
240 goto bad;
241 }
242 break;
243 case DST(AIND|AFP):
244 case DST(AIND|AMP):
245 ip->d.i.f = operand(isp);
246 ip->d.i.s = operand(isp);
247 break;
248 }
249 ip++;
250 }
251
252 m->ntype = hsize;
253 m->type = malloc(hsize*sizeof(Type*));
254 if(m->type == nil) {
255 kwerrstr(exNomem);
256 goto bad;
257 }
258 for(i = 0; i < hsize; i++) {
259 id = operand(isp);
260 if(id > hsize) {
261 kwerrstr("heap id range");
262 goto bad;
263 }
264 tsz = operand(isp);
265 tnp = operand(isp);
266 if(tsz < 0 || tnp < 0 || tnp > 128*1024){
267 kwerrstr("implausible Dis file");
268 goto bad;
269 }
270 pt = dtype(freeheap, tsz, istream, tnp);
271 if(pt == nil) {
272 kwerrstr(exNomem);
273 goto bad;
274 }
275 istream += tnp;
276 m->type[id] = pt;
277 }
278
279 if(dsize != 0) {
280 pt = m->type[0];
281 if(pt == 0 || pt->size != dsize) {
282 kwerrstr("bad desc for mp");
283 goto bad;
284 }
285 h = heapz(pt);
286 m->origmp = H2D(uchar*, h);
287 }
288 addr = m->origmp;
289 dasp = 0;
290 for(;;) {
291 sm = *istream++;
292 if(sm == 0)
293 break;
294 n = DLEN(sm);
295 if(n == 0)
296 n = operand(isp);
297 v = operand(isp);
298 si = addr + v;
299 switch(DTYPE(sm)) {
300 default:
301 kwerrstr("bad data item");
302 goto bad;
303 case DEFS:
304 s = c2string((char*)istream, n);
305 istream += n;
306 *(String**)si = s;
307 break;
308 case DEFB:
309 for(i = 0; i < n; i++)
310 *si++ = *istream++;
311 break;
312 case DEFW:
313 for(i = 0; i < n; i++) {
314 *(WORD*)si = disw(isp);
315 si += sizeof(WORD);
316 }
317 break;
318 case DEFL:
319 for(i = 0; i < n; i++) {
320 hi = disw(isp);
321 lo = disw(isp);
322 *(LONG*)si = (LONG)hi << 32 | (LONG)(ulong)lo;
323 si += sizeof(LONG);
324 }
325 break;
326 case DEFF:
327 for(i = 0; i < n; i++) {
328 ul[0] = disw(isp);
329 ul[1] = disw(isp);
330 *(REAL*)si = canontod(ul);
331 si += sizeof(REAL);
332 }
333 break;
334 case DEFA: /* Array */
335 v = disw(isp);
336 if(v < 0 || v > m->ntype) {
337 kwerrstr("bad array type");
338 goto bad;
339 }
340 pt = m->type[v];
341 v = disw(isp);
342 h = nheap(sizeof(Array)+(pt->size*v));
343 h->t = &Tarray;
344 h->t->ref++;
345 ary = H2D(Array*, h);
346 ary->t = pt;
347 ary->len = v;
348 ary->root = H;
349 ary->data = (uchar*)ary+sizeof(Array);
350 memset((void*)ary->data, 0, pt->size*v);
351 initarray(pt, ary);
352 A(si) = ary;
353 break;
354 case DIND: /* Set index */
355 ary = A(si);
356 if(ary == H || D2H(ary)->t != &Tarray) {
357 kwerrstr("ind not array");
358 goto bad;
359 }
360 v = disw(isp);
361 if(v > ary->len || v < 0 || dasp >= DADEPTH) {
362 kwerrstr("array init range");
363 goto bad;
364 }
365 dastack[dasp++] = addr;
366 addr = ary->data+v*ary->t->size;
367 break;
368 case DAPOP:
369 if(dasp == 0) {
370 kwerrstr("pop range");
371 goto bad;
372 }
373 addr = dastack[--dasp];
374 break;
375 }
376 }
377 mod = istream;
378 if(memchr(mod, 0, 128) == 0) {
379 kwerrstr("bad module name");
380 goto bad;
381 }
382 m->name = strdup((char*)mod);
383 if(m->name == nil) {
384 kwerrstr(exNomem);
385 goto bad;
386 }
387 while(*istream++)
388 ;
389
390 l = m->ext = (Link*)malloc((lsize+1)*sizeof(Link));
391 if(l == nil){
392 kwerrstr(exNomem);
393 goto bad;
394 }
395 for(i = 0; i < lsize; i++, l++) {
396 pc = operand(isp);
397 de = operand(isp);
398 v = disw(isp);
399 pt = nil;
400 if(de != -1)
401 pt = m->type[de];
402 mlink(m, l, istream, v, pc, pt);
403 while(*istream++)
404 ;
405 }
406 l->name = nil;
407
408 if(m->rt & HASLDT0){
409 kwerrstr("obsolete dis");
410 goto bad;
411 }
412
413 if(m->rt & HASLDT){
414 int j, nl;
415 Import *i1, **i2;
416
417 nl = operand(isp);
418 i2 = m->ldt = (Import**)malloc((nl+1)*sizeof(Import*));
419 if(i2 == nil){
420 kwerrstr(exNomem);
421 goto bad;
422 }
423 for(i = 0; i < nl; i++, i2++){
424 n = operand(isp);
425 i1 = *i2 = (Import*)malloc((n+1)*sizeof(Import));
426 if(i1 == nil){
427 kwerrstr(exNomem);
428 goto bad;
429 }
430 for(j = 0; j < n; j++, i1++){
431 i1->sig = disw(isp);
432 i1->name = strdup((char*)istream);
433 if(i1->name == nil){
434 kwerrstr(exNomem);
435 goto bad;
436 }
437 while(*istream++)
438 ;
439 }
440 }
441 istream++;
442 }
443
444 if(m->rt & HASEXCEPT){
445 int j, nh;
446 Handler *h;
447 Except *e;
448
449 nh = operand(isp);
450 m->htab = malloc((nh+1)*sizeof(Handler));
451 if(m->htab == nil){
452 kwerrstr(exNomem);
453 goto bad;
454 }
455 h = m->htab;
456 for(i = 0; i < nh; i++, h++){
457 h->eoff = operand(isp);
458 h->pc1 = operand(isp);
459 h->pc2 = operand(isp);
460 n = operand(isp);
461 if(n != -1)
462 h->t = m->type[n];
463 n = operand(isp);
464 h->ne = n>>16;
465 n &= 0xffff;
466 h->etab = malloc((n+1)*sizeof(Except));
467 if(h->etab == nil){
468 kwerrstr(exNomem);
469 goto bad;
470 }
471 e = h->etab;
472 for(j = 0; j < n; j++, e++){
473 e->s = strdup((char*)istream);
474 if(e->s == nil){
475 kwerrstr(exNomem);
476 goto bad;
477 }
478 while(*istream++)
479 ;
480 e->pc = operand(isp);
481 }
482 e->s = nil;
483 e->pc = operand(isp);
484 }
485 istream++;
486 }
487
488 m->entryt = nil;
489 m->entry = m->prog;
490 if((ulong)entry < isize && (ulong)entryt < hsize) {
491 m->entry = &m->prog[entry];
492 m->entryt = m->type[entryt];
493 }
494
495 if(cflag) {
496 if((m->rt&DONTCOMPILE) == 0 && !dontcompile)
497 compile(m, isize, nil);
498 }
499 else
500 if(m->rt & MUSTCOMPILE && !dontcompile) {
501 if(compile(m, isize, nil) == 0) {
502 kwerrstr("compiler required");
503 goto bad;
504 }
505 }
506
507 m->path = strdup(path);
508 if(m->path == nil) {
509 kwerrstr(exNomem);
510 goto bad;
511 }
512 m->link = modules;
513 modules = m;
514
515 return m;
516 bad:
517 destroy(m->origmp);
518 freemod(m);
519 return nil;
520 }
521
522 Module*
newmod(char * s)523 newmod(char *s)
524 {
525 Module *m;
526
527 m = malloc(sizeof(Module));
528 if(m == nil)
529 error(exNomem);
530 m->ref = 1;
531 m->path = s;
532 m->origmp = H;
533 m->name = strdup(s);
534 if(m->name == nil) {
535 free(m);
536 error(exNomem);
537 }
538 m->link = modules;
539 modules = m;
540 m->pctab = nil;
541 return m;
542 }
543
544 Module*
lookmod(char * s)545 lookmod(char *s)
546 {
547 Module *m;
548
549 for(m = modules; m != nil; m = m->link)
550 if(strcmp(s, m->path) == 0) {
551 m->ref++;
552 return m;
553 }
554 return nil;
555 }
556
557 void
freemod(Module * m)558 freemod(Module *m)
559 {
560 int i;
561 Handler *h;
562 Except *e;
563 Import *i1, **i2;
564
565 if(m->type != nil) {
566 for(i = 0; i < m->ntype; i++)
567 freetype(m->type[i]);
568 free(m->type);
569 }
570 free(m->name);
571 free(m->prog);
572 free(m->path);
573 free(m->pctab);
574 if(m->ldt != nil){
575 for(i2 = m->ldt; *i2 != nil; i2++){
576 for(i1 = *i2; i1->name != nil; i1++)
577 free(i1->name);
578 free(*i2);
579 }
580 free(m->ldt);
581 }
582 if(m->htab != nil){
583 for(h = m->htab; h->etab != nil; h++){
584 for(e = h->etab; e->s != nil; e++)
585 free(e->s);
586 free(h->etab);
587 }
588 free(m->htab);
589 }
590 free(m);
591 }
592
593 void
unload(Module * m)594 unload(Module *m)
595 {
596 Module **last, *mm;
597
598 m->ref--;
599 if(m->ref > 0)
600 return;
601 if(m->ref == -1)
602 abort();
603
604 last = &modules;
605 for(mm = modules; mm != nil; mm = mm->link) {
606 if(mm == m) {
607 *last = m->link;
608 break;
609 }
610 last = &mm->link;
611 }
612
613 if(m->rt == DYNMOD)
614 freedyncode(m);
615 else
616 destroy(m->origmp);
617
618 destroylinks(m);
619
620 freemod(m);
621 }
622