From: Joel Sing Date: Wed, 16 Aug 2023 15:13:32 +0000 (+1000) Subject: cmd/internal/obj/riscv,cmd/link: rework riscv64 call relocations X-Git-Tag: go1.22rc1~793 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=bda5e6c3d07c23d477f68f09e3414e495b12a87e;p=gostls13.git cmd/internal/obj/riscv,cmd/link: rework riscv64 call relocations The riscv64 assembler and linker generate three types of calls. Most calls are made via a single JAL instruction, however this is limited to +/-1MB of text. In the case where a call target is unreachable (or unknown), the JAL targets an AUIPC+JALR trampoline. All other cases use AUIPC+JALR pairs, including the case where a single function exceeds 1MB in text size, potentially making it impossible to reach trampolines. Currently, the single instruction JAL call is marked with R_RISCV_CALL and the two instruction AUIPC+JALR call is marked with R_RISCV_PCREL_ITYPE, which is also used for memory load instructions. This means that we have no way to identify that the latter is a call. Switch to using R_RISCV_CALL to mark the AUIPC+JALR pair (aligning somewhat with the elf.R_RISCV_CALL, which is deprecated in favour of elf.R_RISCV_CALL_PLT). Add R_RISCV_JAL and use this to mark the single instruction JAL direct calls. This is clearer and allows us to map elf.R_RISCV_CALL_PLT to Go's R_RISCV_CALL. Add all three types to IsDirectCall, so that direct calls are correctly identified when a function exceeds 1MB of text. Fixes #62465 Change-Id: Id3eea09688a2b7d6e481eae9ed0aa0d1f9a3a48f Reviewed-on: https://go-review.googlesource.com/c/go/+/520095 TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui Run-TryBot: Joel Sing Reviewed-by: Than McIntosh --- diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 9899ec9e7b..2afa457105 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -381,7 +381,7 @@ start: JMP 4(X5) // 67804200 // CALL and JMP to symbol are encoded as JAL (using LR or ZERO - // respectively), with a R_RISCV_CALL relocation. The linker resolves + // respectively), with a R_RISCV_JAL relocation. The linker resolves // the real address and updates the immediate, using a trampoline in // the case where the address is not directly reachable. CALL asmtest(SB) // ef000000 diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go index bfd5153da4..edd1ac820b 100644 --- a/src/cmd/internal/obj/riscv/cpu.go +++ b/src/cmd/internal/obj/riscv/cpu.go @@ -260,8 +260,13 @@ const ( // corresponding *obj.Prog uses the temporary register. USES_REG_TMP = 1 << iota - // NEED_CALL_RELOC is set on JAL instructions to indicate that a - // R_RISCV_CALL relocation is needed. + // NEED_JAL_RELOC is set on JAL instructions to indicate that a + // R_RISCV_JAL relocation is needed. + NEED_JAL_RELOC + + // NEED_CALL_RELOC is set on an AUIPC instruction to indicate that it + // is the first instruction in an AUIPC + JAL pair that needs a + // R_RISCV_CALL relocation. NEED_CALL_RELOC // NEED_PCREL_ITYPE_RELOC is set on AUIPC instructions to indicate that diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 4df28a43f6..501d518019 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -41,7 +41,7 @@ func jalToSym(ctxt *obj.Link, p *obj.Prog, lr int16) { } p.As = AJAL - p.Mark |= NEED_CALL_RELOC + p.Mark |= NEED_JAL_RELOC p.From.Type = obj.TYPE_REG p.From.Reg = lr p.Reg = obj.REG_NONE @@ -610,7 +610,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { var callCount int for p := cursym.Func().Text; p != nil; p = p.Link { markRelocs(p) - if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC { + if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC { callCount++ } } @@ -664,7 +664,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} p.As = AAUIPC - p.Mark = (p.Mark &^ NEED_CALL_RELOC) | NEED_PCREL_ITYPE_RELOC + p.Mark = (p.Mark &^ NEED_JAL_RELOC) | NEED_CALL_RELOC p.AddRestSource(obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym}) p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0} p.Reg = obj.REG_NONE @@ -2345,13 +2345,13 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { for p := cursym.Func().Text; p != nil; p = p.Link { switch p.As { case AJAL: - if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC { + if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC { rel := obj.Addrel(cursym) rel.Off = int32(p.Pc) rel.Siz = 4 rel.Sym = p.To.Sym rel.Add = p.To.Offset - rel.Type = objabi.R_RISCV_CALL + rel.Type = objabi.R_RISCV_JAL } case AJALR: if p.To.Sym != nil { @@ -2361,7 +2361,10 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: var addr *obj.Addr var rt objabi.RelocType - if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC { + if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC { + rt = objabi.R_RISCV_CALL + addr = &p.From + } else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC { rt = objabi.R_RISCV_PCREL_ITYPE addr = &p.From } else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC { diff --git a/src/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go index 3312a4de7e..e3e042a511 100644 --- a/src/cmd/internal/objabi/reloctype.go +++ b/src/cmd/internal/objabi/reloctype.go @@ -259,28 +259,31 @@ const ( // RISC-V. - // R_RISCV_CALL relocates a J-type instruction with a 21 bit PC-relative - // address. - R_RISCV_CALL + // R_RISCV_JAL resolves a 20 bit offset for a J-type instruction. + R_RISCV_JAL - // R_RISCV_CALL_TRAMP is the same as R_RISCV_CALL but denotes the use of a + // R_RISCV_JAL_TRAMP is the same as R_RISCV_JAL but denotes the use of a // trampoline, which we may be able to avoid during relocation. These are // only used by the linker and are not emitted by the compiler or assembler. - R_RISCV_CALL_TRAMP + R_RISCV_JAL_TRAMP - // R_RISCV_PCREL_ITYPE resolves a 32 bit PC-relative address using an + // R_RISCV_CALL resolves a 32 bit PC-relative address for an AUIPC + JALR + // instruction pair. + R_RISCV_CALL + + // R_RISCV_PCREL_ITYPE resolves a 32 bit PC-relative address for an // AUIPC + I-type instruction pair. R_RISCV_PCREL_ITYPE - // R_RISCV_PCREL_STYPE resolves a 32 bit PC-relative address using an + // R_RISCV_PCREL_STYPE resolves a 32 bit PC-relative address for an // AUIPC + S-type instruction pair. R_RISCV_PCREL_STYPE - // R_RISCV_TLS_IE resolves a 32 bit TLS initial-exec address using an + // R_RISCV_TLS_IE resolves a 32 bit TLS initial-exec address for an // AUIPC + I-type instruction pair. R_RISCV_TLS_IE - // R_RISCV_TLS_LE resolves a 32 bit TLS local-exec address using an + // R_RISCV_TLS_LE resolves a 32 bit TLS local-exec address for a // LUI + I-type instruction sequence. R_RISCV_TLS_LE @@ -387,12 +390,13 @@ const ( // IsDirectCall reports whether r is a relocation for a direct call. // A direct call is a CALL instruction that takes the target address -// as an immediate. The address is embedded into the instruction, possibly +// as an immediate. The address is embedded into the instruction(s), possibly // with limited width. An indirect call is a CALL instruction that takes // the target address in register or memory. func (r RelocType) IsDirectCall() bool { switch r { - case R_CALL, R_CALLARM, R_CALLARM64, R_CALLLOONG64, R_CALLMIPS, R_CALLPOWER, R_RISCV_CALL, R_RISCV_CALL_TRAMP: + case R_CALL, R_CALLARM, R_CALLARM64, R_CALLLOONG64, R_CALLMIPS, R_CALLPOWER, + R_RISCV_CALL, R_RISCV_JAL, R_RISCV_JAL_TRAMP: return true } return false diff --git a/src/cmd/internal/objabi/reloctype_string.go b/src/cmd/internal/objabi/reloctype_string.go index ea4be10e4b..e8793dedc1 100644 --- a/src/cmd/internal/objabi/reloctype_string.go +++ b/src/cmd/internal/objabi/reloctype_string.go @@ -67,40 +67,41 @@ func _() { _ = x[R_ADDRPOWER_TOCREL_DS-57] _ = x[R_ADDRPOWER_D34-58] _ = x[R_ADDRPOWER_PCREL34-59] - _ = x[R_RISCV_CALL-60] - _ = x[R_RISCV_CALL_TRAMP-61] - _ = x[R_RISCV_PCREL_ITYPE-62] - _ = x[R_RISCV_PCREL_STYPE-63] - _ = x[R_RISCV_TLS_IE-64] - _ = x[R_RISCV_TLS_LE-65] - _ = x[R_RISCV_GOT_HI20-66] - _ = x[R_RISCV_PCREL_HI20-67] - _ = x[R_RISCV_PCREL_LO12_I-68] - _ = x[R_RISCV_PCREL_LO12_S-69] - _ = x[R_RISCV_BRANCH-70] - _ = x[R_RISCV_RVC_BRANCH-71] - _ = x[R_RISCV_RVC_JUMP-72] - _ = x[R_PCRELDBL-73] - _ = x[R_ADDRLOONG64-74] - _ = x[R_ADDRLOONG64U-75] - _ = x[R_ADDRLOONG64TLS-76] - _ = x[R_ADDRLOONG64TLSU-77] - _ = x[R_CALLLOONG64-78] - _ = x[R_LOONG64_TLS_IE_PCREL_HI-79] - _ = x[R_LOONG64_TLS_IE_LO-80] - _ = x[R_JMPLOONG64-81] - _ = x[R_ADDRMIPSU-82] - _ = x[R_ADDRMIPSTLS-83] - _ = x[R_ADDRCUOFF-84] - _ = x[R_WASMIMPORT-85] - _ = x[R_XCOFFREF-86] - _ = x[R_PEIMAGEOFF-87] - _ = x[R_INITORDER-88] + _ = x[R_RISCV_JAL-60] + _ = x[R_RISCV_JAL_TRAMP-61] + _ = x[R_RISCV_CALL-62] + _ = x[R_RISCV_PCREL_ITYPE-63] + _ = x[R_RISCV_PCREL_STYPE-64] + _ = x[R_RISCV_TLS_IE-65] + _ = x[R_RISCV_TLS_LE-66] + _ = x[R_RISCV_GOT_HI20-67] + _ = x[R_RISCV_PCREL_HI20-68] + _ = x[R_RISCV_PCREL_LO12_I-69] + _ = x[R_RISCV_PCREL_LO12_S-70] + _ = x[R_RISCV_BRANCH-71] + _ = x[R_RISCV_RVC_BRANCH-72] + _ = x[R_RISCV_RVC_JUMP-73] + _ = x[R_PCRELDBL-74] + _ = x[R_ADDRLOONG64-75] + _ = x[R_ADDRLOONG64U-76] + _ = x[R_ADDRLOONG64TLS-77] + _ = x[R_ADDRLOONG64TLSU-78] + _ = x[R_CALLLOONG64-79] + _ = x[R_LOONG64_TLS_IE_PCREL_HI-80] + _ = x[R_LOONG64_TLS_IE_LO-81] + _ = x[R_JMPLOONG64-82] + _ = x[R_ADDRMIPSU-83] + _ = x[R_ADDRMIPSTLS-84] + _ = x[R_ADDRCUOFF-85] + _ = x[R_WASMIMPORT-86] + _ = x[R_XCOFFREF-87] + _ = x[R_PEIMAGEOFF-88] + _ = x[R_INITORDER-89] } -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_DWARFFILEREFR_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_CALLR_RISCV_CALL_TRAMPR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IER_RISCV_TLS_LER_RISCV_GOT_HI20R_RISCV_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_ADDRLOONG64R_ADDRLOONG64UR_ADDRLOONG64TLSR_ADDRLOONG64TLSUR_CALLLOONG64R_LOONG64_TLS_IE_PCREL_HIR_LOONG64_TLS_IE_LOR_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDER" +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_DWARFFILEREFR_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_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_ADDRLOONG64R_ADDRLOONG64UR_ADDRLOONG64TLSR_ADDRLOONG64TLSUR_CALLLOONG64R_LOONG64_TLS_IE_PCREL_HIR_LOONG64_TLS_IE_LOR_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDER" -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, 328, 344, 355, 368, 387, 407, 427, 447, 460, 474, 488, 502, 517, 531, 545, 556, 578, 600, 614, 629, 652, 669, 687, 708, 723, 742, 754, 772, 791, 810, 824, 838, 854, 872, 892, 912, 926, 944, 960, 970, 983, 997, 1013, 1030, 1043, 1068, 1087, 1099, 1110, 1123, 1134, 1146, 1156, 1168, 1179} +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, 328, 344, 355, 368, 387, 407, 427, 447, 460, 474, 488, 502, 517, 531, 545, 556, 578, 600, 614, 629, 652, 669, 687, 708, 723, 742, 753, 770, 782, 801, 820, 834, 848, 864, 882, 902, 922, 936, 954, 970, 980, 993, 1007, 1023, 1040, 1053, 1078, 1097, 1109, 1120, 1133, 1144, 1156, 1166, 1178, 1189} func (i RelocType) String() string { i -= 1 diff --git a/src/cmd/link/internal/riscv64/asm.go b/src/cmd/link/internal/riscv64/asm.go index 654d639aa7..d95de6cb36 100644 --- a/src/cmd/link/internal/riscv64/asm.go +++ b/src/cmd/link/internal/riscv64/asm.go @@ -63,7 +63,7 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade ldr.Errorf(s, "unknown symbol %s in RISCV call", ldr.SymName(targ)) } su := ldr.MakeSymbolUpdater(s) - su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_ITYPE) + su.SetRelocType(rIdx, objabi.R_RISCV_CALL) return true case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_GOT_HI20): @@ -130,7 +130,7 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade r = relocs.At(rIdx) switch r.Type() { - case objabi.R_RISCV_PCREL_ITYPE: + case objabi.R_RISCV_CALL: if targType != sym.SDYNIMPORT { // nothing to do, the relocation will be laid out in reloc return true @@ -228,12 +228,12 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, } out.Write64(uint64(r.Xadd)) - case objabi.R_RISCV_CALL, objabi.R_RISCV_CALL_TRAMP: + case objabi.R_RISCV_JAL, objabi.R_RISCV_JAL_TRAMP: out.Write64(uint64(sectoff)) out.Write64(uint64(elf.R_RISCV_JAL) | uint64(elfsym)<<32) out.Write64(uint64(r.Xadd)) - case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE: + case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE: // Find the text symbol for the AUIPC instruction targeted // by this relocation. relocs := ldr.Relocs(s) @@ -256,7 +256,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, // var hiRel, loRel elf.R_RISCV switch r.Type { - case objabi.R_RISCV_PCREL_ITYPE: + case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE: hiRel, loRel = elf.R_RISCV_PCREL_HI20, elf.R_RISCV_PCREL_LO12_I case objabi.R_RISCV_PCREL_STYPE: hiRel, loRel = elf.R_RISCV_PCREL_HI20, elf.R_RISCV_PCREL_LO12_S @@ -399,20 +399,20 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade // If the call points to a trampoline, see if we can reach the symbol // directly. This situation can occur when the relocation symbol is // not assigned an address until after the trampolines are generated. - if r.Type() == objabi.R_RISCV_CALL_TRAMP { + if r.Type() == objabi.R_RISCV_JAL_TRAMP { relocs := ldr.Relocs(rs) if relocs.Count() != 1 { ldr.Errorf(s, "trampoline %v has %d relocations", ldr.SymName(rs), relocs.Count()) } tr := relocs.At(0) - if tr.Type() != objabi.R_RISCV_PCREL_ITYPE { + if tr.Type() != objabi.R_RISCV_CALL { ldr.Errorf(s, "trampoline %v has unexpected relocation %v", ldr.SymName(rs), tr.Type()) } trs := tr.Sym() if ldr.SymValue(trs) != 0 && ldr.SymType(trs) != sym.SDYNIMPORT && ldr.SymType(trs) != sym.SUNDEFEXT { trsOff := ldr.SymValue(trs) + tr.Add() - pc if trsOff >= -(1<<20) && trsOff < (1<<20) { - r.SetType(objabi.R_RISCV_CALL) + r.SetType(objabi.R_RISCV_JAL) r.SetSym(trs) r.SetAdd(tr.Add()) rs = trs @@ -423,10 +423,10 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade if target.IsExternal() { switch r.Type() { - case objabi.R_RISCV_CALL, objabi.R_RISCV_CALL_TRAMP: + case objabi.R_RISCV_JAL, objabi.R_RISCV_JAL_TRAMP: return val, 1, true - case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE: + case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE: return val, 2, true } @@ -436,11 +436,11 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade off := ldr.SymValue(rs) + r.Add() - pc switch r.Type() { - case objabi.R_RISCV_CALL, objabi.R_RISCV_CALL_TRAMP: + case objabi.R_RISCV_JAL, objabi.R_RISCV_JAL_TRAMP: // Generate instruction immediates. imm, err := riscv.EncodeJImmediate(off) if err != nil { - ldr.Errorf(s, "cannot encode R_RISCV_CALL relocation offset for %s: %v", ldr.SymName(rs), err) + ldr.Errorf(s, "cannot encode J-type instruction relocation offset for %s: %v", ldr.SymName(rs), err) } immMask := int64(riscv.JTypeImmMask) @@ -574,31 +574,31 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade ins = (ins &^ immMask) | int64(uint32(imm)) return ins, 0, true - case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE: + case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE: // Generate AUIPC and second instruction immediates. low, high, err := riscv.Split32BitImmediate(off) if err != nil { - ldr.Errorf(s, "R_RISCV_PCREL_ relocation does not fit in 32 bits: %d", off) + ldr.Errorf(s, "pc-relative relocation does not fit in 32 bits: %d", off) } auipcImm, err := riscv.EncodeUImmediate(high) if err != nil { - ldr.Errorf(s, "cannot encode R_RISCV_PCREL_ AUIPC relocation offset for %s: %v", ldr.SymName(rs), err) + ldr.Errorf(s, "cannot encode AUIPC relocation offset for %s: %v", ldr.SymName(rs), err) } var secondImm, secondImmMask int64 switch r.Type() { - case objabi.R_RISCV_PCREL_ITYPE: + case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE: secondImmMask = riscv.ITypeImmMask secondImm, err = riscv.EncodeIImmediate(low) if err != nil { - ldr.Errorf(s, "cannot encode R_RISCV_PCREL_ITYPE I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err) + ldr.Errorf(s, "cannot encode I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err) } case objabi.R_RISCV_PCREL_STYPE: secondImmMask = riscv.STypeImmMask secondImm, err = riscv.EncodeSImmediate(low) if err != nil { - ldr.Errorf(s, "cannot encode R_RISCV_PCREL_STYPE S-type instruction relocation offset for %s: %v", ldr.SymName(rs), err) + ldr.Errorf(s, "cannot encode S-type instruction relocation offset for %s: %v", ldr.SymName(rs), err) } default: panic(fmt.Sprintf("unknown relocation type: %v", r.Type())) @@ -623,10 +623,10 @@ func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) { switch r.Type() { - case objabi.R_RISCV_CALL, objabi.R_RISCV_CALL_TRAMP: + case objabi.R_RISCV_JAL, objabi.R_RISCV_JAL_TRAMP: return ld.ExtrelocSimple(ldr, r), true - case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE: + case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE: return ld.ExtrelocViaOuterSym(ldr, r, s), true } return loader.ExtReloc{}, false @@ -637,7 +637,7 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { r := relocs.At(ri) switch r.Type() { - case objabi.R_RISCV_CALL: + case objabi.R_RISCV_JAL: pc := ldr.SymValue(s) + int64(r.Off()) off := ldr.SymValue(rs) + r.Add() - pc @@ -691,13 +691,16 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { // address, so we have to assume a trampoline is required. Mark // this as a call via a trampoline so that we can potentially // switch to a direct call during relocation. - sb.SetRelocType(ri, objabi.R_RISCV_CALL_TRAMP) + sb.SetRelocType(ri, objabi.R_RISCV_JAL_TRAMP) } relocs := sb.Relocs() r := relocs.At(ri) r.SetSym(tramp) r.SetAdd(0) + case objabi.R_RISCV_CALL: + // Nothing to do, already using AUIPC+JALR. + default: ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type())) } @@ -707,7 +710,7 @@ func genCallTramp(arch *sys.Arch, linkmode ld.LinkMode, ldr *loader.Loader, tram tramp.AddUint32(arch, 0x00000f97) // AUIPC $0, X31 tramp.AddUint32(arch, 0x000f8067) // JALR X0, (X31) - r, _ := tramp.AddRel(objabi.R_RISCV_PCREL_ITYPE) + r, _ := tramp.AddRel(objabi.R_RISCV_CALL) r.SetSiz(8) r.SetSym(target) r.SetAdd(offset)