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