9 char *noname = "<none>";
10 char symname[] = SYMDEF;
12 char *thestring = "amd64";
13 char *paramspace = "FP";
16 * -H2 -T0x200028 -R0x200000 is plan9 format (was -T4136 -R4096)
17 * -H3 -T4128 -R4096 is plan9 32-bit format
18 * -H5 -T0x80110000 -R4096 is ELF32
20 * options used: 189BLQSWabcjlnpsvz
28 char buf1[5], buf2[SARMAG];
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 */
38 n = Bread(b, buf2, SARMAG);
39 v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0;
46 main(int argc, char *argv[])
51 Binit(&bso, 1, OWRITE);
54 memset(debug, 0, sizeof(debug));
65 if(c >= 0 && c < sizeof(debug))
68 case 'o': /* output to (next arg) */
79 HEADTYPE = atolwhex(a);
84 INITTEXT = atolwhex(a);
89 INITDAT = atolwhex(a);
94 INITRND = atolwhex(a);
96 case 'x': /* produce export table */
98 if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
99 readundefs(ARGF(), SEXPORT);
101 case 'u': /* produce dynamically loadable module */
104 if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
105 readundefs(ARGF(), SIMPORT);
110 diag("usage: 6l [-options] objects");
113 if(!debug['9'] && !debug['U'] && !debug['B'])
123 diag("unknown -H option");
128 INITTEXT = 0x200000+HEADR;
137 INITTEXT = 4096+HEADR;
143 case 5: /* elf32 executable */
144 HEADR = rnd(52L+3*32L, 16);
146 INITTEXT = 0xf0110000L;
153 if(INITDAT != 0 && INITRND != 0)
154 print("warning: -D0x%llux is ignored because of -R0x%lux\n",
157 Bprint(&bso, "HEADER = -H%ld -T0x%llux -D0x%llux -R0x%lux\n",
158 HEADTYPE, INITTEXT, INITDAT, INITRND);
160 for(i=1; optab[i].as; i++) {
162 if(opindex[c] != nil) {
163 diag("phase error in optab: %d (%A)", i, c);
166 opindex[c] = &optab[i];
169 for(i=0; i<Ymax; i++)
170 ycover[i*Ymax + i] = 1;
172 ycover[Yi0*Ymax + Yi8] = 1;
173 ycover[Yi1*Ymax + Yi8] = 1;
175 ycover[Yi0*Ymax + Ys32] = 1;
176 ycover[Yi1*Ymax + Ys32] = 1;
177 ycover[Yi8*Ymax + Ys32] = 1;
179 ycover[Yi0*Ymax + Yi32] = 1;
180 ycover[Yi1*Ymax + Yi32] = 1;
181 ycover[Yi8*Ymax + Yi32] = 1;
182 ycover[Ys32*Ymax + Yi32] = 1;
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;
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;
197 ycover[Ycl*Ymax + Ycx] = 1;
199 ycover[Yax*Ymax + Yrx] = 1;
200 ycover[Ycx*Ymax + Yrx] = 1;
202 ycover[Yax*Ymax + Yrl] = 1;
203 ycover[Ycx*Ymax + Yrl] = 1;
204 ycover[Yrx*Ymax + Yrl] = 1;
206 ycover[Yf0*Ymax + Yrf] = 1;
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;
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;
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;
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;
237 for(i=0; i<D_NONE; i++) {
239 if(i >= D_AL && i <= D_R15B) {
240 reg[i] = (i-D_AL) & 7;
241 if(i >= D_SPB && i <= D_DIB)
243 if(i >= D_R8B && i <= D_R15B)
244 regrex[i] = Rxr | Rxx | Rxb;
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;
251 regrex[i] = Rxr | Rxx | Rxb;
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;
260 regrex[i] = Rxr | Rxx | Rxb;
262 if(i >= D_CR+8 && i <= D_CR+15)
270 zprg.from.type = D_NONE;
271 zprg.from.index = D_NONE;
284 cout = create(outfile, 1, 0775);
286 diag("cannot create %s", outfile);
291 cbc = sizeof(buf.cbuf);
298 INITENTRY = "_mainp";
300 lookup(INITENTRY, 0)->type = SXREF;
301 } else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))
302 lookup(INITENTRY, 0)->type = SXREF;
308 firstp = firstp->link;
312 EXPTAB = "_exporttab";
331 paramspace = "SP"; /* (FP) now (SP) on output */
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));
362 for(i=0; i<libraryp; i++) {
364 Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
368 for(h=0; h<nelem(hash); h++)
369 for(s = hash[h]; s != S; s = s->link)
389 long off, esym, cnt, l;
393 char name[100], pname[150];
395 char *e, *start, *stop;
397 if(file[0] == '-' && file[1] == 'l') {
399 snprint(name, sizeof name, "/%s/lib/lib%s.a", thestring, file+2);
401 snprint(name, sizeof name, "/usr/%clib/lib%s.a", thechar, file+2);
405 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
409 diag("cannot open file: %s", file);
412 l = read(f, magbuf, SARMAG);
413 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
414 /* load it as a regular file */
422 l = read(f, &arhdr, SAR_HDR);
424 diag("%s: short read on archive file symbol header", file);
427 if(strncmp(arhdr.name, symname, strlen(symname))) {
428 diag("%s: first entry not symbol header", file);
432 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
433 off = SARMAG + SAR_HDR;
436 * just bang the whole symbol file into memory
440 start = malloc(cnt + 10);
441 cnt = read(f, start, cnt);
452 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
455 for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
459 snprint(pname, sizeof pname, "%s(%s)", file, s->name);
461 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
464 l |= (e[2] & 0xff) << 8;
465 l |= (e[3] & 0xff) << 16;
466 l |= (e[4] & 0xff) << 24;
468 l = read(f, &arhdr, SAR_HDR);
471 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
473 l = atolwhex(arhdr.size);
475 if(s->type == SXREF) {
476 diag("%s: failed to load: %s", file, s->name);
486 diag("%s: bad or out of date archive", file);
492 zaddr(uchar *p, Adr *a, Sym *h[])
512 * Hack until Charles fixes the compiler.
513 a->offset = (long)(p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24));
515 l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
519 l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
520 a->offset = ((vlong)l<<32) | (a->offset & 0xFFFFFFFFUL);
531 a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
532 a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24);
537 for(i=0; i<NSNAME; i++)
551 if(t != D_AUTO && t != D_PARAM)
554 for(u=curauto; u; u=u->link) {
563 while(nhunk < sizeof(Auto))
566 nhunk -= sizeof(Auto);
567 hunk += sizeof(Auto);
580 char name[1024], comp[256], *p;
586 if(histfrog[0]->name[1] == '/') {
590 if(histfrog[0]->name[1] == '.') {
591 snprint(name, sizeof name, ".");
595 snprint(name, sizeof name, "/%s/lib", thestring);
597 snprint(name, sizeof name, "/usr/%clib", thechar);
601 for(; i<histfrogp; i++) {
602 snprint(comp, sizeof comp, histfrog[i]->name+1);
604 p = strstr(comp, "$O");
607 memmove(p+1, p+2, strlen(p+2)+1);
611 p = strstr(comp, "$M");
614 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
615 diag("library component too long");
618 memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
619 memmove(p, thestring, strlen(thestring));
621 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
622 diag("library component too long");
628 for(i=0; i<libraryp; i++)
629 if(strcmp(name, library[i]) == 0)
631 if(libraryp == nelem(library)){
632 diag("too many autolibs; skipping %s", name);
636 p = malloc(strlen(name) + 1);
638 library[libraryp] = p;
639 p = malloc(strlen(obj) + 1);
641 libraryobj[libraryp] = p;
646 addhist(long line, int type)
652 u = malloc(sizeof(Auto));
653 s = malloc(sizeof(Sym));
654 s->name = malloc(2*(histfrogp+1) + 1);
663 for(i=0; i<histfrogp; i++) {
664 k = histfrog[i]->value;
689 * bad encoding of path components only allows
690 * MAXHIST components. if there is an overflow,
691 * first try to collapse xxx/..
693 for(i=1; i<histfrogp; i++)
694 if(strcmp(histfrog[i]->name+1, "..") == 0) {
695 memmove(histfrog+i-1, histfrog+i+1,
696 (histfrogp-i-1)*sizeof(histfrog[0]));
702 * next try to collapse .
704 for(i=0; i<histfrogp; i++)
705 if(strcmp(histfrog[i]->name+1, ".") == 0) {
706 memmove(histfrog+i, histfrog+i+1,
707 (histfrogp-i-1)*sizeof(histfrog[0]));
712 * last chance, just truncate from front
714 memmove(histfrog+0, histfrog+1,
715 (histfrogp-1)*sizeof(histfrog[0]));
718 histfrog[histfrogp-1] = s;
725 p->from.type = D_NONE;
730 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
735 memmove(buf, good, stop - good);
740 n = read(f, stop, n);
747 ldobj(int f, long c, char *pn)
751 uchar *bloc, *bsize, *stop;
752 int v, o, r, skip, mode;
753 Sym *h[NSYM], *s, *di;
760 nfilen = malloc((files+16)*sizeof(char*));
761 memmove(nfilen, filen, files*sizeof(char*));
765 filen[files++] = strdup(pn);
772 memset(h, 0, sizeof(h));
783 if(r < 100 && r < c) { /* enough for largest prog */
784 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
790 o = bloc[0] | (bloc[1] << 8);
791 if(o <= AXXX || o >= ALAST) {
794 diag("%s: opcode out of range %d", pn, o);
795 print(" probably not a .6 file\n");
799 if(o == ANAME || o == ASIGNAME) {
802 sig = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
806 stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
808 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
812 stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
814 fprint(2, "%s: name too long\n", pn);
818 v = bloc[2]; /* type */
819 o = bloc[3]; /* sym */
826 s = lookup((char*)bloc, r);
827 c -= &stop[1] - bloc;
830 if(debug['S'] && r == 0)
833 if(s->sig != 0 && s->sig != sig)
834 diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name);
840 print(" ANAME %s\n", s->name);
842 if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
845 if(s->type != SFILE) {
850 if(histfrogp < MAXHIST) {
851 histfrog[histfrogp] = s;
859 while(nhunk < sizeof(Prog))
862 nhunk -= sizeof(Prog);
863 hunk += sizeof(Prog);
866 p->line = bloc[2] | (bloc[3] << 8) | (bloc[4] << 16) | (bloc[5] << 24);
869 r = zaddr(bloc+6, &p->from, h) + 6;
870 r += zaddr(bloc+r, &p->to, h);
879 if(p->to.offset == -1) {
884 addhist(p->line, D_FILE); /* 'z' */
886 addhist(p->to.offset, D_FILE1); /* 'Z' */
893 curtext->to.autom = curauto;
902 if(p->from.scale & DUPOK)
904 if(s->type == 0 || s->type == SXREF) {
909 if(s->type != SBSS) {
910 diag("%s: redefinition: %s in %s",
915 if(p->to.offset > s->value)
916 s->value = p->to.offset;
921 diag("DYNT without a sym\n%P", p);
926 if(di->type == SXREF) {
928 Bprint(&bso, "%P set to %d\n", p, dtype);
936 p->from.offset = di->value;
937 p->from.sym->type = SDATA;
939 diag("DYNT not in text: %P", p);
942 p->to.sym = curtext->from.sym;
944 p->to.index = D_EXTERN;
948 if(p->from.sym == S) {
949 diag("INIT without a sym\n%P", p);
953 diag("INIT without previous DYNT\n%P", p);
956 p->from.offset = di->value;
957 p->from.sym->type = SDATA;
971 diag("%s: GOK opcode in %s", pn, TNAME);
978 curtext->to.autom = curauto;
985 diag("%s: no TEXT symbol: %P", pn, p);
988 if(s->type != 0 && s->type != SXREF) {
989 if(p->from.scale & DUPOK) {
993 diag("%s: redefinition: %s\n%P", pn, s->name, p);
1011 if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE){
1012 switch((int)p->from.offset){
1013 case 16: case 32: case 64:
1014 mode = p->from.offset;
1038 if(p->from.type == D_FCONST) {
1040 snprint(literal, sizeof literal, "$%lux", ieeedtof(&p->from.ieee));
1041 s = lookup(literal, 0);
1048 t->from.type = D_EXTERN;
1059 p->from.type = D_EXTERN;
1083 if(p->from.type == D_FCONST) {
1084 /* size sb 18 max */
1085 snprint(literal, sizeof literal, "$%lux.%lux",
1086 p->from.ieee.l, p->from.ieee.h);
1087 s = lookup(literal, 0);
1094 t->from.type = D_EXTERN;
1105 p->from.type = D_EXTERN;
1116 if(p->to.type == D_BRANCH)
1117 p->to.offset += ipc;
1127 diag("truncated object file: %s", pn);
1131 lookup(char *symb, int v)
1139 for(p=symb; c = *p; p++)
1145 for(s = hash[h]; s != S; s = s->link)
1147 if(memcmp(s->name, symb, l) == 0)
1150 while(nhunk < sizeof(Sym))
1153 nhunk -= sizeof(Sym);
1154 hunk += sizeof(Sym);
1156 s->name = malloc(l + 1);
1157 memmove(s->name, symb, l);
1175 while(nhunk < sizeof(Prog))
1178 nhunk -= sizeof(Prog);
1179 hunk += sizeof(Prog);
1215 if(thunk >= 5L*NHUNK) {
1217 if(thunk >= 25L*NHUNK)
1221 if(h == (char*)-1) {
1222 diag("out of memory");
1238 Bprint(&bso, "%5.2f profile 1\n", cputime());
1240 s = lookup("__mcount", 0);
1242 for(p = firstp->link; p != P; p = p->link) {
1243 if(p->as == ATEXT) {
1249 q->from.type = D_EXTERN;
1250 q->from.offset = n*4;
1254 q->to.type = D_CONST;
1263 p->from.type = D_CONST;
1265 p->to.type = D_EXTERN;
1267 p->to.offset = n*4 + 4;
1279 q->from.type = D_EXTERN;
1282 q->to.type = D_CONST;
1293 Prog *p, *q, *q2, *ps2, *ps4;
1296 Bprint(&bso, "%5.2f profile 2\n", cputime());
1300 s2 = lookup("_tracein", 0);
1301 s4 = lookup("_traceout", 0);
1303 s2 = lookup("_profin", 0);
1304 s4 = lookup("_profout", 0);
1306 if(s2->type != STEXT || s4->type != STEXT) {
1308 diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1310 diag("_profin/_profout not defined");
1316 for(p = firstp; p != P; p = p->link) {
1317 if(p->as == ATEXT) {
1318 if(p->from.sym == s2) {
1322 if(p->from.sym == s4) {
1328 for(p = firstp; p != P; p = p->link) {
1329 if(p->as == ATEXT) {
1332 if(p->from.scale & NOPROF) { /* dont profile */
1351 if(debug['e']){ /* embedded tracing */
1360 q2->to.type = D_BRANCH;
1361 q2->to.sym = p->to.sym;
1362 q2->pcond = q->link;
1367 p->to.type = D_BRANCH;
1377 if(debug['e']){ /* embedded tracing */
1399 p->from = zprg.from;
1401 p->to.type = D_BRANCH;
1417 for(i=0; i<4; i++) {
1418 c = find1(0x04030201L, i+1);
1430 inuxi8[i] = find1v(0x0807060504030201LL, i+1);
1433 Bprint(&bso, "inuxi = ");
1435 Bprint(&bso, "%d", inuxi1[i]);
1438 Bprint(&bso, "%d", inuxi2[i]);
1441 Bprint(&bso, "%d", inuxi4[i]);
1444 Bprint(&bso, "%d", inuxi8[i]);
1445 Bprint(&bso, "\nfnuxi = ");
1447 Bprint(&bso, "%d", fnuxi4[i]);
1450 Bprint(&bso, "%d", fnuxi8[i]);
1457 find1(long l, int c)
1470 find1v(vlong l, int c)
1483 find2(long l, int c)
1489 for(i=0; i<4; i+=2) {
1490 if(((*p >> 8) & 0xff) == c)
1492 if((*p++ & 0xff) == c)
1506 exp = (e->h>>20) & ((1L<<11)-1L);
1507 exp -= (1L<<10) - 2L;
1508 v = (e->h & 0xfffffL) << 3;
1509 v |= (e->l >> 29) & 0x7L;
1510 if((e->l >> 28) & 1) {
1513 v = (v & 0x7fffffL) >> 1;
1517 if(exp <= -126 || exp >= 130)
1518 diag("double fp to single fp overflow");
1519 v |= ((exp + 126) & 0xffL) << 23;
1520 v |= e->h & 0x80000000L;
1525 ieeedtod(Ieee *ieeep)
1531 if(ieeep->h & (1L<<31)) {
1532 e.h = ieeep->h & ~(1L<<31);
1534 return -ieeedtod(&e);
1536 if(ieeep->l == 0 && ieeep->h == 0)
1538 fr = ieeep->l & ((1L<<16)-1L);
1540 fr += (ieeep->l>>16) & ((1L<<16)-1L);
1542 fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1544 exp = (ieeep->h>>20) & ((1L<<11)-1L);
1545 exp -= (1L<<10) - 2L;
1546 return ldexp(fr, exp);
1556 diag("value != 0 on SXREF");
1558 diag("import index %d out of range", n);
1559 s->value = n<<Roffset;
1574 readundefs(char *f, int t)
1579 char *l, buf[256], *fields[64];
1583 b = Bopen(f, OREAD);
1585 diag("could not open %s: %r", f);
1588 while((l = Brdline(b, '\n')) != nil){
1590 if(n >= sizeof(buf)){
1591 diag("%s: line too long", f);
1596 n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
1597 if(n == nelem(fields)){
1598 diag("%s: bad format", f);
1601 for(i = 0; i < n; i++){
1602 s = lookup(fields[i], 0);