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