summaryrefslogtreecommitdiffstats
path: root/src/runtime/testdata/testprog/badtraceback.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/runtime/testdata/testprog/badtraceback.go50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/runtime/testdata/testprog/badtraceback.go b/src/runtime/testdata/testprog/badtraceback.go
new file mode 100644
index 0000000..09aa2b8
--- /dev/null
+++ b/src/runtime/testdata/testprog/badtraceback.go
@@ -0,0 +1,50 @@
+// 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 (
+ "runtime"
+ "runtime/debug"
+ "unsafe"
+)
+
+func init() {
+ register("BadTraceback", BadTraceback)
+}
+
+func BadTraceback() {
+ // Disable GC to prevent traceback at unexpected time.
+ debug.SetGCPercent(-1)
+ // Out of an abundance of caution, also make sure that there are
+ // no GCs actively in progress.
+ runtime.GC()
+
+ // Run badLR1 on its own stack to minimize the stack size and
+ // exercise the stack bounds logic in the hex dump.
+ go badLR1()
+ select {}
+}
+
+//go:noinline
+func badLR1() {
+ // We need two frames on LR machines because we'll smash this
+ // frame's saved LR.
+ badLR2(0)
+}
+
+//go:noinline
+func badLR2(arg int) {
+ // Smash the return PC or saved LR.
+ lrOff := unsafe.Sizeof(uintptr(0))
+ if runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" {
+ lrOff = 32 // FIXED_FRAME or sys.MinFrameSize
+ }
+ lrPtr := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&arg)) - lrOff))
+ *lrPtr = 0xbad
+
+ // Print a backtrace. This should include diagnostics for the
+ // bad return PC and a hex dump.
+ panic("backtrace")
+}