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