| // Copyright 2025 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 windows |
| |
| import ( |
| "internal/goarch" |
| "unsafe" |
| ) |
| |
| // NOTE(rsc): CONTEXT_CONTROL is actually 0x400001 and should include PC, SP, and LR. |
| // However, empirically, LR doesn't come along on Windows 10 |
| // unless you also set CONTEXT_INTEGER (0x400002). |
| // Without LR, we skip over the next-to-bottom function in profiles |
| // when the bottom function is frameless. |
| // So we set both here, to make a working CONTEXT_CONTROL. |
| const CONTEXT_CONTROL = 0x400003 |
| |
| type Neon128 struct { |
| Low uint64 |
| High int64 |
| } |
| |
| // See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-arm64_nt_context |
| type Context struct { |
| ContextFlags uint32 |
| Cpsr uint32 |
| X [31]uint64 // fp is x[29], lr is x[30] |
| XSp uint64 |
| Pc uint64 |
| V [32]Neon128 |
| Fpcr uint32 |
| Fpsr uint32 |
| Bcr [8]uint32 |
| Bvr [8]uint64 |
| Wcr [2]uint32 |
| Wvr [2]uint64 |
| } |
| |
| func (c *Context) PC() uintptr { return uintptr(c.Pc) } |
| func (c *Context) SP() uintptr { return uintptr(c.XSp) } |
| func (c *Context) LR() uintptr { return uintptr(c.X[30]) } |
| |
| func (c *Context) SetPC(x uintptr) { c.Pc = uint64(x) } |
| func (c *Context) SetSP(x uintptr) { c.XSp = uint64(x) } |
| func (c *Context) SetLR(x uintptr) { c.X[30] = uint64(x) } |
| func (c *Context) SetFP(x uintptr) { c.X[29] = uint64(x) } |
| |
| func (c *Context) PushCall(targetPC, resumePC uintptr) { |
| // Push LR. The injected call is responsible |
| // for restoring LR. gentraceback is aware of |
| // this extra slot. See sigctxt.pushCall in |
| // signal_arm64.go. |
| sp := c.SP() - goarch.StackAlign |
| c.SetSP(sp) |
| *(*uint64)(unsafe.Pointer(sp)) = uint64(c.LR()) |
| c.SetLR(resumePC) |
| c.SetPC(targetPC) |
| } |
| |
| type DISPATCHER_CONTEXT struct { |
| ControlPc uint64 |
| ImageBase uint64 |
| FunctionEntry uintptr |
| EstablisherFrame uint64 |
| TargetIp uint64 |
| Context *Context |
| LanguageHandler uintptr |
| HandlerData uintptr |
| } |
| |
| func (c *DISPATCHER_CONTEXT) Ctx() *Context { |
| return c.Context |
| } |