[lld] r248854 - Start adding support for static programs using dynamic libraries.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 16:22:16 PDT 2015


Author: rafael
Date: Tue Sep 29 18:22:16 2015
New Revision: 248854

URL: http://llvm.org/viewvc/llvm-project?rev=248854&view=rev
Log:
Start adding support for static programs using dynamic libraries.

This is just enough for a hello world using a dynamic glibc.

Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/elf2/relocation.s

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue Sep 29 18:22:16 2015
@@ -52,10 +52,10 @@ void InputSection<ELFT>::relocate(
       const auto &Body =
           *cast<ELFSymbolBody<ELFT>>(File.getSymbolBody(SymIndex));
       SymVA = getSymVA<ELFT>(Body, BssSec);
-      if (Target->relocNeedsPlt(Type)) {
+      if (Target->relocNeedsPlt(Type, Body)) {
         SymVA = PltSec.getEntryAddr(Body);
         Type = Target->getPCRelReloc();
-      } else if (Target->relocNeedsGot(Type)) {
+      } else if (Target->relocNeedsGot(Type, Body)) {
         SymVA = GotSec.getEntryAddr(Body);
         Type = Target->getGotRefReloc();
       } else if (Target->relocPointsToGot(Type)) {

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue Sep 29 18:22:16 2015
@@ -104,7 +104,7 @@ template <class ELFT> void RelocationSec
     uint32_t SymIndex = RI.getSymbol(IsMips64EL);
     const SymbolBody *Body = C.getFile()->getSymbolBody(SymIndex);
     uint32_t Type = RI.getType(IsMips64EL);
-    if (Target->relocNeedsGot(Type)) {
+    if (Target->relocNeedsGot(Type, *Body)) {
       P->r_offset = GotSec.getEntryAddr(*Body);
       P->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
                           Target->getGotReloc(), IsMips64EL);

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Tue Sep 29 18:22:16 2015
@@ -9,6 +9,7 @@
 
 #include "Target.h"
 #include "Error.h"
+#include "Symbols.h"
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Object/ELF.h"
@@ -44,8 +45,8 @@ void X86TargetInfo::writePltEntry(uint8_
   write32le(Buf + 2, GotEntryAddr);
 }
 
-bool X86TargetInfo::relocNeedsGot(uint32_t Type) const {
-  if (relocNeedsPlt(Type))
+bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+  if (relocNeedsPlt(Type, S))
     return true;
   switch (Type) {
   default:
@@ -59,7 +60,7 @@ bool X86TargetInfo::relocPointsToGot(uin
   return Type == R_386_GOTPC;
 }
 
-bool X86TargetInfo::relocNeedsPlt(uint32_t Type) const {
+bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
   switch (Type) {
   default:
     return false;
@@ -112,8 +113,8 @@ void X86_64TargetInfo::writePltEntry(uin
   write32le(Buf + 2, Delta);
 }
 
-bool X86_64TargetInfo::relocNeedsGot(uint32_t Type) const {
-  if (relocNeedsPlt(Type))
+bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+  if (relocNeedsPlt(Type, S))
     return true;
   switch (Type) {
   default:
@@ -123,10 +124,28 @@ bool X86_64TargetInfo::relocNeedsGot(uin
   }
 }
 
-bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type) const {
+bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
   switch (Type) {
   default:
     return false;
+  case R_X86_64_PC32:
+    // This relocation is defined to have a value of (S + A - P).
+    // The problems start when a non PIC program calls a function is a shared
+    // library.
+    // In an idea world, we could just report an error saying the relocation
+    // can overflow at runtime.
+    // In the real world, crt1.o has a R_X86_64_PC32 pointing to libc.so.
+    // The general idea is to create a PLT entry and use that as the function
+    // value, which is why we return true in here.
+    // The remaining (unimplemented) problem is making sure pointer equality
+    // still works. For that, we need the help of the dynamic linker. We
+    // let it know that we have a direct reference to a symbol by creating
+    // an undefined symbol with a non zero st_value. Seeing that the
+    // dynamic linker resolves the symbol to the value of the symbol we created.
+    // This is true even for got entries, so pointer equality is maintained.
+    // To avoid an infinite loop, the only entry that points to the
+    // real function is a dedicated got entry used by the plt.
+    return S.isShared();
   case R_X86_64_PLT32:
     return true;
   }
@@ -171,8 +190,12 @@ PPC64TargetInfo::PPC64TargetInfo() {
 }
 void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                                     uint64_t PltEntryAddr) const {}
-bool PPC64TargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
-bool PPC64TargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
+bool PPC64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+  return false;
+}
+bool PPC64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+  return false;
+}
 void PPC64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                                   uint64_t BaseAddr, uint64_t SymVA,
                                   uint64_t GotVA) const {
@@ -200,8 +223,12 @@ PPCTargetInfo::PPCTargetInfo() {
 }
 void PPCTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                                   uint64_t PltEntryAddr) const {}
-bool PPCTargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
-bool PPCTargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
+bool PPCTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+  return false;
+}
+bool PPCTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+  return false;
+}
 void PPCTargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                                 uint64_t BaseAddr, uint64_t SymVA,
                                 uint64_t GotVA) const {}
@@ -212,8 +239,12 @@ ARMTargetInfo::ARMTargetInfo() {
 }
 void ARMTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                                   uint64_t PltEntryAddr) const {}
-bool ARMTargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
-bool ARMTargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
+bool ARMTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+  return false;
+}
+bool ARMTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+  return false;
+}
 void ARMTargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                                 uint64_t BaseAddr, uint64_t SymVA,
                                 uint64_t GotVA) const {}
@@ -224,8 +255,14 @@ AArch64TargetInfo::AArch64TargetInfo() {
 }
 void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                                       uint64_t PltEntryAddr) const {}
-bool AArch64TargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
-bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
+bool AArch64TargetInfo::relocNeedsGot(uint32_t Type,
+                                      const SymbolBody &S) const {
+  return false;
+}
+bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type,
+                                      const SymbolBody &S) const {
+  return false;
+}
 
 static void handle_ADR_PREL_LO21(uint8_t *Location, uint64_t S, int64_t A,
                                  uint64_t P) {
@@ -268,9 +305,13 @@ MipsTargetInfo::MipsTargetInfo() {
 void MipsTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                                    uint64_t PltEntryAddr) const {}
 
-bool MipsTargetInfo::relocNeedsGot(uint32_t Type) const { return false; }
+bool MipsTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+  return false;
+}
 
-bool MipsTargetInfo::relocNeedsPlt(uint32_t Type) const { return false; }
+bool MipsTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+  return false;
+}
 
 void MipsTargetInfo::relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                                  uint64_t BaseAddr, uint64_t SymVA,

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Tue Sep 29 18:22:16 2015
@@ -26,9 +26,9 @@ public:
   unsigned getGotRefReloc() const { return GotRefReloc; };
   virtual void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                              uint64_t PltEntryAddr) const = 0;
-  virtual bool relocNeedsGot(uint32_t Type) const = 0;
+  virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0;
   virtual bool relocPointsToGot(uint32_t Type) const;
-  virtual bool relocNeedsPlt(uint32_t Type) const = 0;
+  virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0;
   virtual void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                            uint64_t BaseAddr, uint64_t SymVA,
                            uint64_t GotVA) const = 0;
@@ -47,9 +47,9 @@ public:
   X86TargetInfo();
   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                      uint64_t PltEntryAddr) const override;
-  bool relocNeedsGot(uint32_t Type) const override;
+  bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
   bool relocPointsToGot(uint32_t Type) const override;
-  bool relocNeedsPlt(uint32_t Type) const override;
+  bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                    uint64_t BaseAddr, uint64_t SymVA,
                    uint64_t GotVA) const override;
@@ -60,8 +60,8 @@ public:
   X86_64TargetInfo();
   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                      uint64_t PltEntryAddr) const override;
-  bool relocNeedsGot(uint32_t Type) const override;
-  bool relocNeedsPlt(uint32_t Type) const override;
+  bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+  bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                    uint64_t BaseAddr, uint64_t SymVA,
                    uint64_t GotVA) const override;
@@ -72,8 +72,8 @@ public:
   PPC64TargetInfo();
   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                      uint64_t PltEntryAddr) const override;
-  bool relocNeedsGot(uint32_t Type) const override;
-  bool relocNeedsPlt(uint32_t Type) const override;
+  bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+  bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                    uint64_t BaseAddr, uint64_t SymVA,
                    uint64_t GotVA) const override;
@@ -84,8 +84,8 @@ public:
   PPCTargetInfo();
   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                      uint64_t PltEntryAddr) const override;
-  bool relocNeedsGot(uint32_t Type) const override;
-  bool relocNeedsPlt(uint32_t Type) const override;
+  bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+  bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                    uint64_t BaseAddr, uint64_t SymVA,
                    uint64_t GotVA) const override;
@@ -96,8 +96,8 @@ public:
   ARMTargetInfo();
   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                      uint64_t PltEntryAddr) const override;
-  bool relocNeedsGot(uint32_t Type) const override;
-  bool relocNeedsPlt(uint32_t Type) const override;
+  bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+  bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                    uint64_t BaseAddr, uint64_t SymVA,
                    uint64_t GotVA) const override;
@@ -108,8 +108,8 @@ public:
   AArch64TargetInfo();
   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                      uint64_t PltEntryAddr) const override;
-  bool relocNeedsGot(uint32_t Type) const override;
-  bool relocNeedsPlt(uint32_t Type) const override;
+  bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+  bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                    uint64_t BaseAddr, uint64_t SymVA,
                    uint64_t GotVA) const override;
@@ -120,8 +120,8 @@ public:
   MipsTargetInfo();
   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                      uint64_t PltEntryAddr) const override;
-  bool relocNeedsGot(uint32_t Type) const override;
-  bool relocNeedsPlt(uint32_t Type) const override;
+  bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+  bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type,
                    uint64_t BaseAddr, uint64_t SymVA,
                    uint64_t GotVA) const override;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Sep 29 18:22:16 2015
@@ -234,12 +234,12 @@ void Writer<ELFT>::scanRelocs(
     if (!Body)
       continue;
     uint32_t Type = RI.getType(IsMips64EL);
-    if (Target->relocNeedsPlt(Type)) {
+    if (Target->relocNeedsPlt(Type, *Body)) {
       if (Body->isInPlt())
         continue;
       PltSec.addEntry(Body);
     }
-    if (Target->relocNeedsGot(Type)) {
+    if (Target->relocNeedsGot(Type, *Body)) {
       if (Body->isInGot())
         continue;
       GotSec.addEntry(Body);

Modified: lld/trunk/test/elf2/relocation.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/relocation.s?rev=248854&r1=248853&r2=248854&view=diff
==============================================================================
--- lld/trunk/test/elf2/relocation.s (original)
+++ lld/trunk/test/elf2/relocation.s Tue Sep 29 18:22:16 2015
@@ -1,7 +1,9 @@
 // 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
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2
+// RUN: lld -flavor gnu2 %t2 -o %t2.so -shared
+// RUN: lld -flavor gnu2 %t %t2.so -o %t3
+// RUN: llvm-readobj -s  %t3 | FileCheck --check-prefix=SEC %s
+// RUN: llvm-objdump -s -d %t3 | FileCheck %s
 // REQUIRES: x86
 
 // SEC:         Name: .got
@@ -10,15 +12,25 @@
 // SEC-NEXT:     SHF_ALLOC
 // SEC-NEXT:     SHF_WRITE
 // SEC-NEXT:   ]
-// SEC-NEXT:   Address: 0x13000
+// SEC-NEXT:   Address: 0x15000
 // SEC-NEXT:   Offset:
-// SEC-NEXT:   Size: 8
+// SEC-NEXT:   Size: 16
 // SEC-NEXT:   Link: 0
 // SEC-NEXT:   Info: 0
 // SEC-NEXT:   AddressAlignment: 8
 // SEC-NEXT:   EntrySize: 0
 // SEC-NEXT: }
 
+// SEC:      Name: .plt
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT:   SHF_ALLOC
+// SEC-NEXT:   SHF_EXECINSTR
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x16000
+// SEC-NEXT: Offset: 0x6000
+// SEC-NEXT: Size: 8
+
 .section       .text,"ax", at progbits,unique,1
 .global _start
 _start:
@@ -59,6 +71,15 @@ R_X86_64_32S:
 // CHECK-NEXT: R_X86_64_32S:
 // CHECK-NEXT:  {{.*}}: {{.*}} movq -978935, %rdx
 
+.section .R_X86_64_PC32,"ax", at progbits
+.global R_X86_64_PC32
+R_X86_64_PC32:
+ call bar
+// 0x16000 - (0x11019 + 5) = 20450
+// CHECK:      Disassembly of section .R_X86_64_PC32:
+// CHECK-NEXT: R_X86_64_PC32:
+// CHECK-NEXT:  11019:   e8 e2 4f 00 00  callq  20450
+
 .section .R_X86_64_64,"a", at progbits
 .global R_X86_64_64
 R_X86_64_64:
@@ -72,7 +93,7 @@ R_X86_64_64:
 R_X86_64_GOTPCREL:
  .long R_X86_64_GOTPCREL at gotpcrel
 
-// 0x13000 - 0x12008 = 4088
-// 4088 = 0xf80f0000 in little endian
+// 0x15008 - 0x12008 = 12288
+// 12288 = 0x00300000   in little endian
 // CHECK:      Contents of section .R_X86_64_GOTPCREL
-// CHECK-NEXT:   12008 f80f0000
+// CHECK-NEXT:   12008 00300000




More information about the llvm-commits mailing list