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:
Ian Lance Taylor 2016-10-14 17:20:40 +00:00
parent d2c4425e86
commit db2fb304fe
4 changed files with 44 additions and 125 deletions

View File

@ -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.

View File

@ -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

View File

@ -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;
}

View File

@ -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*));