9 char *noname = "<none>";
10 char symname[] = SYMDEF;
12 char *thestring = "sparc";
15 * -H0 -T0x200000 -R0 is boot
16 * -H2 -T4128 -R4096 is plan9 format
17 * -H3 -T0xE0004000 -R4 is javastation boot format
21 main(int argc, char *argv[])
26 Binit(&bso, 1, OWRITE);
41 if(c >= 0 && c < sizeof(debug))
55 INITTEXT = atolwhex(a);
60 INITDAT = atolwhex(a);
65 INITRND = atolwhex(a);
70 HEADTYPE = atolwhex(a);
75 diag("usage: vl [-options] objects");
78 if(!debug['9'] && !debug['U'] && !debug['B'])
90 diag("unknown -H option");
102 case 1: /* garbage */
105 INITTEXT = 0x80020000L;
120 case 3: /* javastation boot */
123 INITTEXT = 0xE0004020L;
130 if(INITDAT != 0 && INITRND != 0)
131 print("warning: -D0x%lux is ignored because of -R0x%lux\n",
134 Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n",
135 HEADTYPE, INITTEXT, INITDAT, INITRND);
139 zprg.from.name = D_NONE;
140 zprg.from.type = D_NONE;
141 zprg.from.reg = NREG;
151 cout = create(outfile, 1, 0775);
153 diag("%s: cannot create", outfile);
159 cbc = sizeof(buf.cbuf);
166 INITENTRY = "_mainp";
168 lookup(INITENTRY, 0)->type = SXREF;
170 lookup(INITENTRY, 0)->type = SXREF;
176 firstp = firstp->link;
196 Bprint(&bso, "%5.2f cpu time\n", cputime());
197 Bprint(&bso, "%ld memory used\n", tothunk);
198 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
199 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
213 for(i=0; i<libraryp; i++) {
215 Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
219 for(h=0; h<nelem(hash); h++)
220 for(s = hash[h]; s != S; s = s->link)
241 long off, esym, cnt, l;
245 char name[100], pname[150];
247 char *e, *start, *stop;
249 if(file[0] == '-' && file[1] == 'l') {
251 snprint(name, sizeof name, "/%s/lib/lib%s.a", thestring, file+2);
253 snprint(name, sizeof name, "/usr/%clib/lib%s.a", thechar, file+2);
257 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
261 diag("cannot open file: %s", file);
264 l = read(f, magbuf, SARMAG);
265 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
266 /* load it as a regular file */
274 l = read(f, &arhdr, SAR_HDR);
276 diag("%s: short read on archive file symbol header", file);
279 if(strncmp(arhdr.name, symname, strlen(symname))) {
280 diag("%s: first entry not symbol header", file);
284 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
285 off = SARMAG + SAR_HDR;
288 * just bang the whole symbol file into memory
292 start = malloc(cnt + 10);
293 cnt = read(f, start, cnt);
304 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
307 for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
311 snprint(pname, sizeof pname, "%s(%s)", file, s->name);
313 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
316 l |= (e[2] & 0xff) << 8;
317 l |= (e[3] & 0xff) << 16;
318 l |= (e[4] & 0xff) << 24;
320 l = read(f, &arhdr, SAR_HDR);
323 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
325 l = atolwhex(arhdr.size);
327 if(s->type == SXREF) {
328 diag("%s: failed to load: %s", file, s->name);
338 diag("%s: bad or out of date archive", file);
344 zaddr(uchar *p, Adr *a, Sym *h[])
352 if(c < 0 || c > NSYM){
353 print("sym out of range: %d\n", c);
363 if(a->reg < 0 || a->reg > NREG) {
364 print("register out of range %d\n", a->reg);
366 return 0; /* force real diagnostic */
371 print("unknown type %d\n", a->type);
373 return 0; /* force real diagnostic */
386 a->offset = p[4] | (p[5]<<8) |
387 (p[6]<<16) | (p[7]<<24);
392 memmove(a->sval, p+4, NSNAME);
397 a->ieee.l = p[4] | (p[5]<<8) |
398 (p[6]<<16) | (p[7]<<24);
399 a->ieee.h = p[8] | (p[9]<<8) |
400 (p[10]<<16) | (p[11]<<24);
408 if(i != D_AUTO && i != D_PARAM)
412 for(u=curauto; u; u=u->link)
420 u = malloc(sizeof(Auto));
434 char name[1024], comp[256], *p;
440 if(histfrog[0]->name[1] == '/') {
444 if(histfrog[0]->name[1] == '.') {
445 snprint(name, sizeof name, ".");
449 snprint(name, sizeof name, "/%s/lib", thestring);
451 snprint(name, sizeof name, "/usr/%clib", thechar);
455 for(; i<histfrogp; i++) {
456 snprint(comp, sizeof comp, histfrog[i]->name+1);
458 p = strstr(comp, "$O");
461 memmove(p+1, p+2, strlen(p+2)+1);
465 p = strstr(comp, "$M");
468 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
469 diag("library component too long");
472 memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
473 memmove(p, thestring, strlen(thestring));
475 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
476 diag("library component too long");
482 for(i=0; i<libraryp; i++)
483 if(strcmp(name, library[i]) == 0)
485 if(libraryp == nelem(library)){
486 diag("too many autolibs; skipping %s", name);
490 p = malloc(strlen(name) + 1);
492 library[libraryp] = p;
493 p = malloc(strlen(obj) + 1);
495 libraryobj[libraryp] = p;
500 addhist(long line, int type)
506 u = malloc(sizeof(Auto));
507 s = malloc(sizeof(Sym));
508 s->name = malloc(2*(histfrogp+1) + 1);
517 for(i=0; i<histfrogp; i++) {
518 k = histfrog[i]->value;
543 * bad encoding of path components only allows
544 * MAXHIST components. if there is an overflow,
545 * first try to collapse xxx/..
547 for(i=1; i<histfrogp; i++)
548 if(strcmp(histfrog[i]->name+1, "..") == 0) {
549 memmove(histfrog+i-1, histfrog+i+1,
550 (histfrogp-i-1)*sizeof(histfrog[0]));
556 * next try to collapse .
558 for(i=0; i<histfrogp; i++)
559 if(strcmp(histfrog[i]->name+1, ".") == 0) {
560 memmove(histfrog+i, histfrog+i+1,
561 (histfrogp-i-1)*sizeof(histfrog[0]));
566 * last chance, just truncate from front
568 memmove(histfrog+0, histfrog+1,
569 (histfrogp-1)*sizeof(histfrog[0]));
572 histfrog[histfrogp-1] = s;
579 p->from.type = D_NONE;
584 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
589 memmove(buf, good, stop - good);
594 n = read(f, stop, n);
601 ldobj(int f, long c, char *pn)
604 Sym *h[NSYM], *s, *di;
607 uchar *bloc, *bsize, *stop;
614 memset(h, 0, sizeof(h));
624 if(r < 100 && r < c) { /* enough for largest prog */
625 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
631 o = bloc[0]; /* as */
632 if(o <= 0 || o >= ALAST) {
633 diag("%s: opcode out of range %d", pn, o);
634 print(" probably not a .k file\n");
637 if(o == ANAME || o == ASIGNAME) {
642 stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
644 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
648 stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
650 fprint(2, "%s: name too long\n", pn);
654 v = bloc[1]; /* type */
655 o = bloc[2]; /* sym */
662 s = lookup((char*)bloc, r);
663 c -= &stop[1] - bloc;
667 print(" ANAME %s\n", s->name);
669 if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
672 if(s->type != SFILE) {
677 if(histfrogp < MAXHIST) {
678 histfrog[histfrogp] = s;
686 if(nhunk < sizeof(Prog))
689 nhunk -= sizeof(Prog);
690 hunk += sizeof(Prog);
693 p->reg = bloc[1] & 0x7f;
696 p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
697 r = zaddr(bloc+6, &p->from, h) + 6;
698 r += zaddr(bloc+r, &p->to, h);
702 if(p->reg < 0 || p->reg > NREG)
703 diag("register out of range %d", p->reg);
713 if(p->to.offset == -1) {
718 addhist(p->line, D_FILE); /* 'z' */
720 addhist(p->to.offset, D_FILE1); /* 'Z' */
727 curtext->to.autom = curauto;
737 diag("GLOBL must have a name\n%P", p);
742 if(s->type == 0 || s->type == SXREF) {
746 if(s->type != SBSS) {
747 diag("redefinition: %s\n%P", s->name, p);
751 if(p->to.offset > s->value)
752 s->value = p->to.offset;
757 diag("DYNT without a sym\n%P", p);
762 if(di->type == SXREF) {
764 Bprint(&bso, "%P set to %d\n", p, dtype);
772 p->from.offset = di->value;
773 p->from.sym->type = SDATA;
775 diag("DYNT not in text: %P", p);
778 p->to.sym = curtext->from.sym;
779 p->to.type = D_CONST;
785 if(p->from.sym == S) {
786 diag("INIT without a sym\n%P", p);
790 diag("INIT without previous DYNT\n%P", p);
793 p->from.offset = di->value;
794 p->from.sym->type = SDATA;
805 diag("unknown opcode\n%P", p);
813 curtext->to.autom = curauto;
817 autosize = (p->to.offset+3L) & ~3L;
818 p->to.offset = autosize;
822 diag("TEXT must have a name\n%P", p);
825 if(s->type != 0 && s->type != SXREF) {
830 diag("redefinition: %s\n%P", s->name, p);
835 for(t = textp; t->cond != P; t = t->cond)
850 if(p->from.type == D_FCONST) {
852 snprint(literal, sizeof literal, "$%lux", ieeedtof(&p->from.ieee));
853 s = lookup(literal, 0);
860 t->from.type = D_OREG;
862 t->from.name = D_EXTERN;
868 p->from.type = D_OREG;
870 p->from.name = D_EXTERN;
878 if(p->from.type == D_FCONST) {
880 snprint(literal, sizeof literal, "$%lux.%lux",
881 p->from.ieee.l, p->from.ieee.h);
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;
909 if(p->to.type == D_BRANCH)
920 diag("truncated object file: %s", pn);
924 lookup(char *symb, int v)
932 for(p=symb; c = *p; p++)
938 for(s = hash[h]; s != S; s = s->link)
940 if(memcmp(s->name, symb, l) == 0)
943 while(nhunk < sizeof(Sym))
946 nhunk -= sizeof(Sym);
949 s->name = malloc(l + 1);
950 memmove(s->name, symb, l);
967 n = (sizeof(Prog) + 3) & ~3;
986 if(tothunk >= 5L*NHUNK) {
988 if(tothunk >= 25L*NHUNK)
992 if(h == (char *)-1) {
993 diag("out of memory");
1010 Bprint(&bso, "%5.2f profile 1\n", cputime());
1012 s = lookup("__mcount", 0);
1014 for(p = firstp->link; p != P; p = p->link) {
1015 if(p->as == ATEXT) {
1021 q->from.type = D_OREG;
1022 q->from.name = D_EXTERN;
1023 q->from.offset = n*4;
1027 q->to.type = D_CONST;
1036 p->from.type = D_OREG;
1037 p->from.name = D_EXTERN;
1039 p->from.offset = n*4 + 4;
1050 p->from.type = D_CONST;
1062 p->from.type = D_REG;
1063 p->from.reg = REGTMP;
1064 p->to.type = D_OREG;
1065 p->to.name = D_EXTERN;
1067 p->to.offset = n*4 + 4;
1079 q->from.type = D_OREG;
1080 q->from.name = D_EXTERN;
1083 q->to.type = D_CONST;
1094 Prog *p, *q, *q2, *ps2, *ps4;
1097 Bprint(&bso, "%5.2f profile 2\n", cputime());
1101 s2 = lookup("_tracein", 0);
1102 s4 = lookup("_traceout", 0);
1104 s2 = lookup("_profin", 0);
1105 s4 = lookup("_profout", 0);
1107 if(s2->type != STEXT || s4->type != STEXT) {
1109 diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1111 diag("_profin/_profout not defined");
1117 for(p = firstp; p != P; p = p->link) {
1118 if(p->as == ATEXT) {
1119 if(p->from.sym == s2) {
1123 if(p->from.sym == s4) {
1129 for(p = firstp; p != P; p = p->link) {
1130 if(p->as == ATEXT) {
1133 if(p->reg & NOPROF) { /* dont profile */
1152 if(debug['e']){ /* embedded tracing */
1161 q2->to.type = D_BRANCH;
1162 q2->to.sym = p->to.sym;
1168 p->to.type = D_BRANCH;
1174 if(p->as == ARETURN) {
1178 if(debug['e']){ /* embedded tracing */
1200 p->from = zprg.from;
1202 p->to.type = D_BRANCH;
1218 for(i=0; i<4; i++) {
1219 c = find1(0x01020304L, i+1);
1230 Bprint(&bso, "inuxi = ");
1232 Bprint(&bso, "%d", inuxi1[i]);
1235 Bprint(&bso, "%d", inuxi2[i]);
1238 Bprint(&bso, "%d", inuxi4[i]);
1239 Bprint(&bso, "\nfnuxi = ");
1241 Bprint(&bso, "%d", fnuxi8[i]);
1248 find1(long l, int c)
1261 ieeedtof(Ieee *ieeep)
1268 exp = (ieeep->h>>20) & ((1L<<11)-1L);
1269 exp -= (1L<<10) - 2L;
1270 v = (ieeep->h & 0xfffffL) << 3;
1271 v |= (ieeep->l >> 29) & 0x7L;
1272 if((ieeep->l >> 28) & 1) {
1275 v = (v & 0x7fffffL) >> 1;
1279 if(exp <= -126 || exp >= 130)
1280 diag("double fp to single fp overflow");
1281 v |= ((exp + 126) & 0xffL) << 23;
1282 v |= ieeep->h & 0x80000000L;
1287 ieeedtod(Ieee *ieeep)
1293 if(ieeep->h & (1L<<31)) {
1294 e.h = ieeep->h & ~(1L<<31);
1296 return -ieeedtod(&e);
1298 if(ieeep->l == 0 && ieeep->h == 0)
1300 fr = ieeep->l & ((1L<<16)-1L);
1302 fr += (ieeep->l>>16) & ((1L<<16)-1L);
1304 fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1306 exp = (ieeep->h>>20) & ((1L<<11)-1L);
1307 exp -= (1L<<10) - 2L;
1308 return ldexp(fr, exp);