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