9 char *noname = "<none>";
10 char symname[] = SYMDEF;
12 char *thestring = "arm64";
19 char buf1[5], buf2[SARMAG];
24 n = Bread(b, buf1, 5);
25 if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<'))
26 v = 1; /* good enough for our purposes */
29 n = Bread(b, buf2, SARMAG);
30 v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0;
38 * -H2 -T0x100028 -R0x100000 is plan9 format
39 * -H6 -R0x10000 no header with segments padded to pages
46 diag("usage: %s [-options] objects", argv0);
51 main(int argc, char *argv[])
56 Binit(&bso, 1, OWRITE);
72 if(c >= 0 && c < sizeof(debug))
84 // addlibpath(EARGF(usage()));
89 INITTEXT = atolwhex(a);
94 INITTEXTP = atolwhex(a);
99 INITDAT = atolwhex(a);
104 INITRND = atolwhex(a);
109 HEADTYPE = atolwhex(a);
111 case 'x': /* produce export table */
113 if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
114 readundefs(ARGF(), SEXPORT);
116 case 'u': /* produce dynamically loadable module */
118 if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
119 readundefs(ARGF(), SIMPORT);
127 if(!debug['9'] && !debug['U'] && !debug['B'])
140 diag("unknown -H option");
142 case 0: /* no header */
143 case 6: /* no header, padded segments */
155 INITTEXT = 0x10000+HEADR;
163 INITTEXTP = INITTEXT;
164 if(INITDAT != 0 && INITRND != 0)
165 print("warning: -D0x%lux is ignored because of -R0x%lux\n",
168 Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n",
169 HEADTYPE, INITTEXT, INITDAT, INITRND);
173 zprg.from.name = D_NONE;
174 zprg.from.type = D_NONE;
175 zprg.from.reg = NREG;
177 zprg.from3 = zprg.from;
186 cout = create(outfile, 1, 0775);
188 diag("cannot create %s: %r", outfile);
195 cbc = sizeof(buf.cbuf);
202 INITENTRY = "_mainp";
204 lookup(INITENTRY, 0)->type = SXREF;
205 } else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))
206 lookup(INITENTRY, 0)->type = SXREF;
212 firstp = firstp->link;
216 EXPTAB = "_exporttab";
224 INITTEXT = INITDAT = 0;
247 Bprint(&bso, "%5.2f cpu time\n", cputime());
248 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
249 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
276 for(i=0; i<libraryp; i++) {
278 Bprint(&bso, "%5.2f autolib: %s\n", cputime(), library[i]);
282 for(h=0; h<nelem(hash); h++)
283 for(s = hash[h]; s != S; s = s->link)
291 long off, esym, cnt, l;
295 char name[100], pname[150];
297 char *e, *start, *stop;
299 if(file[0] == '-' && file[1] == 'l') {
301 snprint(name, sizeof name, "/%s/lib/lib%s.a", thestring, file+2);
303 snprint(name, sizeof name, "/usr/%clib/lib%s.a", thechar, file+2);
307 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
311 diag("cannot open file: %s", file);
314 l = read(f, magbuf, SARMAG);
315 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
316 /* load it as a regular file */
325 Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file);
326 l = read(f, &arhdr, SAR_HDR);
328 diag("%s: short read on archive file symbol header", file);
331 if(strncmp(arhdr.name, symname, strlen(symname))) {
332 diag("%s: first entry not symbol header: %s", file, arhdr.name);
336 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
337 off = SARMAG + SAR_HDR;
340 * just bang the whole symbol file into memory
344 start = malloc(cnt + 10);
345 cnt = read(f, start, cnt);
356 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
359 for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
363 snprint(pname, sizeof pname, "%s(%s)", file, s->name);
365 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
368 l |= (e[2] & 0xff) << 8;
369 l |= (e[3] & 0xff) << 16;
370 l |= (e[4] & 0xff) << 24;
372 l = read(f, &arhdr, SAR_HDR);
375 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
377 l = atolwhex(arhdr.size);
379 if(s->type == SXREF) {
380 diag("%s: failed to load: %s", file, s->name);
390 diag("%s: bad or out of date archive", file);
396 zaddr(uchar *p, Adr *a, Sym *h[])
404 if(c < 0 || c > NSYM){
405 print("sym out of range: %d\n", c);
415 if(a->reg < 0 || a->reg > NREG) {
416 print("register out of range %d\n", a->reg);
418 return 0; /* force real diagnostic */
423 print("unknown type %d\n", a->type);
425 return 0; /* force real diagnostic */
444 l = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);
447 if(a->type == D_CONST && l == 0)
452 l = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);
453 a->offset = (uvlong)l & 0xFFFFFFFFUL;
454 l = p[8] | (p[9]<<8) | (p[10]<<16) | (p[11]<<24);
455 a->offset |= (vlong)l << 32;
463 a->sval = halloc(NSNAME);
464 memmove(a->sval, p+4, NSNAME);
469 a->ieee = halloc(sizeof(Ieee));
470 a->ieee->l = p[4] | (p[5]<<8) |
471 (p[6]<<16) | (p[7]<<24);
472 a->ieee->h = p[8] | (p[9]<<8) |
473 (p[10]<<16) | (p[11]<<24);
481 if(i != D_AUTO && i != D_PARAM)
485 for(u=curauto; u; u=u->link)
493 u = halloc(sizeof(Auto));
520 * bad encoding of path components only allows
521 * MAXHIST components. if there is an overflow,
522 * first try to collapse xxx/..
524 for(i=1; i<histfrogp; i++)
525 if(strcmp(histfrog[i]->name+1, "..") == 0) {
526 memmove(histfrog+i-1, histfrog+i+1,
527 (histfrogp-i-1)*sizeof(histfrog[0]));
533 * next try to collapse .
535 for(i=0; i<histfrogp; i++)
536 if(strcmp(histfrog[i]->name+1, ".") == 0) {
537 memmove(histfrog+i, histfrog+i+1,
538 (histfrogp-i-1)*sizeof(histfrog[0]));
543 * last chance, just truncate from front
545 memmove(histfrog+0, histfrog+1,
546 (histfrogp-1)*sizeof(histfrog[0]));
549 histfrog[histfrogp-1] = s;
556 p->from.type = D_NONE;
563 if(p->from.type == D_CONST &&
564 p->from.name == D_NONE &&
571 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
576 memmove(buf, good, stop - good);
581 n = read(f, stop, n);
590 char name[1024], comp[256], *p;
596 if(histfrog[0]->name[1] == '/') {
600 if(histfrog[0]->name[1] == '.') {
601 snprint(name, sizeof name, ".");
605 snprint(name, sizeof name, "/%s/lib", thestring);
607 snprint(name, sizeof name, "/usr/%clib", thechar);
611 for(; i<histfrogp; i++) {
612 snprint(comp, sizeof comp, histfrog[i]->name+1);
614 p = strstr(comp, "$O");
617 memmove(p+1, p+2, strlen(p+2)+1);
621 p = strstr(comp, "$M");
624 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
625 diag("library component too long");
628 memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
629 memmove(p, thestring, strlen(thestring));
631 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
632 diag("library component too long");
638 for(i=0; i<libraryp; i++)
639 if(strcmp(name, library[i]) == 0)
641 if(libraryp == nelem(library)){
642 diag("too many autolibs; skipping %s", name);
646 p = malloc(strlen(name) + 1);
648 library[libraryp] = p;
649 p = malloc(strlen(obj) + 1);
651 libraryobj[libraryp] = p;
656 addhist(long line, int type)
662 u = malloc(sizeof(Auto));
663 s = malloc(sizeof(Sym));
664 s->name = malloc(2*(histfrogp+1) + 1);
673 for(i=0; i<histfrogp; i++) {
674 k = histfrog[i]->value;
682 ldobj(int f, long c, char *pn)
686 uchar *bloc, *bsize, *stop;
687 Sym *h[NSYM], *s, *di;
695 nfilen = malloc((files+16)*sizeof(char*));
696 memmove(nfilen, filen, files*sizeof(char*));
700 filen[files++] = strdup(pn);
707 memset(h, 0, sizeof(h));
717 if(r < 100 && r < c) { /* enough for largest prog */
718 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
724 o = bloc[0] | (bloc[1] << 8); /* as */
725 if(o <= AXXX || o >= ALAST) {
726 diag("%s: line %lld: opcode out of range %d", pn, pc-ipc, o);
727 print(" probably not a .7 file\n");
730 if(o == ANAME || o == ASIGNAME) {
733 sig = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
737 stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
739 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
743 stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
745 fprint(2, "%s: name too long\n", pn);
749 v = bloc[2]; /* type */
750 o = bloc[3]; /* sym */
757 s = lookup((char*)bloc, r);
758 c -= &stop[1] - bloc;
762 if(s->sig != 0 && s->sig != sig)
763 diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name);
769 print(" ANAME %s\n", s->name);
771 if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
774 if(s->type != SFILE) {
779 if(histfrogp < MAXHIST) {
780 histfrog[histfrogp] = s;
788 p = halloc(sizeof(Prog));
790 p->reg = bloc[2] & 0x3F;
793 p->line = bloc[3] | (bloc[4]<<8) | (bloc[5]<<16) | (bloc[6]<<24);
795 r = zaddr(bloc+7, &p->from, h) + 7;
797 r += zaddr(bloc+r, &p->from3, h);
799 p->from3 = zprg.from3;
800 r += zaddr(bloc+r, &p->to, h);
805 diag("register out of range %d", p->reg);
815 if(p->to.offset == -1) {
820 addhist(p->line, D_FILE); /* 'z' */
822 addhist(p->to.offset, D_FILE1); /* 'Z' */
829 curtext->to.autom = curauto;
839 diag("GLOBL must have a name\n%P", p);
842 if(s->type == 0 || s->type == SXREF) {
846 if(s->type != SBSS) {
847 diag("redefinition: %s\n%P", s->name, p);
851 if(p->to.offset > s->value)
852 s->value = p->to.offset;
857 diag("DYNT without a sym\n%P", p);
862 if(di->type == SXREF) {
864 Bprint(&bso, "%P set to %d\n", p, dtype);
872 p->from.offset = di->value;
873 p->from.sym->type = SDATA;
875 diag("DYNT not in text: %P", p);
878 p->to.sym = curtext->from.sym;
879 p->to.type = D_CONST;
885 if(p->from.sym == S) {
886 diag("INIT without a sym\n%P", p);
890 diag("INIT without previous DYNT\n%P", p);
893 p->from.offset = di->value;
894 p->from.sym->type = SDATA;
900 if(p->from.sym == S) {
901 diag("DATA without a sym\n%P", p);
909 diag("unknown opcode\n%P", p);
917 curtext->to.autom = curauto;
922 if(p->to.offset > 0){
923 autosize = (p->to.offset+7L) & ~7L;
924 p->to.offset = autosize;
930 diag("TEXT must have a name\n%P", p);
933 if(s->type != 0 && s->type != SXREF) {
938 diag("redefinition: %s\n%P", s->name, p);
957 p->from.offset = -p->from.offset;
964 p->from.offset = -p->from.offset;
971 p->from.offset = -p->from.offset;
978 p->from.offset = -p->from.offset;
985 p->from.offset = -p->from.offset;
992 p->from.offset = -p->from.offset;
999 p->from.offset = -p->from.offset;
1006 p->from.offset = -p->from.offset;
1012 if(p->from.type != D_FCONST)
1020 if(p->from.type == D_FCONST && chipfloat(p->from.ieee) < 0) {
1022 sprint(literal, "$%lux", ieeedtof(p->from.ieee));
1023 s = lookup(literal, 0);
1030 t->from.type = D_OREG;
1032 t->from.name = D_EXTERN;
1038 p->from.type = D_OREG;
1040 p->from.name = D_EXTERN;
1049 if(p->from.type == D_FCONST && chipfloat(p->from.ieee) < 0) {
1050 /* size sb 18 max */
1051 sprint(literal, "$%lux.%lux",
1052 p->from.ieee->l, p->from.ieee->h);
1053 s = lookup(literal, 0);
1060 t->from.type = D_OREG;
1062 t->from.name = D_EXTERN;
1068 p->from.type = D_OREG;
1070 p->from.name = D_EXTERN;
1080 if(p->to.type == D_BRANCH)
1081 p->to.offset += ipc;
1082 if(p->from.type == D_BRANCH)
1083 p->from.offset += ipc;
1093 diag("truncated object file: %s", pn);
1097 lookup(char *symb, int v)
1105 for(p=symb; c = *p; p++)
1111 for(s = hash[h]; s != S; s = s->link)
1113 if(memcmp(s->name, symb, l) == 0)
1116 while(nhunk < sizeof(Sym))
1119 nhunk -= sizeof(Sym);
1120 hunk += sizeof(Sym);
1122 s->name = malloc(l);
1123 memmove(s->name, symb, l);
1140 while(nhunk < sizeof(Prog))
1143 nhunk -= sizeof(Prog);
1144 hunk += sizeof(Prog);
1171 if(thunk >= 5L*NHUNK) {
1173 if(thunk >= 25L*NHUNK)
1177 if(h == (char*)-1) {
1178 diag("out of memory");
1194 Bprint(&bso, "%5.2f profile 1\n", cputime());
1196 s = lookup("__mcount", 0);
1198 for(p = firstp->link; p != P; p = p->link) {
1199 if(p->as == ATEXT) {
1205 q->from.type = D_OREG;
1206 q->from.name = D_EXTERN;
1207 q->from.offset = n*4;
1211 q->to.type = D_CONST;
1220 p->from.type = D_OREG;
1221 p->from.name = D_EXTERN;
1223 p->from.offset = n*PCSZ + PCSZ;
1234 p->from.type = D_CONST;
1246 p->from.type = D_REG;
1247 p->from.reg = REGTMP;
1248 p->to.type = D_OREG;
1249 p->to.name = D_EXTERN;
1251 p->to.offset = n*PCSZ + PCSZ;
1263 q->from.type = D_OREG;
1264 q->from.name = D_EXTERN;
1267 q->to.type = D_CONST;
1278 Prog *p, *q, *q2, *ps2, *ps4;
1281 Bprint(&bso, "%5.2f profile 2\n", cputime());
1285 s2 = lookup("_tracein", 0);
1286 s4 = lookup("_traceout", 0);
1288 s2 = lookup("_profin", 0);
1289 s4 = lookup("_profout", 0);
1291 if(s2->type != STEXT || s4->type != STEXT) {
1293 diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1295 diag("_profin/_profout not defined");
1301 for(p = firstp; p != P; p = p->link) {
1302 if(p->as == ATEXT) {
1303 if(p->from.sym == s2) {
1307 if(p->from.sym == s4) {
1313 for(p = firstp; p != P; p = p->link) {
1314 if(p->as == ATEXT) {
1315 if(p->reg & NOPROF) {
1334 if(debug['e']){ /* embedded tracing */
1343 q2->to.type = D_BRANCH;
1344 q2->to.sym = p->to.sym;
1350 p->to.type = D_BRANCH;
1356 if(p->as == ARETURN) {
1360 if(debug['e']){ /* embedded tracing */
1385 p->from = zprg.from;
1387 p->to.type = D_BRANCH;
1403 for(i=0; i<4; i++) {
1404 c = find1(0x04030201L, i+1);
1417 Bprint(&bso, "inuxi = ");
1419 Bprint(&bso, "%d", inuxi1[i]);
1422 Bprint(&bso, "%d", inuxi2[i]);
1425 Bprint(&bso, "%d", inuxi4[i]);
1428 Bprint(&bso, "%d", inuxi8[i]);
1429 Bprint(&bso, "\nfnuxi = ");
1431 Bprint(&bso, "%d", fnuxi4[i]);
1434 Bprint(&bso, "%d", fnuxi8[i]);
1441 find1(long l, int c)
1454 ieeedtof(Ieee *ieeep)
1461 exp = (ieeep->h>>20) & ((1L<<11)-1L);
1462 exp -= (1L<<10) - 2L;
1463 v = (ieeep->h & 0xfffffL) << 3;
1464 v |= (ieeep->l >> 29) & 0x7L;
1465 if((ieeep->l >> 28) & 1) {
1468 v = (v & 0x7fffffL) >> 1;
1472 if(exp <= -126 || exp >= 130)
1473 diag("double fp to single fp overflow");
1474 v |= ((exp + 126) & 0xffL) << 23;
1475 v |= ieeep->h & 0x80000000L;
1480 ieeedtod(Ieee *ieeep)
1486 if(ieeep->h & (1L<<31)) {
1487 e.h = ieeep->h & ~(1L<<31);
1489 return -ieeedtod(&e);
1491 if(ieeep->l == 0 && ieeep->h == 0)
1493 fr = ieeep->l & ((1L<<16)-1L);
1495 fr += (ieeep->l>>16) & ((1L<<16)-1L);
1497 fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1499 exp = (ieeep->h>>20) & ((1L<<11)-1L);
1500 exp -= (1L<<10) - 2L;
1501 return ldexp(fr, exp);