Commit c3de91bb authored by Russ Cox's avatar Russ Cox

cmd/ld, runtime: use new contiguous pcln table

R=golang-dev, r, dave
CC=golang-dev
https://golang.org/cl/11494043
parent 08ce3c31
......@@ -278,7 +278,6 @@ main(int argc, char *argv[])
span();
addexport();
// textaddress() functionality is handled in span()
functab();
pclntab();
symtab();
dodata();
......
......@@ -289,7 +289,6 @@ main(int argc, char *argv[])
dope();
addexport();
textaddress();
functab();
pclntab();
symtab();
dodata();
......
......@@ -316,7 +316,6 @@ main(int argc, char *argv[])
span();
addexport();
textaddress();
functab();
pclntab();
symtab();
dodata();
......
This diff is collapsed.
......@@ -46,7 +46,7 @@ enum
SFUNCTAB,
STYPELINK,
SSYMTAB, // TODO: move to unmapped section
SPCLNTAB, // TODO: move to unmapped section
SPCLNTAB,
SELFROSECT,
/* writable, non-executable */
......@@ -227,7 +227,6 @@ void objfile(char *file, char *pkg);
void libinit(void);
void pclntab(void);
void symtab(void);
void functab(void);
void Lflag(char *arg);
void usage(void);
void adddynrel(Sym*, Reloc*);
......
......@@ -371,7 +371,7 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
Reloc *rel;
USED(size);
// type byte
if('A' <= t && t <= 'Z')
c = t - 'A' + (ver ? 26 : 0);
......
......@@ -1383,6 +1383,8 @@ addroot(Obj obj)
work.nroot++;
}
extern byte pclntab[]; // base for f->ptrsoff
// Scan a stack frame: local variables and function arguments/results.
static void
addframeroots(Stkframe *frame, void*)
......@@ -1402,7 +1404,7 @@ addframeroots(Stkframe *frame, void*)
if(f->args > 0 && f->ptrslen > 0) {
ap = frame->argp;
nuintptr = f->args / sizeof(uintptr);
ptrs = (uint32*)((byte*)f + f->ptrsoff);
ptrs = (uint32*)(pclntab + f->ptrsoff);
for(i = 0; i < f->ptrslen; i++) {
w = ptrs[i];
b = 1;
......
......@@ -402,12 +402,14 @@ enum
SigIgnored = 1<<6, // the signal was ignored before we registered for it
};
// layout of in-memory per-function information prepared by linker
// Layout of in-memory per-function information prepared by linker
// See http://golang.org/s/go12symtab.
// Keep in sync with linker and with ../../libmach/sym.c
// and with package debug/gosym.
struct Func
{
String *name; // function name
uintptr entry; // start pc
int32 nameoff; // function name
// TODO: Remove these fields.
int32 args; // in/out args size
......@@ -799,6 +801,7 @@ Func* runtime·findfunc(uintptr);
int32 runtime·funcline(Func*, uintptr, String*);
int32 runtime·funcarglen(Func*, uintptr);
int32 runtime·funcspdelta(Func*, uintptr);
int8* runtime·funcname(Func*);
void* runtime·stackalloc(uint32);
void runtime·stackfree(void*, uintptr);
MCache* runtime·allocmcache(void);
......
......@@ -16,15 +16,15 @@ typedef struct Ftab Ftab;
struct Ftab
{
uintptr entry;
Func *func;
uintptr funcoff;
};
extern uintptr functab[];
extern byte pclntab[];
static Ftab *ftab;
static uintptr nftab;
extern String *filetab[];
static uintptr nfiletab;
static uint32 *filetab;
static uint32 nfiletab;
static String end = { (uint8*)"end", 3 };
......@@ -32,20 +32,32 @@ void
runtime·symtabinit(void)
{
int32 i, j;
ftab = (Ftab*)(functab+1);
nftab = functab[0];
Func *f1, *f2;
// See golang.org/s/go12symtab for header: 0xfffffffb,
// two zero bytes, a byte giving the PC quantum,
// and a byte giving the pointer width in bytes.
if(*(uint32*)pclntab != 0xfffffffb || pclntab[4] != 0 || pclntab[5] != 0 || pclntab[6] != PCQuantum || pclntab[7] != sizeof(void*)) {
runtime·printf("runtime: function symbol table header: 0x%x 0x%x\n", *(uint32*)pclntab, *(uint32*)(pclntab+4));
runtime·throw("invalid function symbol table\n");
}
nftab = *(uintptr*)(pclntab+8);
ftab = (Ftab*)(pclntab+8+sizeof(void*));
for(i=0; i<nftab; i++) {
// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
if(ftab[i].entry > ftab[i+1].entry) {
runtime·printf("function symbol table not sorted by program counter: %p %S > %p %S", ftab[i].entry, *ftab[i].func->name, ftab[i+1].entry, i+1 == nftab ? end : *ftab[i+1].func->name);
f1 = (Func*)(pclntab + ftab[i].funcoff);
f2 = (Func*)(pclntab + ftab[i+1].funcoff);
runtime·printf("function symbol table not sorted by program counter: %p %s > %p %s", ftab[i].entry, runtime·funcname(f1), ftab[i+1].entry, i+1 == nftab ? "end" : runtime·funcname(f2));
for(j=0; j<=i; j++)
runtime·printf("\t%p %S\n", ftab[j].entry, *ftab[j].func->name);
runtime·printf("\t%p %s\n", ftab[j].entry, runtime·funcname((Func*)(pclntab + ftab[j].funcoff)));
runtime·throw("invalid runtime symbol table");
}
}
nfiletab = (uintptr)filetab[0];
filetab = (uint32*)(pclntab + *(uint32*)&ftab[nftab].funcoff);
nfiletab = filetab[0];
}
static uint32
......@@ -79,6 +91,26 @@ funcdata(Func *f, int32 i)
return ((uintptr*)p)[i];
}
static bool
step(byte **pp, uintptr *pc, int32 *value, bool first)
{
uint32 uvdelta, pcdelta;
int32 vdelta;
uvdelta = readvarint(pp);
if(uvdelta == 0 && !first)
return 0;
if(uvdelta&1)
uvdelta = ~(uvdelta>>1);
else
uvdelta >>= 1;
vdelta = (int32)uvdelta;
pcdelta = readvarint(pp) * PCQuantum;
*value += vdelta;
*pc += pcdelta;
return 1;
}
// Return associated data value for targetpc in func f.
// (Source file is f->src.)
static int32
......@@ -86,8 +118,7 @@ pcvalue(Func *f, int32 off, uintptr targetpc, bool strict)
{
byte *p;
uintptr pc;
int32 value, vdelta;
uint32 uvdelta, pcdelta;
int32 value;
enum {
debug = 0
......@@ -101,26 +132,15 @@ pcvalue(Func *f, int32 off, uintptr targetpc, bool strict)
// The table ends at a value delta of 0 except in the first pair.
if(off == 0)
return -1;
p = (byte*)f + off;
p = pclntab + off;
pc = f->entry;
value = -1;
if(debug && !runtime·panicking)
runtime·printf("pcvalue start f=%S [%p] pc=%p targetpc=%p value=%d tab=%p\n",
*f->name, f, pc, targetpc, value, p);
runtime·printf("pcvalue start f=%s [%p] pc=%p targetpc=%p value=%d tab=%p\n",
runtime·funcname(f), f, pc, targetpc, value, p);
for(;;) {
uvdelta = readvarint(&p);
if(uvdelta == 0 && pc != f->entry)
break;
if(uvdelta&1)
uvdelta = ~(uvdelta>>1);
else
uvdelta >>= 1;
vdelta = (int32)uvdelta;
pcdelta = readvarint(&p) * PCQuantum;
value += vdelta;
pc += pcdelta;
while(step(&p, &pc, &value, pc == f->entry)) {
if(debug)
runtime·printf("\tvalue=%d until pc=%p\n", value, pc);
if(targetpc < pc)
......@@ -131,25 +151,14 @@ pcvalue(Func *f, int32 off, uintptr targetpc, bool strict)
// If not, something is wrong.
if(runtime·panicking || !strict)
return -1;
runtime·printf("runtime: invalid pc-encoded table f=%S pc=%p targetpc=%p tab=%p\n",
*f->name, pc, targetpc, p);
runtime·printf("runtime: invalid pc-encoded table f=%s pc=%p targetpc=%p tab=%p\n",
runtime·funcname(f), pc, targetpc, p);
p = (byte*)f + off;
pc = f->entry;
value = -1;
for(;;) {
uvdelta = readvarint(&p);
if(uvdelta == 0 && pc != f->entry)
break;
if(uvdelta&1)
uvdelta = ~(uvdelta>>1);
else
uvdelta >>= 1;
vdelta = (int32)uvdelta;
pcdelta = readvarint(&p) * PCQuantum;
value += vdelta;
pc += pcdelta;
while(step(&p, &pc, &value, pc == f->entry))
runtime·printf("\tvalue=%d until pc=%p\n", value, pc);
}
runtime·throw("invalid runtime symbol table");
return -1;
......@@ -157,6 +166,14 @@ pcvalue(Func *f, int32 off, uintptr targetpc, bool strict)
static String unknown = { (uint8*)"?", 1 };
int8*
runtime·funcname(Func *f)
{
if(f == nil || f->nameoff == 0)
return nil;
return (int8*)(pclntab + f->nameoff);
}
static int32
funcline(Func *f, uintptr targetpc, String *file, bool strict)
{
......@@ -170,7 +187,7 @@ funcline(Func *f, uintptr targetpc, String *file, bool strict)
// runtime·printf("looking for %p in %S got file=%d line=%d\n", targetpc, *f->name, fileno, line);
return 0;
}
*file = *filetab[fileno];
*file = runtime·gostringnocopy(pclntab + filetab[fileno]);
return line;
}
......@@ -219,7 +236,7 @@ runtime·funcline_go(Func *f, uintptr targetpc, String retfile, intgo retline)
void
runtime·funcname_go(Func *f, String ret)
{
ret = *f->name;
ret = runtime·gostringnocopy((uint8*)runtime·funcname(f));
FLUSH(&ret);
}
......@@ -247,7 +264,7 @@ runtime·findfunc(uintptr addr)
while(nf > 0) {
n = nf/2;
if(f[n].entry <= addr && addr < f[n+1].entry)
return f[n].func;
return (Func*)(pclntab + f[n].funcoff);
else if(addr < f[n].entry)
nf = n;
else {
......@@ -298,10 +315,12 @@ bool
runtime·showframe(Func *f, G *gp)
{
static int32 traceback = -1;
String name;
if(m->throwing && gp != nil && (gp == m->curg || gp == m->caughtsig))
return 1;
if(traceback < 0)
traceback = runtime·gotraceback(nil);
return traceback > 1 || f != nil && contains(*f->name, ".") && !hasprefix(*f->name, "runtime.");
name = runtime·gostringnocopy((uint8*)runtime·funcname(f));
return traceback > 1 || f != nil && contains(name, ".") && !hasprefix(name, "runtime.");
}
......@@ -88,7 +88,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.lr = *(uintptr*)frame.sp;
flr = runtime·findfunc(frame.lr);
if(flr == nil) {
runtime·printf("runtime: unexpected return pc for %S called from %p", *f->name, frame.lr);
runtime·printf("runtime: unexpected return pc for %s called from %p\n", runtime·funcname(f), frame.lr);
runtime·throw("unknown caller pc");
}
}
......@@ -110,8 +110,8 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
else if((i = runtime·funcarglen(flr, frame.lr)) >= 0)
frame.arglen = i;
else {
runtime·printf("runtime: unknown argument frame size for %S called from %p [%S]\n",
*f->name, frame.lr, flr ? *flr->name : unknown);
runtime·printf("runtime: unknown argument frame size for %s called from %p [%s]\n",
runtime·funcname(f), frame.lr, flr ? runtime·funcname(flr) : "?");
if(!printing)
runtime·throw("invalid stack");
frame.arglen = 0;
......@@ -130,7 +130,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.varlen = frame.fp - frame.sp;
} else {
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, runtime·funcname(f));
runtime·throw("invalid stack");
}
frame.varp = (byte*)frame.fp - f->locals;
......@@ -155,7 +155,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
tracepc = frame.pc; // back up to CALL instruction for funcline.
if(n > 0 && frame.pc > f->entry && !waspanic)
tracepc -= sizeof(uintptr);
runtime·printf("%S(", *f->name);
runtime·printf("%s(", runtime·funcname(f));
for(i = 0; i < frame.arglen/sizeof(uintptr); i++) {
if(i >= 5) {
runtime·prints(", ...");
......@@ -220,7 +220,7 @@ printcreatedby(G *gp)
if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
&& runtime·showframe(f, gp) && gp->goid != 1) {
runtime·printf("created by %S\n", *f->name);
runtime·printf("created by %s\n", runtime·funcname(f));
tracepc = pc; // back up to CALL instruction for funcline.
if(pc > f->entry)
tracepc -= sizeof(uintptr);
......
......@@ -104,7 +104,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.lr = ((uintptr*)frame.fp)[-1];
flr = runtime·findfunc(frame.lr);
if(flr == nil) {
runtime·printf("runtime: unexpected return pc for %S called from %p", *f->name, frame.lr);
runtime·printf("runtime: unexpected return pc for %s called from %p", runtime·funcname(f), frame.lr);
runtime·throw("unknown caller pc");
}
}
......@@ -126,8 +126,8 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
else if((i = runtime·funcarglen(flr, frame.lr)) >= 0)
frame.arglen = i;
else {
runtime·printf("runtime: unknown argument frame size for %S called from %p [%S]\n",
*f->name, frame.lr, flr ? *flr->name : unknown);
runtime·printf("runtime: unknown argument frame size for %s called from %p [%s]\n",
runtime·funcname(f), frame.lr, flr ? runtime·funcname(flr) : "?");
if(!printing)
runtime·throw("invalid stack");
frame.arglen = 0;
......@@ -146,7 +146,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.varlen = frame.fp - sizeof(uintptr) - frame.sp;
} else {
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, runtime·funcname(f));
runtime·throw("invalid stack");
}
frame.varp = (byte*)frame.fp - sizeof(uintptr) - f->locals;
......@@ -171,7 +171,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
tracepc = frame.pc; // back up to CALL instruction for funcline.
if(n > 0 && frame.pc > f->entry && !waspanic)
tracepc--;
runtime·printf("%S(", *f->name);
runtime·printf("%s(", runtime·funcname(f));
for(i = 0; i < frame.arglen/sizeof(uintptr); i++) {
if(i >= 5) {
runtime·prints(", ...");
......@@ -225,7 +225,7 @@ printcreatedby(G *gp)
// Show what created goroutine, except main goroutine (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", runtime·funcname(f));
tracepc = pc; // back up to CALL instruction for funcline.
if(pc > f->entry)
tracepc--;
......
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