Home | History | Annotate | Download | only in testprog
      1 // Copyright 2018 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package main
      6 
      7 import (
      8 	"runtime"
      9 	"runtime/debug"
     10 	"unsafe"
     11 )
     12 
     13 func init() {
     14 	register("BadTraceback", BadTraceback)
     15 }
     16 
     17 func BadTraceback() {
     18 	// Disable GC to prevent traceback at unexpected time.
     19 	debug.SetGCPercent(-1)
     20 
     21 	// Run badLR1 on its own stack to minimize the stack size and
     22 	// exercise the stack bounds logic in the hex dump.
     23 	go badLR1()
     24 	select {}
     25 }
     26 
     27 //go:noinline
     28 func badLR1() {
     29 	// We need two frames on LR machines because we'll smash this
     30 	// frame's saved LR.
     31 	badLR2(0)
     32 }
     33 
     34 //go:noinline
     35 func badLR2(arg int) {
     36 	// Smash the return PC or saved LR.
     37 	lrOff := unsafe.Sizeof(uintptr(0))
     38 	if runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" {
     39 		lrOff = 32 // FIXED_FRAME or sys.MinFrameSize
     40 	}
     41 	lrPtr := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&arg)) - lrOff))
     42 	*lrPtr = 0xbad
     43 
     44 	// Print a backtrace. This should include diagnostics for the
     45 	// bad return PC and a hex dump.
     46 	panic("backtrace")
     47 }
     48