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