[lld] r247487 - Start adding support for creating shared libraries.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 11 15:42:45 PDT 2015


Author: rafael
Date: Fri Sep 11 17:42:45 2015
New Revision: 247487

URL: http://llvm.org/viewvc/llvm-project?rev=247487&view=rev
Log:
Start adding support for creating shared libraries.

They are not fully functional yet, but this implements enough support for lld
itself to read them.

With that, delete the .so binary we were using for tests and start eating our
own dog food.

Added:
    lld/trunk/test/elf2/Inputs/shared.s
Removed:
    lld/trunk/test/elf2/Inputs/i686-simple-library.so
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/elf2/incompatible.s
    lld/trunk/test/elf2/shared.s

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=247487&r1=247486&r2=247487&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Fri Sep 11 17:42:45 2015
@@ -19,6 +19,7 @@ struct Configuration {
   llvm::StringRef OutputFile;
   llvm::StringRef DynamicLinker;
   std::string RPath;
+  bool Shared = false;
 };
 
 extern Configuration *Config;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=247487&r1=247486&r2=247487&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Fri Sep 11 17:42:45 2015
@@ -79,6 +79,9 @@ void LinkerDriver::link(ArrayRef<const c
   if (!RPaths.empty())
     Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
 
+  if (Args.hasArg(OPT_shared))
+    Config->Shared = true;
+
   // Create a list of input files.
   std::vector<MemoryBufferRef> Inputs;
 

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=247487&r1=247486&r2=247487&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Fri Sep 11 17:42:45 2015
@@ -12,3 +12,6 @@ def dynamic_linker : Separate<["-"], "dy
 
 def rpath : Separate<["-"], "rpath">,
      HelpText<"Add a DT_RUNPATH to the output">;
+
+def shared : Flag<["-"], "shared">,
+     HelpText<"Build a shared object">;

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=247487&r1=247486&r2=247487&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Fri Sep 11 17:42:45 2015
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "SymbolTable.h"
+#include "Config.h"
 #include "Error.h"
 #include "Symbols.h"
 
@@ -32,6 +33,8 @@ void SymbolTable::addFile(std::unique_pt
 }
 
 template <class ELFT> void SymbolTable::init() {
+  if (Config->Shared)
+    return;
   EntrySym = new (Alloc) Undefined<ELFT>("_start", Undefined<ELFT>::Synthetic);
   resolve<ELFT>(EntrySym);
 }

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=247487&r1=247486&r2=247487&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Fri Sep 11 17:42:45 2015
@@ -55,6 +55,8 @@ public:
   }
 
   SymbolBody *getEntrySym() const {
+    if (!EntrySym)
+      return nullptr;
     return EntrySym->getReplacement();
   }
 

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=247487&r1=247486&r2=247487&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Sep 11 17:42:45 2015
@@ -311,6 +311,10 @@ private:
     return !SymTabSec.getSymTable().getSharedFiles().empty() &&
            !Config->DynamicLinker.empty();
   }
+  bool needsDynamicSections() const {
+    return !SymTabSec.getSymTable().getSharedFiles().empty() || Config->Shared;
+  }
+  unsigned getVAStart() const { return Config->Shared ? 0 : VAStart; }
 
   std::unique_ptr<llvm::FileOutputBuffer> Buffer;
   llvm::SpecificBumpPtrAllocator<OutputSection<ELFT>> CAlloc;
@@ -604,8 +608,6 @@ template <class ELFT> void Writer<ELFT>:
     }
   }
 
-  const std::vector<std::unique_ptr<SharedFileBase>> &SharedFiles =
-      Symtab.getSharedFiles();
   BSSSec = getSection(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
   // FIXME: Try to avoid the extra walk over all global symbols.
   std::vector<DefinedCommon<ELFT> *> CommonSymbols;
@@ -624,7 +626,7 @@ template <class ELFT> void Writer<ELFT>:
     // FIXME: This adds way too much to the dynamic symbol table. We only
     // need to add the symbols use by dynamic relocations when producing
     // an executable (ignoring --export-dynamic).
-    if (!SharedFiles.empty())
+    if (needsDynamicSections())
       DynSymSec.addSymbol(Name);
   }
 
@@ -644,7 +646,7 @@ template <class ELFT> void Writer<ELFT>:
   OutputSections.push_back(&SymTabSec);
   OutputSections.push_back(&StrTabSec);
 
-  if (!SharedFiles.empty()) {
+  if (needsDynamicSections()) {
     if (needsInterpSection())
       OutputSections.push_back(&InterpSec);
     OutputSections.push_back(&DynSymSec);
@@ -666,7 +668,7 @@ static bool outputSectionHasPHDR(OutputS
 // Visits all sections to assign incremental, non-overlapping RVAs and
 // file offsets.
 template <class ELFT> void Writer<ELFT>::assignAddresses() {
-  uintX_t VA = VAStart;
+  uintX_t VA = getVAStart();
   uintX_t FileOff = 0;
 
   FileOff += sizeof(Elf_Ehdr);
@@ -711,7 +713,7 @@ template <class ELFT> void Writer<ELFT>:
   }
 
   // Add a PHDR for the dynamic table.
-  if (!SymTabSec.getSymTable().getSharedFiles().empty())
+  if (needsDynamicSections())
     ++NumPhdrs;
 
   FileOff += OffsetToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
@@ -762,13 +764,13 @@ template <class ELFT> void Writer<ELFT>:
   // FIXME: Generalize the segment construction similar to how we create
   // output sections.
   const SymbolTable &Symtab = SymTabSec.getSymTable();
-  bool HasDynamicSegment = !Symtab.getSharedFiles().empty();
 
-  EHdr->e_type = ET_EXEC;
+  EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC;
   auto &FirstObj = cast<ObjectFile<ELFT>>(*Symtab.getFirstELF());
   EHdr->e_machine = FirstObj.getEMachine();
   EHdr->e_version = EV_CURRENT;
-  EHdr->e_entry = getSymVA(cast<DefinedRegular<ELFT>>(Symtab.getEntrySym()));
+  SymbolBody *Entry = Symtab.getEntrySym();
+  EHdr->e_entry = Entry ? getSymVA(cast<DefinedRegular<ELFT>>(Entry)) : 0;
   EHdr->e_phoff = ProgramHeaderOff;
   EHdr->e_shoff = SectionHeaderOff;
   EHdr->e_ehsize = sizeof(Elf_Ehdr);
@@ -788,7 +790,7 @@ template <class ELFT> void Writer<ELFT>:
   PHdrs->p_type = PT_LOAD;
   PHdrs->p_flags = PF_R;
   PHdrs->p_offset = 0;
-  PHdrs->p_vaddr = VAStart;
+  PHdrs->p_vaddr = getVAStart();
   PHdrs->p_paddr = PHdrs->p_vaddr;
   PHdrs->p_filesz = ProgramHeaderOff + NumPhdrs * sizeof(Elf_Phdr);
   PHdrs->p_memsz = PHdrs->p_filesz;
@@ -809,7 +811,7 @@ template <class ELFT> void Writer<ELFT>:
     ++PHdrs;
   }
 
-  if (HasDynamicSegment) {
+  if (needsDynamicSections()) {
     PHdrs->p_type = PT_DYNAMIC;
     setValuesFromSection<ELFT>(*PHdrs, DynamicSec);
   }

Removed: lld/trunk/test/elf2/Inputs/i686-simple-library.so
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/i686-simple-library.so?rev=247486&view=auto
==============================================================================
Binary files lld/trunk/test/elf2/Inputs/i686-simple-library.so (original) and lld/trunk/test/elf2/Inputs/i686-simple-library.so (removed) differ

Added: lld/trunk/test/elf2/Inputs/shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/shared.s?rev=247487&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/shared.s (added)
+++ lld/trunk/test/elf2/Inputs/shared.s Fri Sep 11 17:42:45 2015
@@ -0,0 +1,6 @@
+.global bar
+.type bar, @function
+bar:
+
+.global zed
+zed:

Modified: lld/trunk/test/elf2/incompatible.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/incompatible.s?rev=247487&r1=247486&r2=247487&view=diff
==============================================================================
--- lld/trunk/test/elf2/incompatible.s (original)
+++ lld/trunk/test/elf2/incompatible.s Fri Sep 11 17:42:45 2015
@@ -1,5 +1,6 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %ta.o
 // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %tb.o
+// RUN: lld -flavor gnu2 -shared %tb.o -o %ti686.so
 // RUN: llvm-mc -filetype=obj -triple=arm-unknown-linux %s -o %tc.o
 
 // RUN: not lld -flavor gnu2 %ta.o %tb.o -o %t 2>&1 | \
@@ -10,17 +11,16 @@
 // RUN:   FileCheck --check-prefix=B-AND-C %s
 // B-AND-C: b.o is incompatible with {{.*}}c.o
 
-// FIMME: create the .so ourselves once we are able to
-// RUN: not lld -flavor gnu2 %ta.o %p/Inputs/i686-simple-library.so -o %t 2>&1 | \
+// RUN: not lld -flavor gnu2 %ta.o %ti686.so -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=A-AND-SO %s
-// A-AND-SO: a.o is incompatible with {{.*}}/Inputs/i686-simple-library.so
+// A-AND-SO: a.o is incompatible with {{.*}}i686.so
 
-// RUN: not lld -flavor gnu2 %tc.o %p/Inputs/i686-simple-library.so -o %t 2>&1 | \
+// RUN: not lld -flavor gnu2 %tc.o %ti686.so -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=C-AND-SO %s
-// C-AND-SO: c.o is incompatible with {{.*}}/Inputs/i686-simple-library.so
+// C-AND-SO: c.o is incompatible with {{.*}}i686.so
 
-// RUN: not lld -flavor gnu2 %p/Inputs/i686-simple-library.so %tc.o -o %t 2>&1 | \
+// RUN: not lld -flavor gnu2 %ti686.so %tc.o -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=SO-AND-C %s
-// SO-AND-C: /Inputs/i686-simple-library.so is incompatible with {{.*}}c.o
+// SO-AND-C: i686.so is incompatible with {{.*}}c.o
 
 // REQUIRES: x86,arm

Modified: lld/trunk/test/elf2/shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/shared.s?rev=247487&r1=247486&r2=247487&view=diff
==============================================================================
--- lld/trunk/test/elf2/shared.s (original)
+++ lld/trunk/test/elf2/shared.s Fri Sep 11 17:42:45 2015
@@ -1,5 +1,7 @@
 // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
-// RUN: lld -flavor gnu2 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar %t.o %p/Inputs/i686-simple-library.so -o %t
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
+// RUN: lld -flavor gnu2 -shared %t2.o -o %t2.so
+// RUN: lld -flavor gnu2 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar %t.o %t2.so -o %t
 // RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck %s
 // REQUIRES: x86
 
@@ -144,7 +146,7 @@
 // CHECK-NEXT:   0x00000005 STRTAB               [[DYNSTRADDR]]
 // CHECK-NEXT:   0x0000000A STRSZ
 // CHECK-NEXT:   0x0000001D RUNPATH              foo:bar
-// CHECK-NEXT:   0x00000001 NEEDED               SharedLibrary ({{.*}}/Inputs/i686-simple-library.so)
+// CHECK-NEXT:   0x00000001 NEEDED               SharedLibrary ({{.*}}2.so)
 // CHECK-NEXT:   0x00000000 NULL                 0x0
 // CHECK-NEXT: ]
 




More information about the llvm-commits mailing list