From 74e6f14adb7057b29d361cc35c76f16663d1e649 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 8 Feb 2018 15:37:43 +0000 Subject: 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 From-SVN: r257495 --- libgo/go/runtime/crash_gccgo_test.go | 59 ++++++++++++++++++++++ .../testdata/testprogcgo/traceback_gccgo.go | 40 +++++++++++++++ libgo/go/runtime/testdata/testprogcxx/main.go | 35 +++++++++++++ libgo/go/runtime/testdata/testprogcxx/traceback.cc | 19 +++++++ libgo/go/runtime/testdata/testprogcxx/traceback.go | 24 +++++++++ 5 files changed, 177 insertions(+) create mode 100644 libgo/go/runtime/crash_gccgo_test.go create mode 100644 libgo/go/runtime/testdata/testprogcgo/traceback_gccgo.go create mode 100644 libgo/go/runtime/testdata/testprogcxx/main.go create mode 100644 libgo/go/runtime/testdata/testprogcxx/traceback.cc create mode 100644 libgo/go/runtime/testdata/testprogcxx/traceback.go (limited to 'libgo/go') diff --git a/libgo/go/runtime/crash_gccgo_test.go b/libgo/go/runtime/crash_gccgo_test.go new file mode 100644 index 0000000..c216e54 --- /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 0000000..83357fd --- /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 + +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 0000000..0ecab10 --- /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 0000000..d4bd26c --- /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 0000000..0e40ca8 --- /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() +} -- cgit v1.1