diff options
| author | Keith Randall <khr@golang.org> | 2020-08-20 14:22:30 -0700 |
|---|---|---|
| committer | Keith Randall <khr@golang.org> | 2020-09-18 17:21:06 +0000 |
| commit | d91d0762c7757c12c7d5f9e2ae3f170d5bd7ba84 (patch) | |
| tree | 9e8f3dfd38e462c88f765c4352ac1dbfa3d3ab55 /src/runtime/debug | |
| parent | 65dfe4a772a4bc612219d93886e5c07290785ee6 (diff) | |
| download | go-d91d0762c7757c12c7d5f9e2ae3f170d5bd7ba84.tar.xz | |
runtime/debug: provide Addr method for errors from SetPanicOnFault
When we're building a panic that's triggered by a memory fault when
SetPanicOnFault has been called, include an Addr method. This
method reports the address at which the fault occurred.
Fixes #37023
RELNOTE=yes
Change-Id: Idff144587d6b75070fdc861a36efec76f4ec7384
Reviewed-on: https://go-review.googlesource.com/c/go/+/249677
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Keith Randall <khr@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/runtime/debug')
| -rw-r--r-- | src/runtime/debug/garbage.go | 5 | ||||
| -rw-r--r-- | src/runtime/debug/panic_test.go | 46 |
2 files changed, 51 insertions, 0 deletions
diff --git a/src/runtime/debug/garbage.go b/src/runtime/debug/garbage.go index 785e9d4598..e36e54f12d 100644 --- a/src/runtime/debug/garbage.go +++ b/src/runtime/debug/garbage.go @@ -139,6 +139,11 @@ func SetMaxThreads(threads int) int { // manipulation of memory may cause faults at non-nil addresses in less // dramatic situations; SetPanicOnFault allows such programs to request // that the runtime trigger only a panic, not a crash. +// The runtime.Error that the runtime panics with may have an additional method: +// Addr() uintptr +// If that method exists, it returns the memory address which triggered the fault. +// The results of Addr are best-effort and the veracity of the result +// may depend on the platform. // SetPanicOnFault applies only to the current goroutine. // It returns the previous setting. func SetPanicOnFault(enabled bool) bool { diff --git a/src/runtime/debug/panic_test.go b/src/runtime/debug/panic_test.go new file mode 100644 index 0000000000..2aad418bae --- /dev/null +++ b/src/runtime/debug/panic_test.go @@ -0,0 +1,46 @@ +// Copyright 2020 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. + +// +build aix darwin dragonfly freebsd linux netbsd openbsd + +// TODO: test on Windows? + +package debug_test + +import ( + "runtime/debug" + "syscall" + "testing" + "unsafe" +) + +func TestPanicOnFault(t *testing.T) { + m, err := syscall.Mmap(-1, 0, 0x1000, syscall.PROT_READ /* Note: no PROT_WRITE */, syscall.MAP_SHARED|syscall.MAP_ANON) + if err != nil { + t.Fatalf("can't map anonymous memory: %s", err) + } + defer syscall.Munmap(m) + old := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(old) + const lowBits = 0x3e7 + defer func() { + r := recover() + if r == nil { + t.Fatalf("write did not fault") + } + type addressable interface { + Addr() uintptr + } + a, ok := r.(addressable) + if !ok { + t.Fatalf("fault does not contain address") + } + want := uintptr(unsafe.Pointer(&m[lowBits])) + got := a.Addr() + if got != want { + t.Fatalf("fault address %x, want %x", got, want) + } + }() + m[lowBits] = 1 // will fault +} |
