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