go/test/fixedbugs/issue17381.go
Cherry Zhang 698bfa17a8 cmd/internal/obj: save link register in leaf function with non-empty frame on PPC64, ARM64, S390X
The runtime traceback code assumes non-empty frame has link
link register saved on LR architectures. Make sure it is so in
the assember.

Also make sure that LR is stored before update SP, so the traceback
code will not see a half-updated stack frame if a signal comes
during the execution of function prologue.

Fixes #17381.

Change-Id: I668b04501999b7f9b080275a2d1f8a57029cbbb3
Reviewed-on: https://go-review.googlesource.com/31760
Reviewed-by: Michael Munday <munday@ca.ibm.com>
2016-10-25 21:44:32 +00:00

55 lines
1 KiB
Go

// run
// Copyright 2016 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.
// issue 17381: make sure leave function with non-empty frame
// saves link register, so that traceback will work.
package main
import (
"runtime"
"unsafe"
)
func main() {
defer func() {
if recover() == nil {
panic("did not panic")
}
pcs := make([]uintptr, 20)
n := runtime.Callers(1, pcs)
for _, pc := range pcs[:n] {
if runtime.FuncForPC(pc).Name() == "main.main" {
return
}
}
panic("cannot find main.main in backtrace")
}()
prep()
f() // should panic
}
func funcPC(f interface{}) uintptr {
var ptr uintptr
return **(**uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&f)) + unsafe.Sizeof(ptr)))
}
//go:noinline
func f() {
var t [1]int // non-empty frame
*(*int)(nil) = t[0]
}
var p = funcPC(runtime.GC) + 8
//go:noinline
func prep() {
// put some garbage on stack
var x = [20]uintptr{p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p}
_ = x
}