8 char *noname = "<none>";
9 char symname[] = SYMDEF;
11 char *thestring = "alpha";
14 * -H0 -T0x12000004C -D0x140000000 is abbrev unix
15 * -H1 -T0x20000000 -R4 is bootp() format
16 * -H2 -T8224 -R8192 is plan9 format
20 main(int argc, char *argv[])
25 Binit(&bso, 1, OWRITE);
40 if(c >= 0 && c < sizeof(debug))
54 INITTEXT = atolwhex(a);
59 INITDAT = atolwhex(a);
64 INITRND = atolwhex(a);
69 HEADTYPE = atolwhex(a);
70 /* do something about setting INITTEXT */
77 diag("usage: 7l [-options] objects");
80 if(!debug['9'] && !debug['B'] && !debug['U'])
92 diag("unknown -H option");
95 case 0: /* unix simple */
98 INITTEXT = 0x120000070LL; /* BUG */
100 INITDAT = 0x140000000LL; /* BUG */
108 INITTEXT = 0x20000074L;
123 case 3: /* ``headerless'' tftp boot -- uses branch as magic */
126 INITTEXT = 0x20000020L;
133 if(INITDAT != 0 && INITRND != 0)
134 print("warning: -D0x%lux is ignored because of -R0x%lux\n",
137 Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n",
138 HEADTYPE, INITTEXT, INITDAT, INITRND);
142 zprg.from.name = D_NONE;
143 zprg.from.type = D_NONE;
144 zprg.from.reg = NREG;
154 cout = create(outfile, 1, 0775);
156 diag("%s: cannot create", outfile);
163 cbc = sizeof(buf.cbuf);
170 INITENTRY = "_mainp";
172 lookup(INITENTRY, 0)->type = SXREF;
174 lookup(INITENTRY, 0)->type = SXREF;
180 firstp = firstp->link;
193 dodata(); /* is before follow() on other arch */
200 Bprint(&bso, "%5.2f cpu time\n", cputime());
201 Bprint(&bso, "%ld memory used\n", thunk);
202 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
203 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
218 for(i=0; i<libraryp; i++) {
220 Bprint(&bso, "%5.2f autolib: %s\n", cputime(), library[i]);
224 for(h=0; h<nelem(hash); h++)
225 for(s = hash[h]; s != S; s = s->link)
246 long off, esym, cnt, l;
250 char name[100], pname[150];
252 char *e, *start, *stop;
254 if(file[0] == '-' && file[1] == 'l') {
256 sprint(name, "/%s/lib/lib", thestring);
258 sprint(name, "/usr/%clib/lib", thechar);
259 strcat(name, file+2);
264 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
268 diag("cannot open file: %s", file);
271 l = read(f, magbuf, SARMAG);
272 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
273 /* load it as a regular file */
282 Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file);
283 l = read(f, &arhdr, SAR_HDR);
285 diag("%s: short read on archive file symbol header", file);
288 if(strncmp(arhdr.name, symname, strlen(symname))) {
289 diag("%s: first entry not symbol header", file);
293 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
294 off = SARMAG + SAR_HDR;
297 * just bang the whole symbol file into memory
301 start = malloc(cnt + 10);
302 cnt = read(f, start, cnt);
313 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
316 for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
320 sprint(pname, "%s(%s)", file, s->name);
322 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
325 l |= (e[2] & 0xff) << 8;
326 l |= (e[3] & 0xff) << 16;
327 l |= (e[4] & 0xff) << 24;
329 l = read(f, &arhdr, SAR_HDR);
332 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
334 l = atolwhex(arhdr.size);
336 if(s->type == SXREF) {
337 diag("%s: failed to load: %s", file, s->name);
347 diag("%s: bad or out of date archive", file);
353 zaddr(uchar *p, Adr *a, Sym *h[])
361 if(c < 0 || c > NSYM){
362 print("sym out of range: %d\n", c);
372 if(a->reg < 0 || a->reg > NREG) {
373 print("register out of range %d\n", a->reg);
375 return 0; /* force real diagnostic */
380 print("unknown type %d\n", a->type);
382 return 0; /* force real diagnostic */
395 a->offset = (uvlong)p[4] | ((uvlong)p[5]<<8L) |
396 ((uvlong) p[6]<<16L) | ((uvlong) p[7]<<24L) |
397 ((uvlong) p[8]<<32L) | ((uvlong) p[9]<<40L) |
398 ((uvlong) p[10]<<48L) | ((uvlong) p[11]<<56L);
403 while(nhunk < NSNAME)
405 a->sval = (char*)hunk;
409 memmove(a->sval, p+4, NSNAME);
414 while(nhunk < sizeof(Ieee))
416 a->ieee = (Ieee*)hunk;
417 nhunk -= sizeof(Ieee);
418 hunk += sizeof(Ieee);
420 a->ieee->l = p[4] | (p[5]<<8) |
421 (p[6]<<16) | (p[7]<<24);
422 a->ieee->h = p[8] | (p[9]<<8) |
423 (p[10]<<16) | (p[11]<<24);
431 if(i != D_AUTO && i != D_PARAM)
435 for(u=curauto; u; u=u->link)
443 while(nhunk < sizeof(Auto))
446 nhunk -= sizeof(Auto);
447 hunk += sizeof(Auto);
460 char name[1024], comp[256], *p;
466 if(histfrog[0]->name[1] == '/') {
470 if(histfrog[0]->name[1] == '.') {
475 sprint(name, "/%s/lib", thestring);
477 sprint(name, "/usr/%clib", thechar);
481 for(; i<histfrogp; i++) {
482 snprint(comp, sizeof comp, histfrog[i]->name+1);
484 p = strstr(comp, "$O");
487 memmove(p+1, p+2, strlen(p+2)+1);
491 p = strstr(comp, "$M");
494 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
495 diag("library component too long");
498 memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
499 memmove(p, thestring, strlen(thestring));
501 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
502 diag("library component too long");
508 for(i=0; i<libraryp; i++)
509 if(strcmp(name, library[i]) == 0)
511 if(libraryp == nelem(library)){
512 diag("too many autolibs; skipping %s", name);
516 p = malloc(strlen(name) + 1);
518 library[libraryp] = p;
519 p = malloc(strlen(obj) + 1);
521 libraryobj[libraryp] = p;
526 addhist(long line, int type)
532 u = malloc(sizeof(Auto));
533 s = malloc(sizeof(Sym));
534 s->name = malloc(2*(histfrogp+1) + 1);
543 for(i=0; i<histfrogp; i++) {
544 k = histfrog[i]->value;
569 * bad encoding of path components only allows
570 * MAXHIST components. if there is an overflow,
571 * first try to collapse xxx/..
573 for(i=1; i<histfrogp; i++)
574 if(strcmp(histfrog[i]->name+1, "..") == 0) {
575 memmove(histfrog+i-1, histfrog+i+1,
576 (histfrogp-i-1)*sizeof(histfrog[0]));
582 * next try to collapse .
584 for(i=0; i<histfrogp; i++)
585 if(strcmp(histfrog[i]->name+1, ".") == 0) {
586 memmove(histfrog+i, histfrog+i+1,
587 (histfrogp-i-1)*sizeof(histfrog[0]));
592 * last chance, just truncate from front
594 memmove(histfrog+0, histfrog+1,
595 (histfrogp-1)*sizeof(histfrog[0]));
598 histfrog[histfrogp-1] = s;
605 p->from.type = D_NONE;
610 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
615 memmove(buf, good, stop - good);
620 n = read(f, stop, n);
627 ldobj(int f, long c, char *pn)
631 uchar *bloc, *bsize, *stop;
632 Sym *h[NSYM], *s, *di;
640 memset(h, 0, sizeof(h));
650 if(r < 100 && r < c) { /* enough for largest prog */
651 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
657 o = bloc[0]; /* as */
658 if(o <= AXXX || o >= ALAST) {
659 diag("%s: line %ld: opcode out of range %d", pn, pc-ipc, o);
660 print(" probably not a .7 file\n");
664 stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
666 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
670 stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
672 fprint(2, "%s: name too long\n", pn);
676 v = bloc[1]; /* type */
677 o = bloc[2]; /* sym */
684 s = lookup((char*)bloc, r);
685 c -= &stop[1] - bloc;
689 print(" ANAME %s\n", s->name);
691 if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
694 if(s->type != SFILE) {
699 if(histfrogp < MAXHIST) {
700 histfrog[histfrogp] = s;
708 if(nhunk < sizeof(Prog))
711 nhunk -= sizeof(Prog);
712 hunk += sizeof(Prog);
715 p->reg = bloc[1] & 0x7f;
718 p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
720 r = zaddr(bloc+6, &p->from, h) + 6;
721 r += zaddr(bloc+r, &p->to, h);
725 if(p->reg < 0 || p->reg > NREG)
726 diag("register out of range %d", p->reg);
736 if(p->to.offset == -1) {
741 addhist(p->line, D_FILE); /* 'z' */
743 addhist(p->to.offset, D_PREG); /* 'Z' */
750 curtext->to.autom = curauto;
760 diag("GLOBL must have a name\n%P", p);
763 if(s->type == 0 || s->type == SXREF) {
767 if(s->type != SBSS) {
768 diag("redefinition: %s\n%P", s->name, p);
772 if(p->to.offset > s->value)
773 s->value = p->to.offset;
778 diag("DYNT without a sym\n%P", p);
783 if(di->type == SXREF) {
785 Bprint(&bso, "%P set to %d\n", p, dtype);
793 p->from.offset = di->value;
794 p->from.sym->type = SDATA;
796 diag("DYNT not in text: %P", p);
799 p->to.sym = curtext->from.sym;
800 p->to.type = D_CONST;
806 if(p->from.sym == S) {
807 diag("INIT without a sym\n%P", p);
811 diag("INIT without previous DYNT\n%P", p);
814 p->from.offset = di->value;
815 p->from.sym->type = SDATA;
821 if(p->from.sym == S) {
822 diag("DATA without a sym\n%P", p);
830 diag("unknown opcode\n%P", p);
838 curtext->to.autom = curauto;
843 autosize = (p->to.offset+3L) & ~3L;
846 p->to.offset = autosize;
850 diag("TEXT must have a name\n%P", p);
853 if(s->type != 0 && s->type != SXREF) {
858 diag("redefinition: %s\n%P", s->name, p);
879 if(p->from.type == D_FCONST) {
881 sprint(literal, "$%lux", ieeedtof(p->from.ieee));
882 s = lookup(literal, 0);
889 t->from.type = D_OREG;
891 t->from.name = D_EXTERN;
897 p->from.type = D_OREG;
899 p->from.name = D_EXTERN;
908 if(p->from.type == D_FCONST) {
910 sprint(literal, "$%lux.%lux",
911 p->from.ieee->l, p->from.ieee->h);
912 s = lookup(literal, 0);
919 t->from.type = D_OREG;
921 t->from.name = D_EXTERN;
927 p->from.type = D_OREG;
929 p->from.name = D_EXTERN;
938 if (p->from.type == D_FREG || p->to.type == D_FREG)
939 p->as = AMOVT; /* stupid compiler optimiser kkludge */
945 if (p->from.type == D_CONST)
946 if (p->from.offset == 0LL && p->from.name == D_NONE) {
947 p->from.type = D_REG;
948 p->from.reg = REGZERO;
957 if(p->to.type == D_BRANCH)
968 diag("truncated object file: %s", pn);
972 lookup(char *symb, int v)
980 for(p=symb; c0 = *p; p++)
986 for(s = hash[h]; s != S; s = s->link)
988 if(memcmp(s->name, symb, l) == 0)
991 while(nhunk < sizeof(Sym))
994 nhunk -= sizeof(Sym);
998 memmove(s->name, symb, l);
1013 while(nhunk < sizeof(Prog))
1016 nhunk -= sizeof(Prog);
1017 hunk += sizeof(Prog);
1030 if(thunk >= 5L*NHUNK) {
1032 if(thunk >= 25L*NHUNK)
1036 if(h == (char*)-1) {
1037 diag("out of memory");
1053 Bprint(&bso, "%5.2f profile 1\n", cputime());
1055 s = lookup("__mcount", 0);
1057 for(p = firstp->link; p != P; p = p->link) {
1058 if(p->as == ATEXT) {
1064 q->from.type = D_OREG;
1065 q->from.name = D_EXTERN;
1066 q->from.offset = n*4;
1070 q->to.type = D_CONST;
1079 p->from.type = D_OREG;
1080 p->from.name = D_EXTERN;
1082 p->from.offset = n*4 + 4;
1093 p->from.type = D_CONST;
1105 p->from.type = D_REG;
1106 p->from.reg = REGTMP;
1107 p->to.type = D_OREG;
1108 p->to.name = D_EXTERN;
1110 p->to.offset = n*4 + 4;
1122 q->from.type = D_OREG;
1123 q->from.name = D_EXTERN;
1126 q->to.type = D_CONST;
1137 Prog *p, *q, *q2, *ps2, *ps4;
1140 Bprint(&bso, "%5.2f profile 2\n", cputime());
1144 s2 = lookup("_tracein", 0);
1145 s4 = lookup("_traceout", 0);
1147 s2 = lookup("_profin", 0);
1148 s4 = lookup("_profout", 0);
1150 if(s2->type != STEXT || s4->type != STEXT) {
1152 diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1154 diag("_profin/_profout not defined");
1160 for(p = firstp; p != P; p = p->link) {
1161 if(p->as == ATEXT) {
1162 if(p->from.sym == s2) {
1166 if(p->from.sym == s4) {
1172 for(p = firstp; p != P; p = p->link) {
1173 if(p->as == ATEXT) {
1174 if(p->reg != NREG) {
1193 if(debug['e']){ /* embedded tracing */
1202 q2->to.type = D_BRANCH;
1203 q2->to.sym = p->to.sym;
1209 p->to.type = D_BRANCH;
1219 if(debug['e']){ /* embedded tracing */
1231 p->to.type = D_BRANCH;
1257 for(i=0; i<4; i++) {
1258 c = find1(0x04030201L, i+1);
1266 for (i = 0; i < 4; i++) {
1267 c = find1(0x04030201L, i+1);
1269 fnuxi8[i+4] = c + sizeof(long);
1273 Bprint(&bso, "inuxi = ");
1275 Bprint(&bso, "%d", inuxi1[i]);
1278 Bprint(&bso, "%d", inuxi2[i]);
1281 Bprint(&bso, "%d", inuxi4[i]);
1283 Bprint(&bso, "\nfnuxi = ");
1285 Bprint(&bso, "%d", fnuxi8[i]);
1291 find1(long l, int c)
1304 ieeedtof(Ieee *ieee)
1311 exp = (ieee->h>>20) & ((1L<<11)-1L);
1312 exp -= (1L<<10) - 2L;
1313 v = (ieee->h & 0xfffffL) << 3;
1314 v |= (ieee->l >> 29) & 0x7L;
1315 if((ieee->l >> 28) & 1) {
1318 v = (v & 0x7fffffL) >> 1;
1322 if(exp <= -126 || exp >= 130)
1323 diag("double fp to single fp overflow");
1324 v |= ((exp + 126) & 0xffL) << 23;
1325 v |= ieee->h & 0x80000000L;
1330 ieeedtod(Ieee *ieee)
1336 if(ieee->h & (1L<<31)) {
1337 e.h = ieee->h & ~(1L<<31);
1339 return -ieeedtod(&e);
1341 if(ieee->l == 0 && ieee->h == 0)
1343 fr = ieee->l & ((1L<<16)-1L);
1345 fr += (ieee->l>>16) & ((1L<<16)-1L);
1347 fr += (ieee->h & (1L<<20)-1L) | (1L<<20);
1349 exp = (ieee->h>>20) & ((1L<<11)-1L);
1350 exp -= (1L<<10) - 2L;
1351 return ldexp(fr, exp);