diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h index dc2066dbe23e..585773472303 100644 --- a/llvm/include/llvm/Object/Archive.h +++ b/llvm/include/llvm/Object/Archive.h @@ -101,7 +101,7 @@ public: ErrorOr getMemoryBufferRef() const; - ErrorOr> + Expected> getAsBinary(LLVMContext *Context = nullptr) const; }; diff --git a/llvm/include/llvm/Object/Error.h b/llvm/include/llvm/Object/Error.h index 116b8234f491..c5c6f005e69e 100644 --- a/llvm/include/llvm/Object/Error.h +++ b/llvm/include/llvm/Object/Error.h @@ -81,4 +81,34 @@ template <> struct is_error_code_enum : std::true_type {}; } +namespace llvm { +namespace object { + +// isNotObjectErrorInvalidFileType() is used when looping through the children +// of an archive after calling getAsBinary() on the child and it returns an +// llvm::Error. In the cases we want to loop through the children and ignore the +// non-objects in the archive this is used to test the error to see if an +// error() function needs to called on the llvm::Error. +static inline llvm::Error isNotObjectErrorInvalidFileType(llvm::Error Err) { + if (auto Err2 = + handleErrors(std::move(Err), + [](std::unique_ptr M) { + // Try to handle 'M'. If successful, return a success value from + // the handler. + if (M->convertToErrorCode() == object_error::invalid_file_type) + return Error::success(); + + // We failed to handle 'M' - return it from the handler. + // This value will be passed back from catchErrors and + // wind up in Err2, where it will be returned from this function. + return Error(std::move(M)); + })) + return Err2; + return Err; +} + +} // end namespace object. + +} // end namespace llvm. + #endif diff --git a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 938b9fb7a545..55c7ff08d2e1 100644 --- a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -329,10 +329,13 @@ RuntimeDyld::SymbolInfo MCJIT::findSymbol(const std::string &Name, report_fatal_error(EC.message()); if (ChildIt != A->child_end()) { // FIXME: Support nested archives? - ErrorOr> ChildBinOrErr = + Expected> ChildBinOrErr = (*ChildIt)->getAsBinary(); - if (ChildBinOrErr.getError()) + if (!ChildBinOrErr) { + // TODO: Actually report errors helpfully. + consumeError(ChildBinOrErr.takeError()); continue; + } std::unique_ptr &ChildBin = ChildBinOrErr.get(); if (ChildBin->isObject()) { std::unique_ptr OF( diff --git a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 896c184d4400..db7c08fa8fc4 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -263,10 +263,13 @@ private: report_fatal_error(EC.message()); if (ChildIt != A->child_end()) { // FIXME: Support nested archives? - ErrorOr> ChildBinOrErr = + Expected> ChildBinOrErr = (*ChildIt)->getAsBinary(); - if (ChildBinOrErr.getError()) + if (!ChildBinOrErr) { + // TODO: Actually report errors helpfully. + consumeError(ChildBinOrErr.takeError()); continue; + } std::unique_ptr &ChildBin = ChildBinOrErr.get(); if (ChildBin->isObject()) { std::vector> ObjSet; diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp index 4ea1057520d2..21621c189cf9 100644 --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -228,6 +228,11 @@ ErrorOr Archive::Child::getName() const { if (name.substr(3).rtrim(' ').getAsInteger(10, name_size)) llvm_unreachable("Long name length is not an ingeter"); return Data.substr(sizeof(ArchiveMemberHeader), name_size).rtrim('\0'); + } else { + // It is not a long name so trim the blanks at the end of the name. + if (name[name.size() - 1] != '/') { + return name.rtrim(' '); + } } // It's a simple name. if (name[name.size() - 1] == '/') @@ -246,16 +251,16 @@ ErrorOr Archive::Child::getMemoryBufferRef() const { return MemoryBufferRef(*Buf, Name); } -ErrorOr> +Expected> Archive::Child::getAsBinary(LLVMContext *Context) const { ErrorOr BuffOrErr = getMemoryBufferRef(); if (std::error_code EC = BuffOrErr.getError()) - return EC; + return errorCodeToError(EC); auto BinaryOrErr = createBinary(BuffOrErr.get(), Context); if (BinaryOrErr) return std::move(*BinaryOrErr); - return errorToErrorCode(BinaryOrErr.takeError()); + return BinaryOrErr.takeError(); } ErrorOr> Archive::create(MemoryBufferRef Source) { diff --git a/llvm/test/Object/Inputs/macho-bad-archive1.a b/llvm/test/Object/Inputs/macho-bad-archive1.a new file mode 100644 index 000000000000..42ef43f59325 Binary files /dev/null and b/llvm/test/Object/Inputs/macho-bad-archive1.a differ diff --git a/llvm/test/Object/Inputs/macho-bad-archive2.a b/llvm/test/Object/Inputs/macho-bad-archive2.a new file mode 100644 index 000000000000..006822f00019 Binary files /dev/null and b/llvm/test/Object/Inputs/macho-bad-archive2.a differ diff --git a/llvm/test/Object/macho-invalid.test b/llvm/test/Object/macho-invalid.test index 35fc5c6d1cb7..55d9d25ab721 100644 --- a/llvm/test/Object/macho-invalid.test +++ b/llvm/test/Object/macho-invalid.test @@ -56,6 +56,10 @@ RUN: llvm-nm -pax %p/Inputs/macho-invalid-symbol-name-past-eof 2>&1 \ RUN: | FileCheck -check-prefix NAME-PAST-EOF-nm-pax %s NAME-PAST-EOF-nm-pax: 0000000000000000 64 00 0000 fe000002 bad string index +RUN: not llvm-objdump -t %p/Inputs/macho-bad-archive1.a 2>&1 \ +RUN: | FileCheck -check-prefix NAME-PAST-EOF-ARCHIVE %s +NAME-PAST-EOF-ARCHIVE: macho-bad-archive1.a(macho-invalid-symbol-name-past-eof) truncated or malformed object (bad string index: 4261412866 for symbol at index 0) + RUN: llvm-nm %p/Inputs/macho-invalid-section-index-getSectionRawName 2>&1 \ RUN: | FileCheck -check-prefix INVALID-SECTION-IDX-SYMBOL-SEC %s INVALID-SECTION-IDX-SYMBOL-SEC: 0000000100000000 S __mh_execute_header @@ -74,3 +78,6 @@ INVALID-HEADER: The file was not recognized as a valid object file RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho64-invalid-incomplete-segment-load-command 2>&1 | FileCheck -check-prefix INCOMPLETE-SEGMENT-LOADC %s INCOMPLETE-SEGMENT-LOADC: truncated or malformed object (load commands extend past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-bad-archive2.a 2>&1 | FileCheck -check-prefix INCOMPLETE-SEGMENT-LOADC-ARCHIVE %s +INCOMPLETE-SEGMENT-LOADC-ARCHIVE: macho-bad-archive2.a(macho64-invalid-incomplete-segment-load-command) truncated or malformed object (load commands extend past the end of the file) diff --git a/llvm/test/Object/nm-archive.test b/llvm/test/Object/nm-archive.test index 8f8cdbe9f08c..1a13c23f2450 100644 --- a/llvm/test/Object/nm-archive.test +++ b/llvm/test/Object/nm-archive.test @@ -55,9 +55,10 @@ RUN: llvm-nm %p/Inputs/archive-test.a-empty This archive has an unaligned member and a unknown format member. GNU AR is able to parse the unaligned member and warns about the member with -the unknown format. We should probably simply warn on both. For now just check -that we don't produce an error. -RUN: llvm-nm %p/Inputs/corrupt-archive.a +the unknown format. We should probably simply warn on both. For now we just +produce an error for the unknown format. +RUN: not llvm-nm %p/Inputs/corrupt-archive.a 2>&1 | FileCheck %s -check-prefix CORRUPT +CORRUPT: corrupt-archive.a(trivial-object-test2.elf-x86-64) Invalid data was encountered while parsing the file RUN: llvm-nm %p/Inputs/thin.a | FileCheck %s -check-prefix THIN diff --git a/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp b/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp index 206d65b6c20a..d4a290c786b2 100644 --- a/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp +++ b/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp @@ -485,11 +485,17 @@ static void dumpArchive(const Archive *Arc) { for (auto &ErrorOrChild : Arc->children()) { error(ErrorOrChild.getError()); const Archive::Child &ArcC = *ErrorOrChild; - ErrorOr> ChildOrErr = ArcC.getAsBinary(); - if (std::error_code EC = ChildOrErr.getError()) { + Expected> ChildOrErr = ArcC.getAsBinary(); + if (!ChildOrErr) { // Ignore non-object files. - if (EC != object_error::invalid_file_type) - reportError(Arc->getFileName(), EC.message()); + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) { + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(std::move(E), OS, ""); + OS.flush(); + reportError(Arc->getFileName(), Buf); + } + ChildOrErr.takeError(); continue; } diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index 4c0d7535ec21..a9234229062a 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -190,6 +190,29 @@ static bool error(std::error_code EC, Twine Path = Twine()) { return false; } +// This version of error() prints the archive name and member name, for example: +// "libx.a(foo.o)" after the ToolName before the error message. It sets +// HadError but returns allowing the code to move on to other archive members. +static void error(llvm::Error E, StringRef FileName, const Archive::Child &C) { + HadError = true; + errs() << ToolName << ": " << FileName; + + ErrorOr NameOrErr = C.getName(); + // TODO: if we have a error getting the name then it would be nice to print + // the index of which archive member this is and or its offset in the + // archive instead of "???" as the name. + if (NameOrErr.getError()) + errs() << "(" << "???" << ")"; + else + errs() << "(" << NameOrErr.get() << ")"; + + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(std::move(E), OS, ""); + OS.flush(); + errs() << " " << Buf << "\n"; +} + namespace { struct NMSymbol { uint64_t Address; @@ -1066,9 +1089,12 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { if (error(I->getError())) return; auto &C = I->get(); - ErrorOr> ChildOrErr = C.getAsBinary(&Context); - if (ChildOrErr.getError()) + Expected> ChildOrErr = C.getAsBinary(&Context); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + error(std::move(E), Filename, C); continue; + } if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { if (!checkMachOAndArchFlags(O, Filename)) return; @@ -1124,10 +1150,14 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { if (error(AI->getError())) return; auto &C = AI->get(); - ErrorOr> ChildOrErr = + Expected> ChildOrErr = C.getAsBinary(&Context); - if (ChildOrErr.getError()) + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType( + ChildOrErr.takeError())) + error(std::move(E), Filename, C); continue; + } if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { if (PrintFileName) { @@ -1181,10 +1211,14 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { if (error(AI->getError())) return; auto &C = AI->get(); - ErrorOr> ChildOrErr = + Expected> ChildOrErr = C.getAsBinary(&Context); - if (ChildOrErr.getError()) + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType( + ChildOrErr.takeError())) + error(std::move(E), Filename, C); continue; + } if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { if (PrintFileName) @@ -1233,9 +1267,13 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { if (error(AI->getError())) return; auto &C = AI->get(); - ErrorOr> ChildOrErr = C.getAsBinary(&Context); - if (ChildOrErr.getError()) + Expected> ChildOrErr = C.getAsBinary(&Context); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType( + ChildOrErr.takeError())) + error(std::move(E), Filename, C); continue; + } if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { if (PrintFileName) { ArchiveName = A->getFileName(); diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index 232f17f4cd0b..d94bf07f9e8c 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -1211,7 +1211,7 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, // If we are doing some processing here on the Mach-O file print the header // info. And don't print it otherwise like in the case of printing the // UniversalHeaders or ArchiveHeaders. - if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || + if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) { outs() << Filename; @@ -1244,8 +1244,10 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, PrintDylibs(MachOOF, false); if (DylibId) PrintDylibs(MachOOF, true); - if (SymbolTable) - PrintSymbolTable(MachOOF); + if (SymbolTable) { + StringRef ArchiveName = ArchiveMemberName == StringRef() ? "" : Filename; + PrintSymbolTable(MachOOF, ArchiveName); + } if (UnwindInfo) printMachOUnwindInfo(MachOOF); if (PrivateHeaders) { @@ -1552,9 +1554,12 @@ void llvm::ParseInputMachO(StringRef Filename) { if (std::error_code EC = I->getError()) report_error(Filename, EC); auto &C = I->get(); - ErrorOr> ChildOrErr = C.getAsBinary(); - if (ChildOrErr.getError()) + Expected> ChildOrErr = C.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + report_error(Filename, C, std::move(E)); continue; + } if (MachOObjectFile *O = dyn_cast(&*ChildOrErr.get())) { if (!checkMachOAndArchFlags(O, Filename)) return; @@ -1603,9 +1608,12 @@ void llvm::ParseInputMachO(StringRef Filename) { if (std::error_code EC = AI->getError()) report_error(Filename, EC); auto &C = AI->get(); - ErrorOr> ChildOrErr = C.getAsBinary(); - if (ChildOrErr.getError()) + Expected> ChildOrErr = C.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + report_error(Filename, C, std::move(E)); continue; + } if (MachOObjectFile *O = dyn_cast(&*ChildOrErr.get())) ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); @@ -1648,9 +1656,12 @@ void llvm::ParseInputMachO(StringRef Filename) { if (std::error_code EC = AI->getError()) report_error(Filename, EC); auto &C = AI->get(); - ErrorOr> ChildOrErr = C.getAsBinary(); - if (ChildOrErr.getError()) + Expected> ChildOrErr = C.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + report_error(Filename, C, std::move(E)); continue; + } if (MachOObjectFile *O = dyn_cast(&*ChildOrErr.get())) ProcessMachO(Filename, O, O->getFileName()); @@ -1687,9 +1698,12 @@ void llvm::ParseInputMachO(StringRef Filename) { if (std::error_code EC = AI->getError()) report_error(Filename, EC); auto &C = AI->get(); - ErrorOr> ChildOrErr = C.getAsBinary(); - if (ChildOrErr.getError()) + Expected> ChildOrErr = C.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + report_error(Filename, C, std::move(E)); continue; + } if (MachOObjectFile *O = dyn_cast(&*ChildOrErr.get())) { if (MachOObjectFile *MachOOF = dyn_cast(O)) diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index bd065986cb3e..dfdb4ba7d7c2 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -281,6 +281,36 @@ LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File, exit(1); } +LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef ArchiveName, + StringRef FileName, + llvm::Error E) { + assert(E); + errs() << ToolName << ": "; + if (ArchiveName != "") + errs() << ArchiveName << "(" << FileName << ")"; + else + errs() << FileName; + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(std::move(E), OS, ""); + OS.flush(); + errs() << " " << Buf; + exit(1); +} + +LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef ArchiveName, + const object::Archive::Child &C, + llvm::Error E) { + ErrorOr NameOrErr = C.getName(); + // TODO: if we have a error getting the name then it would be nice to print + // the index of which archive member this is and or its offset in the + // archive instead of "???" as the name. + if (NameOrErr.getError()) + llvm::report_error(ArchiveName, "???", std::move(E)); + else + llvm::report_error(ArchiveName, NameOrErr.get(), std::move(E)); +} + static const Target *getTarget(const ObjectFile *Obj = nullptr) { // Figure out the target triple. llvm::Triple TheTriple("unknown-unknown-unknown"); @@ -1346,7 +1376,7 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) { } } -void llvm::PrintSymbolTable(const ObjectFile *o) { +void llvm::PrintSymbolTable(const ObjectFile *o, StringRef ArchiveName) { outs() << "SYMBOL TABLE:\n"; if (const COFFObjectFile *coff = dyn_cast(o)) { @@ -1359,7 +1389,7 @@ void llvm::PrintSymbolTable(const ObjectFile *o) { uint64_t Address = *AddressOrError; Expected TypeOrError = Symbol.getType(); if (!TypeOrError) - report_error(o->getFileName(), TypeOrError.takeError()); + report_error(ArchiveName, o->getFileName(), TypeOrError.takeError()); SymbolRef::Type Type = *TypeOrError; uint32_t Flags = Symbol.getFlags(); Expected SectionOrErr = Symbol.getSection(); @@ -1371,7 +1401,7 @@ void llvm::PrintSymbolTable(const ObjectFile *o) { } else { Expected NameOrErr = Symbol.getName(); if (!NameOrErr) - report_error(o->getFileName(), NameOrErr.takeError()); + report_error(ArchiveName, o->getFileName(), NameOrErr.takeError()); Name = *NameOrErr; } @@ -1603,12 +1633,16 @@ static void printFirstPrivateFileHeader(const ObjectFile *o) { report_fatal_error("Invalid/Unsupported object file format"); } -static void DumpObject(const ObjectFile *o) { +static void DumpObject(const ObjectFile *o, const Archive *a = nullptr) { + StringRef ArchiveName = a != nullptr ? a->getFileName() : ""; // Avoid other output when using a raw option. if (!RawClangAST) { outs() << '\n'; - outs() << o->getFileName() - << ":\tfile format " << o->getFileFormatName() << "\n\n"; + if (a) + outs() << a->getFileName() << "(" << o->getFileName() << ")"; + else + outs() << o->getFileName(); + outs() << ":\tfile format " << o->getFileFormatName() << "\n\n"; } if (Disassemble) @@ -1620,7 +1654,7 @@ static void DumpObject(const ObjectFile *o) { if (SectionContents) PrintSectionContents(o); if (SymbolTable) - PrintSymbolTable(o); + PrintSymbolTable(o, ArchiveName); if (UnwindInfo) PrintUnwindInfo(o); if (PrivateHeaders) @@ -1654,12 +1688,14 @@ static void DumpArchive(const Archive *a) { 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) - report_error(a->getFileName(), EC); + Expected> ChildOrErr = C.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + report_error(a->getFileName(), C, std::move(E)); + continue; + } if (ObjectFile *o = dyn_cast(&*ChildOrErr.get())) - DumpObject(o); + DumpObject(o, a); else report_error(a->getFileName(), object_error::invalid_file_type); } diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h index 19b62ac459c7..51a600d9a047 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/llvm/tools/llvm-objdump/llvm-objdump.h @@ -13,6 +13,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Object/Archive.h" namespace llvm { class StringRef; @@ -21,6 +22,7 @@ namespace object { class COFFObjectFile; class MachOObjectFile; class ObjectFile; + class Archive; class RelocationRef; } @@ -84,9 +86,15 @@ void printRawClangAST(const object::ObjectFile *o); void PrintRelocations(const object::ObjectFile *o); void PrintSectionHeaders(const object::ObjectFile *o); void PrintSectionContents(const object::ObjectFile *o); -void PrintSymbolTable(const object::ObjectFile *o); +void PrintSymbolTable(const object::ObjectFile *o, StringRef ArchiveName); LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, std::error_code EC); LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, llvm::Error E); +LLVM_ATTRIBUTE_NORETURN void report_error(StringRef FileName, + StringRef ArchiveName, + llvm::Error E); +LLVM_ATTRIBUTE_NORETURN void report_error(StringRef ArchiveName, + const object::Archive::Child &C, + llvm::Error E); } // end namespace llvm diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index 0a48918cf383..1181a67dbcbf 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -421,14 +421,17 @@ static void dumpArchive(const Archive *Arc) { 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. - if (EC != object_error::invalid_file_type) - reportError(Arc->getFileName(), EC.message()); + Expected> ChildOrErr = Child.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) { + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(ChildOrErr.takeError(), OS, ""); + OS.flush(); + reportError(Arc->getFileName(), Buf); + } continue; } - if (ObjectFile *Obj = dyn_cast(&*ChildOrErr.get())) dumpObject(Obj); else diff --git a/llvm/tools/llvm-size/llvm-size.cpp b/llvm/tools/llvm-size/llvm-size.cpp index e3b487c388ff..351a6b1bfbd9 100644 --- a/llvm/tools/llvm-size/llvm-size.cpp +++ b/llvm/tools/llvm-size/llvm-size.cpp @@ -99,6 +99,29 @@ static bool error(std::error_code ec) { return true; } +// This version of error() prints the archive name and member name, for example: +// "libx.a(foo.o)" after the ToolName before the error message. It sets +// HadError but returns allowing the code to move on to other archive members. +static void error(llvm::Error E, StringRef FileName, const Archive::Child &C) { + HadError = true; + errs() << ToolName << ": " << FileName; + + ErrorOr NameOrErr = C.getName(); + // TODO: if we have a error getting the name then it would be nice to print + // the index of which archive member this is and or its offset in the + // archive instead of "???" as the name. + if (NameOrErr.getError()) + errs() << "(" << "???" << ")"; + else + errs() << "(" << NameOrErr.get() << ")"; + + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(std::move(E), OS, ""); + OS.flush(); + errs() << " " << Buf << "\n"; +} + /// Get the length of the string that represents @p num in Radix including the /// leading 0x or 0 for hexadecimal and octal respectively. static size_t getNumLengthAsString(uint64_t num) { @@ -480,9 +503,12 @@ static void printFileSectionSizes(StringRef file) { i != e; ++i) { if (error(i->getError())) exit(1); - ErrorOr> ChildOrErr = i->get().getAsBinary(); - if (error(ChildOrErr.getError())) + Expected> ChildOrErr = i->get().getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + error(std::move(E), a->getFileName(), i->get()); continue; + } if (ObjectFile *o = dyn_cast(&*ChildOrErr.get())) { MachOObjectFile *MachO = dyn_cast(o); if (!checkMachOAndArchFlags(o, file)) @@ -542,9 +568,13 @@ static void printFileSectionSizes(StringRef file) { i != e; ++i) { if (error(i->getError())) exit(1); - ErrorOr> ChildOrErr = i->get().getAsBinary(); - if (error(ChildOrErr.getError())) + Expected> ChildOrErr = + i->get().getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + error(std::move(E), a->getFileName(), i->get()); continue; + } if (ObjectFile *o = dyn_cast(&*ChildOrErr.get())) { MachOObjectFile *MachO = dyn_cast(o); if (OutputFormat == sysv) @@ -618,9 +648,13 @@ static void printFileSectionSizes(StringRef file) { i != e; ++i) { if (error(i->getError())) exit(1); - ErrorOr> ChildOrErr = i->get().getAsBinary(); - if (error(ChildOrErr.getError())) + Expected> ChildOrErr = + i->get().getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + error(std::move(E), a->getFileName(), i->get()); continue; + } if (ObjectFile *o = dyn_cast(&*ChildOrErr.get())) { MachOObjectFile *MachO = dyn_cast(o); if (OutputFormat == sysv) @@ -681,9 +715,12 @@ static void printFileSectionSizes(StringRef file) { i != e; ++i) { if (error(i->getError())) exit(1); - ErrorOr> ChildOrErr = i->get().getAsBinary(); - if (error(ChildOrErr.getError())) + Expected> ChildOrErr = i->get().getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + error(std::move(E), UA->getFileName(), i->get()); continue; + } if (ObjectFile *o = dyn_cast(&*ChildOrErr.get())) { MachOObjectFile *MachO = dyn_cast(o); if (OutputFormat == sysv) diff --git a/llvm/tools/sancov/sancov.cc b/llvm/tools/sancov/sancov.cc index 294b687debdf..891304d4f13d 100644 --- a/llvm/tools/sancov/sancov.cc +++ b/llvm/tools/sancov/sancov.cc @@ -414,8 +414,8 @@ visitObjectFiles(const object::Archive &A, for (auto &ErrorOrChild : A.children()) { FailIfError(ErrorOrChild); const object::Archive::Child &C = *ErrorOrChild; - ErrorOr> ChildOrErr = C.getAsBinary(); - FailIfError(ChildOrErr); + Expected> ChildOrErr = C.getAsBinary(); + FailIfError(errorToErrorCode(ChildOrErr.takeError())); if (auto *O = dyn_cast(&*ChildOrErr.get())) Fn(*O); else