[lld] r364812 - [ELF][RISCV] Support PLT, GOT, copy and relative relocations

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 1 10:12:18 PDT 2019


Author: maskray
Date: Mon Jul  1 10:12:18 2019
New Revision: 364812

URL: http://llvm.org/viewvc/llvm-project?rev=364812&view=rev
Log:
[ELF][RISCV] Support PLT, GOT, copy and relative relocations

* Handle initial relocation types: R_RISCV_CALL_PLT and R_RISCV_GOT_HI20.
* Produce dynamic relocation types: R_RISCV_COPY, R_RISCV_RELATIVE, R_RISCV_JUMP_SLOT.
* Define SymbolRel as R_RISCV_{32,64}
* Generate PLT header: it is used by lazy binding PLT in glibc.
* R_RISCV_CALL is changed from R_PC to R_PC_PLT. If the target symbol is preemptable, this will suppress an unnecessary "canonical PLT".
  This behavior is different from ld.bfd but it is agreed the current lld behavior is favored.
  I have received positive responses from the binutils maintainer that the ABI/binutils implementation can be improved, see:
  https://github.com/riscv/riscv-elf-psabi-doc/issues/98
  https://sourceware.org/bugzilla/show_bug.cgi?id=24685

Many -no-pie/-pie/-shared programs linked against musl or glibc should work with this patch.

Reviewed By: jrtc27

Differential Revision: https://reviews.llvm.org/D63076

Added:
    lld/trunk/test/ELF/riscv-plt.s
    lld/trunk/test/ELF/riscv-reloc-64-pic.s
    lld/trunk/test/ELF/riscv-reloc-copy.s
    lld/trunk/test/ELF/riscv-reloc-got.s
    lld/trunk/test/ELF/riscv32-reloc-32-pic.s
    lld/trunk/test/ELF/riscv64-reloc-64-pic.s
Modified:
    lld/trunk/ELF/Arch/RISCV.cpp
    lld/trunk/ELF/InputSection.cpp

Modified: lld/trunk/ELF/Arch/RISCV.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/RISCV.cpp?rev=364812&r1=364811&r2=364812&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/RISCV.cpp (original)
+++ lld/trunk/ELF/Arch/RISCV.cpp Mon Jul  1 10:12:18 2019
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "InputFiles.h"
+#include "SyntheticSections.h"
 #include "Target.h"
 
 using namespace llvm;
@@ -22,6 +23,12 @@ class RISCV final : public TargetInfo {
 public:
   RISCV();
   uint32_t calcEFlags() const override;
+  void writeGotHeader(uint8_t *Buf) const override;
+  void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;
+  void writePltHeader(uint8_t *Buf) const override;
+  void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
+                int32_t Index, unsigned RelOff) const override;
+  RelType getDynRel(RelType Type) const override;
   RelExpr getRelExpr(RelType Type, const Symbol &S,
                      const uint8_t *Loc) const override;
   void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
@@ -29,7 +36,55 @@ public:
 
 } // end anonymous namespace
 
-RISCV::RISCV() { NoneRel = R_RISCV_NONE; }
+enum Op {
+  ADDI = 0x13,
+  AUIPC = 0x17,
+  JALR = 0x67,
+  LD = 0x3003,
+  LW = 0x2003,
+  SRLI = 0x5013,
+  SUB = 0x40000033,
+};
+
+enum Reg {
+  X_RA = 1,
+  X_T0 = 5,
+  X_T1 = 6,
+  X_T2 = 7,
+  X_T3 = 28,
+};
+
+static uint32_t hi20(uint32_t Val) { return (Val + 0x800) >> 12; }
+static uint32_t lo12(uint32_t Val) { return Val & 4095; }
+
+static uint32_t itype(uint32_t Op, uint32_t Rd, uint32_t Rs1, uint32_t Imm) {
+  return Op | (Rd << 7) | (Rs1 << 15) | (Imm << 20);
+}
+static uint32_t rtype(uint32_t Op, uint32_t Rd, uint32_t Rs1, uint32_t Rs2) {
+  return Op | (Rd << 7) | (Rs1 << 15) | (Rs2 << 20);
+}
+static uint32_t utype(uint32_t Op, uint32_t Rd, uint32_t Imm) {
+  return Op | (Rd << 7) | (Imm << 12);
+}
+
+RISCV::RISCV() {
+  CopyRel = R_RISCV_COPY;
+  NoneRel = R_RISCV_NONE;
+  PltRel = R_RISCV_JUMP_SLOT;
+  RelativeRel = R_RISCV_RELATIVE;
+  SymbolicRel = Config->Is64 ? R_RISCV_64 : R_RISCV_32;
+  GotRel = SymbolicRel;
+
+  // .got[0] = _DYNAMIC
+  GotBaseSymInGotPlt = false;
+  GotHeaderEntriesNum = 1;
+
+  // .got.plt[0] = _dl_runtime_resolve, .got.plt[1] = link_map
+  GotPltHeaderEntriesNum = 2;
+
+  PltEntrySize = 16;
+  PltHeaderSize = 32;
+}
 
 static uint32_t getEFlags(InputFile *F) {
   if (Config->Is64)
@@ -59,6 +114,59 @@ uint32_t RISCV::calcEFlags() const {
   return Target;
 }
 
+void RISCV::writeGotHeader(uint8_t *Buf) const {
+  if (Config->Is64)
+    write64le(Buf, Main->Dynamic->getVA());
+  else
+    write32le(Buf, Main->Dynamic->getVA());
+}
+
+void RISCV::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
+  if (Config->Is64)
+    write64le(Buf, In.Plt->getVA());
+  else
+    write32le(Buf, In.Plt->getVA());
+}
+
+void RISCV::writePltHeader(uint8_t *Buf) const {
+  // 1: auipc t2, %pcrel_hi(.got.plt)
+  // sub t1, t1, t3
+  // l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve
+  // addi t1, t1, -PltHeaderSize-12; t1 = &.plt[i] - &.plt[0]
+  // addi t0, t2, %pcrel_lo(1b)
+  // srli t1, t1, (rv64?1:2); t1 = &.got.plt[i] - &.got.plt[0]
+  // l[wd] t0, Wordsize(t0); t0 = link_map
+  // jr t3
+  uint32_t Offset = In.GotPlt->getVA() - In.Plt->getVA();
+  uint32_t Load = Config->Is64 ? LD : LW;
+  write32le(Buf + 0, utype(AUIPC, X_T2, hi20(Offset)));
+  write32le(Buf + 4, rtype(SUB, X_T1, X_T1, X_T3));
+  write32le(Buf + 8, itype(Load, X_T3, X_T2, lo12(Offset)));
+  write32le(Buf + 12, itype(ADDI, X_T1, X_T1, -Target->PltHeaderSize - 12));
+  write32le(Buf + 16, itype(ADDI, X_T0, X_T2, lo12(Offset)));
+  write32le(Buf + 20, itype(SRLI, X_T1, X_T1, Config->Is64 ? 1 : 2));
+  write32le(Buf + 24, itype(Load, X_T0, X_T0, Config->Wordsize));
+  write32le(Buf + 28, itype(JALR, 0, X_T3, 0));
+}
+
+void RISCV::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
+                     uint64_t PltEntryAddr, int32_t Index,
+                     unsigned RelOff) const {
+  // 1: auipc t3, %pcrel_hi(f at .got.plt)
+  // l[wd] t3, %pcrel_lo(1b)(t3)
+  // jalr t1, t3
+  // nop
+  uint32_t Offset = GotPltEntryAddr - PltEntryAddr;
+  write32le(Buf + 0, utype(AUIPC, X_T3, hi20(Offset)));
+  write32le(Buf + 4, itype(Config->Is64 ? LD : LW, X_T3, X_T3, lo12(Offset)));
+  write32le(Buf + 8, itype(JALR, X_T1, X_T3, 0));
+  write32le(Buf + 12, itype(ADDI, 0, 0, 0));
+}
+
+RelType RISCV::getDynRel(RelType Type) const {
+  return Type == Target->SymbolicRel ? Type : R_RISCV_NONE;
+}
+
 RelExpr RISCV::getRelExpr(const RelType Type, const Symbol &S,
                           const uint8_t *Loc) const {
   switch (Type) {
@@ -78,12 +186,16 @@ RelExpr RISCV::getRelExpr(const RelType
     return R_RISCV_ADD;
   case R_RISCV_JAL:
   case R_RISCV_BRANCH:
-  case R_RISCV_CALL:
   case R_RISCV_PCREL_HI20:
   case R_RISCV_RVC_BRANCH:
   case R_RISCV_RVC_JUMP:
   case R_RISCV_32_PCREL:
     return R_PC;
+  case R_RISCV_CALL:
+  case R_RISCV_CALL_PLT:
+    return R_PLT_PC;
+  case R_RISCV_GOT_HI20:
+    return R_GOT_PC;
   case R_RISCV_PCREL_LO12_I:
   case R_RISCV_PCREL_LO12_S:
     return R_RISCV_PC_INDIRECT;
@@ -189,7 +301,8 @@ void RISCV::relocateOne(uint8_t *Loc, co
   }
 
   // auipc + jalr pair
-  case R_RISCV_CALL: {
+  case R_RISCV_CALL:
+  case R_RISCV_CALL_PLT: {
     int64_t Hi = SignExtend64(Val + 0x800, Bits) >> 12;
     checkInt(Loc, Hi, 20, Type);
     if (isInt<20>(Hi)) {
@@ -199,6 +312,7 @@ void RISCV::relocateOne(uint8_t *Loc, co
     return;
   }
 
+  case R_RISCV_GOT_HI20:
   case R_RISCV_PCREL_HI20:
   case R_RISCV_HI20: {
     uint64_t Hi = Val + 0x800;

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=364812&r1=364811&r2=364812&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Mon Jul  1 10:12:18 2019
@@ -587,7 +587,7 @@ static Relocation *getRISCVPCRelHi20(con
                        });
 
   for (auto It = Range.first; It != Range.second; ++It)
-    if (It->Expr == R_PC)
+    if (It->Type == R_RISCV_PCREL_HI20 || It->Type == R_RISCV_GOT_HI20)
       return &*It;
 
   error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) +

Added: lld/trunk/test/ELF/riscv-plt.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/riscv-plt.s?rev=364812&view=auto
==============================================================================
--- lld/trunk/test/ELF/riscv-plt.s (added)
+++ lld/trunk/test/ELF/riscv-plt.s Mon Jul  1 10:12:18 2019
@@ -0,0 +1,103 @@
+# REQUIRES: riscv
+# RUN: echo '.globl bar, weak; .type bar, at function; .type weak, at function; bar: weak:' > %t1.s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 %t1.s -o %t1.32.o
+# RUN: ld.lld -shared %t1.32.o -o %t1.32.so
+# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32.o
+# RUN: ld.lld %t.32.o %t1.32.so -o %t.32
+# RUN: llvm-readelf -S -s %t.32 | FileCheck --check-prefixes=SEC,NM %s
+# RUN: llvm-readobj -r %t.32 | FileCheck --check-prefix=RELOC32 %s
+# RUN: llvm-readelf -x .got.plt %t.32 | FileCheck --check-prefix=GOTPLT32 %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=DIS,DIS32 %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %t1.s -o %t1.64.o
+# RUN: ld.lld -shared %t1.64.o -o %t1.64.so
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
+# RUN: ld.lld %t.64.o %t1.64.so -o %t.64
+# RUN: llvm-readelf -S -s %t.64 | FileCheck --check-prefixes=SEC,NM %s
+# RUN: llvm-readobj -r %t.64 | FileCheck --check-prefix=RELOC64 %s
+# RUN: llvm-readelf -x .got.plt %t.64 | FileCheck --check-prefix=GOTPLT64 %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=DIS,DIS64 %s
+
+# SEC: .plt PROGBITS {{0*}}00011030
+
+## A canonical PLT has a non-zero st_value. bar and weak are called but their
+## addresses are not taken, so a canonical PLT is not necessary.
+# NM: {{0*}}00000000 0 FUNC GLOBAL DEFAULT UND bar
+# NM: {{0*}}00000000 0 FUNC WEAK   DEFAULT UND weak
+
+## The .got.plt slots relocated by .rela.plt point to .plt
+## This is required by glibc.
+# RELOC32:      .rela.plt {
+# RELOC32-NEXT:   0x13008 R_RISCV_JUMP_SLOT bar 0x0
+# RELOC32-NEXT:   0x1300C R_RISCV_JUMP_SLOT weak 0x0
+# RELOC32-NEXT: }
+# GOTPLT32:      section '.got.plt'
+# GOTPLT32-NEXT: 0x00013000 00000000 00000000 30100100 30100100
+
+# RELOC64:      .rela.plt {
+# RELOC64-NEXT:   0x13010 R_RISCV_JUMP_SLOT bar 0x0
+# RELOC64-NEXT:   0x13018 R_RISCV_JUMP_SLOT weak 0x0
+# RELOC64-NEXT: }
+# GOTPLT64:      section '.got.plt'
+# GOTPLT64-NEXT: 0x00013000 00000000 00000000 00000000 00000000
+# GOTPLT64-NEXT: 0x00013010 30100100 00000000 30100100 00000000
+
+# DIS:      _start:
+## Direct call
+## foo - . = 0x11020-0x11000 = 32
+# DIS-NEXT:          auipc ra, 0
+# DIS-NEXT:   11004: jalr ra, ra, 32
+## bar at plt - . = 0x11050-0x1100c = 72
+# DIS-NEXT:          auipc ra, 0
+# DIS-NEXT:   1100c: jalr ra, ra, 72
+## bar at plt - . = 0x11050-0x11014 = 64
+# DIS-NEXT:          auipc ra, 0
+# DIS-NEXT:   11014: jalr ra, ra, 64
+## weak at plt - . = 0x11060-0x1101c = 72
+# DIS-NEXT:          auipc ra, 0
+# DIS-NEXT:   1101c: jalr ra, ra, 72
+# DIS:      foo:
+# DIS-NEXT:   11020:
+
+# DIS:      Disassembly of section .plt:
+# DIS:      .plt:
+# DIS-NEXT:     auipc t2, 2
+# DIS-NEXT:     sub t1, t1, t3
+## .got.plt - .plt = 0x13000 - 0x11030 = 4096*2-48
+# DIS32-NEXT:   lw t3, -48(t2)
+# DIS64-NEXT:   ld t3, -48(t2)
+# DIS-NEXT:     addi t1, t1, -44
+# DIS-NEXT:     addi t0, t2, -48
+# DIS32-NEXT:   srli t1, t1, 2
+# DIS64-NEXT:   srli t1, t1, 1
+# DIS32-NEXT:   lw t0, 4(t0)
+# DIS64-NEXT:   ld t0, 8(t0)
+# DIS-NEXT:     jr t3
+
+## 32-bit: &.got.plt[bar]-. = 0x13008-0x11050 = 4096*2-72
+# DIS:        11050: auipc t3, 2
+# DIS32-NEXT:   lw t3, -72(t3)
+# DIS64-NEXT:   ld t3, -64(t3)
+# DIS-NEXT:     jalr t1, t3, 0
+# DIS-NEXT:     nop
+
+## 32-bit: &.got.plt[weak]-. = 0x1300c-0x11060 = 4096*2-84
+# DIS:        11060: auipc t3, 2
+# DIS32-NEXT:   lw t3, -84(t3)
+# DIS64-NEXT:   ld t3, -72(t3)
+# DIS-NEXT:     jalr t1, t3, 0
+# DIS-NEXT:     nop
+
+.global _start, foo, bar
+.weak weak
+
+_start:
+  call foo
+  call bar
+  call bar at plt
+  call weak
+
+## foo is local and non-preemptale, no PLT is generated.
+foo:
+  ret

Added: lld/trunk/test/ELF/riscv-reloc-64-pic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/riscv-reloc-64-pic.s?rev=364812&view=auto
==============================================================================
--- lld/trunk/test/ELF/riscv-reloc-64-pic.s (added)
+++ lld/trunk/test/ELF/riscv-reloc-64-pic.s Mon Jul  1 10:12:18 2019
@@ -0,0 +1,10 @@
+# REQUIRES: riscv
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.o
+# RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
+
+# CHECK: error: relocation R_RISCV_32 cannot be used against symbol a
+
+.globl a
+
+.data
+.long a

Added: lld/trunk/test/ELF/riscv-reloc-copy.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/riscv-reloc-copy.s?rev=364812&view=auto
==============================================================================
--- lld/trunk/test/ELF/riscv-reloc-copy.s (added)
+++ lld/trunk/test/ELF/riscv-reloc-copy.s Mon Jul  1 10:12:18 2019
@@ -0,0 +1,23 @@
+# REQUIRES: riscv
+# RUN: llvm-mc -filetype=obj -triple=riscv32 %p/Inputs/relocation-copy.s -o %t1.o
+# RUN: ld.lld -shared %t1.o -o %t1.so
+# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.o
+# RUN: ld.lld %t.o %t1.so -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-nm -S %t | FileCheck --check-prefix=NM32 %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %p/Inputs/relocation-copy.s -o %t1.o
+# RUN: ld.lld -shared %t1.o -o %t1.so
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.o
+# RUN: ld.lld %t.o %t1.so -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-nm -S %t | FileCheck --check-prefix=NM64 %s
+
+# RELOC:      .rela.dyn {
+# RELOC-NEXT:   0x13000 R_RISCV_COPY x 0x0
+# RELOC-NEXT: }
+
+# NM32: 00013000 00000004 B x
+# NM64: 0000000000013000 0000000000000004 B x
+
+la a0, x

Added: lld/trunk/test/ELF/riscv-reloc-got.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/riscv-reloc-got.s?rev=364812&view=auto
==============================================================================
--- lld/trunk/test/ELF/riscv-reloc-got.s (added)
+++ lld/trunk/test/ELF/riscv-reloc-got.s Mon Jul  1 10:12:18 2019
@@ -0,0 +1,65 @@
+# REQUIRES: riscv
+# RUN: echo '.globl b; b:' | llvm-mc -filetype=obj -triple=riscv32 - -o %t1.o
+# RUN: ld.lld -shared %t1.o -o %t1.so
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -position-independent %s -o %t.o
+# RUN: ld.lld %t.o %t1.so -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC32 %s
+# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
+# RUN: llvm-readobj -x .got %t | FileCheck --check-prefix=HEX32 %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=DIS32 %s
+
+# RUN: echo '.globl b; b:' | llvm-mc -filetype=obj -triple=riscv64 - -o %t1.o
+# RUN: ld.lld -shared %t1.o -o %t1.so
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -position-independent %s -o %t.o
+# RUN: ld.lld %t.o %t1.so -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC64 %s
+# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
+# RUN: llvm-readobj -x .got %t | FileCheck --check-prefix=HEX64 %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=DIS64 %s
+
+# SEC: .got PROGBITS 00012060 020060 00000c
+
+# RELOC32:      .rela.dyn {
+# RELOC32-NEXT:   0x12068 R_RISCV_32 b 0x0
+# RELOC32-NEXT: }
+
+# RELOC64:      .rela.dyn {
+# RELOC64-NEXT:   0x120D0 R_RISCV_64 b 0x0
+# RELOC64-NEXT: }
+
+# NM: 00013000 d a
+
+## .got[0] = _DYNAMIC
+## .got[1] = a (filled at link time)
+## .got[2] = 0 (relocated by R_RISCV_64 at runtime)
+# HEX32: section '.got':
+# HEX32: 0x00012060 00200100 00300100 00000000
+
+# HEX64: section '.got':
+# HEX64: 0x000120c0 00200100 00000000 00300100 00000000
+# HEX64: 0x000120d0 00000000 00000000
+
+## &.got[1]-. = 0x12060-0x11000 = 4096*1+100
+# DIS32:      11000: auipc a0, 1
+# DIS32-NEXT:        lw a0, 100(a0)
+## &.got[2]-. = 0x12064-0x11008 = 4096*1+96
+# DIS32:      11008: auipc a0, 1
+# DIS32-NEXT:        lw a0, 96(a0)
+
+## &.got[1]-. = 0x120c8-0x11000 = 4096*1+100
+# DIS64:      11000: auipc a0, 1
+# DIS64-NEXT:        ld a0, 200(a0)
+## &.got[2]-. = 0x120d0-0x11008 = 4096*1+200
+# DIS64:      11008: auipc a0, 1
+# DIS64-NEXT:        ld a0, 200(a0)
+
+la a0,a
+la a0,b
+
+.data
+a:
+## An undefined reference of _GLOBAL_OFFSET_TABLE_ causes .got[0] to be
+## allocated to store _DYNAMIC.
+.long _GLOBAL_OFFSET_TABLE_ - .

Added: lld/trunk/test/ELF/riscv32-reloc-32-pic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/riscv32-reloc-32-pic.s?rev=364812&view=auto
==============================================================================
--- lld/trunk/test/ELF/riscv32-reloc-32-pic.s (added)
+++ lld/trunk/test/ELF/riscv32-reloc-32-pic.s Mon Jul  1 10:12:18 2019
@@ -0,0 +1,23 @@
+# REQUIRES: riscv
+# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t.so
+# RUN: llvm-nm %t.so | FileCheck --check-prefix=NM %s
+# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOC %s
+
+## R_RISCV_32 is an absolute relocation type.
+## In PIC mode, it creates a relative relocation if the symbol is non-preemptable.
+
+# NM: 00002004 d b
+
+# RELOC:      .rela.dyn {
+# RELOC-NEXT:   0x2004 R_RISCV_RELATIVE - 0x2004
+# RELOC-NEXT:   0x2000 R_RISCV_32 a 0
+# RELOC-NEXT: }
+
+.globl a, b
+.hidden b
+
+.data
+.long a
+b:
+.long b

Added: lld/trunk/test/ELF/riscv64-reloc-64-pic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/riscv64-reloc-64-pic.s?rev=364812&view=auto
==============================================================================
--- lld/trunk/test/ELF/riscv64-reloc-64-pic.s (added)
+++ lld/trunk/test/ELF/riscv64-reloc-64-pic.s Mon Jul  1 10:12:18 2019
@@ -0,0 +1,23 @@
+# REQUIRES: riscv
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t.so
+# RUN: llvm-nm %t.so | FileCheck --check-prefix=NM %s
+# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOC %s
+
+## R_RISCV_64 is an absolute relocation type.
+## In PIC mode, it creates a relative relocation if the symbol is non-preemptable.
+
+# NM: 0000000000002008 d b
+
+# RELOC:      .rela.dyn {
+# RELOC-NEXT:   0x2008 R_RISCV_RELATIVE - 0x2008
+# RELOC-NEXT:   0x2000 R_RISCV_64 a 0
+# RELOC-NEXT: }
+
+.globl a, b
+.hidden b
+
+.data
+.quad a
+b:
+.quad b




More information about the llvm-commits mailing list