Index: include/llvm/Object/Archive.h =================================================================== --- include/llvm/Object/Archive.h +++ include/llvm/Object/Archive.h @@ -66,7 +66,7 @@ bool isThinMember() const; public: - Child(const Archive *Parent, const char *Start); + Child(const Archive *Parent, const char *Start, std::error_code *EC); Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile); bool operator ==(const Child &other) const { @@ -75,7 +75,7 @@ } const Archive *getParent() const { return Parent; } - Child getNext() const; + ErrorOr getNext() const; ErrorOr getName() const; StringRef getRawName() const { return getHeader()->getName(); } @@ -91,9 +91,9 @@ return getHeader()->getAccessMode(); } /// \return the size of the archive member without the header or padding. - uint64_t getSize() const; + ErrorOr getSize() const; /// \return the size in the archive header for this member. - uint64_t getRawSize() const; + ErrorOr getRawSize() const; ErrorOr getBuffer() const; uint64_t getChildOffset() const; @@ -105,24 +105,32 @@ }; class child_iterator { - Child child; + ErrorOr child; public: - child_iterator() : child(Child(nullptr, nullptr)) {} + child_iterator() : child(Child(nullptr, nullptr, nullptr)) {} child_iterator(const Child &c) : child(c) {} - const Child *operator->() const { return &child; } - const Child &operator*() const { return child; } + child_iterator(std::error_code EC) : child(EC) {} + const ErrorOr *operator->() const { return &child; } + const ErrorOr &operator*() const { return child; } bool operator==(const child_iterator &other) const { - return child == other.child; + // We ignore error states so that comparisions with end() work, which + // allows range loops. + if (child.getError() || other.child.getError()) + return false; + return *child == *other.child; } bool operator!=(const child_iterator &other) const { return !(*this == other); } + // Code in loops with child_iterators must check for errors on each loop + // iteration. And if there is an error break out of the loop. child_iterator &operator++() { // Preincrement - child = child.getNext(); + assert(child && "Can't increment iterator with error"); + child = child->getNext(); return *this; } }; Index: include/llvm/Support/ErrorOr.h =================================================================== --- include/llvm/Support/ErrorOr.h +++ include/llvm/Support/ErrorOr.h @@ -91,6 +91,7 @@ typedef typename std::remove_reference::type &reference; typedef const typename std::remove_reference::type &const_reference; typedef typename std::remove_reference::type *pointer; + typedef const typename std::remove_reference::type *const_pointer; public: template @@ -183,10 +184,14 @@ return toPointer(getStorage()); } + const_pointer operator->() const { return toPointer(getStorage()); } + reference operator *() { return *getStorage(); } + const_reference operator*() const { return *getStorage(); } + private: template void copyConstruct(const ErrorOr &Other) { @@ -246,10 +251,14 @@ return Val; } + const_pointer toPointer(const_pointer Val) const { return Val; } + pointer toPointer(wrap *Val) { return &Val->get(); } + const_pointer toPointer(const wrap *Val) const { return &Val->get(); } + storage_type *getStorage() { assert(!HasError && "Cannot get value when an error exists!"); return reinterpret_cast(TStorage.buffer); Index: lib/ExecutionEngine/MCJIT/MCJIT.cpp =================================================================== --- lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -318,10 +318,12 @@ object::Archive *A = OB.getBinary(); // Look for our symbols in each Archive object::Archive::child_iterator ChildIt = A->findSym(Name); + if (std::error_code EC = ChildIt->getError()) + report_fatal_error(EC.message()); if (ChildIt != A->child_end()) { // FIXME: Support nested archives? ErrorOr> ChildBinOrErr = - ChildIt->getAsBinary(); + (*ChildIt)->getAsBinary(); if (ChildBinOrErr.getError()) continue; std::unique_ptr &ChildBin = ChildBinOrErr.get(); Index: lib/ExecutionEngine/Orc/OrcMCJITReplacement.h =================================================================== --- lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -252,10 +252,12 @@ object::Archive *A = OB.getBinary(); // Look for our symbols in each Archive object::Archive::child_iterator ChildIt = A->findSym(Name); + if (std::error_code EC = ChildIt->getError()) + report_fatal_error(EC.message()); if (ChildIt != A->child_end()) { // FIXME: Support nested archives? ErrorOr> ChildBinOrErr = - ChildIt->getAsBinary(); + (*ChildIt)->getAsBinary(); if (ChildBinOrErr.getError()) continue; std::unique_ptr &ChildBin = ChildBinOrErr.get(); Index: lib/Object/Archive.cpp =================================================================== --- lib/Object/Archive.cpp +++ lib/Object/Archive.cpp @@ -46,7 +46,7 @@ ErrorOr ArchiveMemberHeader::getSize() const { uint32_t Ret; if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, Ret)) - return object_error::parse_failed; + return object_error::parse_failed; // Size is not a decimal number. return Ret; } @@ -86,7 +86,8 @@ uint16_t StartOfFile) : Parent(Parent), Data(Data), StartOfFile(StartOfFile) {} -Archive::Child::Child(const Archive *Parent, const char *Start) +Archive::Child::Child(const Archive *Parent, const char *Start, + std::error_code *EC) : Parent(Parent) { if (!Start) return; @@ -94,7 +95,10 @@ uint64_t Size = sizeof(ArchiveMemberHeader); Data = StringRef(Start, Size); if (!isThinMember()) { - Size += getRawSize(); + ErrorOr MemberSize = getRawSize(); + if ((*EC = MemberSize.getError())) + return; + Size += MemberSize.get(); Data = StringRef(Start, Size); } @@ -110,20 +114,20 @@ } } -uint64_t Archive::Child::getSize() const { +ErrorOr Archive::Child::getSize() const { if (Parent->IsThin) { ErrorOr Size = getHeader()->getSize(); - if (Size.getError()) - return 0; + if (std::error_code EC = Size.getError()) + return EC; return Size.get(); } return Data.size() - StartOfFile; } -uint64_t Archive::Child::getRawSize() const { +ErrorOr Archive::Child::getRawSize() const { ErrorOr Size = getHeader()->getSize(); - if (Size.getError()) - return 0; + if (std::error_code EC = Size.getError()) + return EC; return Size.get(); } @@ -133,8 +137,12 @@ } ErrorOr Archive::Child::getBuffer() const { - if (!isThinMember()) - return StringRef(Data.data() + StartOfFile, getSize()); + if (!isThinMember()) { + ErrorOr Size = getSize(); + if (std::error_code EC = Size.getError()) + return EC; + return StringRef(Data.data() + StartOfFile, Size.get()); + } ErrorOr Name = getName(); if (std::error_code EC = Name.getError()) return EC; @@ -148,7 +156,7 @@ return Parent->ThinBuffers.back()->getBuffer(); } -Archive::Child Archive::Child::getNext() const { +ErrorOr Archive::Child::getNext() const { size_t SpaceToSkip = Data.size(); // If it's odd, add 1 to make it even. if (SpaceToSkip & 1) @@ -156,11 +164,19 @@ const char *NextLoc = Data.data() + SpaceToSkip; + // Check to see if this is at the end of the archive. + if (NextLoc == Parent->Data.getBufferEnd()) + return Child(Parent, nullptr, nullptr); + // Check to see if this is past the end of the archive. - if (NextLoc >= Parent->Data.getBufferEnd()) - return Child(Parent, nullptr); + if (NextLoc > Parent->Data.getBufferEnd()) + return object_error::parse_failed; - return Child(Parent, NextLoc); + std::error_code EC; + Child Ret(Parent, NextLoc, &EC); + if (EC) + return EC; + return Ret; } uint64_t Archive::Child::getChildOffset() const { @@ -255,15 +271,26 @@ } // Get the special members. - child_iterator i = child_begin(false); - child_iterator e = child_end(); + child_iterator I = child_begin(false); + if ((ec = I->getError())) + return; + child_iterator E = child_end(); - if (i == e) { + if (I == E) { ec = std::error_code(); return; } + const Child *C = &**I; - StringRef Name = i->getRawName(); + auto Increment = [&]() { + ++I; + if ((ec = I->getError())) + return true; + C = &**I; + return false; + }; + + StringRef Name = C->getRawName(); // Below is the pattern that is used to figure out the archive format // GNU archive format @@ -288,9 +315,11 @@ Format = K_BSD; // We know that the symbol table is not an external file, so we just assert // there is no error. - SymbolTable = *i->getBuffer(); - ++i; - setFirstRegular(*i); + SymbolTable = *C->getBuffer(); + if (Increment()) + return; + setFirstRegular(*C); + ec = std::error_code(); return; } @@ -298,7 +327,7 @@ if (Name.startswith("#1/")) { Format = K_BSD; // We know this is BSD, so getName will work since there is no string table. - ErrorOr NameOrErr = i->getName(); + ErrorOr NameOrErr = C->getName(); ec = NameOrErr.getError(); if (ec) return; @@ -306,10 +335,11 @@ if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") { // We know that the symbol table is not an external file, so we just // assert there is no error. - SymbolTable = *i->getBuffer(); - ++i; + SymbolTable = *C->getBuffer(); + if (Increment()) + return; } - setFirstRegular(*i); + setFirstRegular(*C); return; } @@ -322,32 +352,34 @@ if (Name == "/" || Name == "/SYM64/") { // We know that the symbol table is not an external file, so we just assert // there is no error. - SymbolTable = *i->getBuffer(); + SymbolTable = *C->getBuffer(); if (Name == "/SYM64/") has64SymTable = true; - ++i; - if (i == e) { + if (Increment()) + return; + if (I == E) { ec = std::error_code(); return; } - Name = i->getRawName(); + Name = C->getRawName(); } if (Name == "//") { Format = has64SymTable ? K_MIPS64 : K_GNU; // The string table is never an external member, so we just assert on the // ErrorOr. - StringTable = *i->getBuffer(); - ++i; - setFirstRegular(*i); + StringTable = *C->getBuffer(); + if (Increment()) + return; + setFirstRegular(*C); ec = std::error_code(); return; } if (Name[0] != '/') { Format = has64SymTable ? K_MIPS64 : K_GNU; - setFirstRegular(*i); + setFirstRegular(*C); ec = std::error_code(); return; } @@ -360,25 +392,28 @@ Format = K_COFF; // We know that the symbol table is not an external file, so we just assert // there is no error. - SymbolTable = *i->getBuffer(); + SymbolTable = *C->getBuffer(); + + if (Increment()) + return; - ++i; - if (i == e) { - setFirstRegular(*i); + if (I == E) { + setFirstRegular(*C); ec = std::error_code(); return; } - Name = i->getRawName(); + Name = C->getRawName(); if (Name == "//") { // The string table is never an external member, so we just assert on the // ErrorOr. - StringTable = *i->getBuffer(); - ++i; + StringTable = *C->getBuffer(); + if (Increment()) + return; } - setFirstRegular(*i); + setFirstRegular(*C); ec = std::error_code(); } @@ -390,12 +425,15 @@ return Child(this, FirstRegularData, FirstRegularStartOfFile); const char *Loc = Data.getBufferStart() + strlen(Magic); - Child c(this, Loc); - return c; + std::error_code EC; + Child c(this, Loc, &EC); + if (EC) + return child_iterator(EC); + return child_iterator(c); } Archive::child_iterator Archive::child_end() const { - return Child(this, nullptr); + return Child(this, nullptr, nullptr); } StringRef Archive::Symbol::getName() const { @@ -447,7 +485,11 @@ } const char *Loc = Parent->getData().begin() + Offset; - return Child(Parent, Loc); + std::error_code EC; + Child C(Parent, Loc, &EC); + if (EC) + return EC; + return C; } Archive::Symbol Archive::Symbol::getNext() const { Index: lib/Object/ArchiveWriter.cpp =================================================================== --- lib/Object/ArchiveWriter.cpp +++ lib/Object/ArchiveWriter.cpp @@ -39,7 +39,7 @@ : IsNewMember(false), Name(Name), OldMember(OldMember) {} NewArchiveIterator::NewArchiveIterator(StringRef FileName) - : IsNewMember(true), Name(FileName), OldMember(nullptr, nullptr) {} + : IsNewMember(true), Name(FileName), OldMember(nullptr, nullptr, nullptr) {} StringRef NewArchiveIterator::getName() const { return Name; } @@ -412,8 +412,11 @@ Status.getSize()); } else { const object::Archive::Child &OldMember = I.getOld(); + ErrorOr Size = OldMember.getSize(); + if (std::error_code EC = Size.getError()) + return std::make_pair("", EC); printMemberHeader(Out, Kind, Thin, I.getName(), StringMapIndexIter, - ModTime, UID, GID, Perms, OldMember.getSize()); + ModTime, UID, GID, Perms, Size.get()); } if (!Thin) Index: test/tools/llvm-objdump/Inputs/libbogus1.a =================================================================== --- test/tools/llvm-objdump/Inputs/libbogus1.a +++ test/tools/llvm-objdump/Inputs/libbogus1.a @@ -0,0 +1,13 @@ +! +hello.c 1444941273 124 0 100644 10% ` +#include +#include +int +main() +{ + printf("Hello World\n"); + return EXIT_SUCCESS; +} +foo.c 1444941645 124 0 100644 1% ` +void foo(void){} + Index: test/tools/llvm-objdump/Inputs/libbogus2.a =================================================================== --- test/tools/llvm-objdump/Inputs/libbogus2.a +++ test/tools/llvm-objdump/Inputs/libbogus2.a @@ -0,0 +1,13 @@ +! +hello.c 1444941273 124 0 100644 102 ` +#include +#include +int +main() +{ + printf("Hello World\n"); + return EXIT_SUCCESS; +} +foo.c 1444941645 124 0 100644 1% ` +void foo(void){} + Index: test/tools/llvm-objdump/Inputs/libbogus3.a =================================================================== --- test/tools/llvm-objdump/Inputs/libbogus3.a +++ test/tools/llvm-objdump/Inputs/libbogus3.a @@ -0,0 +1,16 @@ +! +hello.c 1444941273 124 0 100644 102 ` +#include +#include +int +main() +{ + printf("Hello World\n"); + return EXIT_SUCCESS; +} +foo.c 1444941645 124 0 100644 171 ` +void foo(void){} + +bar.c 1445026190 124 0 100644 17 ` +void foo(void){} + Index: test/tools/llvm-objdump/malformed-archives.test =================================================================== --- test/tools/llvm-objdump/malformed-archives.test +++ test/tools/llvm-objdump/malformed-archives.test @@ -0,0 +1,20 @@ +// These test checks that llvm-objdump will not crash with malformed Archive +// files. So the check line is not all that important but the bug fixes to +// make sure llvm-objdump is robust is what matters. +# RUN: llvm-objdump -macho -archive-headers \ +# RUN: %p/Inputs/libbogus1.a \ +# RUN: 2>&1 | FileCheck -check-prefix=bogus1 %s + +# bogus1: Invalid data was encountered while parsing the file + +# RUN: not llvm-objdump -macho -archive-headers \ +# RUN: %p/Inputs/libbogus2.a \ +# RUN: 2>&1 | FileCheck -check-prefix=bogus2 %s + +# bogus2: LLVM ERROR: Invalid data was encountered while parsing the file + +# RUN: not llvm-objdump -macho -archive-headers \ +# RUN: %p/Inputs/libbogus3.a \ +# RUN: 2>&1 | FileCheck -check-prefix=bogus3 %s + +# bogus3: LLVM ERROR: Invalid data was encountered while parsing the file Index: tools/dsymutil/BinaryHolder.cpp =================================================================== --- tools/dsymutil/BinaryHolder.cpp +++ tools/dsymutil/BinaryHolder.cpp @@ -109,7 +109,10 @@ Buffers.reserve(CurrentArchives.size()); for (const auto &CurrentArchive : CurrentArchives) { - for (const auto &Child : CurrentArchive->children()) { + for (auto ChildOrErr : CurrentArchive->children()) { + if (std::error_code Err = ChildOrErr.getError()) + return Err; + const auto &Child = *ChildOrErr; if (auto NameOrErr = Child.getName()) { if (*NameOrErr == Filename) { if (Timestamp != sys::TimeValue::PosixZeroTime() && Index: tools/llvm-ar/llvm-ar.cpp =================================================================== --- tools/llvm-ar/llvm-ar.cpp +++ tools/llvm-ar/llvm-ar.cpp @@ -338,7 +338,9 @@ printMode(Mode & 007); outs() << ' ' << C.getUID(); outs() << '/' << C.getGID(); - outs() << ' ' << format("%6llu", C.getSize()); + ErrorOr Size = C.getSize(); + failIfError(Size.getError()); + outs() << ' ' << format("%6llu", Size.get()); outs() << ' ' << C.getLastModified().str(); outs() << ' '; } @@ -403,7 +405,10 @@ } bool Filter = !Members.empty(); - for (const object::Archive::Child &C : OldArchive->children()) { + for (auto &ChildOrErr : OldArchive->children()) { + failIfError(ChildOrErr.getError()); + const object::Archive::Child &C = *ChildOrErr; + ErrorOr NameOrErr = C.getName(); failIfError(NameOrErr.getError()); StringRef Name = NameOrErr.get(); @@ -523,7 +528,9 @@ int InsertPos = -1; StringRef PosName = sys::path::filename(RelPos); if (OldArchive) { - for (auto &Child : OldArchive->children()) { + for (auto &ChildOrErr : OldArchive->children()) { + failIfError(ChildOrErr.getError()); + auto &Child = ChildOrErr.get(); int Pos = Ret.size(); ErrorOr NameOrErr = Child.getName(); failIfError(NameOrErr.getError()); @@ -726,7 +733,9 @@ failIfError(LibOrErr.getError(), "Could not parse library"); Archives.push_back(std::move(*LibOrErr)); object::Archive &Lib = *Archives.back(); - for (auto &Member : Lib.children()) { + for (auto &MemberOrErr : Lib.children()) { + failIfError(MemberOrErr.getError()); + auto &Member = MemberOrErr.get(); ErrorOr NameOrErr = Member.getName(); failIfError(NameOrErr.getError()); addMember(NewMembers, Member, *NameOrErr); Index: tools/llvm-cxxdump/llvm-cxxdump.cpp =================================================================== --- tools/llvm-cxxdump/llvm-cxxdump.cpp +++ tools/llvm-cxxdump/llvm-cxxdump.cpp @@ -482,7 +482,9 @@ } static void dumpArchive(const Archive *Arc) { - for (const Archive::Child &ArcC : Arc->children()) { + for (auto &ErrorOrChild : Arc->children()) { + error(ErrorOrChild.getError()); + const Archive::Child &ArcC = *ErrorOrChild; ErrorOr> ChildOrErr = ArcC.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { // Ignore non-object files. Index: tools/llvm-nm/llvm-nm.cpp =================================================================== --- tools/llvm-nm/llvm-nm.cpp +++ tools/llvm-nm/llvm-nm.cpp @@ -967,7 +967,10 @@ for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E; ++I) { - ErrorOr> ChildOrErr = I->getAsBinary(&Context); + if (error(I->getError())) + return; + auto &C = I->get(); + ErrorOr> ChildOrErr = C.getAsBinary(&Context); if (ChildOrErr.getError()) continue; if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { @@ -1022,8 +1025,11 @@ for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { + if (error(AI->getError())) + return; + auto &C = AI->get(); ErrorOr> ChildOrErr = - AI->getAsBinary(&Context); + C.getAsBinary(&Context); if (ChildOrErr.getError()) continue; if (SymbolicFile *O = @@ -1076,8 +1082,11 @@ for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { + if (error(AI->getError())) + return; + auto &C = AI->get(); ErrorOr> ChildOrErr = - AI->getAsBinary(&Context); + C.getAsBinary(&Context); if (ChildOrErr.getError()) continue; if (SymbolicFile *O = @@ -1125,8 +1134,10 @@ std::unique_ptr &A = *AOrErr; for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { - ErrorOr> ChildOrErr = - AI->getAsBinary(&Context); + if (error(AI->getError())) + return; + auto &C = AI->get(); + ErrorOr> ChildOrErr = C.getAsBinary(&Context); if (ChildOrErr.getError()) continue; if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { Index: tools/llvm-objdump/MachODump.cpp =================================================================== --- tools/llvm-objdump/MachODump.cpp +++ tools/llvm-objdump/MachODump.cpp @@ -1417,8 +1417,10 @@ outs() << format("%3d/", UID); unsigned GID = C.getGID(); outs() << format("%-3d ", GID); - uint64_t Size = C.getRawSize(); - outs() << format("%5" PRId64, Size) << " "; + ErrorOr Size = C.getRawSize(); + if (std::error_code EC = Size.getError()) + report_fatal_error(EC.message()); + outs() << format("%5" PRId64, Size.get()) << " "; StringRef RawLastModified = C.getRawLastModified(); if (verbose) { @@ -1454,7 +1456,9 @@ static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) { for (Archive::child_iterator I = A->child_begin(false), E = A->child_end(); I != E; ++I) { - Archive::Child C = *I; + if (std::error_code EC = I->getError()) + report_fatal_error(EC.message()); + const Archive::Child &C = **I; printArchiveChild(C, verbose, print_offset); } } @@ -1491,7 +1495,13 @@ printArchiveHeaders(A, !NonVerbose, ArchiveMemberOffsets); for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E; ++I) { - ErrorOr> ChildOrErr = I->getAsBinary(); + if (std::error_code EC = I->getError()) { + errs() << "llvm-objdump: '" << Filename << "': " << EC.message() + << ".\n"; + exit(1); + } + auto &C = I->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = dyn_cast(&*ChildOrErr.get())) { @@ -1539,7 +1549,13 @@ for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { - ErrorOr> ChildOrErr = AI->getAsBinary(); + if (std::error_code EC = AI->getError()) { + errs() << "llvm-objdump: '" << Filename + << "': " << EC.message() << ".\n"; + exit(1); + } + auto &C = AI->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = @@ -1581,7 +1597,13 @@ for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { - ErrorOr> ChildOrErr = AI->getAsBinary(); + if (std::error_code EC = AI->getError()) { + errs() << "llvm-objdump: '" << Filename << "': " << EC.message() + << ".\n"; + exit(1); + } + auto &C = AI->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = @@ -1617,7 +1639,13 @@ printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets); for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { - ErrorOr> ChildOrErr = AI->getAsBinary(); + if (std::error_code EC = AI->getError()) { + errs() << "llvm-objdump: '" << Filename << "': " << EC.message() + << ".\n"; + exit(1); + } + auto &C = AI->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -1537,7 +1537,10 @@ /// @brief Dump each object file in \a a; static void DumpArchive(const Archive *a) { - for (const Archive::Child &C : a->children()) { + for (auto &ErrorOrChild : a->children()) { + if (std::error_code EC = ErrorOrChild.getError()) + report_error(a->getFileName(), EC); + const Archive::Child &C = *ErrorOrChild; ErrorOr> ChildOrErr = C.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) if (EC != object_error::invalid_file_type) Index: tools/llvm-readobj/llvm-readobj.cpp =================================================================== --- tools/llvm-readobj/llvm-readobj.cpp +++ tools/llvm-readobj/llvm-readobj.cpp @@ -377,7 +377,10 @@ /// @brief Dumps each object file in \a Arc; static void dumpArchive(const Archive *Arc) { - for (const auto &Child : Arc->children()) { + for (auto &ErrorOrChild : Arc->children()) { + if (std::error_code EC = ErrorOrChild.getError()) + reportError(Arc->getFileName(), EC.message()); + const auto &Child = *ErrorOrChild; ErrorOr> ChildOrErr = Child.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { // Ignore non-object files. Index: tools/llvm-size/llvm-size.cpp =================================================================== --- tools/llvm-size/llvm-size.cpp +++ tools/llvm-size/llvm-size.cpp @@ -428,7 +428,13 @@ for (object::Archive::child_iterator i = a->child_begin(), e = a->child_end(); i != e; ++i) { - ErrorOr> ChildOrErr = i->getAsBinary(); + if (i->getError()) { + errs() << ToolName << ": " << file << ": " << i->getError().message() + << ".\n"; + exit(1); + } + auto &c = i->get(); + ErrorOr> ChildOrErr = c.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; continue; @@ -490,7 +496,13 @@ for (object::Archive::child_iterator i = UA->child_begin(), e = UA->child_end(); i != e; ++i) { - ErrorOr> ChildOrErr = i->getAsBinary(); + if (std::error_code EC = i->getError()) { + errs() << ToolName << ": " << file << ": " << EC.message() + << ".\n"; + exit(1); + } + auto &c = i->get(); + ErrorOr> ChildOrErr = c.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; @@ -567,7 +579,13 @@ for (object::Archive::child_iterator i = UA->child_begin(), e = UA->child_end(); i != e; ++i) { - ErrorOr> ChildOrErr = i->getAsBinary(); + if (std::error_code EC = i->getError()) { + errs() << ToolName << ": " << file << ": " << EC.message() + << ".\n"; + exit(1); + } + auto &c = i->get(); + ErrorOr> ChildOrErr = c.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; @@ -631,7 +649,12 @@ for (object::Archive::child_iterator i = UA->child_begin(), e = UA->child_end(); i != e; ++i) { - ErrorOr> ChildOrErr = i->getAsBinary(); + if (std::error_code EC = i->getError()) { + errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; + exit(1); + } + auto &c = i->get(); + ErrorOr> ChildOrErr = c.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; continue;