Index: lld/trunk/include/lld/Core/LinkingContext.h =================================================================== --- lld/trunk/include/lld/Core/LinkingContext.h +++ lld/trunk/include/lld/Core/LinkingContext.h @@ -307,6 +307,15 @@ // Derived classes may use it to change the list of input files. virtual void finalizeInputFiles() {} + /// Callback invoked for each file the Resolver decides we are going to load. + /// This can be used to update context state based on the file, and emit + /// errors for any differences between the context state and a loaded file. + /// For example, we can error if we try to load a file which is a different + /// arch from that being linked. + virtual std::error_code handleLoadedFile(File &file) { + return std::error_code(); + } + TaskGroup &getTaskGroup() { return _taskGroup; } /// @} Index: lld/trunk/include/lld/Core/Resolver.h =================================================================== --- lld/trunk/include/lld/Core/Resolver.h +++ lld/trunk/include/lld/Core/Resolver.h @@ -17,6 +17,7 @@ #include "lld/Core/SymbolTable.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/Support/ErrorOr.h" #include #include #include @@ -43,13 +44,13 @@ // Handle files, this adds atoms from the current file thats // being processed by the resolver - bool handleFile(File &); + ErrorOr handleFile(File &); // Handle an archive library file. - bool handleArchiveFile(File &); + ErrorOr handleArchiveFile(File &); // Handle a shared library file. - void handleSharedLibrary(File &); + std::error_code handleSharedLibrary(File &); /// @brief do work of merging and resolving and return list bool resolve(); @@ -57,7 +58,7 @@ std::unique_ptr resultFile() { return std::move(_result); } private: - typedef std::function UndefCallback; + typedef std::function(StringRef, bool)> UndefCallback; bool undefinesAdded(int begin, int end); File *getFile(int &index); @@ -73,7 +74,8 @@ bool checkUndefines(); void removeCoalescedAwayAtoms(); void checkDylibSymbolCollisions(); - void forEachUndefines(File &file, bool searchForOverrides, UndefCallback callback); + ErrorOr forEachUndefines(File &file, bool searchForOverrides, + UndefCallback callback); void markLive(const Atom *atom); void addAtoms(const std::vector&); Index: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h =================================================================== --- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h +++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h @@ -342,6 +342,8 @@ void finalizeInputFiles() override; + std::error_code handleLoadedFile(File &file) override; + bool customAtomOrderer(const DefinedAtom *left, const DefinedAtom *right, bool &leftBeforeRight) const; Index: lld/trunk/lib/Core/Resolver.cpp =================================================================== --- lld/trunk/lib/Core/Resolver.cpp +++ lld/trunk/lib/Core/Resolver.cpp @@ -29,7 +29,9 @@ namespace lld { -bool Resolver::handleFile(File &file) { +ErrorOr Resolver::handleFile(File &file) { + if (auto ec = _ctx.handleLoadedFile(file)) + return ec; bool undefAdded = false; for (const DefinedAtom *atom : file.defined()) doDefinedAtom(*atom); @@ -46,9 +48,10 @@ return undefAdded; } -void Resolver::forEachUndefines(File &file, bool searchForOverrides, - UndefCallback callback) { +ErrorOr Resolver::forEachUndefines(File &file, bool searchForOverrides, + UndefCallback callback) { size_t i = _undefineIndex[&file]; + bool undefAdded = false; do { for (; i < _undefines.size(); ++i) { StringRef undefName = _undefines[i]; @@ -60,7 +63,10 @@ _undefines[i] = ""; continue; } - callback(undefName, false); + auto undefAddedOrError = callback(undefName, false); + if (undefAddedOrError.getError()) + return undefAddedOrError; + undefAdded |= undefAddedOrError.get(); } if (!searchForOverrides) continue; @@ -69,43 +75,57 @@ // something that overrode this tentative, so always check. const Atom *curAtom = _symbolTable.findByName(tentDefName); assert(curAtom != nullptr); - if (const DefinedAtom *curDefAtom = dyn_cast(curAtom)) - if (curDefAtom->merge() == DefinedAtom::mergeAsTentative) - callback(tentDefName, true); + if (const DefinedAtom *curDefAtom = dyn_cast(curAtom)) { + if (curDefAtom->merge() == DefinedAtom::mergeAsTentative) { + auto undefAddedOrError = callback(tentDefName, true); + if (undefAddedOrError.getError()) + return undefAddedOrError; + undefAdded |= undefAddedOrError.get(); + } + } } } while (i < _undefines.size()); _undefineIndex[&file] = i; + return undefAdded; } -bool Resolver::handleArchiveFile(File &file) { +ErrorOr Resolver::handleArchiveFile(File &file) { ArchiveLibraryFile *archiveFile = cast(&file); bool searchForOverrides = _ctx.searchArchivesToOverrideTentativeDefinitions(); - bool undefAdded = false; - forEachUndefines(file, searchForOverrides, - [&](StringRef undefName, bool dataSymbolOnly) { + return forEachUndefines(file, searchForOverrides, + [&](StringRef undefName, + bool dataSymbolOnly)->ErrorOr { if (File *member = archiveFile->find(undefName, dataSymbolOnly)) { member->setOrdinal(_ctx.getNextOrdinalAndIncrement()); member->beforeLink(); updatePreloadArchiveMap(); - undefAdded = handleFile(*member) || undefAdded; + return handleFile(*member); } + return false; }); - return undefAdded; } -void Resolver::handleSharedLibrary(File &file) { +std::error_code Resolver::handleSharedLibrary(File &file) { // Add all the atoms from the shared library SharedLibraryFile *sharedLibrary = cast(&file); - handleFile(*sharedLibrary); + auto undefAddedOrError = handleFile(*sharedLibrary); + if (undefAddedOrError.getError()) + return undefAddedOrError.getError(); bool searchForOverrides = _ctx.searchSharedLibrariesToOverrideTentativeDefinitions(); - forEachUndefines(file, searchForOverrides, - [&](StringRef undefName, bool dataSymbolOnly) { + undefAddedOrError = forEachUndefines(file, searchForOverrides, + [&](StringRef undefName, + bool dataSymbolOnly)->ErrorOr { if (const SharedLibraryAtom *atom = sharedLibrary->exports(undefName, dataSymbolOnly)) doSharedLibraryAtom(*atom); + return false; }); + + if (undefAddedOrError.getError()) + return undefAddedOrError.getError(); + return std::error_code(); } bool Resolver::doUndefinedAtom(const UndefinedAtom &atom) { @@ -318,7 +338,7 @@ file->beforeLink(); updatePreloadArchiveMap(); switch (file->kind()) { - case File::kindObject: + case File::kindObject: { // The same file may be visited more than once if the file is // in --start-group and --end-group. Only library files should // be processed more than once. @@ -327,17 +347,35 @@ seen.insert(file); assert(!file->hasOrdinal()); file->setOrdinal(_ctx.getNextOrdinalAndIncrement()); - undefAdded = handleFile(*file); + auto undefAddedOrError = handleFile(*file); + if (undefAddedOrError.getError()) { + llvm::errs() << "Error in " + file->path() + << ": " << undefAddedOrError.getError().message() << "\n"; + return false; + } + undefAdded = undefAddedOrError.get(); break; - case File::kindArchiveLibrary: + } + case File::kindArchiveLibrary: { if (!file->hasOrdinal()) file->setOrdinal(_ctx.getNextOrdinalAndIncrement()); - undefAdded = handleArchiveFile(*file); + auto undefAddedOrError = handleArchiveFile(*file); + if (undefAddedOrError.getError()) { + llvm::errs() << "Error in " + file->path() + << ": " << undefAddedOrError.getError().message() << "\n"; + return false; + } + undefAdded = undefAddedOrError.get(); break; + } case File::kindSharedLibrary: if (!file->hasOrdinal()) file->setOrdinal(_ctx.getNextOrdinalAndIncrement()); - handleSharedLibrary(*file); + if (auto EC = handleSharedLibrary(*file)) { + llvm::errs() << "Error in " + file->path() + << ": " << EC.message() << "\n"; + return false; + } break; } _newUndefinesAdded[file] = undefAdded; Index: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp =================================================================== --- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp +++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp @@ -990,4 +990,8 @@ elements.push_back(llvm::make_unique(numLibs)); } +std::error_code MachOLinkingContext::handleLoadedFile(File &file) { + return std::error_code(); +} + } // end namespace lld