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