aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link
diff options
context:
space:
mode:
authorWANG Xuerui <git@xen0n.name>2025-10-06 18:09:14 +0800
committerabner chenc <chenguoqi@loongson.cn>2025-11-20 19:04:50 -0800
commit4b0e3cc1d63a00ee184ea1f6b17e79808e3d9fdc (patch)
treea39935c924fff622dc112d627030d86a5cc1fb1a /src/cmd/link
parentcdba82c7d6fce54b212872ae45d04c3911b11014 (diff)
downloadgo-4b0e3cc1d63a00ee184ea1f6b17e79808e3d9fdc.tar.xz
cmd/link: support loading R_LARCH_PCREL20_S2 and R_LARCH_CALL36 relocs
Host libgcc.a (among other libraries) on loong64 systems may contain such relocs if built with the "medium" code model and/or linker relaxation, which is increasingly the case. Make the internal linker aware of these for cgo interopability going forward. While at it, fix some of the comments for the loong64-specific RelocTypes. Fixes #75562 Change-Id: I0810969dcd229c5131ef06b0f70f51d81a3be4cd Reviewed-on: https://go-review.googlesource.com/c/go/+/709717 Reviewed-by: abner chenc <chenguoqi@loongson.cn> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Mark Freeman <markfreeman@google.com> Reviewed-by: Meidan Li <limeidan@loongson.cn> Reviewed-by: Junyang Shao <shaojunyang@google.com>
Diffstat (limited to 'src/cmd/link')
-rw-r--r--src/cmd/link/internal/loadelf/ldelf.go6
-rw-r--r--src/cmd/link/internal/loong64/asm.go53
2 files changed, 48 insertions, 11 deletions
diff --git a/src/cmd/link/internal/loadelf/ldelf.go b/src/cmd/link/internal/loadelf/ldelf.go
index 1c83f03a5d..8f4c1a5765 100644
--- a/src/cmd/link/internal/loadelf/ldelf.go
+++ b/src/cmd/link/internal/loadelf/ldelf.go
@@ -1065,13 +1065,15 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
LOONG64 | uint32(elf.R_LARCH_PCALA_LO12)<<16,
LOONG64 | uint32(elf.R_LARCH_GOT_PC_HI20)<<16,
LOONG64 | uint32(elf.R_LARCH_GOT_PC_LO12)<<16,
- LOONG64 | uint32(elf.R_LARCH_32_PCREL)<<16:
+ LOONG64 | uint32(elf.R_LARCH_32_PCREL)<<16,
+ LOONG64 | uint32(elf.R_LARCH_PCREL20_S2)<<16:
return 4, 4, nil
case LOONG64 | uint32(elf.R_LARCH_64)<<16,
LOONG64 | uint32(elf.R_LARCH_ADD64)<<16,
LOONG64 | uint32(elf.R_LARCH_SUB64)<<16,
- LOONG64 | uint32(elf.R_LARCH_64_PCREL)<<16:
+ LOONG64 | uint32(elf.R_LARCH_64_PCREL)<<16,
+ LOONG64 | uint32(elf.R_LARCH_CALL36)<<16:
return 8, 8, nil
case S390X | uint32(elf.R_390_8)<<16:
diff --git a/src/cmd/link/internal/loong64/asm.go b/src/cmd/link/internal/loong64/asm.go
index e7f3fd1d98..219cfc7196 100644
--- a/src/cmd/link/internal/loong64/asm.go
+++ b/src/cmd/link/internal/loong64/asm.go
@@ -85,7 +85,8 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
}
return true
- case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26):
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_CALL36):
if targType == sym.SDYNIMPORT {
addpltsym(target, ldr, syms, targ)
su := ldr.MakeSymbolUpdater(s)
@@ -95,8 +96,12 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
if targType == 0 || targType == sym.SXREF {
ldr.Errorf(s, "unknown symbol %s in callloong64", ldr.SymName(targ))
}
+ relocType := objabi.R_CALLLOONG64
+ if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_CALL36) {
+ relocType = objabi.R_LOONG64_CALL36
+ }
su := ldr.MakeSymbolUpdater(s)
- su.SetRelocType(rIdx, objabi.R_CALLLOONG64)
+ su.SetRelocType(rIdx, relocType)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT_PC_HI20),
@@ -117,7 +122,8 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_HI20),
- objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_LO12):
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_LO12),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCREL20_S2):
if targType == sym.SDYNIMPORT {
ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
}
@@ -125,12 +131,17 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
ldr.Errorf(s, "unknown symbol %s", ldr.SymName(targ))
}
- su := ldr.MakeSymbolUpdater(s)
- if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_PCALA_HI20) {
- su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_HI)
- } else {
- su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_LO)
+ var relocType objabi.RelocType
+ switch r.Type() - objabi.ElfRelocOffset {
+ case objabi.RelocType(elf.R_LARCH_PCALA_HI20):
+ relocType = objabi.R_LOONG64_ADDR_HI
+ case objabi.RelocType(elf.R_LARCH_PCALA_LO12):
+ relocType = objabi.R_LOONG64_ADDR_LO
+ case objabi.RelocType(elf.R_LARCH_PCREL20_S2):
+ relocType = objabi.R_LOONG64_ADDR_PCREL20_S2
}
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, relocType)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_ADD64),
@@ -418,6 +429,11 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
out.Write64(uint64(elf.R_LARCH_B26) | uint64(elfsym)<<32)
out.Write64(uint64(r.Xadd))
+ case objabi.R_LOONG64_CALL36:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_CALL36) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd))
+
case objabi.R_LOONG64_TLS_IE_HI:
out.Write64(uint64(sectoff))
out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_HI20) | uint64(elfsym)<<32)
@@ -438,6 +454,11 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
out.Write64(uint64(elf.R_LARCH_PCALA_HI20) | uint64(elfsym)<<32)
out.Write64(uint64(r.Xadd))
+ case objabi.R_LOONG64_ADDR_PCREL20_S2:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_PCREL20_S2) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd))
+
case objabi.R_LOONG64_GOT_HI:
out.Write64(uint64(sectoff))
out.Write64(uint64(elf.R_LARCH_GOT_PC_HI20) | uint64(elfsym)<<32)
@@ -463,7 +484,8 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
default:
return val, 0, false
case objabi.R_LOONG64_ADDR_HI,
- objabi.R_LOONG64_ADDR_LO:
+ objabi.R_LOONG64_ADDR_LO,
+ objabi.R_LOONG64_ADDR_PCREL20_S2:
// set up addend for eventual relocation via outer symbol.
rs, _ := ld.FoldSubSymbolOffset(ldr, rs)
rst := ldr.SymType(rs)
@@ -474,6 +496,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
case objabi.R_LOONG64_TLS_LE_HI,
objabi.R_LOONG64_TLS_LE_LO,
objabi.R_CALLLOONG64,
+ objabi.R_LOONG64_CALL36,
objabi.R_JMPLOONG64,
objabi.R_LOONG64_TLS_IE_HI,
objabi.R_LOONG64_TLS_IE_LO,
@@ -499,6 +522,10 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
return val&0xffc003ff | (t << 10), noExtReloc, isOk
}
return val&0xfe00001f | (t << 5), noExtReloc, isOk
+ case objabi.R_LOONG64_ADDR_PCREL20_S2:
+ pc := ldr.SymValue(s) + int64(r.Off())
+ t := (ldr.SymAddr(rs) + r.Add() - pc) >> 2
+ return val&0xfe00001f | ((t & 0xfffff) << 5), noExtReloc, isOk
case objabi.R_LOONG64_TLS_LE_HI,
objabi.R_LOONG64_TLS_LE_LO:
t := ldr.SymAddr(rs) + r.Add()
@@ -512,6 +539,14 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
t := ldr.SymAddr(rs) + r.Add() - pc
return val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16), noExtReloc, isOk
+ case objabi.R_LOONG64_CALL36:
+ pc := ldr.SymValue(s) + int64(r.Off())
+ t := (ldr.SymAddr(rs) + r.Add() - pc) >> 2
+ // val is pcaddu18i (lower half) + jirl (upper half)
+ pcaddu18i := (val & 0xfe00001f) | (((t + 0x8000) >> 16) << 5)
+ jirl := ((val >> 32) & 0xfc0003ff) | ((t & 0xffff) << 10)
+ return pcaddu18i | (jirl << 32), noExtReloc, isOk
+
case objabi.R_JMP16LOONG64,
objabi.R_JMP21LOONG64:
pc := ldr.SymValue(s) + int64(r.Off())