]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm64: make function epilogue async-signal safe
authorCherry Zhang <cherryyz@google.com>
Fri, 8 Nov 2019 03:40:50 +0000 (22:40 -0500)
committerCherry Zhang <cherryyz@google.com>
Fri, 8 Nov 2019 16:46:24 +0000 (16:46 +0000)
When the frame size is large, we generate

MOVD.P 0xf0(SP), LR
ADD $(framesize-0xf0), SP

This is problematic: after the first instruction, we have a
partial frame of size (framesize-0xf0). If we try to unwind the
stack at this point, we'll try to read the LR from the stack at
0(SP) (the new SP) as the frame size is not 0. But this slot does
not contain a valid LR.

Fix this by not changing SP in two instructions. Instead,
generate

MOVD (SP), LR
ADD $framesize, SP

This affects not only async preemption but also profiling. So we
change the generated instructions, instead of marking unsafe
point.

Change-Id: I4e78c62d50ffc4acff70ccfbfec16a5ccae17f24
Reviewed-on: https://go-review.googlesource.com/c/go/+/206057
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/internal/obj/arm64/obj7.go

index 464cbb4b50fe9e064d722172abe54ec4908c6c2f..e7cb16be7b76c11ca1f883eafc210172e9300b44 100644 (file)
@@ -812,22 +812,27 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
 
                                aoffset := c.autosize
 
-                               if aoffset > 0xF0 {
-                                       aoffset = 0xF0
-                               }
-                               p.As = AMOVD
-                               p.From.Type = obj.TYPE_MEM
-                               p.Scond = C_XPOST
-                               p.From.Offset = int64(aoffset)
-                               p.From.Reg = REGSP
-                               p.To.Type = obj.TYPE_REG
-                               p.To.Reg = REGLINK
-                               p.Spadj = -aoffset
-                               if c.autosize > aoffset {
+                               if aoffset <= 0xF0 {
+                                       p.As = AMOVD
+                                       p.From.Type = obj.TYPE_MEM
+                                       p.Scond = C_XPOST
+                                       p.From.Offset = int64(aoffset)
+                                       p.From.Reg = REGSP
+                                       p.To.Type = obj.TYPE_REG
+                                       p.To.Reg = REGLINK
+                                       p.Spadj = -aoffset
+                               } else {
+                                       p.As = AMOVD
+                                       p.From.Type = obj.TYPE_MEM
+                                       p.From.Offset = 0
+                                       p.From.Reg = REGSP
+                                       p.To.Type = obj.TYPE_REG
+                                       p.To.Reg = REGLINK
+
                                        q = newprog()
                                        q.As = AADD
                                        q.From.Type = obj.TYPE_CONST
-                                       q.From.Offset = int64(c.autosize) - int64(aoffset)
+                                       q.From.Offset = int64(aoffset)
                                        q.To.Type = obj.TYPE_REG
                                        q.To.Reg = REGSP
                                        q.Link = p.Link