9 char *noname = "<none>";
10 char symname[] = SYMDEF;
12 char *thestring = "68020";
15 * -H0 -T0x40004C -D0x10000000 is garbage unix
16 * -H1 -T0x80020000 -R4 is garbage format
17 * -H2 -T8224 -R8192 is plan9 format
18 * -H3 -Tx -Rx is next boot
22 main(int argc, char *argv[])
27 Binit(&bso, 1, OWRITE);
30 memset(debug, 0, sizeof(debug));
42 if(c >= 0 && c < sizeof(debug))
45 case 'o': /* output to (next arg) */
56 HEADTYPE = atolwhex(a);
61 INITTEXT = atolwhex(a);
66 INITDAT = atolwhex(a);
71 INITRND = atolwhex(a);
78 diag("usage: 2l [-options] objects");
81 if(!debug['9'] && !debug['U'] && !debug['B'])
91 if(INITDAT != -1 && INITRND == -1)
95 diag("unknown -H option %ld", HEADTYPE);
98 case 0: /* this is garbage */
101 INITTEXT = 0x40004CL;
103 INITDAT = 0x10000000L;
104 if(INITDAT != 0 && INITRND == -1)
109 case 1: /* plan9 boot data goes into text */
115 if(INITDAT != 0 && INITRND == -1)
126 if(INITDAT != 0 && INITRND == -1)
131 case 3: /* next boot */
132 HEADR = 28+124+192+24;
134 INITTEXT = 0x04002000;
137 if(INITDAT != 0 && INITRND == -1)
142 case 4: /* preprocess pilot */
148 if(INITDAT != 0 && INITRND == -1)
154 if(INITDAT != 0 && INITRND != 0)
155 print("warning: -D0x%lux is ignored because of -R0x%lux\n",
158 Bprint(&bso, "HEADER = -H0x%ld -T0x%lux -D0x%lux -R0x%lux\n",
159 HEADTYPE, INITTEXT, INITDAT, INITRND);
161 for(i=1; optab[i].as; i++)
162 if(i != optab[i].as) {
163 diag("phase error in optab: %d", i);
171 zprg.from.type = D_NONE;
172 zprg.from.index = D_NONE;
175 memset(special, 0, sizeof(special));
188 special[D_FPIAR] = 1;
194 special[D_MMUSR] = 1;
197 memset(simple, 0177, sizeof(simple));
200 simple[D_F0+i] = i+0100;
201 simple[D_A0+i] = i+010;
202 simple[D_A0+I_INDIR+i] = i+020;
203 simple[D_A0+I_INDINC+i] = i+030;
204 simple[D_A0+I_INDDEC+i] = i+040;
211 cout = create(outfile, 1, 0775);
213 diag("cannot create %s", outfile);
218 cbc = sizeof(buf.cbuf);
225 INITENTRY = "_mainp";
227 lookup(INITENTRY, 0)->type = SXREF;
229 lookup(INITENTRY, 0)->type = SXREF;
235 firstp = firstp->link;
251 Bprint(&bso, "%5.2f cpu time\n", cputime());
252 Bprint(&bso, "%ld+%ld = %ld data statements\n",
253 ndata, ncase, ndata+ncase);
254 Bprint(&bso, "%ld symbols\n", nsymbol);
255 Bprint(&bso, "%ld memory used\n", thunk);
256 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
257 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
273 for(i=0; i<libraryp; i++) {
275 Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
279 for(h=0; h<nelem(hash); h++)
280 for(s = hash[h]; s != S; s = s->link)
301 long off, esym, cnt, l;
305 char name[100], pname[150];
307 char *e, *start, *stop;
309 if(file[0] == '-' && file[1] == 'l') {
311 snprint(name, sizeof name, "/%s/lib/lib%s.a", thestring, file+2);
313 snprint(name, sizeof name, "/usr/%clib/lib%s.a", thechar, file+2);
317 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
321 diag("cannot open file: %s", file);
324 l = read(f, magbuf, SARMAG);
325 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
326 /* load it as a regular file */
334 l = read(f, &arhdr, SAR_HDR);
336 diag("%s: short read on archive file symbol header", file);
339 if(strncmp(arhdr.name, symname, strlen(symname))) {
340 diag("%s: first entry not symbol header", file);
344 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
345 off = SARMAG + SAR_HDR;
348 * just bang the whole symbol file into memory
352 start = malloc(cnt + 10);
353 cnt = read(f, start, cnt);
364 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
367 for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
371 snprint(pname, sizeof pname, "%s(%s)", file, s->name);
373 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
376 l |= (e[2] & 0xff) << 8;
377 l |= (e[3] & 0xff) << 16;
378 l |= (e[4] & 0xff) << 24;
380 l = read(f, &arhdr, SAR_HDR);
383 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
385 l = atolwhex(arhdr.size);
387 if(s->type == SXREF) {
388 diag("%s: failed to load: %s", file, s->name);
398 diag("%s: bad or out of date archive", file);
404 zaddr(uchar *p, Adr *a, Sym *h[])
414 * first try the high-time formats
423 a->offset = p[1] | (p[2]<<8) | (p[3]<<16) | (p[4]<<24);
427 if(t == (T_OFFSET|T_SYM)) {
429 a->offset = p[1] | (p[2]<<8) | (p[3]<<16) | (p[4]<<24);
444 if(t == (T_INDEX|T_OFFSET|T_SYM)) {
445 a->index = p[1] | (p[2]<<8);
447 a->displace = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);
448 a->offset = p[8] | (p[9]<<8) | (p[10]<<16) | (p[11]<<24);
457 * now do it the hard way
462 a->field = p[c] | (p[c+1]<<8);
466 a->index = p[c] | (p[c+1]<<8);
468 a->displace = p[c+3] | (p[c+4]<<8) | (p[c+5]<<16) | (p[c+6]<<24);
472 a->offset = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
480 a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
481 a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24);
486 for(i=0; i<NSNAME; i++)
492 a->type = p[c] | (p[c+1]<<8);
503 t = a->type & D_MASK;
504 if(t != D_AUTO && t != D_PARAM)
507 for(u=curauto; u; u=u->link) {
516 while(nhunk < sizeof(Auto))
519 nhunk -= sizeof(Auto);
520 hunk += sizeof(Auto);
533 char name[1024], comp[256], *p;
539 if(histfrog[0]->name[1] == '/') {
543 if(histfrog[0]->name[1] == '.') {
544 snprint(name, sizeof name, ".");
548 snprint(name, sizeof name, "/%s/lib", thestring);
550 snprint(name, sizeof name, "/usr/%clib", thechar);
554 for(; i<histfrogp; i++) {
555 snprint(comp, sizeof comp, histfrog[i]->name+1);
557 p = strstr(comp, "$O");
560 memmove(p+1, p+2, strlen(p+2)+1);
564 p = strstr(comp, "$M");
567 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
568 diag("library component too long");
571 memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
572 memmove(p, thestring, strlen(thestring));
574 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
575 diag("library component too long");
581 for(i=0; i<libraryp; i++)
582 if(strcmp(name, library[i]) == 0)
584 if(libraryp == nelem(library)){
585 diag("too many autolibs; skipping %s", name);
589 p = malloc(strlen(name) + 1);
591 library[libraryp] = p;
592 p = malloc(strlen(obj) + 1);
594 libraryobj[libraryp] = p;
598 addhist(long line, int type)
604 u = malloc(sizeof(Auto));
605 s = malloc(sizeof(Sym));
606 s->name = malloc(2*(histfrogp+1) + 1);
615 for(i=0; i<histfrogp; i++) {
616 k = histfrog[i]->value;
641 * bad encoding of path components only allows
642 * MAXHIST components. if there is an overflow,
643 * first try to collapse xxx/..
645 for(i=1; i<histfrogp; i++)
646 if(strcmp(histfrog[i]->name+1, "..") == 0) {
647 memmove(histfrog+i-1, histfrog+i+1,
648 (histfrogp-i-1)*sizeof(histfrog[0]));
654 * next try to collapse .
656 for(i=0; i<histfrogp; i++)
657 if(strcmp(histfrog[i]->name+1, ".") == 0) {
658 memmove(histfrog+i, histfrog+i+1,
659 (histfrogp-i-1)*sizeof(histfrog[0]));
664 * last chance, just truncate from front
666 memmove(histfrog+0, histfrog+1,
667 (histfrogp-1)*sizeof(histfrog[0]));
670 histfrog[histfrogp-1] = s;
674 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
679 memmove(buf, good, stop - good);
684 n = read(f, stop, n);
691 ldobj(int f, long c, char *pn)
698 uchar *bloc, *bsize, *stop;
704 memset(h, 0, sizeof(h));
713 if(r < 100 && r < c) { /* enough for largest prog */
714 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
720 o = bloc[0] | (bloc[1] << 8);
721 if(o <= AXXX || o >= ALAST) {
724 diag("%s: opcode out of range %d", pn, o);
725 print(" probably not a .2 file\n");
729 if(o == ANAME || o == ASIGNAME) {
734 stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
736 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
740 stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
742 fprint(2, "%s: name too long\n", pn);
746 v = bloc[2]; /* type */
747 o = bloc[3]; /* sym */
754 s = lookup((char*)bloc, r);
755 c -= &stop[1] - bloc;
759 print(" ANAME %s\n", s->name);
761 if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
764 if(s->type != SFILE) {
769 if(histfrogp < MAXHIST) {
770 histfrog[histfrogp] = s;
778 while(nhunk < sizeof(Prog))
781 nhunk -= sizeof(Prog);
782 hunk += sizeof(Prog);
785 p->line = bloc[2] | (bloc[3] << 8) | (bloc[4] << 16) | (bloc[5] << 24);
787 r = zaddr(bloc+6, &p->from, h) + 6;
788 r += zaddr(bloc+r, &p->to, h);
797 if(p->to.offset == -1) {
802 addhist(p->line, D_FILE); /* 'z' */
804 addhist(p->to.offset, D_FILE1); /* 'Z' */
811 curtext->to.autom = curauto;
820 if(s->type == 0 || s->type == SXREF) {
824 if(s->type != SBSS) {
825 diag("%s: redefinition: %s in %s",
830 if(p->to.offset > s->value)
831 s->value = p->to.offset;
845 diag("%s: unknown opcode in %s", pn, TNAME);
852 curtext->to.autom = curauto;
860 if(s->type != 0 && s->type != SXREF)
861 diag("%s: redefinition: %s", pn, s->name);
879 if(p->to.index != D_NONE)
881 if(p->to.type != D_EXTERN && p->to.type != D_STATIC)
888 if(p->from.type != D_CONST)
891 if(lv >= -128 && lv < 128)
892 if(p->to.type >= D_R0 && p->to.type < D_R0+8)
893 if(p->to.index == D_NONE) {
894 p->from.type = D_QUICK;
898 if(lv >= -0x7fff && lv <= 0x7fff)
899 if(p->to.type >= D_A0 && p->to.type < D_A0+8)
900 if(p->to.index == D_NONE)
908 if(p->from.type != D_CONST)
925 p->from.type = D_QUICK;
931 if(p->from.type != D_CONST)
948 p->from.type = D_QUICK;
970 if(p->from.type == D_CONST)
971 if(p->from.offset > 0)
972 if(p->from.offset <= 8)
973 p->from.type = D_QUICK;
977 if(p->to.type >= D_A0 && p->to.type < D_A0+8) {
980 p->to.type = D_CONST;
986 if(p->to.type != D_CONST)
989 if(lv >= -0x7fff && lv <= 0x7fff)
990 if(p->from.type >= D_A0 && p->from.type < D_A0+8)
991 if(p->from.index == D_NONE)
996 if(p->to.type >= D_A0 && p->to.type < D_A0+8) {
998 p->from.type = D_CONST;
1005 if(p->from.type == D_FCONST)
1006 if(optab[p->as].fas != AXXX) {
1007 dv = ieeedtod(&p->from.ieee);
1008 if(dv >= -(1L<<30) && dv <= (1L<<30)) {
1011 p->as = optab[p->as].fas;
1012 p->from.type = D_CONST;
1013 p->from.offset = lv;
1014 p->from.displace = 0;
1018 if(p->to.type == D_BRANCH)
1019 p->to.offset += ipc;
1029 diag("%s: truncated object file in %s", pn, TNAME);
1033 lookup(char *symb, int v)
1041 for(p=symb; c = *p; p++)
1047 for(s = hash[h]; s != S; s = s->link)
1049 if(memcmp(s->name, symb, l) == 0)
1052 while(nhunk < sizeof(Sym))
1055 nhunk -= sizeof(Sym);
1056 hunk += sizeof(Sym);
1058 s->name = malloc(l + 1);
1059 memmove(s->name, symb, l);
1075 while(nhunk < sizeof(Prog))
1078 nhunk -= sizeof(Prog);
1079 hunk += sizeof(Prog);
1114 if(thunk >= 5L*NHUNK) {
1116 if(thunk >= 25L*NHUNK)
1120 if(h == (char*)-1) {
1121 diag("out of memory");
1137 Bprint(&bso, "%5.2f profile 1\n", cputime());
1139 s = lookup("__mcount", 0);
1141 for(p = firstp->link; p != P; p = p->link) {
1142 if(p->as == ATEXT) {
1149 q->from.type = D_CONST;
1151 q->to.type = D_EXTERN;
1153 q->to.offset = n*4 + 4;
1160 q->from.type = D_EXTERN;
1162 q->from.offset = n*4;
1163 q->from.displace = 4;
1164 q->to.type = D_EXTERN;
1165 q->to.sym = p->from.sym;
1175 q->from.type = D_EXTERN;
1177 q->from.displace = 4;
1178 q->to.type = D_CONST;
1188 Prog *p, *q, *q2, *ps2, *ps4;
1191 Bprint(&bso, "%5.2f profile 2\n", cputime());
1195 s2 = lookup("_tracein", 0);
1196 s4 = lookup("_traceout", 0);
1198 s2 = lookup("_profin", 0);
1199 s4 = lookup("_profout", 0);
1201 if(s2->type != STEXT || s4->type != STEXT) {
1203 diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1205 diag("_profin/_profout not defined");
1211 for(p = firstp; p != P; p = p->link) {
1212 if(p->as == ATEXT) {
1213 if(p->from.sym == s2) {
1215 p->from.displace = 1;
1217 if(p->from.sym == s4) {
1219 p->from.displace = 1;
1223 for(p = firstp; p != P; p = p->link) {
1224 if(p->as == ATEXT) {
1225 if(p->from.displace != 0) {
1241 if(debug['e']){ /* embedded tracing */
1250 q2->to.type = D_BRANCH;
1251 q2->to.sym = p->to.sym;
1252 q2->pcond = q->link;
1257 p->to.type = D_BRANCH;
1267 if(debug['e']){ /* embedded tracing */
1289 p->from = zprg.from;
1291 p->to.type = D_BRANCH;
1303 reuse(Prog *r, Sym *s)
1310 for(p = datap; p != r; p = p->link)
1312 return p->from.offset;
1321 for(i=0; i<4; i++) {
1322 c = find1(0x01020304L, i+1);
1330 c = find2(0x01020304L, i+1);
1335 Bprint(&bso, "inuxi = ");
1337 Bprint(&bso, "%d", inuxi1[i]);
1340 Bprint(&bso, "%d", inuxi2[i]);
1343 Bprint(&bso, "%d", inuxi4[i]);
1344 Bprint(&bso, "\n[fg]nuxi = ");
1346 Bprint(&bso, "%d", fnuxi8[i]);
1349 Bprint(&bso, "%d", gnuxi8[i]);
1356 find1(long l, int c)
1369 find2(long l, int c)
1375 for(i=0; i<4; i+=2) {
1376 if(((*p >> 8) & 0xff) == c)
1378 if((*p++ & 0xff) == c)
1392 exp = (e->h>>20) & ((1L<<11)-1L);
1393 exp -= (1L<<10) - 2L;
1394 v = (e->h & 0xfffffL) << 3;
1395 v |= (e->l >> 29) & 0x7L;
1396 if((e->l >> 28) & 1) {
1399 v = (v & 0x7fffffL) >> 1;
1403 if(exp <= -126 || exp >= 130)
1404 diag("double fp to single fp overflow");
1405 v |= ((exp + 126) & 0xffL) << 23;
1406 v |= e->h & 0x80000000L;
1411 ieeedtod(Ieee *ieeep)
1417 if(ieeep->h & (1L<<31)) {
1418 e.h = ieeep->h & ~(1L<<31);
1420 return -ieeedtod(&e);
1422 if(ieeep->l == 0 && ieeep->h == 0)
1424 fr = ieeep->l & ((1L<<16)-1L);
1426 fr += (ieeep->l>>16) & ((1L<<16)-1L);
1428 fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1430 exp = (ieeep->h>>20) & ((1L<<11)-1L);
1431 exp -= (1L<<10) - 2L;
1432 return ldexp(fr, exp);