summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/FileArchive.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/FileArchive.cpp')
-rw-r--r--lib/ReaderWriter/FileArchive.cpp173
1 files changed, 45 insertions, 128 deletions
diff --git a/lib/ReaderWriter/FileArchive.cpp b/lib/ReaderWriter/FileArchive.cpp
index a09923f57d07..eb7e7fb1837b 100644
--- a/lib/ReaderWriter/FileArchive.cpp
+++ b/lib/ReaderWriter/FileArchive.cpp
@@ -8,27 +8,28 @@
//===----------------------------------------------------------------------===//
#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/File.h"
#include "lld/Core/LLVM.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Parallel.h"
-#include "lld/Driver/Driver.h"
-#include "llvm/ADT/Hashing.h"
+#include "lld/Core/Reader.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Archive.h"
-#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Object/Error.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
#include <memory>
-#include <mutex>
#include <set>
+#include <string>
+#include <system_error>
#include <unordered_map>
+#include <utility>
+#include <vector>
using llvm::object::Archive;
-using llvm::object::ObjectFile;
-using llvm::object::SymbolRef;
-using llvm::object::symbol_iterator;
-using llvm::object::object_error;
namespace lld {
@@ -44,39 +45,23 @@ public:
/// \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.
- File *find(StringRef name, bool dataSymbolOnly) override {
+ File *find(StringRef name) override {
auto member = _symbolMemberMap.find(name);
if (member == _symbolMemberMap.end())
return nullptr;
- Archive::child_iterator ci = member->second;
- if (ci->getError())
- return nullptr;
+ Archive::Child c = member->second;
// Don't return a member already returned
- ErrorOr<StringRef> buf = (*ci)->getBuffer();
+ ErrorOr<StringRef> buf = c.getBuffer();
if (!buf)
return nullptr;
const char *memberStart = buf->data();
if (_membersInstantiated.count(memberStart))
return nullptr;
- if (dataSymbolOnly && !isDataSymbol(ci, name))
- return nullptr;
-
_membersInstantiated.insert(memberStart);
- // Check if a file is preloaded.
- {
- std::lock_guard<std::mutex> lock(_mutex);
- auto it = _preloaded.find(memberStart);
- if (it != _preloaded.end()) {
- std::unique_ptr<Future<File *>> &p = it->second;
- Future<File *> *future = p.get();
- return future->get();
- }
- }
-
std::unique_ptr<File> result;
- if (instantiateMember(ci, result))
+ if (instantiateMember(c, result))
return nullptr;
File *file = result.get();
@@ -86,97 +71,68 @@ public:
return file;
}
- // Instantiate a member file containing a given symbol name.
- void preload(TaskGroup &group, StringRef name) override {
- auto member = _symbolMemberMap.find(name);
- if (member == _symbolMemberMap.end())
- return;
- Archive::child_iterator ci = member->second;
- if (ci->getError())
- return;
-
- // Do nothing if a member is already instantiated.
- ErrorOr<StringRef> buf = (*ci)->getBuffer();
- if (!buf)
- return;
- const char *memberStart = buf->data();
- if (_membersInstantiated.count(memberStart))
- return;
-
- std::lock_guard<std::mutex> lock(_mutex);
- if (_preloaded.find(memberStart) != _preloaded.end())
- return;
-
- // Instantiate the member
- auto *future = new Future<File *>();
- _preloaded[memberStart] = std::unique_ptr<Future<File *>>(future);
-
- group.spawn([=] {
- std::unique_ptr<File> result;
- std::error_code ec = instantiateMember(ci, result);
- future->set(ec ? nullptr : result.release());
- });
- }
-
/// \brief parse each member
std::error_code
parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
if (std::error_code ec = parse())
return ec;
- for (auto mf = _archive->child_begin(), me = _archive->child_end();
+ llvm::Error err;
+ for (auto mf = _archive->child_begin(err), me = _archive->child_end();
mf != me; ++mf) {
std::unique_ptr<File> file;
- if (std::error_code ec = instantiateMember(mf, file))
+ if (std::error_code ec = instantiateMember(*mf, file)) {
+ // err is Success (or we wouldn't be in the loop body) but we can't
+ // return without testing or consuming it.
+ consumeError(std::move(err));
return ec;
+ }
result.push_back(std::move(file));
}
+ if (err)
+ return errorToErrorCode(std::move(err));
return std::error_code();
}
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
return _noDefinedAtoms;
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _noUndefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _noSharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
- /// Returns a set of all defined symbols in the archive.
- std::set<StringRef> getDefinedSymbols() override {
- parse();
- std::set<StringRef> ret;
- for (const auto &e : _symbolMemberMap)
- ret.insert(e.first);
- return ret;
+ void clearAtoms() override {
+ _noDefinedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
}
protected:
std::error_code doParse() override {
// Make Archive object which will be owned by FileArchive object.
+ llvm::Error Err;
+ _archive.reset(new Archive(_mb->getMemBufferRef(), Err));
+ if (Err)
+ return errorToErrorCode(std::move(Err));
std::error_code ec;
- _archive.reset(new Archive(_mb->getMemBufferRef(), ec));
- if (ec)
- return ec;
if ((ec = buildTableOfContents()))
return ec;
return std::error_code();
}
private:
- std::error_code instantiateMember(Archive::child_iterator cOrErr,
+ std::error_code instantiateMember(Archive::Child member,
std::unique_ptr<File> &result) const {
- if (std::error_code ec = cOrErr->getError())
- return ec;
- Archive::child_iterator member = cOrErr->get();
- ErrorOr<llvm::MemoryBufferRef> mbOrErr = (*member)->getMemoryBufferRef();
+ ErrorOr<llvm::MemoryBufferRef> mbOrErr = member.getMemoryBufferRef();
if (std::error_code ec = mbOrErr.getError())
return ec;
llvm::MemoryBufferRef mb = mbOrErr.get();
@@ -204,64 +160,27 @@ private:
return std::error_code();
}
- // Parses the given memory buffer as an object file, and returns true
- // code if the given symbol is a data symbol. If the symbol is not a data
- // symbol or does not exist, returns false.
- bool isDataSymbol(Archive::child_iterator cOrErr, StringRef symbol) const {
- if (cOrErr->getError())
- return false;
- Archive::child_iterator member = cOrErr->get();
- ErrorOr<llvm::MemoryBufferRef> buf = (*member)->getMemoryBufferRef();
- if (buf.getError())
- return false;
- std::unique_ptr<MemoryBuffer> mb(MemoryBuffer::getMemBuffer(
- buf.get().getBuffer(), buf.get().getBufferIdentifier(), false));
-
- auto objOrErr(ObjectFile::createObjectFile(mb->getMemBufferRef()));
- if (objOrErr.getError())
- return false;
- std::unique_ptr<ObjectFile> obj = std::move(objOrErr.get());
-
- for (SymbolRef sym : obj->symbols()) {
- // Skip until we find the symbol.
- ErrorOr<StringRef> name = sym.getName();
- if (!name)
- return false;
- if (*name != symbol)
- continue;
- uint32_t flags = sym.getFlags();
- if (flags <= SymbolRef::SF_Undefined)
- continue;
-
- // Returns true if it's a data symbol.
- SymbolRef::Type type = sym.getType();
- if (type == SymbolRef::ST_Data)
- return true;
- }
- return false;
- }
-
std::error_code buildTableOfContents() {
DEBUG_WITH_TYPE("FileArchive", llvm::dbgs()
<< "Table of contents for archive '"
<< _archive->getFileName() << "':\n");
for (const Archive::Symbol &sym : _archive->symbols()) {
StringRef name = sym.getName();
- ErrorOr<Archive::child_iterator> memberOrErr = sym.getMember();
+ ErrorOr<Archive::Child> memberOrErr = sym.getMember();
if (std::error_code ec = memberOrErr.getError())
return ec;
- Archive::child_iterator member = memberOrErr.get();
+ Archive::Child member = memberOrErr.get();
DEBUG_WITH_TYPE("FileArchive",
llvm::dbgs()
<< llvm::format("0x%08llX ",
- (*member)->getBuffer()->data())
+ member.getBuffer()->data())
<< "'" << name << "'\n");
_symbolMemberMap.insert(std::make_pair(name, member));
}
return std::error_code();
}
- typedef std::unordered_map<StringRef, Archive::child_iterator> MemberMap;
+ typedef std::unordered_map<StringRef, Archive::Child> MemberMap;
typedef std::set<const char *> InstantiatedSet;
std::shared_ptr<MemoryBuffer> _mb;
@@ -271,9 +190,7 @@ private:
InstantiatedSet _membersInstantiated;
bool _logLoading;
std::vector<std::unique_ptr<MemoryBuffer>> _memberBuffers;
- std::map<const char *, std::unique_ptr<Future<File *>>> _preloaded;
- std::mutex _mutex;
- FileVector _filesReturned;
+ std::vector<std::unique_ptr<File>> _filesReturned;
};
class ArchiveReader : public Reader {
@@ -302,4 +219,4 @@ void Registry::addSupportArchives(bool logLoading) {
add(std::unique_ptr<Reader>(new ArchiveReader(logLoading)));
}
-} // end namespace lld
+} // namespace lld