mirror of
https://github.com/golang/go
synced 2024-11-22 12:04:46 -07:00
use pc/ln table to print source lines in traceback
r45=; 6.out oops panic PC=0x400316 0x400316?zi /home/rsc/go/src/runtime/rt0_amd64_linux.s:83 main·g(4195177, 0, 4205661, ...) main·g(0x400369, 0x402c5d, 0x403e49, ...) 0x40034c?zi /home/rsc/go/src/runtime/x.go:24 main·f(4205661, 0, 4210249, ...) main·f(0x402c5d, 0x403e49, 0x1, ...) 0x400368?zi /home/rsc/go/src/runtime/x.go:37 main·main(4210249, 0, 1, ...) main·main(0x403e49, 0x1, 0x7fff9d894bd8, ...) 0x402c5c?zi /home/rsc/go/src/runtime/rt0_amd64.s:70 mainstart(1, 0, 2643020760, ...) mainstart(0x1, 0x7fff9d894bd8, 0x0, ...) r45=; R=r DELTA=251 (198 added, 25 deleted, 28 changed) OCL=19965 CL=19979
This commit is contained in:
parent
afff0ff1b8
commit
a5433369aa
@ -11,8 +11,6 @@ extern uint8 end;
|
||||
void
|
||||
traceback(uint8 *pc, uint8 *sp, void* r15)
|
||||
{
|
||||
int32 spoff;
|
||||
int8* spp;
|
||||
uint8* callpc;
|
||||
int32 counter;
|
||||
int32 i;
|
||||
@ -60,7 +58,11 @@ traceback(uint8 *pc, uint8 *sp, void* r15)
|
||||
/* print this frame */
|
||||
prints("0x");
|
||||
sys·printpointer(callpc - 1); // -1 to get to CALL instr.
|
||||
prints("?zi\n");
|
||||
prints("?zi ");
|
||||
sys·printstring(f->src);
|
||||
prints(":");
|
||||
sys·printint(funcline(f, (uint64)callpc-1)); // -1 to get to CALL instr.
|
||||
prints("\n");
|
||||
prints("\t");
|
||||
sys·printstring(name);
|
||||
prints("(");
|
||||
|
@ -189,9 +189,13 @@ struct SigTab
|
||||
struct Func
|
||||
{
|
||||
string name;
|
||||
string type;
|
||||
uint64 entry;
|
||||
int64 frame;
|
||||
string type; // go type string
|
||||
string src; // src file name
|
||||
uint64 entry; // entry pc
|
||||
int64 frame; // stack frame size
|
||||
Array pcln; // pc/ln tab for this func
|
||||
int64 pc0; // starting pc, ln for table
|
||||
int32 ln0;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -261,6 +265,7 @@ void signalstack(byte*, int32);
|
||||
G* malg(int32);
|
||||
void minit(void);
|
||||
Func* findfunc(uint64);
|
||||
int32 funcline(Func*, uint64);
|
||||
|
||||
/*
|
||||
* mutual exclusion locks. in the uncontended case,
|
||||
|
@ -2,21 +2,22 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "runtime.h"
|
||||
// Runtime symbol table access. Work in progress.
|
||||
// The Plan 9 symbol table is not in a particularly convenient form.
|
||||
// The routines here massage it into a more usable form; eventually
|
||||
// we'll change 6l to do this for us, but it is easier to experiment
|
||||
// here than to change 6l and all the other tools.
|
||||
//
|
||||
// The symbol table also needs to be better integrated with the type
|
||||
// strings table in the future. This is just a quick way to get started
|
||||
// and figure out exactly what we want.
|
||||
|
||||
// Runtime symbol table access.
|
||||
// Very much a work in progress.
|
||||
#include "runtime.h"
|
||||
|
||||
#define SYMCOUNTS ((int32*)(0x99LL<<32)) // known to 6l
|
||||
#define SYMDATA ((byte*)(0x99LL<<32) + 8)
|
||||
|
||||
// Return a pointer to a byte array containing the symbol table segment.
|
||||
//
|
||||
// NOTE(rsc): I expect that we will clean up both the method of getting
|
||||
// at the symbol table and the exact format of the symbol table at some
|
||||
// point in the future. It probably needs to be better integrated with
|
||||
// the type strings table too. This is just a quick way to get started
|
||||
// and figure out what we want from/can do with it.
|
||||
void
|
||||
sys·symdat(Array *symtab, Array *pclntab)
|
||||
{
|
||||
@ -50,7 +51,7 @@ struct Sym
|
||||
};
|
||||
|
||||
// Walk over symtab, calling fn(&s) for each symbol.
|
||||
void
|
||||
static void
|
||||
walksymtab(void (*fn)(Sym*))
|
||||
{
|
||||
int32 *v;
|
||||
@ -68,10 +69,10 @@ walksymtab(void (*fn)(Sym*))
|
||||
break;
|
||||
s.symtype = p[4] & ~0x80;
|
||||
p += 5;
|
||||
s.name = p;
|
||||
if(s.symtype == 'z' || s.symtype == 'Z') {
|
||||
// path reference string - skip first byte,
|
||||
// then 2-byte pairs ending at two zeros.
|
||||
// for now, just skip over it and ignore it.
|
||||
q = p+1;
|
||||
for(;;) {
|
||||
if(q+2 > ep)
|
||||
@ -81,12 +82,10 @@ walksymtab(void (*fn)(Sym*))
|
||||
q += 2;
|
||||
}
|
||||
p = q+2;
|
||||
s.name = nil;
|
||||
}else{
|
||||
q = mchr(p, '\0', ep);
|
||||
if(q == nil)
|
||||
break;
|
||||
s.name = p;
|
||||
p = q+1;
|
||||
}
|
||||
q = mchr(p, '\0', ep);
|
||||
@ -100,33 +99,198 @@ walksymtab(void (*fn)(Sym*))
|
||||
|
||||
// Symtab walker; accumulates info about functions.
|
||||
|
||||
Func *func;
|
||||
int32 nfunc;
|
||||
static Func *func;
|
||||
static int32 nfunc;
|
||||
|
||||
static byte **fname;
|
||||
static int32 nfname;
|
||||
|
||||
static void
|
||||
dofunc(Sym *sym)
|
||||
{
|
||||
static byte *lastfuncname;
|
||||
static Func *lastfunc;
|
||||
Func *f;
|
||||
|
||||
if(lastfunc && sym->symtype == 'm') {
|
||||
lastfunc->frame = sym->value;
|
||||
return;
|
||||
}
|
||||
if(sym->symtype != 'T' && sym->symtype != 't')
|
||||
return;
|
||||
if(strcmp(sym->name, (byte*)"etext") == 0)
|
||||
return;
|
||||
if(func == nil) {
|
||||
nfunc++;
|
||||
return;
|
||||
switch(sym->symtype) {
|
||||
case 't':
|
||||
case 'T':
|
||||
if(strcmp(sym->name, (byte*)"etext") == 0)
|
||||
break;
|
||||
if(func == nil) {
|
||||
nfunc++;
|
||||
break;
|
||||
}
|
||||
f = &func[nfunc++];
|
||||
f->name = gostring(sym->name);
|
||||
f->entry = sym->value;
|
||||
break;
|
||||
case 'm':
|
||||
if(nfunc > 0 && func != nil)
|
||||
func[nfunc-1].frame = sym->value;
|
||||
break;
|
||||
case 'f':
|
||||
if(fname == nil) {
|
||||
if(sym->value >= nfname)
|
||||
nfname = sym->value+1;
|
||||
break;
|
||||
}
|
||||
fname[sym->value] = sym->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
f = &func[nfunc++];
|
||||
f->name = gostring(sym->name);
|
||||
f->entry = sym->value;
|
||||
lastfunc = f;
|
||||
// put together the path name for a z entry.
|
||||
// the f entries have been accumulated into fname already.
|
||||
static void
|
||||
makepath(byte *buf, int32 nbuf, byte *path)
|
||||
{
|
||||
int32 n, len;
|
||||
byte *p, *ep, *q;
|
||||
|
||||
if(nbuf <= 0)
|
||||
return;
|
||||
|
||||
p = buf;
|
||||
ep = buf + nbuf;
|
||||
*p = '\0';
|
||||
for(;;) {
|
||||
if(path[0] == 0 && path[1] == 0)
|
||||
break;
|
||||
n = (path[0]<<8) | path[1];
|
||||
path += 2;
|
||||
if(n >= nfname)
|
||||
break;
|
||||
q = fname[n];
|
||||
len = findnull(q);
|
||||
if(p+1+len >= ep)
|
||||
break;
|
||||
if(p > buf && p[-1] != '/')
|
||||
*p++ = '/';
|
||||
mcpy(p, q, len+1);
|
||||
p += len;
|
||||
}
|
||||
}
|
||||
|
||||
// walk symtab accumulating path names for use by pc/ln table.
|
||||
// don't need the full generality of the z entry history stack because
|
||||
// there are no includes in go (and only sensible includes in our c).
|
||||
static void
|
||||
dosrcline(Sym *sym)
|
||||
{
|
||||
static byte srcbuf[1000];
|
||||
static string srcstring;
|
||||
static int32 lno, incstart;
|
||||
static int32 nf, nhist;
|
||||
Func *f;
|
||||
|
||||
switch(sym->symtype) {
|
||||
case 't':
|
||||
case 'T':
|
||||
f = &func[nf++];
|
||||
f->src = srcstring;
|
||||
f->ln0 += lno;
|
||||
break;
|
||||
case 'z':
|
||||
if(sym->value == 1) {
|
||||
// entry for main source file for a new object.
|
||||
makepath(srcbuf, sizeof srcbuf, sym->name+1);
|
||||
srcstring = gostring(srcbuf);
|
||||
lno = 0;
|
||||
nhist = 0;
|
||||
} else {
|
||||
// push or pop of included file.
|
||||
makepath(srcbuf, sizeof srcbuf, sym->name+1);
|
||||
if(srcbuf[0] != '\0') {
|
||||
if(nhist++ == 0)
|
||||
incstart = sym->value;
|
||||
}else{
|
||||
if(--nhist == 0)
|
||||
lno -= sym->value - incstart;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum { PcQuant = 1 };
|
||||
|
||||
// Interpret pc/ln table, saving the subpiece for each func.
|
||||
static void
|
||||
splitpcln(void)
|
||||
{
|
||||
int32 line;
|
||||
uint64 pc;
|
||||
byte *p, *ep;
|
||||
Func *f, *ef;
|
||||
int32 *v;
|
||||
|
||||
// pc/ln table bounds
|
||||
v = SYMCOUNTS;
|
||||
p = SYMDATA;
|
||||
p += v[0];
|
||||
ep = p+v[1];
|
||||
|
||||
f = func;
|
||||
ef = func + nfunc;
|
||||
f->pcln.array = p;
|
||||
pc = func[0].entry; // text base
|
||||
line = 0;
|
||||
for(; p < ep; p++) {
|
||||
if(f < ef && pc >= (f+1)->entry) {
|
||||
f->pcln.nel = p - f->pcln.array;
|
||||
f->pcln.cap = f->pcln.nel;
|
||||
f++;
|
||||
f->pcln.array = p;
|
||||
f->pc0 = pc;
|
||||
f->ln0 = line;
|
||||
}
|
||||
if(*p == 0) {
|
||||
// 4 byte add to line
|
||||
line += (p[1]<<24) | (p[2]<<16) | (p[3]<<8) | p[4];
|
||||
p += 4;
|
||||
} else if(*p <= 64) {
|
||||
line += *p;
|
||||
} else if(*p <= 128) {
|
||||
line -= *p - 64;
|
||||
} else {
|
||||
pc += PcQuant*(*p - 129);
|
||||
}
|
||||
pc += PcQuant;
|
||||
}
|
||||
if(f < ef) {
|
||||
f->pcln.nel = p - f->pcln.array;
|
||||
f->pcln.cap = f->pcln.nel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Return actual file line number for targetpc in func f.
|
||||
// (Source file is f->src.)
|
||||
int32
|
||||
funcline(Func *f, uint64 targetpc)
|
||||
{
|
||||
byte *p, *ep;
|
||||
uint64 pc;
|
||||
int32 line;
|
||||
|
||||
p = f->pcln.array;
|
||||
ep = p + f->pcln.nel;
|
||||
pc = f->pc0;
|
||||
line = f->ln0;
|
||||
for(; p < ep; p++) {
|
||||
if(pc >= targetpc)
|
||||
return line;
|
||||
if(*p == 0) {
|
||||
line += (p[1]<<24) | (p[2]<<16) | (p[3]<<8) | p[4];
|
||||
p += 4;
|
||||
} else if(*p <= 64) {
|
||||
line += *p;
|
||||
} else if(*p <= 128) {
|
||||
line -= *p - 64;
|
||||
} else {
|
||||
pc += PcQuant*(*p - 129);
|
||||
}
|
||||
pc += PcQuant;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -136,19 +300,30 @@ buildfuncs(void)
|
||||
|
||||
if(func != nil)
|
||||
return;
|
||||
// count funcs, fnames
|
||||
nfunc = 0;
|
||||
nfname = 0;
|
||||
walksymtab(dofunc);
|
||||
|
||||
// initialize tables
|
||||
func = mal((nfunc+1)*sizeof func[0]);
|
||||
func[nfunc].entry = (uint64)etext;
|
||||
fname = mal(nfname*sizeof fname[0]);
|
||||
nfunc = 0;
|
||||
walksymtab(dofunc);
|
||||
func[nfunc].entry = (uint64)etext;
|
||||
|
||||
// split pc/ln table by func
|
||||
splitpcln();
|
||||
|
||||
// record src file and line info for each func
|
||||
walksymtab(dosrcline);
|
||||
}
|
||||
|
||||
Func*
|
||||
findfunc(uint64 addr)
|
||||
{
|
||||
Func *f;
|
||||
int32 i, nf, n;
|
||||
int32 nf, n;
|
||||
|
||||
if(func == nil)
|
||||
buildfuncs();
|
||||
@ -157,15 +332,6 @@ findfunc(uint64 addr)
|
||||
if(addr < func[0].entry || addr >= func[nfunc].entry)
|
||||
return nil;
|
||||
|
||||
// linear search, for debugging
|
||||
if(0) {
|
||||
for(i=0; i<nfunc; i++) {
|
||||
if(func[i].entry <= addr && addr < func[i+1].entry)
|
||||
return &func[i];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
// binary search to find func with entry <= addr.
|
||||
f = func;
|
||||
nf = nfunc;
|
||||
|
Loading…
Reference in New Issue
Block a user