aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/defs_windows_386.go3
-rw-r--r--src/runtime/defs_windows_amd64.go1
-rw-r--r--src/runtime/defs_windows_arm.go3
-rw-r--r--src/runtime/defs_windows_arm64.go1
-rw-r--r--src/runtime/export_windows_test.go16
-rw-r--r--src/runtime/runtime-seh_windows_test.go63
6 files changed, 87 insertions, 0 deletions
diff --git a/src/runtime/defs_windows_386.go b/src/runtime/defs_windows_386.go
index 8d6c443a14..b11b15554e 100644
--- a/src/runtime/defs_windows_386.go
+++ b/src/runtime/defs_windows_386.go
@@ -56,6 +56,9 @@ func (c *context) set_lr(x uintptr) {}
func (c *context) set_ip(x uintptr) { c.eip = uint32(x) }
func (c *context) set_sp(x uintptr) { c.esp = uint32(x) }
+// 386 does not have frame pointer register.
+func (c *context) set_fp(x uintptr) {}
+
func prepareContextForSigResume(c *context) {
c.edx = c.esp
c.ecx = c.eip
diff --git a/src/runtime/defs_windows_amd64.go b/src/runtime/defs_windows_amd64.go
index afa8a657b8..20c9c4d932 100644
--- a/src/runtime/defs_windows_amd64.go
+++ b/src/runtime/defs_windows_amd64.go
@@ -69,6 +69,7 @@ func (c *context) set_lr(x uintptr) {}
func (c *context) set_ip(x uintptr) { c.rip = uint64(x) }
func (c *context) set_sp(x uintptr) { c.rsp = uint64(x) }
+func (c *context) set_fp(x uintptr) { c.rbp = uint64(x) }
func prepareContextForSigResume(c *context) {
c.r8 = c.rsp
diff --git a/src/runtime/defs_windows_arm.go b/src/runtime/defs_windows_arm.go
index 21c7991519..7a18c95cf1 100644
--- a/src/runtime/defs_windows_arm.go
+++ b/src/runtime/defs_windows_arm.go
@@ -58,6 +58,9 @@ func (c *context) set_ip(x uintptr) { c.pc = uint32(x) }
func (c *context) set_sp(x uintptr) { c.spr = uint32(x) }
func (c *context) set_lr(x uintptr) { c.lrr = uint32(x) }
+// arm does not have frame pointer register.
+func (c *context) set_fp(x uintptr) {}
+
func prepareContextForSigResume(c *context) {
c.r0 = c.spr
c.r1 = c.pc
diff --git a/src/runtime/defs_windows_arm64.go b/src/runtime/defs_windows_arm64.go
index 6c71133b43..ef2efb1bb3 100644
--- a/src/runtime/defs_windows_arm64.go
+++ b/src/runtime/defs_windows_arm64.go
@@ -40,6 +40,7 @@ func (c *context) lr() uintptr { return uintptr(c.x[30]) }
func (c *context) set_ip(x uintptr) { c.pc = uint64(x) }
func (c *context) set_sp(x uintptr) { c.xsp = uint64(x) }
func (c *context) set_lr(x uintptr) { c.x[30] = uint64(x) }
+func (c *context) set_fp(x uintptr) { c.x[29] = uint64(x) }
func prepareContextForSigResume(c *context) {
c.x[0] = c.xsp
diff --git a/src/runtime/export_windows_test.go b/src/runtime/export_windows_test.go
index 332136b586..5b9f08fb79 100644
--- a/src/runtime/export_windows_test.go
+++ b/src/runtime/export_windows_test.go
@@ -20,3 +20,19 @@ func NumberOfProcessors() int32 {
stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
return int32(info.dwnumberofprocessors)
}
+
+type ContextStub struct {
+ context
+}
+
+func (c ContextStub) GetPC() uintptr {
+ return c.ip()
+}
+
+func NewContextStub() ContextStub {
+ var ctx context
+ ctx.set_ip(getcallerpc())
+ ctx.set_sp(getcallersp())
+ ctx.set_fp(getcallerfp())
+ return ContextStub{ctx}
+}
diff --git a/src/runtime/runtime-seh_windows_test.go b/src/runtime/runtime-seh_windows_test.go
new file mode 100644
index 0000000000..23f5b87bf5
--- /dev/null
+++ b/src/runtime/runtime-seh_windows_test.go
@@ -0,0 +1,63 @@
+// Copyright 2023 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 runtime_test
+
+import (
+ "internal/abi"
+ "internal/syscall/windows"
+ "runtime"
+ "testing"
+)
+
+func sehf1() int {
+ return sehf1()
+}
+
+func sehf2() {}
+
+func TestSehLookupFunctionEntry(t *testing.T) {
+ if runtime.GOARCH != "amd64" {
+ t.Skip("skipping amd64-only test")
+ }
+ // This test checks that Win32 is able to retrieve
+ // function metadata stored in the .pdata section
+ // by the Go linker.
+ // Win32 unwinding will fail if this test fails,
+ // as RtlUnwindEx uses RtlLookupFunctionEntry internally.
+ // If that's the case, don't bother investigating further,
+ // first fix the .pdata generation.
+ sehf1pc := abi.FuncPCABIInternal(sehf1)
+ var fnwithframe func()
+ fnwithframe = func() {
+ fnwithframe()
+ }
+ fnwithoutframe := func() {}
+ tests := []struct {
+ name string
+ pc uintptr
+ hasframe bool
+ }{
+ {"no frame func", abi.FuncPCABIInternal(sehf2), false},
+ {"no func", sehf1pc - 1, false},
+ {"func at entry", sehf1pc, true},
+ {"func in prologue", sehf1pc + 1, true},
+ {"anonymous func with frame", abi.FuncPCABIInternal(fnwithframe), true},
+ {"anonymous func without frame", abi.FuncPCABIInternal(fnwithoutframe), false},
+ {"pc at func body", runtime.NewContextStub().GetPC(), true},
+ }
+ for _, tt := range tests {
+ var base uintptr
+ fn := windows.RtlLookupFunctionEntry(tt.pc, &base, nil)
+ if !tt.hasframe {
+ if fn != 0 {
+ t.Errorf("%s: unexpected frame", tt.name)
+ }
+ continue
+ }
+ if fn == 0 {
+ t.Errorf("%s: missing frame", tt.name)
+ }
+ }
+}