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