diff options
Diffstat (limited to 'src/cmd/6l/obj.c')
-rw-r--r-- | src/cmd/6l/obj.c | 549 |
1 files changed, 116 insertions, 433 deletions
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c index 5a4b6a3fc..96d78c3b9 100644 --- a/src/cmd/6l/obj.c +++ b/src/cmd/6l/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 <ar.h> char *noname = "<none>"; @@ -51,28 +54,6 @@ char* paramspace = "FP"; * options used: 189BLQSWabcjlnpsvz */ -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) { @@ -83,7 +64,7 @@ usage(void) void main(int argc, char *argv[]) { - int i, c; + int c; Binit(&bso, 1, OWRITE); cout = -1; @@ -187,6 +168,11 @@ main(int argc, char *argv[]) INITRND = 4096; break; case 6: /* apple MACH */ + /* + * OS X system constant - offset from 0(GS) to our TLS. + * Explained in ../../libcgo/darwin_amd64.c. + */ + tlsoffset = 0x8a0; machoinit(); HEADR = MACHORESERVE; if(INITRND == -1) @@ -198,6 +184,13 @@ main(int argc, char *argv[]) break; case 7: /* elf64 executable */ case 9: /* freebsd */ + /* + * ELF uses TLS offset negative from FS. + * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS). + * Also known to ../../pkg/runtime/linux/amd64/sys.s + * and ../../libcgo/linux_amd64.s. + */ + tlsoffset = -16; elfinit(); HEADR = ELFRESERVE; if(INITTEXT == -1) @@ -209,117 +202,13 @@ main(int argc, char *argv[]) break; } if(INITDAT != 0 && INITRND != 0) - print("warning: -D0x%llux is ignored because of -R0x%lux\n", + print("warning: -D0x%llux is ignored because of -R0x%ux\n", INITDAT, INITRND); if(debug['v']) - Bprint(&bso, "HEADER = -H%ld -T0x%llux -D0x%llux -R0x%lux\n", + Bprint(&bso, "HEADER = -H%d -T0x%llux -D0x%llux -R0x%ux\n", HEADTYPE, INITTEXT, INITDAT, INITRND); Bflush(&bso); - for(i=1; optab[i].as; i++) { - c = optab[i].as; - if(opindex[c] != nil) { - diag("phase error in optab: %d (%A)", i, c); - errorexit(); - } - opindex[c] = &optab[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 + Ys32] = 1; - ycover[Yi1*Ymax + Ys32] = 1; - ycover[Yi8*Ymax + Ys32] = 1; - - ycover[Yi0*Ymax + Yi32] = 1; - ycover[Yi1*Ymax + Yi32] = 1; - ycover[Yi8*Ymax + Yi32] = 1; - ycover[Ys32*Ymax + Yi32] = 1; - - ycover[Yi0*Ymax + Yi64] = 1; - ycover[Yi1*Ymax + Yi64] = 1; - ycover[Yi8*Ymax + Yi64] = 1; - ycover[Ys32*Ymax + Yi64] = 1; - ycover[Yi32*Ymax + Yi64] = 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[Yrl*Ymax + Yrb] = 1; - - ycover[Ycl*Ymax + Ycx] = 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[Yrl*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; - - ycover[Yax*Ymax + Ymm] = 1; - ycover[Ycx*Ymax + Ymm] = 1; - ycover[Yrx*Ymax + Ymm] = 1; - ycover[Yrl*Ymax + Ymm] = 1; - ycover[Ym*Ymax + Ymm] = 1; - ycover[Ymr*Ymax + Ymm] = 1; - - ycover[Yax*Ymax + Yxm] = 1; - ycover[Ycx*Ymax + Yxm] = 1; - ycover[Yrx*Ymax + Yxm] = 1; - ycover[Yrl*Ymax + Yxm] = 1; - ycover[Ym*Ymax + Yxm] = 1; - ycover[Yxr*Ymax + Yxm] = 1; - - for(i=0; i<D_NONE; i++) { - reg[i] = -1; - if(i >= D_AL && i <= D_R15B) { - reg[i] = (i-D_AL) & 7; - if(i >= D_SPB && i <= D_DIB) - regrex[i] = 0x40; - if(i >= D_R8B && i <= D_R15B) - regrex[i] = Rxr | Rxx | Rxb; - } - if(i >= D_AH && i<= D_BH) - reg[i] = 4 + ((i-D_AH) & 7); - if(i >= D_AX && i <= D_R15) { - reg[i] = (i-D_AX) & 7; - if(i >= D_R8) - regrex[i] = Rxr | Rxx | Rxb; - } - if(i >= D_F0 && i <= D_F0+7) - reg[i] = (i-D_F0) & 7; - if(i >= D_M0 && i <= D_M0+7) - reg[i] = (i-D_M0) & 7; - if(i >= D_X0 && i <= D_X0+15) { - reg[i] = (i-D_X0) & 7; - if(i >= D_X0+8) - regrex[i] = Rxr | Rxx | Rxb; - } - if(i >= D_CR+8 && i <= D_CR+15) - regrex[i] = Rxr; - } + instinit(); zprg.link = P; zprg.pcond = P; @@ -334,50 +223,20 @@ main(int argc, char *argv[]) pcstr = "%.6llux "; 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 = 0; - INITDAT = 0; - INITRND = 8; - INITENTRY = EXPTAB; - } - export(); - } - patch(); follow(); doelf(); if(HEADTYPE == 6) domacho(); - dodata(); - dobss(); dostkoff(); paramspace = "SP"; /* (FP) now (SP) on output */ if(debug['p']) @@ -386,12 +245,18 @@ main(int argc, char *argv[]) else doprof2(); span(); - doinit(); + 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)); } @@ -400,8 +265,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; @@ -425,7 +301,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); a->type = D_NONE; if(t & T_FCONST) { a->ieee.l = Bget4(f); @@ -438,16 +314,17 @@ zaddr(Biobuf *f, Adr *a, Sym *h[]) } if(t & T_TYPE) a->type = Bgetc(f); + if(a->type < 0 || a->type >= D_SIZE) + mangle(pn); adrgotype = S; if(t & T_GOTYPE) - adrgotype = h[Bgetc(f)]; + adrgotype = zsym(pn, f, h); s = a->sym; - if(s == S) - return; - t = a->type; + if(t == D_INDIR+D_GS) + a->offset += tlsoffset; if(t != D_AUTO && t != D_PARAM) { - if(adrgotype) + if(s && adrgotype) s->gotype = adrgotype; return; } @@ -484,7 +361,7 @@ void ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) { vlong ipc; - Prog *p, *t; + Prog *p; int v, o, r, skip, mode; Sym *h[NSYM], *s, *di; uint32 sig; @@ -492,7 +369,9 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) int ntext; vlong eof; char src[1024]; + Prog *lastp; + lastp = nil; ntext = 0; eof = Boffset(f) + len; di = S; @@ -549,7 +428,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; @@ -557,6 +436,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; @@ -571,6 +452,7 @@ loop: histfrogp++; } else collapsefrog(s); + dwarfaddfrag(s->value, s->name); } goto loop; } @@ -582,9 +464,18 @@ loop: p->mode = mode; 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); + + switch(p->as) { + case ATEXT: + case ADATA: + case AGLOBL: + if(p->from.sym == S) + mangle(pn); + break; + } if(debug['W']) print("%P\n", p); @@ -606,10 +497,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; @@ -618,89 +509,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: @@ -710,23 +553,29 @@ loop: case ATEXT: s = p->from.sym; + 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 */ if(debug['v']) Bprint(&bso, "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(s == S) { - diag("%s: no TEXT symbol: %P", pn, p); - errorexit(); - } + 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; @@ -739,7 +588,10 @@ loop: diag("%s: type mismatch for %s", pn, s->name); s->gotype = fromgotype; } - newtext(p, s); + s->type = STEXT; + s->value = pc; + lastp = p; + p->pc = pc++; goto loop; case AMODE: @@ -772,24 +624,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; @@ -817,25 +657,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; @@ -847,13 +676,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; @@ -895,154 +729,3 @@ appendp(Prog *q) p->mode = q->mode; 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; - } - } -} - |