-2aa95f1499cf931ef8e95c7958463829276a0f2c
+7e94bac5676afc8188677c98ecb263c78c1a7f8d
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
--- /dev/null
+// 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)
+ }
+}
--- /dev/null
+// 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()
+}
--- /dev/null
+// 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()
+}
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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()
+}
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
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
--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;
}
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
;;
"!"*)