runtime: just do file/line lookup in C, move Func to Go
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 14 Oct 2016 17:20:40 +0000 (17:20 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 14 Oct 2016 17:20:40 +0000 (17:20 +0000)
    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
libgo/go/runtime/symtab.go
libgo/runtime/go-caller.c
libgo/runtime/runtime.h

index cadd8ec1b310f7b3c07be6d7e4d48560f4a80e50..b2f0413da895d241fdd9de1a532d77716d349a27 100644 (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.
index 7b76f11f3a687faae5a1c21e2814267de8687bbb..52e2d03d14b5a18185966ad8638c18bb4738fcd9 100644 (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
index 34abf6c9ffce2b936a4db37e34a4a7060b896344..a35d8d73f44bbb66a381e99461a34dbb5c5fc076 100644 (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;
-}
+  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;
 }
index 96f550ced0b140c29af66a9e250dd610b82576fd..27b0649f30f922e866df4a01dc03c6be61b0336f 100644 (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*));