diff --git a/src/runtime/signal_386.go b/src/runtime/signal_386.go index ef97979796..2670dc850d 100644 --- a/src/runtime/signal_386.go +++ b/src/runtime/signal_386.go @@ -57,14 +57,21 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { sp := uintptr(c.esp()) if shouldPushSigpanic(gp, pc, *(*uintptr)(unsafe.Pointer(sp))) { - // Make it look like the faulting PC called sigpanic. - if sys.RegSize > sys.PtrSize { - sp -= sys.PtrSize - *(*uintptr)(unsafe.Pointer(sp)) = 0 - } - sp -= sys.PtrSize - *(*uintptr)(unsafe.Pointer(sp)) = pc - c.set_esp(uint32(sp)) + c.pushCall(funcPC(sigpanic)) + } else { + // Not safe to push the call. Just clobber the frame. + c.set_eip(uint32(funcPC(sigpanic))) } - c.set_eip(uint32(funcPC(sigpanic))) +} + +const pushCallSupported = true + +func (c *sigctxt) pushCall(targetPC uintptr) { + // Make it look like the signaled instruction called target. + pc := uintptr(c.eip()) + sp := uintptr(c.esp()) + sp -= sys.PtrSize + *(*uintptr)(unsafe.Pointer(sp)) = pc + c.set_esp(uint32(sp)) + c.set_eip(uint32(targetPC)) } diff --git a/src/runtime/signal_amd64.go b/src/runtime/signal_amd64.go index 9e9bb9ca33..29b6a9e7e6 100644 --- a/src/runtime/signal_amd64.go +++ b/src/runtime/signal_amd64.go @@ -66,14 +66,22 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { sp := uintptr(c.rsp()) if shouldPushSigpanic(gp, pc, *(*uintptr)(unsafe.Pointer(sp))) { - // Make it look the like faulting PC called sigpanic. - if sys.RegSize > sys.PtrSize { - sp -= sys.PtrSize - *(*uintptr)(unsafe.Pointer(sp)) = 0 - } - sp -= sys.PtrSize - *(*uintptr)(unsafe.Pointer(sp)) = pc - c.set_rsp(uint64(sp)) + c.pushCall(funcPC(sigpanic)) + } else { + // Not safe to push the call. Just clobber the frame. + c.set_rip(uint64(funcPC(sigpanic))) } - c.set_rip(uint64(funcPC(sigpanic))) +} + +// TODO: Remove pushCallSupported once all platforms support it. +const pushCallSupported = true + +func (c *sigctxt) pushCall(targetPC uintptr) { + // Make it look like the signaled instruction called target. + pc := uintptr(c.rip()) + sp := uintptr(c.rsp()) + sp -= sys.PtrSize + *(*uintptr)(unsafe.Pointer(sp)) = pc + c.set_rsp(uint64(sp)) + c.set_rip(uint64(targetPC)) } diff --git a/src/runtime/signal_arm.go b/src/runtime/signal_arm.go index 97742206c7..1b3e53d01c 100644 --- a/src/runtime/signal_arm.go +++ b/src/runtime/signal_arm.go @@ -62,3 +62,9 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { c.set_r10(uint32(uintptr(unsafe.Pointer(gp)))) c.set_pc(uint32(funcPC(sigpanic))) } + +const pushCallSupported = false + +func (c *sigctxt) pushCall(targetPC uintptr) { + throw("not implemented") +} diff --git a/src/runtime/signal_arm64.go b/src/runtime/signal_arm64.go index e1fe62d99d..2341d779da 100644 --- a/src/runtime/signal_arm64.go +++ b/src/runtime/signal_arm64.go @@ -78,3 +78,9 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { c.set_r28(uint64(uintptr(unsafe.Pointer(gp)))) c.set_pc(uint64(funcPC(sigpanic))) } + +const pushCallSupported = false + +func (c *sigctxt) pushCall(targetPC uintptr) { + throw("not implemented") +} diff --git a/src/runtime/signal_linux_s390x.go b/src/runtime/signal_linux_s390x.go index 6892f63b9f..390ff5db48 100644 --- a/src/runtime/signal_linux_s390x.go +++ b/src/runtime/signal_linux_s390x.go @@ -109,3 +109,9 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { c.set_r13(uint64(uintptr(unsafe.Pointer(gp)))) c.set_pc(uint64(funcPC(sigpanic))) } + +const pushCallSupported = false + +func (c *sigctxt) pushCall(targetPC uintptr) { + throw("not implemented") +} diff --git a/src/runtime/signal_mips64x.go b/src/runtime/signal_mips64x.go index 1b9684295e..3f1992c711 100644 --- a/src/runtime/signal_mips64x.go +++ b/src/runtime/signal_mips64x.go @@ -84,3 +84,9 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { c.set_r30(uint64(uintptr(unsafe.Pointer(gp)))) c.set_pc(sigpanicPC) } + +const pushCallSupported = false + +func (c *sigctxt) pushCall(targetPC uintptr) { + throw("not implemented") +} diff --git a/src/runtime/signal_mipsx.go b/src/runtime/signal_mipsx.go index e223c28402..6b5ed2872d 100644 --- a/src/runtime/signal_mipsx.go +++ b/src/runtime/signal_mipsx.go @@ -79,3 +79,9 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { c.set_r30(uint32(uintptr(unsafe.Pointer(gp)))) c.set_pc(uint32(funcPC(sigpanic))) } + +const pushCallSupported = false + +func (c *sigctxt) pushCall(targetPC uintptr) { + throw("not implemented") +} diff --git a/src/runtime/signal_ppc64x.go b/src/runtime/signal_ppc64x.go index cac1a23c9f..7befad40d2 100644 --- a/src/runtime/signal_ppc64x.go +++ b/src/runtime/signal_ppc64x.go @@ -85,3 +85,9 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { c.set_r12(uint64(funcPC(sigpanic))) c.set_pc(uint64(funcPC(sigpanic))) } + +const pushCallSupported = false + +func (c *sigctxt) pushCall(targetPC uintptr) { + throw("not implemented") +}