Commit 5d363c63 authored by Russ Cox's avatar Russ Cox

cmd/ld, runtime: new in-memory symbol table format

Design at http://golang.org/s/go12symtab.

This enables some cleanup of the garbage collector metadata
that will be done in future CLs.

This CL does not move the old symtab and pclntab back into
an unmapped section of the file. That's a bit tricky and will be
done separately.

Fixes #4020.

R=golang-dev, dave, cshapiro, iant, r
CC=golang-dev, nigeltao
https://golang.org/cl/11085043
parent 63e0ddc7
...@@ -197,8 +197,12 @@ enum as ...@@ -197,8 +197,12 @@ enum as
AMULAWB, AMULAWB,
AUSEFIELD, AUSEFIELD,
ALOCALS,
ATYPE, ATYPE,
AFUNCDATA,
APCDATA,
// TODO: Remove these.
ALOCALS,
ANPTRS, ANPTRS,
APTRS, APTRS,
......
...@@ -172,6 +172,7 @@ struct Sym ...@@ -172,6 +172,7 @@ struct Sym
char* dynimplib; char* dynimplib;
char* dynimpvers; char* dynimpvers;
struct Section* sect; struct Section* sect;
struct Hist* hist;
// STEXT // STEXT
Auto* autom; Auto* autom;
...@@ -282,7 +283,7 @@ enum ...@@ -282,7 +283,7 @@ enum
MINSIZ = 64, MINSIZ = 64,
NENT = 100, NENT = 100,
MAXIO = 8192, MAXIO = 8192,
MAXHIST = 20, /* limit of path elements for history symbols */ MAXHIST = 40, /* limit of path elements for history symbols */
MINLC = 4, MINLC = 4,
}; };
...@@ -319,7 +320,6 @@ EXTERN char* rpath; ...@@ -319,7 +320,6 @@ EXTERN char* rpath;
EXTERN uint32 stroffset; EXTERN uint32 stroffset;
EXTERN int32 symsize; EXTERN int32 symsize;
EXTERN Sym* textp; EXTERN Sym* textp;
EXTERN int version;
EXTERN char xcmp[C_GOK+1][C_GOK+1]; EXTERN char xcmp[C_GOK+1][C_GOK+1];
EXTERN Prog zprg; EXTERN Prog zprg;
EXTERN int dtype; EXTERN int dtype;
......
...@@ -278,6 +278,7 @@ main(int argc, char *argv[]) ...@@ -278,6 +278,7 @@ main(int argc, char *argv[])
span(); span();
addexport(); addexport();
// textaddress() functionality is handled in span() // textaddress() functionality is handled in span()
functab();
pclntab(); pclntab();
symtab(); symtab();
dodata(); dodata();
...@@ -549,6 +550,7 @@ loop: ...@@ -549,6 +550,7 @@ loop:
addhist(p->line, D_FILE); /* 'z' */ addhist(p->line, D_FILE); /* 'z' */
if(p->to.offset) if(p->to.offset)
addhist(p->to.offset, D_FILE1); /* 'Z' */ addhist(p->to.offset, D_FILE1); /* 'Z' */
savehist(p->line, p->to.offset);
histfrogp = 0; histfrogp = 0;
goto loop; goto loop;
...@@ -699,6 +701,7 @@ loop: ...@@ -699,6 +701,7 @@ loop:
p->to.offset = autosize; p->to.offset = autosize;
autosize += 4; autosize += 4;
s->type = STEXT; s->type = STEXT;
s->hist = gethist();
s->text = p; s->text = p;
s->value = pc; s->value = pc;
s->args = p->to.offset2; s->args = p->to.offset2;
......
...@@ -759,15 +759,18 @@ enum as ...@@ -759,15 +759,18 @@ enum as
AAESKEYGENASSIST, AAESKEYGENASSIST,
APSHUFD, APSHUFD,
APCLMULQDQ,
AUSEFIELD, AUSEFIELD,
ALOCALS,
ATYPE, ATYPE,
AFUNCDATA,
APCDATA,
// TODO: Remove these.
ALOCALS,
ANPTRS, ANPTRS,
APTRS, APTRS,
APCLMULQDQ,
ALAST ALAST
}; };
......
...@@ -177,6 +177,7 @@ struct Sym ...@@ -177,6 +177,7 @@ struct Sym
char* dynimplib; char* dynimplib;
char* dynimpvers; char* dynimpvers;
struct Section* sect; struct Section* sect;
struct Hist* hist; // for ATEXT
// STEXT // STEXT
Auto* autom; Auto* autom;
...@@ -213,7 +214,7 @@ enum ...@@ -213,7 +214,7 @@ enum
STRINGSZ = 200, STRINGSZ = 200,
MINLC = 1, MINLC = 1,
MAXIO = 8192, MAXIO = 8192,
MAXHIST = 20, /* limit of path elements for history symbols */ MAXHIST = 40, /* limit of path elements for history symbols */
Yxxx = 0, Yxxx = 0,
Ynone, Ynone,
...@@ -359,7 +360,6 @@ EXTERN int32 spsize; ...@@ -359,7 +360,6 @@ EXTERN int32 spsize;
EXTERN Sym* symlist; EXTERN Sym* symlist;
EXTERN int32 symsize; EXTERN int32 symsize;
EXTERN int tlsoffset; EXTERN int tlsoffset;
EXTERN int version;
EXTERN Prog zprg; EXTERN Prog zprg;
EXTERN int dtype; EXTERN int dtype;
EXTERN char* paramspace; EXTERN char* paramspace;
......
...@@ -289,6 +289,7 @@ main(int argc, char *argv[]) ...@@ -289,6 +289,7 @@ main(int argc, char *argv[])
dope(); dope();
addexport(); addexport();
textaddress(); textaddress();
functab();
pclntab(); pclntab();
symtab(); symtab();
dodata(); dodata();
...@@ -542,6 +543,7 @@ loop: ...@@ -542,6 +543,7 @@ loop:
addhist(p->line, D_FILE); /* 'z' */ addhist(p->line, D_FILE); /* 'z' */
if(p->to.offset) if(p->to.offset)
addhist(p->to.offset, D_FILE1); /* 'Z' */ addhist(p->to.offset, D_FILE1); /* 'Z' */
savehist(p->line, p->to.offset);
histfrogp = 0; histfrogp = 0;
goto loop; goto loop;
...@@ -690,6 +692,7 @@ loop: ...@@ -690,6 +692,7 @@ loop:
s->gotype = fromgotype; s->gotype = fromgotype;
} }
s->type = STEXT; s->type = STEXT;
s->hist = gethist();
s->value = pc; s->value = pc;
s->args = p->to.offset >> 32; s->args = p->to.offset >> 32;
s->nptrs = -1; s->nptrs = -1;
......
...@@ -1339,14 +1339,11 @@ Optab optab[] = ...@@ -1339,14 +1339,11 @@ Optab optab[] =
{ AAESKEYGENASSIST, yaes2, Pq, 0x3a,0xdf,(0) }, { AAESKEYGENASSIST, yaes2, Pq, 0x3a,0xdf,(0) },
{ APSHUFD, yaes2, Pq, 0x70,(0) }, { APSHUFD, yaes2, Pq, 0x70,(0) },
{ APCLMULQDQ, yxshuf, Pq, 0x3a,0x44,0 },
{ AUSEFIELD, ynop, Px, 0,0 }, { AUSEFIELD, ynop, Px, 0,0 },
{ ALOCALS }, { AFUNCDATA, ynop, Px, 0,0 },
{ ATYPE }, { APCDATA, ynop, Px, 0,0 },
{ ANPTRS },
{ APTRS },
{ APCLMULQDQ, yxshuf, Pq, 0x3a,0x44,0 },
{ AEND }, { AEND },
0 0
......
...@@ -578,8 +578,12 @@ enum as ...@@ -578,8 +578,12 @@ enum as
APSHUFB, APSHUFB,
AUSEFIELD, AUSEFIELD,
ALOCALS,
ATYPE, ATYPE,
AFUNCDATA,
APCDATA,
// TODO: Remove these.
ALOCALS,
ANPTRS, ANPTRS,
APTRS, APTRS,
......
...@@ -159,6 +159,7 @@ struct Sym ...@@ -159,6 +159,7 @@ struct Sym
char* dynimplib; char* dynimplib;
char* dynimpvers; char* dynimpvers;
struct Section* sect; struct Section* sect;
struct Hist* hist; // for ATEXT
// STEXT // STEXT
Auto* autom; Auto* autom;
...@@ -187,7 +188,7 @@ enum ...@@ -187,7 +188,7 @@ enum
STRINGSZ = 200, STRINGSZ = 200,
MINLC = 1, MINLC = 1,
MAXIO = 8192, MAXIO = 8192,
MAXHIST = 20, /* limit of path elements for history symbols */ MAXHIST = 40, /* limit of path elements for history symbols */
Yxxx = 0, Yxxx = 0,
Ynone, Ynone,
...@@ -313,7 +314,6 @@ EXTERN Sym* symlist; ...@@ -313,7 +314,6 @@ EXTERN Sym* symlist;
EXTERN int32 symsize; EXTERN int32 symsize;
EXTERN Sym* textp; EXTERN Sym* textp;
EXTERN int32 textsize; EXTERN int32 textsize;
EXTERN int version;
EXTERN Prog zprg; EXTERN Prog zprg;
EXTERN int dtype; EXTERN int dtype;
EXTERN int tlsoffset; EXTERN int tlsoffset;
......
...@@ -316,6 +316,7 @@ main(int argc, char *argv[]) ...@@ -316,6 +316,7 @@ main(int argc, char *argv[])
span(); span();
addexport(); addexport();
textaddress(); textaddress();
functab();
pclntab(); pclntab();
symtab(); symtab();
dodata(); dodata();
...@@ -552,6 +553,7 @@ loop: ...@@ -552,6 +553,7 @@ loop:
addhist(p->line, D_FILE); /* 'z' */ addhist(p->line, D_FILE); /* 'z' */
if(p->to.offset) if(p->to.offset)
addhist(p->to.offset, D_FILE1); /* 'Z' */ addhist(p->to.offset, D_FILE1); /* 'Z' */
savehist(p->line, p->to.offset);
histfrogp = 0; histfrogp = 0;
goto loop; goto loop;
...@@ -695,6 +697,7 @@ loop: ...@@ -695,6 +697,7 @@ loop:
diag("%s: redefinition: %s\n%P", pn, s->name, p); diag("%s: redefinition: %s\n%P", pn, s->name, p);
} }
s->type = STEXT; s->type = STEXT;
s->hist = gethist();
s->value = pc; s->value = pc;
s->args = p->to.offset2; s->args = p->to.offset2;
s->nptrs = -1; s->nptrs = -1;
......
...@@ -1001,10 +1001,9 @@ Optab optab[] = ...@@ -1001,10 +1001,9 @@ Optab optab[] =
{ APSHUFB, ymshufb,Pq, 0x38, 0x00 }, { APSHUFB, ymshufb,Pq, 0x38, 0x00 },
{ AUSEFIELD, ynop, Px, 0,0 }, { AUSEFIELD, ynop, Px, 0,0 },
{ ALOCALS },
{ ATYPE }, { ATYPE },
{ ANPTRS }, { AFUNCDATA, ynop, Px, 0,0 },
{ APTRS }, { APCDATA, ynop, Px, 0,0 },
0 0
}; };
...@@ -415,6 +415,8 @@ Zconv(Fmt *fp) ...@@ -415,6 +415,8 @@ Zconv(Fmt *fp)
s = sp->s; s = sp->s;
se = s + sp->len; se = s + sp->len;
// NOTE: Keep in sync with ../ld/go.c:/^Zconv.
while(s < se) { while(s < se) {
n = chartorune(&r, s); n = chartorune(&r, s);
s += n; s += n;
......
...@@ -763,7 +763,7 @@ setuintxx(Sym *s, vlong off, uint64 v, vlong wid) ...@@ -763,7 +763,7 @@ setuintxx(Sym *s, vlong off, uint64 v, vlong wid)
s->p[off+i] = cast[inuxi8[i]]; s->p[off+i] = cast[inuxi8[i]];
break; break;
} }
return off; return off+wid;
} }
vlong vlong
...@@ -800,28 +800,28 @@ adduint64(Sym *s, uint64 v) ...@@ -800,28 +800,28 @@ adduint64(Sym *s, uint64 v)
return adduintxx(s, v, 8); return adduintxx(s, v, 8);
} }
void vlong
setuint8(Sym *s, vlong r, uint8 v) setuint8(Sym *s, vlong r, uint8 v)
{ {
setuintxx(s, r, v, 1); return setuintxx(s, r, v, 1);
} }
void vlong
setuint16(Sym *s, vlong r, uint16 v) setuint16(Sym *s, vlong r, uint16 v)
{ {
setuintxx(s, r, v, 2); return setuintxx(s, r, v, 2);
} }
void vlong
setuint32(Sym *s, vlong r, uint32 v) setuint32(Sym *s, vlong r, uint32 v)
{ {
setuintxx(s, r, v, 4); return setuintxx(s, r, v, 4);
} }
void vlong
setuint64(Sym *s, vlong r, uint64 v) setuint64(Sym *s, vlong r, uint64 v)
{ {
setuintxx(s, r, v, 8); return setuintxx(s, r, v, 8);
} }
vlong vlong
...@@ -842,7 +842,7 @@ addaddrplus(Sym *s, Sym *t, vlong add) ...@@ -842,7 +842,7 @@ addaddrplus(Sym *s, Sym *t, vlong add)
r->siz = PtrSize; r->siz = PtrSize;
r->type = D_ADDR; r->type = D_ADDR;
r->add = add; r->add = add;
return i; return i + r->siz;
} }
static vlong static vlong
...@@ -863,7 +863,7 @@ addaddrplus4(Sym *s, Sym *t, vlong add) ...@@ -863,7 +863,7 @@ addaddrplus4(Sym *s, Sym *t, vlong add)
r->siz = 4; r->siz = 4;
r->type = D_ADDR; r->type = D_ADDR;
r->add = add; r->add = add;
return i; return i + r->siz;
} }
vlong vlong
...@@ -884,7 +884,7 @@ addpcrelplus(Sym *s, Sym *t, vlong add) ...@@ -884,7 +884,7 @@ addpcrelplus(Sym *s, Sym *t, vlong add)
r->add = add; r->add = add;
r->type = D_PCREL; r->type = D_PCREL;
r->siz = 4; r->siz = 4;
return i; return i + r->siz;
} }
vlong vlong
...@@ -911,7 +911,7 @@ setaddrplus(Sym *s, vlong off, Sym *t, vlong add) ...@@ -911,7 +911,7 @@ setaddrplus(Sym *s, vlong off, Sym *t, vlong add)
r->siz = PtrSize; r->siz = PtrSize;
r->type = D_ADDR; r->type = D_ADDR;
r->add = add; r->add = add;
return off; return off + r->siz;
} }
vlong vlong
...@@ -937,7 +937,7 @@ addsize(Sym *s, Sym *t) ...@@ -937,7 +937,7 @@ addsize(Sym *s, Sym *t)
r->off = i; r->off = i;
r->siz = PtrSize; r->siz = PtrSize;
r->type = D_SIZE; r->type = D_SIZE;
return i; return i + r->siz;
} }
void void
......
...@@ -613,7 +613,7 @@ markflood(void) ...@@ -613,7 +613,7 @@ markflood(void)
} }
static char* static char*
morename[] = markextra[] =
{ {
"runtime.morestack", "runtime.morestack",
"runtime.morestackx", "runtime.morestackx",
...@@ -629,6 +629,12 @@ morename[] = ...@@ -629,6 +629,12 @@ morename[] =
"runtime.morestack32", "runtime.morestack32",
"runtime.morestack40", "runtime.morestack40",
"runtime.morestack48", "runtime.morestack48",
// on arm, lock in the div/mod helpers too
"_div",
"_divu",
"_mod",
"_modu",
}; };
static int static int
...@@ -676,8 +682,8 @@ deadcode(void) ...@@ -676,8 +682,8 @@ deadcode(void)
mark(lookup(INITENTRY, 0)); mark(lookup(INITENTRY, 0));
if(flag_shared) if(flag_shared)
mark(lookup(LIBINITENTRY, 0)); mark(lookup(LIBINITENTRY, 0));
for(i=0; i<nelem(morename); i++) for(i=0; i<nelem(markextra); i++)
mark(lookup(morename[i], 0)); mark(lookup(markextra[i], 0));
for(i=0; i<ndynexp; i++) for(i=0; i<ndynexp; i++)
mark(dynexp[i]); mark(dynexp[i]);
...@@ -794,6 +800,8 @@ Zconv(Fmt *fp) ...@@ -794,6 +800,8 @@ Zconv(Fmt *fp)
return fmtstrcpy(fp, "<nil>"); return fmtstrcpy(fp, "<nil>");
se = s + strlen(s); se = s + strlen(s);
// NOTE: Keep in sync with ../gc/go.c:/^Zconv.
while(s < se) { while(s < se) {
n = chartorune(&r, s); n = chartorune(&r, s);
s += n; s += n;
...@@ -822,6 +830,9 @@ Zconv(Fmt *fp) ...@@ -822,6 +830,9 @@ Zconv(Fmt *fp)
fmtrune(fp, '\\'); fmtrune(fp, '\\');
fmtrune(fp, r); fmtrune(fp, r);
break; break;
case 0xFEFF: // BOM, basically disallowed in source code
fmtstrcpy(fp, "\\uFEFF");
break;
} }
} }
return 0; return 0;
......
This diff is collapsed.
...@@ -41,10 +41,12 @@ enum ...@@ -41,10 +41,12 @@ enum
STYPE, STYPE,
SSTRING, SSTRING,
SGOSTRING, SGOSTRING,
SGOFUNC,
SRODATA, SRODATA,
SFUNCTAB,
STYPELINK, STYPELINK,
SSYMTAB, SSYMTAB, // TODO: move to unmapped section
SPCLNTAB, SPCLNTAB, // TODO: move to unmapped section
SELFROSECT, SELFROSECT,
/* writable, non-executable */ /* writable, non-executable */
...@@ -67,6 +69,7 @@ enum ...@@ -67,6 +69,7 @@ enum
SMACHOINDIRECTPLT, SMACHOINDIRECTPLT,
SMACHOINDIRECTGOT, SMACHOINDIRECTGOT,
SFILE, SFILE,
SFILEPATH,
SCONST, SCONST,
SDYNIMPORT, SDYNIMPORT,
SHOSTOBJ, SHOSTOBJ,
...@@ -129,9 +132,14 @@ struct Section ...@@ -129,9 +132,14 @@ struct Section
uvlong rellen; uvlong rellen;
}; };
typedef struct Hist Hist;
#pragma incomplete struct Hist
extern char symname[]; extern char symname[];
extern char **libdir; extern char **libdir;
extern int nlibdir; extern int nlibdir;
extern int version;
EXTERN char* INITENTRY; EXTERN char* INITENTRY;
EXTERN char* thestring; EXTERN char* thestring;
...@@ -194,6 +202,9 @@ void addlibpath(char *srcref, char *objref, char *file, char *pkg); ...@@ -194,6 +202,9 @@ void addlibpath(char *srcref, char *objref, char *file, char *pkg);
Section* addsection(Segment*, char*, int); Section* addsection(Segment*, char*, int);
void copyhistfrog(char *buf, int nbuf); void copyhistfrog(char *buf, int nbuf);
void addhist(int32 line, int type); void addhist(int32 line, int type);
void savehist(int32 line, int32 off);
Hist* gethist(void);
void getline(Hist*, int32 line, int32 *f, int32 *l);
void asmlc(void); void asmlc(void);
void histtoauto(void); void histtoauto(void);
void collapsefrog(Sym *s); void collapsefrog(Sym *s);
...@@ -216,6 +227,7 @@ void objfile(char *file, char *pkg); ...@@ -216,6 +227,7 @@ void objfile(char *file, char *pkg);
void libinit(void); void libinit(void);
void pclntab(void); void pclntab(void);
void symtab(void); void symtab(void);
void functab(void);
void Lflag(char *arg); void Lflag(char *arg);
void usage(void); void usage(void);
void adddynrel(Sym*, Reloc*); void adddynrel(Sym*, Reloc*);
...@@ -251,10 +263,11 @@ vlong addpcrelplus(Sym*, Sym*, vlong); ...@@ -251,10 +263,11 @@ vlong addpcrelplus(Sym*, Sym*, vlong);
vlong addsize(Sym*, Sym*); vlong addsize(Sym*, Sym*);
vlong setaddrplus(Sym*, vlong, Sym*, vlong); vlong setaddrplus(Sym*, vlong, Sym*, vlong);
vlong setaddr(Sym*, vlong, Sym*); vlong setaddr(Sym*, vlong, Sym*);
void setuint8(Sym*, vlong, uint8); vlong setuint8(Sym*, vlong, uint8);
void setuint16(Sym*, vlong, uint16); vlong setuint16(Sym*, vlong, uint16);
void setuint32(Sym*, vlong, uint32); vlong setuint32(Sym*, vlong, uint32);
void setuint64(Sym*, vlong, uint64); vlong setuint64(Sym*, vlong, uint64);
vlong setuintxx(Sym*, vlong, uint64, vlong);
void asmsym(void); void asmsym(void);
void asmelfsym(void); void asmelfsym(void);
void asmplan9sym(void); void asmplan9sym(void);
...@@ -284,6 +297,7 @@ void hostobjs(void); ...@@ -284,6 +297,7 @@ void hostobjs(void);
void hostlink(void); void hostlink(void);
char* estrdup(char*); char* estrdup(char*);
void* erealloc(void*, long); void* erealloc(void*, long);
Sym* defgostring(char*);
int pathchar(void); int pathchar(void);
void* mal(uint32); void* mal(uint32);
......
...@@ -466,7 +466,8 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ) ...@@ -466,7 +466,8 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
void void
symtab(void) symtab(void)
{ {
Sym *s, *symtype, *symtypelink, *symgostring; Sym *s, *symtype, *symtypelink, *symgostring, *symgofunc;
dosymtype(); dosymtype();
// Define these so that they'll get put into the symbol table. // Define these so that they'll get put into the symbol table.
...@@ -519,6 +520,12 @@ symtab(void) ...@@ -519,6 +520,12 @@ symtab(void)
s->reachable = 1; s->reachable = 1;
symgostring = s; symgostring = s;
s = lookup("go.func.*", 0);
s->type = SGOFUNC;
s->size = 0;
s->reachable = 1;
symgofunc = s;
symtypelink = lookup("typelink", 0); symtypelink = lookup("typelink", 0);
symt = lookup("symtab", 0); symt = lookup("symtab", 0);
...@@ -548,6 +555,11 @@ symtab(void) ...@@ -548,6 +555,11 @@ symtab(void)
s->hide = 1; s->hide = 1;
s->outer = symgostring; s->outer = symgostring;
} }
if(strncmp(s->name, "go.func.", 8) == 0) {
s->type = SGOFUNC;
s->hide = 1;
s->outer = symgofunc;
}
} }
if(debug['s']) if(debug['s'])
......
...@@ -573,9 +573,9 @@ havem: ...@@ -573,9 +573,9 @@ havem:
MOVL BP, 0(DI) MOVL BP, 0(DI)
// Push arguments to cgocallbackg. // Push arguments to cgocallbackg.
// Frame size here must match the frame size above // Frame size here must match the frame size above plus the pushes
// to trick traceback routines into doing the right thing. // to trick traceback routines into doing the right thing.
SUBL $12, DI SUBL $20, DI
MOVL AX, 0(DI) MOVL AX, 0(DI)
MOVL BX, 4(DI) MOVL BX, 4(DI)
MOVL DX, 8(DI) MOVL DX, 8(DI)
...@@ -587,9 +587,9 @@ havem: ...@@ -587,9 +587,9 @@ havem:
// Restore g->sched (== m->curg->sched) from saved values. // Restore g->sched (== m->curg->sched) from saved values.
get_tls(CX) get_tls(CX)
MOVL g(CX), SI MOVL g(CX), SI
MOVL 12(SP), BP MOVL 20(SP), BP
MOVL BP, (g_sched+gobuf_pc)(SI) MOVL BP, (g_sched+gobuf_pc)(SI)
LEAL (12+4)(SP), DI LEAL (20+4)(SP), DI
MOVL DI, (g_sched+gobuf_sp)(SI) MOVL DI, (g_sched+gobuf_sp)(SI)
// Switch back to m->g0's stack and restore m->g0->sched.sp. // Switch back to m->g0's stack and restore m->g0->sched.sp.
......
...@@ -609,9 +609,9 @@ havem: ...@@ -609,9 +609,9 @@ havem:
MOVQ BP, 0(DI) MOVQ BP, 0(DI)
// Push arguments to cgocallbackg. // Push arguments to cgocallbackg.
// Frame size here must match the frame size above // Frame size here must match the frame size above plus the pushes
// to trick traceback routines into doing the right thing. // to trick traceback routines into doing the right thing.
SUBQ $24, DI SUBQ $40, DI
MOVQ AX, 0(DI) MOVQ AX, 0(DI)
MOVQ BX, 8(DI) MOVQ BX, 8(DI)
MOVQ DX, 16(DI) MOVQ DX, 16(DI)
...@@ -623,9 +623,9 @@ havem: ...@@ -623,9 +623,9 @@ havem:
// Restore g->sched (== m->curg->sched) from saved values. // Restore g->sched (== m->curg->sched) from saved values.
get_tls(CX) get_tls(CX)
MOVQ g(CX), SI MOVQ g(CX), SI
MOVQ 24(SP), BP MOVQ 40(SP), BP
MOVQ BP, (g_sched+gobuf_pc)(SI) MOVQ BP, (g_sched+gobuf_pc)(SI)
LEAQ (24+8)(SP), DI LEAQ (40+8)(SP), DI
MOVQ DI, (g_sched+gobuf_sp)(SI) MOVQ DI, (g_sched+gobuf_sp)(SI)
// Switch back to m->g0's stack and restore m->g0->sched.sp. // Switch back to m->g0's stack and restore m->g0->sched.sp.
......
...@@ -368,12 +368,12 @@ havem: ...@@ -368,12 +368,12 @@ havem:
MOVW (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 MOVW (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
// Push gobuf.pc // Push gobuf.pc
// Frame size here must match the frame size above plus the push
// to trick traceback routines into doing the right thing.
MOVW (g_sched+gobuf_pc)(g), R5 MOVW (g_sched+gobuf_pc)(g), R5
MOVW.W R5, -16(R4) MOVW.W R5, -20(R4)
// Push arguments to cgocallbackg. // Push arguments to cgocallbackg.
// Frame size here must match the frame size above
// to trick traceback routines into doing the right thing.
MOVW R0, 4(R4) MOVW R0, 4(R4)
MOVW R1, 8(R4) MOVW R1, 8(R4)
MOVW R2, 12(R4) MOVW R2, 12(R4)
...@@ -385,7 +385,7 @@ havem: ...@@ -385,7 +385,7 @@ havem:
// Restore g->sched (== m->curg->sched) from saved values. // Restore g->sched (== m->curg->sched) from saved values.
MOVW 0(R13), R5 MOVW 0(R13), R5
MOVW R5, (g_sched+gobuf_pc)(g) MOVW R5, (g_sched+gobuf_pc)(g)
ADD $(12+4), R13, R4 ADD $(16+4), R13, R4
MOVW R4, (g_sched+gobuf_sp)(g) MOVW R4, (g_sched+gobuf_sp)(g)
// Switch back to m->g0's stack and restore m->g0->sched.sp. // Switch back to m->g0's stack and restore m->g0->sched.sp.
......
...@@ -78,18 +78,8 @@ func Caller(skip int) (pc uintptr, file string, line int, ok bool) ...@@ -78,18 +78,8 @@ func Caller(skip int) (pc uintptr, file string, line int, ok bool)
// It returns the number of entries written to pc. // It returns the number of entries written to pc.
func Callers(skip int, pc []uintptr) int func Callers(skip int, pc []uintptr) int
type Func struct { // Keep in sync with runtime.h:struct Func type Func struct {
name string opaque struct{} // unexported field to disallow conversions
typ string // go type string
src string // src file name
pcln []byte // pc/ln tab for this func
entry uintptr // entry pc
pc0 uintptr // starting pc, ln for table
ln0 int32
frame int32 // stack frame size
args int32 // in/out args size
locals int32 // locals size
ptrs []int32 // pointer map
} }
// FuncForPC returns a *Func describing the function that contains the // FuncForPC returns a *Func describing the function that contains the
...@@ -97,10 +87,14 @@ type Func struct { // Keep in sync with runtime.h:struct Func ...@@ -97,10 +87,14 @@ type Func struct { // Keep in sync with runtime.h:struct Func
func FuncForPC(pc uintptr) *Func func FuncForPC(pc uintptr) *Func
// Name returns the name of the function. // Name returns the name of the function.
func (f *Func) Name() string { return f.name } func (f *Func) Name() string {
return funcname_go(f)
}
// Entry returns the entry address of the function. // Entry returns the entry address of the function.
func (f *Func) Entry() uintptr { return f.entry } func (f *Func) Entry() uintptr {
return funcentry_go(f)
}
// FileLine returns the file name and line number of the // FileLine returns the file name and line number of the
// source code corresponding to the program counter pc. // source code corresponding to the program counter pc.
...@@ -112,6 +106,8 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) { ...@@ -112,6 +106,8 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
// implemented in symtab.c // implemented in symtab.c
func funcline_go(*Func, uintptr) (string, int) func funcline_go(*Func, uintptr) (string, int)
func funcname_go(*Func) string
func funcentry_go(*Func) uintptr
// SetFinalizer sets the finalizer associated with x to f. // SetFinalizer sets the finalizer associated with x to f.
// When the garbage collector finds an unreachable block // When the garbage collector finds an unreachable block
......
...@@ -1390,7 +1390,7 @@ addframeroots(Stkframe *frame, void*) ...@@ -1390,7 +1390,7 @@ addframeroots(Stkframe *frame, void*)
Func *f; Func *f;
byte *ap; byte *ap;
int32 i, j, nuintptr; int32 i, j, nuintptr;
uint32 w, b; uint32 w, b, *ptrs;
// Scan local variables if stack frame has been allocated. // Scan local variables if stack frame has been allocated.
if(frame->varlen > 0) if(frame->varlen > 0)
...@@ -1399,11 +1399,12 @@ addframeroots(Stkframe *frame, void*) ...@@ -1399,11 +1399,12 @@ addframeroots(Stkframe *frame, void*)
// Scan arguments. // Scan arguments.
// Use pointer information if known. // Use pointer information if known.
f = frame->fn; f = frame->fn;
if(f->args > 0 && f->ptrs.array != nil) { if(f->args > 0 && f->ptrslen > 0) {
ap = frame->argp; ap = frame->argp;
nuintptr = f->args / sizeof(uintptr); nuintptr = f->args / sizeof(uintptr);
for(i = 0; i < f->ptrs.len; i++) { ptrs = (uint32*)((byte*)f + f->ptrsoff);
w = ((uint32*)f->ptrs.array)[i]; for(i = 0; i < f->ptrslen; i++) {
w = ptrs[i];
b = 1; b = 1;
j = nuintptr; j = nuintptr;
if(j > 32) if(j > 32)
......
...@@ -294,12 +294,11 @@ runtime·Caller(intgo skip, uintptr retpc, String retfile, intgo retline, bool r ...@@ -294,12 +294,11 @@ runtime·Caller(intgo skip, uintptr retpc, String retfile, intgo retline, bool r
retbool = true; // have retpc at least retbool = true; // have retpc at least
} else { } else {
retpc = rpc[1]; retpc = rpc[1];
retfile = f->src;
pc = retpc; pc = retpc;
g = runtime·findfunc(rpc[0]); g = runtime·findfunc(rpc[0]);
if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic)) if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic))
pc--; pc--;
retline = runtime·funcline(f, pc); retline = runtime·funcline(f, pc, &retfile);
retbool = true; retbool = true;
} }
FLUSH(&retpc); FLUSH(&retpc);
......
...@@ -401,21 +401,25 @@ enum ...@@ -401,21 +401,25 @@ enum
SigIgnored = 1<<6, // the signal was ignored before we registered for it SigIgnored = 1<<6, // the signal was ignored before we registered for it
}; };
// NOTE(rsc): keep in sync with extern.go:/type.Func. // layout of in-memory per-function information prepared by linker
// Eventually, the loaded symbol table should be closer to this form. // See http://golang.org/s/go12symtab.
struct Func struct Func
{ {
String name; String *name; // function name
String type; // go type string uintptr entry; // start pc
String src; // src file name
Slice pcln; // pc/ln tab for this func // TODO: Remove these fields.
uintptr entry; // entry pc
uintptr pc0; // starting pc, ln for table
int32 ln0;
int32 frame; // stack frame size
int32 args; // in/out args size int32 args; // in/out args size
int32 locals; // locals size int32 locals; // locals size
Slice ptrs; // pointer map int32 frame; // legacy frame size; use pcsp if possible
int32 ptrsoff;
int32 ptrslen;
int32 pcsp;
int32 pcfile;
int32 pcln;
int32 npcdata;
int32 nfuncdata;
}; };
// layout of Itab known to compilers // layout of Itab known to compilers
...@@ -790,7 +794,9 @@ void runtime·unminit(void); ...@@ -790,7 +794,9 @@ void runtime·unminit(void);
void runtime·signalstack(byte*, int32); void runtime·signalstack(byte*, int32);
void runtime·symtabinit(void); void runtime·symtabinit(void);
Func* runtime·findfunc(uintptr); Func* runtime·findfunc(uintptr);
int32 runtime·funcline(Func*, uintptr); int32 runtime·funcline(Func*, uintptr, String*);
int32 runtime·funcarglen(Func*, uintptr);
int32 runtime·funcspdelta(Func*, uintptr);
void* runtime·stackalloc(uint32); void* runtime·stackalloc(uint32);
void runtime·stackfree(void*, uintptr); void runtime·stackfree(void*, uintptr);
MCache* runtime·allocmcache(void); MCache* runtime·allocmcache(void);
......
This diff is collapsed.
...@@ -15,15 +15,18 @@ void _mod(void); ...@@ -15,15 +15,18 @@ void _mod(void);
void _divu(void); void _divu(void);
void _modu(void); void _modu(void);
static String unknown = { (uint8*)"?", 1 };
int32 int32
runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*callback)(Stkframe*, void*), void *v, bool printall) runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*callback)(Stkframe*, void*), void *v, bool printall)
{ {
int32 i, n, nprint, skip0; int32 i, n, nprint, skip0, line;
uintptr x, tracepc; uintptr x, tracepc;
bool waspanic, printing; bool waspanic, printing;
Func *f, *f2; Func *f, *f2;
Stkframe frame; Stkframe frame;
Stktop *stk; Stktop *stk;
String file;
skip0 = skip; skip0 = skip;
...@@ -76,11 +79,8 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -76,11 +79,8 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
// Derive frame pointer and link register. // Derive frame pointer and link register.
if(frame.lr == 0) if(frame.lr == 0)
frame.lr = *(uintptr*)frame.sp; frame.lr = *(uintptr*)frame.sp;
if(frame.fp == 0) { if(frame.fp == 0)
frame.fp = frame.sp; frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc);
if(frame.pc > f->entry && f->frame >= sizeof(uintptr))
frame.fp += f->frame;
}
// Derive size of arguments. // Derive size of arguments.
frame.argp = (byte*)frame.fp + sizeof(uintptr); frame.argp = (byte*)frame.fp + sizeof(uintptr);
...@@ -96,7 +96,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -96,7 +96,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
else if((f2 = runtime·findfunc(frame.lr)) != nil && f2->frame >= sizeof(uintptr)) else if((f2 = runtime·findfunc(frame.lr)) != nil && f2->frame >= sizeof(uintptr))
frame.arglen = f2->frame; // conservative overestimate frame.arglen = f2->frame; // conservative overestimate
else { else {
runtime·printf("runtime: unknown argument frame size for %S\n", f->name); runtime·printf("runtime: unknown argument frame size for %S\n", *f->name);
if(!printing) if(!printing)
runtime·throw("invalid stack"); runtime·throw("invalid stack");
} }
...@@ -113,7 +113,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -113,7 +113,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.varlen = frame.fp - frame.sp; frame.varlen = frame.fp - frame.sp;
} else { } else {
if(f->locals > frame.fp - frame.sp) { if(f->locals > frame.fp - frame.sp) {
runtime·printf("runtime: inconsistent locals=%p frame=%p fp=%p sp=%p for %S\n", (uintptr)f->locals, (uintptr)f->frame, frame.fp, frame.sp, f->name); runtime·printf("runtime: inconsistent locals=%p frame=%p fp=%p sp=%p for %S\n", (uintptr)f->locals, (uintptr)f->frame, frame.fp, frame.sp, *f->name);
runtime·throw("invalid stack"); runtime·throw("invalid stack");
} }
frame.varp = (byte*)frame.fp - f->locals; frame.varp = (byte*)frame.fp - f->locals;
...@@ -138,7 +138,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -138,7 +138,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
tracepc = frame.pc; // back up to CALL instruction for funcline. tracepc = frame.pc; // back up to CALL instruction for funcline.
if(n > 0 && frame.pc > f->entry && !waspanic) if(n > 0 && frame.pc > f->entry && !waspanic)
tracepc -= sizeof(uintptr); tracepc -= sizeof(uintptr);
runtime·printf("%S(", f->name); runtime·printf("%S(", *f->name);
for(i = 0; i < frame.arglen/sizeof(uintptr); i++) { for(i = 0; i < frame.arglen/sizeof(uintptr); i++) {
if(i >= 5) { if(i >= 5) {
runtime·prints(", ..."); runtime·prints(", ...");
...@@ -149,7 +149,8 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -149,7 +149,8 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
runtime·printhex(((uintptr*)frame.argp)[i]); runtime·printhex(((uintptr*)frame.argp)[i]);
} }
runtime·prints(")\n"); runtime·prints(")\n");
runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc)); line = runtime·funcline(f, tracepc, &file);
runtime·printf("\t%S:%d", file, line);
if(frame.pc > f->entry) if(frame.pc > f->entry)
runtime·printf(" +%p", (uintptr)(frame.pc - f->entry)); runtime·printf(" +%p", (uintptr)(frame.pc - f->entry));
if(m->throwing && gp == m->curg) if(m->throwing && gp == m->curg)
...@@ -164,7 +165,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -164,7 +165,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
waspanic = f->entry == (uintptr)runtime·sigpanic; waspanic = f->entry == (uintptr)runtime·sigpanic;
// Do not unwind past the bottom of the stack. // Do not unwind past the bottom of the stack.
if(f->entry == (uintptr)runtime·goexit || f->entry == (uintptr)runtime·mstart || f->entry == (uintptr)_rt0_go) if(f->entry == (uintptr)runtime·goexit || f->entry == (uintptr)runtime·mstart || f->entry == (uintptr)runtime·mcall || f->entry == (uintptr)_rt0_go)
break; break;
// Unwind to next frame. // Unwind to next frame.
...@@ -172,16 +173,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -172,16 +173,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.lr = 0; frame.lr = 0;
frame.sp = frame.fp; frame.sp = frame.fp;
frame.fp = 0; frame.fp = 0;
// If this was div or divu or mod or modu, the caller had
// an extra 8 bytes on its stack. Adjust sp.
if(f->entry == (uintptr)_div || f->entry == (uintptr)_divu || f->entry == (uintptr)_mod || f->entry == (uintptr)_modu)
frame.sp += 8;
// If this was deferproc or newproc, the caller had an extra 12.
if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
frame.sp += 12;
// sighandler saves the lr on stack before faking a call to sigpanic // sighandler saves the lr on stack before faking a call to sigpanic
if(waspanic) { if(waspanic) {
x = *(uintptr*)frame.sp; x = *(uintptr*)frame.sp;
...@@ -203,16 +195,19 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -203,16 +195,19 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
static void static void
printcreatedby(G *gp) printcreatedby(G *gp)
{ {
int32 line;
uintptr pc, tracepc; uintptr pc, tracepc;
Func *f; Func *f;
String file;
if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
&& runtime·showframe(f, gp) && gp->goid != 1) { && runtime·showframe(f, gp) && gp->goid != 1) {
runtime·printf("created by %S\n", f->name); runtime·printf("created by %S\n", *f->name);
tracepc = pc; // back up to CALL instruction for funcline. tracepc = pc; // back up to CALL instruction for funcline.
if(pc > f->entry) if(pc > f->entry)
tracepc -= sizeof(uintptr); tracepc -= sizeof(uintptr);
runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc)); line = runtime·funcline(f, tracepc, &file);
runtime·printf("\t%S:%d", file, line);
if(pc > f->entry) if(pc > f->entry)
runtime·printf(" +%p", (uintptr)(pc - f->entry)); runtime·printf(" +%p", (uintptr)(pc - f->entry));
runtime·printf("\n"); runtime·printf("\n");
......
...@@ -16,6 +16,8 @@ void runtime·sigpanic(void); ...@@ -16,6 +16,8 @@ void runtime·sigpanic(void);
// This code is also used for the 386 tracebacks. // This code is also used for the 386 tracebacks.
// Use uintptr for an appropriate word-sized integer. // Use uintptr for an appropriate word-sized integer.
static String unknown = { (uint8*)"?", 1 };
// Generic traceback. Handles runtime stack prints (pcbuf == nil), // Generic traceback. Handles runtime stack prints (pcbuf == nil),
// the runtime.Callers function (pcbuf != nil), as well as the garbage // the runtime.Callers function (pcbuf != nil), as well as the garbage
// collector (callback != nil). A little clunky to merge these, but avoids // collector (callback != nil). A little clunky to merge these, but avoids
...@@ -23,12 +25,13 @@ void runtime·sigpanic(void); ...@@ -23,12 +25,13 @@ void runtime·sigpanic(void);
int32 int32
runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*callback)(Stkframe*, void*), void *v, bool printall) runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*callback)(Stkframe*, void*), void *v, bool printall)
{ {
int32 i, n, nprint; int32 i, n, nprint, line;
uintptr tracepc; uintptr tracepc;
bool waspanic, printing; bool waspanic, printing;
Func *f, *f2; Func *f, *flr;
Stkframe frame; Stkframe frame;
Stktop *stk; Stktop *stk;
String file;
USED(lr0); USED(lr0);
...@@ -62,33 +65,36 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -62,33 +65,36 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.sp = stk->gobuf.sp; frame.sp = stk->gobuf.sp;
frame.lr = 0; frame.lr = 0;
frame.fp = 0; frame.fp = 0;
frame.fn = nil;
if(printing && runtime·showframe(nil, gp)) if(printing && runtime·showframe(nil, gp))
runtime·printf("----- stack segment boundary -----\n"); runtime·printf("----- stack segment boundary -----\n");
stk = (Stktop*)stk->stackbase; stk = (Stktop*)stk->stackbase;
continue; continue;
} }
if(frame.pc <= 0x1000 || (frame.fn = f = runtime·findfunc(frame.pc)) == nil) { f = frame.fn;
if(callback != nil) if(f == nil && (frame.pc <= 0x1000 || (frame.fn = f = runtime·findfunc(frame.pc)) == nil)) {
if(callback != nil) {
runtime·printf("unknown pc %p\n", frame.pc);
runtime·throw("unknown pc"); runtime·throw("unknown pc");
}
break; break;
} }
// Found an actual function. // Found an actual function.
// Derive frame pointer and link register. // Derive frame pointer and link register.
if(frame.fp == 0) { if(frame.fp == 0) {
frame.fp = frame.sp; frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc);
if(frame.pc > f->entry && f->frame >= sizeof(uintptr)) frame.fp += sizeof(uintptr); // caller PC
frame.fp += f->frame;
else
frame.fp += sizeof(uintptr);
} }
if(frame.lr == 0) if(frame.lr == 0)
frame.lr = ((uintptr*)frame.fp)[-1]; frame.lr = ((uintptr*)frame.fp)[-1];
flr = runtime·findfunc(frame.lr);
// Derive size of arguments. // Derive size of arguments.
frame.argp = (byte*)frame.fp; frame.argp = (byte*)frame.fp;
frame.arglen = 0; if(flr != nil && (i = runtime·funcarglen(flr, frame.lr)) >= 0)
if(f->args != ArgsSizeUnknown) frame.arglen = i;
else if(f->args != ArgsSizeUnknown)
frame.arglen = f->args; frame.arglen = f->args;
else if(runtime·haszeroargs(f->entry)) else if(runtime·haszeroargs(f->entry))
frame.arglen = 0; frame.arglen = 0;
...@@ -96,10 +102,10 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -96,10 +102,10 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.arglen = stk->argsize; frame.arglen = stk->argsize;
else if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc) else if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
frame.arglen = 2*sizeof(uintptr) + *(int32*)frame.argp; frame.arglen = 2*sizeof(uintptr) + *(int32*)frame.argp;
else if((f2 = runtime·findfunc(frame.lr)) != nil && f2->frame >= sizeof(uintptr)) else if(flr != nil && flr->frame >= sizeof(uintptr))
frame.arglen = f2->frame; // conservative overestimate frame.arglen = flr->frame; // conservative overestimate
else { else {
runtime·printf("runtime: unknown argument frame size for %S\n", f->name); runtime·printf("runtime: unknown argument frame size for %S called from %p [%S]\n", *f->name, frame.lr, flr ? *flr->name : unknown);
if(!printing) if(!printing)
runtime·throw("invalid stack"); runtime·throw("invalid stack");
} }
...@@ -116,7 +122,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -116,7 +122,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.varlen = frame.fp - sizeof(uintptr) - frame.sp; frame.varlen = frame.fp - sizeof(uintptr) - frame.sp;
} else { } else {
if(f->locals > frame.fp - sizeof(uintptr) - frame.sp) { if(f->locals > frame.fp - sizeof(uintptr) - frame.sp) {
runtime·printf("runtime: inconsistent locals=%p frame=%p fp=%p sp=%p for %S\n", (uintptr)f->locals, (uintptr)f->frame, frame.fp, frame.sp, f->name); runtime·printf("runtime: inconsistent locals=%p frame=%p fp=%p sp=%p for %S\n", (uintptr)f->locals, (uintptr)f->frame, frame.fp, frame.sp, *f->name);
runtime·throw("invalid stack"); runtime·throw("invalid stack");
} }
frame.varp = (byte*)frame.fp - sizeof(uintptr) - f->locals; frame.varp = (byte*)frame.fp - sizeof(uintptr) - f->locals;
...@@ -141,7 +147,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -141,7 +147,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
tracepc = frame.pc; // back up to CALL instruction for funcline. tracepc = frame.pc; // back up to CALL instruction for funcline.
if(n > 0 && frame.pc > f->entry && !waspanic) if(n > 0 && frame.pc > f->entry && !waspanic)
tracepc--; tracepc--;
runtime·printf("%S(", f->name); runtime·printf("%S(", *f->name);
for(i = 0; i < frame.arglen/sizeof(uintptr); i++) { for(i = 0; i < frame.arglen/sizeof(uintptr); i++) {
if(i >= 5) { if(i >= 5) {
runtime·prints(", ..."); runtime·prints(", ...");
...@@ -152,7 +158,8 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -152,7 +158,8 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
runtime·printhex(((uintptr*)frame.argp)[i]); runtime·printhex(((uintptr*)frame.argp)[i]);
} }
runtime·prints(")\n"); runtime·prints(")\n");
runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc)); line = runtime·funcline(f, tracepc, &file);
runtime·printf("\t%S:%d", file, line);
if(frame.pc > f->entry) if(frame.pc > f->entry)
runtime·printf(" +%p", (uintptr)(frame.pc - f->entry)); runtime·printf(" +%p", (uintptr)(frame.pc - f->entry));
if(m->throwing && gp == m->curg) if(m->throwing && gp == m->curg)
...@@ -166,14 +173,12 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -166,14 +173,12 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
skipped: skipped:
waspanic = f->entry == (uintptr)runtime·sigpanic; waspanic = f->entry == (uintptr)runtime·sigpanic;
if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
frame.fp += 2*sizeof(uintptr);
// Do not unwind past the bottom of the stack. // Do not unwind past the bottom of the stack.
if(f->entry == (uintptr)runtime·goexit || f->entry == (uintptr)runtime·mstart || f->entry == (uintptr)_rt0_go) if(f->entry == (uintptr)runtime·goexit || f->entry == (uintptr)runtime·mstart || f->entry == (uintptr)runtime·mcall || f->entry == (uintptr)_rt0_go)
break; break;
// Unwind to next frame. // Unwind to next frame.
frame.fn = flr;
frame.pc = frame.lr; frame.pc = frame.lr;
frame.lr = 0; frame.lr = 0;
frame.sp = frame.fp; frame.sp = frame.fp;
...@@ -189,16 +194,19 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, ...@@ -189,16 +194,19 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
static void static void
printcreatedby(G *gp) printcreatedby(G *gp)
{ {
int32 line;
String file;
uintptr pc, tracepc; uintptr pc, tracepc;
Func *f; Func *f;
// Show what created goroutine, except main goroutine (goid 1). // Show what created goroutine, except main goroutine (goid 1).
if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && gp->goid != 1) { if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && gp->goid != 1) {
runtime·printf("created by %S\n", f->name); runtime·printf("created by %S\n", *f->name);
tracepc = pc; // back up to CALL instruction for funcline. tracepc = pc; // back up to CALL instruction for funcline.
if(pc > f->entry) if(pc > f->entry)
tracepc--; tracepc--;
runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc)); line = runtime·funcline(f, tracepc, &file);
runtime·printf("\t%S:%d", file, line);
if(pc > f->entry) if(pc > f->entry)
runtime·printf(" +%p", (uintptr)(pc - f->entry)); runtime·printf(" +%p", (uintptr)(pc - f->entry));
runtime·printf("\n"); runtime·printf("\n");
......
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