diff options
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/defs_windows_386.go | 3 | ||||
| -rw-r--r-- | src/runtime/defs_windows_amd64.go | 1 | ||||
| -rw-r--r-- | src/runtime/defs_windows_arm.go | 3 | ||||
| -rw-r--r-- | src/runtime/defs_windows_arm64.go | 1 | ||||
| -rw-r--r-- | src/runtime/export_windows_test.go | 16 | ||||
| -rw-r--r-- | src/runtime/runtime-seh_windows_test.go | 63 |
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) + } + } +} |
