Index: ELF/Arch/RISCV.cpp
===================================================================
--- ELF/Arch/RISCV.cpp
+++ ELF/Arch/RISCV.cpp
@@ -42,10 +42,21 @@
 template <class ELFT>
 class RISCV final : public TargetInfo {
 public:
-  RISCV() {}
+  RISCV();
   RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
                      const uint8_t *Loc) const override;
   void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+
+  virtual void writeGotPltHeader(uint8_t *Buf) const override;
+  virtual void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
+
+  virtual void writePltHeader(uint8_t *Buf) const override;
+
+  virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
+                        uint64_t PltEntryAddr, int32_t Index,
+                        unsigned RelOff) const override;
+
+  virtual bool usesOnlyLowPageBits(uint32_t Type) const override;
 };
 
 // RISC-V instructions are stored as 16-bit parcels starting with lower bits;
@@ -61,6 +72,98 @@
   return read16<E>(Buf) | static_cast<uint32_t>(read16<E>(Buf + 2)) << 16;
 }
 
+template <class ELFT>
+RISCV<ELFT>::RISCV()
+{
+  CopyRel = R_RISCV_COPY;
+  RelativeRel = R_RISCV_RELATIVE;
+  GotRel = ELFT::Is64Bits ? R_RISCV_64 : R_RISCV_32;
+  PltRel = R_RISCV_JUMP_SLOT;
+  GotEntrySize = sizeof(typename ELFT::uint);
+  GotPltEntrySize = sizeof(typename ELFT::uint);
+  PltEntrySize = 16;
+  PltHeaderSize = 32;
+  GotPltHeaderEntriesNum = 2;
+}
+
+template <class ELFT>
+bool RISCV<ELFT>::usesOnlyLowPageBits(uint32_t Type) const {
+  return Type == R_RISCV_LO12_I || Type == R_RISCV_PCREL_LO12_I
+      || Type == R_RISCV_LO12_S || Type == R_RISCV_PCREL_LO12_S
+      // These are used in a pair to calculate relative address in debug
+      // sections, so they aren't really absolute. We list those here as a hack
+      // so the linker doesn't try to create dynamic relocations.
+      || Type == R_RISCV_ADD8 || Type == R_RISCV_ADD16
+      || Type == R_RISCV_ADD32 || Type == R_RISCV_ADD64
+      || Type == R_RISCV_SUB8 || Type == R_RISCV_SUB16
+      || Type == R_RISCV_SUB32 || Type == R_RISCV_SUB64
+      || Type == R_RISCV_SUB6
+      || Type == R_RISCV_SET6 || Type == R_RISCV_SET8
+      || Type == R_RISCV_SET16 || Type == R_RISCV_SET32;
+}
+
+template <class ELFT>
+void RISCV<ELFT>::writeGotPltHeader(uint8_t *Buf) const {
+  constexpr endianness E = ELFT::TargetEndianness;
+  using uint = typename ELFT::uint;
+
+  write<uint, E>(Buf, -1);
+  write<uint, E>(Buf + 1 * sizeof(uint), 0);
+}
+
+template <class ELFT>
+void RISCV<ELFT>::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const {
+  write<typename ELFT::uint, ELFT::TargetEndianness>(Buf, InX::Plt->getVA());
+}
+
+template <class ELFT>
+void RISCV<ELFT>::writePltHeader(uint8_t *Buf) const
+{
+  constexpr endianness E = ELFT::TargetEndianness;
+  const uint64_t PcRelGotPlt = InX::GotPlt->getVA() - InX::Plt->getVA();
+
+  writeInsn32<E>(Buf +  0, 0x00000397);   // 1: auipc  t2, %pcrel_hi(.got.plt)
+  relocateOne(Buf + 0, R_RISCV_PCREL_HI20, PcRelGotPlt);
+  writeInsn32<E>(Buf +  4, 0x41c30333);   // sub    t1, t1, t3
+  if (ELFT::Is64Bits) {
+    writeInsn32<E>(Buf +  8, 0x0003be03); // ld     t3, %pcrel_lo(1b)(t2)
+  } else {
+    writeInsn32<E>(Buf +  8, 0x0003ae03); // lw     t3, %pcrel_lo(1b)(t2)
+  }
+  relocateOne(Buf + 8, R_RISCV_PCREL_LO12_I, PcRelGotPlt);
+  writeInsn32<E>(Buf + 12, 0xfd430313);   // addi   t1, t1, -44
+  writeInsn32<E>(Buf + 16, 0x00038293);   // addi   t0, t2, %pcrel_lo(1b)
+  relocateOne(Buf + 16, R_RISCV_PCREL_LO12_I, PcRelGotPlt);
+  if (ELFT::Is64Bits) {
+    writeInsn32<E>(Buf + 20, 0x00135313); // srli   t1, t1, 1
+    writeInsn32<E>(Buf + 24, 0x0082b283); // ld     t0, 8(t0)
+  } else {
+    writeInsn32<E>(Buf + 20, 0x00235313); // srli   t1, t1, 2
+    writeInsn32<E>(Buf + 24, 0x0042a283); // lw     t0, 4(t0)
+  }
+  writeInsn32<E>(Buf + 28, 0x000e0067);   // jr     t3
+}
+
+template <class ELFT>
+void RISCV<ELFT>::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
+                           uint64_t PltEntryAddr, int32_t Index,
+                           unsigned RelOff) const
+{
+  constexpr endianness E = ELFT::TargetEndianness;
+
+  writeInsn32<E>(Buf +  0, 0x00000e17);   // auipc   t3, %pcrel_hi(f@.got.plt)
+  if (ELFT::Is64Bits) {
+    writeInsn32<E>(Buf +  4, 0x000e3e03); // ld      t3, %pcrel_lo(-4)(t3)
+  } else {
+    writeInsn32<E>(Buf +  4, 0x000e2e03); // lw      t3, %pcrel_lo(-4)(t3)
+  }
+  writeInsn32<E>(Buf +  8, 0x000e0367);   // jalr    t1, t3
+  writeInsn32<E>(Buf + 12, 0x00000013);   // nop
+
+  relocateOne(Buf + 0, R_RISCV_PCREL_HI20, GotEntryAddr - PltEntryAddr);
+  relocateOne(Buf + 4, R_RISCV_PCREL_LO12_I, GotEntryAddr - PltEntryAddr);
+}
+
 template <class ELFT>
 RelExpr RISCV<ELFT>::getRelExpr(const uint32_t Type, const SymbolBody &S,
                                 const uint8_t *Loc) const {
@@ -73,11 +176,15 @@
     case R_RISCV_RVC_JUMP:
     case R_RISCV_32_PCREL:
       return R_PC;
+    case R_RISCV_CALL_PLT:
+      return R_PLT_PC;
     case R_RISCV_PCREL_LO12_I:
     case R_RISCV_PCREL_LO12_S:
       return R_RISCV_PC_INDIRECT;
-    case R_RISCV_RELAX:
+    case R_RISCV_GOT_HI20:
+      return R_GOT_PC;
     case R_RISCV_ALIGN:
+    case R_RISCV_RELAX:
       return R_HINT;
     default:
       return R_ABS;
@@ -178,6 +285,7 @@
     return;
   }
   // auipc + jalr pair
+  case R_RISCV_CALL_PLT:
   case R_RISCV_CALL: {
     checkInt<32>(Loc, static_cast<int64_t>(Val), Type);
     const uint32_t Hi = Val + 0x800;
@@ -189,6 +297,7 @@
   }
 
   case R_RISCV_PCREL_HI20:
+  case R_RISCV_GOT_HI20:
   case R_RISCV_HI20: {
     checkInt<32>(Loc, static_cast<int64_t>(Val), Type);
     const uint32_t Hi = Val + 0x800;
Index: ELF/InputSection.cpp
===================================================================
--- ELF/InputSection.cpp
+++ ELF/InputSection.cpp
@@ -576,7 +576,7 @@
     for (const Relocation& HiRel: IS->Relocations) {
       const uint64_t HiOffset = IS->getOffset(HiRel.Offset);
       const uint64_t HiAddrLoc = IS->getOutputSection()->Addr + HiOffset;
-      if (Label == HiAddrLoc && isRelExprOneOf<R_PC>(HiRel.Expr)) {
+      if (Label == HiAddrLoc && isRelExprOneOf<R_PC, R_PLT_PC, R_GOT_PC>(HiRel.Expr)) {
         return getRelocTargetVA(
           HiRel.Type, HiRel.Addend, HiAddrLoc, *HiRel.Sym, HiRel.Expr);
       }
Index: ELF/Relocations.cpp
===================================================================
--- ELF/Relocations.cpp
+++ ELF/Relocations.cpp
@@ -356,7 +356,7 @@
 // file (PC, or GOT for example).
 static bool isRelExpr(RelExpr Expr) {
   return isRelExprOneOf<R_PC, R_GOTREL, R_GOTREL_FROM_END, R_MIPS_GOTREL,
-                        R_PAGE_PC, R_RELAX_GOT_PC>(Expr);
+                        R_PAGE_PC, R_RELAX_GOT_PC, R_RISCV_PC_INDIRECT>(Expr);
 }
 
 // Returns true if a given relocation can be computed at link-time.
@@ -413,6 +413,11 @@
   if (Body.isUndefWeak())
     return true;
 
+  // __global_pointer$ is defined as absolute but will be set to .sdata + 0x800
+  // by Writer during finalization, so we white-list it here.
+  if (Config->Pie && &Body == ElfSym::RISCVGlobalPointer)
+    return true;
+
   error("relocation " + toString(Type) + " cannot refer to absolute symbol: " +
         toString(Body) + getLocation<ELFT>(S, Body, RelOff));
   return true;
Index: test/ELF/Inputs/riscv-shared.yaml
===================================================================
--- /dev/null
+++ test/ELF/Inputs/riscv-shared.yaml
@@ -0,0 +1,42 @@
+--- !ELF
+FileHeader:      
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_RISCV
+  Flags:           [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
+Sections:        
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000002
+    Content:         ''
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         2A000000
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+Symbols:         
+  Local:           
+    - Name:            .text
+      Type:            STT_SECTION
+      Section:         .text
+    - Name:            .data
+      Type:            STT_SECTION
+      Section:         .data
+    - Name:            .bss
+      Type:            STT_SECTION
+      Section:         .bss
+  Global:          
+    - Name:            f
+      Type:            STT_FUNC
+      Section:         .text
+    - Name:            x
+      Type:            STT_OBJECT
+      Section:         .data
+      Size:            0x0000000000000004
+...
Index: test/ELF/riscv-copy.test
===================================================================
--- /dev/null
+++ test/ELF/riscv-copy.test
@@ -0,0 +1,78 @@
+# .option norelax
+# .global _start
+#
+# .section .text, "ax", @progbits
+# _start:
+#     la   a0, x
+#
+# REQUIRES: riscv
+# RUN: yaml2obj %s -o %t.o
+# RUN: yaml2obj %p/Inputs/riscv-shared.yaml -o %t2.o
+# RUN: ld.lld -shared %t2.o -o %t3.so
+# RUN: ld.lld %t.o %t3.so -o %t -Tbss=0x13000 -Ttext=0x10000
+# RUN: llvm-readelf -r %t | FileCheck -check-prefix=READELF %s
+# RUN: obj2yaml %t | FileCheck %s
+#
+# READELF: Relocation section '.rela.dyn'
+# READELF: 00013000  00000104 R_RISCV_COPY           00013000   x + 0
+#
+# CHECK:     - Name:            .text
+# CHECK:       Content:         '1735000013050500'
+# CHECK:     - Name:            .bss
+#
+# 10000:       00003517                auipc   a0,0x3
+# 10004:       00050513                mv      a0,a0
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_RISCV
+  Flags:           [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000002
+    Content:         '1705000013050500'
+  - Name:            .rela.text
+    Type:            SHT_RELA
+    Flags:           [ SHF_INFO_LINK ]
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000000
+        Symbol:          x
+        Type:            R_RISCV_PCREL_HI20
+      - Offset:          0x0000000000000004
+        Symbol:          '.L0 '
+        Type:            R_RISCV_PCREL_LO12_I
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+Symbols:
+  Local:
+    - Name:            .text
+      Type:            STT_SECTION
+      Section:         .text
+    - Name:            .data
+      Type:            STT_SECTION
+      Section:         .data
+    - Name:            .bss
+      Type:            STT_SECTION
+      Section:         .bss
+    - Name:            '.L0 '
+      Section:         .text
+  Global:
+    - Name:            _start
+      Section:         .text
+    - Name:            x
+...
Index: test/ELF/riscv-fpic-got.test
===================================================================
--- /dev/null
+++ test/ELF/riscv-fpic-got.test
@@ -0,0 +1,80 @@
+# .option norelax
+# .option pic
+# .global _start
+#
+# .section .text, "ax", @progbits
+# _start:
+#     la   a0, x
+#
+# REQUIRES: riscv
+# RUN: yaml2obj %s -o %t.o
+# RUN: yaml2obj %p/Inputs/riscv-shared.yaml -o %t2.o
+# RUN: ld.lld -shared %t2.o -o %t3.so
+# RUN: ld.lld %t.o %t3.so -o %t --section-start .got=0x20000 --section-start .text=0x10000
+# RUN: llvm-readelf -r %t | FileCheck -check-prefix=READELF %s
+# RUN: obj2yaml %t | FileCheck %s
+#
+# READELF: Relocation section '.rela.dyn'
+# READELF: 00020000  00000101 R_RISCV_32             00000000   x + 0
+#
+# CHECK: - Name:            .text
+# CHECK:   Content:         '1705010003250500'
+#
+# 10000:       00010517                auipc   a0,0x10
+# 10004:       00052503                lw      a0,0(a0) # 20000 <_start+0x10000>
+#
+# CHECK: - Name:            .got
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_RISCV
+  Flags:           [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000002
+    Content:         '1705000003250500'
+  - Name:            .rela.text
+    Type:            SHT_RELA
+    Flags:           [ SHF_INFO_LINK ]
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000000
+        Symbol:          x
+        Type:            R_RISCV_GOT_HI20
+      - Offset:          0x0000000000000004
+        Symbol:          '.L0 '
+        Type:            R_RISCV_PCREL_LO12_I
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+Symbols:
+  Local:
+    - Name:            .text
+      Type:            STT_SECTION
+      Section:         .text
+    - Name:            .data
+      Type:            STT_SECTION
+      Section:         .data
+    - Name:            .bss
+      Type:            STT_SECTION
+      Section:         .bss
+    - Name:            '.L0 '
+      Section:         .text
+  Global:
+    - Name:            _start
+      Section:         .text
+    - Name:            x
+...
Index: test/ELF/riscv-fpic-pie.test
===================================================================
--- /dev/null
+++ test/ELF/riscv-fpic-pie.test
@@ -0,0 +1,77 @@
+# .option norelax
+# .option pic
+# .global _start
+#
+# .section .text, "ax", @progbits
+# _start:
+#     la   a0, _start
+#
+# REQUIRES: riscv
+# RUN: yaml2obj %s -o %t.o
+# RUN: ld.lld %t.o -o %t -pie --section-start .got=0x20000 --section-start .text=0x10000
+# RUN: llvm-readelf -r %t | FileCheck -check-prefix=READELF %s
+# RUN: obj2yaml %t | FileCheck %s
+#
+# READELF: Relocation section '.rela.dyn'
+# READELF: 00020000  00000003 R_RISCV_RELATIVE       10000
+#
+# CHECK: - Name:            .text
+# CHECK:   Content:         '1705010003250500'
+#
+# 10000:       00010517                auipc   a0,0x10
+# 10004:       00052503                lw      a0,0(a0) # 20000 <_start+0x10000>
+#
+# CHECK: - Name:            .got
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_RISCV
+  Flags:           [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000002
+    Content:         '1705000003250500'
+  - Name:            .rela.text
+    Type:            SHT_RELA
+    Flags:           [ SHF_INFO_LINK ]
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000000
+        Symbol:          _start
+        Type:            R_RISCV_GOT_HI20
+      - Offset:          0x0000000000000004
+        Symbol:          '.L0 '
+        Type:            R_RISCV_PCREL_LO12_I
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+Symbols:
+  Local:
+    - Name:            .text
+      Type:            STT_SECTION
+      Section:         .text
+    - Name:            .data
+      Type:            STT_SECTION
+      Section:         .data
+    - Name:            .bss
+      Type:            STT_SECTION
+      Section:         .bss
+    - Name:            '.L0 '
+      Section:         .text
+  Global:
+    - Name:            _start
+      Section:         .text
+...
Index: test/ELF/riscv-fpic-plt.test
===================================================================
--- /dev/null
+++ test/ELF/riscv-fpic-plt.test
@@ -0,0 +1,86 @@
+# .option norelax
+# .option pic
+# .global _start
+#
+# .section .text, "ax", @progbits
+# _start:
+#     call f@plt
+#
+# REQUIRES: riscv
+# RUN: yaml2obj %s -o %t.o
+# RUN: yaml2obj %p/Inputs/riscv-shared.yaml -o %t2.o
+# RUN: ld.lld -shared %t2.o -o %t3.so
+# RUN: ld.lld %t.o %t3.so -o %t --section-start .text=0x10000 --section-start .got.plt=0x20000 --section-start .plt=0x21000
+# RUN: llvm-readelf -r %t | FileCheck -check-prefix=READELF %s
+# RUN: obj2yaml %t | FileCheck %s
+#
+# READELF: Relocation section '.rela.plt'
+# READELF: 00020008  00000105 R_RISCV_JUMP_SLOT      00000000   f + 0
+#
+# CHECK: - Name:            .text
+# CHECK:   Content:         '97100100E7800002'
+# 10000:       00011097                auipc   ra,0x11
+# 10004:       020080e7                jalr    32(ra) # 21020 <f@plt>
+#
+# CHECK: - Name:            .got.plt
+# CHECK:   Content:         FFFFFFFF0000000000100200
+#
+# CHECK: - Name:            .plt
+# CHECK:   Content:         97F3FFFF3303C34103AE0300130343FD938203001353230083A2420067000E0017FEFFFF032E8EFE67030E0013000000
+# 21000:       fffff397                auipc   t2,0xfffff
+# 21004:       41c30333                sub     t1,t1,t3
+# 21008:       0003ae03                lw      t3,0(t2) # 20000 <_start+0x10000>
+# 2100c:       fd430313                addi    t1,t1,-44
+# 21010:       00038293                mv      t0,t2
+# 21014:       00235313                srli    t1,t1,0x2
+# 21018:       0042a283                lw      t0,4(t0)
+# 2101c:       000e0067                jr      t3
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_RISCV
+  Flags:           [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000002
+    Content:         '97000000E7800000'
+  - Name:            .rela.text
+    Type:            SHT_RELA
+    Flags:           [ SHF_INFO_LINK ]
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000000
+        Symbol:          f
+        Type:            R_RISCV_CALL_PLT
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+Symbols:
+  Local:
+    - Name:            .text
+      Type:            STT_SECTION
+      Section:         .text
+    - Name:            .data
+      Type:            STT_SECTION
+      Section:         .data
+    - Name:            .bss
+      Type:            STT_SECTION
+      Section:         .bss
+  Global:
+    - Name:            _start
+      Section:         .text
+    - Name:            f
+...