Commit a9f6db58 authored by Russ Cox's avatar Russ Cox

cmd/ld: move instruction selection + layout into compilers, assemblers

- new object file reader/writer (liblink/objfile.c)
- remove old object file writing routines
- add pcdata iterator
- remove all trace of "line number stack" and "path fragments" from
  object files, linker (!!!)
- dwarf now writes a single "compilation unit" instead of one per package

This CL disables the check for chains of no-split functions that
could overflow the stack red zone. A future CL will attack the problem
of reenabling that check (issue 6931).

This CL is just the liblink and cmd/ld changes.
There are minor associated adjustments in CL 37030045.
Each depends on the other.

R=golang-dev, dave, iant
CC=golang-dev
https://golang.org/cl/39680043
parent 870e821d
...@@ -34,7 +34,6 @@ typedef struct LSym LSym; ...@@ -34,7 +34,6 @@ typedef struct LSym LSym;
typedef struct Reloc Reloc; typedef struct Reloc Reloc;
typedef struct Auto Auto; typedef struct Auto Auto;
typedef struct Hist Hist; typedef struct Hist Hist;
typedef struct Hist2 Hist2;
typedef struct Link Link; typedef struct Link Link;
typedef struct Plist Plist; typedef struct Plist Plist;
typedef struct LinkArch LinkArch; typedef struct LinkArch LinkArch;
...@@ -42,6 +41,7 @@ typedef struct Library Library; ...@@ -42,6 +41,7 @@ typedef struct Library Library;
typedef struct Pcln Pcln; typedef struct Pcln Pcln;
typedef struct Pcdata Pcdata; typedef struct Pcdata Pcdata;
typedef struct Pciter Pciter;
// prevent incompatible type signatures between liblink and 8l on Plan 9 // prevent incompatible type signatures between liblink and 8l on Plan 9
#pragma incomplete struct Node #pragma incomplete struct Node
...@@ -154,11 +154,11 @@ struct LSym ...@@ -154,11 +154,11 @@ struct LSym
char* dynimplib; char* dynimplib;
char* dynimpvers; char* dynimpvers;
struct Section* sect; struct Section* sect;
Hist2* hist; // for ATEXT
// STEXT // STEXT
Auto* autom; Auto* autom;
Prog* text; Prog* text;
Prog* etext;
Pcln* pcln; Pcln* pcln;
// SDATA, SBSS // SDATA, SBSS
...@@ -286,18 +286,21 @@ struct Pcln ...@@ -286,18 +286,21 @@ struct Pcln
int lastindex; int lastindex;
}; };
enum // Pcdata iterator.
// for(pciterinit(&it, &pcd); !it.done; pciternext(&it)) { it.value holds in [it.pc, it.nextpc) }
struct Pciter
{ {
LinkMaxHist = 40, Pcdata d;
uchar *p;
uint32 pc;
uint32 nextpc;
int32 value;
int start;
int done;
}; };
// TODO: Replace uses of Hist2 with Hist and delete this. void pciterinit(Pciter*, Pcdata*);
struct Hist2 void pciternext(Pciter*);
{
int32 line;
int32 off;
LSym *file;
};
// symbol version, incremented each time a file is loaded. // symbol version, incremented each time a file is loaded.
// version==1 is reserved for savehist. // version==1 is reserved for savehist.
...@@ -377,20 +380,13 @@ struct Link ...@@ -377,20 +380,13 @@ struct Link
int nlibrary; int nlibrary;
int tlsoffset; int tlsoffset;
void (*diag)(char*, ...); void (*diag)(char*, ...);
void (*dwarfaddfrag)(int, char*); int mode;
LSym* histfrog[LinkMaxHist];
int histfrogp;
int histgen;
Auto* curauto; Auto* curauto;
Auto* curhist; Auto* curhist;
LSym* cursym; LSym* cursym;
int version; int version;
LSym* textp; LSym* textp;
LSym* etextp; LSym* etextp;
Hist2* histcopy;
Hist2* hist2;
int32 nhist2;
int32 maxhist2;
int32 histdepth; int32 histdepth;
int32 nhistfile; int32 nhistfile;
LSym* filesyms; LSym* filesyms;
...@@ -400,6 +396,7 @@ struct Link ...@@ -400,6 +396,7 @@ struct Link
struct LinkArch struct LinkArch
{ {
char* name; // "arm", "amd64", and so on char* name; // "arm", "amd64", and so on
int thechar; // '5', '6', and so on
void (*addstacksplit)(Link*, LSym*); void (*addstacksplit)(Link*, LSym*);
void (*assemble)(Link*, LSym*); void (*assemble)(Link*, LSym*);
...@@ -407,17 +404,11 @@ struct LinkArch ...@@ -407,17 +404,11 @@ struct LinkArch
void (*follow)(Link*, LSym*); void (*follow)(Link*, LSym*);
int (*iscall)(Prog*); int (*iscall)(Prog*);
int (*isdata)(Prog*); int (*isdata)(Prog*);
void (*ldobj)(Link*, Biobuf*, char*, int64, char*);
void (*nopout)(Prog*);
Prog* (*prg)(void); Prog* (*prg)(void);
void (*progedit)(Link*, Prog*); void (*progedit)(Link*, Prog*);
void (*settextflag)(Prog*, int); void (*settextflag)(Prog*, int);
int (*symtype)(Addr*); int (*symtype)(Addr*);
int (*textflag)(Prog*); int (*textflag)(Prog*);
void (*zfile)(Biobuf*, char*, int);
void (*zhist)(Biobuf*, int, vlong);
void (*zprog)(Link*, Biobuf*, Prog*, int, int, int, int);
void (*zname)(Biobuf*, LSym*, int);
int minlc; int minlc;
int ptrsize; int ptrsize;
...@@ -432,14 +423,19 @@ struct LinkArch ...@@ -432,14 +423,19 @@ struct LinkArch
int D_PCREL; int D_PCREL;
int D_SCONST; int D_SCONST;
int D_SIZE; int D_SIZE;
int D_STATIC;
int ACALL; int ACALL;
int ADATA;
int AEND;
int AFUNCDATA; int AFUNCDATA;
int AGLOBL;
int AJMP; int AJMP;
int ANOP; int ANOP;
int APCDATA; int APCDATA;
int ARET; int ARET;
int ATEXT; int ATEXT;
int ATYPE;
int AUSEFIELD; int AUSEFIELD;
}; };
...@@ -473,6 +469,8 @@ extern uchar inuxi8[8]; ...@@ -473,6 +469,8 @@ extern uchar inuxi8[8];
// asm5.c // asm5.c
void span5(Link *ctxt, LSym *s); void span5(Link *ctxt, LSym *s);
int chipfloat5(Link *ctxt, float64 e);
int chipzero5(Link *ctxt, float64 e);
// asm6.c // asm6.c
void span6(Link *ctxt, LSym *s); void span6(Link *ctxt, LSym *s);
...@@ -504,23 +502,20 @@ vlong setuintxx(Link *ctxt, LSym *s, vlong off, uint64 v, vlong wid); ...@@ -504,23 +502,20 @@ vlong setuintxx(Link *ctxt, LSym *s, vlong off, uint64 v, vlong wid);
void symgrow(Link *ctxt, LSym *s, int32 siz); void symgrow(Link *ctxt, LSym *s, int32 siz);
// go.c // go.c
void double2ieee(uint64 *ieee, double native);
void* emallocz(long n); void* emallocz(long n);
void* erealloc(void *p, long n); void* erealloc(void *p, long n);
char* estrdup(char *p); char* estrdup(char *p);
char* expandpkg(char *t0, char *pkg); char* expandpkg(char *t0, char *pkg);
// ieee.c
void double2ieee(uint64 *ieee, double native);
// ld.c // ld.c
void addhist(Link *ctxt, int32 line, int type); void addhist(Link *ctxt, int32 line, int type);
void addlib(Link *ctxt, char *src, char *obj); void addlib(Link *ctxt, char *src, char *obj, char *path);
void addlibpath(Link *ctxt, char *srcref, char *objref, char *file, char *pkg); void addlibpath(Link *ctxt, char *srcref, char *objref, char *file, char *pkg);
void collapsefrog(Link *ctxt, LSym *s); void collapsefrog(Link *ctxt, LSym *s);
void copyhistfrog(Link *ctxt, char *buf, int nbuf); void copyhistfrog(Link *ctxt, char *buf, int nbuf);
int find1(int32 l, int c); int find1(int32 l, int c);
Hist2* gethist(Link *ctxt); void linkgetline(Link *ctxt, int32 line, LSym **f, int32 *l);
void linkgetline(Link *ctxt, Hist2 *h, int32 line, LSym **f, int32 *l);
void histtoauto(Link *ctxt); void histtoauto(Link *ctxt);
void mkfwd(LSym*); void mkfwd(LSym*);
void nuxiinit(void); void nuxiinit(void);
...@@ -529,13 +524,20 @@ Prog* copyp(Link*, Prog*); ...@@ -529,13 +524,20 @@ Prog* copyp(Link*, Prog*);
Prog* appendp(Link*, Prog*); Prog* appendp(Link*, Prog*);
vlong atolwhex(char*); vlong atolwhex(char*);
// list[568].c
void listinit5(void);
void listinit6(void);
void listinit8(void);
// obj.c // obj.c
int linklinefmt(Link *ctxt, Fmt *fp); int linklinefmt(Link *ctxt, Fmt *fp);
void linklinehist(Link *ctxt, int lineno, char *f, int offset); void linklinehist(Link *ctxt, int lineno, char *f, int offset);
Plist* linknewplist(Link *ctxt); Plist* linknewplist(Link *ctxt);
void linkouthist(Link *ctxt, Biobuf *b);
void linkprfile(Link *ctxt, int32 l); void linkprfile(Link *ctxt, int32 l);
void linkwritefuncs(Link *ctxt, Biobuf *b);
// objfile.c
void ldobjfile(Link *ctxt, Biobuf *b, char *pkg, int64 len, char *path);
void linkwriteobj(Link *ctxt, Biobuf *b);
// pass.c // pass.c
Prog* brchain(Link *ctxt, Prog *p); Prog* brchain(Link *ctxt, Prog *p);
...@@ -545,24 +547,14 @@ void linkpatch(Link *ctxt, LSym *sym); ...@@ -545,24 +547,14 @@ void linkpatch(Link *ctxt, LSym *sym);
// pcln.c // pcln.c
void linkpcln(Link*, LSym*); void linkpcln(Link*, LSym*);
// rdobj5.c
void ldobj5(Link *ctxt, Biobuf *f, char *pkg, int64 len, char *pn);
void nopout5(Prog *p);
// rdobj6.c
void ldobj6(Link *ctxt, Biobuf *f, char *pkg, int64 len, char *pn);
void nopout6(Prog *p);
// rdobj8.c
void ldobj8(Link *ctxt, Biobuf *f, char *pkg, int64 len, char *pn);
void nopout8(Prog *p);
// sym.c // sym.c
LSym* linklookup(Link *ctxt, char *name, int v); LSym* linklookup(Link *ctxt, char *name, int v);
Link* linknew(LinkArch*); Link* linknew(LinkArch*);
LSym* linknewsym(Link *ctxt, char *symb, int v); LSym* linknewsym(Link *ctxt, char *symb, int v);
LSym* linkrlookup(Link *ctxt, char *name, int v); LSym* linkrlookup(Link *ctxt, char *name, int v);
int linksymfmt(Fmt *f); int linksymfmt(Fmt *f);
int headtype(char*);
char* headstr(int);
extern char* anames5[]; extern char* anames5[];
extern char* anames6[]; extern char* anames6[];
......
...@@ -77,8 +77,6 @@ archinit(void) ...@@ -77,8 +77,6 @@ archinit(void)
case Hfreebsd: case Hfreebsd:
case Hnetbsd: case Hnetbsd:
debug['d'] = 0; // with dynamic linking debug['d'] = 0; // with dynamic linking
ctxt->tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then 4-byte word for m
// this number is known to ../../pkg/runtime/rt0_*_arm.s
elfinit(); elfinit();
HEADR = ELFRESERVE; HEADR = ELFRESERVE;
if(INITTEXT == -1) if(INITTEXT == -1)
...@@ -96,5 +94,5 @@ archinit(void) ...@@ -96,5 +94,5 @@ archinit(void)
// embed goarm to runtime.goarm // embed goarm to runtime.goarm
s = linklookup(ctxt, "runtime.goarm", 0); s = linklookup(ctxt, "runtime.goarm", 0);
s->type = SRODATA; s->type = SRODATA;
adduint8(ctxt, s, goarm); adduint8(ctxt, s, ctxt->goarm);
} }
...@@ -92,11 +92,6 @@ archinit(void) ...@@ -92,11 +92,6 @@ archinit(void)
INITRND = 4096; INITRND = 4096;
break; break;
case Hdarwin: /* apple MACH */ case Hdarwin: /* apple MACH */
/*
* OS X system constant - offset from 0(GS) to our TLS.
* Explained in ../../pkg/runtime/cgo/gcc_darwin_amd64.c.
*/
ctxt->tlsoffset = 0x8a0;
machoinit(); machoinit();
HEADR = INITIAL_MACHO_HEADR; HEADR = INITIAL_MACHO_HEADR;
if(INITRND == -1) if(INITRND == -1)
...@@ -111,13 +106,6 @@ archinit(void) ...@@ -111,13 +106,6 @@ archinit(void)
case Hnetbsd: /* netbsd */ case Hnetbsd: /* netbsd */
case Hopenbsd: /* openbsd */ case Hopenbsd: /* openbsd */
case Hdragonfly: /* dragonfly */ case Hdragonfly: /* dragonfly */
/*
* ELF uses TLS offset negative from FS.
* Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
* Also known to ../../pkg/runtime/sys_linux_amd64.s
* and ../../pkg/runtime/cgo/gcc_linux_amd64.c.
*/
ctxt->tlsoffset = -16;
elfinit(); elfinit();
HEADR = ELFRESERVE; HEADR = ELFRESERVE;
if(INITTEXT == -1) if(INITTEXT == -1)
......
...@@ -72,7 +72,6 @@ archinit(void) ...@@ -72,7 +72,6 @@ archinit(void)
errorexit(); errorexit();
case Hplan9: /* plan 9 */ case Hplan9: /* plan 9 */
ctxt->tlsoffset = -8;
HEADR = 32L; HEADR = 32L;
if(INITTEXT == -1) if(INITTEXT == -1)
INITTEXT = 4096+32; INITTEXT = 4096+32;
...@@ -82,11 +81,6 @@ archinit(void) ...@@ -82,11 +81,6 @@ archinit(void)
INITRND = 4096; INITRND = 4096;
break; break;
case Hdarwin: /* apple MACH */ case Hdarwin: /* apple MACH */
/*
* OS X system constant - offset from %gs to our TLS.
* Explained in ../../pkg/runtime/cgo/gcc_darwin_386.c.
*/
ctxt->tlsoffset = 0x468;
machoinit(); machoinit();
HEADR = INITIAL_MACHO_HEADR; HEADR = INITIAL_MACHO_HEADR;
if(INITTEXT == -1) if(INITTEXT == -1)
...@@ -101,13 +95,6 @@ archinit(void) ...@@ -101,13 +95,6 @@ archinit(void)
case Hnetbsd: case Hnetbsd:
case Hopenbsd: case Hopenbsd:
case Hdragonfly: case Hdragonfly:
/*
* ELF uses TLS offsets negative from %gs.
* Translate 0(GS) and 4(GS) into -8(GS) and -4(GS).
* Also known to ../../pkg/runtime/sys_linux_386.s
* and ../../pkg/runtime/cgo/gcc_linux_386.c.
*/
ctxt->tlsoffset = -8;
elfinit(); elfinit();
HEADR = ELFRESERVE; HEADR = ELFRESERVE;
if(INITTEXT == -1) if(INITTEXT == -1)
......
...@@ -401,8 +401,7 @@ void ...@@ -401,8 +401,7 @@ void
codeblk(int32 addr, int32 size) codeblk(int32 addr, int32 size)
{ {
LSym *sym; LSym *sym;
int32 eaddr, n, epc; int32 eaddr, n;
Prog *p;
uchar *q; uchar *q;
if(debug['a']) if(debug['a'])
...@@ -434,9 +433,8 @@ codeblk(int32 addr, int32 size) ...@@ -434,9 +433,8 @@ codeblk(int32 addr, int32 size)
Bprint(&bso, " %.2ux", 0); Bprint(&bso, " %.2ux", 0);
Bprint(&bso, "\n"); Bprint(&bso, "\n");
} }
p = sym->text;
if(p == nil) { Bprint(&bso, "%.6llux\t%-20s\n", (vlong)addr, sym->name);
Bprint(&bso, "%.6llux\t%-20s | foreign text\n", (vlong)addr, sym->name);
n = sym->size; n = sym->size;
q = sym->p; q = sym->p;
...@@ -449,21 +447,6 @@ codeblk(int32 addr, int32 size) ...@@ -449,21 +447,6 @@ codeblk(int32 addr, int32 size)
if(n > 0) if(n > 0)
Bprint(&bso, "%.6ux\t%-20.*I\n", addr, (int)n, q); Bprint(&bso, "%.6ux\t%-20.*I\n", addr, (int)n, q);
addr += n; addr += n;
continue;
}
Bprint(&bso, "%.6llux\t%-20s | %P\n", (vlong)sym->value, sym->name, p);
for(p = p->link; p != P; p = p->link) {
if(p->link != P)
epc = p->link->pc;
else
epc = sym->value + sym->size;
Bprint(&bso, "%.6llux\t", (uvlong)p->pc);
q = sym->p + p->pc - sym->value;
n = epc - p->pc;
Bprint(&bso, "%-20.*I | %P\n", (int)n, q, p);
addr += n;
}
} }
if(addr < eaddr) { if(addr < eaddr) {
...@@ -1031,7 +1014,6 @@ void ...@@ -1031,7 +1014,6 @@ void
textaddress(void) textaddress(void)
{ {
uvlong va; uvlong va;
Prog *p;
Section *sect; Section *sect;
LSym *sym, *sub; LSym *sym, *sub;
...@@ -1052,17 +1034,11 @@ textaddress(void) ...@@ -1052,17 +1034,11 @@ textaddress(void)
continue; continue;
if(sym->align != 0) if(sym->align != 0)
va = rnd(va, sym->align); va = rnd(va, sym->align);
else if(sym->text != P)
va = rnd(va, FuncAlign);
sym->value = 0; sym->value = 0;
for(sub = sym; sub != S; sub = sub->sub) { for(sub = sym; sub != S; sub = sub->sub)
sub->value += va; sub->value += va;
for(p = sub->text; p != P; p = p->link) if(sym->size == 0 && sym->sub != S)
p->pc += sub->value;
}
if(sym->size == 0 && sym->sub != S) {
ctxt->cursym = sym; ctxt->cursym = sym;
}
va += sym->size; va += sym->size;
} }
sect->len = va - sect->vaddr; sect->len = va - sect->vaddr;
......
This diff is collapsed.
...@@ -2,12 +2,6 @@ ...@@ -2,12 +2,6 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
/*
* Register 'f' symbol file fragments. Doing this while parsing the
* .6 input saves a pass over the symbol table later.
*/
void dwarfaddfrag(int n, char* frag);
/* /*
* Emit debug_abbrevs, debug_info and debug_line sections to current * Emit debug_abbrevs, debug_info and debug_line sections to current
* offset in cout. * offset in cout.
......
...@@ -558,23 +558,22 @@ static void ...@@ -558,23 +558,22 @@ static void
markflood(void) markflood(void)
{ {
Auto *a; Auto *a;
Prog *p;
LSym *s; LSym *s;
int i; int i;
for(s=markq; s!=S; s=s->queue) { for(s=markq; s!=S; s=s->queue) {
if(s->text) { if(s->type == STEXT) {
if(debug['v'] > 1) if(debug['v'] > 1)
Bprint(&bso, "marktext %s\n", s->name); Bprint(&bso, "marktext %s\n", s->name);
for(a=s->autom; a; a=a->link) for(a=s->autom; a; a=a->link)
mark1(a->gotype, s); mark1(a->gotype, s);
for(p=s->text; p != P; p=p->link) {
mark1(p->from.sym, s);
mark1(p->to.sym, s);
}
} }
for(i=0; i<s->nr; i++) for(i=0; i<s->nr; i++)
mark1(s->r[i].sym, s); mark1(s->r[i].sym, s);
if(s->pcln) {
for(i=0; i<s->pcln->nfuncdata; i++)
mark1(s->pcln->funcdata[i], s);
}
mark1(s->gotype, s); mark1(s->gotype, s);
mark1(s->sub, s); mark1(s->sub, s);
mark1(s->outer, s); mark1(s->outer, s);
...@@ -606,43 +605,11 @@ markextra[] = ...@@ -606,43 +605,11 @@ markextra[] =
"_modu", "_modu",
}; };
static int
isz(Auto *a)
{
for(; a; a=a->link)
if(a->type == D_FILE || a->type == D_FILE1)
return 1;
return 0;
}
static void
addz(LSym *s, Auto *z)
{
Auto *a, *last;
// strip out non-z
last = nil;
for(a = z; a != nil; a = a->link) {
if(a->type == D_FILE || a->type == D_FILE1) {
if(last == nil)
z = a;
else
last->link = a;
last = a;
}
}
if(last) {
last->link = s->autom;
s->autom = z;
}
}
void void
deadcode(void) deadcode(void)
{ {
int i; int i;
LSym *s, *last, *p; LSym *s, *last, *p;
Auto *z;
Fmt fmt; Fmt fmt;
if(debug['v']) if(debug['v'])
...@@ -665,23 +632,14 @@ deadcode(void) ...@@ -665,23 +632,14 @@ deadcode(void)
// remove dead text but keep file information (z symbols). // remove dead text but keep file information (z symbols).
last = nil; last = nil;
z = nil;
for(s = ctxt->textp; s != nil; s = s->next) { for(s = ctxt->textp; s != nil; s = s->next) {
if(!s->reachable) { if(!s->reachable)
if(isz(s->autom))
z = s->autom;
continue; continue;
}
if(last == nil) if(last == nil)
ctxt->textp = s; ctxt->textp = s;
else else
last->next = s; last->next = s;
last = s; last = s;
if(z != nil) {
if(!isz(s->autom))
addz(s, z);
z = nil;
}
} }
if(last == nil) if(last == nil)
ctxt->textp = nil; ctxt->textp = nil;
......
...@@ -182,12 +182,17 @@ loadlib(void) ...@@ -182,12 +182,17 @@ loadlib(void)
// whether to initialize the TLS. So give it one. This could // whether to initialize the TLS. So give it one. This could
// be handled differently but it's an unusual case. // be handled differently but it's an unusual case.
loadinternal("runtime/cgo"); loadinternal("runtime/cgo");
// Pretend that we really imported the package. // Pretend that we really imported the package.
// This will do no harm if we did in fact import it. // This will do no harm if we did in fact import it.
s = linklookup(ctxt, "go.importpath.runtime/cgo.", 0); s = linklookup(ctxt, "go.importpath.runtime/cgo.", 0);
s->type = SDATA; s->type = SDATA;
s->dupok = 1; s->dupok = 1;
s->reachable = 1; s->reachable = 1;
// Provided by the code that imports the package.
// Since we are simulating the import, we have to provide this string.
addstrdata("go.string.\"runtime/cgo\"", "runtime/cgo");
} }
for(i=0; i<ctxt->libraryp; i++) { for(i=0; i<ctxt->libraryp; i++) {
...@@ -765,7 +770,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, char *file, int whence) ...@@ -765,7 +770,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, char *file, int whence)
ldpkg(f, pkg, import1 - import0 - 2, pn, whence); // -2 for !\n ldpkg(f, pkg, import1 - import0 - 2, pn, whence); // -2 for !\n
Bseek(f, import1, 0); Bseek(f, import1, 0);
ctxt->arch->ldobj(ctxt, f, pkg, eof - Boffset(f), pn); ldobjfile(ctxt, f, pkg, eof - Boffset(f), pn);
free(pn); free(pn);
return; return;
...@@ -979,6 +984,9 @@ enum ...@@ -979,6 +984,9 @@ enum
CallSize = (!HasLinkRegister)*PtrSize, // bytes of stack required for a call CallSize = (!HasLinkRegister)*PtrSize, // bytes of stack required for a call
}; };
// TODO: Record enough information in new object files to
// allow stack checks here.
void void
dostkcheck(void) dostkcheck(void)
{ {
...@@ -988,6 +996,7 @@ dostkcheck(void) ...@@ -988,6 +996,7 @@ dostkcheck(void)
morestack = linklookup(ctxt, "runtime.morestack", 0); morestack = linklookup(ctxt, "runtime.morestack", 0);
newstack = linklookup(ctxt, "runtime.newstack", 0); newstack = linklookup(ctxt, "runtime.newstack", 0);
// TODO
// First the nosplits on their own. // First the nosplits on their own.
for(s = ctxt->textp; s != nil; s = s->next) { for(s = ctxt->textp; s != nil; s = s->next) {
if(s->text == nil || s->text->link == nil || (ctxt->arch->textflag(s->text) & NOSPLIT) == 0) if(s->text == nil || s->text->link == nil || (ctxt->arch->textflag(s->text) & NOSPLIT) == 0)
...@@ -1137,34 +1146,6 @@ stkprint(Chain *ch, int limit) ...@@ -1137,34 +1146,6 @@ stkprint(Chain *ch, int limit)
print("\t%d\tafter %s uses %d\n", limit, name, ch->limit - limit); print("\t%d\tafter %s uses %d\n", limit, name, ch->limit - limit);
} }
int
headtype(char *name)
{
int i;
for(i=0; headers[i].name; i++)
if(strcmp(name, headers[i].name) == 0) {
headstring = headers[i].name;
return headers[i].val;
}
fprint(2, "unknown header type -H %s\n", name);
errorexit();
return -1; // not reached
}
char*
headstr(int v)
{
static char buf[20];
int i;
for(i=0; headers[i].name; i++)
if(v == headers[i].val)
return headers[i].name;
snprint(buf, sizeof buf, "%d", v);
return buf;
}
int int
Yconv(Fmt *fp) Yconv(Fmt *fp)
{ {
...@@ -1267,6 +1248,13 @@ usage(void) ...@@ -1267,6 +1248,13 @@ usage(void)
void void
setheadtype(char *s) setheadtype(char *s)
{ {
int h;
h = headtype(s);
if(h < 0) {
fprint(2, "unknown header type -H %s\n", s);
errorexit();
}
HEADTYPE = headtype(s); HEADTYPE = headtype(s);
} }
...@@ -1337,9 +1325,6 @@ genasmsym(void (*put)(LSym*, char*, int, vlong, vlong, int, LSym*)) ...@@ -1337,9 +1325,6 @@ genasmsym(void (*put)(LSym*, char*, int, vlong, vlong, int, LSym*))
} }
for(s = ctxt->textp; s != nil; s = s->next) { for(s = ctxt->textp; s != nil; s = s->next) {
if(s->text == nil)
continue;
put(s, s->name, 'T', s->value, s->size, s->version, s->gotype); put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
for(a=s->autom; a; a=a->link) { for(a=s->autom; a; a=a->link) {
...@@ -1434,10 +1419,8 @@ undefsym(LSym *s) ...@@ -1434,10 +1419,8 @@ undefsym(LSym *s)
r = &s->r[i]; r = &s->r[i];
if(r->sym == nil) // happens for some external ARM relocs if(r->sym == nil) // happens for some external ARM relocs
continue; continue;
if(r->sym->type == Sxxx || r->sym->type == SXREF) { if(r->sym->type == Sxxx || r->sym->type == SXREF)
diag("undefined: %s", r->sym->name); diag("undefined: %s", r->sym->name);
continue;
}
if(!r->sym->reachable) if(!r->sym->reachable)
diag("use of unreachable symbol: %s", r->sym->name); diag("use of unreachable symbol: %s", r->sym->name);
} }
......
...@@ -162,8 +162,6 @@ EXTERN char* cbpmax; ...@@ -162,8 +162,6 @@ EXTERN char* cbpmax;
if(--cbc <= 0)\ if(--cbc <= 0)\
cflush(); } cflush(); }
EXTERN int goarm;
void Lflag(char *arg); void Lflag(char *arg);
int Yconv(Fmt *fp); int Yconv(Fmt *fp);
int Zconv(Fmt *fp); int Zconv(Fmt *fp);
......
...@@ -54,33 +54,15 @@ ftabaddstring(LSym *ftab, char *s) ...@@ -54,33 +54,15 @@ ftabaddstring(LSym *ftab, char *s)
return start; return start;
} }
static uint32
getvarint(uchar **pp)
{
uchar *p;
int shift;
uint32 v;
v = 0;
p = *pp;
for(shift = 0;; shift += 7) {
v |= (*p & 0x7F) << shift;
if(!(*p++ & 0x80))
break;
}
*pp = p;
return v;
}
static void static void
renumberfiles(LSym **files, int nfiles, Pcdata *d) renumberfiles(LSym **files, int nfiles, Pcdata *d)
{ {
int i; int i;
LSym *f; LSym *f;
Pcdata out; Pcdata out;
Pciter it;
uint32 v; uint32 v;
int32 oldval, newval, val, dv; int32 oldval, newval, val, dv;
uchar *p;
// Give files numbers. // Give files numbers.
for(i=0; i<nfiles; i++) { for(i=0; i<nfiles; i++) {
...@@ -93,19 +75,12 @@ renumberfiles(LSym **files, int nfiles, Pcdata *d) ...@@ -93,19 +75,12 @@ renumberfiles(LSym **files, int nfiles, Pcdata *d)
} }
} }
oldval = -1;
newval = -1; newval = -1;
memset(&out, 0, sizeof out); memset(&out, 0, sizeof out);
p = d->p;
while(p < d->p + d->n) { for(pciterinit(&it, d); !it.done; pciternext(&it)) {
// value delta // value delta
v = getvarint(&p); oldval = it.value;
if(v == 0 && p != d->p) {
addvarint(&out, 0);
break;
}
dv = (int32)(v>>1) ^ ((int32)(v<<31)>>31);
oldval += dv;
if(oldval == -1) if(oldval == -1)
val = -1; val = -1;
else { else {
...@@ -114,14 +89,16 @@ renumberfiles(LSym **files, int nfiles, Pcdata *d) ...@@ -114,14 +89,16 @@ renumberfiles(LSym **files, int nfiles, Pcdata *d)
val = files[oldval]->value; val = files[oldval]->value;
} }
dv = val - newval; dv = val - newval;
v = (uint32)(dv<<1) ^ (uint32)(dv>>31); v = (uint32)(dv<<1) ^ (uint32)(int32)(dv>>31);
addvarint(&out, v); addvarint(&out, v);
// pc delta // pc delta
v = getvarint(&p); addvarint(&out, it.nextpc - it.pc);
addvarint(&out, v);
} }
// terminating value delta
addvarint(&out, 0);
free(d->p); free(d->p);
*d = out; *d = out;
} }
...@@ -186,9 +163,6 @@ pclntab(void) ...@@ -186,9 +163,6 @@ pclntab(void)
// args int32 // args int32
// TODO: Move into funcinfo. // TODO: Move into funcinfo.
if(ctxt->cursym->text == nil)
off = setuint32(ctxt, ftab, off, ArgsSizeUnknown);
else
off = setuint32(ctxt, ftab, off, ctxt->cursym->args); off = setuint32(ctxt, ftab, off, ctxt->cursym->args);
// frame int32 // frame int32
...@@ -197,10 +171,7 @@ pclntab(void) ...@@ -197,10 +171,7 @@ pclntab(void)
// when a called function doesn't have argument information. // when a called function doesn't have argument information.
// We need to make sure everything has argument information // We need to make sure everything has argument information
// and then remove this. // and then remove this.
if(ctxt->cursym->text == nil) off = setuint32(ctxt, ftab, off, ctxt->cursym->locals + PtrSize);
off = setuint32(ctxt, ftab, off, 0);
else
off = setuint32(ctxt, ftab, off, (uint32)ctxt->cursym->text->to.offset+PtrSize);
if(pcln != &zpcln) if(pcln != &zpcln)
renumberfiles(pcln->file, pcln->nfile, &pcln->pcfile); renumberfiles(pcln->file, pcln->nfile, &pcln->pcfile);
......
...@@ -42,30 +42,13 @@ ...@@ -42,30 +42,13 @@
char *noname = "<none>"; char *noname = "<none>";
char* paramspace = "FP"; char* paramspace = "FP";
Header headers[] = {
"darwin", Hdarwin,
"dragonfly", Hdragonfly,
"elf", Helf,
"freebsd", Hfreebsd,
"linux", Hlinux,
"netbsd", Hnetbsd,
"openbsd", Hopenbsd,
"plan9", Hplan9,
"windows", Hwindows,
"windowsgui", Hwindows,
0, 0
};
void void
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
char *p;
ctxt = linknew(thelinkarch); ctxt = linknew(thelinkarch);
ctxt->thechar = thechar; ctxt->thechar = thechar;
ctxt->thestring = thestring; ctxt->thestring = thestring;
ctxt->diag = diag; ctxt->diag = diag;
ctxt->dwarfaddfrag = dwarfaddfrag;
ctxt->bso = &bso; ctxt->bso = &bso;
Binit(&bso, 1, OWRITE); Binit(&bso, 1, OWRITE);
...@@ -81,16 +64,8 @@ main(int argc, char *argv[]) ...@@ -81,16 +64,8 @@ main(int argc, char *argv[])
linkmode = LinkAuto; linkmode = LinkAuto;
nuxiinit(); nuxiinit();
if(thechar == '5') { if(thechar == '5' && ctxt->goarm == 5)
p = getgoarm();
if(p != nil)
goarm = atoi(p);
else
goarm = 6;
if(goarm == 5)
debug['F'] = 1; debug['F'] = 1;
ctxt->goarm = goarm;
}
flagcount("1", "use alternate profiling code", &debug['1']); flagcount("1", "use alternate profiling code", &debug['1']);
if(thechar == '6') if(thechar == '6')
...@@ -186,13 +161,8 @@ main(int argc, char *argv[]) ...@@ -186,13 +161,8 @@ main(int argc, char *argv[])
mark(linklookup(ctxt, "runtime.read_tls_fallback", 0)); mark(linklookup(ctxt, "runtime.read_tls_fallback", 0));
} }
patch();
deadcode(); deadcode();
follow();
dostkoff();
paramspace = "SP"; /* (FP) now (SP) on output */ paramspace = "SP"; /* (FP) now (SP) on output */
span();
pcln();
doelf(); doelf();
if(HEADTYPE == Hdarwin) if(HEADTYPE == Hdarwin)
......
...@@ -383,8 +383,6 @@ static int32 oshrr(Link*, int, int, int, int); ...@@ -383,8 +383,6 @@ static int32 oshrr(Link*, int, int, int, int);
static int32 omvl(Link*, Prog*, Addr*, int); static int32 omvl(Link*, Prog*, Addr*, int);
static int32 immaddr(int32); static int32 immaddr(int32);
static int aclass(Link*, Addr*); static int aclass(Link*, Addr*);
static int chipzero(Link*, float64);
static int chipfloat(Link*, float64);
static int32 immrot(uint32); static int32 immrot(uint32);
static int32 immaddr(int32); static int32 immaddr(int32);
static int32 opbra(Link*, int, int); static int32 opbra(Link*, int, int);
...@@ -857,9 +855,9 @@ aclass(Link *ctxt, Addr *a) ...@@ -857,9 +855,9 @@ aclass(Link *ctxt, Addr *a)
return C_GOK; return C_GOK;
case D_FCONST: case D_FCONST:
if(chipzero(ctxt, a->u.dval) >= 0) if(chipzero5(ctxt, a->u.dval) >= 0)
return C_ZFCON; return C_ZFCON;
if(chipfloat(ctxt, a->u.dval) >= 0) if(chipfloat5(ctxt, a->u.dval) >= 0)
return C_SFCON; return C_SFCON;
return C_LFCON; return C_LFCON;
...@@ -950,7 +948,7 @@ oplook(Link *ctxt, Prog *p) ...@@ -950,7 +948,7 @@ oplook(Link *ctxt, Prog *p)
o = oprange[r].stop; /* just generate an error */ o = oprange[r].stop; /* just generate an error */
} }
if(0 /*debug['O']*/) { if(0 /*debug['O']*/) {
print("oplook %A %O %O %O\n", print("oplook %A %d %d %d\n",
(int)p->as, a1, a2, a3); (int)p->as, a1, a2, a3);
print(" %d %d\n", p->from.type, p->to.type); print(" %d %d\n", p->from.type, p->to.type);
} }
...@@ -964,8 +962,9 @@ oplook(Link *ctxt, Prog *p) ...@@ -964,8 +962,9 @@ oplook(Link *ctxt, Prog *p)
p->optab = (o-optab)+1; p->optab = (o-optab)+1;
return o; return o;
} }
ctxt->diag("illegal combination %A %O %O %O, %d %d", ctxt->diag("illegal combination %P; %d %d %d, %d %d",
p->as, a1, a2, a3, p->from.type, p->to.type); p, a1, a2, a3, p->from.type, p->to.type);
ctxt->diag("from %d %d to %d %d\n", p->from.type, p->from.name, p->to.type, p->to.name);
prasm(p); prasm(p);
if(o == 0) if(o == 0)
o = optab; o = optab;
...@@ -1557,7 +1556,7 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na ...@@ -1557,7 +1556,7 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na
aclass(ctxt, &p->from); aclass(ctxt, &p->from);
movm: movm:
if(ctxt->instoffset != 0) if(ctxt->instoffset != 0)
ctxt->diag("offset must be zero in MOVM"); ctxt->diag("offset must be zero in MOVM; %P", p);
o1 |= (p->scond & C_SCOND) << 28; o1 |= (p->scond & C_SCOND) << 28;
if(p->scond & C_PBIT) if(p->scond & C_PBIT)
o1 |= 1 << 24; o1 |= 1 << 24;
...@@ -1878,7 +1877,7 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na ...@@ -1878,7 +1877,7 @@ if(0 /*debug['G']*/) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->na
o1 = 0xeeb00b00; // VMOV imm 64 o1 = 0xeeb00b00; // VMOV imm 64
o1 |= (p->scond & C_SCOND) << 28; o1 |= (p->scond & C_SCOND) << 28;
o1 |= p->to.reg << 12; o1 |= p->to.reg << 12;
v = chipfloat(ctxt, p->from.u.dval); v = chipfloat5(ctxt, p->from.u.dval);
o1 |= (v&0xf) << 0; o1 |= (v&0xf) << 0;
o1 |= (v&0xf0) << 12; o1 |= (v&0xf0) << 12;
break; break;
...@@ -2392,8 +2391,8 @@ omvl(Link *ctxt, Prog *p, Addr *a, int dr) ...@@ -2392,8 +2391,8 @@ omvl(Link *ctxt, Prog *p, Addr *a, int dr)
return o1; return o1;
} }
static int int
chipzero(Link *ctxt, float64 e) chipzero5(Link *ctxt, float64 e)
{ {
// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions. // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
if(ctxt->goarm < 7 || e != 0) if(ctxt->goarm < 7 || e != 0)
...@@ -2401,8 +2400,8 @@ chipzero(Link *ctxt, float64 e) ...@@ -2401,8 +2400,8 @@ chipzero(Link *ctxt, float64 e)
return 0; return 0;
} }
static int int
chipfloat(Link *ctxt, float64 e) chipfloat5(Link *ctxt, float64 e)
{ {
int n; int n;
ulong h1; ulong h1;
......
...@@ -1677,6 +1677,7 @@ span6(Link *ctxt, LSym *s) ...@@ -1677,6 +1677,7 @@ span6(Link *ctxt, LSym *s)
sysfatal("loop"); sysfatal("loop");
} }
} while(loop); } while(loop);
c += -c&(FuncAlign-1);
s->size = c; s->size = c;
if(0 /* debug['a'] > 1 */) { if(0 /* debug['a'] > 1 */) {
......
...@@ -155,11 +155,15 @@ static uchar ytext[] = ...@@ -155,11 +155,15 @@ static uchar ytext[] =
}; };
static uchar ynop[] = static uchar ynop[] =
{ {
Ynone, Ynone, Zpseudo,1, Ynone, Ynone, Zpseudo,0,
Ynone, Yml, Zpseudo,1, Ynone, Yiauto, Zpseudo,0,
Ynone, Yrf, Zpseudo,1, Ynone, Yml, Zpseudo,0,
Yml, Ynone, Zpseudo,1, Ynone, Yrf, Zpseudo,0,
Yrf, Ynone, Zpseudo,1, Yiauto, Ynone, Zpseudo,0,
Ynone, Yxr, Zpseudo,0,
Yml, Ynone, Zpseudo,0,
Yrf, Ynone, Zpseudo,0,
Yxr, Ynone, Zpseudo,1,
0 0
}; };
static uchar yfuncdata[] = static uchar yfuncdata[] =
...@@ -1255,6 +1259,7 @@ span8(Link *ctxt, LSym *s) ...@@ -1255,6 +1259,7 @@ span8(Link *ctxt, LSym *s)
sysfatal("bad code"); sysfatal("bad code");
} }
} while(loop); } while(loop);
c += -c&(FuncAlign-1);
s->size = c; s->size = c;
if(0 /* debug['a'] > 1 */) { if(0 /* debug['a'] > 1 */) {
......
...@@ -35,329 +35,14 @@ ...@@ -35,329 +35,14 @@
#include <link.h> #include <link.h>
void void
copyhistfrog(Link *ctxt, char *buf, int nbuf) addlib(Link *ctxt, char *src, char *obj, char *pathname)
{ {
char *p, *ep; char name[1024], pname[1024], *p;
int i; int i;
p = buf; if(strlen(pathname) >= sizeof name)
ep = buf + nbuf; sysfatal("addlib pathname too long");
for(i=0; i<ctxt->histfrogp; i++) { strcpy(name, pathname);
p = seprint(p, ep, "%s", ctxt->histfrog[i]->name+1);
if(i+1<ctxt->histfrogp && (p == buf || p[-1] != '/'))
p = seprint(p, ep, "/");
}
}
void
addhist(Link *ctxt, int32 line, int type)
{
Auto *u;
LSym *s;
int i, j, k;
u = emallocz(sizeof(Auto));
s = emallocz(sizeof(LSym));
s->name = emallocz(2*(ctxt->histfrogp+1) + 1);
u->asym = s;
u->type = type;
u->aoffset = line;
u->link = ctxt->curhist;
ctxt->curhist = u;
s->name[0] = 0;
j = 1;
for(i=0; i<ctxt->histfrogp; i++) {
k = ctxt->histfrog[i]->value;
s->name[j+0] = k>>8;
s->name[j+1] = k;
j += 2;
}
s->name[j] = 0;
s->name[j+1] = 0;
}
void
histtoauto(Link *ctxt)
{
Auto *l;
while(l = ctxt->curhist) {
ctxt->curhist = l->link;
l->link = ctxt->curauto;
ctxt->curauto = l;
}
}
void
collapsefrog(Link *ctxt, LSym *s)
{
int i;
/*
* bad encoding of path components only allows
* MAXHIST components. if there is an overflow,
* first try to collapse xxx/..
*/
for(i=1; i<ctxt->histfrogp; i++)
if(strcmp(ctxt->histfrog[i]->name+1, "..") == 0) {
memmove(ctxt->histfrog+i-1, ctxt->histfrog+i+1,
(ctxt->histfrogp-i-1)*sizeof(ctxt->histfrog[0]));
ctxt->histfrogp--;
goto out;
}
/*
* next try to collapse .
*/
for(i=0; i<ctxt->histfrogp; i++)
if(strcmp(ctxt->histfrog[i]->name+1, ".") == 0) {
memmove(ctxt->histfrog+i, ctxt->histfrog+i+1,
(ctxt->histfrogp-i-1)*sizeof(ctxt->histfrog[0]));
goto out;
}
/*
* last chance, just truncate from front
*/
memmove(ctxt->histfrog+0, ctxt->histfrog+1,
(ctxt->histfrogp-1)*sizeof(ctxt->histfrog[0]));
out:
ctxt->histfrog[ctxt->histfrogp-1] = s;
}
// Saved history stacks encountered while reading archives.
// Keeping them allows us to answer virtual lineno -> file:line
// queries.
//
// The history stack is a complex data structure, described best at the
// bottom of http://plan9.bell-labs.com/magic/man2html/6/a.out.
// One of the key benefits of interpreting it here is that the runtime
// does not have to. Perhaps some day the compilers could generate
// a simpler linker input too.
// savehist processes a single line, off history directive
// found in the input object file.
void
savehist(Link *ctxt, int32 line, int32 off)
{
char tmp[1024];
LSym *file;
Hist2 *h;
// NOTE(rsc): We used to do the copyctxt->histfrog first and this
// condition was if(tmp[0] != '\0') to check for an empty string,
// implying that ctxt->histfrogp == 0, implying that this is a history pop.
// However, on Windows in the misc/cgo test, the linker is
// presented with an ANAME corresponding to an empty string,
// that ANAME ends up being the only ctxt->histfrog, and thus we have
// a situation where ctxt->histfrogp > 0 (not a pop) but the path we find
// is the empty string. Really that shouldn't happen, but it doesn't
// seem to be bothering anyone yet, and it's easier to fix the condition
// to test ctxt->histfrogp than to track down where that empty string is
// coming from. Probably it is coming from go tool pack's P command.
if(ctxt->histfrogp > 0) {
tmp[0] = '\0';
copyhistfrog(ctxt, tmp, sizeof tmp);
file = linklookup(ctxt, tmp, HistVersion);
} else
file = nil;
if(file != nil && line == 1 && off == 0) {
// start of new stack
if(ctxt->histdepth != 0)
sysfatal("history stack phase error: unexpected start of new stack depth=%d file=%s", ctxt->histdepth, tmp);
ctxt->nhist2 = 0;
ctxt->histcopy = nil;
}
if(ctxt->nhist2 >= ctxt->maxhist2) {
if(ctxt->maxhist2 == 0)
ctxt->maxhist2 = 1;
ctxt->maxhist2 *= 2;
ctxt->hist2 = erealloc(ctxt->hist2, ctxt->maxhist2*sizeof ctxt->hist2[0]);
}
h = &ctxt->hist2[ctxt->nhist2++];
h->line = line;
h->off = off;
h->file = file;
if(file != nil) {
if(off == 0)
ctxt->histdepth++;
} else {
if(off != 0)
sysfatal("history stack phase error: bad offset in pop");
ctxt->histdepth--;
}
}
// gethist returns the history stack currently in effect.
// The result is valid indefinitely.
Hist2*
gethist(Link *ctxt)
{
if(ctxt->histcopy == nil) {
if(ctxt->nhist2 == 0)
return nil;
ctxt->histcopy = emallocz((ctxt->nhist2+1)*sizeof ctxt->hist2[0]);
memmove(ctxt->histcopy, ctxt->hist2, ctxt->nhist2*sizeof ctxt->hist2[0]);
ctxt->histcopy[ctxt->nhist2].line = -1;
}
return ctxt->histcopy;
}
typedef struct Hstack Hstack;
struct Hstack
{
Hist2 *h;
int delta;
};
// getline sets *f to the file number and *l to the line number
// of the virtual line number line according to the history stack h.
void
linkgetline(Link *ctxt, Hist2 *h, int32 line, LSym **f, int32 *l)
{
Hstack stk[100];
int nstk, start;
Hist2 *top, *h0;
static Hist2 *lasth;
static int32 laststart, lastend, lastdelta;
static LSym *lastfile;
h0 = h;
*f = 0;
*l = 0;
start = 0;
if(h == nil || line == 0) {
print("%s: getline: h=%p line=%d\n", ctxt->cursym->name, h, line);
return;
}
// Cache span used during last lookup, so that sequential
// translation of line numbers in compiled code is efficient.
if(!ctxt->debughist && lasth == h && laststart <= line && line < lastend) {
*f = lastfile;
*l = line - lastdelta;
return;
}
if(ctxt->debughist)
print("getline %d laststart=%d lastend=%d\n", line, laststart, lastend);
nstk = 0;
for(; h->line != -1; h++) {
if(ctxt->debughist)
print("\t%s %d %d\n", h->file ? h->file->name : "?", h->line, h->off);
if(h->line > line) {
if(nstk == 0)
sysfatal("history stack phase error: empty stack at line %d", (int)line);
top = stk[nstk-1].h;
lasth = h;
lastfile = top->file;
laststart = start;
lastend = h->line;
lastdelta = stk[nstk-1].delta;
*f = lastfile;
*l = line - lastdelta;
if(ctxt->debughist)
print("\tgot %d %d [%d %d %d]\n", *f, *l, laststart, lastend, lastdelta);
return;
}
if(h->file == nil) {
// pop included file
if(nstk == 0)
sysfatal("history stack phase error: stack underflow");
nstk--;
if(nstk > 0)
stk[nstk-1].delta += h->line - stk[nstk].h->line;
start = h->line;
} else if(h->off == 0) {
// push included file
if(nstk >= nelem(stk))
sysfatal("history stack phase error: stack overflow");
start = h->line;
stk[nstk].h = h;
stk[nstk].delta = h->line - 1;
nstk++;
} else {
// #line directive
if(nstk == 0)
sysfatal("history stack phase error: stack underflow");
stk[nstk-1].h = h;
stk[nstk-1].delta = h->line - h->off;
start = h->line;
}
if(ctxt->debughist)
print("\t\tnstk=%d delta=%d\n", nstk, stk[nstk].delta);
}
sysfatal("history stack phase error: cannot find line for %d", line);
nstk = 0;
for(h = h0; h->line != -1; h++) {
print("\t%d %d %s\n", h->line, h->off, h->file ? h->file->name : "");
if(h->file == nil)
nstk--;
else if(h->off == 0)
nstk++;
}
}
void
addlib(Link *ctxt, char *src, char *obj)
{
char name[1024], pname[1024], comp[256], *p;
int i, search;
if(ctxt->histfrogp <= 0)
return;
search = 0;
if(ctxt->histfrog[0]->name[1] == '/') {
sprint(name, "");
i = 1;
} else
if(isalpha((uchar)ctxt->histfrog[0]->name[1]) && ctxt->histfrog[0]->name[2] == ':') {
strcpy(name, ctxt->histfrog[0]->name+1);
i = 1;
} else
if(ctxt->histfrog[0]->name[1] == '.') {
sprint(name, ".");
i = 0;
} else {
sprint(name, "");
i = 0;
search = 1;
}
for(; i<ctxt->histfrogp; i++) {
snprint(comp, sizeof comp, "%s", ctxt->histfrog[i]->name+1);
for(;;) {
p = strstr(comp, "$O");
if(p == 0)
break;
memmove(p+1, p+2, strlen(p+2)+1);
p[0] = ctxt->thechar;
}
for(;;) {
p = strstr(comp, "$M");
if(p == 0)
break;
if(strlen(comp)+strlen(ctxt->thestring)-2+1 >= sizeof comp)
sysfatal("library component too long");
memmove(p+strlen(ctxt->thestring), p+2, strlen(p+2)+1);
memmove(p, ctxt->thestring, strlen(ctxt->thestring));
}
if(strlen(name) + strlen(comp) + 3 >= sizeof(name))
sysfatal("library component too long");
if(i > 0 || !search)
strcat(name, "/");
strcat(name, comp);
}
cleanname(name); cleanname(name);
// runtime.a -> runtime // runtime.a -> runtime
...@@ -376,15 +61,12 @@ addlib(Link *ctxt, char *src, char *obj) ...@@ -376,15 +61,12 @@ addlib(Link *ctxt, char *src, char *obj)
if(p != nil) if(p != nil)
*p = '.'; *p = '.';
if(search) {
// try dot, -L "libdir", and then goroot. // try dot, -L "libdir", and then goroot.
for(i=0; i<ctxt->nlibdir; i++) { for(i=0; i<ctxt->nlibdir; i++) {
snprint(pname, sizeof pname, "%s/%s", ctxt->libdir[i], name); snprint(pname, sizeof pname, "%s/%s", ctxt->libdir[i], name);
if(access(pname, AEXIST) >= 0) if(access(pname, AEXIST) >= 0)
break; break;
} }
}else
strcpy(pname, name);
cleanname(pname); cleanname(pname);
/* runtime.a -> runtime */ /* runtime.a -> runtime */
......
...@@ -87,130 +87,81 @@ linklinefmt(Link *ctxt, Fmt *fp) ...@@ -87,130 +87,81 @@ linklinefmt(Link *ctxt, Fmt *fp)
return 0; return 0;
} }
static void // This is a simplified copy of linklinefmt above.
outzfile(Link *ctxt, Biobuf *b, char *p) // It doesn't allow printing the full stack, and it returns the file name and line number separately.
// TODO: Unify with linklinefmt somehow.
void
linkgetline(Link *ctxt, int32 line, LSym **f, int32 *l)
{ {
char *q, *q2; struct
{
Hist* incl; /* start of this include file */
int32 idel; /* delta line number to apply to include */
Hist* line; /* start of this #line directive */
int32 ldel; /* delta line number to apply to #line */
} a[HISTSZ];
int32 lno, d, dlno;
int n;
Hist *h;
char buf[1024], *file;
while(p) { lno = line;
q = utfrune(p, '/'); n = 0;
if(ctxt->windows) { for(h=ctxt->hist; h!=nil; h=h->link) {
q2 = utfrune(p, '\\'); if(h->offset < 0)
if(q2 && (!q || q2 < q)) continue;
q = q2; if(lno < h->line)
break;
if(h->name) {
if(h->offset > 0) {
// #line directive
if(n > 0 && n < HISTSZ) {
a[n-1].line = h;
a[n-1].ldel = h->line - h->offset + 1;
} }
if(!q) { } else {
ctxt->arch->zfile(b, p, strlen(p)); // beginning of file
return; if(n < HISTSZ) {
a[n].incl = h;
a[n].idel = h->line;
a[n].line = 0;
} }
if(q > p) n++;
ctxt->arch->zfile(b, p, q-p);
p = q + 1;
} }
} continue;
#define isdelim(c) (c == '/' || c == '\\')
static void
outwinname(Link *ctxt, Biobuf *b, Hist *h, char *ds, char *p)
{
if(isdelim(p[0])) {
// full rooted name
ctxt->arch->zfile(b, ds, 3); // leading "c:/"
outzfile(ctxt, b, p+1);
} else {
// relative name
if(h->offset >= 0 && ctxt->pathname && ctxt->pathname[1] == ':') {
if(tolowerrune(ds[0]) == tolowerrune(ctxt->pathname[0])) {
// using current drive
ctxt->arch->zfile(b, ctxt->pathname, 3); // leading "c:/"
outzfile(ctxt, b, ctxt->pathname+3);
} else {
// using drive other then current,
// we don't have any simple way to
// determine current working directory
// there, therefore will output name as is
ctxt->arch->zfile(b, ds, 2); // leading "c:"
} }
n--;
if(n > 0 && n < HISTSZ) {
d = h->line - a[n].incl->line;
a[n-1].ldel += d;
a[n-1].idel += d;
} }
outzfile(ctxt, b, p);
} }
}
void if(n > HISTSZ)
linkouthist(Link *ctxt, Biobuf *b) n = HISTSZ;
{
Hist *h;
char *p, ds[] = {'c', ':', '/', 0};
char *tofree;
int n;
static int first = 1;
static char *goroot, *goroot_final;
if(first) { if(n <= 0) {
// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL. *f = linklookup(ctxt, "??", HistVersion);
first = 0; *l = 0;
goroot = getenv("GOROOT"); return;
goroot_final = getenv("GOROOT_FINAL");
if(goroot == nil)
goroot = "";
if(goroot_final == nil)
goroot_final = goroot;
if(strcmp(goroot, goroot_final) == 0) {
goroot = nil;
goroot_final = nil;
}
} }
tofree = nil; n--;
for(h = ctxt->hist; h != nil; h = h->link) { if(a[n].line) {
p = h->name; file = a[n].line->name;
if(p) { dlno = a[n].ldel-1;
if(goroot != nil) {
n = strlen(goroot);
if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
tofree = smprint("%s%s", goroot_final, p+n);
p = tofree;
}
}
if(ctxt->windows) {
// if windows variable is set, then, we know already,
// pathname is started with windows drive specifier
// and all '\' were replaced with '/' (see lex.c)
if(isdelim(p[0]) && isdelim(p[1])) {
// file name has network name in it,
// like \\server\share\dir\file.go
ctxt->arch->zfile(b, "//", 2); // leading "//"
outzfile(ctxt, b, p+2);
} else if(p[1] == ':') {
// file name has drive letter in it
ds[0] = p[0];
outwinname(ctxt, b, h, ds, p+2);
} else {
// no drive letter in file name
outwinname(ctxt, b, h, ctxt->pathname, p);
}
} else {
if(p[0] == '/') {
// full rooted name, like /home/rsc/dir/file.go
ctxt->arch->zfile(b, "/", 1); // leading "/"
outzfile(ctxt, b, p+1);
} else { } else {
// relative name, like dir/file.go file = a[n].incl->name;
if(h->offset >= 0 && ctxt->pathname && ctxt->pathname[0] == '/') { dlno = a[n].idel-1;
ctxt->arch->zfile(b, "/", 1); // leading "/"
outzfile(ctxt, b, ctxt->pathname+1);
}
outzfile(ctxt, b, p);
}
}
}
ctxt->arch->zhist(b, h->line, h->offset);
if(tofree) {
free(tofree);
tofree = nil;
}
} }
if((!ctxt->windows && file[0] == '/') || (ctxt->windows && file[1] == ':'))
snprint(buf, sizeof buf, "%s", file);
else
snprint(buf, sizeof buf, "%s/%s", ctxt->pathname, file);
lno -= dlno;
*f = linklookup(ctxt, buf, HistVersion);
*l = lno;
} }
void void
...@@ -299,105 +250,3 @@ linknewplist(Link *ctxt) ...@@ -299,105 +250,3 @@ linknewplist(Link *ctxt)
return pl; return pl;
} }
static struct {
struct { LSym *sym; short type; } h[NSYM];
int sym;
} z;
static void
zsymreset(void)
{
for(z.sym=0; z.sym<NSYM; z.sym++) {
z.h[z.sym].sym = nil;
z.h[z.sym].type = 0;
}
z.sym = 1;
}
static int
zsym(Link *ctxt, Biobuf *b, LSym *s, int t, int *new)
{
int i;
*new = 0;
if(s == nil)
return 0;
i = s->symid;
if(i < 0 || i >= NSYM)
i = 0;
if(z.h[i].type == t && z.h[i].sym == s)
return i;
i = z.sym;
s->symid = i;
ctxt->arch->zname(b, s, t);
z.h[i].sym = s;
z.h[i].type = t;
if(++z.sym >= NSYM)
z.sym = 1;
*new = 1;
return i;
}
static int
zsymaddr(Link *ctxt, Biobuf *b, Addr *a, int *new)
{
return zsym(ctxt, b, a->sym, ctxt->arch->symtype(a), new);
}
void
linkwritefuncs(Link *ctxt, Biobuf *b)
{
int32 pcloc;
Plist *pl;
LSym *s;
Prog *p;
int sf, st, gf, gt, new;
zsymreset();
// fix up pc
pcloc = 0;
for(pl=ctxt->plist; pl!=nil; pl=pl->link) {
if(pl->name != nil && strcmp(pl->name->name, "_") == 0)
continue;
for(p=pl->firstpc; p!=nil; p=p->link) {
p->loc = pcloc;
if(!ctxt->arch->isdata(p))
pcloc++;
}
}
// put out functions
for(pl=ctxt->plist; pl!=nil; pl=pl->link) {
if(pl->name != nil && strcmp(pl->name->name, "_") == 0)
continue;
// -S prints code; -S -S prints code and data
if(ctxt->debugasm && (pl->name || ctxt->debugasm>1)) {
s = pl->name;
print("\n--- prog list \"%lS\" ---\n", s);
for(p=pl->firstpc; p!=nil; p=p->link)
print("%P\n", p);
}
for(p=pl->firstpc; p!=nil; p=p->link) {
for(;;) {
sf = zsymaddr(ctxt, b, &p->from, &new);
gf = zsym(ctxt, b, p->from.gotype, ctxt->arch->D_EXTERN, &new);
if(new && sf == gf)
continue;
st = zsymaddr(ctxt, b, &p->to, &new);
if(new && (st == sf || st == gf))
continue;
gt = zsym(ctxt, b, p->to.gotype, ctxt->arch->D_EXTERN, &new);
if(new && (gt == sf || gt == gf || gt == st))
continue;
break;
}
ctxt->arch->zprog(ctxt, b, p, sf, gf, st, gt);
}
}
}
...@@ -35,12 +35,6 @@ ...@@ -35,12 +35,6 @@
#include "../cmd/5l/5.out.h" #include "../cmd/5l/5.out.h"
#include "../pkg/runtime/stack.h" #include "../pkg/runtime/stack.h"
static Addr noaddr = {
.type = D_NONE,
.name = D_NONE,
.reg = NREG,
};
static Prog zprg = { static Prog zprg = {
.as = AGOK, .as = AGOK,
.scond = 14, .scond = 14,
...@@ -57,142 +51,12 @@ static Prog zprg = { ...@@ -57,142 +51,12 @@ static Prog zprg = {
}, },
}; };
static void
zname(Biobuf *b, LSym *s, int t)
{
BPUTC(b, ANAME); /* as */
BPUTC(b, t); /* type */
BPUTC(b, s->symid); /* sym */
Bwrite(b, s->name, strlen(s->name)+1);
}
static void
zfile(Biobuf *b, char *p, int n)
{
BPUTC(b, ANAME);
BPUTC(b, D_FILE);
BPUTC(b, 1);
BPUTC(b, '<');
Bwrite(b, p, n);
BPUTC(b, 0);
}
static void
zaddr(Biobuf *b, Addr *a, int s, int gotype)
{
int32 l;
uint64 e;
int i;
char *n;
switch(a->type) {
case D_STATIC:
case D_AUTO:
case D_EXTERN:
case D_PARAM:
// TODO(kaib): remove once everything seems to work
sysfatal("We should no longer generate these as types");
default:
BPUTC(b, a->type);
BPUTC(b, a->reg);
BPUTC(b, s);
BPUTC(b, a->name);
BPUTC(b, gotype);
}
switch(a->type) {
default:
print("unknown type %d in zaddr\n", a->type);
case D_NONE:
case D_REG:
case D_FREG:
case D_PSR:
break;
case D_CONST2:
l = a->offset2;
BPUTLE4(b, l); // fall through
case D_OREG:
case D_CONST:
case D_SHIFT:
case D_STATIC:
case D_AUTO:
case D_EXTERN:
case D_PARAM:
l = a->offset;
BPUTLE4(b, l);
break;
case D_BRANCH:
if(a->offset == 0 || a->u.branch != nil) {
if(a->u.branch == nil)
sysfatal("unpatched branch %D", a);
a->offset = a->u.branch->loc;
}
l = a->offset;
BPUTLE4(b, l);
break;
case D_SCONST:
n = a->u.sval;
for(i=0; i<NSNAME; i++) {
BPUTC(b, *n);
n++;
}
break;
case D_REGREG:
case D_REGREG2:
BPUTC(b, a->offset);
break;
case D_FCONST:
double2ieee(&e, a->u.dval);
BPUTLE4(b, e);
BPUTLE4(b, e >> 32);
break;
}
}
static void
zhist(Biobuf *b, int line, vlong offset)
{
Addr a;
BPUTC(b, AHISTORY);
BPUTC(b, C_SCOND_NONE);
BPUTC(b, NREG);
BPUTLE4(b, line);
zaddr(b, &noaddr, 0, 0);
a = noaddr;
if(offset != 0) {
a.offset = offset;
a.type = D_CONST;
}
zaddr(b, &a, 0, 0);
}
static int static int
symtype(Addr *a) symtype(Addr *a)
{ {
return a->name; return a->name;
} }
static void
zprog(Link *ctxt, Biobuf *b, Prog *p, int sf, int gf, int st, int gt)
{
USED(ctxt);
BPUTC(b, p->as);
BPUTC(b, p->scond);
BPUTC(b, p->reg);
BPUTLE4(b, p->lineno);
zaddr(b, &p->from, sf, gf);
zaddr(b, &p->to, st, gt);
}
static int static int
isdata(Prog *p) isdata(Prog *p)
{ {
...@@ -223,6 +87,68 @@ settextflag(Prog *p, int f) ...@@ -223,6 +87,68 @@ settextflag(Prog *p, int f)
p->reg = f; p->reg = f;
} }
static void
progedit(Link *ctxt, Prog *p)
{
char literal[64];
LSym *s;
p->from.class = 0;
p->to.class = 0;
// Rewrite B/BL to symbol as D_BRANCH.
switch(p->as) {
case AB:
case ABL:
if(p->to.type == D_OREG && (p->to.name == D_EXTERN || p->to.name == D_STATIC) && p->to.sym != nil)
p->to.type = D_BRANCH;
break;
}
// Rewrite float constants to values stored in memory.
switch(p->as) {
case AMOVF:
if(p->from.type == D_FCONST && chipfloat5(ctxt, p->from.u.dval) < 0 &&
(chipzero5(ctxt, p->from.u.dval) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) {
int32 i32;
float32 f32;
f32 = p->from.u.dval;
memmove(&i32, &f32, 4);
sprint(literal, "$f32.%08ux", (uint32)i32);
s = linklookup(ctxt, literal, 0);
if(s->type == 0) {
s->type = SRODATA;
adduint32(ctxt, s, i32);
s->reachable = 0;
}
p->from.type = D_OREG;
p->from.sym = s;
p->from.name = D_EXTERN;
p->from.offset = 0;
}
break;
case AMOVD:
if(p->from.type == D_FCONST && chipfloat5(ctxt, p->from.u.dval) < 0 &&
(chipzero5(ctxt, p->from.u.dval) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) {
int64 i64;
memmove(&i64, &p->from.u.dval, 8);
sprint(literal, "$f64.%016llux", (uvlong)i64);
s = linklookup(ctxt, literal, 0);
if(s->type == 0) {
s->type = SRODATA;
adduint64(ctxt, s, i64);
s->reachable = 0;
}
p->from.type = D_OREG;
p->from.sym = s;
p->from.name = D_EXTERN;
p->from.offset = 0;
}
break;
}
}
static Prog* static Prog*
prg(void) prg(void)
{ {
...@@ -293,11 +219,14 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -293,11 +219,14 @@ addstacksplit(Link *ctxt, LSym *cursym)
softfloat(ctxt, cursym); softfloat(ctxt, cursym);
if(ctxt->debugzerostack) {
p = cursym->text; p = cursym->text;
autoffset = p->to.offset; autoffset = p->to.offset;
if(autoffset < 0) if(autoffset < 0)
autoffset = 0; autoffset = 0;
cursym->locals = autoffset;
cursym->args = p->to.offset2;
if(ctxt->debugzerostack) {
if(autoffset && !(p->reg&NOSPLIT)) { if(autoffset && !(p->reg&NOSPLIT)) {
// MOVW $4(R13), R1 // MOVW $4(R13), R1
p = appendp(ctxt, p); p = appendp(ctxt, p);
...@@ -427,15 +356,10 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -427,15 +356,10 @@ addstacksplit(Link *ctxt, LSym *cursym)
if(ctxt->headtype == Hopenbsd) { if(ctxt->headtype == Hopenbsd) {
p->as = ARET; p->as = ARET;
} else if(ctxt->goarm < 7) { } else if(ctxt->goarm < 7) {
if(tlsfallback->type != STEXT) {
ctxt->diag("runtime·read_tls_fallback not defined");
sysfatal("tlsfallback");
}
// BL runtime.read_tls_fallback(SB) // BL runtime.read_tls_fallback(SB)
p->as = ABL; p->as = ABL;
p->to.type = D_BRANCH; p->to.type = D_BRANCH;
p->to.sym = tlsfallback; p->to.sym = tlsfallback;
p->pcond = tlsfallback->text;
p->to.offset = 0; p->to.offset = 0;
cursym->text->mark &= ~LEAF; cursym->text->mark &= ~LEAF;
} }
...@@ -578,7 +502,6 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -578,7 +502,6 @@ addstacksplit(Link *ctxt, LSym *cursym)
p->from = zprg.from; p->from = zprg.from;
if(p->to.sym) { // retjmp if(p->to.sym) { // retjmp
p->to.type = D_BRANCH; p->to.type = D_BRANCH;
p->pcond = p->to.sym->text;
} else { } else {
p->to.type = D_OREG; p->to.type = D_OREG;
p->to.offset = 0; p->to.offset = 0;
...@@ -643,7 +566,6 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -643,7 +566,6 @@ addstacksplit(Link *ctxt, LSym *cursym)
q2->as = AB; q2->as = AB;
q2->to.type = D_BRANCH; q2->to.type = D_BRANCH;
q2->to.sym = p->to.sym; q2->to.sym = p->to.sym;
q2->pcond = p->to.sym->text;
p->to.sym = nil; p->to.sym = nil;
p = q2; p = q2;
} }
...@@ -698,7 +620,6 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -698,7 +620,6 @@ addstacksplit(Link *ctxt, LSym *cursym)
p->as = ABL; p->as = ABL;
p->lineno = q1->lineno; p->lineno = q1->lineno;
p->to.type = D_BRANCH; p->to.type = D_BRANCH;
p->pcond = p;
switch(o) { switch(o) {
case ADIV: case ADIV:
p->to.sym = ctxt->sym_div; p->to.sym = ctxt->sym_div;
...@@ -775,17 +696,14 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -775,17 +696,14 @@ addstacksplit(Link *ctxt, LSym *cursym)
static void static void
softfloat(Link *ctxt, LSym *cursym) softfloat(Link *ctxt, LSym *cursym)
{ {
Prog *p, *next, *psfloat; Prog *p, *next;
LSym *symsfloat; LSym *symsfloat;
int wasfloat; int wasfloat;
if(!ctxt->debugfloat) if(ctxt->goarm > 5)
return; return;
symsfloat = linklookup(ctxt, "_sfloat", 0); symsfloat = linklookup(ctxt, "_sfloat", 0);
psfloat = nil;
if(symsfloat->type == STEXT)
psfloat = symsfloat->text;
wasfloat = 0; wasfloat = 0;
for(p = cursym->text; p != nil; p = p->link) for(p = cursym->text; p != nil; p = p->link)
...@@ -827,8 +745,6 @@ softfloat(Link *ctxt, LSym *cursym) ...@@ -827,8 +745,6 @@ softfloat(Link *ctxt, LSym *cursym)
goto notsoft; goto notsoft;
soft: soft:
if (psfloat == nil)
ctxt->diag("floats used with _sfloat not defined");
if (!wasfloat || (p->mark&LABEL)) { if (!wasfloat || (p->mark&LABEL)) {
next = ctxt->arch->prg(); next = ctxt->arch->prg();
*next = *p; *next = *p;
...@@ -839,7 +755,6 @@ softfloat(Link *ctxt, LSym *cursym) ...@@ -839,7 +755,6 @@ softfloat(Link *ctxt, LSym *cursym)
p->as = ABL; p->as = ABL;
p->to.type = D_BRANCH; p->to.type = D_BRANCH;
p->to.sym = symsfloat; p->to.sym = symsfloat;
p->pcond = psfloat;
p->lineno = next->lineno; p->lineno = next->lineno;
p = next; p = next;
...@@ -1145,6 +1060,7 @@ loop: ...@@ -1145,6 +1060,7 @@ loop:
LinkArch linkarm = { LinkArch linkarm = {
.name = "arm", .name = "arm",
.thechar = '5',
.addstacksplit = addstacksplit, .addstacksplit = addstacksplit,
.assemble = span5, .assemble = span5,
...@@ -1152,16 +1068,11 @@ LinkArch linkarm = { ...@@ -1152,16 +1068,11 @@ LinkArch linkarm = {
.follow = follow, .follow = follow,
.iscall = iscall, .iscall = iscall,
.isdata = isdata, .isdata = isdata,
.ldobj = ldobj5,
.nopout = nopout5,
.prg = prg, .prg = prg,
.progedit = progedit,
.settextflag = settextflag, .settextflag = settextflag,
.symtype = symtype, .symtype = symtype,
.textflag = textflag, .textflag = textflag,
.zfile = zfile,
.zhist = zhist,
.zname = zname,
.zprog = zprog,
.minlc = 4, .minlc = 4,
.ptrsize = 4, .ptrsize = 4,
...@@ -1175,13 +1086,18 @@ LinkArch linkarm = { ...@@ -1175,13 +1086,18 @@ LinkArch linkarm = {
.D_PCREL = D_PCREL, .D_PCREL = D_PCREL,
.D_SCONST = D_SCONST, .D_SCONST = D_SCONST,
.D_SIZE = D_SIZE, .D_SIZE = D_SIZE,
.D_STATIC = D_STATIC,
.ACALL = ABL, .ACALL = ABL,
.ADATA = ADATA,
.AEND = AEND,
.AFUNCDATA = AFUNCDATA, .AFUNCDATA = AFUNCDATA,
.AGLOBL = AGLOBL,
.AJMP = AB, .AJMP = AB,
.ANOP = ANOP, .ANOP = ANOP,
.APCDATA = APCDATA, .APCDATA = APCDATA,
.ARET = ARET, .ARET = ARET,
.ATEXT = ATEXT, .ATEXT = ATEXT,
.ATYPE = ATYPE,
.AUSEFIELD = AUSEFIELD, .AUSEFIELD = AUSEFIELD,
}; };
...@@ -35,12 +35,6 @@ ...@@ -35,12 +35,6 @@
#include "../cmd/6l/6.out.h" #include "../cmd/6l/6.out.h"
#include "../pkg/runtime/stack.h" #include "../pkg/runtime/stack.h"
static Addr noaddr = {
.type = D_NONE,
.index = D_NONE,
.scale = 0,
};
static Prog zprg = { static Prog zprg = {
.back = 2, .back = 2,
.as = AGOK, .as = AGOK,
...@@ -55,118 +49,11 @@ static Prog zprg = { ...@@ -55,118 +49,11 @@ static Prog zprg = {
}; };
static void static void
zname(Biobuf *b, LSym *s, int t) nopout(Prog *p)
{
BPUTLE2(b, ANAME); /* as */
BPUTC(b, t); /* type */
BPUTC(b, s->symid); /* sym */
Bwrite(b, s->name, strlen(s->name)+1);
}
static void
zfile(Biobuf *b, char *p, int n)
{
BPUTLE2(b, ANAME);
BPUTC(b, D_FILE);
BPUTC(b, 1);
BPUTC(b, '<');
Bwrite(b, p, n);
BPUTC(b, 0);
}
static void
zaddr(Biobuf *b, Addr *a, int s, int gotype)
{ {
int32 l; p->as = ANOP;
uint64 e; p->from.type = D_NONE;
int i, t; p->to.type = D_NONE;
char *n;
t = 0;
if(a->index != D_NONE || a->scale != 0)
t |= T_INDEX;
if(s != 0)
t |= T_SYM;
if(gotype != 0)
t |= T_GOTYPE;
switch(a->type) {
case D_BRANCH:
if(a->offset == 0 || a->u.branch != nil) {
if(a->u.branch == nil)
sysfatal("unpatched branch %D", a);
a->offset = a->u.branch->loc;
}
default:
t |= T_TYPE;
case D_NONE:
if(a->offset != 0) {
t |= T_OFFSET;
l = a->offset;
if((vlong)l != a->offset)
t |= T_64;
}
break;
case D_FCONST:
t |= T_FCONST;
break;
case D_SCONST:
t |= T_SCONST;
break;
}
BPUTC(b, t);
if(t & T_INDEX) { /* implies index, scale */
BPUTC(b, a->index);
BPUTC(b, a->scale);
}
if(t & T_OFFSET) { /* implies offset */
l = a->offset;
BPUTLE4(b, l);
if(t & T_64) {
l = a->offset>>32;
BPUTLE4(b, l);
}
}
if(t & T_SYM) /* implies sym */
BPUTC(b, s);
if(t & T_FCONST) {
double2ieee(&e, a->u.dval);
BPUTLE4(b, e);
BPUTLE4(b, e >> 32);
return;
}
if(t & T_SCONST) {
n = a->u.sval;
for(i=0; i<NSNAME; i++) {
BPUTC(b, *n);
n++;
}
return;
}
if(t & T_TYPE)
BPUTC(b, a->type);
if(t & T_GOTYPE)
BPUTC(b, gotype);
}
static void
zhist(Biobuf *b, int line, vlong offset)
{
Addr a;
BPUTLE2(b, AHISTORY);
BPUTLE4(b, line);
zaddr(b, &noaddr, 0, 0);
a = noaddr;
if(offset != 0) {
a.offset = offset;
a.type = D_CONST;
}
zaddr(b, &a, 0, 0);
} }
static int static int
...@@ -180,17 +67,6 @@ symtype(Addr *a) ...@@ -180,17 +67,6 @@ symtype(Addr *a)
return t; return t;
} }
static void
zprog(Link *ctxt, Biobuf *b, Prog *p, int sf, int gf, int st, int gt)
{
USED(ctxt);
BPUTLE2(b, p->as);
BPUTLE4(b, p->lineno);
zaddr(b, &p->from, sf, gf);
zaddr(b, &p->to, st, gt);
}
static int static int
isdata(Prog *p) isdata(Prog *p)
{ {
...@@ -224,8 +100,15 @@ settextflag(Prog *p, int f) ...@@ -224,8 +100,15 @@ settextflag(Prog *p, int f)
static void static void
progedit(Link *ctxt, Prog *p) progedit(Link *ctxt, Prog *p)
{ {
char literal[64];
LSym *s;
Prog *q; Prog *q;
if(p->from.type == D_INDIR+D_GS || p->from.index == D_GS)
p->from.offset += ctxt->tlsoffset;
if(p->to.type == D_INDIR+D_GS || p->to.index == D_GS)
p->to.offset += ctxt->tlsoffset;
if(ctxt->gmsym == nil) if(ctxt->gmsym == nil)
ctxt->gmsym = linklookup(ctxt, "runtime.tlsgm", 0); ctxt->gmsym = linklookup(ctxt, "runtime.tlsgm", 0);
...@@ -313,6 +196,105 @@ progedit(Link *ctxt, Prog *p) ...@@ -313,6 +196,105 @@ progedit(Link *ctxt, Prog *p)
p->from.offset = 0; p->from.offset = 0;
} }
} }
// Maintain information about code generation mode.
if(ctxt->mode == 0)
ctxt->mode = 64;
p->mode = ctxt->mode;
switch(p->as) {
case AMODE:
if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE) {
switch((int)p->from.offset) {
case 16:
case 32:
case 64:
ctxt->mode = p->from.offset;
break;
}
}
nopout(p);
break;
}
// Rewrite CALL/JMP/RET to symbol as D_BRANCH.
switch(p->as) {
case ACALL:
case AJMP:
case ARET:
if((p->to.type == D_EXTERN || p->to.type == D_STATIC) && p->to.sym != nil)
p->to.type = D_BRANCH;
break;
}
// Rewrite float constants to values stored in memory.
switch(p->as) {
case AFMOVF:
case AFADDF:
case AFSUBF:
case AFSUBRF:
case AFMULF:
case AFDIVF:
case AFDIVRF:
case AFCOMF:
case AFCOMFP:
case AMOVSS:
case AADDSS:
case ASUBSS:
case AMULSS:
case ADIVSS:
case ACOMISS:
case AUCOMISS:
if(p->from.type == D_FCONST) {
int32 i32;
float32 f32;
f32 = p->from.u.dval;
memmove(&i32, &f32, 4);
sprint(literal, "$f32.%08ux", (uint32)i32);
s = linklookup(ctxt, literal, 0);
if(s->type == 0) {
s->type = SRODATA;
adduint32(ctxt, s, i32);
s->reachable = 0;
}
p->from.type = D_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
break;
case AFMOVD:
case AFADDD:
case AFSUBD:
case AFSUBRD:
case AFMULD:
case AFDIVD:
case AFDIVRD:
case AFCOMD:
case AFCOMDP:
case AMOVSD:
case AADDSD:
case ASUBSD:
case AMULSD:
case ADIVSD:
case ACOMISD:
case AUCOMISD:
if(p->from.type == D_FCONST) {
int64 i64;
memmove(&i64, &p->from.u.dval, 8);
sprint(literal, "$f64.%016llux", (uvlong)i64);
s = linklookup(ctxt, literal, 0);
if(s->type == 0) {
s->type = SRODATA;
adduint64(ctxt, s, i64);
s->reachable = 0;
}
p->from.type = D_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
break;
}
} }
static char* static char*
...@@ -375,6 +357,9 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -375,6 +357,9 @@ addstacksplit(Link *ctxt, LSym *cursym)
if(autoffset < 0) if(autoffset < 0)
autoffset = 0; autoffset = 0;
cursym->args = p->to.offset>>32;
cursym->locals = textstksiz;
if(autoffset < StackSmall && !(p->from.scale & NOSPLIT)) { if(autoffset < StackSmall && !(p->from.scale & NOSPLIT)) {
for(q = p; q != nil; q = q->link) for(q = p; q != nil; q = q->link)
if(q->as == ACALL) if(q->as == ACALL)
...@@ -1033,24 +1018,19 @@ prg(void) ...@@ -1033,24 +1018,19 @@ prg(void)
LinkArch linkamd64 = { LinkArch linkamd64 = {
.name = "amd64", .name = "amd64",
.thechar = '6',
.zprog = zprog,
.zhist = zhist,
.zfile = zfile,
.zname = zname,
.isdata = isdata,
.ldobj = ldobj6,
.nopout = nopout6,
.symtype = symtype,
.iscall = iscall,
.datasize = datasize,
.textflag = textflag,
.settextflag = settextflag,
.progedit = progedit,
.prg = prg,
.addstacksplit = addstacksplit, .addstacksplit = addstacksplit,
.assemble = span6, .assemble = span6,
.datasize = datasize,
.follow = follow, .follow = follow,
.iscall = iscall,
.isdata = isdata,
.prg = prg,
.progedit = progedit,
.settextflag = settextflag,
.symtype = symtype,
.textflag = textflag,
.minlc = 1, .minlc = 1,
.ptrsize = 8, .ptrsize = 8,
...@@ -1064,13 +1044,18 @@ LinkArch linkamd64 = { ...@@ -1064,13 +1044,18 @@ LinkArch linkamd64 = {
.D_PCREL = D_PCREL, .D_PCREL = D_PCREL,
.D_SCONST = D_SCONST, .D_SCONST = D_SCONST,
.D_SIZE = D_SIZE, .D_SIZE = D_SIZE,
.D_STATIC = D_STATIC,
.ACALL = ACALL, .ACALL = ACALL,
.ADATA = ADATA,
.AEND = AEND,
.AFUNCDATA = AFUNCDATA, .AFUNCDATA = AFUNCDATA,
.AGLOBL = AGLOBL,
.AJMP = AJMP, .AJMP = AJMP,
.ANOP = ANOP, .ANOP = ANOP,
.APCDATA = APCDATA, .APCDATA = APCDATA,
.ARET = ARET, .ARET = ARET,
.ATEXT = ATEXT, .ATEXT = ATEXT,
.ATYPE = ATYPE,
.AUSEFIELD = AUSEFIELD, .AUSEFIELD = AUSEFIELD,
}; };
...@@ -35,12 +35,6 @@ ...@@ -35,12 +35,6 @@
#include "../cmd/8l/8.out.h" #include "../cmd/8l/8.out.h"
#include "../pkg/runtime/stack.h" #include "../pkg/runtime/stack.h"
static Addr noaddr = {
.type = D_NONE,
.index = D_NONE,
.scale = 1,
};
static Prog zprg = { static Prog zprg = {
.back = 2, .back = 2,
.as = AGOK, .as = AGOK,
...@@ -56,119 +50,6 @@ static Prog zprg = { ...@@ -56,119 +50,6 @@ static Prog zprg = {
}, },
}; };
static void
zname(Biobuf *b, LSym *s, int t)
{
BPUTLE2(b, ANAME); /* as */
BPUTC(b, t); /* type */
BPUTC(b, s->symid); /* sym */
Bwrite(b, s->name, strlen(s->name)+1);
}
static void
zfile(Biobuf *b, char *p, int n)
{
BPUTLE2(b, ANAME);
BPUTC(b, D_FILE);
BPUTC(b, 1);
BPUTC(b, '<');
Bwrite(b, p, n);
BPUTC(b, 0);
}
static void
zaddr(Biobuf *b, Addr *a, int s, int gotype)
{
int32 l;
uint64 e;
int i, t;
char *n;
t = 0;
if(a->index != D_NONE || a->scale != 0)
t |= T_INDEX;
if(s != 0)
t |= T_SYM;
if(gotype != 0)
t |= T_GOTYPE;
switch(a->type) {
case D_BRANCH:
if(a->offset == 0 || a->u.branch != nil) {
if(a->u.branch == nil)
sysfatal("unpatched branch %D", a);
a->offset = a->u.branch->loc;
}
default:
t |= T_TYPE;
case D_NONE:
if(a->offset != 0)
t |= T_OFFSET;
if(a->offset2 != 0)
t |= T_OFFSET2;
break;
case D_FCONST:
t |= T_FCONST;
break;
case D_SCONST:
t |= T_SCONST;
break;
}
BPUTC(b, t);
if(t & T_INDEX) { /* implies index, scale */
BPUTC(b, a->index);
BPUTC(b, a->scale);
}
if(t & T_OFFSET) { /* implies offset */
l = a->offset;
BPUTLE4(b, l);
}
if(t & T_OFFSET2) { /* implies offset */
l = a->offset2;
BPUTLE4(b, l);
}
if(t & T_SYM) /* implies sym */
BPUTC(b, s);
if(t & T_FCONST) {
double2ieee(&e, a->u.dval);
BPUTLE4(b, e);
BPUTLE4(b, e >> 32);
return;
}
if(t & T_SCONST) {
n = a->u.sval;
for(i=0; i<NSNAME; i++) {
BPUTC(b, *n);
n++;
}
return;
}
if(t & T_TYPE)
BPUTC(b, a->type);
if(t & T_GOTYPE)
BPUTC(b, gotype);
}
static void
zhist(Biobuf *b, int line, vlong offset)
{
Addr a;
BPUTLE2(b, AHISTORY);
BPUTLE4(b, line);
zaddr(b, &noaddr, 0, 0);
a = noaddr;
if(offset != 0) {
a.offset = offset;
a.type = D_CONST;
}
zaddr(b, &a, 0, 0);
}
static int static int
symtype(Addr *a) symtype(Addr *a)
{ {
...@@ -180,17 +61,6 @@ symtype(Addr *a) ...@@ -180,17 +61,6 @@ symtype(Addr *a)
return t; return t;
} }
static void
zprog(Link *ctxt, Biobuf *b, Prog *p, int sf, int gf, int st, int gt)
{
USED(ctxt);
BPUTLE2(b, p->as);
BPUTLE4(b, p->lineno);
zaddr(b, &p->from, sf, gf);
zaddr(b, &p->to, st, gt);
}
static int static int
isdata(Prog *p) isdata(Prog *p)
{ {
...@@ -225,6 +95,13 @@ static void ...@@ -225,6 +95,13 @@ static void
progedit(Link *ctxt, Prog *p) progedit(Link *ctxt, Prog *p)
{ {
Prog *q; Prog *q;
char literal[64];
LSym *s;
if(p->from.type == D_INDIR+D_GS)
p->from.offset += ctxt->tlsoffset;
if(p->to.type == D_INDIR+D_GS)
p->to.offset += ctxt->tlsoffset;
if(ctxt->headtype == Hwindows) { if(ctxt->headtype == Hwindows) {
// Convert // Convert
...@@ -287,6 +164,85 @@ progedit(Link *ctxt, Prog *p) ...@@ -287,6 +164,85 @@ progedit(Link *ctxt, Prog *p)
p->from.offset = 0; p->from.offset = 0;
} }
} }
// Rewrite CALL/JMP/RET to symbol as D_BRANCH.
switch(p->as) {
case ACALL:
case AJMP:
case ARET:
if((p->to.type == D_EXTERN || p->to.type == D_STATIC) && p->to.sym != nil)
p->to.type = D_BRANCH;
break;
}
// Rewrite float constants to values stored in memory.
switch(p->as) {
case AFMOVF:
case AFADDF:
case AFSUBF:
case AFSUBRF:
case AFMULF:
case AFDIVF:
case AFDIVRF:
case AFCOMF:
case AFCOMFP:
case AMOVSS:
case AADDSS:
case ASUBSS:
case AMULSS:
case ADIVSS:
case ACOMISS:
case AUCOMISS:
if(p->from.type == D_FCONST) {
int32 i32;
float32 f32;
f32 = p->from.u.dval;
memmove(&i32, &f32, 4);
sprint(literal, "$f32.%08ux", (uint32)i32);
s = linklookup(ctxt, literal, 0);
if(s->type == 0) {
s->type = SRODATA;
adduint32(ctxt, s, i32);
s->reachable = 0;
}
p->from.type = D_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
break;
case AFMOVD:
case AFADDD:
case AFSUBD:
case AFSUBRD:
case AFMULD:
case AFDIVD:
case AFDIVRD:
case AFCOMD:
case AFCOMDP:
case AMOVSD:
case AADDSD:
case ASUBSD:
case AMULSD:
case ADIVSD:
case ACOMISD:
case AUCOMISD:
if(p->from.type == D_FCONST) {
int64 i64;
memmove(&i64, &p->from.u.dval, 8);
sprint(literal, "$f64.%016llux", (uvlong)i64);
s = linklookup(ctxt, literal, 0);
if(s->type == 0) {
s->type = SRODATA;
adduint64(ctxt, s, i64);
s->reachable = 0;
}
p->from.type = D_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
break;
}
} }
static Prog* static Prog*
...@@ -325,6 +281,9 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -325,6 +281,9 @@ addstacksplit(Link *ctxt, LSym *cursym)
if(autoffset < 0) if(autoffset < 0)
autoffset = 0; autoffset = 0;
cursym->locals = autoffset;
cursym->args = p->to.offset2;
q = nil; q = nil;
if(!(p->from.scale & NOSPLIT) || (p->from.scale & WRAPPER)) { if(!(p->from.scale & NOSPLIT) || (p->from.scale & WRAPPER)) {
...@@ -894,6 +853,7 @@ loop: ...@@ -894,6 +853,7 @@ loop:
LinkArch link386 = { LinkArch link386 = {
.name = "386", .name = "386",
.thechar = '8',
.addstacksplit = addstacksplit, .addstacksplit = addstacksplit,
.assemble = span8, .assemble = span8,
...@@ -901,17 +861,11 @@ LinkArch link386 = { ...@@ -901,17 +861,11 @@ LinkArch link386 = {
.follow = follow, .follow = follow,
.iscall = iscall, .iscall = iscall,
.isdata = isdata, .isdata = isdata,
.ldobj = ldobj8,
.nopout = nopout8,
.prg = prg, .prg = prg,
.progedit = progedit, .progedit = progedit,
.settextflag = settextflag, .settextflag = settextflag,
.symtype = symtype, .symtype = symtype,
.textflag = textflag, .textflag = textflag,
.zfile = zfile,
.zhist = zhist,
.zname = zname,
.zprog = zprog,
.minlc = 1, .minlc = 1,
.ptrsize = 4, .ptrsize = 4,
...@@ -925,13 +879,18 @@ LinkArch link386 = { ...@@ -925,13 +879,18 @@ LinkArch link386 = {
.D_PCREL = D_PCREL, .D_PCREL = D_PCREL,
.D_SCONST = D_SCONST, .D_SCONST = D_SCONST,
.D_SIZE = D_SIZE, .D_SIZE = D_SIZE,
.D_STATIC = D_STATIC,
.ACALL = ACALL, .ACALL = ACALL,
.ADATA = ADATA,
.AEND = AEND,
.AFUNCDATA = AFUNCDATA, .AFUNCDATA = AFUNCDATA,
.AGLOBL = AGLOBL,
.AJMP = AJMP, .AJMP = AJMP,
.ANOP = ANOP, .ANOP = ANOP,
.APCDATA = APCDATA, .APCDATA = APCDATA,
.ARET = ARET, .ARET = ARET,
.ATEXT = ATEXT, .ATEXT = ATEXT,
.ATYPE = ATYPE,
.AUSEFIELD = AUSEFIELD, .AUSEFIELD = AUSEFIELD,
}; };
This diff is collapsed.
...@@ -70,22 +70,20 @@ linkpatch(Link *ctxt, LSym *sym) ...@@ -70,22 +70,20 @@ linkpatch(Link *ctxt, LSym *sym)
{ {
int32 c; int32 c;
Prog *p, *q; Prog *p, *q;
LSym *s;
ctxt->cursym = sym; ctxt->cursym = sym;
for(p = sym->text; p != nil; p = p->link) { for(p = sym->text; p != nil; p = p->link) {
if(ctxt->arch->progedit) if(ctxt->arch->progedit)
ctxt->arch->progedit(ctxt, p); ctxt->arch->progedit(ctxt, p);
if(p->as == ctxt->arch->ACALL || (p->as == ctxt->arch->AJMP && p->to.type != ctxt->arch->D_BRANCH) || (p->as == ctxt->arch->ARET && p->to.sym != nil)) { if(p->to.type != ctxt->arch->D_BRANCH)
s = p->to.sym; continue;
// The STEXT check avoids rewriting indirect call to addr in memory on x86. if(p->to.u.branch != nil) {
if(s && s->type == STEXT) { // TODO: Remove to.u.branch in favor of p->pcond.
p->to.type = ctxt->arch->D_BRANCH; p->pcond = p->to.u.branch;
continue; continue;
} }
} if(p->to.sym != nil)
if(p->to.type != ctxt->arch->D_BRANCH)
continue; continue;
c = p->to.offset; c = p->to.offset;
for(q = sym->text; q != nil;) { for(q = sym->text; q != nil;) {
...@@ -101,6 +99,7 @@ linkpatch(Link *ctxt, LSym *sym) ...@@ -101,6 +99,7 @@ linkpatch(Link *ctxt, LSym *sym)
c, p, p->to.sym ? p->to.sym->name : "<nil>"); c, p, p->to.sym ? p->to.sym->name : "<nil>");
p->to.type = ctxt->arch->D_NONE; p->to.type = ctxt->arch->D_NONE;
} }
p->to.u.branch = q;
p->pcond = q; p->pcond = q;
} }
......
...@@ -66,8 +66,10 @@ funcpctab(Link *ctxt, Pcdata *dst, LSym *func, char *desc, int32 (*valfunc)(Link ...@@ -66,8 +66,10 @@ funcpctab(Link *ctxt, Pcdata *dst, LSym *func, char *desc, int32 (*valfunc)(Link
val = -1; val = -1;
oldval = val; oldval = val;
if(func->text == nil) if(func->text == nil) {
ctxt->debugpcln -= dbg;
return; return;
}
pc = func->text->pc; pc = func->text->pc;
...@@ -156,9 +158,11 @@ pctofileline(Link *ctxt, LSym *sym, int32 oldval, Prog *p, int32 phase, void *ar ...@@ -156,9 +158,11 @@ pctofileline(Link *ctxt, LSym *sym, int32 oldval, Prog *p, int32 phase, void *ar
LSym *f; LSym *f;
Pcln *pcln; Pcln *pcln;
USED(sym);
if(p->as == ctxt->arch->ATEXT || p->as == ctxt->arch->ANOP || p->as == ctxt->arch->AUSEFIELD || p->lineno == 0 || phase == 1) if(p->as == ctxt->arch->ATEXT || p->as == ctxt->arch->ANOP || p->as == ctxt->arch->AUSEFIELD || p->lineno == 0 || phase == 1)
return oldval; return oldval;
linkgetline(ctxt, sym->hist, p->lineno, &f, &l); linkgetline(ctxt, p->lineno, &f, &l);
if(f == nil) { if(f == nil) {
// print("getline failed for %s %P\n", ctxt->cursym->name, p); // print("getline failed for %s %P\n", ctxt->cursym->name, p);
return oldval; return oldval;
...@@ -296,3 +300,65 @@ linkpcln(Link *ctxt, LSym *cursym) ...@@ -296,3 +300,65 @@ linkpcln(Link *ctxt, LSym *cursym)
} }
} }
} }
// iteration over encoded pcdata tables.
static uint32
getvarint(uchar **pp)
{
uchar *p;
int shift;
uint32 v;
v = 0;
p = *pp;
for(shift = 0;; shift += 7) {
v |= (*p & 0x7F) << shift;
if(!(*p++ & 0x80))
break;
}
*pp = p;
return v;
}
void
pciternext(Pciter *it)
{
uint32 v;
int32 dv;
it->pc = it->nextpc;
if(it->done)
return;
if(it->p >= it->d.p + it->d.n) {
it->done = 1;
return;
}
// value delta
v = getvarint(&it->p);
if(v == 0 && !it->start) {
it->done = 1;
return;
}
it->start = 0;
dv = (int32)(v>>1) ^ ((int32)(v<<31)>>31);
it->value += dv;
// pc delta
v = getvarint(&it->p);
it->nextpc = it->pc + v;
}
void
pciterinit(Pciter *it, Pcdata *d)
{
it->d = *d;
it->p = it->d.p;
it->pc = 0;
it->nextpc = 0;
it->value = -1;
it->start = 1;
it->done = 0;
pciternext(it);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -40,6 +40,47 @@ yy_isalpha(int c) ...@@ -40,6 +40,47 @@ yy_isalpha(int c)
return c >= 0 && c <= 0xFF && isalpha(c); return c >= 0 && c <= 0xFF && isalpha(c);
} }
static struct {
char *name;
int val;
} headers[] = {
"darwin", Hdarwin,
"dragonfly", Hdragonfly,
"elf", Helf,
"freebsd", Hfreebsd,
"linux", Hlinux,
"netbsd", Hnetbsd,
"openbsd", Hopenbsd,
"plan9", Hplan9,
"windows", Hwindows,
"windowsgui", Hwindows,
0, 0
};
int
headtype(char *name)
{
int i;
for(i=0; headers[i].name; i++)
if(strcmp(name, headers[i].name) == 0)
return headers[i].val;
return -1;
}
char*
headstr(int v)
{
static char buf[20];
int i;
for(i=0; headers[i].name; i++)
if(v == headers[i].val)
return headers[i].name;
snprint(buf, sizeof buf, "%d", v);
return buf;
}
Link* Link*
linknew(LinkArch *arch) linknew(LinkArch *arch)
{ {
...@@ -53,8 +94,6 @@ linknew(LinkArch *arch) ...@@ -53,8 +94,6 @@ linknew(LinkArch *arch)
ctxt->arch = arch; ctxt->arch = arch;
ctxt->version = HistVersion; ctxt->version = HistVersion;
// TODO: Make caller pass in ctxt->arch,
// so that for example 6g only has the linkamd64 code.
p = getgoarch(); p = getgoarch();
if(strncmp(p, arch->name, strlen(arch->name)) != 0) if(strncmp(p, arch->name, strlen(arch->name)) != 0)
sysfatal("invalid goarch %s (want %s or derivative)", p, arch->name); sysfatal("invalid goarch %s (want %s or derivative)", p, arch->name);
...@@ -72,6 +111,59 @@ linknew(LinkArch *arch) ...@@ -72,6 +111,59 @@ linknew(LinkArch *arch)
} }
ctxt->pathname = strdup(buf); ctxt->pathname = strdup(buf);
ctxt->headtype = headtype(getgoos());
if(ctxt->headtype < 0)
sysfatal("unknown goos %s", getgoos());
// Record thread-local storage offset.
switch(ctxt->headtype) {
default:
sysfatal("unknown thread-local storage offset for %s", headstr(ctxt->headtype));
case Hplan9:
ctxt->tlsoffset = -2*ctxt->arch->ptrsize;
break;
case Hwindows:
break;
case Hlinux:
case Hfreebsd:
case Hnetbsd:
case Hopenbsd:
case Hdragonfly:
/*
* ELF uses TLS offset negative from FS.
* Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
* Known to low-level assembly in package runtime and runtime/cgo.
*/
ctxt->tlsoffset = -2*ctxt->arch->ptrsize;
break;
case Hdarwin:
/*
* OS X system constants - offset from 0(GS) to our TLS.
* Explained in ../../pkg/runtime/cgo/gcc_darwin_*.c.
*/
switch(ctxt->arch->thechar) {
default:
sysfatal("unknown thread-local storage offset for darwin/%s", ctxt->arch->name);
case '6':
ctxt->tlsoffset = 0x8a0;
break;
case '8':
ctxt->tlsoffset = 0x468;
break;
}
break;
}
// On arm, record goarm.
if(ctxt->arch->thechar == '5') {
p = getgoarm();
if(p != nil)
ctxt->goarm = atoi(p);
else
ctxt->goarm = 6;
}
return ctxt; return ctxt;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment