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