]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/riscv,cmd/link: rework riscv64 call relocations
authorJoel Sing <joel@sing.id.au>
Wed, 16 Aug 2023 15:13:32 +0000 (01:13 +1000)
committerJoel Sing <joel@sing.id.au>
Tue, 19 Sep 2023 18:10:13 +0000 (18:10 +0000)
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 <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Joel Sing <joel@sing.id.au>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/asm/internal/asm/testdata/riscv64.s
src/cmd/internal/obj/riscv/cpu.go
src/cmd/internal/obj/riscv/obj.go
src/cmd/internal/objabi/reloctype.go
src/cmd/internal/objabi/reloctype_string.go
src/cmd/link/internal/riscv64/asm.go

index 9899ec9e7b63a3636de37a099576294b5848f1b8..2afa45710517dd81d33f6f9d338b10bbf515cdeb 100644 (file)
@@ -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
index bfd5153da445998e4631c92834083d9433f2690b..edd1ac820bf03a691007a9832272e4c73e9d8fe3 100644 (file)
@@ -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
index 4df28a43f6bb05bcf6b43689b2e53931292a5465..501d518019044593e076166e0fef1a3cd6286f73 100644 (file)
@@ -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 {
index 3312a4de7e36394946ba6220bed3120a9aa8ab79..e3e042a511d02b023ce4eff899a4eceb1e233d58 100644 (file)
@@ -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
index ea4be10e4bdbcf93963afe04d567828eb79df35c..e8793dedc1e28de6f5dab7f8acae17224db04d99 100644 (file)
@@ -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
index 654d639aa748db116a7ba7aabf8aef68ce59cbda..d95de6cb3627cbc8a3c081acc565af6653fadbbb 100644 (file)
@@ -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)