[llvm-commits] [lld] r167854 - in /lld/trunk: include/lld/ReaderWriter/ReaderArchive.h include/lld/ReaderWriter/ReaderELF.h lib/ReaderWriter/CMakeLists.txt lib/ReaderWriter/ELF/ReaderELF.cpp lib/ReaderWriter/ReaderArchive.cpp test/elf/Inputs/libfnarchive.x86_64 test/elf/Inputs/mainobj.x86_64 test/elf/archive-elf-forceload.objtxt test/elf/archive-elf.objtxt tools/lld-core/lld-core.cpp

Shankar Easwaran shankare at codeaurora.org
Tue Nov 13 10:39:11 PST 2012


Author: shankare
Date: Tue Nov 13 12:39:10 2012
New Revision: 167854

URL: http://llvm.org/viewvc/llvm-project?rev=167854&view=rev
Log:
Adding support to resolve symbols with archive libraries in lld

Added:
    lld/trunk/include/lld/ReaderWriter/ReaderArchive.h
    lld/trunk/lib/ReaderWriter/ReaderArchive.cpp
    lld/trunk/test/elf/Inputs/libfnarchive.x86_64   (with props)
    lld/trunk/test/elf/Inputs/mainobj.x86_64   (with props)
    lld/trunk/test/elf/archive-elf-forceload.objtxt
    lld/trunk/test/elf/archive-elf.objtxt
Modified:
    lld/trunk/include/lld/ReaderWriter/ReaderELF.h
    lld/trunk/lib/ReaderWriter/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp
    lld/trunk/tools/lld-core/lld-core.cpp

Added: lld/trunk/include/lld/ReaderWriter/ReaderArchive.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ReaderArchive.h?rev=167854&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ReaderArchive.h (added)
+++ lld/trunk/include/lld/ReaderWriter/ReaderArchive.h Tue Nov 13 12:39:10 2012
@@ -0,0 +1,80 @@
+//===- ReaderWriter/ReaderArchive.h - Archive Library Reader ------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------------===//
+
+#ifndef LLD_READER_ARCHIVE_H
+#define LLD_READER_ARCHIVE_H
+
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Object/Archive.h"
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
+#include <memory>
+#include <bits/unique_ptr.h>
+#include <vector>
+
+namespace lld
+{
+///
+/// The ReaderOptionsArchive encapsulates the options used by the ReaderArchive.
+/// The option objects are the only way to control the behaviour of Readers.
+///
+class ReaderOptionsArchive
+{
+public:
+  ReaderOptionsArchive(bool is_force_load=false): _isForceLoad(is_force_load),
+                                                  _reader(nullptr)
+  { }
+  
+  bool isForceLoad() const {
+    return _isForceLoad;
+  }
+  
+  Reader *reader() const {
+    return _reader;
+  }
+
+  void setReader(Reader *r) {
+    _reader = r;
+  }
+  
+private:
+  bool _isForceLoad;
+  Reader *_reader;
+};
+
+// ReaderArchive is a class for reading archive libraries
+class ReaderArchive final
+{
+public:
+  ReaderArchive(ReaderOptionsArchive &options) : _options(options),
+                                                 _archive()
+  { }
+
+  // Returns a vector of Files that are contained in the archive file 
+  // pointed to by the Memorybuffer
+  virtual error_code parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
+                               std::vector<std::unique_ptr<File>> &result);
+
+  virtual ~ReaderArchive() { }
+
+private:
+  ReaderOptionsArchive &_options;
+  std::unique_ptr<llvm::object::Archive> _archive;
+};
+
+} // namespace lld
+
+#endif // LLD_READER_ARCHIVE_H

Modified: lld/trunk/include/lld/ReaderWriter/ReaderELF.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ReaderELF.h?rev=167854&r1=167853&r2=167854&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ReaderELF.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ReaderELF.h Tue Nov 13 12:39:10 2012
@@ -11,6 +11,7 @@
 #define LLD_READERWRITER_READER_ELF_H_
 
 #include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
 #include "lld/Core/LLVM.h"
 
 
@@ -56,7 +57,8 @@
 /// ReaderOptionsELF object supplied, so the objects object must not be  
 /// destroyed before the Reader object. 
 ///
-Reader* createReaderELF(const ReaderOptionsELF &options);
+Reader* createReaderELF(const ReaderOptionsELF &options, 
+                        ReaderOptionsArchive &optionsArchive);
 
 
 

Modified: lld/trunk/lib/ReaderWriter/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/CMakeLists.txt?rev=167854&r1=167853&r2=167854&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/CMakeLists.txt (original)
+++ lld/trunk/lib/ReaderWriter/CMakeLists.txt Tue Nov 13 12:39:10 2012
@@ -6,4 +6,5 @@
 add_lld_library(lldReaderWriter
   Reader.cpp
   Writer.cpp
+  ReaderArchive.cpp
   )

Modified: lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp?rev=167854&r1=167853&r2=167854&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp Tue Nov 13 12:39:10 2012
@@ -12,9 +12,9 @@
 //
 //===----------------------------------------------------------------------===//
 #include "lld/ReaderWriter/ReaderELF.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
 #include "lld/Core/File.h"
 #include "lld/Core/Reference.h"
-
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
@@ -30,6 +30,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/system_error.h"
+#include "llvm/Support/Path.h"
 
 
 #include <map>
@@ -751,43 +752,72 @@
 
 class ReaderELF: public Reader {
 public:
-  ReaderELF(const ReaderOptionsELF &) {}
+  ReaderELF(const ReaderOptionsELF &readerELFOptions,
+            ReaderOptionsArchive &readerOptionsArchive)
+         : _readerELFOptions(readerELFOptions),
+           _readerOptionsArchive(readerOptionsArchive),
+           _readerArchive(_readerOptionsArchive) { 
+    _readerOptionsArchive.setReader(this);
+  }
+
   error_code parseFile(std::unique_ptr<MemoryBuffer> mb, std::vector<
-      std::unique_ptr<File> > &result) {
+                       std::unique_ptr<File> > &result) {
+    llvm::error_code ec; 
+    std::unique_ptr<File> f;
+    std::pair<unsigned char, unsigned char> Ident;
 
-    std::pair<unsigned char, unsigned char> Ident =
-        llvm::object::getElfArchType(&*mb);
-    llvm::error_code ec;
-    //    Instantiate the correct FileELF template instance
-    //    based on the Ident pair. Once the File is created
-    //     we push the file to the vector of files already
-    //     created during parser's life.
+    llvm::sys::LLVMFileType fileType = 
+          llvm::sys::IdentifyFileType(mb->getBufferStart(),
+                                static_cast<unsigned>(mb->getBufferSize()));
+    switch (fileType) {
+
+      case llvm::sys::ELF_Relocatable_FileType:
+
+        Ident = llvm::object::getElfArchType(&*mb);
+        //    Instantiate the correct FileELF template instance
+        //    based on the Ident pair. Once the File is created
+        //     we push the file to the vector of files already
+        //     created during parser's life.
+
+        if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
+            == llvm::ELF::ELFDATA2LSB) {
+          f.reset(new FileELF<llvm::support::little, false>(std::move(mb), ec));
+
+        } else if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
+            == llvm::ELF::ELFDATA2MSB) {
+          f.reset(new FileELF<llvm::support::big, false> (std::move(mb), ec));
+
+        } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
+            == llvm::ELF::ELFDATA2MSB) {
+          f.reset(new FileELF<llvm::support::big, true> (std::move(mb), ec));
+
+        } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
+            == llvm::ELF::ELFDATA2LSB) {
+          f.reset(new FileELF<llvm::support::little, true> (std::move(mb), ec));
+        }
+        if (!ec)
+          result.push_back(std::move(f));
+        break;
 
-    std::unique_ptr<File> f;
+      case llvm::sys::Archive_FileType:
+        ec = _readerArchive.parseFile(std::move(mb), result);
+        break;
 
-    if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
-        == llvm::ELF::ELFDATA2LSB) {
-      f.reset(new FileELF<llvm::support::little, false>(std::move(mb), ec));
-
-    } else if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
-        == llvm::ELF::ELFDATA2MSB) {
-      f.reset(new FileELF<llvm::support::big, false> (std::move(mb), ec));
-
-    } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
-        == llvm::ELF::ELFDATA2MSB) {
-      f.reset(new FileELF<llvm::support::big, true> (std::move(mb), ec));
-
-    } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
-        == llvm::ELF::ELFDATA2LSB) {
-      f.reset(new FileELF<llvm::support::little, true> (std::move(mb), ec));
+      default:
+        llvm_unreachable("not supported format");
+        break;
     }
 
     if (ec)
       return ec;
 
-    result.push_back(std::move(f));
     return error_code::success();
   }
+
+private:
+  const ReaderOptionsELF &_readerELFOptions;
+  ReaderOptionsArchive &_readerOptionsArchive;
+  ReaderArchive _readerArchive;
 };
 
 } // namespace anonymous
@@ -800,8 +830,9 @@
 ReaderOptionsELF::~ReaderOptionsELF() {
 }
 
-Reader *createReaderELF(const ReaderOptionsELF &options) {
-  return new ReaderELF(options);
+Reader *createReaderELF(const ReaderOptionsELF &options,
+                        ReaderOptionsArchive &optionsArchive) {
+  return new ReaderELF(options, optionsArchive);
 }
 
 } // namespace LLD

Added: lld/trunk/lib/ReaderWriter/ReaderArchive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ReaderArchive.cpp?rev=167854&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ReaderArchive.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ReaderArchive.cpp Tue Nov 13 12:39:10 2012
@@ -0,0 +1,160 @@
+//===- lib/ReaderWriter/ReaderArchive.cpp - Archive Library Reader--------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "lld/ReaderWriter/ReaderArchive.h"
+
+namespace lld 
+{
+// The FileArchive class represents an Archive Library file
+class FileArchive : public ArchiveLibraryFile {
+public:
+
+  virtual ~FileArchive() { }
+
+  /// Check if any member of the archive contains an Atom with the
+  /// specified name and return the File object for that member, or nullptr.
+  virtual const File *find(StringRef name, bool dataSymbolOnly) const {
+    error_code ec;  
+    llvm::object::Archive::child_iterator ci;
+
+    ci = _archive.get()->findSym(name);
+    if (ci == _archive->end_children()) 
+      return nullptr;
+    
+    if (dataSymbolOnly && (ec = isDataSymbol(ci->getBuffer(), name)))
+      return nullptr;
+    
+    std::vector<std::unique_ptr<File>> result;
+
+    if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
+                                           (ci->getBuffer()), result)))
+      return nullptr;
+
+    assert(result.size() == 1);
+
+    // give up the pointer so that this object no longer manages it
+    for (std::unique_ptr<File> &f : result) {
+      return f.release();
+    }
+
+    return nullptr;
+  }
+
+  virtual void addAtom(const Atom&) {
+    llvm_unreachable("cannot add atoms to archive files");
+  }
+
+  virtual const atom_collection<DefinedAtom> &defined() const {
+    return _definedAtoms;
+  }
+
+  virtual const atom_collection<UndefinedAtom> &undefined() const {
+    return _undefinedAtoms;
+  }
+
+  virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
+    return _sharedLibraryAtoms;
+  }
+
+  virtual const atom_collection<AbsoluteAtom> &absolute() const {
+    return _absoluteAtoms;
+  }
+
+protected:
+  error_code isDataSymbol(MemoryBuffer *mb, StringRef symbol) const
+  {
+    llvm::object::ObjectFile *obj = 
+                  llvm::object::ObjectFile::createObjectFile(mb);
+    error_code ec;
+    llvm::object::SymbolRef::Type symtype;
+    uint32_t symflags;
+    llvm::object::symbol_iterator ibegin = obj->begin_symbols();
+    llvm::object::symbol_iterator iend = obj->end_symbols();
+    StringRef symbolname;
+
+    for (llvm::object::symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
+      if (ec) return ec;
+      
+      // Get symbol name
+      if ((ec = (i->getName(symbolname)))) return ec;
+      
+      if (symbolname != symbol) 
+          continue;
+      
+      // Get symbol flags
+      if ((ec = (i->getFlags(symflags)))) return ec;
+      
+      if (symflags <= llvm::object::SymbolRef::SF_Undefined)
+          continue;
+      
+      // Get Symbol Type
+      if ((ec = (i->getType(symtype)))) return ec;
+      
+      if (symtype == llvm::object::SymbolRef::ST_Data) {
+        return error_code::success();
+      }
+    }
+    return llvm::object::object_error::parse_failed;
+  }
+
+private:
+  llvm::MemoryBuffer *_mb;
+  std::unique_ptr<llvm::object::Archive> _archive;
+  const ReaderOptionsArchive _options;
+  atom_collection_vector<DefinedAtom>       _definedAtoms;
+  atom_collection_vector<UndefinedAtom>     _undefinedAtoms;
+  atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+  atom_collection_vector<AbsoluteAtom>      _absoluteAtoms;
+
+public:
+  /// only subclasses of ArchiveLibraryFile can be instantiated 
+  explicit FileArchive(llvm::MemoryBuffer *mb, 
+                       const ReaderOptionsArchive &options, 
+                       error_code &ec)
+                      :ArchiveLibraryFile(mb->getBufferIdentifier()),
+                       _mb(mb),
+                       _archive(nullptr),
+                       _options(options) { 
+    auto *archive_obj = new llvm::object::Archive(mb, ec);
+    if (ec) 
+      return;
+    _archive.reset(archive_obj);
+  }
+}; // class FileArchive
+
+// Returns a vector of Files that are contained in the archive file 
+// pointed to by the MemoryBuffer
+error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
+		std::vector<std::unique_ptr<File>> &result) {
+  error_code ec;
+  
+  if (_options.isForceLoad())
+  {
+    _archive.reset(new llvm::object::Archive(mb.release(), ec));
+    if (ec)
+      return ec;
+    
+    for (auto mf = _archive->begin_children(), 
+              me = _archive->end_children(); mf != me; ++mf)
+    {
+    	if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
+                                             (mf->getBuffer()), result)))
+        return ec;
+    }
+  } else {
+    std::unique_ptr<File> f;
+    f.reset(new FileArchive(mb.release(), _options, ec));
+    if (ec)
+      return ec;
+
+    result.push_back(std::move(f));
+  }
+  return llvm::error_code::success();
+}
+
+} // namespace lld

Added: lld/trunk/test/elf/Inputs/libfnarchive.x86_64
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Inputs/libfnarchive.x86_64?rev=167854&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lld/trunk/test/elf/Inputs/libfnarchive.x86_64
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lld/trunk/test/elf/Inputs/mainobj.x86_64
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Inputs/mainobj.x86_64?rev=167854&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lld/trunk/test/elf/Inputs/mainobj.x86_64
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lld/trunk/test/elf/archive-elf-forceload.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/archive-elf-forceload.objtxt?rev=167854&view=auto
==============================================================================
--- lld/trunk/test/elf/archive-elf-forceload.objtxt (added)
+++ lld/trunk/test/elf/archive-elf-forceload.objtxt Tue Nov 13 12:39:10 2012
@@ -0,0 +1,48 @@
+# Tests the functionality of archive libraries reading 
+# and resolution 
+# Note: The binary files would not be required once we have support to generate
+# binary archives from textual(yaml) input
+#
+# Tests generated using the source files below
+# main file
+# int main()
+# {
+#   fn();
+#   return 0;
+# }
+#  
+# archive file
+# int fn()
+# {
+#   return 0;
+# }
+# 
+# int fn1()
+# {
+#   return 0;
+# }
+# gcc -c main.c fn.c fn1.c
+
+RUN: lld-core -reader ELF %p/Inputs/mainobj.x86_64 %p/Inputs/libfnarchive.x86_64 -force-load | FileCheck -check-prefix FORCELOAD %s
+
+FORCELOAD:    - name:              fn1
+FORCELOAD:      scope:             global
+FORCELOAD:      type:              code
+FORCELOAD:      section-choice:    custom-required
+FORCELOAD:      section-name:      .text
+FORCELOAD:      content:           [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
+FORCELOAD:    - name:              fn
+FORCELOAD:      scope:             global
+FORCELOAD:      type:              code
+FORCELOAD:      section-choice:    custom-required
+FORCELOAD:      section-name:      .text
+FORCELOAD:      content:           [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
+FORCELOAD:    - name:              main.c
+FORCELOAD:      definition:        absolute
+FORCELOAD:      value:             0x0
+FORCELOAD:    - name:              fn1.c
+FORCELOAD:      definition:        absolute
+FORCELOAD:      value:             0x0
+FORCELOAD:    - name:              fn.c
+FORCELOAD:      definition:        absolute
+FORCELOAD:      value:             0x0

Added: lld/trunk/test/elf/archive-elf.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/archive-elf.objtxt?rev=167854&view=auto
==============================================================================
--- lld/trunk/test/elf/archive-elf.objtxt (added)
+++ lld/trunk/test/elf/archive-elf.objtxt Tue Nov 13 12:39:10 2012
@@ -0,0 +1,39 @@
+# Tests the functionality of archive libraries reading 
+# and resolution 
+# Note: The binary files would not be required once we have support to generate
+# binary archives from textual(yaml) input
+#
+# Tests generated using the source files below
+# main file
+# int main()
+# {
+#   fn();
+#   return 0;
+# }
+#  
+# archive file
+# int fn()
+# {
+#   return 0;
+# }
+# 
+# int fn1()
+# {
+#   return 0;
+# }
+# gcc -c main.c fn.c fn1.c
+
+RUN: lld-core -reader ELF %p/Inputs/mainobj.x86_64 %p/Inputs/libfnarchive.x86_64 | FileCheck -check-prefix NOFORCELOAD %s
+
+NOFORCELOAD:    - name:              fn
+NOFORCELOAD:      scope:             global
+NOFORCELOAD:      type:              code
+NOFORCELOAD:      section-choice:    custom-required
+NOFORCELOAD:      section-name:      .text
+NOFORCELOAD:      content:           [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
+NOFORCELOAD:    - name:              main.c
+NOFORCELOAD:      definition:        absolute
+NOFORCELOAD:      value:             0x0
+NOFORCELOAD:    - name:              fn.c
+NOFORCELOAD:      definition:        absolute
+NOFORCELOAD:      value:             0x0

Modified: lld/trunk/tools/lld-core/lld-core.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/lld-core.cpp?rev=167854&r1=167853&r2=167854&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Tue Nov 13 12:39:10 2012
@@ -12,6 +12,7 @@
 #include "lld/Core/Pass.h"
 #include "lld/Core/Resolver.h"
 #include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderArchive.h"
 #include "lld/ReaderWriter/ReaderNative.h"
 #include "lld/ReaderWriter/ReaderYAML.h"
 #include "lld/ReaderWriter/ReaderELF.h"
@@ -76,6 +77,10 @@
           llvm::cl::desc("Any undefined symbols at end is an error"));
 
 llvm::cl::opt<bool> 
+cmdLineForceLoad("force-load", 
+          llvm::cl::desc("force load all members of the archive"));
+
+llvm::cl::opt<bool> 
 cmdLineCommonsSearchArchives("commons-search-archives", 
           llvm::cl::desc("Tentative definitions trigger archive search"));
 
@@ -214,6 +219,8 @@
   // create object to mange input files
   InputFiles inputFiles;
 
+  ReaderOptionsArchive readerOptionsArchive(cmdLineForceLoad);
+
   // read input files into in-memory File objects
 
   TestingReaderOptionsYAML  readerOptionsYAML;
@@ -231,7 +238,9 @@
       reader = createReaderPECOFF(lld::ReaderOptionsPECOFF());
       break;
     case readerELF:
-      reader = createReaderELF(lld::ReaderOptionsELF());
+      reader = createReaderELF(lld::ReaderOptionsELF(),
+                               readerOptionsArchive);
+
       break;
     default:
       reader = createReaderYAML(readerOptionsYAML);





More information about the llvm-commits mailing list