From: Russ Cox Date: Sun, 17 Nov 2024 16:51:52 +0000 (-0500) Subject: cmd/internal/obj/arm64: recognize FIPS static temps as unaligned X-Git-Tag: go1.24rc1~263 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=fd0294b99c2def6a5def7fde9793c2e57ca04240;p=gostls13.git cmd/internal/obj/arm64: recognize FIPS static temps as unaligned 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 Auto-Submit: Russ Cox Reviewed-by: Cherry Mui TryBot-Bypass: Russ Cox --- diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 37de7706e8..f8d4c7aa98 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -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") diff --git a/src/crypto/internal/fips/check/checktest/test.go b/src/crypto/internal/fips/check/checktest/test.go index 84d92332b5..66efe31a09 100644 --- a/src/crypto/internal/fips/check/checktest/test.go +++ b/src/crypto/internal/fips/check/checktest/test.go @@ -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") + } +}