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