From db2fb304fe27afd8939aa94a4b11f050e6f625b3 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 14 Oct 2016 17:20:40 +0000 Subject: [PATCH] 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 --- gcc/go/gofrontend/MERGE | 2 +- libgo/go/runtime/symtab.go | 38 +++++++----- libgo/runtime/go-caller.c | 115 ++++++------------------------------- libgo/runtime/runtime.h | 12 ---- 4 files changed, 43 insertions(+), 124 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index cadd8ec1b31..b2f0413da89 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/libgo/go/runtime/symtab.go b/libgo/go/runtime/symtab.go index 7b76f11f3a6..52e2d03d14b 100644 --- a/libgo/go/runtime/symtab.go +++ b/libgo/go/runtime/symtab.go @@ -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 diff --git a/libgo/runtime/go-caller.c b/libgo/runtime/go-caller.c index 34abf6c9ffc..a35d8d73f44 100644 --- a/libgo/runtime/go-caller.c +++ b/libgo/runtime/go-caller.c @@ -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; -} + uintptr val; -/* 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; + if (!__go_symbol_value (pc, &val)) + return 0; + return val; } diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index 96f550ced0b..27b0649f30f 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -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*)); -- 2.30.2