diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/internal/obj/fips140.go | 4 | ||||
| -rw-r--r-- | src/cmd/internal/objabi/reloctype.go | 26 | ||||
| -rw-r--r-- | src/cmd/internal/objabi/reloctype_string.go | 64 | ||||
| -rw-r--r-- | src/cmd/internal/objabi/symkind_string.go | 5 | ||||
| -rw-r--r-- | src/cmd/link/internal/loadelf/ldelf.go | 4 | ||||
| -rw-r--r-- | src/cmd/link/internal/loong64/asm.go | 197 |
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. |
