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