[llvm-commits] [lld] Supporting archive libraries in lld

Nick Kledzik kledzik at apple.com
Tue Nov 6 12:52:59 PST 2012


On Nov 6, 2012, at 8:30 AM, Shankar Easwaran wrote:

> Hi Nick, Michael,
> 
> I incorporated your comments in lld / llvm for supporting reading archive libraries.
> 
> Please look at the new changes and let me know if you are ok to commit this in.
Shankar, 

Looking good!  Just a few tweaks left:



The class FileArchive should just be a class local to lib/ReaderWriter/ReaderArchive.cpp

> Index: include/lld/Core/FileArchive.h
> ===================================================================
> --- include/lld/Core/FileArchive.h	(revision 0)
> +++ include/lld/Core/FileArchive.h	(revision 0)
> @@ -0,0 +1,142 @@
> +//===- Core/FileArchive.h - Support static library -----------------------===//


> +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;
> +
> +    if ((ec = (_archive.get()->findSym(name, ci))))
> +        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;
> +
should be an assert() here that result.size() == 1, just to make sure parseFile() does not return multiple Files and we only use one of them.

> +    // give up the pointer so that this object no longer manages it
> +    for (std::unique_ptr<File> &f : result) {
> +      return f.release();
> +    }


> 


> Index: lib/ReaderWriter/ReaderArchive.cpp
> ===================================================================
> --- lib/ReaderWriter/ReaderArchive.cpp	(revision 0)
> +++ lib/ReaderWriter/ReaderArchive.cpp	(revision 0)
> @@ -0,0 +1,56 @@
> +//===- 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"
> +#include "lld/Core/FileArchive.h"
> +
> +namespace lld 
> +{
> +  // Returns a vector of Files that are contained in the archive file 
> +  error_code ReaderArchive::parseFile(StringRef path,
> +  		std::vector<std::unique_ptr<File>> &result) {
> +    error_code ec;
> +    OwningPtr<llvm::MemoryBuffer> opmb;
> +    if ((ec = llvm::MemoryBuffer::getFile(path, opmb)))
> +    	return ec;
> +
> +    std::unique_ptr<MemoryBuffer> mb(opmb.take());
> +    
> +    return parseFile(std::move(mb), result);
> +  }

ReaderArchive::parseFile() should not be needed.  The base class Reader defines readFile() which already does the above.

> 
>  
>  #include <map>
> @@ -751,20 +752,36 @@
>  
>  class ReaderELF: public Reader {
>  public:
> -  ReaderELF(const ReaderOptionsELF &) {}
> +  ReaderELF(const ReaderOptionsELF &readerELFOptions,
> +            ReaderOptionsArchive &readerOptionsArchive)
> +         : _readerELFOptions(readerELFOptions),
> +           _readerOptionsArchive(readerOptionsArchive)
> +  { 
> +    _readerOptionsArchive.setReader(this);
> +    _readerArchive.reset(new ReaderArchive(_readerOptionsArchive));
> +  }
> +
>    error_code parseFile(std::unique_ptr<MemoryBuffer> mb, std::vector<
>        std::unique_ptr<File> > &result) {
>  
>      std::pair<unsigned char, unsigned char> Ident =
>          llvm::object::getElfArchType(&*mb);
>      llvm::error_code ec;
> +
> +    llvm::sys::LLVMFileType fileType = 
> +          llvm::sys::IdentifyFileType(mb->getBufferStart(),
> +                                static_cast<unsigned>(mb->getBufferSize()));
> +
> +    std::unique_ptr<File> f;
> +
> +    switch (fileType) {
> +
> +      case llvm::sys::ELF_Relocatable_FileType:
>      //    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.
>  
> -    std::unique_ptr<File> f;
> -
>      if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
>          == llvm::ELF::ELFDATA2LSB) {
>        f.reset(new FileELF<llvm::support::little, false>(std::move(mb), ec));
> @@ -781,13 +798,29 @@
>          == llvm::ELF::ELFDATA2LSB) {
>        f.reset(new FileELF<llvm::support::little, true> (std::move(mb), ec));
>      }
The getElfArchType() is currently always called.  It only needs to be called if the filetype is ELF_Relocatable_FileType.


> +        if (!ec)
> +          result.push_back(std::move(f));
> +        break;
> +
> +      case llvm::sys::Archive_FileType:
> +        ec = _readerArchive->parseFile(std::move(mb), result);
> +        break;
> +
> +      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;
> +  std::unique_ptr<ReaderArchive> _readerArchive;
>  };
Since ReaderELF constructor always  takes a ReaderOptionsArchive parameter, you can make _readerArchive be an instance of ReaderArchive rather than an owned pointer to a ReaderArchive.

-Nick




More information about the llvm-commits mailing list