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