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