|  | // 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") | 
|  | } |