aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2018-02-08 15:37:43 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2018-02-08 15:37:43 +0000
commit22b83eeea664106638d6d01952bb9f3207b039b5 (patch)
treef26b729ad50f3c18a319ff63f115f7eeb5c01eb5 /libgo
parentf90e86cfd8ce6875498d527bab2275ae7431cb89 (diff)
runtime: get missing function name from symbol table
If we trace back through code that has no debug info, as when calling through C code compiled with -g0, we won't have a function name. Try to fetch the function name using the symbol table. Adding the test case revealed that gotest failed to use the gccgo tag when matching files, so add that. Reviewed-on: https://go-review.googlesource.com/92756 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257495 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/runtime/crash_gccgo_test.go59
-rw-r--r--libgo/go/runtime/testdata/testprogcgo/traceback_gccgo.go40
-rw-r--r--libgo/go/runtime/testdata/testprogcxx/main.go35
-rw-r--r--libgo/go/runtime/testdata/testprogcxx/traceback.cc19
-rw-r--r--libgo/go/runtime/testdata/testprogcxx/traceback.go24
-rw-r--r--libgo/runtime/go-callers.c32
-rwxr-xr-xlibgo/testsuite/gotest8
7 files changed, 211 insertions, 6 deletions
diff --git a/libgo/go/runtime/crash_gccgo_test.go b/libgo/go/runtime/crash_gccgo_test.go
new file mode 100644
index 00000000000..c216e542ce8
--- /dev/null
+++ b/libgo/go/runtime/crash_gccgo_test.go
@@ -0,0 +1,59 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build cgo,gccgo
+
+package runtime_test
+
+import (
+ "bytes"
+ "fmt"
+ "internal/testenv"
+ "os"
+ "os/exec"
+ "strings"
+ "testing"
+)
+
+func TestGccgoCrashTraceback(t *testing.T) {
+ t.Parallel()
+ got := runTestProg(t, "testprogcgo", "CrashTracebackGccgo")
+ ok := true
+ for i := 1; i <= 3; i++ {
+ if !strings.Contains(got, fmt.Sprintf("CFunction%d", i)) {
+ t.Errorf("missing C function CFunction%d", i)
+ ok = false
+ }
+ }
+ if !ok {
+ t.Log(got)
+ }
+}
+
+func TestGccgoCrashTracebackNodebug(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+ if os.Getenv("CC") == "" {
+ t.Skip("no compiler in environment")
+ }
+
+ cc := strings.Fields(os.Getenv("CC"))
+ cc = append(cc, "-x", "c++", "-")
+ out, _ := exec.Command(cc[0], cc[1:]...).CombinedOutput()
+ if bytes.Contains(out, []byte("error trying to exec 'cc1plus'")) {
+ t.Skip("no C++ compiler")
+ }
+ os.Setenv("CXX", os.Getenv("CC"))
+
+ got := runTestProg(t, "testprogcxx", "CrashTracebackNodebug")
+ ok := true
+ for i := 1; i <= 3; i++ {
+ if !strings.Contains(got, fmt.Sprintf("cxxFunction%d", i)) {
+ t.Errorf("missing C++ function cxxFunction%d", i)
+ ok = false
+ }
+ }
+ if !ok {
+ t.Log(got)
+ }
+}
diff --git a/libgo/go/runtime/testdata/testprogcgo/traceback_gccgo.go b/libgo/go/runtime/testdata/testprogcgo/traceback_gccgo.go
new file mode 100644
index 00000000000..83357fdd5d9
--- /dev/null
+++ b/libgo/go/runtime/testdata/testprogcgo/traceback_gccgo.go
@@ -0,0 +1,40 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gccgo
+
+package main
+
+// This program will crash.
+// We want the stack trace to include the C functions.
+
+/*
+#cgo CFLAGS: -g -O0
+
+#include <stdint.h>
+
+char *p;
+
+static int CFunction3(void) {
+ *p = 0;
+ return 0;
+}
+
+static int CFunction2(void) {
+ return CFunction3();
+}
+
+static int CFunction1(void) {
+ return CFunction2();
+}
+*/
+import "C"
+
+func init() {
+ register("CrashTracebackGccgo", CrashTracebackGccgo)
+}
+
+func CrashTracebackGccgo() {
+ C.CFunction1()
+}
diff --git a/libgo/go/runtime/testdata/testprogcxx/main.go b/libgo/go/runtime/testdata/testprogcxx/main.go
new file mode 100644
index 00000000000..0ecab1079c6
--- /dev/null
+++ b/libgo/go/runtime/testdata/testprogcxx/main.go
@@ -0,0 +1,35 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "os"
+
+var cmds = map[string]func(){}
+
+func register(name string, f func()) {
+ if cmds[name] != nil {
+ panic("duplicate registration: " + name)
+ }
+ cmds[name] = f
+}
+
+func registerInit(name string, f func()) {
+ if len(os.Args) >= 2 && os.Args[1] == name {
+ f()
+ }
+}
+
+func main() {
+ if len(os.Args) < 2 {
+ println("usage: " + os.Args[0] + " name-of-test")
+ return
+ }
+ f := cmds[os.Args[1]]
+ if f == nil {
+ println("unknown function: " + os.Args[1])
+ return
+ }
+ f()
+}
diff --git a/libgo/go/runtime/testdata/testprogcxx/traceback.cc b/libgo/go/runtime/testdata/testprogcxx/traceback.cc
new file mode 100644
index 00000000000..d4bd26cf768
--- /dev/null
+++ b/libgo/go/runtime/testdata/testprogcxx/traceback.cc
@@ -0,0 +1,19 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+char *p;
+
+static int cxxFunction3() {
+ *p = 0;
+ return 0;
+}
+
+static int cxxFunction2() {
+ return cxxFunction3();
+}
+
+extern "C"
+int cxxFunction1() {
+ return cxxFunction2();
+}
diff --git a/libgo/go/runtime/testdata/testprogcxx/traceback.go b/libgo/go/runtime/testdata/testprogcxx/traceback.go
new file mode 100644
index 00000000000..0e40ca8ffbb
--- /dev/null
+++ b/libgo/go/runtime/testdata/testprogcxx/traceback.go
@@ -0,0 +1,24 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// This program will crash.
+// We want the stack trace to include the C++ functions,
+// even though we compile with -g0.
+
+/*
+#cgo CXXFLAGS: -g0 -O0
+
+extern int cxxFunction1(void);
+*/
+import "C"
+
+func init() {
+ register("CrashTracebackNodebug", CrashTracebackNodebug)
+}
+
+func CrashTracebackNodebug() {
+ C.cxxFunction1()
+}
diff --git a/libgo/runtime/go-callers.c b/libgo/runtime/go-callers.c
index 2eaac682779..590315376e3 100644
--- a/libgo/runtime/go-callers.c
+++ b/libgo/runtime/go-callers.c
@@ -143,6 +143,20 @@ callback (void *data, uintptr_t pc, const char *filename, int lineno,
return arg->index >= arg->max;
}
+/* Syminfo callback. */
+
+static void
+syminfo_fnname_callback (void *data, uintptr_t pc __attribute__ ((unused)),
+ const char *symname,
+ uintptr_t address __attribute__ ((unused)),
+ uintptr_t size __attribute__ ((unused)))
+{
+ Location* locptr = (Location*) data;
+
+ if (symname != NULL)
+ locptr->function = runtime_gostringnocopy ((const byte *) symname);
+}
+
/* Error callback. */
static void
@@ -179,15 +193,17 @@ int32
runtime_callers (int32 skip, Location *locbuf, int32 m, bool keep_thunks)
{
struct callers_data data;
+ struct backtrace_state* state;
+ int32 i;
data.locbuf = locbuf;
data.skip = skip + 1;
data.index = 0;
data.max = m;
data.keep_thunks = keep_thunks;
+ state = __go_get_backtrace_state ();
runtime_xadd (&runtime_in_callers, 1);
- backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback,
- &data);
+ backtrace_full (state, 0, callback, error_callback, &data);
runtime_xadd (&runtime_in_callers, -1);
/* For some reason GCC sometimes loses the name of a thunk function
@@ -204,6 +220,18 @@ runtime_callers (int32 skip, Location *locbuf, int32 m, bool keep_thunks)
--data.index;
}
+ /* Try to use backtrace_syminfo to fill in any missing function
+ names. This can happen when tracing through an object which has
+ no debug info; backtrace_syminfo will look at the symbol table to
+ get the name. This should only happen when tracing through code
+ that is not written in Go and is not part of libgo. */
+ for (i = 0; i < data.index; ++i)
+ {
+ if (locbuf[i].function.len == 0 && locbuf[i].pc != 0)
+ backtrace_syminfo (state, locbuf[i].pc, syminfo_fnname_callback,
+ error_callback, &locbuf[i]);
+ }
+
return data.index;
}
diff --git a/libgo/testsuite/gotest b/libgo/testsuite/gotest
index f5c908adef8..f978042cccc 100755
--- a/libgo/testsuite/gotest
+++ b/libgo/testsuite/gotest
@@ -348,18 +348,18 @@ x)
fi
match=false
;;
- $goos | $goarch | cgo | go1.[0-9])
+ $goos | $goarch | cgo | gccgo | go1.[0-9])
match=true
;;
- "!"$goos | "!"$goarch | "!cgo" | "!"go1.[0-9])
+ "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!"go1.[0-9])
;;
*,*)
cmatch=true
for ctag in `echo $tag | sed -e 's/,/ /g'`; do
case $ctag in
- $goos | $goarch | cgo | go1.[0-9])
+ $goos | $goarch | cgo | gccgo | go1.[0-9])
;;
- "!"$goos | "!"$goarch | "!cgo" | "!"go1.[0-9])
+ "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!"go1.[0-9])
cmatch=false
;;
"!"*)