9 #define OANAME 229 /* old ANAME */
12 char *noname = "<none>";
13 char symname[] = SYMDEF;
15 char *thestring = "power";
18 * -H0 -T0x200000 -R0 is boot
19 * -H1 -T0x100000 -R4 is Be boot
20 * -H2 -T0x100020 -R0x100000 is plan9 format (was -T4128 -R4096)
21 * -H3 -T0x02010000 -D0x00001000 is raw
22 * -H4 -T0x1000200 -D0x20000e00 -R4 is aix xcoff executable
23 * -H5 -T0x80010000 -t0x10000 ELF, phys = 10000, vaddr = 0x8001...
24 * appropriate for blue gene (bg/l anyway)
25 * -H6 -T0xfffe2100 -R4 ELF, phys = vaddr = 0xfffe2100
26 * appropriate for virtex 4 boot
34 char buf1[5], buf2[SARMAG];
39 n = Bread(b, buf1, 5);
40 if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<'))
41 v = 1; /* good enough for our purposes */
44 n = Bread(b, buf2, SARMAG);
45 v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0;
52 main(int argc, char *argv[])
57 Binit(&bso, 1, OWRITE);
72 if(c >= 0 && c < sizeof(debug))
86 INITTEXT = atolwhex(a);
91 INITDAT = atolwhex(a);
96 INITRND = atolwhex(a);
101 HEADTYPE = atolwhex(a);
103 case 'x': /* produce export table */
105 if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
106 readundefs(ARGF(), SEXPORT);
108 case 'u': /* produce dynamically loadable module */
110 if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
111 readundefs(ARGF(), SIMPORT);
116 diag("usage: ql [-options] objects");
119 if(!debug['9'] && !debug['U'] && !debug['B'])
121 r0iszero = debug['0'] == 0;
132 diag("unknown -H option");
138 INITTEXT = 0x200000L;
144 case 1: /* Be boot format (PEF) */
173 case 4: /* aix unix xcoff executable */
174 HEADR = 20L+72L+3*40L;
176 INITTEXT = 0x1000000L+HEADR;
178 INITDAT = 0x20000000;
182 case 5: /* elf executable */
183 case 6: /* elf for virtex 4 */
184 HEADR = rnd(52L+3*32L, 16);
186 INITTEXT = 0x00400000L+HEADR;
188 INITDAT = 0x10000000;
193 if(INITDAT != 0 && INITRND != 0)
194 print("warning: -D0x%lux is ignored because of -R0x%lux\n",
197 Bprint(&bso, "HEADER = -H0x%x -T0x%lux -D0x%lux -R0x%lux\n",
198 HEADTYPE, INITTEXT, INITDAT, INITRND);
202 zprg.from.name = D_NONE;
203 zprg.from.type = D_NONE;
204 zprg.from.reg = NREG;
205 zprg.from3 = zprg.from;
215 cout = create(outfile, 1, 0775);
217 diag("%s: cannot create", outfile);
223 cbc = sizeof(buf.cbuf);
230 INITENTRY = "_mainp";
232 lookup(INITENTRY, 0)->type = SXREF;
234 lookup(INITENTRY, 0)->type = SXREF;
240 firstp = firstp->link;
244 EXPTAB = "_exporttab";
252 INITTEXT = INITDAT = 0;
275 Bprint(&bso, "%5.2f cpu time\n", cputime());
276 Bprint(&bso, "%ld memory used\n", tothunk);
277 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
278 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
292 for(i=0; i<libraryp; i++) {
294 Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
298 for(h=0; h<nelem(hash); h++)
299 for(s = hash[h]; s != S; s = s->link)
320 long off, esym, cnt, l;
324 char name[100], pname[150];
326 char *e, *start, *stop;
328 if(file[0] == '-' && file[1] == 'l') {
330 snprint(name, sizeof name, "/%s/lib/lib%s.a", thestring, file+2);
332 snprint(name, sizeof name, "/usr/%clib/lib%s.a", thechar, file+2);
336 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
340 diag("cannot open file: %s", file);
343 l = read(f, magbuf, SARMAG);
344 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
345 /* load it as a regular file */
353 l = read(f, &arhdr, SAR_HDR);
355 diag("%s: short read on archive file symbol header", file);
358 if(strncmp(arhdr.name, symname, strlen(symname))) {
359 diag("%s: first entry not symbol header", file);
363 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
364 off = SARMAG + SAR_HDR;
367 * just bang the whole symbol file into memory
371 start = malloc(cnt + 10);
372 cnt = read(f, start, cnt);
383 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
386 for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
390 snprint(pname, sizeof pname, "%s(%s)", file, s->name);
392 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
395 l |= (e[2] & 0xff) << 8;
396 l |= (e[3] & 0xff) << 16;
397 l |= (e[4] & 0xff) << 24;
399 l = read(f, &arhdr, SAR_HDR);
402 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
404 l = atolwhex(arhdr.size);
406 if(s->type == SXREF) {
407 diag("%s: failed to load: %s", file, s->name);
417 diag("%s: bad or out of date archive", file);
423 zaddr(uchar *p, Adr *a, Sym *h[])
431 if(c < 0 || c > NSYM){
432 print("sym out of range: %d\n", c);
443 print("register out of range %d\n", a->reg);
445 return 0; /* force real diagnostic */
450 print("unknown type %d\n", a->type);
452 return 0; /* force real diagnostic */
469 a->offset = p[4] | (p[5]<<8) |
470 (p[6]<<16) | (p[7]<<24);
475 memmove(a->sval, p+4, NSNAME);
480 a->ieee.l = p[4] | (p[5]<<8) |
481 (p[6]<<16) | (p[7]<<24);
482 a->ieee.h = p[8] | (p[9]<<8) |
483 (p[10]<<16) | (p[11]<<24);
491 if(i != D_AUTO && i != D_PARAM)
495 for(u=curauto; u; u=u->link)
503 u = malloc(sizeof(Auto));
517 char name[1024], comp[256], *p;
523 if(histfrog[0]->name[1] == '/') {
527 if(histfrog[0]->name[1] == '.') {
528 snprint(name, sizeof name, ".");
532 snprint(name, sizeof name, "/%s/lib", thestring);
534 snprint(name, sizeof name, "/usr/%clib", thechar);
538 for(; i<histfrogp; i++) {
539 snprint(comp, sizeof comp, histfrog[i]->name+1);
541 p = strstr(comp, "$O");
544 memmove(p+1, p+2, strlen(p+2)+1);
548 p = strstr(comp, "$M");
551 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
552 diag("library component too long");
555 memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
556 memmove(p, thestring, strlen(thestring));
558 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
559 diag("library component too long");
565 for(i=0; i<libraryp; i++)
566 if(strcmp(name, library[i]) == 0)
568 if(libraryp == nelem(library)){
569 diag("too many autolibs; skipping %s", name);
573 p = malloc(strlen(name) + 1);
575 library[libraryp] = p;
576 p = malloc(strlen(obj) + 1);
578 libraryobj[libraryp] = p;
583 addhist(long line, int type)
589 u = malloc(sizeof(Auto));
590 s = malloc(sizeof(Sym));
591 s->name = malloc(2*(histfrogp+1) + 1);
600 for(i=0; i<histfrogp; i++) {
601 k = histfrog[i]->value;
626 * bad encoding of path components only allows
627 * MAXHIST components. if there is an overflow,
628 * first try to collapse xxx/..
630 for(i=1; i<histfrogp; i++)
631 if(strcmp(histfrog[i]->name+1, "..") == 0) {
632 memmove(histfrog+i-1, histfrog+i+1,
633 (histfrogp-i-1)*sizeof(histfrog[0]));
639 * next try to collapse .
641 for(i=0; i<histfrogp; i++)
642 if(strcmp(histfrog[i]->name+1, ".") == 0) {
643 memmove(histfrog+i, histfrog+i+1,
644 (histfrogp-i-1)*sizeof(histfrog[0]));
649 * last chance, just truncate from front
651 memmove(histfrog+0, histfrog+1,
652 (histfrogp-1)*sizeof(histfrog[0]));
655 histfrog[histfrogp-1] = s;
662 p->from.type = D_NONE;
667 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
672 memmove(buf, good, stop - good);
677 n = read(f, stop, n);
684 ldobj(int f, long c, char *pn)
687 Sym *h[NSYM], *s, *di;
690 uchar *bloc, *bsize, *stop;
697 nfilen = malloc((files+16)*sizeof(char*));
698 memmove(nfilen, filen, files*sizeof(char*));
702 filen[files++] = strdup(pn);
709 memset(h, 0, sizeof(h));
719 if(r < 100 && r < c) { /* enough for largest prog */
720 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
726 o = bloc[0] | (bloc[1] << 8); /* as */
727 if(bloc[0] == OANAME && o != OANAME) {
728 diag("%s: probably old .q file\n", pn);
731 if(o <= 0 || o >= ALAST) {
732 diag("%s: opcode out of range %d", pn, o);
733 print(" probably not a .%c file\n", thechar);
736 if(o == ANAME || o == ASIGNAME) {
739 sig = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
743 stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
745 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
749 stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
751 fprint(2, "%s: name too long\n", pn);
755 v = bloc[2]; /* type */
756 o = bloc[3]; /* sym */
763 s = lookup((char*)bloc, r);
764 c -= &stop[1] - bloc;
767 if(s->sig != 0 && s->sig != sig)
768 diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name);
775 print(" ANAME %s\n", s->name);
777 if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
780 if(s->type != SFILE) {
785 if(histfrogp < MAXHIST) {
786 histfrog[histfrogp] = s;
794 if(nhunk < sizeof(Prog))
797 nhunk -= sizeof(Prog);
798 hunk += sizeof(Prog);
801 p->reg = bloc[2] & 0x3f;
804 p->line = bloc[3] | (bloc[4]<<8) | (bloc[5]<<16) | (bloc[6]<<24);
805 r = zaddr(bloc+7, &p->from, h) + 7;
807 r += zaddr(bloc+r, &p->from3, h);
809 p->from3 = zprg.from3;
810 r += zaddr(bloc+r, &p->to, h);
814 if(p->reg < 0 || p->reg > NREG)
815 diag("register out of range %d", p->reg);
825 if(p->to.offset == -1) {
830 addhist(p->line, D_FILE); /* 'z' */
832 addhist(p->to.offset, D_FILE1); /* 'Z' */
839 curtext->to.autom = curauto;
849 diag("GLOBL must have a name\n%P", p);
854 if(s->type == 0 || s->type == SXREF) {
858 if(s->type != SBSS) {
859 diag("redefinition: %s\n%P", s->name, p);
863 if(p->to.offset > s->value)
864 s->value = p->to.offset;
869 diag("DYNT without a sym\n%P", p);
874 if(di->type == SXREF) {
876 Bprint(&bso, "%P set to %d\n", p, dtype);
884 p->from.offset = di->value;
885 p->from.sym->type = SDATA;
887 diag("DYNT not in text: %P", p);
890 p->to.sym = curtext->from.sym;
891 p->to.type = D_CONST;
897 if(p->from.sym == S) {
898 diag("INIT without a sym\n%P", p);
902 diag("INIT without previous DYNT\n%P", p);
905 p->from.offset = di->value;
906 p->from.sym->type = SDATA;
917 diag("unknown opcode\n%P", p);
925 curtext->to.autom = curauto;
929 autosize = (p->to.offset+3L) & ~3L;
930 p->to.offset = autosize;
934 diag("TEXT must have a name\n%P", p);
937 if(s->type != 0 && s->type != SXREF) {
942 diag("redefinition: %s\n%P", s->name, p);
947 for(t = textp; t->cond != P; t = t->cond)
962 if(p->from.type == D_FCONST) {
964 snprint(literal, sizeof literal, "$%lux", ieeedtof(&p->from.ieee));
965 s = lookup(literal, 0);
972 t->from.type = D_OREG;
974 t->from.name = D_EXTERN;
980 p->from.type = D_OREG;
982 p->from.name = D_EXTERN;
990 if(p->from.type == D_FCONST) {
992 snprint(literal, sizeof literal, "$%lux.%lux",
993 p->from.ieee.l, p->from.ieee.h);
994 s = lookup(literal, 0);
1001 t->from.type = D_OREG;
1003 t->from.name = D_EXTERN;
1009 p->from.type = D_OREG;
1011 p->from.name = D_EXTERN;
1017 if(p->from.type == D_CONST) {
1018 p->from.offset = -p->from.offset;
1024 if(p->from.type == D_CONST) {
1025 p->from.offset = -p->from.offset;
1031 if(p->from.type == D_CONST) {
1032 p->from.offset = -p->from.offset;
1042 if(p->to.type == D_BRANCH)
1043 p->to.offset += ipc;
1053 diag("truncated object file: %s", pn);
1057 lookup(char *symb, int v)
1065 for(p=symb; c = *p; p++)
1071 for(s = hash[h]; s != S; s = s->link)
1073 if(memcmp(s->name, symb, l) == 0)
1076 while(nhunk < sizeof(Sym))
1079 nhunk -= sizeof(Sym);
1080 hunk += sizeof(Sym);
1082 s->name = malloc(l + 1);
1083 memmove(s->name, symb, l);
1101 n = (sizeof(Prog) + 3) & ~3;
1120 if(tothunk >= 5L*NHUNK) {
1122 if(tothunk >= 25L*NHUNK)
1126 if(h == (char *)-1) {
1127 diag("out of memory");
1144 Bprint(&bso, "%5.2f profile 1\n", cputime());
1146 s = lookup("__mcount", 0);
1148 for(p = firstp->link; p != P; p = p->link) {
1149 if(p->as == ATEXT) {
1155 q->from.type = D_OREG;
1156 q->from.name = D_EXTERN;
1157 q->from.offset = n*4;
1161 q->to.type = D_CONST;
1170 p->from.type = D_OREG;
1171 p->from.name = D_EXTERN;
1173 p->from.offset = n*4 + 4;
1184 p->from.type = D_CONST;
1196 p->from.type = D_REG;
1197 p->from.reg = REGTMP;
1198 p->to.type = D_OREG;
1199 p->to.name = D_EXTERN;
1201 p->to.offset = n*4 + 4;
1213 q->from.type = D_OREG;
1214 q->from.name = D_EXTERN;
1217 q->to.type = D_CONST;
1228 Prog *p, *q, *q2, *ps2, *ps4;
1231 Bprint(&bso, "%5.2f profile 2\n", cputime());
1235 s2 = lookup("_tracein", 0);
1236 s4 = lookup("_traceout", 0);
1238 s2 = lookup("_profin", 0);
1239 s4 = lookup("_profout", 0);
1241 if(s2->type != STEXT || s4->type != STEXT) {
1243 diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1245 diag("_profin/_profout not defined");
1251 for(p = firstp; p != P; p = p->link) {
1252 if(p->as == ATEXT) {
1253 if(p->from.sym == s2) {
1257 if(p->from.sym == s4) {
1263 for(p = firstp; p != P; p = p->link) {
1264 if(p->as == ATEXT) {
1267 if(p->reg & NOPROF) { /* dont profile */
1286 if(debug['e']){ /* embedded tracing */
1295 q2->to.type = D_BRANCH;
1296 q2->to.sym = p->to.sym;
1302 p->to.type = D_BRANCH;
1308 if(p->as == ARETURN) {
1312 if(debug['e']){ /* embedded tracing */
1334 p->from = zprg.from;
1336 p->to.type = D_BRANCH;
1352 for(i=0; i<4; i++) {
1353 c = find1(0x01020304L, i+1);
1364 Bprint(&bso, "inuxi = ");
1366 Bprint(&bso, "%d", inuxi1[i]);
1369 Bprint(&bso, "%d", inuxi2[i]);
1372 Bprint(&bso, "%d", inuxi4[i]);
1373 Bprint(&bso, "\nfnuxi = ");
1375 Bprint(&bso, "%d", fnuxi8[i]);
1382 find1(long l, int c)
1395 ieeedtof(Ieee *ieeep)
1402 exp = (ieeep->h>>20) & ((1L<<11)-1L);
1403 exp -= (1L<<10) - 2L;
1404 v = (ieeep->h & 0xfffffL) << 3;
1405 v |= (ieeep->l >> 29) & 0x7L;
1406 if((ieeep->l >> 28) & 1) {
1409 v = (v & 0x7fffffL) >> 1;
1413 if(exp <= -126 || exp >= 130)
1414 diag("double fp to single fp overflow");
1415 v |= ((exp + 126) & 0xffL) << 23;
1416 v |= ieeep->h & 0x80000000L;
1421 ieeedtod(Ieee *ieeep)
1427 if(ieeep->h & (1L<<31)) {
1428 e.h = ieeep->h & ~(1L<<31);
1430 return -ieeedtod(&e);
1432 if(ieeep->l == 0 && ieeep->h == 0)
1434 fr = ieeep->l & ((1L<<16)-1L);
1436 fr += (ieeep->l>>16) & ((1L<<16)-1L);
1438 fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1440 exp = (ieeep->h>>20) & ((1L<<11)-1L);
1441 exp -= (1L<<10) - 2L;
1442 return ldexp(fr, exp);
1452 diag("value != 0 on SXREF");
1454 diag("import index %d out of range", n);
1455 s->value = n<<Roffset;
1470 readundefs(char *f, int t)
1475 char *l, buf[256], *fields[64];
1479 b = Bopen(f, OREAD);
1481 diag("could not open %s: %r", f);
1484 while((l = Brdline(b, '\n')) != nil){
1486 if(n >= sizeof(buf)){
1487 diag("%s: line too long", f);
1492 n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
1493 if(n == nelem(fields)){
1494 diag("%s: bad format", f);
1497 for(i = 0; i < n; i++){
1498 s = lookup(fields[i], 0);