R_RISCV_CALL/R_RISCV_CALL_PLT distinction isn't necessary. R_RISCV_CALL has been
deprecated as a resolution to
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/98 .
ld.lld and mold treat the two relocation types the same. GNU ld has a custom
handling for undefined weak functions which is unnecessary: calling an
unresolved undefined weak function is UB and GNU ld can handle the case without
a relocation error (such a function call is usually guarded by a zero value
check and should be allowed).
This patch assembles `call foo` to use R_RISCV_CALL_PLT instead of the
deprecated R_RISCV_CALL.
Note: the code generator still differentiates `call foo` and (maybe preemptible)
`call foo@plt`, but the difference is purely aesthetic.
Note: D105429 does not support R_RISCV_CALL_PLT correctly. Changed the test to
force R_RISCV_CALL for now.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D132530
# RUN: ld.lld %t.rv32.o --defsym foo=_start+0x7ffff800 --defsym bar=_start+8-0x80000801 -o %t
# RUN: not ld.lld %t.rv64.o --defsym foo=_start+0x7ffff800 --defsym bar=_start+8-0x80000801 -o /dev/null 2>&1 | \
# RUN: FileCheck --check-prefix=ERROR %s
-# ERROR: relocation R_RISCV_CALL out of range: 524288 is not in [-524288, 524287]; references foo
-# ERROR: relocation R_RISCV_CALL out of range: -524289 is not in [-524288, 524287]; references bar
+# ERROR: relocation R_RISCV_CALL_PLT out of range: 524288 is not in [-524288, 524287]; references foo
+# ERROR: relocation R_RISCV_CALL_PLT out of range: -524289 is not in [-524288, 524287]; references bar
.global _start
_start:
## Branch relocations
## If .dynsym does not exist, an undefined weak symbol is non-preemptible.
## Treat them as PC relative relocations.
-# RELOC: 0x18 R_RISCV_CALL target 0x0
+# RELOC: 0x18 R_RISCV_CALL_PLT target 0x0
# RELOC-NEXT: 0x20 R_RISCV_JAL target 0x0
# RELOC-NEXT: 0x24 R_RISCV_BRANCH target 0x0
case RISCV::fixup_riscv_rvc_branch:
return ELF::R_RISCV_RVC_BRANCH;
case RISCV::fixup_riscv_call:
- return ELF::R_RISCV_CALL;
+ return ELF::R_RISCV_CALL_PLT;
case RISCV::fixup_riscv_call_plt:
return ELF::R_RISCV_CALL_PLT;
case RISCV::fixup_riscv_add_8:
# Test R_RISCV_CALL
# jitlink-check: decode_operand(test_call, 1) = ((external_func - test_call) + 0x800)[31:12]
# jitlink-check: decode_operand(test_call+4, 2)[11:0] = (external_func - test_call)[11:0]
- .globl test_call
+ .globl test_call, external_func
.p2align 1
.type test_call,@function
test_call:
- call external_func
+ .reloc ., R_RISCV_CALL, external_func
+ auipc ra, 0
+ jalr ra
ret
.size test_call, .-test_call
.long foo
call foo
-# RELOC: R_RISCV_CALL foo 0x0
+# RELOC: R_RISCV_CALL_PLT foo 0x0
# INSTR: auipc ra, 0
# INSTR: jalr ra
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_call
call bar
-# RELOC: R_RISCV_CALL bar 0x0
+# RELOC: R_RISCV_CALL_PLT bar 0x0
# INSTR: auipc ra, 0
# INSTR: jalr ra
# FIXUP: fixup A - offset: 0, value: bar, kind: fixup_riscv_call
# Ensure that calls to functions whose names coincide with register names work.
call zero
-# RELOC: R_RISCV_CALL zero 0x0
+# RELOC: R_RISCV_CALL_PLT zero 0x0
# INSTR: auipc ra, 0
# INSTR: jalr ra
# FIXUP: fixup A - offset: 0, value: zero, kind: fixup_riscv_call
call f1
-# RELOC: R_RISCV_CALL f1 0x0
+# RELOC: R_RISCV_CALL_PLT f1 0x0
# INSTR: auipc ra, 0
# INSTR: jalr ra
# FIXUP: fixup A - offset: 0, value: f1, kind: fixup_riscv_call
call ra
-# RELOC: R_RISCV_CALL ra 0x0
+# RELOC: R_RISCV_CALL_PLT ra 0x0
# INSTR: auipc ra, 0
# INSTR: jalr ra
# FIXUP: fixup A - offset: 0, value: ra, kind: fixup_riscv_call
call mstatus
-# RELOC: R_RISCV_CALL mstatus 0x0
+# RELOC: R_RISCV_CALL_PLT mstatus 0x0
# INSTR: auipc ra, 0
# INSTR: jalr ra
# FIXUP: fixup A - offset: 0, value: mstatus, kind: fixup_riscv_call
# Ensure that an explicit register operand can be parsed.
call a0, foo
-# RELOC: R_RISCV_CALL foo 0x0
+# RELOC: R_RISCV_CALL_PLT foo 0x0
# INSTR: auipc a0, 0
# INSTR: jalr a0
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_call
.long foo
call foo
-# NORELAX-RELOC: R_RISCV_CALL foo 0x0
+# NORELAX-RELOC: R_RISCV_CALL_PLT foo 0x0
# NORELAX-RELOC-NOT: R_RISCV_RELAX
-# RELAX-RELOC: R_RISCV_CALL foo 0x0
+# RELAX-RELOC: R_RISCV_CALL_PLT foo 0x0
# RELAX-RELOC: R_RISCV_RELAX - 0x0
# RELAX-FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_call
# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
call bar
# NORELAX-RELOC-NOT: R_RISCV_CALL
# NORELAX-RELOC-NOT: R_RISCV_RELAX
-# RELAX-RELOC: R_RISCV_CALL bar 0x0
+# RELAX-RELOC: R_RISCV_CALL_PLT bar 0x0
# RELAX-RELOC: R_RISCV_RELAX - 0x0
# RELAX-FIXUP: fixup A - offset: 0, value: bar, kind: fixup_riscv_call
# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
# where .option pop was last used.
# CHECK-INST: call foo
-# CHECK-RELOC: R_RISCV_CALL foo 0x0
+# CHECK-RELOC: R_RISCV_CALL_PLT foo 0x0
# CHECK-RELOC-NOT: R_RISCV_RELAX - 0x0
call foo
.option relax
# CHECK-INST: .option relax
# CHECK-INST: call bar
-# CHECK-RELOC-NEXT: R_RISCV_CALL bar 0x0
+# CHECK-RELOC-NEXT: R_RISCV_CALL_PLT bar 0x0
# CHECK-RELOC-NEXT: R_RISCV_RELAX - 0x0
call bar
addi s0, sp, 1020
# CHECK-INST: call bar
-# CHECK-RELOC-NEXT: R_RISCV_CALL bar 0x0
+# CHECK-RELOC-NEXT: R_RISCV_CALL_PLT bar 0x0
# CHECK-RELOC-NEXT: R_RISCV_RELAX - 0x0
call bar
.option pop # Pop relax=false, rvc=false
# CHECK-INST: .option pop
# CHECK-INST: call baz
-# CHECK-RELOC: R_RISCV_CALL baz 0x0
+# CHECK-RELOC: R_RISCV_CALL_PLT baz 0x0
# CHECK-RELOC-NOT: R_RISCV_RELAX - 0x0
call baz
# CHECK-INST: .option norelax
# CHECK-INST: call foo
-# CHECK-RELOC: R_RISCV_CALL foo 0x0
+# CHECK-RELOC: R_RISCV_CALL_PLT foo 0x0
# CHECK-RELOC-NOT: R_RISCV_RELAX - 0x0
call foo
# CHECK-INST: .option relax
# CHECK-INST: call bar
-# CHECK-RELOC-NEXT: R_RISCV_CALL bar 0x0
+# CHECK-RELOC-NEXT: R_RISCV_CALL_PLT bar 0x0
# CHECK-RELOC-NEXT: R_RISCV_RELAX - 0x0
call bar
# CHECK-INST: .option norelax
# CHECK-INST: call baz
-# CHECK-RELOC-NEXT: R_RISCV_CALL baz 0x0
+# CHECK-RELOC-NEXT: R_RISCV_CALL_PLT baz 0x0
# CHECK-RELOC-NOT: R_RISCV_RELAX - 0x0
call baz
.long foo
jump foo, x31
-# RELOC: R_RISCV_CALL foo 0x0
+# RELOC: R_RISCV_CALL_PLT foo 0x0
# INSTR: auipc t6, 0
# INSTR: jr t6
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_call
# Ensure that jumps to symbols whose names coincide with register names work.
jump zero, x1
-# RELOC: R_RISCV_CALL zero 0x0
+# RELOC: R_RISCV_CALL_PLT zero 0x0
# INSTR: auipc ra, 0
# INSTR: ret
# FIXUP: fixup A - offset: 0, value: zero, kind: fixup_riscv_call
.long foo
tail foo
-# RELOC: R_RISCV_CALL foo 0x0
+# RELOC: R_RISCV_CALL_PLT foo 0x0
# INSTR: auipc t1, 0
# INSTR: jr t1
# FIXUP: fixup A - offset: 0, value: foo, kind:
tail bar
-# RELOC: R_RISCV_CALL bar 0x0
+# RELOC: R_RISCV_CALL_PLT bar 0x0
# INSTR: auipc t1, 0
# INSTR: jr t1
# FIXUP: fixup A - offset: 0, value: bar, kind:
# work.
tail zero
-# RELOC: R_RISCV_CALL zero 0x0
+# RELOC: R_RISCV_CALL_PLT zero 0x0
# INSTR: auipc t1, 0
# INSTR: jr t1
# FIXUP: fixup A - offset: 0, value: zero, kind:
tail f1
-# RELOC: R_RISCV_CALL f1 0x0
+# RELOC: R_RISCV_CALL_PLT f1 0x0
# INSTR: auipc t1, 0
# INSTR: jr t1
# FIXUP: fixup A - offset: 0, value: f1, kind:
tail ra
-# RELOC: R_RISCV_CALL ra 0x0
+# RELOC: R_RISCV_CALL_PLT ra 0x0
# INSTR: auipc t1, 0
# INSTR: jr t1
# FIXUP: fixup A - offset: 0, value: ra, kind: