From c7fa66179b51bc90612f564f2cb3afbc1b21d511 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Mon, 10 Jan 2022 10:57:16 -0600 Subject: [PATCH] test: workaround SIGILL on issue11656 on aix For some reason, aix sometimes executes the bogus function body. This should never happen as it lives in a no-execute section. It might be a transient permission blip as the heap grows. Add a small function to cleanup and synchronize the icache before jumping to the bogus function to ensure it causes a panic, not SIGILL. Fixes #44583 Change-Id: Iadca62d82bfb70fc62088705dac42a880a1208fa Reviewed-on: https://go-review.googlesource.com/c/go/+/377314 Trust: Bryan Mills Run-TryBot: Paul Murphy TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui --- test/fixedbugs/issue11656.dir/asm.go | 10 +++ test/fixedbugs/issue11656.dir/asm_generic.go | 11 +++ test/fixedbugs/issue11656.dir/asm_ppc64.s | 13 ++++ test/fixedbugs/issue11656.dir/asm_ppc64le.s | 13 ++++ test/fixedbugs/issue11656.dir/issue11656.go | 75 ++++++++++++++++++ test/fixedbugs/issue11656.go | 81 ++------------------ 6 files changed, 129 insertions(+), 74 deletions(-) create mode 100644 test/fixedbugs/issue11656.dir/asm.go create mode 100644 test/fixedbugs/issue11656.dir/asm_generic.go create mode 100644 test/fixedbugs/issue11656.dir/asm_ppc64.s create mode 100644 test/fixedbugs/issue11656.dir/asm_ppc64le.s create mode 100644 test/fixedbugs/issue11656.dir/issue11656.go diff --git a/test/fixedbugs/issue11656.dir/asm.go b/test/fixedbugs/issue11656.dir/asm.go new file mode 100644 index 0000000000..cdcb064dc5 --- /dev/null +++ b/test/fixedbugs/issue11656.dir/asm.go @@ -0,0 +1,10 @@ +// Copyright 2022 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. + +//go:build ppc64 || ppc64le +// +build ppc64 ppc64le + +package main + +func syncIcache(p uintptr) diff --git a/test/fixedbugs/issue11656.dir/asm_generic.go b/test/fixedbugs/issue11656.dir/asm_generic.go new file mode 100644 index 0000000000..104d44dfeb --- /dev/null +++ b/test/fixedbugs/issue11656.dir/asm_generic.go @@ -0,0 +1,11 @@ +// Copyright 2022 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. + +//go:build !ppc64 && !ppc64le +// +build !ppc64,!ppc64le + +package main + +func syncIcache(p uintptr) { +} diff --git a/test/fixedbugs/issue11656.dir/asm_ppc64.s b/test/fixedbugs/issue11656.dir/asm_ppc64.s new file mode 100644 index 0000000000..125a197ed8 --- /dev/null +++ b/test/fixedbugs/issue11656.dir/asm_ppc64.s @@ -0,0 +1,13 @@ +// Copyright 2022 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. + +#include "textflag.h" + +// func syncIcache(p uintptr) +TEXT main·syncIcache(SB), NOSPLIT|NOFRAME, $0-0 + SYNC + MOVD (R3), R3 + ICBI (R3) + ISYNC + RET diff --git a/test/fixedbugs/issue11656.dir/asm_ppc64le.s b/test/fixedbugs/issue11656.dir/asm_ppc64le.s new file mode 100644 index 0000000000..125a197ed8 --- /dev/null +++ b/test/fixedbugs/issue11656.dir/asm_ppc64le.s @@ -0,0 +1,13 @@ +// Copyright 2022 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. + +#include "textflag.h" + +// func syncIcache(p uintptr) +TEXT main·syncIcache(SB), NOSPLIT|NOFRAME, $0-0 + SYNC + MOVD (R3), R3 + ICBI (R3) + ISYNC + RET diff --git a/test/fixedbugs/issue11656.dir/issue11656.go b/test/fixedbugs/issue11656.dir/issue11656.go new file mode 100644 index 0000000000..a5a52df698 --- /dev/null +++ b/test/fixedbugs/issue11656.dir/issue11656.go @@ -0,0 +1,75 @@ +// Copyright 2015 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 ( + "encoding/binary" + "runtime" + "runtime/debug" + "unsafe" +) + +func main() { + debug.SetPanicOnFault(true) + defer func() { + if err := recover(); err == nil { + panic("not panicking") + } + pc, _, _, _ := runtime.Caller(10) + f := runtime.FuncForPC(pc) + if f == nil || f.Name() != "main.f" { + if f == nil { + println("no func for ", unsafe.Pointer(pc)) + } else { + println("found func:", f.Name()) + } + panic("cannot find main.f on stack") + } + }() + f(20) +} + +func f(n int) { + if n > 0 { + f(n - 1) + } + var f struct { + x uintptr + } + + // We want to force a seg fault, to get a crash at a PC value != 0. + // Not all systems make the data section non-executable. + ill := make([]byte, 64) + switch runtime.GOARCH { + case "386", "amd64": + ill = append(ill[:0], 0x89, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00) // MOVL AX, 0 + case "arm": + binary.LittleEndian.PutUint32(ill[0:4], 0xe3a00000) // MOVW $0, R0 + binary.LittleEndian.PutUint32(ill[4:8], 0xe5800000) // MOVW R0, (R0) + case "arm64": + binary.LittleEndian.PutUint32(ill, 0xf90003ff) // MOVD ZR, (ZR) + case "ppc64": + binary.BigEndian.PutUint32(ill, 0xf8000000) // MOVD R0, (R0) + case "ppc64le": + binary.LittleEndian.PutUint32(ill, 0xf8000000) // MOVD R0, (R0) + case "mips", "mips64": + binary.BigEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0) + case "mipsle", "mips64le": + binary.LittleEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0) + case "s390x": + ill = append(ill[:0], 0xa7, 0x09, 0x00, 0x00) // MOVD $0, R0 + ill = append(ill, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x24) // MOVD R0, (R0) + case "riscv64": + binary.LittleEndian.PutUint32(ill, 0x00003023) // MOV X0, (X0) + default: + // Just leave it as 0 and hope for the best. + } + + f.x = uintptr(unsafe.Pointer(&ill[0])) + p := &f + fn := *(*func())(unsafe.Pointer(&p)) + syncIcache(f.x) + fn() +} diff --git a/test/fixedbugs/issue11656.go b/test/fixedbugs/issue11656.go index 85fe720b30..dba8e35439 100644 --- a/test/fixedbugs/issue11656.go +++ b/test/fixedbugs/issue11656.go @@ -1,89 +1,22 @@ -// run +// runindir -// Copyright 2015 The Go Authors. All rights reserved. +// Copyright 2022 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 11656: runtime: jump to bad PC missing good traceback + // windows doesn't work, because Windows exception handling // delivers signals based on the current PC, and that current PC // doesn't go into the Go runtime. -// +build !windows // wasm does not work, because the linear memory is not executable. -// +build !wasm // This test doesn't work on gccgo/GoLLVM, because they will not find // any unwind information for the artificial function, and will not be // able to unwind past that point. -// +build !gccgo -package main +//go:build !windows && !wasm && !gccgo +// +build !windows,!wasm,!gccgo -import ( - "encoding/binary" - "runtime" - "runtime/debug" - "unsafe" -) - -func main() { - debug.SetPanicOnFault(true) - defer func() { - if err := recover(); err == nil { - panic("not panicking") - } - pc, _, _, _ := runtime.Caller(10) - f := runtime.FuncForPC(pc) - if f == nil || f.Name() != "main.f" { - if f == nil { - println("no func for ", unsafe.Pointer(pc)) - } else { - println("found func:", f.Name()) - } - panic("cannot find main.f on stack") - } - }() - f(20) -} - -func f(n int) { - if n > 0 { - f(n - 1) - } - var f struct { - x uintptr - } - - // We want to force a seg fault, to get a crash at a PC value != 0. - // Not all systems make the data section non-executable. - ill := make([]byte, 64) - switch runtime.GOARCH { - case "386", "amd64": - ill = append(ill[:0], 0x89, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00) // MOVL AX, 0 - case "arm": - binary.LittleEndian.PutUint32(ill[0:4], 0xe3a00000) // MOVW $0, R0 - binary.LittleEndian.PutUint32(ill[4:8], 0xe5800000) // MOVW R0, (R0) - case "arm64": - binary.LittleEndian.PutUint32(ill, 0xf90003ff) // MOVD ZR, (ZR) - case "ppc64": - binary.BigEndian.PutUint32(ill, 0xf8000000) // MOVD R0, (R0) - case "ppc64le": - binary.LittleEndian.PutUint32(ill, 0xf8000000) // MOVD R0, (R0) - case "mips", "mips64": - binary.BigEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0) - case "mipsle", "mips64le": - binary.LittleEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0) - case "s390x": - ill = append(ill[:0], 0xa7, 0x09, 0x00, 0x00) // MOVD $0, R0 - ill = append(ill, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x24) // MOVD R0, (R0) - case "riscv64": - binary.LittleEndian.PutUint32(ill, 0x00003023) // MOV X0, (X0) - default: - // Just leave it as 0 and hope for the best. - } - - f.x = uintptr(unsafe.Pointer(&ill[0])) - p := &f - fn := *(*func())(unsafe.Pointer(&p)) - fn() -} +package ignored