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