diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index 1d3d179e5d6fb..62498ded1a2b1 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -290,6 +290,7 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s, case R_RISCV_PLT32: return R_PLT_PC; case R_RISCV_GOT_HI20: + case R_RISCV_GOT32_PCREL: return R_GOT_PC; case R_RISCV_PCREL_LO12_I: case R_RISCV_PCREL_LO12_S: @@ -499,6 +500,8 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { case R_RISCV_SET32: case R_RISCV_32_PCREL: case R_RISCV_PLT32: + case R_RISCV_GOT32_PCREL: + checkInt(loc, val, 32, rel); write32le(loc, val); return; diff --git a/lld/test/ELF/riscv64-reloc-got32-pcrel.s b/lld/test/ELF/riscv64-reloc-got32-pcrel.s new file mode 100644 index 0000000000000..24bd828235b25 --- /dev/null +++ b/lld/test/ELF/riscv64-reloc-got32-pcrel.s @@ -0,0 +1,27 @@ +// REQUIRES: riscv +// RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.o +// RUN: ld.lld %t.o -o %t.so -shared --noinhibit-exec 2>&1 | FileCheck %s --check-prefix=WARN +// RUN: llvm-readelf -S %t.so | FileCheck --check-prefix=SEC %s +// RUN: llvm-objdump --no-print-imm-hex -s -d %t.so | FileCheck %s + +// SEC: .got PROGBITS 0000000000002390 + + .section .data + .globl bar +bar: + + .globl _start +_start: // PC = 0x33a8 +// bar@GOTPCREL = 0x2398 (got entry for `bar`) - 0x33a8 (.) = 0xf0efffff +// bar@GOTPCREL+4 = 0x2398 (got entry for `bar`) - 0x33ac (.) + 4 = 0xf0efffff +// bar@GOTPCREL-4 = 0x2398 (got entry for `bar`) - 0x33b0 (.) - 4 = 0xe4efffff +// CHECK: Contents of section .data: +// CHECK-NEXT: {{.*}} f0efffff f0efffff e4efffff + .word bar@GOTPCREL + .word bar@GOTPCREL+4 + .word bar@GOTPCREL-4 + +// WARN: relocation R_RISCV_GOT32_PCREL out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz' +// WARN: relocation R_RISCV_GOT32_PCREL out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz' + .word baz@GOTPCREL+0xffffffff + .word baz@GOTPCREL-0xffffffff diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def index c7fd6490041cd..b478799c91fb2 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def @@ -40,8 +40,7 @@ ELF_RELOC(R_RISCV_SUB8, 37) ELF_RELOC(R_RISCV_SUB16, 38) ELF_RELOC(R_RISCV_SUB32, 39) ELF_RELOC(R_RISCV_SUB64, 40) -ELF_RELOC(R_RISCV_GNU_VTINHERIT, 41) -ELF_RELOC(R_RISCV_GNU_VTENTRY, 42) +ELF_RELOC(R_RISCV_GOT32_PCREL, 41) ELF_RELOC(R_RISCV_ALIGN, 43) ELF_RELOC(R_RISCV_RVC_BRANCH, 44) ELF_RELOC(R_RISCV_RVC_JUMP, 45) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp index 0799267eaf7c7..76e5b3ed40254 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp @@ -106,6 +106,8 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx, if (Expr->getKind() == MCExpr::Target && cast(Expr)->getKind() == RISCVMCExpr::VK_RISCV_32_PCREL) return ELF::R_RISCV_32_PCREL; + if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOTPCREL) + return ELF::R_RISCV_GOT32_PCREL; return ELF::R_RISCV_32; case FK_Data_8: return ELF::R_RISCV_64; diff --git a/llvm/test/MC/RISCV/elf-reloc-got32-pcrel.s b/llvm/test/MC/RISCV/elf-reloc-got32-pcrel.s new file mode 100644 index 0000000000000..32a1d57fb5360 --- /dev/null +++ b/llvm/test/MC/RISCV/elf-reloc-got32-pcrel.s @@ -0,0 +1,14 @@ +// RUN: llvm-mc -triple=riscv64 -filetype=obj %s -o - | \ +// RUN: llvm-readobj -r - | FileCheck %s + + .section .data +this: + .word this@GOTPCREL + .word extern_sym@GOTPCREL+4 + .word negative_offset@GOTPCREL-4 + +// CHECK: Section ({{.*}}) .rela.data +// CHECK-NEXT: 0x0 R_RISCV_GOT32_PCREL this 0x0 +// CHECK-NEXT: 0x4 R_RISCV_GOT32_PCREL extern_sym 0x4 +// CHECK-NEXT: 0x8 R_RISCV_GOT32_PCREL negative_offset 0xFFFFFFFFFFFFFFFC +// CHECK-NEXT: }