libgo patch committed: just do flie/line lookup in C, move Func to Go

Ian Lance Taylor iant@golang.org
Fri Oct 14 17:20:00 GMT 2016


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 libgo 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.  Bootstrapped and ran Go testsuite on
x86_64-pc-linux-gnu.  Committed to mainline.

Ian
-------------- next part --------------
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 241171)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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: libgo/go/runtime/symtab.go
===================================================================
--- libgo/go/runtime/symtab.go	(revision 240942)
+++ libgo/go/runtime/symtab.go	(working copy)
@@ -65,19 +65,20 @@ func (ci *Frames) Next() (frame Frame, m
 	}
 	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, m
 
 // 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: libgo/runtime/go-caller.c
===================================================================
--- libgo/runtime/go-caller.c	(revision 240942)
+++ libgo/runtime/go-caller.c	(working copy)
@@ -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.  */
-
-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.  */
+/* Look up the function name, file name, and line number for a PC.  */
 
-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.  */
+  uintptr val;
 
-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: libgo/runtime/runtime.h
===================================================================
--- libgo/runtime/runtime.h	(revision 241163)
+++ libgo/runtime/runtime.h	(working copy)
@@ -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*));


More information about the Gcc-patches mailing list