9 char *noname = "<none>";
10 char symname[] = SYMDEF;
12 char *thestring = "mips";
15 * -H0 -T0x40004C -D0x10000000 is abbrev unix
16 * -H1 -T0x80020000 -R4 is bootp() format for 3k
17 * -H2 -T0x4020 -R0x4000 is plan9 format
18 * -H3 -T0x80020000 -R8 is bootp() format for 4k
19 * -H4 -T0x400000 -R4 is sgi unix coff executable
20 * -H5 -T0x4000A0 -R4 is sgi unix elf executable
27 main(int argc, char *argv[])
32 Binit(&bso, 1, OWRITE);
47 if(c >= 0 && c < sizeof(debug))
58 case 'L': /* for little-endian mips */
66 INITTEXT = atolwhex(a);
71 INITDAT = atolwhex(a);
76 INITRND = atolwhex(a);
81 HEADTYPE = atolwhex(a);
82 /* do something about setting INITTEXT */
89 diag("usage: %cl [-options] objects", thechar);
92 if(!debug['9'] && !debug['U'] && !debug['B'])
104 diag("unknown -H option");
107 case 0: /* unix simple */
110 INITTEXT = 0x40004CL;
112 INITDAT = 0x10000000L;
116 case 1: /* boot for 3k */
119 INITTEXT = 0x80020000L;
132 INITTEXT = INITRND+HEADR;
134 case 3: /* boot for 4k */
135 HEADR = 20L+56L+3*40L;
137 INITTEXT = 0x80020000L;
143 case 4: /* sgi unix coff executable */
144 HEADR = 20L+56L+3*40L;
146 INITTEXT = 0x00400000L+HEADR;
148 INITDAT = 0x10000000;
152 case 5: /* sgi unix elf executable */
153 HEADR = rnd(52L+3*32L, 16);
155 INITTEXT = 0x00400000L+HEADR;
157 INITDAT = 0x10000000;
161 case 6: /* headerless */
164 INITTEXT = 0x80000000L+HEADR;
171 if(INITDAT != 0 && INITRND != 0)
172 print("warning: -D0x%lux is ignored because of -R0x%lux\n",
175 Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n",
176 HEADTYPE, INITTEXT, INITDAT, INITRND);
180 zprg.from.name = D_NONE;
181 zprg.from.type = D_NONE;
182 zprg.from.reg = NREG;
191 static char name[20];
193 snprint(name, sizeof name, "%c.out", thechar);
196 cout = create(outfile, 1, 0775);
198 diag("%s: cannot create", outfile);
205 cbc = sizeof(buf.cbuf);
212 INITENTRY = "_mainp";
214 lookup(INITENTRY, 0)->type = SXREF;
216 lookup(INITENTRY, 0)->type = SXREF;
222 firstp = firstp->link;
242 Bprint(&bso, "%5.2f cpu time\n", cputime());
243 Bprint(&bso, "%ld memory used\n", thunk);
244 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
245 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
260 for(i=0; i<libraryp; i++) {
262 Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
266 for(h=0; h<nelem(hash); h++)
267 for(s = hash[h]; s != S; s = s->link)
287 long off, esym, cnt, l;
291 char name[100], pname[150];
293 char *e, *start, *stop;
295 if(file[0] == '-' && file[1] == 'l') {
297 snprint(name, sizeof name, "/%s/lib/lib%s.a", thestring, file+2);
299 snprint(name, sizeof name, "/usr/%clib/lib%s.a", thechar, file+2);
303 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
307 diag("cannot open file: %s", file);
310 l = read(f, magbuf, SARMAG);
311 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
312 /* load it as a regular file */
321 Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file);
322 l = read(f, &arhdr, SAR_HDR);
324 diag("%s: short read on archive file symbol header", file);
327 if(strncmp(arhdr.name, symname, strlen(symname))) {
328 diag("%s: first entry not symbol header", file);
332 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
333 off = SARMAG + SAR_HDR;
336 * just bang the whole symbol file into memory
340 start = malloc(cnt + 10);
341 cnt = read(f, start, cnt);
352 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
355 for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
359 snprint(pname, sizeof pname, "%s(%s)", file, s->name);
361 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
364 l |= (e[2] & 0xff) << 8;
365 l |= (e[3] & 0xff) << 16;
366 l |= (e[4] & 0xff) << 24;
368 l = read(f, &arhdr, SAR_HDR);
371 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
373 l = atolwhex(arhdr.size);
375 if(s->type == SXREF) {
376 diag("%s: failed to load: %s", file, s->name);
386 diag("%s: bad or out of date archive", file);
392 zaddr(uchar *p, Adr *a, Sym *h[])
400 if(c < 0 || c > NSYM){
401 print("sym out of range: %d\n", c);
411 if(a->reg < 0 || a->reg > NREG) {
412 print("register out of range %d\n", a->reg);
414 return 0; /* force real diagnostic */
419 print("unknown type %d\n", a->type);
421 return 0; /* force real diagnostic */
436 a->offset = p[4] | (p[5]<<8) |
437 (p[6]<<16) | (p[7]<<24);
442 while(nhunk < NSNAME)
444 a->sval = (char*)hunk;
448 memmove(a->sval, p+4, NSNAME);
453 while(nhunk < sizeof(Ieee))
455 a->ieee = (Ieee*)hunk;
459 a->ieee->l = p[4] | (p[5]<<8) |
460 (p[6]<<16) | (p[7]<<24);
461 a->ieee->h = p[8] | (p[9]<<8) |
462 (p[10]<<16) | (p[11]<<24);
470 if(i != D_AUTO && i != D_PARAM)
474 for(u=curauto; u; u=u->link)
482 while(nhunk < sizeof(Auto))
485 nhunk -= sizeof(Auto);
486 hunk += sizeof(Auto);
499 char name[1024], comp[256], *p;
505 if(histfrog[0]->name[1] == '/') {
509 if(histfrog[0]->name[1] == '.') {
510 snprint(name, sizeof name, ".");
514 snprint(name, sizeof name, "/%s/lib", thestring);
516 snprint(name, sizeof name, "/usr/%clib", thechar);
520 for(; i<histfrogp; i++) {
521 snprint(comp, sizeof comp, histfrog[i]->name+1);
523 p = strstr(comp, "$O");
526 memmove(p+1, p+2, strlen(p+2)+1);
530 p = strstr(comp, "$M");
533 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
534 diag("library component too long");
537 memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
538 memmove(p, thestring, strlen(thestring));
540 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
541 diag("library component too long");
547 for(i=0; i<libraryp; i++)
548 if(strcmp(name, library[i]) == 0)
550 if(libraryp == nelem(library)){
551 diag("too many autolibs; skipping %s", name);
555 p = malloc(strlen(name) + 1);
557 library[libraryp] = p;
558 p = malloc(strlen(obj) + 1);
560 libraryobj[libraryp] = p;
565 addhist(long line, int type)
571 u = malloc(sizeof(Auto));
572 s = malloc(sizeof(Sym));
573 s->name = malloc(2*(histfrogp+1) + 1);
582 for(i=0; i<histfrogp; i++) {
583 k = histfrog[i]->value;
608 * bad encoding of path components only allows
609 * MAXHIST components. if there is an overflow,
610 * first try to collapse xxx/..
612 for(i=1; i<histfrogp; i++)
613 if(strcmp(histfrog[i]->name+1, "..") == 0) {
614 memmove(histfrog+i-1, histfrog+i+1,
615 (histfrogp-i-1)*sizeof(histfrog[0]));
621 * next try to collapse .
623 for(i=0; i<histfrogp; i++)
624 if(strcmp(histfrog[i]->name+1, ".") == 0) {
625 memmove(histfrog+i, histfrog+i+1,
626 (histfrogp-i-1)*sizeof(histfrog[0]));
631 * last chance, just truncate from front
633 memmove(histfrog+0, histfrog+1,
634 (histfrogp-1)*sizeof(histfrog[0]));
637 histfrog[histfrogp-1] = s;
644 p->from.type = D_NONE;
649 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
654 memmove(buf, good, stop - good);
659 n = read(f, stop, n);
666 ldobj(int f, long c, char *pn)
670 uchar *bloc, *bsize, *stop;
671 Sym *h[NSYM], *s, *di;
679 memset(h, 0, sizeof(h));
689 if(r < 100 && r < c) { /* enough for largest prog */
690 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
696 o = bloc[0]; /* as */
697 if(o <= AXXX || o >= ALAST) {
698 diag("%s: line %ld: opcode out of range %d", pn, pc-ipc, o);
699 print(" probably not a .%c file\n", thechar);
702 if(o == ANAME || o == ASIGNAME) {
707 stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
709 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
713 stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
715 fprint(2, "%s: name too long\n", pn);
719 v = bloc[1]; /* type */
720 o = bloc[2]; /* sym */
727 s = lookup((char*)bloc, r);
728 c -= &stop[1] - bloc;
732 print(" ANAME %s\n", s->name);
734 if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
737 if(s->type != SFILE) {
742 if(histfrogp < MAXHIST) {
743 histfrog[histfrogp] = s;
751 if(nhunk < sizeof(Prog))
754 nhunk -= sizeof(Prog);
755 hunk += sizeof(Prog);
758 p->reg = bloc[1] & 0x7f;
761 p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
763 r = zaddr(bloc+6, &p->from, h) + 6;
764 r += zaddr(bloc+r, &p->to, h);
768 if(p->reg < 0 || p->reg > NREG)
769 diag("register out of range %d", p->reg);
779 if(p->to.offset == -1) {
784 addhist(p->line, D_FILE); /* 'z' */
786 addhist(p->to.offset, D_FILE1); /* 'Z' */
793 curtext->to.autom = curauto;
803 diag("GLOBL must have a name\n%P", p);
808 if(s->type == 0 || s->type == SXREF) {
812 if(s->type != SBSS) {
813 diag("redefinition: %s\n%P", s->name, p);
817 if(p->to.offset > s->value)
818 s->value = p->to.offset;
823 diag("DYNT without a sym\n%P", p);
828 if(di->type == SXREF) {
830 Bprint(&bso, "%P set to %d\n", p, dtype);
838 p->from.offset = di->value;
839 p->from.sym->type = SDATA;
841 diag("DYNT not in text: %P", p);
844 p->to.sym = curtext->from.sym;
845 p->to.type = D_CONST;
851 if(p->from.sym == S) {
852 diag("INIT without a sym\n%P", p);
856 diag("INIT without previous DYNT\n%P", p);
859 p->from.offset = di->value;
860 p->from.sym->type = SDATA;
866 if(p->from.sym == S) {
867 diag("DATA without a sym\n%P", p);
875 diag("unknown opcode\n%P", p);
883 curtext->to.autom = curauto;
888 autosize = (p->to.offset+3L) & ~3L;
889 p->to.offset = autosize;
893 diag("TEXT must have a name\n%P", p);
896 if(s->type != 0 && s->type != SXREF) {
901 diag("redefinition: %s\n%P", s->name, p);
920 if(p->from.type == D_CONST)
921 if(p->from.name == D_NONE) {
922 p->from.offset = -p->from.offset;
934 if(p->from.type == D_FCONST) {
936 snprint(literal, sizeof literal, "$%lux", ieeedtof(p->from.ieee));
937 s = lookup(literal, 0);
944 t->from.type = D_OREG;
946 t->from.name = D_EXTERN;
952 p->from.type = D_OREG;
954 p->from.name = D_EXTERN;
963 if(p->from.type == D_FCONST) {
965 snprint(literal, sizeof literal, "$%lux.%lux",
966 p->from.ieee->l, p->from.ieee->h);
967 s = lookup(literal, 0);
974 t->from.type = D_OREG;
976 t->from.name = D_EXTERN;
982 p->from.type = D_OREG;
984 p->from.name = D_EXTERN;
994 if(p->to.type == D_BRANCH)
1005 diag("truncated object file: %s", pn);
1009 lookup(char *symb, int v)
1017 for(p=symb; c = *p; p++)
1023 for(s = hash[h]; s != S; s = s->link)
1025 if(memcmp(s->name, symb, l) == 0)
1028 while(nhunk < sizeof(Sym))
1031 nhunk -= sizeof(Sym);
1032 hunk += sizeof(Sym);
1034 s->name = malloc(l);
1035 memmove(s->name, symb, l);
1051 while(nhunk < sizeof(Prog))
1054 nhunk -= sizeof(Prog);
1055 hunk += sizeof(Prog);
1068 if(thunk >= 5L*NHUNK) {
1070 if(thunk >= 25L*NHUNK)
1074 if(h == (char*)-1) {
1075 diag("out of memory");
1091 Bprint(&bso, "%5.2f profile 1\n", cputime());
1093 s = lookup("__mcount", 0);
1095 for(p = firstp->link; p != P; p = p->link) {
1096 if(p->as == ATEXT) {
1102 q->from.type = D_OREG;
1103 q->from.name = D_EXTERN;
1104 q->from.offset = n*4;
1108 q->to.type = D_CONST;
1117 p->from.type = D_OREG;
1118 p->from.name = D_EXTERN;
1120 p->from.offset = n*4 + 4;
1131 p->from.type = D_CONST;
1143 p->from.type = D_REG;
1144 p->from.reg = REGTMP;
1145 p->to.type = D_OREG;
1146 p->to.name = D_EXTERN;
1148 p->to.offset = n*4 + 4;
1160 q->from.type = D_OREG;
1161 q->from.name = D_EXTERN;
1164 q->to.type = D_CONST;
1175 Prog *p, *q, *q2, *ps2, *ps4;
1178 Bprint(&bso, "%5.2f profile 2\n", cputime());
1182 s2 = lookup("_tracein", 0);
1183 s4 = lookup("_traceout", 0);
1185 s2 = lookup("_profin", 0);
1186 s4 = lookup("_profout", 0);
1188 if(s2->type != STEXT || s4->type != STEXT) {
1190 diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1192 diag("_profin/_profout not defined");
1198 for(p = firstp; p != P; p = p->link) {
1199 if(p->as == ATEXT) {
1200 if(p->from.sym == s2) {
1204 if(p->from.sym == s4) {
1210 for(p = firstp; p != P; p = p->link) {
1211 if(p->as == ATEXT) {
1212 if(p->reg & NOPROF) {
1231 if(debug['e']){ /* embedded tracing */
1240 q2->to.type = D_BRANCH;
1241 q2->to.sym = p->to.sym;
1247 p->to.type = D_BRANCH;
1257 if(debug['e']){ /* embedded tracing */
1279 p->from = zprg.from;
1281 p->to.type = D_BRANCH;
1298 if (!little) { /* normal big-endian case */
1299 c = find1(0x01020304L, i+1);
1307 } else { /* oddball little-endian case */
1308 c = find1(0x04030201L, i+1);
1319 Bprint(&bso, "inuxi = ");
1321 Bprint(&bso, "%d", inuxi1[i]);
1324 Bprint(&bso, "%d", inuxi2[i]);
1327 Bprint(&bso, "%d", inuxi4[i]);
1328 Bprint(&bso, "\nfnuxi = ");
1330 Bprint(&bso, "%d", fnuxi8[i]);
1336 find1(long l, int c)
1349 ieeedtof(Ieee *ieeep)
1356 exp = (ieeep->h>>20) & ((1L<<11)-1L);
1357 exp -= (1L<<10) - 2L;
1358 v = (ieeep->h & 0xfffffL) << 3;
1359 v |= (ieeep->l >> 29) & 0x7L;
1360 if((ieeep->l >> 28) & 1) {
1363 v = (v & 0x7fffffL) >> 1;
1367 if(exp <= -126 || exp >= 130)
1368 diag("double fp to single fp overflow");
1369 v |= ((exp + 126) & 0xffL) << 23;
1370 v |= ieeep->h & 0x80000000L;
1375 ieeedtod(Ieee *ieeep)
1381 if(ieeep->h & (1L<<31)) {
1382 e.h = ieeep->h & ~(1L<<31);
1384 return -ieeedtod(&e);
1386 if(ieeep->l == 0 && ieeep->h == 0)
1388 fr = ieeep->l & ((1L<<16)-1L);
1390 fr += (ieeep->l>>16) & ((1L<<16)-1L);
1392 fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1394 exp = (ieeep->h>>20) & ((1L<<11)-1L);
1395 exp -= (1L<<10) - 2L;
1396 return ldexp(fr, exp);