]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm64: recognize FIPS static temps as unaligned
authorRuss Cox <rsc@golang.org>
Sun, 17 Nov 2024 16:51:52 +0000 (11:51 -0500)
committerGopher Robot <gobot@golang.org>
Tue, 19 Nov 2024 18:21:27 +0000 (18:21 +0000)
Code like x := [12]byte{1,2,3,4,5,6,7,8,9,10,11,12} stores x in
a pair of registers and uses MOVD/MOVWU to load the values
from RODATA. The code generator needs to understand not
to use the aligned PC-relative relocation for that sequence.

In non-FIPS modes, more statictemp optimizations can be applied
and this problematic sequence doesn't happen.

Fix the decision about whether to assume alignment to match
the code used by the linker when deciding what to align.

Fixes the linker failure in CL 626437 patch set 5.

Change-Id: Iedad862c6faee758d4a2c5120cab2d329265b134
Reviewed-on: https://go-review.googlesource.com/c/go/+/628835
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Bypass: Russ Cox <rsc@golang.org>

src/cmd/internal/obj/arm64/asm7.go
src/crypto/internal/fips/check/checktest/test.go

index 37de7706e8e9d170d886bc5ce520a0962c57a581..f8d4c7aa98a4be93e99f83208d31f2b27b420976 100644 (file)
@@ -1073,15 +1073,49 @@ func (o *Optab) size(ctxt *obj.Link, p *obj.Prog) int {
                // 2-byte and 1-byte aligned addresses, so the address of load/store must be aligned.
                // Also symbols with prefix of "go:string." are Go strings, which will go into
                // the symbol table, their addresses are not necessary aligned, rule this out.
+               //
+               // Note that the code generation routines for these addressing forms call o.size
+               // to decide whether to use the unaligned/aligned forms, so o.size's result is always
+               // in sync with the code generation decisions, because it *is* the code generation decision.
                align := int64(1 << sz)
-               if o.a1 == C_ADDR && p.From.Offset%align == 0 && !strings.HasPrefix(p.From.Sym.Name, "go:string.") ||
-                       o.a4 == C_ADDR && p.To.Offset%align == 0 && !strings.HasPrefix(p.To.Sym.Name, "go:string.") {
+               if o.a1 == C_ADDR && p.From.Offset%align == 0 && symAlign(p.From.Sym) >= align ||
+                       o.a4 == C_ADDR && p.To.Offset%align == 0 && symAlign(p.To.Sym) >= align {
                        return 8
                }
        }
        return int(o.size_)
 }
 
+// symAlign returns the expected symbol alignment of the symbol s.
+// This must match the linker's own default alignment decisions.
+func symAlign(s *obj.LSym) int64 {
+       name := s.Name
+       switch {
+       case strings.HasPrefix(name, "go:string."),
+               strings.HasPrefix(name, "type:.namedata."),
+               strings.HasPrefix(name, "type:.importpath."),
+               strings.HasSuffix(name, ".opendefer"),
+               strings.HasSuffix(name, ".arginfo0"),
+               strings.HasSuffix(name, ".arginfo1"),
+               strings.HasSuffix(name, ".argliveinfo"):
+               // These are just bytes, or varints.
+               return 1
+       case strings.HasPrefix(name, "gclocals·"):
+               // It has 32-bit fields.
+               return 4
+       default:
+               switch {
+               case s.Size%8 == 0:
+                       return 8
+               case s.Size%4 == 0:
+                       return 4
+               case s.Size%2 == 0:
+                       return 2
+               }
+       }
+       return 1
+}
+
 func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
        if ctxt.Retpoline {
                ctxt.Diag("-spectre=ret not supported on arm64")
index 84d92332b556a92aae28fa3e909f6bd64521c14a..66efe31a09234cd93f4fc25ab68e832bc6eac1e9 100644 (file)
@@ -8,6 +8,7 @@ package checktest
 
 import (
        _ "crypto/internal/fips/check"
+       "runtime"
        _ "unsafe" // go:linkname
 )
 
@@ -32,3 +33,30 @@ var NOPTRBSS int
 var BSS *int
 
 func TEXT() {}
+
+var (
+       globl12 [12]byte
+       globl8  [8]byte
+)
+
+func init() {
+       globl8 = [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
+       globl12 = [12]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
+       runtime.Gosched()
+
+       sum := byte(0)
+       for _, x := range globl12 {
+               sum += x
+       }
+       if sum != 78 {
+               panic("globl12 did not sum properly")
+       }
+
+       sum = byte(0)
+       for _, x := range globl8 {
+               sum += x
+       }
+       if sum != 36 {
+               panic("globl8 did not sum properly")
+       }
+}