1 #define EXTERN 2 #include "l.h" 3 #include <ar.h> 4 5 #ifndef DEFAULT 6 #define DEFAULT '9' 7 #endif 8 9 char *noname = "<none>"; 10 char symname[] = SYMDEF; 11 char thechar = '8'; 12 char *thestring = "386"; 13 14 /* 15 * -H0 -T0x40004C -D0x10000000 is garbage unix 16 * -H1 -T0xd0 -R4 is unix coff 17 * -H2 -T4128 -R4096 is plan9 format 18 * -H3 -Tx -Rx is MS-DOS .COM 19 * -H4 -Tx -Rx is fake MS-DOS .EXE 20 * -H5 -T0x80100020 -R4096 is ELF 21 */ 22 23 static int 24 isobjfile(char *f) 25 { 26 int n, v; 27 Biobuf *b; 28 char buf1[5], buf2[SARMAG]; 29 30 b = Bopen(f, OREAD); 31 if(b == nil) 32 return 0; 33 n = Bread(b, buf1, 5); 34 if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<')) 35 v = 1; /* good enough for our purposes */ 36 else{ 37 Bseek(b, 0, 0); 38 n = Bread(b, buf2, SARMAG); 39 v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0; 40 } 41 Bterm(b); 42 return v; 43 } 44 45 void 46 main(int argc, char *argv[]) 47 { 48 int i, c; 49 char *a; 50 51 Binit(&bso, 1, OWRITE); 52 cout = -1; 53 listinit(); 54 memset(debug, 0, sizeof(debug)); 55 nerrors = 0; 56 outfile = "8.out"; 57 HEADTYPE = -1; 58 INITTEXT = -1; 59 INITDAT = -1; 60 INITRND = -1; 61 INITENTRY = 0; 62 ARGBEGIN { 63 default: 64 c = ARGC(); 65 if(c >= 0 && c < sizeof(debug)) 66 debug[c]++; 67 break; 68 case 'o': /* output to (next arg) */ 69 outfile = ARGF(); 70 break; 71 case 'E': 72 a = ARGF(); 73 if(a) 74 INITENTRY = a; 75 break; 76 case 'H': 77 a = ARGF(); 78 if(a) 79 HEADTYPE = atolwhex(a); 80 break; 81 case 'T': 82 a = ARGF(); 83 if(a) 84 INITTEXT = atolwhex(a); 85 break; 86 case 'D': 87 a = ARGF(); 88 if(a) 89 INITDAT = atolwhex(a); 90 break; 91 case 'R': 92 a = ARGF(); 93 if(a) 94 INITRND = atolwhex(a); 95 break; 96 case 'x': /* produce export table */ 97 doexp = 1; 98 if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1])) 99 readundefs(ARGF(), SEXPORT); 100 break; 101 case 'u': /* produce dynamically loadable module */ 102 dlm = 1; 103 debug['l']++; 104 if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1])) 105 readundefs(ARGF(), SIMPORT); 106 break; 107 } ARGEND 108 USED(argc); 109 if(*argv == 0) { 110 diag("usage: 8l [-options] objects"); 111 errorexit(); 112 } 113 if(!debug['9'] && !debug['U'] && !debug['B']) 114 debug[DEFAULT] = 1; 115 if(HEADTYPE == -1) { 116 if(debug['U']) 117 HEADTYPE = 1; 118 if(debug['B']) 119 HEADTYPE = 2; 120 if(debug['9']) 121 HEADTYPE = 2; 122 } 123 switch(HEADTYPE) { 124 default: 125 diag("unknown -H option"); 126 errorexit(); 127 128 case 0: /* this is garbage */ 129 HEADR = 20L+56L; 130 if(INITTEXT == -1) 131 INITTEXT = 0x40004CL; 132 if(INITDAT == -1) 133 INITDAT = 0x10000000L; 134 if(INITRND == -1) 135 INITRND = 0; 136 break; 137 case 1: /* is unix coff */ 138 HEADR = 0xd0L; 139 if(INITTEXT == -1) 140 INITTEXT = 0xd0; 141 if(INITDAT == -1) 142 INITDAT = 0x400000; 143 if(INITRND == -1) 144 INITRND = 0; 145 break; 146 case 2: /* plan 9 */ 147 HEADR = 32L; 148 if(INITTEXT == -1) 149 INITTEXT = 4096+32; 150 if(INITDAT == -1) 151 INITDAT = 0; 152 if(INITRND == -1) 153 INITRND = 4096; 154 break; 155 case 3: /* MS-DOS .COM */ 156 HEADR = 0; 157 if(INITTEXT == -1) 158 INITTEXT = 0x0100; 159 if(INITDAT == -1) 160 INITDAT = 0; 161 if(INITRND == -1) 162 INITRND = 4; 163 break; 164 case 4: /* fake MS-DOS .EXE */ 165 HEADR = 0x200; 166 if(INITTEXT == -1) 167 INITTEXT = 0x0100; 168 if(INITDAT == -1) 169 INITDAT = 0; 170 if(INITRND == -1) 171 INITRND = 4; 172 HEADR += (INITTEXT & 0xFFFF); 173 if(debug['v']) 174 Bprint(&bso, "HEADR = 0x%ld\n", HEADR); 175 break; 176 case 5: /* elf executable */ 177 HEADR = rnd(52L+3*32L, 16); 178 if(INITTEXT == -1) 179 INITTEXT = 0x80100020L; 180 if(INITDAT == -1) 181 INITDAT = 0; 182 if(INITRND == -1) 183 INITRND = 4096; 184 break; 185 } 186 if(INITDAT != 0 && INITRND != 0) 187 print("warning: -D0x%lux is ignored because of -R0x%lux\n", 188 INITDAT, INITRND); 189 if(debug['v']) 190 Bprint(&bso, "HEADER = -H0x%ld -T0x%lux -D0x%lux -R0x%lux\n", 191 HEADTYPE, INITTEXT, INITDAT, INITRND); 192 Bflush(&bso); 193 for(i=1; optab[i].as; i++) 194 if(i != optab[i].as) { 195 diag("phase error in optab: %d", i); 196 errorexit(); 197 } 198 maxop = i; 199 200 for(i=0; i<Ymax; i++) 201 ycover[i*Ymax + i] = 1; 202 203 ycover[Yi0*Ymax + Yi8] = 1; 204 ycover[Yi1*Ymax + Yi8] = 1; 205 206 ycover[Yi0*Ymax + Yi32] = 1; 207 ycover[Yi1*Ymax + Yi32] = 1; 208 ycover[Yi8*Ymax + Yi32] = 1; 209 210 ycover[Yal*Ymax + Yrb] = 1; 211 ycover[Ycl*Ymax + Yrb] = 1; 212 ycover[Yax*Ymax + Yrb] = 1; 213 ycover[Ycx*Ymax + Yrb] = 1; 214 ycover[Yrx*Ymax + Yrb] = 1; 215 216 ycover[Yax*Ymax + Yrx] = 1; 217 ycover[Ycx*Ymax + Yrx] = 1; 218 219 ycover[Yax*Ymax + Yrl] = 1; 220 ycover[Ycx*Ymax + Yrl] = 1; 221 ycover[Yrx*Ymax + Yrl] = 1; 222 223 ycover[Yf0*Ymax + Yrf] = 1; 224 225 ycover[Yal*Ymax + Ymb] = 1; 226 ycover[Ycl*Ymax + Ymb] = 1; 227 ycover[Yax*Ymax + Ymb] = 1; 228 ycover[Ycx*Ymax + Ymb] = 1; 229 ycover[Yrx*Ymax + Ymb] = 1; 230 ycover[Yrb*Ymax + Ymb] = 1; 231 ycover[Ym*Ymax + Ymb] = 1; 232 233 ycover[Yax*Ymax + Yml] = 1; 234 ycover[Ycx*Ymax + Yml] = 1; 235 ycover[Yrx*Ymax + Yml] = 1; 236 ycover[Yrl*Ymax + Yml] = 1; 237 ycover[Ym*Ymax + Yml] = 1; 238 239 for(i=0; i<D_NONE; i++) { 240 reg[i] = -1; 241 if(i >= D_AL && i <= D_BH) 242 reg[i] = (i-D_AL) & 7; 243 if(i >= D_AX && i <= D_DI) 244 reg[i] = (i-D_AX) & 7; 245 if(i >= D_F0 && i <= D_F0+7) 246 reg[i] = (i-D_F0) & 7; 247 } 248 249 zprg.link = P; 250 zprg.pcond = P; 251 zprg.back = 2; 252 zprg.as = AGOK; 253 zprg.from.type = D_NONE; 254 zprg.from.index = D_NONE; 255 zprg.from.scale = 1; 256 zprg.to = zprg.from; 257 258 pcstr = "%.6lux "; 259 nuxiinit(); 260 histgen = 0; 261 textp = P; 262 datap = P; 263 edatap = P; 264 pc = 0; 265 dtype = 4; 266 cout = create(outfile, 1, 0775); 267 if(cout < 0) { 268 diag("cannot create %s", outfile); 269 errorexit(); 270 } 271 version = 0; 272 cbp = buf.cbuf; 273 cbc = sizeof(buf.cbuf); 274 firstp = prg(); 275 lastp = firstp; 276 277 if(INITENTRY == 0) { 278 INITENTRY = "_main"; 279 if(debug['p']) 280 INITENTRY = "_mainp"; 281 if(!debug['l']) 282 lookup(INITENTRY, 0)->type = SXREF; 283 } else 284 lookup(INITENTRY, 0)->type = SXREF; 285 286 while(*argv) 287 objfile(*argv++); 288 if(!debug['l']) 289 loadlib(); 290 firstp = firstp->link; 291 if(firstp == P) 292 errorexit(); 293 if(doexp || dlm){ 294 EXPTAB = "_exporttab"; 295 zerosig(EXPTAB); 296 zerosig("etext"); 297 zerosig("edata"); 298 zerosig("end"); 299 if(dlm){ 300 import(); 301 HEADTYPE = 2; 302 INITTEXT = INITDAT = 0; 303 INITRND = 8; 304 INITENTRY = EXPTAB; 305 } 306 export(); 307 } 308 patch(); 309 follow(); 310 dodata(); 311 dostkoff(); 312 if(debug['p']) 313 if(debug['1']) 314 doprof1(); 315 else 316 doprof2(); 317 span(); 318 doinit(); 319 asmb(); 320 undef(); 321 if(debug['v']) { 322 Bprint(&bso, "%5.2f cpu time\n", cputime()); 323 Bprint(&bso, "%ld symbols\n", nsymbol); 324 Bprint(&bso, "%ld memory used\n", thunk); 325 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); 326 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); 327 } 328 Bflush(&bso); 329 330 errorexit(); 331 } 332 333 void 334 loadlib(void) 335 { 336 int i; 337 long h; 338 Sym *s; 339 340 loop: 341 xrefresolv = 0; 342 for(i=0; i<libraryp; i++) { 343 if(debug['v']) 344 Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]); 345 objfile(library[i]); 346 } 347 if(xrefresolv) 348 for(h=0; h<nelem(hash); h++) 349 for(s = hash[h]; s != S; s = s->link) 350 if(s->type == SXREF) 351 goto loop; 352 } 353 354 void 355 errorexit(void) 356 { 357 358 if(nerrors) { 359 if(cout >= 0) 360 remove(outfile); 361 exits("error"); 362 } 363 exits(0); 364 } 365 366 void 367 objfile(char *file) 368 { 369 long off, esym, cnt, l; 370 int f, work; 371 Sym *s; 372 char magbuf[SARMAG]; 373 char name[100], pname[150]; 374 struct ar_hdr arhdr; 375 char *e, *start, *stop; 376 377 if(file[0] == '-' && file[1] == 'l') { 378 if(debug['9']) 379 sprint(name, "/%s/lib/lib", thestring); 380 else 381 sprint(name, "/usr/%clib/lib", thechar); 382 strcat(name, file+2); 383 strcat(name, ".a"); 384 file = name; 385 } 386 if(debug['v']) 387 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file); 388 Bflush(&bso); 389 f = open(file, 0); 390 if(f < 0) { 391 diag("cannot open file: %s", file); 392 errorexit(); 393 } 394 l = read(f, magbuf, SARMAG); 395 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){ 396 /* load it as a regular file */ 397 l = seek(f, 0L, 2); 398 seek(f, 0L, 0); 399 ldobj(f, l, file); 400 close(f); 401 return; 402 } 403 404 l = read(f, &arhdr, SAR_HDR); 405 if(l != SAR_HDR) { 406 diag("%s: short read on archive file symbol header", file); 407 goto out; 408 } 409 if(strncmp(arhdr.name, symname, strlen(symname))) { 410 diag("%s: first entry not symbol header", file); 411 goto out; 412 } 413 414 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size); 415 off = SARMAG + SAR_HDR; 416 417 /* 418 * just bang the whole symbol file into memory 419 */ 420 seek(f, off, 0); 421 cnt = esym - off; 422 start = malloc(cnt + 10); 423 cnt = read(f, start, cnt); 424 if(cnt <= 0){ 425 close(f); 426 return; 427 } 428 stop = &start[cnt]; 429 memset(stop, 0, 10); 430 431 work = 1; 432 while(work) { 433 if(debug['v']) 434 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file); 435 Bflush(&bso); 436 work = 0; 437 for(e = start; e < stop; e = strchr(e+5, 0) + 1) { 438 s = lookup(e+5, 0); 439 if(s->type != SXREF) 440 continue; 441 sprint(pname, "%s(%s)", file, s->name); 442 if(debug['v']) 443 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname); 444 Bflush(&bso); 445 l = e[1] & 0xff; 446 l |= (e[2] & 0xff) << 8; 447 l |= (e[3] & 0xff) << 16; 448 l |= (e[4] & 0xff) << 24; 449 seek(f, l, 0); 450 l = read(f, &arhdr, SAR_HDR); 451 if(l != SAR_HDR) 452 goto bad; 453 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag))) 454 goto bad; 455 l = atolwhex(arhdr.size); 456 ldobj(f, l, pname); 457 if(s->type == SXREF) { 458 diag("%s: failed to load: %s", file, s->name); 459 errorexit(); 460 } 461 work = 1; 462 xrefresolv = 1; 463 } 464 } 465 return; 466 467 bad: 468 diag("%s: bad or out of date archive", file); 469 out: 470 close(f); 471 } 472 473 int 474 zaddr(uchar *p, Adr *a, Sym *h[]) 475 { 476 int c, t, i; 477 long l; 478 Sym *s; 479 Auto *u; 480 481 t = p[0]; 482 483 c = 1; 484 if(t & T_INDEX) { 485 a->index = p[c]; 486 a->scale = p[c+1]; 487 c += 2; 488 } else { 489 a->index = D_NONE; 490 a->scale = 0; 491 } 492 a->offset = 0; 493 if(t & T_OFFSET) { 494 a->offset = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); 495 c += 4; 496 } 497 a->sym = S; 498 if(t & T_SYM) { 499 a->sym = h[p[c]]; 500 c++; 501 } 502 a->type = D_NONE; 503 if(t & T_FCONST) { 504 a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); 505 a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24); 506 c += 8; 507 a->type = D_FCONST; 508 } else 509 if(t & T_SCONST) { 510 for(i=0; i<NSNAME; i++) 511 a->scon[i] = p[c+i]; 512 c += NSNAME; 513 a->type = D_SCONST; 514 } 515 if(t & T_TYPE) { 516 a->type = p[c]; 517 c++; 518 } 519 s = a->sym; 520 if(s == S) 521 return c; 522 523 t = a->type; 524 if(t != D_AUTO && t != D_PARAM) 525 return c; 526 l = a->offset; 527 for(u=curauto; u; u=u->link) { 528 if(u->asym == s) 529 if(u->type == t) { 530 if(u->aoffset > l) 531 u->aoffset = l; 532 return c; 533 } 534 } 535 536 while(nhunk < sizeof(Auto)) 537 gethunk(); 538 u = (Auto*)hunk; 539 nhunk -= sizeof(Auto); 540 hunk += sizeof(Auto); 541 542 u->link = curauto; 543 curauto = u; 544 u->asym = s; 545 u->aoffset = l; 546 u->type = t; 547 return c; 548 } 549 550 void 551 addlib(char *obj) 552 { 553 char name[1024], comp[256], *p; 554 int i; 555 556 if(histfrogp <= 0) 557 return; 558 559 if(histfrog[0]->name[1] == '/') { 560 sprint(name, ""); 561 i = 1; 562 } else 563 if(histfrog[0]->name[1] == '.') { 564 sprint(name, "."); 565 i = 0; 566 } else { 567 if(debug['9']) 568 sprint(name, "/%s/lib", thestring); 569 else 570 sprint(name, "/usr/%clib", thechar); 571 i = 0; 572 } 573 574 for(; i<histfrogp; i++) { 575 snprint(comp, sizeof comp, histfrog[i]->name+1); 576 for(;;) { 577 p = strstr(comp, "$O"); 578 if(p == 0) 579 break; 580 memmove(p+1, p+2, strlen(p+2)+1); 581 p[0] = thechar; 582 } 583 for(;;) { 584 p = strstr(comp, "$M"); 585 if(p == 0) 586 break; 587 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) { 588 diag("library component too long"); 589 return; 590 } 591 memmove(p+strlen(thestring), p+2, strlen(p+2)+1); 592 memmove(p, thestring, strlen(thestring)); 593 } 594 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) { 595 diag("library component too long"); 596 return; 597 } 598 strcat(name, "/"); 599 strcat(name, comp); 600 } 601 for(i=0; i<libraryp; i++) 602 if(strcmp(name, library[i]) == 0) 603 return; 604 if(libraryp == nelem(library)){ 605 diag("too many autolibs; skipping %s", name); 606 return; 607 } 608 609 p = malloc(strlen(name) + 1); 610 strcpy(p, name); 611 library[libraryp] = p; 612 p = malloc(strlen(obj) + 1); 613 strcpy(p, obj); 614 libraryobj[libraryp] = p; 615 libraryp++; 616 } 617 618 void 619 addhist(long line, int type) 620 { 621 Auto *u; 622 Sym *s; 623 int i, j, k; 624 625 u = malloc(sizeof(Auto)); 626 s = malloc(sizeof(Sym)); 627 s->name = malloc(2*(histfrogp+1) + 1); 628 629 u->asym = s; 630 u->type = type; 631 u->aoffset = line; 632 u->link = curhist; 633 curhist = u; 634 635 j = 1; 636 for(i=0; i<histfrogp; i++) { 637 k = histfrog[i]->value; 638 s->name[j+0] = k>>8; 639 s->name[j+1] = k; 640 j += 2; 641 } 642 } 643 644 void 645 histtoauto(void) 646 { 647 Auto *l; 648 649 while(l = curhist) { 650 curhist = l->link; 651 l->link = curauto; 652 curauto = l; 653 } 654 } 655 656 void 657 collapsefrog(Sym *s) 658 { 659 int i; 660 661 /* 662 * bad encoding of path components only allows 663 * MAXHIST components. if there is an overflow, 664 * first try to collapse xxx/.. 665 */ 666 for(i=1; i<histfrogp; i++) 667 if(strcmp(histfrog[i]->name+1, "..") == 0) { 668 memmove(histfrog+i-1, histfrog+i+1, 669 (histfrogp-i-1)*sizeof(histfrog[0])); 670 histfrogp--; 671 goto out; 672 } 673 674 /* 675 * next try to collapse . 676 */ 677 for(i=0; i<histfrogp; i++) 678 if(strcmp(histfrog[i]->name+1, ".") == 0) { 679 memmove(histfrog+i, histfrog+i+1, 680 (histfrogp-i-1)*sizeof(histfrog[0])); 681 goto out; 682 } 683 684 /* 685 * last chance, just truncate from front 686 */ 687 memmove(histfrog+0, histfrog+1, 688 (histfrogp-1)*sizeof(histfrog[0])); 689 690 out: 691 histfrog[histfrogp-1] = s; 692 } 693 694 void 695 nopout(Prog *p) 696 { 697 p->as = ANOP; 698 p->from.type = D_NONE; 699 p->to.type = D_NONE; 700 } 701 702 uchar* 703 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max) 704 { 705 int n; 706 707 n = stop - good; 708 memmove(buf, good, stop - good); 709 stop = buf + n; 710 n = MAXIO - n; 711 if(n > max) 712 n = max; 713 n = read(f, stop, n); 714 if(n <= 0) 715 return 0; 716 return stop + n; 717 } 718 719 void 720 ldobj(int f, long c, char *pn) 721 { 722 long ipc; 723 Prog *p, *t; 724 uchar *bloc, *bsize, *stop; 725 int v, o, r, skip; 726 Sym *h[NSYM], *s, *di; 727 ulong sig; 728 static int files; 729 static char **filen; 730 char **nfilen; 731 732 if((files&15) == 0){ 733 nfilen = malloc((files+16)*sizeof(char*)); 734 memmove(nfilen, filen, files*sizeof(char*)); 735 free(filen); 736 filen = nfilen; 737 } 738 filen[files++] = strdup(pn); 739 740 bsize = buf.xbuf; 741 bloc = buf.xbuf; 742 di = S; 743 744 newloop: 745 memset(h, 0, sizeof(h)); 746 version++; 747 histfrogp = 0; 748 ipc = pc; 749 skip = 0; 750 751 loop: 752 if(c <= 0) 753 goto eof; 754 r = bsize - bloc; 755 if(r < 100 && r < c) { /* enough for largest prog */ 756 bsize = readsome(f, buf.xbuf, bloc, bsize, c); 757 if(bsize == 0) 758 goto eof; 759 bloc = buf.xbuf; 760 goto loop; 761 } 762 o = bloc[0] | (bloc[1] << 8); 763 if(o <= AXXX || o >= ALAST) { 764 if(o < 0) 765 goto eof; 766 diag("%s: opcode out of range %d", pn, o); 767 print(" probably not a .8 file\n"); 768 errorexit(); 769 } 770 771 if(o == ANAME || o == ASIGNAME) { 772 sig = 0; 773 if(o == ASIGNAME) { 774 sig = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24); 775 bloc += 4; 776 c -= 4; 777 } 778 stop = memchr(&bloc[4], 0, bsize-&bloc[4]); 779 if(stop == 0){ 780 bsize = readsome(f, buf.xbuf, bloc, bsize, c); 781 if(bsize == 0) 782 goto eof; 783 bloc = buf.xbuf; 784 stop = memchr(&bloc[4], 0, bsize-&bloc[4]); 785 if(stop == 0){ 786 fprint(2, "%s: name too long\n", pn); 787 errorexit(); 788 } 789 } 790 v = bloc[2]; /* type */ 791 o = bloc[3]; /* sym */ 792 bloc += 4; 793 c -= 4; 794 795 r = 0; 796 if(v == D_STATIC) 797 r = version; 798 s = lookup((char*)bloc, r); 799 c -= &stop[1] - bloc; 800 bloc = stop + 1; 801 802 if(debug['S'] && r == 0) 803 sig = 1729; 804 if(sig != 0){ 805 if(s->sig != 0 && s->sig != sig) 806 diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name); 807 s->sig = sig; 808 s->file = files-1; 809 } 810 811 if(debug['W']) 812 print(" ANAME %s\n", s->name); 813 h[o] = s; 814 if((v == D_EXTERN || v == D_STATIC) && s->type == 0) 815 s->type = SXREF; 816 if(v == D_FILE) { 817 if(s->type != SFILE) { 818 histgen++; 819 s->type = SFILE; 820 s->value = histgen; 821 } 822 if(histfrogp < MAXHIST) { 823 histfrog[histfrogp] = s; 824 histfrogp++; 825 } else 826 collapsefrog(s); 827 } 828 goto loop; 829 } 830 831 while(nhunk < sizeof(Prog)) 832 gethunk(); 833 p = (Prog*)hunk; 834 nhunk -= sizeof(Prog); 835 hunk += sizeof(Prog); 836 837 p->as = o; 838 p->line = bloc[2] | (bloc[3] << 8) | (bloc[4] << 16) | (bloc[5] << 24); 839 p->back = 2; 840 r = zaddr(bloc+6, &p->from, h) + 6; 841 r += zaddr(bloc+r, &p->to, h); 842 bloc += r; 843 c -= r; 844 845 if(debug['W']) 846 print("%P\n", p); 847 848 switch(p->as) { 849 case AHISTORY: 850 if(p->to.offset == -1) { 851 addlib(pn); 852 histfrogp = 0; 853 goto loop; 854 } 855 addhist(p->line, D_FILE); /* 'z' */ 856 if(p->to.offset) 857 addhist(p->to.offset, D_FILE1); /* 'Z' */ 858 histfrogp = 0; 859 goto loop; 860 861 case AEND: 862 histtoauto(); 863 if(curtext != P) 864 curtext->to.autom = curauto; 865 curauto = 0; 866 curtext = P; 867 if(c) 868 goto newloop; 869 return; 870 871 case AGLOBL: 872 s = p->from.sym; 873 if(s->type == 0 || s->type == SXREF) { 874 s->type = SBSS; 875 s->value = 0; 876 } 877 if(s->type != SBSS) { 878 diag("%s: redefinition: %s in %s", 879 pn, s->name, TNAME); 880 s->type = SBSS; 881 s->value = 0; 882 } 883 if(p->to.offset > s->value) 884 s->value = p->to.offset; 885 goto loop; 886 887 case ADYNT: 888 if(p->to.sym == S) { 889 diag("DYNT without a sym\n%P", p); 890 break; 891 } 892 di = p->to.sym; 893 p->from.scale = 4; 894 if(di->type == SXREF) { 895 if(debug['z']) 896 Bprint(&bso, "%P set to %d\n", p, dtype); 897 di->type = SCONST; 898 di->value = dtype; 899 dtype += 4; 900 } 901 if(p->from.sym == S) 902 break; 903 904 p->from.offset = di->value; 905 p->from.sym->type = SDATA; 906 if(curtext == P) { 907 diag("DYNT not in text: %P", p); 908 break; 909 } 910 p->to.sym = curtext->from.sym; 911 p->to.type = D_ADDR; 912 p->to.index = D_EXTERN; 913 goto data; 914 915 case AINIT: 916 if(p->from.sym == S) { 917 diag("INIT without a sym\n%P", p); 918 break; 919 } 920 if(di == S) { 921 diag("INIT without previous DYNT\n%P", p); 922 break; 923 } 924 p->from.offset = di->value; 925 p->from.sym->type = SDATA; 926 goto data; 927 928 case ADATA: 929 data: 930 if(edatap == P) 931 datap = p; 932 else 933 edatap->link = p; 934 edatap = p; 935 p->link = P; 936 goto loop; 937 938 case AGOK: 939 diag("%s: GOK opcode in %s", pn, TNAME); 940 pc++; 941 goto loop; 942 943 case ATEXT: 944 if(curtext != P) { 945 histtoauto(); 946 curtext->to.autom = curauto; 947 curauto = 0; 948 } 949 skip = 0; 950 curtext = p; 951 s = p->from.sym; 952 if(s == S) { 953 diag("%s: no TEXT symbol: %P", pn, p); 954 errorexit(); 955 } 956 if(s->type != 0 && s->type != SXREF) { 957 if(p->from.scale & DUPOK) { 958 skip = 1; 959 goto casdef; 960 } 961 diag("%s: redefinition: %s\n%P", pn, s->name, p); 962 } 963 s->type = STEXT; 964 s->value = pc; 965 lastp->link = p; 966 lastp = p; 967 p->pc = pc; 968 pc++; 969 if(textp == P) { 970 textp = p; 971 etextp = p; 972 goto loop; 973 } 974 etextp->pcond = p; 975 etextp = p; 976 goto loop; 977 978 case AFMOVF: 979 case AFADDF: 980 case AFSUBF: 981 case AFSUBRF: 982 case AFMULF: 983 case AFDIVF: 984 case AFDIVRF: 985 case AFCOMF: 986 case AFCOMFP: 987 if(skip) 988 goto casdef; 989 if(p->from.type == D_FCONST) { 990 /* size sb 9 max */ 991 sprint(literal, "$%lux", ieeedtof(&p->from.ieee)); 992 s = lookup(literal, 0); 993 if(s->type == 0) { 994 s->type = SBSS; 995 s->value = 4; 996 t = prg(); 997 t->as = ADATA; 998 t->line = p->line; 999 t->from.type = D_EXTERN; 1000 t->from.sym = s; 1001 t->from.scale = 4; 1002 t->to = p->from; 1003 if(edatap == P) 1004 datap = t; 1005 else 1006 edatap->link = t; 1007 edatap = t; 1008 t->link = P; 1009 } 1010 p->from.type = D_EXTERN; 1011 p->from.sym = s; 1012 p->from.offset = 0; 1013 } 1014 goto casdef; 1015 1016 case AFMOVD: 1017 case AFADDD: 1018 case AFSUBD: 1019 case AFSUBRD: 1020 case AFMULD: 1021 case AFDIVD: 1022 case AFDIVRD: 1023 case AFCOMD: 1024 case AFCOMDP: 1025 if(skip) 1026 goto casdef; 1027 if(p->from.type == D_FCONST) { 1028 /* size sb 18 max */ 1029 sprint(literal, "$%lux.%lux", 1030 p->from.ieee.l, p->from.ieee.h); 1031 s = lookup(literal, 0); 1032 if(s->type == 0) { 1033 s->type = SBSS; 1034 s->value = 8; 1035 t = prg(); 1036 t->as = ADATA; 1037 t->line = p->line; 1038 t->from.type = D_EXTERN; 1039 t->from.sym = s; 1040 t->from.scale = 8; 1041 t->to = p->from; 1042 if(edatap == P) 1043 datap = t; 1044 else 1045 edatap->link = t; 1046 edatap = t; 1047 t->link = P; 1048 } 1049 p->from.type = D_EXTERN; 1050 p->from.sym = s; 1051 p->from.offset = 0; 1052 } 1053 goto casdef; 1054 1055 casdef: 1056 default: 1057 if(skip) 1058 nopout(p); 1059 1060 if(p->to.type == D_BRANCH) 1061 p->to.offset += ipc; 1062 lastp->link = p; 1063 lastp = p; 1064 p->pc = pc; 1065 pc++; 1066 goto loop; 1067 } 1068 goto loop; 1069 1070 eof: 1071 diag("truncated object file: %s", pn); 1072 } 1073 1074 Sym* 1075 lookup(char *symb, int v) 1076 { 1077 Sym *s; 1078 char *p; 1079 long h; 1080 int l, c; 1081 1082 h = v; 1083 for(p=symb; c = *p; p++) 1084 h = h+h+h + c; 1085 l = (p - symb) + 1; 1086 if(h < 0) 1087 h = ~h; 1088 h %= NHASH; 1089 for(s = hash[h]; s != S; s = s->link) 1090 if(s->version == v) 1091 if(memcmp(s->name, symb, l) == 0) 1092 return s; 1093 1094 while(nhunk < sizeof(Sym)) 1095 gethunk(); 1096 s = (Sym*)hunk; 1097 nhunk -= sizeof(Sym); 1098 hunk += sizeof(Sym); 1099 1100 s->name = malloc(l + 1); 1101 memmove(s->name, symb, l); 1102 1103 s->link = hash[h]; 1104 s->type = 0; 1105 s->version = v; 1106 s->value = 0; 1107 s->sig = 0; 1108 hash[h] = s; 1109 nsymbol++; 1110 return s; 1111 } 1112 1113 Prog* 1114 prg(void) 1115 { 1116 Prog *p; 1117 1118 while(nhunk < sizeof(Prog)) 1119 gethunk(); 1120 p = (Prog*)hunk; 1121 nhunk -= sizeof(Prog); 1122 hunk += sizeof(Prog); 1123 1124 *p = zprg; 1125 return p; 1126 } 1127 1128 Prog* 1129 copyp(Prog *q) 1130 { 1131 Prog *p; 1132 1133 p = prg(); 1134 *p = *q; 1135 return p; 1136 } 1137 1138 Prog* 1139 appendp(Prog *q) 1140 { 1141 Prog *p; 1142 1143 p = prg(); 1144 p->link = q->link; 1145 q->link = p; 1146 p->line = q->line; 1147 return p; 1148 } 1149 1150 void 1151 gethunk(void) 1152 { 1153 char *h; 1154 long nh; 1155 1156 nh = NHUNK; 1157 if(thunk >= 5L*NHUNK) { 1158 nh = 5L*NHUNK; 1159 if(thunk >= 25L*NHUNK) 1160 nh = 25L*NHUNK; 1161 } 1162 h = mysbrk(nh); 1163 if(h == (char*)-1) { 1164 diag("out of memory"); 1165 errorexit(); 1166 } 1167 hunk = h; 1168 nhunk = nh; 1169 thunk += nh; 1170 } 1171 1172 void 1173 doprof1(void) 1174 { 1175 Sym *s; 1176 long n; 1177 Prog *p, *q; 1178 1179 if(debug['v']) 1180 Bprint(&bso, "%5.2f profile 1\n", cputime()); 1181 Bflush(&bso); 1182 s = lookup("__mcount", 0); 1183 n = 1; 1184 for(p = firstp->link; p != P; p = p->link) { 1185 if(p->as == ATEXT) { 1186 q = prg(); 1187 q->line = p->line; 1188 q->link = datap; 1189 datap = q; 1190 q->as = ADATA; 1191 q->from.type = D_EXTERN; 1192 q->from.offset = n*4; 1193 q->from.sym = s; 1194 q->from.scale = 4; 1195 q->to = p->from; 1196 q->to.type = D_CONST; 1197 1198 q = prg(); 1199 q->line = p->line; 1200 q->pc = p->pc; 1201 q->link = p->link; 1202 p->link = q; 1203 p = q; 1204 p->as = AADDL; 1205 p->from.type = D_CONST; 1206 p->from.offset = 1; 1207 p->to.type = D_EXTERN; 1208 p->to.sym = s; 1209 p->to.offset = n*4 + 4; 1210 1211 n += 2; 1212 continue; 1213 } 1214 } 1215 q = prg(); 1216 q->line = 0; 1217 q->link = datap; 1218 datap = q; 1219 1220 q->as = ADATA; 1221 q->from.type = D_EXTERN; 1222 q->from.sym = s; 1223 q->from.scale = 4; 1224 q->to.type = D_CONST; 1225 q->to.offset = n; 1226 1227 s->type = SBSS; 1228 s->value = n*4; 1229 } 1230 1231 void 1232 doprof2(void) 1233 { 1234 Sym *s2, *s4; 1235 Prog *p, *q, *ps2, *ps4; 1236 1237 if(debug['v']) 1238 Bprint(&bso, "%5.2f profile 2\n", cputime()); 1239 Bflush(&bso); 1240 1241 s2 = lookup("_profin", 0); 1242 s4 = lookup("_profout", 0); 1243 if(s2->type != STEXT || s4->type != STEXT) { 1244 diag("_profin/_profout not defined"); 1245 return; 1246 } 1247 1248 ps2 = P; 1249 ps4 = P; 1250 for(p = firstp; p != P; p = p->link) { 1251 if(p->as == ATEXT) { 1252 if(p->from.sym == s2) { 1253 p->from.scale = 1; 1254 ps2 = p; 1255 } 1256 if(p->from.sym == s4) { 1257 p->from.scale = 1; 1258 ps4 = p; 1259 } 1260 } 1261 } 1262 for(p = firstp; p != P; p = p->link) { 1263 if(p->as == ATEXT) { 1264 curtext = p; 1265 1266 if(p->from.scale & NOPROF) { /* dont profile */ 1267 for(;;) { 1268 q = p->link; 1269 if(q == P) 1270 break; 1271 if(q->as == ATEXT) 1272 break; 1273 p = q; 1274 } 1275 continue; 1276 } 1277 1278 /* 1279 * JMPL profin 1280 */ 1281 q = prg(); 1282 q->line = p->line; 1283 q->pc = p->pc; 1284 q->link = p->link; 1285 p->link = q; 1286 p = q; 1287 p->as = ACALL; 1288 p->to.type = D_BRANCH; 1289 p->pcond = ps2; 1290 p->to.sym = s2; 1291 1292 continue; 1293 } 1294 if(p->as == ARET) { 1295 /* 1296 * RET 1297 */ 1298 q = prg(); 1299 q->as = ARET; 1300 q->from = p->from; 1301 q->to = p->to; 1302 q->link = p->link; 1303 p->link = q; 1304 1305 /* 1306 * JAL profout 1307 */ 1308 p->as = ACALL; 1309 p->from = zprg.from; 1310 p->to = zprg.to; 1311 p->to.type = D_BRANCH; 1312 p->pcond = ps4; 1313 p->to.sym = s4; 1314 1315 p = q; 1316 1317 continue; 1318 } 1319 } 1320 } 1321 1322 void 1323 nuxiinit(void) 1324 { 1325 int i, c; 1326 1327 for(i=0; i<4; i++) { 1328 c = find1(0x04030201L, i+1); 1329 if(i < 2) 1330 inuxi2[i] = c; 1331 if(i < 1) 1332 inuxi1[i] = c; 1333 inuxi4[i] = c; 1334 fnuxi4[i] = c; 1335 fnuxi8[i] = c; 1336 fnuxi8[i+4] = c+4; 1337 } 1338 if(debug['v']) { 1339 Bprint(&bso, "inuxi = "); 1340 for(i=0; i<1; i++) 1341 Bprint(&bso, "%d", inuxi1[i]); 1342 Bprint(&bso, " "); 1343 for(i=0; i<2; i++) 1344 Bprint(&bso, "%d", inuxi2[i]); 1345 Bprint(&bso, " "); 1346 for(i=0; i<4; i++) 1347 Bprint(&bso, "%d", inuxi4[i]); 1348 Bprint(&bso, "\nfnuxi = "); 1349 for(i=0; i<4; i++) 1350 Bprint(&bso, "%d", fnuxi4[i]); 1351 Bprint(&bso, " "); 1352 for(i=0; i<8; i++) 1353 Bprint(&bso, "%d", fnuxi8[i]); 1354 Bprint(&bso, "\n"); 1355 } 1356 Bflush(&bso); 1357 } 1358 1359 int 1360 find1(long l, int c) 1361 { 1362 char *p; 1363 int i; 1364 1365 p = (char*)&l; 1366 for(i=0; i<4; i++) 1367 if(*p++ == c) 1368 return i; 1369 return 0; 1370 } 1371 1372 int 1373 find2(long l, int c) 1374 { 1375 short *p; 1376 int i; 1377 1378 p = (short*)&l; 1379 for(i=0; i<4; i+=2) { 1380 if(((*p >> 8) & 0xff) == c) 1381 return i; 1382 if((*p++ & 0xff) == c) 1383 return i+1; 1384 } 1385 return 0; 1386 } 1387 1388 long 1389 ieeedtof(Ieee *e) 1390 { 1391 int exp; 1392 long v; 1393 1394 if(e->h == 0) 1395 return 0; 1396 exp = (e->h>>20) & ((1L<<11)-1L); 1397 exp -= (1L<<10) - 2L; 1398 v = (e->h & 0xfffffL) << 3; 1399 v |= (e->l >> 29) & 0x7L; 1400 if((e->l >> 28) & 1) { 1401 v++; 1402 if(v & 0x800000L) { 1403 v = (v & 0x7fffffL) >> 1; 1404 exp++; 1405 } 1406 } 1407 if(exp <= -126 || exp >= 130) 1408 diag("double fp to single fp overflow"); 1409 v |= ((exp + 126) & 0xffL) << 23; 1410 v |= e->h & 0x80000000L; 1411 return v; 1412 } 1413 1414 double 1415 ieeedtod(Ieee *ieeep) 1416 { 1417 Ieee e; 1418 double fr; 1419 int exp; 1420 1421 if(ieeep->h & (1L<<31)) { 1422 e.h = ieeep->h & ~(1L<<31); 1423 e.l = ieeep->l; 1424 return -ieeedtod(&e); 1425 } 1426 if(ieeep->l == 0 && ieeep->h == 0) 1427 return 0; 1428 fr = ieeep->l & ((1L<<16)-1L); 1429 fr /= 1L<<16; 1430 fr += (ieeep->l>>16) & ((1L<<16)-1L); 1431 fr /= 1L<<16; 1432 fr += (ieeep->h & (1L<<20)-1L) | (1L<<20); 1433 fr /= 1L<<21; 1434 exp = (ieeep->h>>20) & ((1L<<11)-1L); 1435 exp -= (1L<<10) - 2L; 1436 return ldexp(fr, exp); 1437 } 1438 1439 void 1440 undefsym(Sym *s) 1441 { 1442 int n; 1443 1444 n = imports; 1445 if(s->value != 0) 1446 diag("value != 0 on SXREF"); 1447 if(n >= 1<<Rindex) 1448 diag("import index %d out of range", n); 1449 s->value = n<<Roffset; 1450 s->type = SUNDEF; 1451 imports++; 1452 } 1453 1454 void 1455 zerosig(char *sp) 1456 { 1457 Sym *s; 1458 1459 s = lookup(sp, 0); 1460 s->sig = 0; 1461 } 1462 1463 void 1464 readundefs(char *f, int t) 1465 { 1466 int i, n; 1467 Sym *s; 1468 Biobuf *b; 1469 char *l, buf[256], *fields[64]; 1470 1471 if(f == nil) 1472 return; 1473 b = Bopen(f, OREAD); 1474 if(b == nil){ 1475 diag("could not open %s: %r", f); 1476 errorexit(); 1477 } 1478 while((l = Brdline(b, '\n')) != nil){ 1479 n = Blinelen(b); 1480 if(n >= sizeof(buf)){ 1481 diag("%s: line too long", f); 1482 errorexit(); 1483 } 1484 memmove(buf, l, n); 1485 buf[n-1] = '\0'; 1486 n = getfields(buf, fields, nelem(fields), 1, " \t\r\n"); 1487 if(n == nelem(fields)){ 1488 diag("%s: bad format", f); 1489 errorexit(); 1490 } 1491 for(i = 0; i < n; i++){ 1492 s = lookup(fields[i], 0); 1493 s->type = SXREF; 1494 s->subtype = t; 1495 if(t == SIMPORT) 1496 nimports++; 1497 else 1498 nexports++; 1499 } 1500 } 1501 Bterm(b); 1502 } 1503