Commit db2fb304 by Ian Lance Taylor

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