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