[lld] r184266 - [ELF] add -u/--undefined option, to define undefined symbols

Shankar Easwaran shankare at codeaurora.org
Tue Jun 18 17:31:10 PDT 2013


Author: shankare
Date: Tue Jun 18 19:31:09 2013
New Revision: 184266

URL: http://llvm.org/viewvc/llvm-project?rev=184266&view=rev
Log:
[ELF] add -u/--undefined option, to define undefined symbols

Added:
    lld/trunk/test/elf/X86_64/Inputs/libfn.a
    lld/trunk/test/elf/X86_64/undef.test
Modified:
    lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h
    lld/trunk/lib/Driver/GnuLdDriver.cpp
    lld/trunk/lib/Driver/LDOptions.td
    lld/trunk/lib/ReaderWriter/ELF/DynamicLibraryWriter.h
    lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h
    lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h

Modified: lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h?rev=184266&r1=184265&r2=184266&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h Tue Jun 18 19:31:09 2013
@@ -12,6 +12,7 @@
 
 #include "lld/Core/PassManager.h"
 #include "lld/Core/Pass.h"
+#include "lld/Core/range.h"
 #include "lld/Core/TargetInfo.h"
 #include "lld/ReaderWriter/Reader.h"
 #include "lld/ReaderWriter/Writer.h"
@@ -154,6 +155,22 @@ public:
   /// Searches directories then calls appendInputFile()
   bool appendLibrary(StringRef libName);
 
+  /// adds undefined symbols that are specified in the command line
+  void addUndefinedSymbol(StringRef symbolName) {
+    _undefinedSymbols.push_back(symbolName);
+  }
+
+  /// Iterators for symbols that appear on the command line
+  typedef std::vector<StringRef> StringRefVector;
+  typedef StringRefVector::iterator StringRefVectorIter;
+  typedef StringRefVector::const_iterator StringRefVectorConstIter;
+
+  /// Return the list of undefined symbols that are specified in the
+  /// linker command line, using the -u option.
+  range<const StringRef *> undefinedSymbols() const {
+    return _undefinedSymbols;
+  }
+
 private:
   ELFTargetInfo() LLVM_DELETED_FUNCTION;
 protected:
@@ -174,12 +191,13 @@ protected:
   bool                               _dynamicLinkerArg;
   bool                               _noAllowDynamicLibraries;
   OutputMagic                        _outputMagic;
-  std::vector<StringRef>             _inputSearchPaths;
+  StringRefVector                    _inputSearchPaths;
   llvm::BumpPtrAllocator             _extraStrings;
   std::unique_ptr<Reader>            _elfReader;
   std::unique_ptr<Writer>            _writer;
   std::unique_ptr<Reader>            _linkerScriptReader;
   StringRef                          _dynamicLinkerPath;
+  StringRefVector                    _undefinedSymbols;
 };
 } // end namespace lld
 

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=184266&r1=184265&r2=184266&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Tue Jun 18 19:31:09 2013
@@ -217,6 +217,13 @@ GnuLdDriver::parse(int argc, const char
   if (!options->allowLinkWithDynamicLibraries())
     options->setIsStaticExecutable(true);
 
+  // Handle -u, --undefined option
+  for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_u),
+                               ie = parsedArgs->filtered_end();
+       it != ie; ++it) {
+    options->addUndefinedSymbol((*it)->getValue());
+  }
+
   // Handle -Lxxx
   for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_L),
                                ie = parsedArgs->filtered_end();

Modified: lld/trunk/lib/Driver/LDOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/LDOptions.td?rev=184266&r1=184265&r2=184266&view=diff
==============================================================================
--- lld/trunk/lib/Driver/LDOptions.td (original)
+++ lld/trunk/lib/Driver/LDOptions.td Tue Jun 18 19:31:09 2013
@@ -72,6 +72,14 @@ def omagic_alias : Flag<["-"], "N">, Ali
 def no_omagic : Flag<["--"], "no-omagic">,
     HelpText<"This option negates most of the effects of the -N option. Disable linking with shared libraries">;
 
+// TODO: remove the options with the = sign, once the change in the OptionParser
+// is done to recognize the allowed suffixes for an argument. 
+def u : Separate<["-"], "u">,
+    HelpText<"Force symbol to be entered in the output file as an undefined symbol">;
+def undefined : Separate<["--"], "undefined">, Alias<u>;
+def u_equal : Joined<["-"], "u=">, Alias<u>;
+def undefined_equal : Joined<["--"], "undefined=">, Alias<u>;
+
 // extensions
 def emit_yaml : Flag<["-"], "emit-yaml">, 
     HelpText<"Write YAML instead of ELF">;

Modified: lld/trunk/lib/ReaderWriter/ELF/DynamicLibraryWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/DynamicLibraryWriter.h?rev=184266&r1=184265&r2=184266&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/DynamicLibraryWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/DynamicLibraryWriter.h Tue Jun 18 19:31:09 2013
@@ -31,7 +31,6 @@ public:
 private:
   void buildDynamicSymbolTable(const File &file);
   void addDefaultAtoms();
-  void addFiles(InputFiles&);
   void finalizeDefaultAtomValues();
 
   llvm::BumpPtrAllocator _alloc;
@@ -63,11 +62,6 @@ void DynamicLibraryWriter<ELFT>::buildDy
 template<class ELFT>
 void DynamicLibraryWriter<ELFT>::addDefaultAtoms() { }
 
-template <class ELFT>
-void DynamicLibraryWriter<ELFT>::addFiles(InputFiles &inputFiles) {
-  this->_targetHandler.addFiles(inputFiles);
-}
-
 template<class ELFT>
 void DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
   this->_targetHandler.finalizeSymbolValues();

Modified: lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h?rev=184266&r1=184265&r2=184266&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h Tue Jun 18 19:31:09 2013
@@ -64,10 +64,13 @@ void ExecutableWriter<ELFT>::addDefaultA
 /// \brief Hook in lld to add CRuntime file
 template <class ELFT>
 void ExecutableWriter<ELFT>::addFiles(InputFiles &inputFiles) {
+  // Add the default atoms as defined by executables
   addDefaultAtoms();
+  // Add the runtime file
   inputFiles.prependFile(_runtimeFile);
-  // Give a chance for the target to add atoms
-  this->_targetHandler.addFiles(inputFiles);
+  // Add the Linker internal file for symbols that are defined by
+  // command line options
+  OutputELFWriter<ELFT>::addFiles(inputFiles);
 }
 
 template <class ELFT> void ExecutableWriter<ELFT>::createDefaultSections() {
@@ -120,11 +123,14 @@ template <class ELFT> void ExecutableWri
 
   auto bssSection = this->_layout->findOutputSection(".bss");
 
-  (*bssStartAtomIter)->_virtualAddr = bssSection->virtualAddr();
-  (*bssEndAtomIter)->_virtualAddr =
-      bssSection->virtualAddr() + bssSection->memSize();
-  (*underScoreEndAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr;
-  (*endAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr;
+  // If we dont find a bss section, then dont set these values
+  if (bssSection) {
+    (*bssStartAtomIter)->_virtualAddr = bssSection->virtualAddr();
+    (*bssEndAtomIter)->_virtualAddr =
+        bssSection->virtualAddr() + bssSection->memSize();
+    (*underScoreEndAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr;
+    (*endAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr;
+  }
 
   // Give a chance for the target to finalize its atom values
   this->_targetHandler.finalizeSymbolValues();

Modified: lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h?rev=184266&r1=184265&r2=184266&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h Tue Jun 18 19:31:09 2013
@@ -28,6 +28,15 @@ using namespace llvm::object;
 template<class ELFT>
 class OutputELFWriter;
 
+/// \brief This acts as a internal file that the linker uses to add
+/// undefined symbols that are defined by using the linker options such
+/// as -u, or --defsym option.
+template <class ELFT> class LinkerInternalFile : public CRuntimeFile<ELFT> {
+public:
+  LinkerInternalFile(const ELFTargetInfo &ti)
+      : CRuntimeFile<ELFT>(ti, "Linker Internal File") {};
+};
+
 //===----------------------------------------------------------------------===//
 //  OutputELFWriter Class
 //===----------------------------------------------------------------------===//
@@ -78,7 +87,7 @@ protected:
   virtual void addDefaultAtoms() = 0;
 
   // Add any runtime files and their atoms to the output
-  virtual void addFiles(InputFiles&) = 0;
+  virtual void addFiles(InputFiles &);
 
   // Finalize the default atom values
   virtual void finalizeDefaultAtomValues() = 0;
@@ -114,6 +123,7 @@ protected:
   LLD_UNIQUE_BUMP_PTR(HashSection<ELFT>) _hashTable;
   llvm::StringSet<> _soNeeded;
   /// @}
+  LinkerInternalFile<ELFT> _linkerInternalFile;
 };
 
 //===----------------------------------------------------------------------===//
@@ -121,7 +131,8 @@ protected:
 //===----------------------------------------------------------------------===//
 template <class ELFT>
 OutputELFWriter<ELFT>::OutputELFWriter(const ELFTargetInfo &ti)
-    : _targetInfo(ti), _targetHandler(ti.getTargetHandler<ELFT>()) {
+    : _targetInfo(ti), _targetHandler(ti.getTargetHandler<ELFT>()),
+      _linkerInternalFile(ti) {
   _layout = &_targetHandler.targetLayout();
 }
 
@@ -223,8 +234,19 @@ void OutputELFWriter<ELFT>::assignSectio
         _shdrtab->updateSection(section);
 }
 
-template<class ELFT>
-void OutputELFWriter<ELFT>::createDefaultSections() {
+template <class ELFT>
+void OutputELFWriter<ELFT>::addFiles(InputFiles &inputFiles) {
+  // Add all input Files that are defined by the target
+  _targetHandler.addFiles(inputFiles);
+  // Add all symbols that are specified by the -u option
+  // as part of the command line argument to lld
+  for (auto ai : _targetInfo.undefinedSymbols())
+    _linkerInternalFile.addUndefinedAtom(ai);
+  // Make the linker internal file to be the first file
+  inputFiles.prependFile(_linkerInternalFile);
+}
+
+template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
   _Header.reset(new (_alloc) Header<ELFT>(_targetInfo));
   _programHeader.reset(new (_alloc) ProgramHeader<ELFT>(_targetInfo));
   _layout->setHeader(_Header.get());

Added: lld/trunk/test/elf/X86_64/Inputs/libfn.a
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/libfn.a?rev=184266&view=auto
==============================================================================
Binary files lld/trunk/test/elf/X86_64/Inputs/libfn.a (added) and lld/trunk/test/elf/X86_64/Inputs/libfn.a Tue Jun 18 19:31:09 2013 differ

Added: lld/trunk/test/elf/X86_64/undef.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/undef.test?rev=184266&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/undef.test (added)
+++ lld/trunk/test/elf/X86_64/undef.test Tue Jun 18 19:31:09 2013
@@ -0,0 +1,19 @@
+# This tests the functionality that an undefined symbol thats defined in the
+# commmand line pulls in the required object file from the archive library
+# which is usually the usecase for it
+RUN: lld -flavor gnu -target x86_64 -u fn %p/Inputs/libfn.a -o %t --noinhibit-exec
+RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=SYMFROMARCHIVE %s
+RUN: lld -flavor gnu -target x86_64 %p/Inputs/libfn.a -o %t --noinhibit-exec
+RUN: llvm-readobj -symbols %t | FileCheck %s
+
+SYMFROMARCHIVE:  Symbol {
+SYMFROMARCHIVE:    Name: fn (16)
+SYMFROMARCHIVE:    Value: 0x4001A4
+SYMFROMARCHIVE:    Size: 11
+SYMFROMARCHIVE:    Binding: Global (0x1)
+SYMFROMARCHIVE:    Type: Function (0x2)
+SYMFROMARCHIVE:    Other: 0
+SYMFROMARCHIVE:    Section: .text (0x5)
+SYMFROMARCHIVE:  }
+
+CHECK-NOT: Name: fn





More information about the llvm-commits mailing list