[lld] r247446 - Implement the -dynamic-linker option.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 11 11:49:43 PDT 2015


Author: rafael
Date: Fri Sep 11 13:49:42 2015
New Revision: 247446

URL: http://llvm.org/viewvc/llvm-project?rev=247446&view=rev
Log:
Implement the -dynamic-linker option.

With this dynamic executables can be executed with just ./t instead of
/lib64/ld-2.20.so ./t

Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/Writer.cpp
    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=247446&r1=247445&r2=247446&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Fri Sep 11 13:49:42 2015
@@ -17,6 +17,7 @@ namespace elf2 {
 
 struct Configuration {
   llvm::StringRef OutputFile;
+  llvm::StringRef DynamicLinker;
 };
 
 extern Configuration *Config;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=247446&r1=247445&r2=247446&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Fri Sep 11 13:49:42 2015
@@ -68,6 +68,10 @@ void LinkerDriver::link(ArrayRef<const c
   if (Config->OutputFile.empty())
     error("-o must be specified.");
 
+  // Handle -dynamic-linker
+  if (auto *Arg = Args.getLastArg(OPT_dynamic_linker))
+    Config->DynamicLinker = Arg->getValue();
+
   // 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=247446&r1=247445&r2=247446&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Fri Sep 11 13:49:42 2015
@@ -6,3 +6,6 @@ include "llvm/Option/OptParser.td"
 
 def output : Separate<["-"], "o">, MetaVarName<"<path>">,
      HelpText<"Path to file to write output">;
+
+def dynamic_linker : Separate<["-"], "dynamic-linker">,
+     HelpText<"Which dynamic linker to use">;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=247446&r1=247445&r2=247446&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Sep 11 13:49:42 2015
@@ -111,6 +111,20 @@ private:
 
 namespace {
 template <bool Is64Bits>
+class InterpSection final : public OutputSectionBase<Is64Bits> {
+public:
+  InterpSection()
+      : OutputSectionBase<Is64Bits>(".interp", SHT_PROGBITS, SHF_ALLOC) {
+    this->Header.sh_size = Config->DynamicLinker.size() + 1;
+    this->Header.sh_addralign = 1;
+  }
+
+  void writeTo(uint8_t *Buf) override {
+    memcpy(Buf, Config->DynamicLinker.data(), Config->DynamicLinker.size());
+  }
+};
+
+template <bool Is64Bits>
 class StringTableSection final : public OutputSectionBase<Is64Bits> {
 public:
   typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
@@ -169,7 +183,7 @@ public:
 
   void writeTo(uint8_t *Buf) override;
 
-  const SymbolTable &getSymTable() { return Table; }
+  const SymbolTable &getSymTable() const { return Table; }
 
   void addSymbol(StringRef Name) {
     StrTabSec.add(Name);
@@ -280,6 +294,10 @@ private:
   void openFile(StringRef OutputPath);
   void writeHeader();
   void writeSections();
+  bool needsInterpSection() const {
+    return !SymTabSec.getSymTable().getSharedFiles().empty() &&
+           !Config->DynamicLinker.empty();
+  }
 
   std::unique_ptr<llvm::FileOutputBuffer> Buffer;
   llvm::SpecificBumpPtrAllocator<OutputSection<ELFT>> CAlloc;
@@ -299,6 +317,8 @@ private:
 
   DynamicSection<ELFT> DynamicSec;
 
+  InterpSection<ELFT::Is64Bits> InterpSec;
+
   OutputSection<ELFT> *BSSSec = nullptr;
 };
 } // anonymous namespace
@@ -611,6 +631,8 @@ template <class ELFT> void Writer<ELFT>:
   OutputSections.push_back(&StrTabSec);
 
   if (!SharedFiles.empty()) {
+    if (needsInterpSection())
+      OutputSections.push_back(&InterpSec);
     OutputSections.push_back(&DynSymSec);
     OutputSections.push_back(&DynamicSec);
     OutputSections.push_back(&DynStrSec);
@@ -642,6 +664,11 @@ template <class ELFT> void Writer<ELFT>:
   VA = RoundUpToAlignment(VA, PageSize);
 
   NumPhdrs = 0;
+
+  // Add a PHDR for PT_INTERP.
+  if (needsInterpSection())
+    ++NumPhdrs;
+
   // Add a PHDR for the elf header and program headers. Some dynamic linkers
   // (musl at least) require them to be covered by a PT_LOAD.
   ++NumPhdrs;
@@ -692,6 +719,18 @@ static uint32_t convertSectionFlagsToPHD
   return Ret;
 }
 
+template <class ELFT>
+static void setValuesFromSection(typename ELFFile<ELFT>::Elf_Phdr &P,
+                                 OutputSectionBase<ELFT::Is64Bits> &S) {
+  P.p_flags = convertSectionFlagsToPHDRFlags(S.getFlags());
+  P.p_offset = S.getFileOff();
+  P.p_vaddr = S.getVA();
+  P.p_paddr = P.p_vaddr;
+  P.p_filesz = S.getSize();
+  P.p_memsz = P.p_filesz;
+  P.p_align = S.getAlign();
+}
+
 template <class ELFT> void Writer<ELFT>::writeHeader() {
   uint8_t *Buf = Buffer->getBufferStart();
   auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf);
@@ -726,6 +765,12 @@ template <class ELFT> void Writer<ELFT>:
   EHdr->e_shstrndx = StrTabSec.getSectionIndex();
 
   auto PHdrs = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff);
+  if (needsInterpSection()) {
+    PHdrs->p_type = PT_INTERP;
+    setValuesFromSection<ELFT>(*PHdrs, InterpSec);
+    ++PHdrs;
+  }
+
   PHdrs->p_type = PT_LOAD;
   PHdrs->p_flags = PF_R;
   PHdrs->p_offset = 0;
@@ -752,13 +797,7 @@ template <class ELFT> void Writer<ELFT>:
 
   if (HasDynamicSegment) {
     PHdrs->p_type = PT_DYNAMIC;
-    PHdrs->p_flags = convertSectionFlagsToPHDRFlags(DynamicSec.getFlags());
-    PHdrs->p_offset = DynamicSec.getFileOff();
-    PHdrs->p_vaddr = DynamicSec.getVA();
-    PHdrs->p_paddr = PHdrs->p_vaddr;
-    PHdrs->p_filesz = DynamicSec.getSize();
-    PHdrs->p_memsz = DynamicSec.getSize();
-    PHdrs->p_align = DynamicSec.getAlign();
+    setValuesFromSection<ELFT>(*PHdrs, DynamicSec);
   }
 
   auto SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);

Modified: lld/trunk/test/elf2/shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/shared.s?rev=247446&r1=247445&r2=247446&view=diff
==============================================================================
--- lld/trunk/test/elf2/shared.s (original)
+++ lld/trunk/test/elf2/shared.s Fri Sep 11 13:49:42 2015
@@ -1,20 +1,43 @@
 // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
-// RUN: lld -flavor gnu2 %t.o %p/Inputs/i686-simple-library.so -o %t
-// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols %t | FileCheck %s
+// RUN: lld -flavor gnu2 -dynamic-linker /lib64/ld-linux-x86-64.so.2 %t.o %p/Inputs/i686-simple-library.so -o %t
+// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck %s
 // REQUIRES: x86
 
+// CHECK:        Name: .interp
+// CHECK-NEXT:   Type: SHT_PROGBITS
+// CHECK-NEXT:   Flags [
+// CHECK-NEXT:     SHF_ALLOC
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Address: [[INTERPADDR:.*]]
+// CHECK-NEXT:   Offset: [[INTERPOFFSET:.*]]
+// CHECK-NEXT:   Size: [[INTERPSIZE:.*]]
+// CHECK-NEXT:   Link: 0
+// CHECK-NEXT:   Info: 0
+// CHECK-NEXT:   AddressAlignment: 1
+// CHECK-NEXT:   EntrySize: 0
+// CHECK-NEXT:   SectionData (
+// CHECK-NEXT:     0000: 2F6C6962 36342F6C 642D6C69 6E75782D  |/lib64/ld-linux-|
+// CHECK-NEXT:     0010: 7838362D 36342E73 6F2E3200           |x86-64.so.2.|
+// CHECK-NEXT:   )
+// CHECK-NEXT: }
+
 // CHECK:        Name: .dynsym
 // CHECK-NEXT:   Type: SHT_DYNSYM
 // CHECK-NEXT:   Flags [
 // CHECK-NEXT:     SHF_ALLOC
 // CHECK-NEXT:   ]
 // CHECK-NEXT:   Address: [[DYNSYMADDR:.*]]
-// CHECK-NEXT:   Offset: 0x2000
+// CHECK-NEXT:   Offset: 0x3000
 // CHECK-NEXT:   Size: 48
 // CHECK-NEXT:   Link: [[DYNSTR:.*]]
 // CHECK-NEXT:   Info: 1
 // CHECK-NEXT:   AddressAlignment: 4
 // CHECK-NEXT:   EntrySize: 16
+// CHECK-NEXT:   SectionData (
+// CHECK-NEXT:     0000:
+// CHECK-NEXT:     0010:
+// CHECK-NEXT:     0020:
+// CHECK-NEXT:   )
 // CHECK-NEXT: }
 
 // CHECK:        Name: .dynamic
@@ -30,6 +53,11 @@
 // CHECK-NEXT:   Info: 0
 // CHECK-NEXT:   AddressAlignment: [[ALIGN:.*]]
 // CHECK-NEXT:   EntrySize: 8
+// CHECK-NEXT:   SectionData (
+// CHECK-NEXT:     0000:
+// CHECK-NEXT:     0010:
+// CHECK-NEXT:     0020:
+// CHECK-NEXT:   )
 // CHECK-NEXT: }
 
 // CHECK:        Index: [[DYNSTR]]
@@ -45,6 +73,13 @@
 // CHECK-NEXT:   Info: 0
 // CHECK-NEXT:   AddressAlignment: 1
 // CHECK-NEXT:   EntrySize: 0
+// CHECK-NEXT:   SectionData (
+// CHECK-NEXT:     0000:
+// CHECK-NEXT:     0010:
+// CHECK-NEXT:     0020:
+// CHECK-NEXT:     0030:
+// CHECK-NEXT:     0040:
+// CHECK-NEXT:   )
 // CHECK-NEXT: }
 
 
@@ -117,7 +152,19 @@
 // CHECK-NEXT:   0x00000000 NULL                 0x0
 // CHECK-NEXT: ]
 
-// CHECK:      ProgramHeader {
+// CHECK:      ProgramHeaders [
+// CHECK-NEXT:   ProgramHeader {
+// CHECK-NEXT:   Type: PT_INTERP
+// CHECK-NEXT:   Offset: [[INTERPOFFSET]]
+// CHECK-NEXT:   VirtualAddress: [[INTERPADDR]]
+// CHECK-NEXT:   PhysicalAddress: [[INTERPADDR]]
+// CHECK-NEXT:   FileSize: [[INTERPSIZE]]
+// CHECK-NEXT:   MemSize: [[INTERPSIZE]]
+// CHECK-NEXT:   Flags [
+// CHECK-NEXT:     PF_R
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Alignment: 1
+// CHECK-NEXT: }
 // CHECK:        Type: PT_DYNAMIC
 // CHECK-NEXT:   Offset: [[OFFSET]]
 // CHECK-NEXT:   VirtualAddress: [[ADDR]]




More information about the llvm-commits mailing list