package runtime
+import (
+ "internal/goarch"
+ "unsafe"
+)
+
const _CONTEXT_CONTROL = 0x10001
type floatingsavearea struct {
// 386 does not have frame pointer register.
func (c *context) set_fp(x uintptr) {}
+func (c *context) pushCall(targetPC, resumePC uintptr) {
+ sp := c.sp() - goarch.StackAlign
+ *(*uintptr)(unsafe.Pointer(sp)) = resumePC
+ c.set_sp(sp)
+ c.set_ip(targetPC)
+}
+
func prepareContextForSigResume(c *context) {
c.edx = c.esp
c.ecx = c.eip
package runtime
+import (
+ "internal/goarch"
+ "unsafe"
+)
+
const _CONTEXT_CONTROL = 0x100001
type m128a struct {
func (c *context) set_sp(x uintptr) { c.rsp = uint64(x) }
func (c *context) set_fp(x uintptr) { c.rbp = uint64(x) }
+func (c *context) pushCall(targetPC, resumePC uintptr) {
+ sp := c.sp() - goarch.StackAlign
+ *(*uintptr)(unsafe.Pointer(sp)) = resumePC
+ c.set_sp(sp)
+ c.set_ip(targetPC)
+}
+
func prepareContextForSigResume(c *context) {
c.r8 = c.rsp
c.r9 = c.rip
package runtime
+import (
+ "internal/goarch"
+ "unsafe"
+)
+
// NOTE(rsc): _CONTEXT_CONTROL is actually 0x200001 and should include PC, SP, and LR.
// However, empirically, LR doesn't come along on Windows 10
// unless you also set _CONTEXT_INTEGER (0x200002).
// arm does not have frame pointer register.
func (c *context) set_fp(x uintptr) {}
+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_arm.go.
+ sp := c.sp() - goarch.StackAlign
+ c.set_sp(sp)
+ *(*uint32)(unsafe.Pointer(sp)) = uint32(c.lr())
+ c.set_lr(resumePC)
+ c.set_ip(targetPC)
+}
+
func prepareContextForSigResume(c *context) {
c.r0 = c.spr
c.r1 = c.pc
package runtime
+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).
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 (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.set_sp(sp)
+ *(*uint64)(unsafe.Pointer(sp)) = uint64(c.lr())
+ c.set_lr(resumePC)
+ c.set_ip(targetPC)
+}
+
func prepareContextForSigResume(c *context) {
c.x[0] = c.xsp
c.x[1] = c.pc
import (
"internal/abi"
- "internal/goarch"
"internal/runtime/atomic"
"internal/runtime/sys"
"unsafe"
// Does it want a preemption and is it safe to preempt?
gp := gFromSP(mp, c.sp())
if gp != nil && wantAsyncPreempt(gp) {
- if ok, newpc := isAsyncSafePoint(gp, c.ip(), c.sp(), c.lr()); ok {
+ if ok, resumePC := isAsyncSafePoint(gp, c.ip(), c.sp(), c.lr()); ok {
// Inject call to asyncPreempt
targetPC := abi.FuncPCABI0(asyncPreempt)
- switch GOARCH {
- default:
- throw("unsupported architecture")
- case "386", "amd64":
- // Make it look like the thread called targetPC.
- sp := c.sp()
- sp -= goarch.PtrSize
- *(*uintptr)(unsafe.Pointer(sp)) = newpc
- c.set_sp(sp)
- c.set_ip(targetPC)
-
- case "arm":
- // Push LR. The injected call is responsible
- // for restoring LR. gentraceback is aware of
- // this extra slot. See sigctxt.pushCall in
- // signal_arm.go, which is similar except we
- // subtract 1 from IP here.
- sp := c.sp()
- sp -= goarch.PtrSize
- c.set_sp(sp)
- *(*uint32)(unsafe.Pointer(sp)) = uint32(c.lr())
- c.set_lr(newpc - 1)
- c.set_ip(targetPC)
-
- case "arm64":
- // 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() - 16 // SP needs 16-byte alignment
- c.set_sp(sp)
- *(*uint64)(unsafe.Pointer(sp)) = uint64(c.lr())
- c.set_lr(newpc)
- c.set_ip(targetPC)
- }
+ c.pushCall(targetPC, resumePC)
stdcall2(_SetThreadContext, thread, uintptr(unsafe.Pointer(c)))
}
}
import (
"internal/abi"
- "internal/runtime/sys"
"unsafe"
)
// sigpanic call to make it look like that. Instead, just
// overwrite the PC. (See issue #35773)
if r.ip() != 0 && r.ip() != abi.FuncPCABI0(asyncPreempt) {
- sp := unsafe.Pointer(r.sp())
- delta := uintptr(sys.StackAlign)
- sp = add(sp, -delta)
- r.set_sp(uintptr(sp))
- if usesLR {
- *((*uintptr)(sp)) = r.lr()
- r.set_lr(r.ip())
- } else {
- *((*uintptr)(sp)) = r.ip()
- }
+ r.pushCall(abi.FuncPCABI0(sigpanic0), r.ip())
+ } else {
+ // Not safe to push the call. Just clobber the frame.
+ r.set_ip(abi.FuncPCABI0(sigpanic0))
}
- r.set_ip(abi.FuncPCABI0(sigpanic0))
return _EXCEPTION_CONTINUE_EXECUTION
}