[ELF][I386] .got.plt entries for i386 should use VA of ifunc resolver

The i386 glibc ld.so expects the .got.slot entry that is relocated by a 
R_386_IRELATIVE relocation to point directly at the ifunc resolver and
not the address of the PLT entry + 6 (thus entering the lazy resolver).
This is also the case for ARM and I suspect it is because these use REL
relocations and can't use the addend field to store the address of the
ifunc resolver. If the lazy resolver is used we get an error message
stating that only R_386_JUMP_SLOT is supported.

As ARM and i386 share the same code, I've removed the ARM specific test
and added a writeIgotPlt() function that by default calls writeGotPlt().
ARM and i386 override this to write the address of the ifunc resolver.

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

llvm-svn: 289198
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index aa88736..f16853b 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -95,6 +95,7 @@
   bool isTlsGlobalDynamicRel(uint32_t Type) const override;
   bool isTlsInitialExecRel(uint32_t Type) const override;
   void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
+  void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const override;
   void writePltHeader(uint8_t *Buf) const override;
   void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
                 int32_t Index, unsigned RelOff) const override;
@@ -189,6 +190,7 @@
   bool isTlsGlobalDynamicRel(uint32_t Type) const override;
   bool isTlsInitialExecRel(uint32_t Type) const override;
   void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
+  void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const override;
   void writePltHeader(uint8_t *Buf) const override;
   void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
                 int32_t Index, unsigned RelOff) const override;
@@ -274,6 +276,10 @@
 
 bool TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const { return false; }
 
+void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
+  writeGotPlt(Buf, S);
+}
+
 RelExpr TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
                                     RelExpr Expr) const {
   return Expr;
@@ -371,6 +377,11 @@
   write32le(Buf, S.getPltVA<ELF32LE>() + 6);
 }
 
+void X86TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
+  // An x86 entry is the address of the ifunc resolver function.
+  write32le(Buf, S.getVA<ELF32LE>());
+}
+
 uint32_t X86TargetInfo::getDynRel(uint32_t Type) const {
   if (Type == R_386_TLS_LE)
     return R_386_TLS_TPOFF;
@@ -1649,6 +1660,11 @@
   write32le(Buf, In<ELF32LE>::Plt->getVA());
 }
 
+void ARMTargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
+  // An ARM entry is the address of the ifunc resolver function.
+  write32le(Buf, S.getVA<ELF32LE>());
+}
+
 void ARMTargetInfo::writePltHeader(uint8_t *Buf) const {
   const uint8_t PltData[] = {
       0x04, 0xe0, 0x2d, 0xe5, //     str lr, [sp,#-4]!