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