[lld] r219334 - [ELF] Implement --export-dynamic/-E

Rafael Auler rafaelauler at gmail.com
Wed Oct 8 11:54:27 PDT 2014


Author: rafauler
Date: Wed Oct  8 13:54:26 2014
New Revision: 219334

URL: http://llvm.org/viewvc/llvm-project?rev=219334&view=rev
Log:
[ELF] Implement --export-dynamic/-E

When creating a dynamic executable and receiving the -E flag, the linker should
export all globally visible symbols in its dynamic symbol table.

This commit also moves the logic that exports symbols in the dynamic symbol
table from OutputELFWriter to the ExecutableWriter class. It is not correct to
leave this at OutputELFWriter because DynamicLibraryWriter, another subclass of
OutputELFWriter, already exports all symbols, meaning we can potentially end up
with duplicated symbols in the dynamic symbol table when creating shared libs.

Reviewers: shankarke

http://reviews.llvm.org/D5585


Added:
    lld/trunk/test/elf/export-dynamic.test
Modified:
    lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
    lld/trunk/lib/Driver/GnuLdDriver.cpp
    lld/trunk/lib/Driver/GnuLdOptions.td
    lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h
    lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h

Modified: lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h?rev=219334&r1=219333&r2=219334&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h Wed Oct  8 13:54:26 2014
@@ -152,11 +152,14 @@ public:
 
   void setTriple(llvm::Triple trip) { _triple = trip; }
   void setNoInhibitExec(bool v) { _noInhibitExec = v; }
+  void setExportDynamic(bool v) { _exportDynamic = v; }
   void setIsStaticExecutable(bool v) { _isStaticExecutable = v; }
   void setMergeCommonStrings(bool v) { _mergeCommonStrings = v; }
   void setUseShlibUndefines(bool use) { _useShlibUndefines = use; }
   void setOutputELFType(uint32_t type) { _outputELFType = type; }
 
+  bool shouldExportDynamic() const { return _exportDynamic; }
+
   void createInternalFiles(std::vector<std::unique_ptr<File>> &) const override;
 
   /// \brief Set the dynamic linker path
@@ -283,6 +286,7 @@ protected:
   uint64_t _baseAddress;
   bool _isStaticExecutable;
   bool _noInhibitExec;
+  bool _exportDynamic;
   bool _mergeCommonStrings;
   bool _runLayoutPass;
   bool _useShlibUndefines;

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=219334&r1=219333&r2=219334&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Wed Oct  8 13:54:26 2014
@@ -372,6 +372,10 @@ bool GnuLdDriver::parse(int argc, const
       ctx->setAllowRemainingUndefines(true);
       break;
 
+    case OPT_export_dynamic:
+      ctx->setExportDynamic(true);
+      break;
+
     case OPT_merge_strings:
       ctx->setMergeCommonStrings(true);
       break;

Modified: lld/trunk/lib/Driver/GnuLdOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdOptions.td?rev=219334&r1=219333&r2=219334&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdOptions.td (original)
+++ lld/trunk/lib/Driver/GnuLdOptions.td Wed Oct  8 13:54:26 2014
@@ -139,6 +139,12 @@ defm rpath : dashEq<"rpath", "rpath",
 def rpath_link : Separate<["-"], "rpath-link">,
      HelpText<"Specifies the first set of directories to search">,
      Group<grp_dynlibexec>;
+def export_dynamic : Flag<["--"], "export-dynamic">,
+     HelpText<"Add all symbols to the dynamic symbol table"
+              " when creating executables">,
+     Group<grp_main>;
+def alias_export_dynamic: Flag<["-"], "E">,
+      Alias<export_dynamic>;
 
 //===----------------------------------------------------------------------===//
 /// Dynamic Library Options

Modified: lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h?rev=219334&r1=219333&r2=219334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h Wed Oct  8 13:54:26 2014
@@ -30,6 +30,7 @@ public:
         _runtimeFile(new CRuntimeFile<ELFT>(context)) {}
 
 protected:
+  virtual void buildDynamicSymbolTable(const File &file);
   virtual void addDefaultAtoms();
   virtual bool createImplicitFiles(std::vector<std::unique_ptr<File> > &);
   virtual void finalizeDefaultAtomValues();
@@ -41,6 +42,25 @@ protected:
 //===----------------------------------------------------------------------===//
 //  ExecutableWriter
 //===----------------------------------------------------------------------===//
+template<class ELFT>
+void ExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
+  for (auto sec : this->_layout.sections())
+    if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
+      for (const auto &atom : section->atoms()) {
+        const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom);
+        if (!da)
+          continue;
+        if (da->dynamicExport() != DefinedAtom::dynamicExportAlways &&
+            !this->_context.isDynamicallyExportedSymbol(da->name()) &&
+            !(this->_context.shouldExportDynamic() &&
+              da->scope() == Atom::Scope::scopeGlobal))
+          continue;
+        this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
+                                             atom->_virtualAddr, atom);
+      }
+
+  OutputELFWriter<ELFT>::buildDynamicSymbolTable(file);
+}
 
 /// \brief Add absolute symbols by default. These are linker added
 /// absolute symbols

Modified: lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h?rev=219334&r1=219333&r2=219334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h Wed Oct  8 13:54:26 2014
@@ -179,15 +179,6 @@ void OutputELFWriter<ELFT>::buildStaticS
 template <class ELFT>
 void OutputELFWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
   ScopedTask task(getDefaultDomain(), "buildDynamicSymbolTable");
-  for (auto sec : this->_layout.sections())
-    if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
-      for (const auto &atom : section->atoms()) {
-        const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom);
-        if (da && (da->dynamicExport() == DefinedAtom::dynamicExportAlways ||
-                   _context.isDynamicallyExportedSymbol(da->name())))
-          _dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
-                                         atom->_virtualAddr, atom);
-      }
   for (const auto &sla : file.sharedLibrary()) {
     if (isDynSymEntryRequired(sla))
       _dynamicSymbolTable->addSymbol(sla, ELF::SHN_UNDEF);

Added: lld/trunk/test/elf/export-dynamic.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/export-dynamic.test?rev=219334&view=auto
==============================================================================
--- lld/trunk/test/elf/export-dynamic.test (added)
+++ lld/trunk/test/elf/export-dynamic.test Wed Oct  8 13:54:26 2014
@@ -0,0 +1,99 @@
+# Tests the --export-dynamic (-E) flag. When creating a dynamic executable and
+# receiving this flag, the linker should export all globally visible symbols in
+# its dynamic symbol table.
+
+#RUN: yaml2obj -format=elf %s -o=%t.o
+#RUN: lld -flavor gnu  -target x86_64 -E %t.o -e=main -o %t1
+#RUN: llvm-readobj -dt %t1 | FileCheck -check-prefix CHECKSYMS %s
+
+#CHECKSYMS: myfunc1@
+#CHECKSYMS: main@
+#CHECKSYMS: myvar1@
+
+# The object file below was generated with the following code:
+#
+# (command line clang -c prog.c -o prog.o)
+#
+# int myvar1 = 22;
+#
+# static int mysecretvar = 11;
+#
+# int myfunc1() {
+#   return 23;
+# }
+#
+# static int mysecretfunc() {
+#   return 42;
+# }
+#
+# int main() {
+#   return mysecretfunc() + mysecretvar;
+# }
+---
+FileHeader:      
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  OSABI:           ELFOSABI_GNU
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:        
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000010
+    Content:         554889E5B8170000005DC30F1F440000554889E54883EC10C745FC00000000E81C000000030425000000004883C4105DC36666666666662E0F1F840000000000554889E5B82A0000005DC3
+  - Name:            .rela.text
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .text
+    Relocations:     
+      - Offset:          0x0000000000000027
+        Symbol:          .data
+        Type:            R_X86_64_32S
+        Addend:          4
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000004
+    Content:         160000000B000000
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000004
+    Content:         ''
+Symbols:         
+  Local:           
+    - Name:            mysecretfunc
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000040
+      Size:            0x000000000000000B
+    - Name:            mysecretvar
+      Type:            STT_OBJECT
+      Section:         .data
+      Value:           0x0000000000000004
+      Size:            0x0000000000000004
+    - Name:            .text
+      Type:            STT_SECTION
+      Section:         .text
+    - Name:            .data
+      Type:            STT_SECTION
+      Section:         .data
+    - Name:            .bss
+      Type:            STT_SECTION
+      Section:         .bss
+  Global:          
+    - Name:            main
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000010
+      Size:            0x0000000000000021
+    - Name:            myfunc1
+      Type:            STT_FUNC
+      Section:         .text
+      Size:            0x000000000000000B
+    - Name:            myvar1
+      Type:            STT_OBJECT
+      Section:         .data
+      Size:            0x0000000000000004





More information about the llvm-commits mailing list