//===- 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 { /// \brief The FileArchive class represents an Archive Library file class FileArchive : public ArchiveLibraryFile { public: virtual ~FileArchive() { } /// \brief 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> result; if ((ec = _options.reader()->parseFile(std::unique_ptr (ci->getBuffer()), result))) return nullptr; assert(result.size() == 1); // give up the pointer so that this object no longer manages it return result[0].release(); } virtual void addAtom(const Atom&) { llvm_unreachable("cannot add atoms to archive files"); } virtual const atom_collection &defined() const { return _definedAtoms; } virtual const atom_collection &undefined() const { return _undefinedAtoms; } virtual const atom_collection &sharedLibrary() const { return _sharedLibraryAtoms; } virtual const atom_collection &absolute() const { return _absoluteAtoms; } protected: error_code isDataSymbol(MemoryBuffer *mb, StringRef symbol) const { std::unique_ptr 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: std::unique_ptr _archive; const ReaderOptionsArchive _options; atom_collection_vector _definedAtoms; atom_collection_vector _undefinedAtoms; atom_collection_vector _sharedLibraryAtoms; atom_collection_vector _absoluteAtoms; public: /// only subclasses of ArchiveLibraryFile can be instantiated explicit FileArchive(llvm::MemoryBuffer *mb, const ReaderOptionsArchive &options, error_code &ec) :ArchiveLibraryFile(mb->getBufferIdentifier()), _options(options) { std::unique_ptr archive_obj( new llvm::object::Archive(mb, ec)); if (ec) return; _archive.swap(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 mb, std::vector> &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 (mf->getBuffer()), result))) return ec; } } else { std::unique_ptr 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