aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorGuoqi Chen <chenguoqi@loongson.cn>2026-03-12 15:34:02 +0800
committerabner chenc <chenguoqi@loongson.cn>2026-03-18 18:08:22 -0700
commit9def4acb06bf9167441caa8af37e27b3cdbf8cf0 (patch)
tree00dff920091176d8594de42d8f98f2c4ff3881b7 /src/cmd
parent6bdfdb5f51951584732e6a95a7ee8a5ba5e8cb93 (diff)
downloadgo-9def4acb06bf9167441caa8af37e27b3cdbf8cf0.tar.xz
cmd/link: support loading R_LARCH_GOT64_PC_{LO12, HI20} relocs on loong64
On loong64, such relocations are increasingly common when built using an "extreme" code model. To ensure future interoperability with cgo, the linker needs to be made aware of these relocations. Ref: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc Fixes #78047. Change-Id: Ibca205ab837279c69fb243a8e8519c952e11c99e Reviewed-on: https://go-review.googlesource.com/c/go/+/753521 Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Meidan Li <limeidan@loongson.cn> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Carlos Amedee <carlos@golang.org>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/internal/obj/fips140.go4
-rw-r--r--src/cmd/internal/objabi/reloctype.go26
-rw-r--r--src/cmd/internal/objabi/reloctype_string.go64
-rw-r--r--src/cmd/internal/objabi/symkind_string.go5
-rw-r--r--src/cmd/link/internal/loadelf/ldelf.go4
-rw-r--r--src/cmd/link/internal/loong64/asm.go197
6 files changed, 224 insertions, 76 deletions
diff --git a/src/cmd/internal/obj/fips140.go b/src/cmd/internal/obj/fips140.go
index b888396b1f..0e4f2a47a3 100644
--- a/src/cmd/internal/obj/fips140.go
+++ b/src/cmd/internal/obj/fips140.go
@@ -356,6 +356,8 @@ func (s *LSym) checkFIPSReloc(ctxt *Link, rel Reloc) {
objabi.R_GOTPCREL,
objabi.R_LOONG64_ADDR_LO, // used with PC-relative load
objabi.R_LOONG64_ADDR_HI, // used with PC-relative load
+ objabi.R_LOONG64_ADDR64_LO, // used with PC-relative load
+ objabi.R_LOONG64_ADDR64_HI, // used with PC-relative load
objabi.R_LOONG64_ADDR_PCREL20_S2, // used with PC-relative load
objabi.R_LOONG64_CALL36,
objabi.R_LOONG64_TLS_LE_HI,
@@ -364,6 +366,8 @@ func (s *LSym) checkFIPSReloc(ctxt *Link, rel Reloc) {
objabi.R_LOONG64_TLS_IE_LO,
objabi.R_LOONG64_GOT_HI,
objabi.R_LOONG64_GOT_LO,
+ objabi.R_LOONG64_GOT64_HI,
+ objabi.R_LOONG64_GOT64_LO,
objabi.R_JMP16LOONG64,
objabi.R_JMP21LOONG64,
objabi.R_PCREL,
diff --git a/src/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go
index 8e95b5dae2..b6764ff8ef 100644
--- a/src/cmd/internal/objabi/reloctype.go
+++ b/src/cmd/internal/objabi/reloctype.go
@@ -327,13 +327,20 @@ const (
// Loong64.
- // R_LOONG64_ADDR_HI resolves to the sign-adjusted "upper" 20 bits (bit 5-24) of an
- // external address, by encoding it into the instruction.
+ // R_LOONG64_ADDR_HI resolves [31...12]bits of 32/64-bit PC-relative offset of an
+ // external address, by encoding it into addi.w/addi.d instruction
// R_LOONG64_ADDR_LO resolves to the low 12 bits of an external address, by encoding
- // it into the instruction.
+ // it into pcalau12i instruction.
R_LOONG64_ADDR_HI
R_LOONG64_ADDR_LO
+ // R_LOONG64_ADDR64_HI resolves [63...52]bits of 64-bit PC-relative offset of an
+ // external address, by encoding it into lu52i.d instruction
+ // R_LOONG64_ADDR64_LO resolves [51...32]bits of 64-bit PC-relative offset of an
+ // external address, by encoding it into lu32i.d instruction
+ R_LOONG64_ADDR64_HI
+ R_LOONG64_ADDR64_LO
+
// R_LOONG64_ADDR_PCREL20_S2 resolves to the 22-bit, 4-byte aligned offset of an
// external address, by encoding it into a PCADDI instruction.
R_LOONG64_ADDR_PCREL20_S2
@@ -358,11 +365,20 @@ const (
R_LOONG64_TLS_IE_HI
R_LOONG64_TLS_IE_LO
- // R_LOONG64_GOT_HI and R_LOONG64_GOT_LO resolves a GOT-relative instruction sequence,
- // usually an pcalau12i followed by another ld or addi instruction.
+ // R_LOONG64_GOT_HI resolves [31...12]bits of 32/64-bit PC-relative offset of
+ // GOT entry, by encoding it into pcalau12i instruction
+ // R_LOONG64_GOT_LO resolves [11...0]bits of 32/64-bit PC-relative offset of
+ // GOT entry, by encoding it into ld.w/ld.d instruction
R_LOONG64_GOT_HI
R_LOONG64_GOT_LO
+ // R_LOONG64_GOT64_HI resolves [63...52]bits of 64-bit PC-relative offset of
+ // GOT entry, by encoding it into lu52i.d instruction
+ // R_LOONG64_GOT64_LO resolves [51...32]bits of 64-bit PC-relative offset of
+ // GOT entry, by encoding it into lu32i.d instruction
+ R_LOONG64_GOT64_HI
+ R_LOONG64_GOT64_LO
+
// 64-bit in-place addition.
R_LOONG64_ADD64
// 64-bit in-place subtraction.
diff --git a/src/cmd/internal/objabi/reloctype_string.go b/src/cmd/internal/objabi/reloctype_string.go
index 4152afd92f..c7a5e6c07a 100644
--- a/src/cmd/internal/objabi/reloctype_string.go
+++ b/src/cmd/internal/objabi/reloctype_string.go
@@ -86,40 +86,44 @@ func _() {
_ = x[R_PCRELDBL-76]
_ = x[R_LOONG64_ADDR_HI-77]
_ = x[R_LOONG64_ADDR_LO-78]
- _ = x[R_LOONG64_ADDR_PCREL20_S2-79]
- _ = x[R_LOONG64_TLS_LE_HI-80]
- _ = x[R_LOONG64_TLS_LE_LO-81]
- _ = x[R_CALLLOONG64-82]
- _ = x[R_LOONG64_CALL36-83]
- _ = x[R_LOONG64_TLS_IE_HI-84]
- _ = x[R_LOONG64_TLS_IE_LO-85]
- _ = x[R_LOONG64_GOT_HI-86]
- _ = x[R_LOONG64_GOT_LO-87]
- _ = x[R_LOONG64_ADD64-88]
- _ = x[R_LOONG64_SUB64-89]
- _ = x[R_JMP16LOONG64-90]
- _ = x[R_JMP21LOONG64-91]
- _ = x[R_ADDRMIPSU-92]
- _ = x[R_ADDRMIPSTLS-93]
- _ = x[R_ADDRCUOFF-94]
- _ = x[R_WASMIMPORT-95]
- _ = x[R_XCOFFREF-96]
- _ = x[R_PEIMAGEOFF-97]
- _ = x[R_INITORDER-98]
- _ = x[R_DWTXTADDR_U1-99]
- _ = x[R_DWTXTADDR_U2-100]
- _ = x[R_DWTXTADDR_U3-101]
- _ = x[R_DWTXTADDR_U4-102]
+ _ = x[R_LOONG64_ADDR64_HI-79]
+ _ = x[R_LOONG64_ADDR64_LO-80]
+ _ = x[R_LOONG64_ADDR_PCREL20_S2-81]
+ _ = x[R_LOONG64_TLS_LE_HI-82]
+ _ = x[R_LOONG64_TLS_LE_LO-83]
+ _ = x[R_CALLLOONG64-84]
+ _ = x[R_LOONG64_CALL36-85]
+ _ = x[R_LOONG64_TLS_IE_HI-86]
+ _ = x[R_LOONG64_TLS_IE_LO-87]
+ _ = x[R_LOONG64_GOT_HI-88]
+ _ = x[R_LOONG64_GOT_LO-89]
+ _ = x[R_LOONG64_GOT64_HI-90]
+ _ = x[R_LOONG64_GOT64_LO-91]
+ _ = x[R_LOONG64_ADD64-92]
+ _ = x[R_LOONG64_SUB64-93]
+ _ = x[R_JMP16LOONG64-94]
+ _ = x[R_JMP21LOONG64-95]
+ _ = x[R_ADDRMIPSU-96]
+ _ = x[R_ADDRMIPSTLS-97]
+ _ = x[R_ADDRCUOFF-98]
+ _ = x[R_WASMIMPORT-99]
+ _ = x[R_XCOFFREF-100]
+ _ = x[R_PEIMAGEOFF-101]
+ _ = x[R_INITORDER-102]
+ _ = x[R_DWTXTADDR_U1-103]
+ _ = x[R_DWTXTADDR_U2-104]
+ _ = x[R_DWTXTADDR_U3-105]
+ _ = x[R_DWTXTADDR_U4-106]
}
-const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USENAMEDMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_JALR_RISCV_JAL_TRAMPR_RISCV_CALLR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IER_RISCV_TLS_LER_RISCV_GOT_HI20R_RISCV_GOT_PCREL_ITYPER_RISCV_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_ADD32R_RISCV_SUB32R_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_LOONG64_ADDR_HIR_LOONG64_ADDR_LOR_LOONG64_ADDR_PCREL20_S2R_LOONG64_TLS_LE_HIR_LOONG64_TLS_LE_LOR_CALLLOONG64R_LOONG64_CALL36R_LOONG64_TLS_IE_HIR_LOONG64_TLS_IE_LOR_LOONG64_GOT_HIR_LOONG64_GOT_LOR_LOONG64_ADD64R_LOONG64_SUB64R_JMP16LOONG64R_JMP21LOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDERR_DWTXTADDR_U1R_DWTXTADDR_U2R_DWTXTADDR_U3R_DWTXTADDR_U4"
+const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USENAMEDMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_JALR_RISCV_JAL_TRAMPR_RISCV_CALLR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IER_RISCV_TLS_LER_RISCV_GOT_HI20R_RISCV_GOT_PCREL_ITYPER_RISCV_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_ADD32R_RISCV_SUB32R_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_LOONG64_ADDR_HIR_LOONG64_ADDR_LOR_LOONG64_ADDR64_HIR_LOONG64_ADDR64_LOR_LOONG64_ADDR_PCREL20_S2R_LOONG64_TLS_LE_HIR_LOONG64_TLS_LE_LOR_CALLLOONG64R_LOONG64_CALL36R_LOONG64_TLS_IE_HIR_LOONG64_TLS_IE_LOR_LOONG64_GOT_HIR_LOONG64_GOT_LOR_LOONG64_GOT64_HIR_LOONG64_GOT64_LOR_LOONG64_ADD64R_LOONG64_SUB64R_JMP16LOONG64R_JMP21LOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDERR_DWTXTADDR_U1R_DWTXTADDR_U2R_DWTXTADDR_U3R_DWTXTADDR_U4"
-var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 226, 237, 243, 254, 264, 273, 286, 300, 314, 330, 341, 354, 373, 393, 413, 433, 446, 460, 474, 488, 503, 517, 531, 542, 564, 586, 600, 615, 638, 655, 673, 694, 709, 728, 739, 756, 768, 787, 806, 820, 834, 850, 873, 891, 911, 931, 945, 958, 971, 989, 1005, 1015, 1032, 1049, 1074, 1093, 1112, 1125, 1141, 1160, 1179, 1195, 1211, 1226, 1241, 1255, 1269, 1280, 1293, 1304, 1316, 1326, 1338, 1349, 1363, 1377, 1391, 1405}
+var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 226, 237, 243, 254, 264, 273, 286, 300, 314, 330, 341, 354, 373, 393, 413, 433, 446, 460, 474, 488, 503, 517, 531, 542, 564, 586, 600, 615, 638, 655, 673, 694, 709, 728, 739, 756, 768, 787, 806, 820, 834, 850, 873, 891, 911, 931, 945, 958, 971, 989, 1005, 1015, 1032, 1049, 1068, 1087, 1112, 1131, 1150, 1163, 1179, 1198, 1217, 1233, 1249, 1267, 1285, 1300, 1315, 1329, 1343, 1354, 1367, 1378, 1390, 1400, 1412, 1423, 1437, 1451, 1465, 1479}
func (i RelocType) String() string {
- i -= 1
- if i < 0 || i >= RelocType(len(_RelocType_index)-1) {
- return "RelocType(" + strconv.FormatInt(int64(i+1), 10) + ")"
+ idx := int(i) - 1
+ if i < 1 || idx >= len(_RelocType_index)-1 {
+ return "RelocType(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _RelocType_name[_RelocType_index[i]:_RelocType_index[i+1]]
+ return _RelocType_name[_RelocType_index[idx]:_RelocType_index[idx+1]]
}
diff --git a/src/cmd/internal/objabi/symkind_string.go b/src/cmd/internal/objabi/symkind_string.go
index fbf6a826a4..a22f9a6a1c 100644
--- a/src/cmd/internal/objabi/symkind_string.go
+++ b/src/cmd/internal/objabi/symkind_string.go
@@ -41,8 +41,9 @@ const _SymKind_name = "SxxxSTEXTSTEXTFIPSSRODATASRODATAFIPSSNOPTRDATASNOPTRDATAF
var _SymKind_index = [...]uint16{0, 4, 9, 18, 25, 36, 46, 60, 65, 74, 78, 87, 94, 106, 117, 126, 138, 148, 157, 168, 177, 188, 198, 221, 238, 254, 268}
func (i SymKind) String() string {
- if i >= SymKind(len(_SymKind_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_SymKind_index)-1 {
return "SymKind(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _SymKind_name[_SymKind_index[i]:_SymKind_index[i+1]]
+ return _SymKind_name[_SymKind_index[idx]:_SymKind_index[idx+1]]
}
diff --git a/src/cmd/link/internal/loadelf/ldelf.go b/src/cmd/link/internal/loadelf/ldelf.go
index c5c4645656..50bce8613b 100644
--- a/src/cmd/link/internal/loadelf/ldelf.go
+++ b/src/cmd/link/internal/loadelf/ldelf.go
@@ -1071,8 +1071,12 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
LOONG64 | uint32(elf.R_LARCH_B26)<<16,
LOONG64 | uint32(elf.R_LARCH_PCALA_HI20)<<16,
LOONG64 | uint32(elf.R_LARCH_PCALA_LO12)<<16,
+ LOONG64 | uint32(elf.R_LARCH_PCALA64_HI12)<<16,
+ LOONG64 | uint32(elf.R_LARCH_PCALA64_LO20)<<16,
LOONG64 | uint32(elf.R_LARCH_GOT_PC_HI20)<<16,
LOONG64 | uint32(elf.R_LARCH_GOT_PC_LO12)<<16,
+ LOONG64 | uint32(elf.R_LARCH_GOT64_PC_LO20)<<16,
+ LOONG64 | uint32(elf.R_LARCH_GOT64_PC_HI12)<<16,
LOONG64 | uint32(elf.R_LARCH_32_PCREL)<<16,
LOONG64 | uint32(elf.R_LARCH_PCREL20_S2)<<16:
return 4, 4, nil
diff --git a/src/cmd/link/internal/loong64/asm.go b/src/cmd/link/internal/loong64/asm.go
index 9881e37493..0ebdc61936 100644
--- a/src/cmd/link/internal/loong64/asm.go
+++ b/src/cmd/link/internal/loong64/asm.go
@@ -105,24 +105,37 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT_PC_HI20),
- objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT_PC_LO12):
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT_PC_LO12),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT64_PC_HI12),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT64_PC_LO20):
if targType != sym.SDYNIMPORT {
// TODO: turn LDR of GOT entry into ADR of symbol itself
}
ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_LARCH_64))
su := ldr.MakeSymbolUpdater(s)
- if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_GOT_PC_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_GOT_PC_HI20):
+ relocType = objabi.R_LOONG64_ADDR_HI
+ case objabi.RelocType(elf.R_LARCH_GOT_PC_LO12):
+ relocType = objabi.R_LOONG64_ADDR_LO
+ case objabi.RelocType(elf.R_LARCH_GOT64_PC_HI12):
+ relocType = objabi.R_LOONG64_ADDR64_HI
+ case objabi.RelocType(elf.R_LARCH_GOT64_PC_LO20):
+ relocType = objabi.R_LOONG64_ADDR64_LO
}
+
+ su.SetRelocType(rIdx, relocType)
su.SetRelocSym(rIdx, syms.GOT)
su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
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_PCALA64_HI12),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA64_LO20),
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))
@@ -137,9 +150,14 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
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_PCALA64_HI12):
+ relocType = objabi.R_LOONG64_ADDR64_HI
+ case objabi.RelocType(elf.R_LARCH_PCALA64_LO20):
+ relocType = objabi.R_LOONG64_ADDR64_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
@@ -289,14 +307,25 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
}
case objabi.R_LOONG64_GOT_HI,
- objabi.R_LOONG64_GOT_LO:
+ objabi.R_LOONG64_GOT_LO,
+ objabi.R_LOONG64_GOT64_HI,
+ objabi.R_LOONG64_GOT64_LO:
ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_LARCH_64))
su := ldr.MakeSymbolUpdater(s)
- if r.Type() == objabi.R_LOONG64_GOT_HI {
- su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_HI)
- } else {
- su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_LO)
+
+ var relocType objabi.RelocType
+ switch r.Type() {
+ case objabi.R_LOONG64_GOT_HI:
+ relocType = objabi.R_LOONG64_ADDR_HI
+ case objabi.R_LOONG64_GOT_LO:
+ relocType = objabi.R_LOONG64_ADDR_LO
+ case objabi.R_LOONG64_GOT64_HI:
+ relocType = objabi.R_LOONG64_ADDR64_HI
+ case objabi.R_LOONG64_GOT64_LO:
+ relocType = objabi.R_LOONG64_ADDR64_LO
}
+
+ su.SetRelocType(rIdx, relocType)
su.SetRelocSym(rIdx, syms.GOT)
su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
return true
@@ -454,6 +483,16 @@ 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_ADDR64_LO:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_PCALA64_LO20) | uint64(elfsym)<<32)
+ out.Write64(uint64(r.Xadd))
+
+ case objabi.R_LOONG64_ADDR64_HI:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_PCALA64_HI12) | 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)
@@ -468,6 +507,16 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
out.Write64(uint64(sectoff))
out.Write64(uint64(elf.R_LARCH_GOT_PC_LO12) | uint64(elfsym)<<32)
out.Write64(uint64(0x0))
+
+ case objabi.R_LOONG64_GOT64_HI:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_GOT64_PC_HI12) | uint64(elfsym)<<32)
+ out.Write64(uint64(0x0))
+
+ case objabi.R_LOONG64_GOT64_LO:
+ out.Write64(uint64(sectoff))
+ out.Write64(uint64(elf.R_LARCH_GOT64_PC_LO20) | uint64(elfsym)<<32)
+ out.Write64(uint64(0x0))
}
return true
@@ -485,6 +534,8 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
return val, 0, false
case objabi.R_LOONG64_ADDR_HI,
objabi.R_LOONG64_ADDR_LO,
+ objabi.R_LOONG64_ADDR64_HI,
+ objabi.R_LOONG64_ADDR64_LO,
objabi.R_LOONG64_ADDR_PCREL20_S2:
// set up addend for eventual relocation via outer symbol.
rs, _ := ld.FoldSubSymbolOffset(ldr, rs)
@@ -493,6 +544,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
}
return val, 1, true
+
case objabi.R_LOONG64_TLS_LE_HI,
objabi.R_LOONG64_TLS_LE_LO,
objabi.R_CALLLOONG64,
@@ -500,7 +552,9 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
objabi.R_LOONG64_TLS_IE_HI,
objabi.R_LOONG64_TLS_IE_LO,
objabi.R_LOONG64_GOT_HI,
- objabi.R_LOONG64_GOT_LO:
+ objabi.R_LOONG64_GOT_LO,
+ objabi.R_LOONG64_GOT64_HI,
+ objabi.R_LOONG64_GOT64_LO:
return val, 1, true
}
}
@@ -511,20 +565,43 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
switch r.Type() {
case objabi.R_CONST:
return r.Add(), noExtReloc, isOk
+
case objabi.R_GOTOFF:
return ldr.SymValue(r.Sym()) + r.Add() - ldr.SymValue(syms.GOT), noExtReloc, isOk
+
case objabi.R_LOONG64_ADDR_HI,
- objabi.R_LOONG64_ADDR_LO:
+ objabi.R_LOONG64_ADDR_LO,
+ objabi.R_LOONG64_ADDR64_HI,
+ objabi.R_LOONG64_ADDR64_LO:
pc := ldr.SymValue(s) + int64(r.Off())
- t := calculatePCAlignedReloc(r.Type(), ldr.SymAddr(rs)+r.Add(), pc)
- if r.Type() == objabi.R_LOONG64_ADDR_LO {
- return val&0xffc003ff | (t << 10), noExtReloc, isOk
+ var t int64
+
+ switch r.Type() {
+ case objabi.R_LOONG64_ADDR_LO:
+ // pcalau12i
+ t = pc32RelocBits(r.Type(), ldr.SymAddr(rs)+r.Add(), pc)
+ o = val&0xffc003ff | (t << 10)
+ case objabi.R_LOONG64_ADDR_HI:
+ // addi.w/addi.d
+ t = pc32RelocBits(r.Type(), ldr.SymAddr(rs)+r.Add(), pc)
+ o = val&0xfe00001f | (t << 5)
+ case objabi.R_LOONG64_ADDR64_LO:
+ // lu32i.d
+ t = pc64RelocBits(r.Type(), ldr.SymAddr(rs)+r.Add(), pc-8)
+ o = val&0xfe00001f | (t << 5)
+ case objabi.R_LOONG64_ADDR64_HI:
+ // lu52i.d
+ t = pc64RelocBits(r.Type(), ldr.SymAddr(rs)+r.Add(), pc-12)
+ o = val&0xffc003ff | (t << 10)
}
- return val&0xfe00001f | (t << 5), noExtReloc, isOk
+
+ return o, 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()
@@ -532,6 +609,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
return val&0xffc003ff | ((t & 0xfff) << 10), noExtReloc, isOk
}
return val&0xfe00001f | (((t) >> 12 << 5) & 0x1ffffe0), noExtReloc, isOk
+
case objabi.R_CALLLOONG64:
pc := ldr.SymValue(s) + int64(r.Off())
t := ldr.SymAddr(rs) + r.Add() - pc
@@ -589,8 +667,12 @@ func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sy
switch r.Type() {
case objabi.R_LOONG64_ADDR_HI,
objabi.R_LOONG64_ADDR_LO,
+ objabi.R_LOONG64_ADDR64_HI,
+ objabi.R_LOONG64_ADDR64_LO,
objabi.R_LOONG64_GOT_HI,
- objabi.R_LOONG64_GOT_LO:
+ objabi.R_LOONG64_GOT_LO,
+ objabi.R_LOONG64_GOT64_HI,
+ objabi.R_LOONG64_GOT64_LO:
return ld.ExtrelocViaOuterSym(ldr, r, s), true
case objabi.R_LOONG64_TLS_LE_HI,
@@ -605,34 +687,71 @@ func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sy
return loader.ExtReloc{}, false
}
-func isRequestingLowPageBits(t objabi.RelocType) bool {
- switch t {
- case objabi.R_LOONG64_ADDR_LO:
- return true
+// Comments from copying binutils/bfd/elfnn-loongarch.c
+//
+// For example: pc is 0x11000010000100, symbol is 0x1812348ffff812
+//
+// offset = (0x1812348ffff812 & ~0xfff) - (0x11000010000100 & ~0xfff)
+// offset = 0x712347ffff000
+//
+// lo12: 0x1812348ffff812 & 0xfff = 0x812
+// hi20: 0x7ffff + 0x1(lo12 > 0x7ff) = 0x80000
+// lo20: 0x71234 - 0x1(lo12 > 0x7ff) + 0x1(hi20 > 0x7ffff)
+// hi12: 0x0
+//
+// pcalau12i $t1, hi20 (0x80000)
+//
+// $t1 = 0x11000010000100 + sign-extend(0x80000 << 12)
+// = 0x11000010000100 + 0xffffffff80000000
+// = 0x10ffff90000000
+//
+// addi.d $t0, $zero, lo12 (0x812)
+//
+// $t0 = 0xfffffffffffff812 (if lo12 > 0x7ff, because sign-extend,
+// lo20 need to sub 0x1)
+//
+// lu32i.d $t0, lo20 (0x71234)
+//
+// $t0 = {0x71234, 0xfffff812}
+// = 0x71234fffff812
+//
+// lu52i.d $t0, hi12 (0x0)
+//
+// $t0 = {0x0, 0x71234fffff812}
+// = 0x71234fffff812
+func pc32RelocBits(reloc objabi.RelocType, tgt int64, pc int64) int64 {
+ lo12 := tgt & 0xfff
+ if reloc == objabi.R_LOONG64_ADDR_LO {
+ return lo12
}
- return false
+
+ off := (tgt & ^0xfff) - (pc & ^0xfff)
+ if lo12 >= 0x800 {
+ off += 0x1000
+ }
+
+ // objabi.R_LOONG64_ADDR_HI
+ return (off >> 12) & 0xfffff
}
-// Calculates the value to put into the immediate slot, according to the
-// desired relocation type, target and PC.
-// The value to use varies based on the reloc type. Namely, the absolute low
-// bits of the target are to be used for the low part, while the page-aligned
-// offset is to be used for the higher part. A "page" here is not related to
-// the system's actual page size, but rather a fixed 12-bit range (designed to
-// cooperate with ADDI/LD/ST's 12-bit immediates).
-func calculatePCAlignedReloc(t objabi.RelocType, tgt int64, pc int64) int64 {
- if isRequestingLowPageBits(t) {
- // corresponding immediate field is 12 bits wide
- return tgt & 0xfff
+func pc64RelocBits(reloc objabi.RelocType, tgt int64, pc int64) int64 {
+ lo12 := tgt & 0xfff
+ off := (tgt & ^0xfff) - (pc & ^0xfff)
+
+ if lo12 >= 0x800 {
+ off += (0x1000 - 0x100000000)
}
- pageDelta := (tgt >> 12) - (pc >> 12)
- if tgt&0xfff >= 0x800 {
- // adjust for sign-extended addition of the low bits
- pageDelta += 1
+ if (off & 0x80000000) != 0 {
+ off += 0x100000000
}
- // corresponding immediate field is 20 bits wide
- return pageDelta & 0xfffff
+
+ if reloc == objabi.R_LOONG64_ADDR64_LO {
+ return (off >> 32) & 0xfffff
+ }
+
+ // objabi.R_LOONG64_ADDR64_HI
+ return (off >> 52) & 0xfff
}
// Convert the direct jump relocation r to refer to a trampoline if the target is too far.