]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: support for injecting calls at signals on x86
authorAustin Clements <austin@google.com>
Mon, 14 Oct 2019 23:28:58 +0000 (19:28 -0400)
committerAustin Clements <austin@google.com>
Sat, 2 Nov 2019 21:51:12 +0000 (21:51 +0000)
This adds a sigctxt.pushCall method that pushes a call at the signaled
site. We'll use this to inject asynchronous preemptions and in some
places we use it to clean up preparePanic.

For the moment this only works on 386 and amd64. We stub it out on
other platforms and will avoid calling the stubbed version.

For #10958, #24543.

Change-Id: I49e0e853f935d32dd67a70c6cafbae44ee68af8e
Reviewed-on: https://go-review.googlesource.com/c/go/+/201758
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/runtime/signal_386.go
src/runtime/signal_amd64.go
src/runtime/signal_arm.go
src/runtime/signal_arm64.go
src/runtime/signal_linux_s390x.go
src/runtime/signal_mips64x.go
src/runtime/signal_mipsx.go
src/runtime/signal_ppc64x.go

index ef97979796584a2206054aaeb93ddcfb33a46897..2670dc850db507bbe71531a2c58e293637a1f99a 100644 (file)
@@ -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))
 }
index 9e9bb9ca3357cd800cf56b6c330e668c844ab187..29b6a9e7e6acd065981b73c2e981986163d0405f 100644 (file)
@@ -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))
 }
index 97742206c77704f60e95a6b58109021d47387164..1b3e53d01c13324bf2d1f4460c25b47292140666 100644 (file)
@@ -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")
+}
index e1fe62d99dfb286c989ed51a2693c05aa40dd2f9..2341d779da2a45bd62c988eeb8c3b289463dae4d 100644 (file)
@@ -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")
+}
index 6892f63b9f52d60141d66b866fe51255726394e6..390ff5db48c22a0489eb51ca1619d5dcc0f16642 100644 (file)
@@ -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")
+}
index 1b9684295e53128737007ce1a5a782026e154dbf..3f1992c7117b531b189ff1027a2a186eb173dbdb 100644 (file)
@@ -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")
+}
index e223c284024ba51d415129d9b25ba5cd62942e51..6b5ed2872d612a0b9d891812cb660735854e44a6 100644 (file)
@@ -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")
+}
index cac1a23c9fbd402178175581d86025741ea55026..7befad40d2ae9fbc0e5a7e431b0fddbab7d3574d 100644 (file)
@@ -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")
+}