[ELF] Add support for -z origin/now options.
authorDavide Italiano <davide@freebsd.org>
Tue, 26 May 2015 01:57:32 +0000 (01:57 +0000)
committerDavide Italiano <davide@freebsd.org>
Tue, 26 May 2015 01:57:32 +0000 (01:57 +0000)
Differential Revision: http://reviews.llvm.org/D9963

llvm-svn: 238169

lld/include/lld/ReaderWriter/ELFLinkingContext.h
lld/lib/Driver/GnuLdDriver.cpp
lld/lib/ReaderWriter/ELF/OutputELFWriter.cpp
lld/test/elf/zoption_dtflags.test [new file with mode: 0644]

index 7899061..8fb1b54 100644 (file)
@@ -97,6 +97,12 @@ public:
     OMAGIC,
   };
 
+  /// \brief ELF DT_FLAGS.
+  enum DTFlag : uint32_t {
+    DT_NOW = 1 << 1,
+    DT_ORIGIN = 1 << 2,
+  };
+
   llvm::Triple getTriple() const { return _triple; }
 
   uint64_t getPageSize() const { return _maxPageSize; }
@@ -329,6 +335,10 @@ public:
   // --wrap option.
   void addWrapForSymbol(StringRef sym) { _wrapCalls.insert(sym); }
 
+  // \brief Set DT_FLAGS flag.
+  void setDTFlag(DTFlag f) { _dtFlags |= f; };
+  bool getDTFlag(DTFlag f) { return (_dtFlags & f); };
+
   const llvm::StringSet<> &wrapCalls() const { return _wrapCalls; }
 
   void setUndefinesResolver(std::unique_ptr<File> resolver);
@@ -383,6 +393,7 @@ protected:
   bool _armTarget1Rel = false;
   bool _mipsPcRelEhRel = false;
   uint64_t _maxPageSize = 0x1000;
+  uint32_t _dtFlags = 0;
 
   OutputMagic _outputMagic = OutputMagic::DEFAULT;
   StringRefVector _inputSearchPaths;
index ba87e9b..0375ec8 100644 (file)
@@ -584,9 +584,13 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
 
   for (auto *arg : parsedArgs->filtered(OPT_z)) {
     StringRef opt = arg->getValue();
-    if (opt == "muldefs") {
+    if (opt == "muldefs")
       ctx->setAllowDuplicates(true);
-    } else if (opt.startswith("max-page-size")) {
+    else if (opt == "now")
+      ctx->setDTFlag(ELFLinkingContext::DTFlag::DT_NOW);
+    else if (opt == "origin")
+      ctx->setDTFlag(ELFLinkingContext::DTFlag::DT_ORIGIN);
+    else if (opt.startswith("max-page-size")) {
       // Parse -z max-page-size option.
       // The default page size is considered the minimum page size the user
       // can set, check the user input if its atleast the minimum page size
index 1077834..14cd3c4 100644 (file)
@@ -140,6 +140,21 @@ void OutputELFWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
   if (!soname.empty() && _ctx.getOutputELFType() == llvm::ELF::ET_DYN)
     _dynamicTable->addEntry(DT_SONAME, _dynamicStringTable->addString(soname));
 
+  // Add DT_FLAGS/DT_FLAGS_1 entries if necessary.
+  uint32_t dtflags = 0, dt1flags = 0;
+  if (_ctx.getDTFlag(ELFLinkingContext::DTFlag::DT_NOW)) {
+    dtflags |= DF_BIND_NOW;
+    dt1flags |= DF_1_NOW;
+  }
+  if (_ctx.getDTFlag(ELFLinkingContext::DTFlag::DT_ORIGIN)) {
+    dtflags |= DF_ORIGIN;
+    dt1flags |= DF_1_ORIGIN;
+  }
+  if (dtflags != 0)
+    _dynamicTable->addEntry(DT_FLAGS, dtflags);
+  if (dt1flags != 0)
+    _dynamicTable->addEntry(DT_FLAGS_1, dt1flags);
+
   // The dynamic symbol table need to be sorted earlier because the hash
   // table needs to be built using the dynamic symbol table. It would be
   // late to sort the symbols due to that in finalize. In the dynamic symbol
diff --git a/lld/test/elf/zoption_dtflags.test b/lld/test/elf/zoption_dtflags.test
new file mode 100644 (file)
index 0000000..1c5d838
--- /dev/null
@@ -0,0 +1,90 @@
+# Test that -z {origin, now} options work.
+#
+#RUN: yaml2obj -format=elf %s -o=%t.o
+#RUN: lld -flavor gnu -target x86_64 %t.o -e=main -z now -z origin -o %t1
+#RUN: llvm-readobj -dynamic-table %t1 | FileCheck %s
+#
+#CHECK: 0x000000000000001E FLAGS                ORIGIN BIND_NOW
+#CHECK: 0x000000006FFFFFFB FLAGS_1              NOW ORIGIN
+
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  OSABI:           ELFOSABI_FREEBSD
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000010
+    Content:         554889E54883EC10C745FC00000000E81C000000B9000000008945F889C84883C4105DC36666662E0F1F840000000000554889E58B45FC5DC3
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000004
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000004
+    Content:         ''
+  - Name:            .comment
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x0000000000000001
+    Content:         004672656542534420636C616E672076657273696F6E20332E342E312028746167732F52454C454153455F33342F646F74312D66696E616C203230383033322920323031343035313200
+  - Name:            .note.GNU-stack
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .eh_frame
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    AddressAlign:    0x0000000000000008
+    Content:         1400000000000000017A5200017810011B0C070890010000180000001C000000000000002400000000410E108602430D060000001800000038000000000000000900000000410E108602430D06000000
+  - Name:            .rela.eh_frame
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .eh_frame
+    Relocations:
+      - Offset:          0x0000000000000020
+        Symbol:          .text
+        Type:            R_X86_64_PC32
+      - Offset:          0x000000000000003C
+        Symbol:          .text
+        Type:            R_X86_64_PC32
+        Addend:          48
+Symbols:
+  Local:
+    - Name:            local
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000030
+      Size:            0x0000000000000009
+    - Name:            .text
+      Type:            STT_SECTION
+      Section:         .text
+    - Name:            .data
+      Type:            STT_SECTION
+      Section:         .data
+    - Name:            .bss
+      Type:            STT_SECTION
+      Section:         .bss
+    - Name:            .comment
+      Type:            STT_SECTION
+      Section:         .comment
+    - Name:            .note.GNU-stack
+      Type:            STT_SECTION
+      Section:         .note.GNU-stack
+    - Name:            .eh_frame
+      Type:            STT_SECTION
+      Section:         .eh_frame
+  Global:
+    - Name:            main
+      Type:            STT_FUNC
+      Section:         .text
+      Size:            0x0000000000000024
+...