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 case AADDL: 988 if(p->from.type == D_CONST) 989 if(p->from.offset < 0) { 990 p->as = ASUBL; 991 p->from.offset = -p->from.offset; 992 } 993 goto casdef; 994 995 case ASUBL: 996 if(p->from.type == D_CONST) 997 if(p->from.offset < 0) { 998 p->as = AADDL; 999 p->from.offset = -p->from.offset; 1000 } 1001 goto casdef; 1002 1003 casdef: 1004 default: 1005 if(skip) 1006 nopout(p); 1007 1008 if(p->to.type == D_BRANCH) 1009 p->to.offset += ipc; 1010 lastp->link = p; 1011 lastp = p; 1012 p->pc = pc; 1013 pc++; 1014 goto loop; 1015 } 1016 goto loop; 1017 1018 eof: 1019 diag("truncated object file: %s", pn); 1020 } 1021 1022 Sym* 1023 lookup(char *symb, int v) 1024 { 1025 Sym *s; 1026 char *p; 1027 long h; 1028 int l, c; 1029 1030 h = v; 1031 for(p=symb; c = *p; p++) 1032 h = h+h+h + c; 1033 l = (p - symb) + 1; 1034 if(h < 0) 1035 h = ~h; 1036 h %= NHASH; 1037 for(s = hash[h]; s != S; s = s->link) 1038 if(s->version == v) 1039 if(memcmp(s->name, symb, l) == 0) 1040 return s; 1041 1042 while(nhunk < sizeof(Sym)) 1043 gethunk(); 1044 s = (Sym*)hunk; 1045 nhunk -= sizeof(Sym); 1046 hunk += sizeof(Sym); 1047 1048 s->name = malloc(l + 1); 1049 memmove(s->name, symb, l); 1050 1051 s->link = hash[h]; 1052 s->type = 0; 1053 s->version = v; 1054 s->value = 0; 1055 hash[h] = s; 1056 nsymbol++; 1057 return s; 1058 } 1059 1060 Prog* 1061 prg(void) 1062 { 1063 Prog *p; 1064 1065 while(nhunk < sizeof(Prog)) 1066 gethunk(); 1067 p = (Prog*)hunk; 1068 nhunk -= sizeof(Prog); 1069 hunk += sizeof(Prog); 1070 1071 *p = zprg; 1072 return p; 1073 } 1074 1075 Prog* 1076 copyp(Prog *q) 1077 { 1078 Prog *p; 1079 1080 p = prg(); 1081 *p = *q; 1082 return p; 1083 } 1084 1085 Prog* 1086 appendp(Prog *q) 1087 { 1088 Prog *p; 1089 1090 p = prg(); 1091 p->link = q->link; 1092 q->link = p; 1093 p->line = q->line; 1094 return p; 1095 } 1096 1097 void 1098 gethunk(void) 1099 { 1100 char *h; 1101 long nh; 1102 1103 nh = NHUNK; 1104 if(thunk >= 5L*NHUNK) { 1105 nh = 5L*NHUNK; 1106 if(thunk >= 25L*NHUNK) 1107 nh = 25L*NHUNK; 1108 } 1109 h = mysbrk(nh); 1110 if(h == (char*)-1) { 1111 diag("out of memory"); 1112 errorexit(); 1113 } 1114 hunk = h; 1115 nhunk = nh; 1116 thunk += nh; 1117 } 1118 1119 void 1120 doprof1(void) 1121 { 1122 Sym *s; 1123 long n; 1124 Prog *p, *q; 1125 1126 if(debug['v']) 1127 Bprint(&bso, "%5.2f profile 1\n", cputime()); 1128 Bflush(&bso); 1129 s = lookup("__mcount", 0); 1130 n = 1; 1131 for(p = firstp->link; p != P; p = p->link) { 1132 if(p->as == ATEXT) { 1133 q = prg(); 1134 q->line = p->line; 1135 q->link = datap; 1136 datap = q; 1137 q->as = ADATA; 1138 q->from.type = D_EXTERN; 1139 q->from.offset = n*4; 1140 q->from.sym = s; 1141 q->from.scale = 4; 1142 q->to = p->from; 1143 q->to.type = D_CONST; 1144 1145 q = prg(); 1146 q->line = p->line; 1147 q->pc = p->pc; 1148 q->link = p->link; 1149 p->link = q; 1150 p = q; 1151 p->as = AADDL; 1152 p->from.type = D_CONST; 1153 p->from.offset = 1; 1154 p->to.type = D_EXTERN; 1155 p->to.sym = s; 1156 p->to.offset = n*4 + 4; 1157 1158 n += 2; 1159 continue; 1160 } 1161 } 1162 q = prg(); 1163 q->line = 0; 1164 q->link = datap; 1165 datap = q; 1166 1167 q->as = ADATA; 1168 q->from.type = D_EXTERN; 1169 q->from.sym = s; 1170 q->from.scale = 4; 1171 q->to.type = D_CONST; 1172 q->to.offset = n; 1173 1174 s->type = SBSS; 1175 s->value = n*4; 1176 } 1177 1178 void 1179 doprof2(void) 1180 { 1181 Sym *s2, *s4; 1182 Prog *p, *q, *ps2, *ps4; 1183 1184 if(debug['v']) 1185 Bprint(&bso, "%5.2f profile 2\n", cputime()); 1186 Bflush(&bso); 1187 1188 s2 = lookup("_profin", 0); 1189 s4 = lookup("_profout", 0); 1190 if(s2->type != STEXT || s4->type != STEXT) { 1191 diag("_profin/_profout not defined"); 1192 return; 1193 } 1194 1195 ps2 = P; 1196 ps4 = P; 1197 for(p = firstp; p != P; p = p->link) { 1198 if(p->as == ATEXT) { 1199 if(p->from.sym == s2) { 1200 p->from.scale = 1; 1201 ps2 = p; 1202 } 1203 if(p->from.sym == s4) { 1204 p->from.scale = 1; 1205 ps4 = p; 1206 } 1207 } 1208 } 1209 for(p = firstp; p != P; p = p->link) { 1210 if(p->as == ATEXT) { 1211 curtext = p; 1212 1213 if(p->from.scale & NOPROF) { /* dont profile */ 1214 for(;;) { 1215 q = p->link; 1216 if(q == P) 1217 break; 1218 if(q->as == ATEXT) 1219 break; 1220 p = q; 1221 } 1222 continue; 1223 } 1224 1225 /* 1226 * JMPL profin 1227 */ 1228 q = prg(); 1229 q->line = p->line; 1230 q->pc = p->pc; 1231 q->link = p->link; 1232 p->link = q; 1233 p = q; 1234 p->as = ACALL; 1235 p->to.type = D_BRANCH; 1236 p->pcond = ps2; 1237 p->to.sym = s2; 1238 1239 continue; 1240 } 1241 if(p->as == ARET) { 1242 /* 1243 * RET 1244 */ 1245 q = prg(); 1246 q->as = ARET; 1247 q->from = p->from; 1248 q->to = p->to; 1249 q->link = p->link; 1250 p->link = q; 1251 1252 /* 1253 * JAL profout 1254 */ 1255 p->as = ACALL; 1256 p->from = zprg.from; 1257 p->to = zprg.to; 1258 p->to.type = D_BRANCH; 1259 p->pcond = ps4; 1260 p->to.sym = s4; 1261 1262 p = q; 1263 1264 continue; 1265 } 1266 } 1267 } 1268 1269 void 1270 nuxiinit(void) 1271 { 1272 int i, c; 1273 1274 for(i=0; i<4; i++) { 1275 c = find1(0x04030201L, i+1); 1276 if(i < 2) 1277 inuxi2[i] = c; 1278 if(i < 1) 1279 inuxi1[i] = c; 1280 inuxi4[i] = c; 1281 fnuxi4[i] = c; 1282 fnuxi8[i] = c; 1283 fnuxi8[i+4] = c+4; 1284 } 1285 if(debug['v']) { 1286 Bprint(&bso, "inuxi = "); 1287 for(i=0; i<1; i++) 1288 Bprint(&bso, "%d", inuxi1[i]); 1289 Bprint(&bso, " "); 1290 for(i=0; i<2; i++) 1291 Bprint(&bso, "%d", inuxi2[i]); 1292 Bprint(&bso, " "); 1293 for(i=0; i<4; i++) 1294 Bprint(&bso, "%d", inuxi4[i]); 1295 Bprint(&bso, "\nfnuxi = "); 1296 for(i=0; i<4; i++) 1297 Bprint(&bso, "%d", fnuxi4[i]); 1298 Bprint(&bso, " "); 1299 for(i=0; i<8; i++) 1300 Bprint(&bso, "%d", fnuxi8[i]); 1301 Bprint(&bso, "\n"); 1302 } 1303 Bflush(&bso); 1304 } 1305 1306 int 1307 find1(long l, int c) 1308 { 1309 char *p; 1310 int i; 1311 1312 p = (char*)&l; 1313 for(i=0; i<4; i++) 1314 if(*p++ == c) 1315 return i; 1316 return 0; 1317 } 1318 1319 int 1320 find2(long l, int c) 1321 { 1322 short *p; 1323 int i; 1324 1325 p = (short*)&l; 1326 for(i=0; i<4; i+=2) { 1327 if(((*p >> 8) & 0xff) == c) 1328 return i; 1329 if((*p++ & 0xff) == c) 1330 return i+1; 1331 } 1332 return 0; 1333 } 1334 1335 long 1336 ieeedtof(Ieee *e) 1337 { 1338 int exp; 1339 long v; 1340 1341 if(e->h == 0) 1342 return 0; 1343 exp = (e->h>>20) & ((1L<<11)-1L); 1344 exp -= (1L<<10) - 2L; 1345 v = (e->h & 0xfffffL) << 3; 1346 v |= (e->l >> 29) & 0x7L; 1347 if((e->l >> 28) & 1) { 1348 v++; 1349 if(v & 0x800000L) { 1350 v = (v & 0x7fffffL) >> 1; 1351 exp++; 1352 } 1353 } 1354 if(exp <= -126 || exp >= 130) 1355 diag("double fp to single fp overflow"); 1356 v |= ((exp + 126) & 0xffL) << 23; 1357 v |= e->h & 0x80000000L; 1358 return v; 1359 } 1360 1361 double 1362 ieeedtod(Ieee *ieeep) 1363 { 1364 Ieee e; 1365 double fr; 1366 int exp; 1367 1368 if(ieeep->h & (1L<<31)) { 1369 e.h = ieeep->h & ~(1L<<31); 1370 e.l = ieeep->l; 1371 return -ieeedtod(&e); 1372 } 1373 if(ieeep->l == 0 && ieeep->h == 0) 1374 return 0; 1375 fr = ieeep->l & ((1L<<16)-1L); 1376 fr /= 1L<<16; 1377 fr += (ieeep->l>>16) & ((1L<<16)-1L); 1378 fr /= 1L<<16; 1379 fr += (ieeep->h & (1L<<20)-1L) | (1L<<20); 1380 fr /= 1L<<21; 1381 exp = (ieeep->h>>20) & ((1L<<11)-1L); 1382 exp -= (1L<<10) - 2L; 1383 return ldexp(fr, exp); 1384 } 1385 1386 void 1387 readundefs(void) 1388 { 1389 int i, n; 1390 Sym *s; 1391 Biobuf *b; 1392 char *l, buf[256], *fields[5]; 1393 1394 for(i = 0; i < undefsp; i++) { 1395 b = Bopen(undefs[i], OREAD); 1396 if(b == nil) { 1397 diag("could not open %s: %r", undefs[i]); 1398 errorexit(); 1399 } 1400 while((l = Brdline(b, '\n')) != nil) { 1401 n = Blinelen(b); 1402 if(n >= sizeof(buf)) { 1403 diag("%s: line too long", undefs[i]); 1404 errorexit(); 1405 } 1406 strncpy(buf, l, n); 1407 n = getfields(buf, fields, nelem(fields), 1, " \t\r\n"); 1408 if(n == nelem(fields)) { 1409 diag("%s: bad format", undefs[i]); 1410 errorexit(); 1411 } 1412 s = lookup(fields[0], 0); 1413 s->type = SUNDEF; 1414 } 1415 Bterm(b); 1416 } 1417 } 1418