From 82a9d90eda1e1aba06883727756c1e4a06abe772 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Mon, 28 Sep 2015 04:39:01 +1000 Subject: [PATCH] tests/fixedbugs: make test for issue11656 run known instruction As detailed in #11910, the current implementation attempts to execute an area of memory with unknown content. If the memory is executable, the result is unpredictable - instead, make the test deterministic by attempting to execute an instruction that is known to trigger a trap on the given architecture. The new implementation is written by iant@ and provided via #11910. Update issue #11910 Change-Id: Ia698c36e0dd98a9d9d16a701f60f6748c6faf896 Reviewed-on: https://go-review.googlesource.com/15058 Run-TryBot: Joel Sing TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- test/fixedbugs/issue11656.go | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/test/fixedbugs/issue11656.go b/test/fixedbugs/issue11656.go index 90385bbdc4..bbedb43bc6 100644 --- a/test/fixedbugs/issue11656.go +++ b/test/fixedbugs/issue11656.go @@ -4,26 +4,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// darwin/386 seems to mangle the PC and SP before -// it manages to invoke the signal handler, so this test fails there. -// +build !darwin !386 -// -// openbsd/386 and netbsd/386 don't work, not sure why. -// +build !openbsd !386 -// +build !netbsd !386 -// // 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 -// -// arm64 gets "illegal instruction" (why is the data executable?) -// and is unable to do the traceback correctly (why?). -// +build !arm64 package main import ( + "encoding/binary" "runtime" "runtime/debug" "unsafe" @@ -56,7 +45,27 @@ func f(n int) { var f struct { x uintptr } - f.x = uintptr(unsafe.Pointer(&f)) + + // We want to force an illegal instruction, 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": + binary.LittleEndian.PutUint16(ill, 0x0b0f) // ud2 + case "arm": + binary.LittleEndian.PutUint32(ill, 0xe7f000f0) // no name, but permanently undefined + case "arm64": + binary.LittleEndian.PutUint32(ill, 0xd4207d00) // brk #1000 + case "ppc64": + binary.BigEndian.PutUint32(ill, 0x7fe00008) // trap + case "ppc64le": + binary.LittleEndian.PutUint32(ill, 0x7fe00008) // trap + default: + // Just leave it as 0 and hope for the best. + } + + f.x = uintptr(unsafe.Pointer(&ill[0])) fn := *(*func())(unsafe.Pointer(&f)) fn() }