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