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 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 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 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* 77 load(char *path) 78 { 79 return readmod(path, nil, 0); 80 } 81 82 int 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* 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* 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* 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 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 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