runtime: just do file/line lookup in C, move Func to Go
In order to port stack backtraces to Go, we need the ability to look up file/line information for PC values without allocating memory. This patch moves the handling of Func from C code to Go code, and simplifies the C code to just look up function/file/line/entry information for a PC. Reviewed-on: https://go-review.googlesource.com/31150 From-SVN: r241172
This commit is contained in:
parent
d2c4425e86
commit
db2fb304fe
|
@ -1,4 +1,4 @@
|
|||
911fceabd4c955b2f29f6b532f241a002ca7ad4f
|
||||
993840643e27e52cda7e86e6a775f54443ea5d07
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
|
|
@ -65,19 +65,20 @@ func (ci *Frames) Next() (frame Frame, more bool) {
|
|||
}
|
||||
more = len(ci.callers) > 0
|
||||
|
||||
f, file, line := funcframe(pc, i)
|
||||
if f == nil {
|
||||
// Subtract 1 from PC to undo the 1 we added in callback in
|
||||
// go-callers.c.
|
||||
function, file, line := funcfileline(pc-1, int32(i))
|
||||
if function == "" && file == "" {
|
||||
return Frame{}, more
|
||||
}
|
||||
entry := funcentry(pc - 1)
|
||||
f := &Func{name: function, entry: entry}
|
||||
|
||||
entry := f.Entry()
|
||||
xpc := pc
|
||||
if xpc > entry {
|
||||
xpc--
|
||||
}
|
||||
|
||||
function := f.Name()
|
||||
|
||||
frame = Frame{
|
||||
PC: xpc,
|
||||
Func: f,
|
||||
|
@ -97,21 +98,29 @@ func (ci *Frames) Next() (frame Frame, more bool) {
|
|||
|
||||
// A Func represents a Go function in the running binary.
|
||||
type Func struct {
|
||||
opaque struct{} // unexported field to disallow conversions
|
||||
name string
|
||||
entry uintptr
|
||||
}
|
||||
|
||||
// FuncForPC returns a *Func describing the function that contains the
|
||||
// given program counter address, or else nil.
|
||||
func FuncForPC(pc uintptr) *Func
|
||||
func FuncForPC(pc uintptr) *Func {
|
||||
name, _, _ := funcfileline(pc, -1)
|
||||
if name == "" {
|
||||
return nil
|
||||
}
|
||||
entry := funcentry(pc)
|
||||
return &Func{name: name, entry: entry}
|
||||
}
|
||||
|
||||
// Name returns the name of the function.
|
||||
func (f *Func) Name() string {
|
||||
return funcname_go(f)
|
||||
return f.name
|
||||
}
|
||||
|
||||
// Entry returns the entry address of the function.
|
||||
func (f *Func) Entry() uintptr {
|
||||
return funcentry_go(f)
|
||||
return f.entry
|
||||
}
|
||||
|
||||
// FileLine returns the file name and line number of the
|
||||
|
@ -119,11 +128,10 @@ func (f *Func) Entry() uintptr {
|
|||
// The result will not be accurate if pc is not a program
|
||||
// counter within f.
|
||||
func (f *Func) FileLine(pc uintptr) (file string, line int) {
|
||||
return funcline_go(f, pc)
|
||||
_, file, line = funcfileline(pc, -1)
|
||||
return file, line
|
||||
}
|
||||
|
||||
// implemented in symtab.c
|
||||
func funcline_go(*Func, uintptr) (string, int)
|
||||
func funcname_go(*Func) string
|
||||
func funcentry_go(*Func) uintptr
|
||||
func funcframe(uintptr, int) (*Func, string, int)
|
||||
// implemented in go-caller.c
|
||||
func funcfileline(uintptr, int32) (string, string, int)
|
||||
func funcentry(uintptr) uintptr
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* go-caller.c -- runtime.Caller and runtime.FuncForPC for Go.
|
||||
/* go-caller.c -- look up function/file/line/entry info
|
||||
|
||||
Copyright 2009 The Go Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style
|
||||
|
@ -171,8 +171,6 @@ struct caller_ret
|
|||
|
||||
struct caller_ret Caller (int n) __asm__ (GOSYM_PREFIX "runtime.Caller");
|
||||
|
||||
Func *FuncForPC (uintptr_t) __asm__ (GOSYM_PREFIX "runtime.FuncForPC");
|
||||
|
||||
/* Implement runtime.Caller. */
|
||||
|
||||
struct caller_ret
|
||||
|
@ -193,115 +191,40 @@ Caller (int skip)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Implement runtime.FuncForPC. */
|
||||
/* Look up the function name, file name, and line number for a PC. */
|
||||
|
||||
Func *
|
||||
FuncForPC (uintptr_t pc)
|
||||
{
|
||||
Func *ret;
|
||||
String fn;
|
||||
String file;
|
||||
intgo line;
|
||||
uintptr_t val;
|
||||
|
||||
if (!__go_file_line (pc, -1, &fn, &file, &line))
|
||||
return NULL;
|
||||
|
||||
ret = (Func *) runtime_malloc (sizeof (*ret));
|
||||
ret->name = fn;
|
||||
|
||||
if (__go_symbol_value (pc, &val))
|
||||
ret->entry = val;
|
||||
else
|
||||
ret->entry = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Look up the file and line information for a PC within a
|
||||
function. */
|
||||
|
||||
struct funcline_go_return
|
||||
struct funcfileline_return
|
||||
{
|
||||
String retfn;
|
||||
String retfile;
|
||||
intgo retline;
|
||||
};
|
||||
|
||||
struct funcline_go_return
|
||||
runtime_funcline_go (Func *f, uintptr targetpc)
|
||||
__asm__ (GOSYM_PREFIX "runtime.funcline_go");
|
||||
struct funcfileline_return
|
||||
runtime_funcfileline (uintptr targetpc, int32 index)
|
||||
__asm__ (GOSYM_PREFIX "runtime.funcfileline");
|
||||
|
||||
struct funcline_go_return
|
||||
runtime_funcline_go (Func *f __attribute__((unused)), uintptr targetpc)
|
||||
struct funcfileline_return
|
||||
runtime_funcfileline (uintptr targetpc, int32 index)
|
||||
{
|
||||
struct funcline_go_return ret;
|
||||
String fn;
|
||||
struct funcfileline_return ret;
|
||||
|
||||
if (!__go_file_line (targetpc, -1, &fn, &ret.retfile, &ret.retline))
|
||||
if (!__go_file_line (targetpc, index, &ret.retfn, &ret.retfile,
|
||||
&ret.retline))
|
||||
runtime_memclr (&ret, sizeof ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return the name of a function. */
|
||||
String runtime_funcname_go (Func *f)
|
||||
__asm__ (GOSYM_PREFIX "runtime.funcname_go");
|
||||
|
||||
String
|
||||
runtime_funcname_go (Func *f)
|
||||
{
|
||||
if (f == NULL)
|
||||
return runtime_gostringnocopy ((const byte *) "");
|
||||
return f->name;
|
||||
}
|
||||
|
||||
/* Return the entry point of a function. */
|
||||
uintptr runtime_funcentry_go(Func *f)
|
||||
__asm__ (GOSYM_PREFIX "runtime.funcentry_go");
|
||||
uintptr runtime_funcentry(uintptr)
|
||||
__asm__ (GOSYM_PREFIX "runtime.funcentry");
|
||||
|
||||
uintptr
|
||||
runtime_funcentry_go (Func *f)
|
||||
runtime_funcentry (uintptr pc)
|
||||
{
|
||||
return f->entry;
|
||||
}
|
||||
|
||||
/* Look up file and line information for Frames.Next. */
|
||||
|
||||
struct funcframe_return
|
||||
{
|
||||
Func* retfunc;
|
||||
String retfile;
|
||||
intgo retline;
|
||||
};
|
||||
|
||||
struct funcframe_return
|
||||
runtime_funcframe (uintptr pc, int index)
|
||||
__asm__ (GOSYM_PREFIX "runtime.funcframe");
|
||||
|
||||
struct funcframe_return
|
||||
runtime_funcframe (uintptr pc, int index)
|
||||
{
|
||||
struct funcframe_return ret;
|
||||
String fn;
|
||||
Func* func;
|
||||
uintptr_t val;
|
||||
|
||||
// Subtract 1 from PC to undo the 1 we added in callback in go-callers.c.
|
||||
--pc;
|
||||
|
||||
if (!__go_file_line (pc, index, &fn, &ret.retfile, &ret.retline))
|
||||
runtime_memclr (&ret, sizeof ret);
|
||||
else
|
||||
{
|
||||
func = (Func *) runtime_malloc (sizeof (*func));
|
||||
func->name = fn;
|
||||
|
||||
if (__go_symbol_value (pc, &val))
|
||||
func->entry = val;
|
||||
else
|
||||
func->entry = 0;
|
||||
|
||||
ret.retfunc = func;
|
||||
}
|
||||
|
||||
return ret;
|
||||
uintptr val;
|
||||
|
||||
if (!__go_symbol_value (pc, &val))
|
||||
return 0;
|
||||
return val;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@ typedef uintptr uintreg;
|
|||
|
||||
typedef uint8 bool;
|
||||
typedef uint8 byte;
|
||||
typedef struct Func Func;
|
||||
typedef struct g G;
|
||||
typedef struct mutex Lock;
|
||||
typedef struct m M;
|
||||
|
@ -153,16 +152,6 @@ struct SigTab
|
|||
void* fwdsig;
|
||||
};
|
||||
|
||||
// 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;
|
||||
uintptr entry; // entry pc
|
||||
};
|
||||
|
||||
#ifdef GOOS_nacl
|
||||
enum {
|
||||
NaCl = 1,
|
||||
|
@ -446,7 +435,6 @@ void runtime_crash(void);
|
|||
void runtime_parsedebugvars(void)
|
||||
__asm__(GOSYM_PREFIX "runtime.parsedebugvars");
|
||||
void _rt0_go(void);
|
||||
void* runtime_funcdata(Func*, int32);
|
||||
int32 runtime_setmaxthreads(int32);
|
||||
G* runtime_timejump(void);
|
||||
void runtime_iterate_finq(void (*callback)(FuncVal*, void*, const FuncType*, const PtrType*));
|
||||
|
|
Loading…
Reference in New Issue