]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm64: reject misaligned stack frames, except empty frames
authorRuss Cox <rsc@golang.org>
Wed, 29 Jul 2015 19:15:03 +0000 (15:15 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 29 Jul 2015 21:37:12 +0000 (21:37 +0000)
The layout code has to date insisted on stack frames that are 16-aligned
including the saved LR, and it ensured this by growing the frame itself.
This breaks code that refers to values near the top of the frame by positive
offset from SP, and in general it's too magical: if you see TEXT xxx, $N,
you expect that the frame size is actually N, not sometimes N and sometimes N+8.

This led to a serious bug in the compiler where ambiguously live values
were not being zeroed correctly, which in turn triggered an assertion
in the GC about finding only valid pointers. The compiler has been
fixed to always emit aligned frames, and the hand-written assembly
has also been fixed.

Now that everything is aligned, make unaligned an error instead of
something to "fix" silently.

For #9880.

Change-Id: I05f01a9df174d64b37fa19b36a6b6c5f18d5ba2d
Reviewed-on: https://go-review.googlesource.com/12848
Reviewed-by: Austin Clements <austin@google.com>
src/cmd/internal/obj/arm64/obj7.go
test/nosplit.go

index 77117fb530df6c271eea32579177f2a55c151989..da6edd1740c1192915c2cbae936d3bc532e0e5a9 100644 (file)
@@ -553,7 +553,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
        var o int
        var q2 *obj.Prog
        var retjmp *obj.LSym
-       var stkadj int64
        for p := cursym.Text; p != nil; p = p.Link {
                o = int(p.As)
                switch o {
@@ -567,9 +566,20 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                        if (cursym.Text.Mark&LEAF != 0) && ctxt.Autosize <= 8 {
                                ctxt.Autosize = 0
                        } else if ctxt.Autosize&(16-1) != 0 {
-                               stkadj = 16 - (int64(ctxt.Autosize) & (16 - 1))
-                               ctxt.Autosize += int32(stkadj)
-                               cursym.Locals += int32(stkadj)
+                               // The frame includes an LR.
+                               // If the frame size is 8, it's only an LR,
+                               // so there's no potential for breaking references to
+                               // local variables by growing the frame size,
+                               // because there are no local variables.
+                               // But otherwise, if there is a non-empty locals section,
+                               // the author of the code is responsible for making sure
+                               // that the frame size is 8 mod 16.
+                               if ctxt.Autosize == 8 {
+                                       ctxt.Autosize += 8
+                                       ctxt.Locals += 8
+                               } else {
+                                       ctxt.Diag("%v: unaligned frame size %d - must be 8 mod 16 (or 0)", p, ctxt.Autosize-8)
+                               }
                        }
                        p.To.Offset = int64(ctxt.Autosize) - 8
                        if ctxt.Autosize == 0 && !(cursym.Text.Mark&LEAF != 0) {
index 596962b2c162b5ef0f595afd8e82cf3c3d84f3c8..e5c2a9f30e2f708543b8c4387642fb682b1e936b 100644 (file)
@@ -295,7 +295,7 @@ TestCases:
                                        }
                                }
 
-                               if size%ptrSize == 4 {
+                               if size%ptrSize == 4 || goarch == "arm64" && size != 0 && (size+8)%16 != 0 {
                                        continue TestCases
                                }
                                nosplit := m[3]