// 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 }