test(asm): pair the same-named GOROOT functions in definition order

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-07 21:34:30 +02:00
1 parent c27ba30862
commit df7a5091e0
1 file changed
+26 -21
+26 -21
View File
@@ -55,17 +55,11 @@ var gorootARM64Packages = []string{
// not silently dropped: the gaps are findings, and closing one is a matter
// of removing its entry and watching the file pin itself.
var gorootARM64GapFiles = map[string]string{
"runtime/asm_arm64.s": "the unparenthesised NOSPLIT|NOFRAME flag list is not recognised, so the prologue and guard shapes diverge",
"runtime/sys_linux_arm64.s": "the unparenthesised NOSPLIT|NOFRAME flag list is not recognised, so the prologue and guard shapes diverge (cgoSigtramp, clone)",
"runtime/tls_arm64.s": "a branch distance diverges: an earlier statement's expansion is sized differently",
"crypto/internal/fips140/aes/aes_arm64.s": "a tested immediate bit in a TBZ diverges",
"crypto/internal/fips140/aes/gcm/gcm_arm64.s": "an ADD immediate's value diverges mid-function",
"crypto/internal/fips140/nistec/p256_asm_arm64.s": "a branch distance and a logical-immediate lowering diverge",
"runtime/memclr_arm64.s": "a branch distance diverges: an earlier statement's expansion is sized differently",
"runtime/preempt_arm64.s": "the prologue shape for the function's frame diverges at the first word",
"runtime/race_arm64.s": "the flag list and prologue shape diverge at the first words",
"runtime/rt0_linux_arm64.s": "the #ifdef GOOS selection diverges: gasm keeps a word the toolchain drops",
"internal/runtime/syscall/linux/asm_linux_arm64.s": "a branch distance diverges: an earlier statement's expansion is sized differently",
"runtime/asm_arm64.s": "the unparenthesised NOSPLIT|NOFRAME flag list is not recognised, so the prologue and guard shapes diverge",
"runtime/sys_linux_arm64.s": "the unparenthesised NOSPLIT|NOFRAME flag list is not recognised, so the prologue and guard shapes diverge (cgoSigtramp, clone)",
"runtime/preempt_arm64.s": "the unparenthesised NOSPLIT|NOFRAME flag list is not recognised, so the prologue and guard shapes diverge (asyncPreempt)",
"runtime/race_arm64.s": "the unparenthesised NOSPLIT|NOFRAME flag list is not recognised, so the prologue shape diverges (racecallbackthunk)",
"runtime/rt0_linux_arm64.s": "the #ifdef GOOS selection diverges: gasm keeps a word the toolchain drops",
}
// gorootOtherGOOS matches the file names of the ports the linux build never
@@ -152,22 +146,30 @@ func TestGOROOTARM64Parity(t *testing.T) {
if oout, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("go tool asm %s: %v\n%s", base, err, oout)
}
gt := oracleFuncText(t, mustRead(t, objPath))
byLocal := gt
byLocal := oracleFuncText(t, mustRead(t, objPath))
// The object's symdef order is the source order, gasm's
// function list too, so same-named functions pair up in
// definition order: a file-local kernel beside its
// package-level twin (runtime·racefuncenter and
// racefuncenter<>) carries the plain name twice in the
// object and the reader cannot see the locality.
seen := map[string]int{}
for _, fn := range img.Funcs {
gasmCode := maskCode(append([]byte(nil), img.Code[fn.Offset:fn.Offset+fn.Size]...), fn.Relocs)
goCode, ok := byLocal[fn.Name]
if !ok {
bodies := byLocal[fn.Name]
idx := seen[fn.Name]
seen[fn.Name] = idx + 1
if idx >= len(bodies) {
keys := make([]string, 0, len(byLocal))
for name := range byLocal {
keys = append(keys, name)
}
t.Errorf("%s: not in the oracle output (%d functions: %s)",
fn.Name, len(gt), strings.Join(keys, ", "))
fn.Name, len(byLocal), strings.Join(keys, ", "))
continue
}
goCode = maskCode(append([]byte(nil), goCode...), fn.Relocs)
goCode := maskCode(append([]byte(nil), bodies[idx]...), fn.Relocs)
cmpLen := min(len(goCode), len(gasmCode))
if !bytes.Equal(gasmCode[:cmpLen], goCode[:cmpLen]) {
for w := 0; w < cmpLen/4; w++ {
@@ -202,13 +204,16 @@ func TestGOROOTARM64Parity(t *testing.T) {
// non-package and the hashed (file-local) definitions both, keyed by the
// local name: GOROOT keeps several kernels file-local (cmpbody<>,
// encryptBlockAsm<>), and those ride the hashed definition blocks the
// non-package reader never sees.
func oracleFuncText(t *testing.T, obj []byte) map[string][]byte {
// non-package reader never sees. The value is the functions' bodies in
// symdef order: a file-local kernel beside its package-level twin carries
// the same plain name twice (the object reader cannot see the locality),
// and the encoder pairs them up in definition order.
func oracleFuncText(t *testing.T, obj []byte) map[string][][]byte {
t.Helper()
v := openGoobj(t, obj)
data := v.blk(blkData)
didx := v.blk(blkDataIdx)
out := make(map[string][]byte)
out := make(map[string][][]byte)
di := 0
for _, bi := range []int{blkSymdef, blkHashed64def, blkHasheddef, blkNonpkgdef} {
for _, s := range v.syms(bi) {
@@ -221,7 +226,7 @@ func oracleFuncText(t *testing.T, obj []byte) map[string][]byte {
if _, after, ok := strings.Cut(name, "."); ok {
name = after
}
out[name] = data[off : int(off)+int(s.size)]
out[name] = append(out[name], data[off:int(off)+int(s.size)])
}
}
di++