fix(goobj): external package and symbol indices and arm64 pair relocations
Assisted-by: GLM 5.3
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
package asm
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -61,6 +62,62 @@ TEXT ·add(SB), NOSPLIT, $0-24
|
||||
}
|
||||
}
|
||||
|
||||
// TestGOObjectAARCH64PairReloc pins the ADRP-pair relocation shape against
|
||||
// the toolchain's own object for the same source: exactly one R_ADDRARM64
|
||||
// of Siz 8 at the ADRP word (cmd/internal/obj/arm64/asm7.go adds a single
|
||||
// Siz-8 relocation per pair and the linker patches both instructions from
|
||||
// it). gasm's assembler records the ADRP+ADD form as two word relocs; the
|
||||
// emitter must coalesce them, not emit two Siz-4 records.
|
||||
func TestGOObjectAARCH64PairReloc(t *testing.T) {
|
||||
f, errs := parser.Parse("gv_arm64.s", `
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·getv(SB), NOSPLIT, $0-8
|
||||
MOVD $v<>(SB), R4
|
||||
MOVD R4, ret+0(FP)
|
||||
RET
|
||||
|
||||
GLOBL v<>(SB), RODATA, $8
|
||||
DATA v<>+0(SB)/8, $7
|
||||
`)
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("parse: %v", errs)
|
||||
}
|
||||
img, err := AssembleFileARM64(f)
|
||||
if err != nil {
|
||||
t.Fatalf("AssembleFileARM64: %v", err)
|
||||
}
|
||||
obj, err := img.GOObjectAARCH64("main", "gv_arm64.s")
|
||||
if err != nil {
|
||||
t.Fatalf("GOObjectAARCH64: %v", err)
|
||||
}
|
||||
v := openGoobj(t, obj)
|
||||
relocs := v.blk(blkReloc)
|
||||
le := binary.LittleEndian
|
||||
// Two DWARF relocs on the lines/DIE symbols, then the code's one pair
|
||||
// relocation.
|
||||
if len(relocs) != 3*23 {
|
||||
t.Fatalf("relocs = %d bytes, want three entries", len(relocs))
|
||||
}
|
||||
cr := relocs[2*23:]
|
||||
if off := int32(le.Uint32(cr[0:])); off != 0 {
|
||||
t.Errorf("pair reloc off = %d, want 0 (the ADRP word)", off)
|
||||
}
|
||||
if siz := cr[4]; siz != 8 {
|
||||
t.Errorf("pair reloc siz = %d, want 8", siz)
|
||||
}
|
||||
if typ := le.Uint16(cr[5:]); typ != relocArm64Addr {
|
||||
t.Errorf("pair reloc type = %d, want %d (R_ADDRARM64)", typ, relocArm64Addr)
|
||||
}
|
||||
if pkg := le.Uint32(cr[15:]); pkg != pkgIdxSelf {
|
||||
t.Errorf("pair reloc PkgIdx = %#x, want pkgIdxSelf", pkg)
|
||||
}
|
||||
// The GLOBL is the first package definition.
|
||||
if sym := le.Uint32(cr[19:]); sym != 0 {
|
||||
t.Errorf("pair reloc SymIdx = %d, want 0 (the GLOBL definition)", sym)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGOObjectAARCH64Link does an end-to-end link test: it cross-compiles a
|
||||
// Go program for arm64, substitutes the gasm-produced object into the package
|
||||
// archive, re-links with cmd/link, and verifies the symbol appears in the
|
||||
@@ -79,6 +136,14 @@ TEXT ·add(SB), NOSPLIT, $0-24
|
||||
ADD R5, R4, R4
|
||||
MOVD R4, ret+16(FP)
|
||||
RET
|
||||
|
||||
TEXT ·getv(SB), NOSPLIT, $0-8
|
||||
MOVD $v<>(SB), R4
|
||||
MOVD R4, ret+0(FP)
|
||||
RET
|
||||
|
||||
GLOBL v<>(SB), RODATA, $8
|
||||
DATA v<>+0(SB)/8, $7
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(dir, "main_arm64.s"), []byte(asmSrc), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -86,11 +151,15 @@ TEXT ·add(SB), NOSPLIT, $0-24
|
||||
mainSrc := `package main
|
||||
|
||||
func add(a, b int64) int64
|
||||
func getv() *int64
|
||||
|
||||
func main() {
|
||||
if add(20, 22) != 42 {
|
||||
panic("bad add")
|
||||
}
|
||||
if getv() == nil {
|
||||
panic("bad getv")
|
||||
}
|
||||
}
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(dir, "main.go"), []byte(mainSrc), 0o644); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user