fix(asm): add cross-package GOOBJ resolution for riscv64, loong64, arm64

Assisted-by: MiMo V2.5 Pro
This commit is contained in:
2026-08-21 00:35:21 +02:00
parent cc50035375
commit ae550cc05a
4 changed files with 58 additions and 9 deletions
+13 -3
View File
@@ -192,9 +192,9 @@ func encodeARM64Instr(instr *ast.Instr, pc int, offsets map[string]int, fi arm64
}
return a64wordLE(uint32(immFromOperand(ops[0]))), nil
case "B":
return encodeARM64Branch(mnem, ops, pc, offsets, false, resolve)
return encodeARM64Branch(mnem, ops, pc, offsets, false, relocs, resolve)
case "BL", "CALL":
return encodeARM64Branch(mnem, ops, pc, offsets, true, resolve)
return encodeARM64Branch(mnem, ops, pc, offsets, true, relocs, resolve)
case "MOV", "MOVD", "MOVW", "MOVWU", "MOVH", "MOVHU", "MOVB", "MOVBU",
"FMOVS", "FMOVD":
return encodeARM64Mov(instr, mnem, fi, relocs)
@@ -300,7 +300,7 @@ func encodeARM64Instr(instr *ast.Instr, pc int, offsets map[string]int, fi arm64
// ---- branch encoding ----
// encodeARM64Branch encodes an unconditional branch (B/BL) to a label.
func encodeARM64Branch(mnem string, ops []*ast.Operand, pc int, offsets map[string]int, link bool, resolve func(string) string) ([]byte, error) {
func encodeARM64Branch(mnem string, ops []*ast.Operand, pc int, offsets map[string]int, link bool, relocs *[]Reloc, resolve func(string) string) ([]byte, error) {
if len(ops) != 1 {
return nil, fmt.Errorf("%s expects 1 operand, got %d", mnem, len(ops))
}
@@ -308,6 +308,15 @@ func encodeARM64Branch(mnem string, ops []*ast.Operand, pc int, offsets map[stri
// External symbol reference: BL sym(SB).
if link && op.Addr.Sym != nil && op.Addr.Sym.Pseudo == "SB" {
if relocs != nil {
*relocs = append(*relocs, Reloc{
Off: 0,
After: 4,
Name: op.Addr.Sym.Name,
Addend: op.Addr.Sym.Offset,
Kind: RelArm64Branch,
})
}
// Emit BL with zero offset; the linker fills in the target.
return a64wordLE(a64Branch(1, 0)), nil
}
@@ -1324,5 +1333,6 @@ func AssembleFileARM64(f *ast.File) (*Image, error) {
})
}
markExternals(img, dataSyms)
return img, nil
}
+8 -3
View File
@@ -16,6 +16,7 @@ const (
// AArch64 relocation types (the ELF psABI).
rArm64PrelPgHi21 = 275 // R_AARCH64_ADR_PREL_PG_HI21 (ADRP page)
rArm64AddAbsLo12NC = 277 // R_AARCH64_ADD_ABS_LO12_NC (ADD/STR/LDR page offset)
rArm64Call26 = 283 // R_AARCH64_CALL26 (BL instruction)
)
// ELFAARCH64Object returns the image as an ELF64 relocatable object file for
@@ -94,10 +95,14 @@ func (img *Image) ELFAARCH64Object() ([]byte, error) {
if !ok {
return nil, fmt.Errorf("relocation references unknown symbol %q", r.Name)
}
typ := uint32(rArm64PrelPgHi21)
if r.Kind == RelArm64Addr && r.Off%4 == 4 {
// The second instruction in an ADRP pair uses ADD_ABS_LO12_NC.
var typ uint32
switch {
case r.Kind == RelArm64Branch:
typ = rArm64Call26
case r.Kind == RelArm64Addr && r.Off%4 == 4:
typ = rArm64AddAbsLo12NC
default:
typ = rArm64PrelPgHi21
}
relas = append(relas, elfRela{
off: uint64(fn.Offset + r.Off),
+6 -3
View File
@@ -24,14 +24,17 @@ func (img *Image) GOObjectAARCH64(pkgPath, srcPath string) ([]byte, error) {
return nil, err
}
return img.emitGOObject(pkgPath, srcPath, pre, 4, func(r Reloc) (uint16, uint8) {
if r.Kind == RelArm64Branch {
return relocArm64Branch, 4
}
return relocArm64Addr, 4
})
}
// arm64 relocation types (cmd/internal/objabi). R_ADDRARM64 resolves an
// ADRP+ADD/LDR/STR pair to a symbol's address.
// arm64 relocation types (cmd/internal/objabi).
const (
relocArm64Addr = 9 // R_ADDRARM64
relocArm64Addr = 3 // R_ADDRARM64 — ADRP+ADD/LDR/STR pair
relocArm64Branch = 9 // R_CALLARM64 — BL instruction
)
// toolchainObjectPreambleAARCH64 returns the "go object ...\n!\n" header
+31
View File
@@ -97,6 +97,7 @@ const (
RelLoong64AddrHi // R_LOONG64_ADDR_HI (pcalau12i)
RelLoong64AddrLo // R_LOONG64_ADDR_LO (addi.d/ld/st)
RelArm64Addr // R_ADDRARM64 (ADRP + ADD/LDR/STR pair)
RelArm64Branch // R_CALLARM64 (BL instruction)
)
type Reloc struct {
@@ -302,6 +303,7 @@ func AssembleFileRISCV(f *ast.File) (*Image, error) {
})
}
markExternals(img, dataSyms)
return img, nil
}
@@ -373,9 +375,38 @@ func AssembleFileLOONG64(f *ast.File) (*Image, error) {
})
}
markExternals(img, dataSyms)
return img, nil
}
// markExternals identifies relocations that reference symbols not defined in
// the file (neither a GLOBL/DATA symbol nor a TEXT function) and records them
// as external. The non-amd64 architectures emit relocations for every SB
// reference; this post-processing step distinguishes file-local from external.
func markExternals(img *Image, dataSyms []dataSym) {
known := make(map[string]bool, len(dataSyms)+len(img.Funcs))
for _, d := range dataSyms {
known[d.name] = true
}
for _, fn := range img.Funcs {
known[fn.Name] = true
}
externals := map[string]bool{}
for i := range img.Funcs {
for j := range img.Funcs[i].Relocs {
r := &img.Funcs[i].Relocs[j]
if !known[r.Name] {
r.External = true
externals[r.Name] = true
}
}
}
for name := range externals {
img.Externals = append(img.Externals, name)
}
sort.Strings(img.Externals)
}
// dataSym is one GLOBL symbol and its DATA initialiser.
type dataSym struct {
name string