Add support for relocating R_X86_64_GOTPCREL.

llvm-svn: 248425
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index e8fa4a6..2b57e5f 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -50,6 +50,7 @@
       const SymbolBody *Body = File.getSymbolBody(SymIndex);
       if (!Body)
         continue;
+      uint32_t OrigType = Type;
       switch (Body->kind()) {
       case SymbolBody::DefinedRegularKind:
         SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));
@@ -63,15 +64,12 @@
         break;
       }
       case SymbolBody::SharedKind:
-        if (Target->relocNeedsPlt(Type)) {
-          SymVA = PltSec.getEntryAddr(*Body);
+        if (Target->relocNeedsPlt(Type))
           Type = Target->getPCRelReloc();
-        } else if (Target->relocNeedsGot(Type)) {
-          SymVA = GotSec.getEntryAddr(*Body);
+        else if (Target->relocNeedsGot(Type))
           Type = Target->getPCRelReloc();
-        } else {
+        else
           continue;
-        }
         break;
       case SymbolBody::UndefinedKind:
         assert(Body->isWeak() && "Undefined symbol reached writer");
@@ -80,6 +78,11 @@
       case SymbolBody::LazyKind:
         llvm_unreachable("Lazy symbol reached writer");
       }
+
+      if (Target->relocNeedsPlt(OrigType))
+        SymVA = PltSec.getEntryAddr(*Body);
+      else if (Target->relocNeedsGot(OrigType))
+        SymVA = GotSec.getEntryAddr(*Body);
     }
 
     Target->relocateOne(Buf, reinterpret_cast<const void *>(&RI), Type,
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index ff0ccc4..ea20ced 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -137,6 +137,7 @@
   uint8_t *Location = Buf + Offset;
   switch (Type) {
   case R_X86_64_PC32:
+  case R_X86_64_GOTPCREL:
     support::endian::write32le(Location,
                                SymVA + Rel.r_addend - (BaseAddr + Offset));
     break;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index c8985aa..5946958 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -255,9 +255,6 @@
     SymbolBody *Body = File.getSymbolBody(SymIndex);
     if (!Body)
       continue;
-    auto *S = dyn_cast<SharedSymbol<ELFT>>(Body);
-    if (!S)
-      continue;
     uint32_t Type = RI.getType(IsMips64EL);
     if (Target->relocNeedsPlt(Type)) {
       if (Body->isInPlt())
@@ -269,7 +266,9 @@
         continue;
       GotSec.addEntry(Body);
     }
-    S->setUsedInDynamicReloc();
+    if (!isa<SharedSymbol<ELFT>>(Body))
+      continue;
+    Body->setUsedInDynamicReloc();
     RelaDynSec.addReloc({C, RI});
   }
 }
@@ -395,11 +394,11 @@
     OutputSections.push_back(&DynStrSec);
     if (RelaDynSec.hasRelocs())
       OutputSections.push_back(&RelaDynSec);
-    if (!GotSec.empty())
-      OutputSections.push_back(&GotSec);
-    if (!PltSec.empty())
-      OutputSections.push_back(&PltSec);
   }
+  if (!GotSec.empty())
+    OutputSections.push_back(&GotSec);
+  if (!PltSec.empty())
+    OutputSections.push_back(&PltSec);
 
   std::stable_sort(OutputSections.begin(), OutputSections.end(),
                    compSec<ELFT::Is64Bits>);
diff --git a/lld/test/elf2/relocation.s b/lld/test/elf2/relocation.s
index 5e6b407..5c60fa2 100644
--- a/lld/test/elf2/relocation.s
+++ b/lld/test/elf2/relocation.s
@@ -1,8 +1,23 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
 // RUN: lld -flavor gnu2 %t -o %t2
+// RUN: llvm-readobj -s  %t2 | FileCheck --check-prefix=SEC %s
 // RUN: llvm-objdump -s -d %t2 | FileCheck %s
 // REQUIRES: x86
 
+// SEC:         Name: .got
+// SEC-NEXT:   Type: SHT_PROGBITS
+// SEC-NEXT:   Flags [
+// SEC-NEXT:     SHF_ALLOC
+// SEC-NEXT:     SHF_WRITE
+// SEC-NEXT:   ]
+// SEC-NEXT:   Address: 0x13000
+// SEC-NEXT:   Offset:
+// SEC-NEXT:   Size: 8
+// SEC-NEXT:   Link: 0
+// SEC-NEXT:   Info: 0
+// SEC-NEXT:   AddressAlignment: 8
+// SEC-NEXT:   EntrySize: 0
+// SEC-NEXT: }
 
 .section       .text,"ax",@progbits,unique,1
 .global _start
@@ -51,3 +66,13 @@
 
 // CHECK:      Contents of section .R_X86_64_64:
 // CHECK-NEXT:   12000 00200100 00000000
+
+.section .R_X86_64_GOTPCREL,"a",@progbits
+.global R_X86_64_GOTPCREL
+R_X86_64_GOTPCREL:
+ .long R_X86_64_GOTPCREL@gotpcrel
+
+// 0x13000 - 0x12008 = 4088
+// 4088 = 0xf80f0000 in little endian
+// CHECK:      Contents of section .R_X86_64_GOTPCREL
+// CHECK-NEXT:   12008 f80f0000