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