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