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