diff options
Diffstat (limited to 'src/cmd/8l/obj.c')
-rw-r--r-- | src/cmd/8l/obj.c | 505 |
1 files changed, 104 insertions, 401 deletions
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index 1a3ecec1d..18b2112fe 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -28,11 +28,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Reading object files. + #define EXTERN #include "l.h" #include "../ld/lib.h" #include "../ld/elf.h" #include "../ld/macho.h" +#include "../ld/dwarf.h" #include "../ld/pe.h" #include <ar.h> @@ -52,32 +55,12 @@ char *thestring = "386"; * -H4 -Tx -Rx is fake MS-DOS .EXE * -H6 -Tx -Rx is Apple Mach-O * -H7 -Tx -Rx is Linux ELF32 - * -H8 -Tx -Rx is Google Native Client + * -H8 -Tx -Rx was Google Native Client * -H9 -Tx -Rx is FreeBSD ELF32 + * -H10 -Tx -Rx is MS Windows PE + * -H11 -Tx -Rx is tiny (os image) */ -static int -isobjfile(char *f) -{ - int n, v; - Biobuf *b; - char buf1[5], buf2[SARMAG]; - - b = Bopen(f, OREAD); - if(b == nil) - return 0; - n = Bread(b, buf1, 5); - if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<')) - v = 1; /* good enough for our purposes */ - else{ - Bseek(b, 0, 0); - n = Bread(b, buf2, SARMAG); - v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0; - } - Bterm(b); - return v; -} - void usage(void) { @@ -88,7 +71,7 @@ usage(void) void main(int argc, char *argv[]) { - int i, c; + int c; Binit(&bso, 1, OWRITE); cout = -1; @@ -152,9 +135,6 @@ main(int argc, char *argv[]) if(strcmp(goos, "darwin") == 0) HEADTYPE = 6; else - if(strcmp(goos, "nacl") == 0) - HEADTYPE = 8; - else if(strcmp(goos, "freebsd") == 0) HEADTYPE = 9; else @@ -164,6 +144,9 @@ main(int argc, char *argv[]) if(strcmp(goos, "tiny") == 0) HEADTYPE = 11; else + if(strcmp(goos, "plan9") == 0) + HEADTYPE = 2; + else print("goos is not known: %s\n", goos); } @@ -208,7 +191,7 @@ main(int argc, char *argv[]) if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) - INITRND = 4096; + INITRND = 1; break; case 3: /* MS-DOS .COM */ HEADR = 0; @@ -229,7 +212,7 @@ main(int argc, char *argv[]) INITRND = 4; HEADR += (INITTEXT & 0xFFFF); if(debug['v']) - Bprint(&bso, "HEADR = 0x%ld\n", HEADR); + Bprint(&bso, "HEADR = 0x%d\n", HEADR); break; case 6: /* apple MACH */ /* @@ -249,7 +232,7 @@ main(int argc, char *argv[]) case 7: /* elf32 executable */ case 9: /* - * Linux ELF uses TLS offsets negative from %gs. + * ELF uses TLS offsets negative from %gs. * Translate 0(GS) and 4(GS) into -8(GS) and -4(GS). * Also known to ../../pkg/runtime/linux/386/sys.s * and ../../libcgo/linux_386.c. @@ -264,30 +247,15 @@ main(int argc, char *argv[]) if(INITRND == -1) INITRND = 4096; break; - case 8: /* native client elf32 executable */ - elfinit(); - HEADR = 4096; - if(INITTEXT == -1) - INITTEXT = 0x20000; - if(INITDAT == -1) - INITDAT = 0; - if(INITRND == -1) - INITRND = 65536; - - // 512 kB of address space for closures. - // (Doesn't take any space in the binary file.) - // Closures are 64 bytes each, so this is 8,192 closures. - textpad = 512*1024; - break; case 10: /* PE executable */ peinit(); - HEADR = PERESERVE; + HEADR = PEFILEHEADR; if(INITTEXT == -1) - INITTEXT = PEBASE+0x1000; + INITTEXT = PEBASE+PESECTHEADR; if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) - INITRND = PEALIGN; + INITRND = PESECTALIGN; break; case 11: tlsoffset = 0; @@ -302,68 +270,14 @@ main(int argc, char *argv[]) break; } if(INITDAT != 0 && INITRND != 0) - print("warning: -D0x%lux is ignored because of -R0x%lux\n", + print("warning: -D0x%ux is ignored because of -R0x%ux\n", INITDAT, INITRND); if(debug['v']) - Bprint(&bso, "HEADER = -H0x%ld -T0x%lux -D0x%lux -R0x%lux\n", + Bprint(&bso, "HEADER = -H0x%d -T0x%ux -D0x%ux -R0x%ux\n", HEADTYPE, INITTEXT, INITDAT, INITRND); Bflush(&bso); - for(i=1; optab[i].as; i++) - if(i != optab[i].as) { - diag("phase error in optab: %d", i); - errorexit(); - } - maxop = i; - - for(i=0; i<Ymax; i++) - ycover[i*Ymax + i] = 1; - - ycover[Yi0*Ymax + Yi8] = 1; - ycover[Yi1*Ymax + Yi8] = 1; - - ycover[Yi0*Ymax + Yi32] = 1; - ycover[Yi1*Ymax + Yi32] = 1; - ycover[Yi8*Ymax + Yi32] = 1; - - ycover[Yal*Ymax + Yrb] = 1; - ycover[Ycl*Ymax + Yrb] = 1; - ycover[Yax*Ymax + Yrb] = 1; - ycover[Ycx*Ymax + Yrb] = 1; - ycover[Yrx*Ymax + Yrb] = 1; - - ycover[Yax*Ymax + Yrx] = 1; - ycover[Ycx*Ymax + Yrx] = 1; - - ycover[Yax*Ymax + Yrl] = 1; - ycover[Ycx*Ymax + Yrl] = 1; - ycover[Yrx*Ymax + Yrl] = 1; - - ycover[Yf0*Ymax + Yrf] = 1; - - ycover[Yal*Ymax + Ymb] = 1; - ycover[Ycl*Ymax + Ymb] = 1; - ycover[Yax*Ymax + Ymb] = 1; - ycover[Ycx*Ymax + Ymb] = 1; - ycover[Yrx*Ymax + Ymb] = 1; - ycover[Yrb*Ymax + Ymb] = 1; - ycover[Ym*Ymax + Ymb] = 1; - - ycover[Yax*Ymax + Yml] = 1; - ycover[Ycx*Ymax + Yml] = 1; - ycover[Yrx*Ymax + Yml] = 1; - ycover[Yrl*Ymax + Yml] = 1; - ycover[Ym*Ymax + Yml] = 1; - - for(i=0; i<D_NONE; i++) { - reg[i] = -1; - if(i >= D_AL && i <= D_BH) - reg[i] = (i-D_AL) & 7; - if(i >= D_AX && i <= D_DI) - reg[i] = (i-D_AX) & 7; - if(i >= D_F0 && i <= D_F0+7) - reg[i] = (i-D_F0) & 7; - } + instinit(); zprg.link = P; zprg.pcond = P; zprg.back = 2; @@ -373,49 +287,25 @@ main(int argc, char *argv[]) zprg.from.scale = 1; zprg.to = zprg.from; - pcstr = "%.6lux "; + pcstr = "%.6ux "; nuxiinit(); histgen = 0; - textp = P; - datap = P; - edatap = P; pc = 0; dtype = 4; version = 0; cbp = buf.cbuf; cbc = sizeof(buf.cbuf); - firstp = prg(); - lastp = firstp; addlibpath("command line", "command line", argv[0], "main"); loadlib(); - deadcode(); - - firstp = firstp->link; - if(firstp == P) - errorexit(); - if(doexp || dlm){ - EXPTAB = "_exporttab"; - zerosig(EXPTAB); - zerosig("etext"); - zerosig("edata"); - zerosig("end"); - if(dlm){ - import(); - HEADTYPE = 2; - INITTEXT = INITDAT = 0; - INITRND = 8; - INITENTRY = EXPTAB; - } - export(); - } patch(); follow(); doelf(); if(HEADTYPE == 6) domacho(); - dodata(); + if(HEADTYPE == 10) + dope(); dostkoff(); if(debug['p']) if(debug['1']) @@ -423,14 +313,18 @@ main(int argc, char *argv[]) else doprof2(); span(); - doinit(); - if(HEADTYPE == 10) - dope(); + addexport(); + textaddress(); + pclntab(); + symtab(); + dodata(); + address(); + reloc(); asmb(); undef(); if(debug['v']) { Bprint(&bso, "%5.2f cpu time\n", cputime()); - Bprint(&bso, "%ld symbols\n", nsymbol); + Bprint(&bso, "%d symbols\n", nsymbol); Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); } @@ -439,8 +333,19 @@ main(int argc, char *argv[]) errorexit(); } -void -zaddr(Biobuf *f, Adr *a, Sym *h[]) +static Sym* +zsym(char *pn, Biobuf *f, Sym *h[]) +{ + int o; + + o = Bgetc(f); + if(o < 0 || o >= NSYM || h[o] == nil) + mangle(pn); + return h[o]; +} + +static void +zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[]) { int t; int32 l; @@ -465,7 +370,7 @@ zaddr(Biobuf *f, Adr *a, Sym *h[]) } a->sym = S; if(t & T_SYM) - a->sym = h[Bgetc(f)]; + a->sym = zsym(pn, f, h); if(t & T_FCONST) { a->ieee.l = Bget4(f); a->ieee.h = Bget4(f); @@ -479,7 +384,7 @@ zaddr(Biobuf *f, Adr *a, Sym *h[]) a->type = Bgetc(f); adrgotype = S; if(t & T_GOTYPE) - adrgotype = h[Bgetc(f)]; + adrgotype = zsym(pn, f, h); t = a->type; if(t == D_INDIR+D_GS) @@ -526,7 +431,7 @@ void ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) { int32 ipc; - Prog *p, *t; + Prog *p; int v, o, r, skip; Sym *h[NSYM], *s, *di; uint32 sig; @@ -534,7 +439,9 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) int32 eof; char *name, *x; char src[1024]; + Prog *lastp; + lastp = nil; ntext = 0; eof = Boffset(f) + len; di = S; @@ -591,7 +498,7 @@ loop: if(sig != 0){ if(s->sig != 0 && s->sig != sig) diag("incompatible type signatures" - "%lux(%s) and %lux(%s) for %s", + "%ux(%s) and %ux(%s) for %s", s->sig, s->file, sig, pn, s->name); s->sig = sig; s->file = pn; @@ -599,6 +506,8 @@ loop: if(debug['W']) print(" ANAME %s\n", s->name); + if(o < 0 || o >= nelem(h)) + mangle(pn); h[o] = s; if((v == D_EXTERN || v == D_STATIC) && s->type == 0) s->type = SXREF; @@ -613,6 +522,7 @@ loop: histfrogp++; } else collapsefrog(s); + dwarfaddfrag(s->value, s->name); } goto loop; } @@ -623,9 +533,9 @@ loop: p->back = 2; p->ft = 0; p->tt = 0; - zaddr(f, &p->from, h); + zaddr(pn, f, &p->from, h); fromgotype = adrgotype; - zaddr(f, &p->to, h); + zaddr(pn, f, &p->to, h); if(debug['W']) print("%P\n", p); @@ -647,10 +557,10 @@ loop: case AEND: histtoauto(); - if(curtext != P) - curtext->to.autom = curauto; + if(cursym != nil && cursym->text) + cursym->autom = curauto; curauto = 0; - curtext = P; + cursym = nil; if(Boffset(f) == eof) return; goto newloop; @@ -659,89 +569,41 @@ loop: s = p->from.sym; if(s->type == 0 || s->type == SXREF) { s->type = SBSS; - s->value = 0; + s->size = 0; } - if(s->type != SBSS) { + if(s->type != SBSS && !s->dupok) { diag("%s: redefinition: %s in %s", pn, s->name, TNAME); s->type = SBSS; - s->value = 0; + s->size = 0; } - if(p->to.offset > s->value) - s->value = p->to.offset; + if(p->to.offset > s->size) + s->size = p->to.offset; if(p->from.scale & DUPOK) s->dupok = 1; + if(p->from.scale & RODATA) + s->type = SRODATA; goto loop; - case ADYNT: - if(p->to.sym == S) { - diag("DYNT without a sym\n%P", p); - break; - } - di = p->to.sym; - p->from.scale = 4; - if(di->type == SXREF) { - if(debug['z']) - Bprint(&bso, "%P set to %d\n", p, dtype); - di->type = SCONST; - di->value = dtype; - dtype += 4; - } - if(p->from.sym == S) - break; - - p->from.offset = di->value; - p->from.sym->type = SDATA; - if(curtext == P) { - diag("DYNT not in text: %P", p); - break; - } - p->to.sym = curtext->from.sym; - p->to.type = D_ADDR; - p->to.index = D_EXTERN; - goto data; - - case AINIT: - if(p->from.sym == S) { - diag("INIT without a sym\n%P", p); - break; - } - if(di == S) { - diag("INIT without previous DYNT\n%P", p); - break; - } - p->from.offset = di->value; - p->from.sym->type = SDATA; - goto data; - case ADATA: - data: // Assume that AGLOBL comes after ADATA. // If we've seen an AGLOBL that said this sym was DUPOK, // ignore any more ADATA we see, which must be // redefinitions. s = p->from.sym; - if(s != S && s->dupok) { + if(s->dupok) { // if(debug['v']) // Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn); goto loop; } - if(s != S) { - p->dlink = s->data; - s->data = p; - if(s->file == nil) - s->file = pn; - else if(s->file != pn) { - diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn); - errorexit(); - } + if(s->file == nil) + s->file = pn; + else if(s->file != pn) { + diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn); + errorexit(); } - if(edatap == P) - datap = p; - else - edatap->link = p; - edatap = p; - p->link = P; + savedata(s, p); + unmal(p, sizeof *p); goto loop; case AGOK: @@ -751,9 +613,9 @@ loop: case ATEXT: s = p->from.sym; - if(s == S) { - diag("%s: no TEXT symbol: %P", pn, p); - errorexit(); + if(s->text != nil) { + diag("%s: %s: redefinition", pn, s->name); + return; } if(ntext++ == 0 && s->type != 0 && s->type != SXREF) { /* redefinition, so file has probably been seen before */ @@ -761,13 +623,19 @@ loop: diag("skipping: %s: redefinition: %s", pn, s->name); return; } - if(curtext != P) { + if(cursym != nil && cursym->text) { histtoauto(); - curtext->to.autom = curauto; + cursym->autom = curauto; curauto = 0; } skip = 0; - curtext = p; + if(etextp) + etextp->next = s; + else + textp = s; + etextp = s; + s->text = p; + cursym = s; if(s->type != 0 && s->type != SXREF) { if(p->from.scale & DUPOK) { skip = 1; @@ -775,7 +643,10 @@ loop: } diag("%s: redefinition: %s\n%P", pn, s->name, p); } - newtext(p, s); + s->type = STEXT; + s->value = pc; + lastp = p; + p->pc = pc++; goto loop; case AFMOVF: @@ -791,24 +662,12 @@ loop: goto casdef; if(p->from.type == D_FCONST) { /* size sb 9 max */ - sprint(literal, "$%lux", ieeedtof(&p->from.ieee)); + sprint(literal, "$%ux", ieeedtof(&p->from.ieee)); s = lookup(literal, 0); if(s->type == 0) { - s->type = SBSS; - s->value = 4; - t = prg(); - t->as = ADATA; - t->line = p->line; - t->from.type = D_EXTERN; - t->from.sym = s; - t->from.scale = 4; - t->to = p->from; - if(edatap == P) - datap = t; - else - edatap->link = t; - edatap = t; - t->link = P; + s->type = SDATA; + adduint32(s, ieeedtof(&p->from.ieee)); + s->reachable = 0; } p->from.type = D_EXTERN; p->from.sym = s; @@ -829,25 +688,14 @@ loop: goto casdef; if(p->from.type == D_FCONST) { /* size sb 18 max */ - sprint(literal, "$%lux.%lux", + sprint(literal, "$%ux.%ux", p->from.ieee.l, p->from.ieee.h); s = lookup(literal, 0); if(s->type == 0) { - s->type = SBSS; - s->value = 8; - t = prg(); - t->as = ADATA; - t->line = p->line; - t->from.type = D_EXTERN; - t->from.sym = s; - t->from.scale = 8; - t->to = p->from; - if(edatap == P) - datap = t; - else - edatap->link = t; - edatap = t; - t->link = P; + s->type = SDATA; + adduint32(s, p->from.ieee.l); + adduint32(s, p->from.ieee.h); + s->reachable = 0; } p->from.type = D_EXTERN; p->from.sym = s; @@ -859,13 +707,18 @@ loop: default: if(skip) nopout(p); + p->pc = pc; + pc++; if(p->to.type == D_BRANCH) p->to.offset += ipc; + if(lastp == nil) { + if(p->as != ANOP) + diag("unexpected instruction: %P", p); + goto loop; + } lastp->link = p; lastp = p; - p->pc = pc; - pc++; goto loop; } goto loop; @@ -905,153 +758,3 @@ appendp(Prog *q) p->line = q->line; return p; } - -void -doprof1(void) -{ - Sym *s; - int32 n; - Prog *p, *q; - - if(debug['v']) - Bprint(&bso, "%5.2f profile 1\n", cputime()); - Bflush(&bso); - s = lookup("__mcount", 0); - n = 1; - for(p = firstp->link; p != P; p = p->link) { - if(p->as == ATEXT) { - q = prg(); - q->line = p->line; - q->link = datap; - datap = q; - q->as = ADATA; - q->from.type = D_EXTERN; - q->from.offset = n*4; - q->from.sym = s; - q->from.scale = 4; - q->to = p->from; - q->to.type = D_CONST; - - q = prg(); - q->line = p->line; - q->pc = p->pc; - q->link = p->link; - p->link = q; - p = q; - p->as = AADDL; - p->from.type = D_CONST; - p->from.offset = 1; - p->to.type = D_EXTERN; - p->to.sym = s; - p->to.offset = n*4 + 4; - - n += 2; - continue; - } - } - q = prg(); - q->line = 0; - q->link = datap; - datap = q; - - q->as = ADATA; - q->from.type = D_EXTERN; - q->from.sym = s; - q->from.scale = 4; - q->to.type = D_CONST; - q->to.offset = n; - - s->type = SBSS; - s->value = n*4; -} - -void -doprof2(void) -{ - Sym *s2, *s4; - Prog *p, *q, *ps2, *ps4; - - if(debug['v']) - Bprint(&bso, "%5.2f profile 2\n", cputime()); - Bflush(&bso); - - s2 = lookup("_profin", 0); - s4 = lookup("_profout", 0); - if(s2->type != STEXT || s4->type != STEXT) { - diag("_profin/_profout not defined"); - return; - } - - ps2 = P; - ps4 = P; - for(p = firstp; p != P; p = p->link) { - if(p->as == ATEXT) { - if(p->from.sym == s2) { - p->from.scale = 1; - ps2 = p; - } - if(p->from.sym == s4) { - p->from.scale = 1; - ps4 = p; - } - } - } - for(p = firstp; p != P; p = p->link) { - if(p->as == ATEXT) { - curtext = p; - - if(p->from.scale & NOPROF) { /* dont profile */ - for(;;) { - q = p->link; - if(q == P) - break; - if(q->as == ATEXT) - break; - p = q; - } - continue; - } - - /* - * JMPL profin - */ - q = prg(); - q->line = p->line; - q->pc = p->pc; - q->link = p->link; - p->link = q; - p = q; - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = ps2; - p->to.sym = s2; - - continue; - } - if(p->as == ARET) { - /* - * RET - */ - q = prg(); - q->as = ARET; - q->from = p->from; - q->to = p->to; - q->link = p->link; - p->link = q; - - /* - * JAL profout - */ - p->as = ACALL; - p->from = zprg.from; - p->to = zprg.to; - p->to.type = D_BRANCH; - p->pcond = ps4; - p->to.sym = s4; - - p = q; - - continue; - } - } -} |