diff options
Diffstat (limited to 'tools/llvm-size/llvm-size.cpp')
-rw-r--r-- | tools/llvm-size/llvm-size.cpp | 343 |
1 files changed, 231 insertions, 112 deletions
diff --git a/tools/llvm-size/llvm-size.cpp b/tools/llvm-size/llvm-size.cpp index 069cc621f6157..c5966ead4b6c5 100644 --- a/tools/llvm-size/llvm-size.cpp +++ b/tools/llvm-size/llvm-size.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" @@ -49,13 +50,19 @@ static cl::opt<OutputFormatTy> OutputFormatShort( clEnumValN(darwin, "m", "Darwin -m format"), clEnumValEnd), cl::init(berkeley)); -static bool berkeleyHeaderPrinted = false; -static bool moreThanOneFile = false; +static bool BerkeleyHeaderPrinted = false; +static bool MoreThanOneFile = false; cl::opt<bool> DarwinLongFormat("l", cl::desc("When format is darwin, use long format " "to include addresses and offsets.")); +cl::opt<bool> + ELFCommons("common", + cl::desc("Print common symbols in the ELF file. When using " + "Berkely format, this is added to bss."), + cl::init(false)); + static cl::list<std::string> ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), cl::ZeroOrMore); @@ -77,20 +84,75 @@ RadixShort(cl::desc("Print size in radix:"), static cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"), cl::ZeroOrMore); +bool HadError = false; + static std::string ToolName; -/// @brief If ec is not success, print the error and return true. +/// If ec is not success, print the error and return true. static bool error(std::error_code ec) { if (!ec) return false; - outs() << ToolName << ": error reading file: " << ec.message() << ".\n"; - outs().flush(); + HadError = true; + errs() << ToolName << ": error reading file: " << ec.message() << ".\n"; + errs().flush(); + return true; +} + +static bool error(Twine Message) { + HadError = true; + errs() << ToolName << ": " << Message << ".\n"; + errs().flush(); return true; } -/// @brief Get the length of the string that represents @p num in Radix -/// including the leading 0x or 0 for hexadecimal and octal respectively. +// 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, + StringRef ArchitectureName = StringRef()) { + HadError = true; + errs() << ToolName << ": " << FileName; + + ErrorOr<StringRef> 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() << ")"; + + if (!ArchitectureName.empty()) + errs() << " (for architecture " << ArchitectureName << ") "; + + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(std::move(E), OS, ""); + OS.flush(); + errs() << " " << Buf << "\n"; +} + +// This version of error() prints the file name and which architecture slice it // is from, for example: "foo.o (for architecture i386)" after the ToolName +// before the error message. It sets HadError but returns allowing the code to +// move on to other architecture slices. +static void error(llvm::Error E, StringRef FileName, + StringRef ArchitectureName = StringRef()) { + HadError = true; + errs() << ToolName << ": " << FileName; + + if (!ArchitectureName.empty()) + errs() << " (for architecture " << ArchitectureName << ") "; + + 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) { APInt conv(64, num); SmallString<32> result; @@ -98,7 +160,7 @@ static size_t getNumLengthAsString(uint64_t num) { return result.size(); } -/// @brief Return the printing format for the Radix. +/// Return the printing format for the Radix. static const char *getRadixFmt() { switch (Radix) { case octal: @@ -111,11 +173,35 @@ static const char *getRadixFmt() { return nullptr; } -/// @brief Print the size of each Mach-O segment and section in @p MachO. +/// Remove unneeded ELF sections from calculation +static bool considerForSize(ObjectFile *Obj, SectionRef Section) { + if (!Obj->isELF()) + return true; + switch (static_cast<ELFSectionRef>(Section).getType()) { + case ELF::SHT_NULL: + case ELF::SHT_SYMTAB: + case ELF::SHT_STRTAB: + case ELF::SHT_REL: + case ELF::SHT_RELA: + return false; + } + return true; +} + +/// Total size of all ELF common symbols +static uint64_t getCommonSize(ObjectFile *Obj) { + uint64_t TotalCommons = 0; + for (auto &Sym : Obj->symbols()) + if (Obj->getSymbolFlags(Sym.getRawDataRefImpl()) & SymbolRef::SF_Common) + TotalCommons += Obj->getCommonSymbolSize(Sym.getRawDataRefImpl()); + return TotalCommons; +} + +/// Print the size of each Mach-O segment and section in @p MachO. /// /// This is when used when @c OutputFormat is darwin and produces the same /// output as darwin's size(1) -m output. -static void PrintDarwinSectionSizes(MachOObjectFile *MachO) { +static void printDarwinSectionSizes(MachOObjectFile *MachO) { std::string fmtbuf; raw_string_ostream fmt(fmtbuf); const char *radix_fmt = getRadixFmt(); @@ -155,10 +241,11 @@ static void PrintDarwinSectionSizes(MachOObjectFile *MachO) { outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n"; } else if (Load.C.cmd == MachO::LC_SEGMENT) { MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load); + uint64_t Seg_vmsize = Seg.vmsize; outs() << "Segment " << Seg.segname << ": " - << format(fmt.str().c_str(), Seg.vmsize); + << format(fmt.str().c_str(), Seg_vmsize); if (DarwinLongFormat) - outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr) << " fileoff " + outs() << " (vmaddr 0x" << format("%" PRIx32, Seg.vmaddr) << " fileoff " << Seg.fileoff << ")"; outs() << "\n"; total += Seg.vmsize; @@ -170,9 +257,10 @@ static void PrintDarwinSectionSizes(MachOObjectFile *MachO) { << format("%.16s", &Sec.sectname) << "): "; else outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": "; - outs() << format(fmt.str().c_str(), Sec.size); + uint64_t Sec_size = Sec.size; + outs() << format(fmt.str().c_str(), Sec_size); if (DarwinLongFormat) - outs() << " (addr 0x" << format("%" PRIx64, Sec.addr) << " offset " + outs() << " (addr 0x" << format("%" PRIx32, Sec.addr) << " offset " << Sec.offset << ")"; outs() << "\n"; sec_total += Sec.size; @@ -184,11 +272,11 @@ static void PrintDarwinSectionSizes(MachOObjectFile *MachO) { outs() << "total " << format(fmt.str().c_str(), total) << "\n"; } -/// @brief Print the summary sizes of the standard Mach-O segments in @p MachO. +/// Print the summary sizes of the standard Mach-O segments in @p MachO. /// /// This is when used when @c OutputFormat is berkeley with a Mach-O file and /// produces the same output as darwin's size(1) default output. -static void PrintDarwinSegmentSizes(MachOObjectFile *MachO) { +static void printDarwinSegmentSizes(MachOObjectFile *MachO) { uint64_t total_text = 0; uint64_t total_data = 0; uint64_t total_objc = 0; @@ -250,19 +338,19 @@ static void PrintDarwinSegmentSizes(MachOObjectFile *MachO) { } uint64_t total = total_text + total_data + total_objc + total_others; - if (!berkeleyHeaderPrinted) { + if (!BerkeleyHeaderPrinted) { outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n"; - berkeleyHeaderPrinted = true; + BerkeleyHeaderPrinted = true; } outs() << total_text << "\t" << total_data << "\t" << total_objc << "\t" << total_others << "\t" << total << "\t" << format("%" PRIx64, total) << "\t"; } -/// @brief Print the size of each section in @p Obj. +/// Print the size of each section in @p Obj. /// /// The format used is determined by @c OutputFormat and @c Radix. -static void PrintObjectSectionSizes(ObjectFile *Obj) { +static void printObjectSectionSizes(ObjectFile *Obj) { uint64_t total = 0; std::string fmtbuf; raw_string_ostream fmt(fmtbuf); @@ -273,11 +361,11 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) { // let it fall through to OutputFormat berkeley. MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj); if (OutputFormat == darwin && MachO) - PrintDarwinSectionSizes(MachO); + printDarwinSectionSizes(MachO); // If we have a MachOObjectFile and the OutputFormat is berkeley print as // darwin's default berkeley format for Mach-O files. else if (MachO && OutputFormat == berkeley) - PrintDarwinSegmentSizes(MachO); + printDarwinSegmentSizes(MachO); else if (OutputFormat == sysv) { // Run two passes over all sections. The first gets the lengths needed for // formatting the output. The second actually does the output. @@ -285,6 +373,8 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) { std::size_t max_size_len = strlen("size"); std::size_t max_addr_len = strlen("addr"); for (const SectionRef &Section : Obj->sections()) { + if (!considerForSize(Obj, Section)) + continue; uint64_t size = Section.getSize(); total += size; @@ -320,6 +410,8 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) { // Print each section. for (const SectionRef &Section : Obj->sections()) { + if (!considerForSize(Obj, Section)) + continue; StringRef name; if (error(Section.getName(name))) return; @@ -330,6 +422,13 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) { outs() << format(fmt.str().c_str(), namestr.c_str(), size, addr); } + if (ELFCommons) { + uint64_t CommonSize = getCommonSize(Obj); + total += CommonSize; + outs() << format(fmt.str().c_str(), std::string("*COM*").c_str(), + CommonSize, static_cast<uint64_t>(0)); + } + // Print total. fmtbuf.clear(); fmt << "%-" << max_name_len << "s " @@ -357,12 +456,15 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) { total_bss += size; } + if (ELFCommons) + total_bss += getCommonSize(Obj); + total = total_text + total_data + total_bss; - if (!berkeleyHeaderPrinted) { + if (!BerkeleyHeaderPrinted) { outs() << " text data bss " << (Radix == octal ? "oct" : "dec") << " hex filename\n"; - berkeleyHeaderPrinted = true; + BerkeleyHeaderPrinted = true; } // Print result. @@ -377,11 +479,11 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) { } } -/// @brief Checks to see if the @p o ObjectFile is a Mach-O file and if it is -/// and there is a list of architecture flags specified then check to -/// make sure this Mach-O file is one of those architectures or all -/// architectures was specificed. If not then an error is generated and -/// this routine returns false. Else it returns true. +/// Checks to see if the @p o ObjectFile is a Mach-O file and if it is and there +/// is a list of architecture flags specified then check to make sure this +/// Mach-O file is one of those architectures or all architectures was +/// specificed. If not then an error is generated and this routine returns +/// false. Else it returns true. static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) { if (isa<MachOObjectFile>(o) && !ArchAll && ArchFlags.size() != 0) { MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o); @@ -391,10 +493,10 @@ static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) { Triple T; if (MachO->is64Bit()) { H_64 = MachO->MachOObjectFile::getHeader64(); - T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype); + T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype); } else { H = MachO->MachOObjectFile::getHeader(); - T = MachOObjectFile::getArch(H.cputype, H.cpusubtype); + T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype); } unsigned i; for (i = 0; i < ArchFlags.size(); ++i) { @@ -411,32 +513,26 @@ static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) { return true; } -/// @brief Print the section sizes for @p file. If @p file is an archive, print -/// the section sizes for each archive member. -static void PrintFileSectionSizes(StringRef file) { +/// Print the section sizes for @p file. If @p file is an archive, print the +/// section sizes for each archive member. +static void printFileSectionSizes(StringRef file) { // Attempt to open the binary. - ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(file); - if (std::error_code EC = BinaryOrErr.getError()) { - errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; + Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(file); + if (!BinaryOrErr) { + error(errorToErrorCode(BinaryOrErr.takeError())); return; } Binary &Bin = *BinaryOrErr.get().getBinary(); if (Archive *a = dyn_cast<Archive>(&Bin)) { // This is an archive. Iterate over each member and display its sizes. - for (object::Archive::child_iterator i = a->child_begin(), - e = a->child_end(); - i != e; ++i) { - if (i->getError()) { - errs() << ToolName << ": " << file << ": " << i->getError().message() - << ".\n"; - exit(1); - } - auto &c = i->get(); - ErrorOr<std::unique_ptr<Binary>> ChildOrErr = c.getAsBinary(); - if (std::error_code EC = ChildOrErr.getError()) { - errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; + Error Err; + for (auto &C : a->children(Err)) { + Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + error(std::move(E), a->getFileName(), C); continue; } if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) { @@ -447,7 +543,7 @@ static void PrintFileSectionSizes(StringRef file) { outs() << o->getFileName() << " (ex " << a->getFileName() << "):\n"; else if (MachO && OutputFormat == darwin) outs() << a->getFileName() << "(" << o->getFileName() << "):\n"; - PrintObjectSectionSizes(o); + printObjectSectionSizes(o); if (OutputFormat == berkeley) { if (MachO) outs() << a->getFileName() << "(" << o->getFileName() << ")\n"; @@ -456,6 +552,8 @@ static void PrintFileSectionSizes(StringRef file) { } } } + if (Err) + error(std::move(Err), a->getFileName()); } else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { // If we have a list of architecture flags specified dump only those. @@ -469,43 +567,44 @@ static void PrintFileSectionSizes(StringRef file) { I != E; ++I) { if (ArchFlags[i] == I->getArchTypeName()) { ArchFound = true; - ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile(); + Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile(); if (UO) { if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) { MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o); if (OutputFormat == sysv) outs() << o->getFileName() << " :\n"; else if (MachO && OutputFormat == darwin) { - if (moreThanOneFile || ArchFlags.size() > 1) + if (MoreThanOneFile || ArchFlags.size() > 1) outs() << o->getFileName() << " (for architecture " << I->getArchTypeName() << "): \n"; } - PrintObjectSectionSizes(o); + printObjectSectionSizes(o); if (OutputFormat == berkeley) { - if (!MachO || moreThanOneFile || ArchFlags.size() > 1) + if (!MachO || MoreThanOneFile || ArchFlags.size() > 1) outs() << o->getFileName() << " (for architecture " << I->getArchTypeName() << ")"; outs() << "\n"; } } - } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = + } else if (auto E = isNotObjectErrorInvalidFileType( + UO.takeError())) { + error(std::move(E), file, ArchFlags.size() > 1 ? + StringRef(I->getArchTypeName()) : StringRef()); + return; + } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { std::unique_ptr<Archive> &UA = *AOrErr; // This is an archive. Iterate over each member and display its // sizes. - for (object::Archive::child_iterator i = UA->child_begin(), - e = UA->child_end(); - i != e; ++i) { - if (std::error_code EC = i->getError()) { - errs() << ToolName << ": " << file << ": " << EC.message() - << ".\n"; - exit(1); - } - auto &c = i->get(); - ErrorOr<std::unique_ptr<Binary>> ChildOrErr = c.getAsBinary(); - if (std::error_code EC = ChildOrErr.getError()) { - errs() << ToolName << ": " << file << ": " << EC.message() - << ".\n"; + Error Err; + for (auto &C : UA->children(Err)) { + Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType( + ChildOrErr.takeError())) + error(std::move(E), UA->getFileName(), C, + ArchFlags.size() > 1 ? + StringRef(I->getArchTypeName()) : StringRef()); continue; } if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) { @@ -518,7 +617,7 @@ static void PrintFileSectionSizes(StringRef file) { << ")" << " (for architecture " << I->getArchTypeName() << "):\n"; - PrintObjectSectionSizes(o); + printObjectSectionSizes(o); if (OutputFormat == berkeley) { if (MachO) { outs() << UA->getFileName() << "(" << o->getFileName() @@ -533,6 +632,13 @@ static void PrintFileSectionSizes(StringRef file) { } } } + if (Err) + error(std::move(Err), UA->getFileName()); + } else { + consumeError(AOrErr.takeError()); + error("Mach-O universal file: " + file + " for architecture " + + StringRef(I->getArchTypeName()) + + " is not a Mach-O file or an archive file"); } } } @@ -552,43 +658,40 @@ static void PrintFileSectionSizes(StringRef file) { E = UB->end_objects(); I != E; ++I) { if (HostArchName == I->getArchTypeName()) { - ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile(); + Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile(); if (UO) { if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) { MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o); if (OutputFormat == sysv) outs() << o->getFileName() << " :\n"; else if (MachO && OutputFormat == darwin) { - if (moreThanOneFile) + if (MoreThanOneFile) outs() << o->getFileName() << " (for architecture " << I->getArchTypeName() << "):\n"; } - PrintObjectSectionSizes(o); + printObjectSectionSizes(o); if (OutputFormat == berkeley) { - if (!MachO || moreThanOneFile) + if (!MachO || MoreThanOneFile) outs() << o->getFileName() << " (for architecture " << I->getArchTypeName() << ")"; outs() << "\n"; } } - } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = + } else if (auto E = isNotObjectErrorInvalidFileType(UO.takeError())) { + error(std::move(E), file); + return; + } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { std::unique_ptr<Archive> &UA = *AOrErr; // This is an archive. Iterate over each member and display its // sizes. - for (object::Archive::child_iterator i = UA->child_begin(), - e = UA->child_end(); - i != e; ++i) { - if (std::error_code EC = i->getError()) { - errs() << ToolName << ": " << file << ": " << EC.message() - << ".\n"; - exit(1); - } - auto &c = i->get(); - ErrorOr<std::unique_ptr<Binary>> ChildOrErr = c.getAsBinary(); - if (std::error_code EC = ChildOrErr.getError()) { - errs() << ToolName << ": " << file << ": " << EC.message() - << ".\n"; + Error Err; + for (auto &C : UA->children(Err)) { + Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType( + ChildOrErr.takeError())) + error(std::move(E), UA->getFileName(), C); continue; } if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) { @@ -600,7 +703,7 @@ static void PrintFileSectionSizes(StringRef file) { outs() << UA->getFileName() << "(" << o->getFileName() << ")" << " (for architecture " << I->getArchTypeName() << "):\n"; - PrintObjectSectionSizes(o); + printObjectSectionSizes(o); if (OutputFormat == berkeley) { if (MachO) outs() << UA->getFileName() << "(" << o->getFileName() @@ -611,6 +714,13 @@ static void PrintFileSectionSizes(StringRef file) { } } } + if (Err) + error(std::move(Err), UA->getFileName()); + } else { + consumeError(AOrErr.takeError()); + error("Mach-O universal file: " + file + " for architecture " + + StringRef(I->getArchTypeName()) + + " is not a Mach-O file or an archive file"); } return; } @@ -618,45 +728,46 @@ static void PrintFileSectionSizes(StringRef file) { } // Either all architectures have been specified or none have been specified // and this does not contain the host architecture so dump all the slices. - bool moreThanOneArch = UB->getNumberOfObjects() > 1; + bool MoreThanOneArch = UB->getNumberOfObjects() > 1; for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), E = UB->end_objects(); I != E; ++I) { - ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile(); + Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile(); if (UO) { if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) { MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o); if (OutputFormat == sysv) outs() << o->getFileName() << " :\n"; else if (MachO && OutputFormat == darwin) { - if (moreThanOneFile || moreThanOneArch) + if (MoreThanOneFile || MoreThanOneArch) outs() << o->getFileName() << " (for architecture " << I->getArchTypeName() << "):"; outs() << "\n"; } - PrintObjectSectionSizes(o); + printObjectSectionSizes(o); if (OutputFormat == berkeley) { - if (!MachO || moreThanOneFile || moreThanOneArch) + if (!MachO || MoreThanOneFile || MoreThanOneArch) outs() << o->getFileName() << " (for architecture " << I->getArchTypeName() << ")"; outs() << "\n"; } } - } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = + } else if (auto E = isNotObjectErrorInvalidFileType(UO.takeError())) { + error(std::move(E), file, MoreThanOneArch ? + StringRef(I->getArchTypeName()) : StringRef()); + return; + } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { std::unique_ptr<Archive> &UA = *AOrErr; // This is an archive. Iterate over each member and display its sizes. - for (object::Archive::child_iterator i = UA->child_begin(), - e = UA->child_end(); - i != e; ++i) { - if (std::error_code EC = i->getError()) { - errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; - exit(1); - } - auto &c = i->get(); - ErrorOr<std::unique_ptr<Binary>> ChildOrErr = c.getAsBinary(); - if (std::error_code EC = ChildOrErr.getError()) { - errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; + Error Err; + for (auto &C : UA->children(Err)) { + Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType( + ChildOrErr.takeError())) + error(std::move(E), UA->getFileName(), C, MoreThanOneArch ? + StringRef(I->getArchTypeName()) : StringRef()); continue; } if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) { @@ -667,7 +778,7 @@ static void PrintFileSectionSizes(StringRef file) { else if (MachO && OutputFormat == darwin) outs() << UA->getFileName() << "(" << o->getFileName() << ")" << " (for architecture " << I->getArchTypeName() << "):\n"; - PrintObjectSectionSizes(o); + printObjectSectionSizes(o); if (OutputFormat == berkeley) { if (MachO) outs() << UA->getFileName() << "(" << o->getFileName() << ")" @@ -679,6 +790,13 @@ static void PrintFileSectionSizes(StringRef file) { } } } + if (Err) + error(std::move(Err), UA->getFileName()); + } else { + consumeError(AOrErr.takeError()); + error("Mach-O universal file: " + file + " for architecture " + + StringRef(I->getArchTypeName()) + + " is not a Mach-O file or an archive file"); } } } else if (ObjectFile *o = dyn_cast<ObjectFile>(&Bin)) { @@ -686,10 +804,10 @@ static void PrintFileSectionSizes(StringRef file) { return; if (OutputFormat == sysv) outs() << o->getFileName() << " :\n"; - PrintObjectSectionSizes(o); + printObjectSectionSizes(o); if (OutputFormat == berkeley) { MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o); - if (!MachO || moreThanOneFile) + if (!MachO || MoreThanOneFile) outs() << o->getFileName(); outs() << "\n"; } @@ -704,7 +822,7 @@ static void PrintFileSectionSizes(StringRef file) { int main(int argc, char **argv) { // Print a stack trace if we signal out. - sys::PrintStackTraceOnErrorSignal(); + sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. @@ -731,9 +849,10 @@ int main(int argc, char **argv) { if (InputFilenames.size() == 0) InputFilenames.push_back("a.out"); - moreThanOneFile = InputFilenames.size() > 1; + MoreThanOneFile = InputFilenames.size() > 1; std::for_each(InputFilenames.begin(), InputFilenames.end(), - PrintFileSectionSizes); + printFileSectionSizes); - return 0; + if (HadError) + return 1; } |