xref: /aosp_15_r20/external/llvm/tools/llvm-size/llvm-size.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- llvm-size.cpp - Print the size of each object section ---*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This program is a utility that works like traditional Unix "size",
11*9880d681SAndroid Build Coastguard Worker // that is, it prints out the size of each section, and the total size of all
12*9880d681SAndroid Build Coastguard Worker // sections.
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker 
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/APInt.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/Archive.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/ELFObjectFile.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/MachO.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/MachOUniversal.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/ObjectFile.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Casting.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/PrettyStackTrace.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Signals.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
31*9880d681SAndroid Build Coastguard Worker #include <algorithm>
32*9880d681SAndroid Build Coastguard Worker #include <string>
33*9880d681SAndroid Build Coastguard Worker #include <system_error>
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker using namespace llvm;
36*9880d681SAndroid Build Coastguard Worker using namespace object;
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker enum OutputFormatTy { berkeley, sysv, darwin };
39*9880d681SAndroid Build Coastguard Worker static cl::opt<OutputFormatTy>
40*9880d681SAndroid Build Coastguard Worker OutputFormat("format", cl::desc("Specify output format"),
41*9880d681SAndroid Build Coastguard Worker              cl::values(clEnumVal(sysv, "System V format"),
42*9880d681SAndroid Build Coastguard Worker                         clEnumVal(berkeley, "Berkeley format"),
43*9880d681SAndroid Build Coastguard Worker                         clEnumVal(darwin, "Darwin -m format"), clEnumValEnd),
44*9880d681SAndroid Build Coastguard Worker              cl::init(berkeley));
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker static cl::opt<OutputFormatTy> OutputFormatShort(
47*9880d681SAndroid Build Coastguard Worker     cl::desc("Specify output format"),
48*9880d681SAndroid Build Coastguard Worker     cl::values(clEnumValN(sysv, "A", "System V format"),
49*9880d681SAndroid Build Coastguard Worker                clEnumValN(berkeley, "B", "Berkeley format"),
50*9880d681SAndroid Build Coastguard Worker                clEnumValN(darwin, "m", "Darwin -m format"), clEnumValEnd),
51*9880d681SAndroid Build Coastguard Worker     cl::init(berkeley));
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker static bool BerkeleyHeaderPrinted = false;
54*9880d681SAndroid Build Coastguard Worker static bool MoreThanOneFile = false;
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
57*9880d681SAndroid Build Coastguard Worker DarwinLongFormat("l", cl::desc("When format is darwin, use long format "
58*9880d681SAndroid Build Coastguard Worker                                "to include addresses and offsets."));
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker cl::opt<bool>
61*9880d681SAndroid Build Coastguard Worker     ELFCommons("common",
62*9880d681SAndroid Build Coastguard Worker                cl::desc("Print common symbols in the ELF file.  When using "
63*9880d681SAndroid Build Coastguard Worker                         "Berkely format, this is added to bss."),
64*9880d681SAndroid Build Coastguard Worker                cl::init(false));
65*9880d681SAndroid Build Coastguard Worker 
66*9880d681SAndroid Build Coastguard Worker static cl::list<std::string>
67*9880d681SAndroid Build Coastguard Worker ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
68*9880d681SAndroid Build Coastguard Worker           cl::ZeroOrMore);
69*9880d681SAndroid Build Coastguard Worker bool ArchAll = false;
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker enum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 };
72*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned int>
73*9880d681SAndroid Build Coastguard Worker Radix("-radix", cl::desc("Print size in radix. Only 8, 10, and 16 are valid"),
74*9880d681SAndroid Build Coastguard Worker       cl::init(decimal));
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker static cl::opt<RadixTy>
77*9880d681SAndroid Build Coastguard Worker RadixShort(cl::desc("Print size in radix:"),
78*9880d681SAndroid Build Coastguard Worker            cl::values(clEnumValN(octal, "o", "Print size in octal"),
79*9880d681SAndroid Build Coastguard Worker                       clEnumValN(decimal, "d", "Print size in decimal"),
80*9880d681SAndroid Build Coastguard Worker                       clEnumValN(hexadecimal, "x", "Print size in hexadecimal"),
81*9880d681SAndroid Build Coastguard Worker                       clEnumValEnd),
82*9880d681SAndroid Build Coastguard Worker            cl::init(decimal));
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker static cl::list<std::string>
85*9880d681SAndroid Build Coastguard Worker InputFilenames(cl::Positional, cl::desc("<input files>"), cl::ZeroOrMore);
86*9880d681SAndroid Build Coastguard Worker 
87*9880d681SAndroid Build Coastguard Worker bool HadError = false;
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker static std::string ToolName;
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker /// If ec is not success, print the error and return true.
error(std::error_code ec)92*9880d681SAndroid Build Coastguard Worker static bool error(std::error_code ec) {
93*9880d681SAndroid Build Coastguard Worker   if (!ec)
94*9880d681SAndroid Build Coastguard Worker     return false;
95*9880d681SAndroid Build Coastguard Worker 
96*9880d681SAndroid Build Coastguard Worker   HadError = true;
97*9880d681SAndroid Build Coastguard Worker   errs() << ToolName << ": error reading file: " << ec.message() << ".\n";
98*9880d681SAndroid Build Coastguard Worker   errs().flush();
99*9880d681SAndroid Build Coastguard Worker   return true;
100*9880d681SAndroid Build Coastguard Worker }
101*9880d681SAndroid Build Coastguard Worker 
error(Twine Message)102*9880d681SAndroid Build Coastguard Worker static bool error(Twine Message) {
103*9880d681SAndroid Build Coastguard Worker   HadError = true;
104*9880d681SAndroid Build Coastguard Worker   errs() << ToolName << ": " << Message << ".\n";
105*9880d681SAndroid Build Coastguard Worker   errs().flush();
106*9880d681SAndroid Build Coastguard Worker   return true;
107*9880d681SAndroid Build Coastguard Worker }
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker // This version of error() prints the archive name and member name, for example:
110*9880d681SAndroid Build Coastguard Worker // "libx.a(foo.o)" after the ToolName before the error message.  It sets
111*9880d681SAndroid Build Coastguard Worker // HadError but returns allowing the code to move on to other archive members.
error(llvm::Error E,StringRef FileName,const Archive::Child & C,StringRef ArchitectureName=StringRef ())112*9880d681SAndroid Build Coastguard Worker static void error(llvm::Error E, StringRef FileName, const Archive::Child &C,
113*9880d681SAndroid Build Coastguard Worker                   StringRef ArchitectureName = StringRef()) {
114*9880d681SAndroid Build Coastguard Worker   HadError = true;
115*9880d681SAndroid Build Coastguard Worker   errs() << ToolName << ": " << FileName;
116*9880d681SAndroid Build Coastguard Worker 
117*9880d681SAndroid Build Coastguard Worker   ErrorOr<StringRef> NameOrErr = C.getName();
118*9880d681SAndroid Build Coastguard Worker   // TODO: if we have a error getting the name then it would be nice to print
119*9880d681SAndroid Build Coastguard Worker   // the index of which archive member this is and or its offset in the
120*9880d681SAndroid Build Coastguard Worker   // archive instead of "???" as the name.
121*9880d681SAndroid Build Coastguard Worker   if (NameOrErr.getError())
122*9880d681SAndroid Build Coastguard Worker     errs() << "(" << "???" << ")";
123*9880d681SAndroid Build Coastguard Worker   else
124*9880d681SAndroid Build Coastguard Worker     errs() << "(" << NameOrErr.get() << ")";
125*9880d681SAndroid Build Coastguard Worker 
126*9880d681SAndroid Build Coastguard Worker   if (!ArchitectureName.empty())
127*9880d681SAndroid Build Coastguard Worker     errs() << " (for architecture " << ArchitectureName << ") ";
128*9880d681SAndroid Build Coastguard Worker 
129*9880d681SAndroid Build Coastguard Worker   std::string Buf;
130*9880d681SAndroid Build Coastguard Worker   raw_string_ostream OS(Buf);
131*9880d681SAndroid Build Coastguard Worker   logAllUnhandledErrors(std::move(E), OS, "");
132*9880d681SAndroid Build Coastguard Worker   OS.flush();
133*9880d681SAndroid Build Coastguard Worker   errs() << " " << Buf << "\n";
134*9880d681SAndroid Build Coastguard Worker }
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker // 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
137*9880d681SAndroid Build Coastguard Worker // before the error message.  It sets HadError but returns allowing the code to
138*9880d681SAndroid Build Coastguard Worker // move on to other architecture slices.
error(llvm::Error E,StringRef FileName,StringRef ArchitectureName=StringRef ())139*9880d681SAndroid Build Coastguard Worker static void error(llvm::Error E, StringRef FileName,
140*9880d681SAndroid Build Coastguard Worker                   StringRef ArchitectureName = StringRef()) {
141*9880d681SAndroid Build Coastguard Worker   HadError = true;
142*9880d681SAndroid Build Coastguard Worker   errs() << ToolName << ": " << FileName;
143*9880d681SAndroid Build Coastguard Worker 
144*9880d681SAndroid Build Coastguard Worker   if (!ArchitectureName.empty())
145*9880d681SAndroid Build Coastguard Worker     errs() << " (for architecture " << ArchitectureName << ") ";
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker   std::string Buf;
148*9880d681SAndroid Build Coastguard Worker   raw_string_ostream OS(Buf);
149*9880d681SAndroid Build Coastguard Worker   logAllUnhandledErrors(std::move(E), OS, "");
150*9880d681SAndroid Build Coastguard Worker   OS.flush();
151*9880d681SAndroid Build Coastguard Worker   errs() << " " << Buf << "\n";
152*9880d681SAndroid Build Coastguard Worker }
153*9880d681SAndroid Build Coastguard Worker 
154*9880d681SAndroid Build Coastguard Worker /// Get the length of the string that represents @p num in Radix including the
155*9880d681SAndroid Build Coastguard Worker /// leading 0x or 0 for hexadecimal and octal respectively.
getNumLengthAsString(uint64_t num)156*9880d681SAndroid Build Coastguard Worker static size_t getNumLengthAsString(uint64_t num) {
157*9880d681SAndroid Build Coastguard Worker   APInt conv(64, num);
158*9880d681SAndroid Build Coastguard Worker   SmallString<32> result;
159*9880d681SAndroid Build Coastguard Worker   conv.toString(result, Radix, false, true);
160*9880d681SAndroid Build Coastguard Worker   return result.size();
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker 
163*9880d681SAndroid Build Coastguard Worker /// Return the printing format for the Radix.
getRadixFmt()164*9880d681SAndroid Build Coastguard Worker static const char *getRadixFmt() {
165*9880d681SAndroid Build Coastguard Worker   switch (Radix) {
166*9880d681SAndroid Build Coastguard Worker   case octal:
167*9880d681SAndroid Build Coastguard Worker     return PRIo64;
168*9880d681SAndroid Build Coastguard Worker   case decimal:
169*9880d681SAndroid Build Coastguard Worker     return PRIu64;
170*9880d681SAndroid Build Coastguard Worker   case hexadecimal:
171*9880d681SAndroid Build Coastguard Worker     return PRIx64;
172*9880d681SAndroid Build Coastguard Worker   }
173*9880d681SAndroid Build Coastguard Worker   return nullptr;
174*9880d681SAndroid Build Coastguard Worker }
175*9880d681SAndroid Build Coastguard Worker 
176*9880d681SAndroid Build Coastguard Worker /// Remove unneeded ELF sections from calculation
considerForSize(ObjectFile * Obj,SectionRef Section)177*9880d681SAndroid Build Coastguard Worker static bool considerForSize(ObjectFile *Obj, SectionRef Section) {
178*9880d681SAndroid Build Coastguard Worker   if (!Obj->isELF())
179*9880d681SAndroid Build Coastguard Worker     return true;
180*9880d681SAndroid Build Coastguard Worker   switch (static_cast<ELFSectionRef>(Section).getType()) {
181*9880d681SAndroid Build Coastguard Worker   case ELF::SHT_NULL:
182*9880d681SAndroid Build Coastguard Worker   case ELF::SHT_SYMTAB:
183*9880d681SAndroid Build Coastguard Worker   case ELF::SHT_STRTAB:
184*9880d681SAndroid Build Coastguard Worker   case ELF::SHT_REL:
185*9880d681SAndroid Build Coastguard Worker   case ELF::SHT_RELA:
186*9880d681SAndroid Build Coastguard Worker     return false;
187*9880d681SAndroid Build Coastguard Worker   }
188*9880d681SAndroid Build Coastguard Worker   return true;
189*9880d681SAndroid Build Coastguard Worker }
190*9880d681SAndroid Build Coastguard Worker 
191*9880d681SAndroid Build Coastguard Worker /// Total size of all ELF common symbols
getCommonSize(ObjectFile * Obj)192*9880d681SAndroid Build Coastguard Worker static uint64_t getCommonSize(ObjectFile *Obj) {
193*9880d681SAndroid Build Coastguard Worker   uint64_t TotalCommons = 0;
194*9880d681SAndroid Build Coastguard Worker   for (auto &Sym : Obj->symbols())
195*9880d681SAndroid Build Coastguard Worker     if (Obj->getSymbolFlags(Sym.getRawDataRefImpl()) & SymbolRef::SF_Common)
196*9880d681SAndroid Build Coastguard Worker       TotalCommons += Obj->getCommonSymbolSize(Sym.getRawDataRefImpl());
197*9880d681SAndroid Build Coastguard Worker   return TotalCommons;
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker 
200*9880d681SAndroid Build Coastguard Worker /// Print the size of each Mach-O segment and section in @p MachO.
201*9880d681SAndroid Build Coastguard Worker ///
202*9880d681SAndroid Build Coastguard Worker /// This is when used when @c OutputFormat is darwin and produces the same
203*9880d681SAndroid Build Coastguard Worker /// output as darwin's size(1) -m output.
printDarwinSectionSizes(MachOObjectFile * MachO)204*9880d681SAndroid Build Coastguard Worker static void printDarwinSectionSizes(MachOObjectFile *MachO) {
205*9880d681SAndroid Build Coastguard Worker   std::string fmtbuf;
206*9880d681SAndroid Build Coastguard Worker   raw_string_ostream fmt(fmtbuf);
207*9880d681SAndroid Build Coastguard Worker   const char *radix_fmt = getRadixFmt();
208*9880d681SAndroid Build Coastguard Worker   if (Radix == hexadecimal)
209*9880d681SAndroid Build Coastguard Worker     fmt << "0x";
210*9880d681SAndroid Build Coastguard Worker   fmt << "%" << radix_fmt;
211*9880d681SAndroid Build Coastguard Worker 
212*9880d681SAndroid Build Coastguard Worker   uint32_t Filetype = MachO->getHeader().filetype;
213*9880d681SAndroid Build Coastguard Worker 
214*9880d681SAndroid Build Coastguard Worker   uint64_t total = 0;
215*9880d681SAndroid Build Coastguard Worker   for (const auto &Load : MachO->load_commands()) {
216*9880d681SAndroid Build Coastguard Worker     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
217*9880d681SAndroid Build Coastguard Worker       MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
218*9880d681SAndroid Build Coastguard Worker       outs() << "Segment " << Seg.segname << ": "
219*9880d681SAndroid Build Coastguard Worker              << format(fmt.str().c_str(), Seg.vmsize);
220*9880d681SAndroid Build Coastguard Worker       if (DarwinLongFormat)
221*9880d681SAndroid Build Coastguard Worker         outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr) << " fileoff "
222*9880d681SAndroid Build Coastguard Worker                << Seg.fileoff << ")";
223*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
224*9880d681SAndroid Build Coastguard Worker       total += Seg.vmsize;
225*9880d681SAndroid Build Coastguard Worker       uint64_t sec_total = 0;
226*9880d681SAndroid Build Coastguard Worker       for (unsigned J = 0; J < Seg.nsects; ++J) {
227*9880d681SAndroid Build Coastguard Worker         MachO::section_64 Sec = MachO->getSection64(Load, J);
228*9880d681SAndroid Build Coastguard Worker         if (Filetype == MachO::MH_OBJECT)
229*9880d681SAndroid Build Coastguard Worker           outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
230*9880d681SAndroid Build Coastguard Worker                  << format("%.16s", &Sec.sectname) << "): ";
231*9880d681SAndroid Build Coastguard Worker         else
232*9880d681SAndroid Build Coastguard Worker           outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
233*9880d681SAndroid Build Coastguard Worker         outs() << format(fmt.str().c_str(), Sec.size);
234*9880d681SAndroid Build Coastguard Worker         if (DarwinLongFormat)
235*9880d681SAndroid Build Coastguard Worker           outs() << " (addr 0x" << format("%" PRIx64, Sec.addr) << " offset "
236*9880d681SAndroid Build Coastguard Worker                  << Sec.offset << ")";
237*9880d681SAndroid Build Coastguard Worker         outs() << "\n";
238*9880d681SAndroid Build Coastguard Worker         sec_total += Sec.size;
239*9880d681SAndroid Build Coastguard Worker       }
240*9880d681SAndroid Build Coastguard Worker       if (Seg.nsects != 0)
241*9880d681SAndroid Build Coastguard Worker         outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
242*9880d681SAndroid Build Coastguard Worker     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
243*9880d681SAndroid Build Coastguard Worker       MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
244*9880d681SAndroid Build Coastguard Worker       uint64_t Seg_vmsize = Seg.vmsize;
245*9880d681SAndroid Build Coastguard Worker       outs() << "Segment " << Seg.segname << ": "
246*9880d681SAndroid Build Coastguard Worker              << format(fmt.str().c_str(), Seg_vmsize);
247*9880d681SAndroid Build Coastguard Worker       if (DarwinLongFormat)
248*9880d681SAndroid Build Coastguard Worker         outs() << " (vmaddr 0x" << format("%" PRIx32, Seg.vmaddr) << " fileoff "
249*9880d681SAndroid Build Coastguard Worker                << Seg.fileoff << ")";
250*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
251*9880d681SAndroid Build Coastguard Worker       total += Seg.vmsize;
252*9880d681SAndroid Build Coastguard Worker       uint64_t sec_total = 0;
253*9880d681SAndroid Build Coastguard Worker       for (unsigned J = 0; J < Seg.nsects; ++J) {
254*9880d681SAndroid Build Coastguard Worker         MachO::section Sec = MachO->getSection(Load, J);
255*9880d681SAndroid Build Coastguard Worker         if (Filetype == MachO::MH_OBJECT)
256*9880d681SAndroid Build Coastguard Worker           outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
257*9880d681SAndroid Build Coastguard Worker                  << format("%.16s", &Sec.sectname) << "): ";
258*9880d681SAndroid Build Coastguard Worker         else
259*9880d681SAndroid Build Coastguard Worker           outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
260*9880d681SAndroid Build Coastguard Worker         uint64_t Sec_size = Sec.size;
261*9880d681SAndroid Build Coastguard Worker         outs() << format(fmt.str().c_str(), Sec_size);
262*9880d681SAndroid Build Coastguard Worker         if (DarwinLongFormat)
263*9880d681SAndroid Build Coastguard Worker           outs() << " (addr 0x" << format("%" PRIx32, Sec.addr) << " offset "
264*9880d681SAndroid Build Coastguard Worker                  << Sec.offset << ")";
265*9880d681SAndroid Build Coastguard Worker         outs() << "\n";
266*9880d681SAndroid Build Coastguard Worker         sec_total += Sec.size;
267*9880d681SAndroid Build Coastguard Worker       }
268*9880d681SAndroid Build Coastguard Worker       if (Seg.nsects != 0)
269*9880d681SAndroid Build Coastguard Worker         outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
270*9880d681SAndroid Build Coastguard Worker     }
271*9880d681SAndroid Build Coastguard Worker   }
272*9880d681SAndroid Build Coastguard Worker   outs() << "total " << format(fmt.str().c_str(), total) << "\n";
273*9880d681SAndroid Build Coastguard Worker }
274*9880d681SAndroid Build Coastguard Worker 
275*9880d681SAndroid Build Coastguard Worker /// Print the summary sizes of the standard Mach-O segments in @p MachO.
276*9880d681SAndroid Build Coastguard Worker ///
277*9880d681SAndroid Build Coastguard Worker /// This is when used when @c OutputFormat is berkeley with a Mach-O file and
278*9880d681SAndroid Build Coastguard Worker /// produces the same output as darwin's size(1) default output.
printDarwinSegmentSizes(MachOObjectFile * MachO)279*9880d681SAndroid Build Coastguard Worker static void printDarwinSegmentSizes(MachOObjectFile *MachO) {
280*9880d681SAndroid Build Coastguard Worker   uint64_t total_text = 0;
281*9880d681SAndroid Build Coastguard Worker   uint64_t total_data = 0;
282*9880d681SAndroid Build Coastguard Worker   uint64_t total_objc = 0;
283*9880d681SAndroid Build Coastguard Worker   uint64_t total_others = 0;
284*9880d681SAndroid Build Coastguard Worker   for (const auto &Load : MachO->load_commands()) {
285*9880d681SAndroid Build Coastguard Worker     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
286*9880d681SAndroid Build Coastguard Worker       MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
287*9880d681SAndroid Build Coastguard Worker       if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
288*9880d681SAndroid Build Coastguard Worker         for (unsigned J = 0; J < Seg.nsects; ++J) {
289*9880d681SAndroid Build Coastguard Worker           MachO::section_64 Sec = MachO->getSection64(Load, J);
290*9880d681SAndroid Build Coastguard Worker           StringRef SegmentName = StringRef(Sec.segname);
291*9880d681SAndroid Build Coastguard Worker           if (SegmentName == "__TEXT")
292*9880d681SAndroid Build Coastguard Worker             total_text += Sec.size;
293*9880d681SAndroid Build Coastguard Worker           else if (SegmentName == "__DATA")
294*9880d681SAndroid Build Coastguard Worker             total_data += Sec.size;
295*9880d681SAndroid Build Coastguard Worker           else if (SegmentName == "__OBJC")
296*9880d681SAndroid Build Coastguard Worker             total_objc += Sec.size;
297*9880d681SAndroid Build Coastguard Worker           else
298*9880d681SAndroid Build Coastguard Worker             total_others += Sec.size;
299*9880d681SAndroid Build Coastguard Worker         }
300*9880d681SAndroid Build Coastguard Worker       } else {
301*9880d681SAndroid Build Coastguard Worker         StringRef SegmentName = StringRef(Seg.segname);
302*9880d681SAndroid Build Coastguard Worker         if (SegmentName == "__TEXT")
303*9880d681SAndroid Build Coastguard Worker           total_text += Seg.vmsize;
304*9880d681SAndroid Build Coastguard Worker         else if (SegmentName == "__DATA")
305*9880d681SAndroid Build Coastguard Worker           total_data += Seg.vmsize;
306*9880d681SAndroid Build Coastguard Worker         else if (SegmentName == "__OBJC")
307*9880d681SAndroid Build Coastguard Worker           total_objc += Seg.vmsize;
308*9880d681SAndroid Build Coastguard Worker         else
309*9880d681SAndroid Build Coastguard Worker           total_others += Seg.vmsize;
310*9880d681SAndroid Build Coastguard Worker       }
311*9880d681SAndroid Build Coastguard Worker     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
312*9880d681SAndroid Build Coastguard Worker       MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
313*9880d681SAndroid Build Coastguard Worker       if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
314*9880d681SAndroid Build Coastguard Worker         for (unsigned J = 0; J < Seg.nsects; ++J) {
315*9880d681SAndroid Build Coastguard Worker           MachO::section Sec = MachO->getSection(Load, J);
316*9880d681SAndroid Build Coastguard Worker           StringRef SegmentName = StringRef(Sec.segname);
317*9880d681SAndroid Build Coastguard Worker           if (SegmentName == "__TEXT")
318*9880d681SAndroid Build Coastguard Worker             total_text += Sec.size;
319*9880d681SAndroid Build Coastguard Worker           else if (SegmentName == "__DATA")
320*9880d681SAndroid Build Coastguard Worker             total_data += Sec.size;
321*9880d681SAndroid Build Coastguard Worker           else if (SegmentName == "__OBJC")
322*9880d681SAndroid Build Coastguard Worker             total_objc += Sec.size;
323*9880d681SAndroid Build Coastguard Worker           else
324*9880d681SAndroid Build Coastguard Worker             total_others += Sec.size;
325*9880d681SAndroid Build Coastguard Worker         }
326*9880d681SAndroid Build Coastguard Worker       } else {
327*9880d681SAndroid Build Coastguard Worker         StringRef SegmentName = StringRef(Seg.segname);
328*9880d681SAndroid Build Coastguard Worker         if (SegmentName == "__TEXT")
329*9880d681SAndroid Build Coastguard Worker           total_text += Seg.vmsize;
330*9880d681SAndroid Build Coastguard Worker         else if (SegmentName == "__DATA")
331*9880d681SAndroid Build Coastguard Worker           total_data += Seg.vmsize;
332*9880d681SAndroid Build Coastguard Worker         else if (SegmentName == "__OBJC")
333*9880d681SAndroid Build Coastguard Worker           total_objc += Seg.vmsize;
334*9880d681SAndroid Build Coastguard Worker         else
335*9880d681SAndroid Build Coastguard Worker           total_others += Seg.vmsize;
336*9880d681SAndroid Build Coastguard Worker       }
337*9880d681SAndroid Build Coastguard Worker     }
338*9880d681SAndroid Build Coastguard Worker   }
339*9880d681SAndroid Build Coastguard Worker   uint64_t total = total_text + total_data + total_objc + total_others;
340*9880d681SAndroid Build Coastguard Worker 
341*9880d681SAndroid Build Coastguard Worker   if (!BerkeleyHeaderPrinted) {
342*9880d681SAndroid Build Coastguard Worker     outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
343*9880d681SAndroid Build Coastguard Worker     BerkeleyHeaderPrinted = true;
344*9880d681SAndroid Build Coastguard Worker   }
345*9880d681SAndroid Build Coastguard Worker   outs() << total_text << "\t" << total_data << "\t" << total_objc << "\t"
346*9880d681SAndroid Build Coastguard Worker          << total_others << "\t" << total << "\t" << format("%" PRIx64, total)
347*9880d681SAndroid Build Coastguard Worker          << "\t";
348*9880d681SAndroid Build Coastguard Worker }
349*9880d681SAndroid Build Coastguard Worker 
350*9880d681SAndroid Build Coastguard Worker /// Print the size of each section in @p Obj.
351*9880d681SAndroid Build Coastguard Worker ///
352*9880d681SAndroid Build Coastguard Worker /// The format used is determined by @c OutputFormat and @c Radix.
printObjectSectionSizes(ObjectFile * Obj)353*9880d681SAndroid Build Coastguard Worker static void printObjectSectionSizes(ObjectFile *Obj) {
354*9880d681SAndroid Build Coastguard Worker   uint64_t total = 0;
355*9880d681SAndroid Build Coastguard Worker   std::string fmtbuf;
356*9880d681SAndroid Build Coastguard Worker   raw_string_ostream fmt(fmtbuf);
357*9880d681SAndroid Build Coastguard Worker   const char *radix_fmt = getRadixFmt();
358*9880d681SAndroid Build Coastguard Worker 
359*9880d681SAndroid Build Coastguard Worker   // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
360*9880d681SAndroid Build Coastguard Worker   // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
361*9880d681SAndroid Build Coastguard Worker   // let it fall through to OutputFormat berkeley.
362*9880d681SAndroid Build Coastguard Worker   MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
363*9880d681SAndroid Build Coastguard Worker   if (OutputFormat == darwin && MachO)
364*9880d681SAndroid Build Coastguard Worker     printDarwinSectionSizes(MachO);
365*9880d681SAndroid Build Coastguard Worker   // If we have a MachOObjectFile and the OutputFormat is berkeley print as
366*9880d681SAndroid Build Coastguard Worker   // darwin's default berkeley format for Mach-O files.
367*9880d681SAndroid Build Coastguard Worker   else if (MachO && OutputFormat == berkeley)
368*9880d681SAndroid Build Coastguard Worker     printDarwinSegmentSizes(MachO);
369*9880d681SAndroid Build Coastguard Worker   else if (OutputFormat == sysv) {
370*9880d681SAndroid Build Coastguard Worker     // Run two passes over all sections. The first gets the lengths needed for
371*9880d681SAndroid Build Coastguard Worker     // formatting the output. The second actually does the output.
372*9880d681SAndroid Build Coastguard Worker     std::size_t max_name_len = strlen("section");
373*9880d681SAndroid Build Coastguard Worker     std::size_t max_size_len = strlen("size");
374*9880d681SAndroid Build Coastguard Worker     std::size_t max_addr_len = strlen("addr");
375*9880d681SAndroid Build Coastguard Worker     for (const SectionRef &Section : Obj->sections()) {
376*9880d681SAndroid Build Coastguard Worker       if (!considerForSize(Obj, Section))
377*9880d681SAndroid Build Coastguard Worker         continue;
378*9880d681SAndroid Build Coastguard Worker       uint64_t size = Section.getSize();
379*9880d681SAndroid Build Coastguard Worker       total += size;
380*9880d681SAndroid Build Coastguard Worker 
381*9880d681SAndroid Build Coastguard Worker       StringRef name;
382*9880d681SAndroid Build Coastguard Worker       if (error(Section.getName(name)))
383*9880d681SAndroid Build Coastguard Worker         return;
384*9880d681SAndroid Build Coastguard Worker       uint64_t addr = Section.getAddress();
385*9880d681SAndroid Build Coastguard Worker       max_name_len = std::max(max_name_len, name.size());
386*9880d681SAndroid Build Coastguard Worker       max_size_len = std::max(max_size_len, getNumLengthAsString(size));
387*9880d681SAndroid Build Coastguard Worker       max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr));
388*9880d681SAndroid Build Coastguard Worker     }
389*9880d681SAndroid Build Coastguard Worker 
390*9880d681SAndroid Build Coastguard Worker     // Add extra padding.
391*9880d681SAndroid Build Coastguard Worker     max_name_len += 2;
392*9880d681SAndroid Build Coastguard Worker     max_size_len += 2;
393*9880d681SAndroid Build Coastguard Worker     max_addr_len += 2;
394*9880d681SAndroid Build Coastguard Worker 
395*9880d681SAndroid Build Coastguard Worker     // Setup header format.
396*9880d681SAndroid Build Coastguard Worker     fmt << "%-" << max_name_len << "s "
397*9880d681SAndroid Build Coastguard Worker         << "%" << max_size_len << "s "
398*9880d681SAndroid Build Coastguard Worker         << "%" << max_addr_len << "s\n";
399*9880d681SAndroid Build Coastguard Worker 
400*9880d681SAndroid Build Coastguard Worker     // Print header
401*9880d681SAndroid Build Coastguard Worker     outs() << format(fmt.str().c_str(), static_cast<const char *>("section"),
402*9880d681SAndroid Build Coastguard Worker                      static_cast<const char *>("size"),
403*9880d681SAndroid Build Coastguard Worker                      static_cast<const char *>("addr"));
404*9880d681SAndroid Build Coastguard Worker     fmtbuf.clear();
405*9880d681SAndroid Build Coastguard Worker 
406*9880d681SAndroid Build Coastguard Worker     // Setup per section format.
407*9880d681SAndroid Build Coastguard Worker     fmt << "%-" << max_name_len << "s "
408*9880d681SAndroid Build Coastguard Worker         << "%#" << max_size_len << radix_fmt << " "
409*9880d681SAndroid Build Coastguard Worker         << "%#" << max_addr_len << radix_fmt << "\n";
410*9880d681SAndroid Build Coastguard Worker 
411*9880d681SAndroid Build Coastguard Worker     // Print each section.
412*9880d681SAndroid Build Coastguard Worker     for (const SectionRef &Section : Obj->sections()) {
413*9880d681SAndroid Build Coastguard Worker       if (!considerForSize(Obj, Section))
414*9880d681SAndroid Build Coastguard Worker         continue;
415*9880d681SAndroid Build Coastguard Worker       StringRef name;
416*9880d681SAndroid Build Coastguard Worker       if (error(Section.getName(name)))
417*9880d681SAndroid Build Coastguard Worker         return;
418*9880d681SAndroid Build Coastguard Worker       uint64_t size = Section.getSize();
419*9880d681SAndroid Build Coastguard Worker       uint64_t addr = Section.getAddress();
420*9880d681SAndroid Build Coastguard Worker       std::string namestr = name;
421*9880d681SAndroid Build Coastguard Worker 
422*9880d681SAndroid Build Coastguard Worker       outs() << format(fmt.str().c_str(), namestr.c_str(), size, addr);
423*9880d681SAndroid Build Coastguard Worker     }
424*9880d681SAndroid Build Coastguard Worker 
425*9880d681SAndroid Build Coastguard Worker     if (ELFCommons) {
426*9880d681SAndroid Build Coastguard Worker       uint64_t CommonSize = getCommonSize(Obj);
427*9880d681SAndroid Build Coastguard Worker       total += CommonSize;
428*9880d681SAndroid Build Coastguard Worker       outs() << format(fmt.str().c_str(), std::string("*COM*").c_str(),
429*9880d681SAndroid Build Coastguard Worker                        CommonSize, static_cast<uint64_t>(0));
430*9880d681SAndroid Build Coastguard Worker     }
431*9880d681SAndroid Build Coastguard Worker 
432*9880d681SAndroid Build Coastguard Worker     // Print total.
433*9880d681SAndroid Build Coastguard Worker     fmtbuf.clear();
434*9880d681SAndroid Build Coastguard Worker     fmt << "%-" << max_name_len << "s "
435*9880d681SAndroid Build Coastguard Worker         << "%#" << max_size_len << radix_fmt << "\n";
436*9880d681SAndroid Build Coastguard Worker     outs() << format(fmt.str().c_str(), static_cast<const char *>("Total"),
437*9880d681SAndroid Build Coastguard Worker                      total);
438*9880d681SAndroid Build Coastguard Worker   } else {
439*9880d681SAndroid Build Coastguard Worker     // The Berkeley format does not display individual section sizes. It
440*9880d681SAndroid Build Coastguard Worker     // displays the cumulative size for each section type.
441*9880d681SAndroid Build Coastguard Worker     uint64_t total_text = 0;
442*9880d681SAndroid Build Coastguard Worker     uint64_t total_data = 0;
443*9880d681SAndroid Build Coastguard Worker     uint64_t total_bss = 0;
444*9880d681SAndroid Build Coastguard Worker 
445*9880d681SAndroid Build Coastguard Worker     // Make one pass over the section table to calculate sizes.
446*9880d681SAndroid Build Coastguard Worker     for (const SectionRef &Section : Obj->sections()) {
447*9880d681SAndroid Build Coastguard Worker       uint64_t size = Section.getSize();
448*9880d681SAndroid Build Coastguard Worker       bool isText = Section.isText();
449*9880d681SAndroid Build Coastguard Worker       bool isData = Section.isData();
450*9880d681SAndroid Build Coastguard Worker       bool isBSS = Section.isBSS();
451*9880d681SAndroid Build Coastguard Worker       if (isText)
452*9880d681SAndroid Build Coastguard Worker         total_text += size;
453*9880d681SAndroid Build Coastguard Worker       else if (isData)
454*9880d681SAndroid Build Coastguard Worker         total_data += size;
455*9880d681SAndroid Build Coastguard Worker       else if (isBSS)
456*9880d681SAndroid Build Coastguard Worker         total_bss += size;
457*9880d681SAndroid Build Coastguard Worker     }
458*9880d681SAndroid Build Coastguard Worker 
459*9880d681SAndroid Build Coastguard Worker     if (ELFCommons)
460*9880d681SAndroid Build Coastguard Worker       total_bss += getCommonSize(Obj);
461*9880d681SAndroid Build Coastguard Worker 
462*9880d681SAndroid Build Coastguard Worker     total = total_text + total_data + total_bss;
463*9880d681SAndroid Build Coastguard Worker 
464*9880d681SAndroid Build Coastguard Worker     if (!BerkeleyHeaderPrinted) {
465*9880d681SAndroid Build Coastguard Worker       outs() << "   text    data     bss     "
466*9880d681SAndroid Build Coastguard Worker              << (Radix == octal ? "oct" : "dec") << "     hex filename\n";
467*9880d681SAndroid Build Coastguard Worker       BerkeleyHeaderPrinted = true;
468*9880d681SAndroid Build Coastguard Worker     }
469*9880d681SAndroid Build Coastguard Worker 
470*9880d681SAndroid Build Coastguard Worker     // Print result.
471*9880d681SAndroid Build Coastguard Worker     fmt << "%#7" << radix_fmt << " "
472*9880d681SAndroid Build Coastguard Worker         << "%#7" << radix_fmt << " "
473*9880d681SAndroid Build Coastguard Worker         << "%#7" << radix_fmt << " ";
474*9880d681SAndroid Build Coastguard Worker     outs() << format(fmt.str().c_str(), total_text, total_data, total_bss);
475*9880d681SAndroid Build Coastguard Worker     fmtbuf.clear();
476*9880d681SAndroid Build Coastguard Worker     fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << " "
477*9880d681SAndroid Build Coastguard Worker         << "%7" PRIx64 " ";
478*9880d681SAndroid Build Coastguard Worker     outs() << format(fmt.str().c_str(), total, total);
479*9880d681SAndroid Build Coastguard Worker   }
480*9880d681SAndroid Build Coastguard Worker }
481*9880d681SAndroid Build Coastguard Worker 
482*9880d681SAndroid Build Coastguard Worker /// Checks to see if the @p o ObjectFile is a Mach-O file and if it is and there
483*9880d681SAndroid Build Coastguard Worker /// is a list of architecture flags specified then check to make sure this
484*9880d681SAndroid Build Coastguard Worker /// Mach-O file is one of those architectures or all architectures was
485*9880d681SAndroid Build Coastguard Worker /// specificed.  If not then an error is generated and this routine returns
486*9880d681SAndroid Build Coastguard Worker /// false.  Else it returns true.
checkMachOAndArchFlags(ObjectFile * o,StringRef file)487*9880d681SAndroid Build Coastguard Worker static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) {
488*9880d681SAndroid Build Coastguard Worker   if (isa<MachOObjectFile>(o) && !ArchAll && ArchFlags.size() != 0) {
489*9880d681SAndroid Build Coastguard Worker     MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
490*9880d681SAndroid Build Coastguard Worker     bool ArchFound = false;
491*9880d681SAndroid Build Coastguard Worker     MachO::mach_header H;
492*9880d681SAndroid Build Coastguard Worker     MachO::mach_header_64 H_64;
493*9880d681SAndroid Build Coastguard Worker     Triple T;
494*9880d681SAndroid Build Coastguard Worker     if (MachO->is64Bit()) {
495*9880d681SAndroid Build Coastguard Worker       H_64 = MachO->MachOObjectFile::getHeader64();
496*9880d681SAndroid Build Coastguard Worker       T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype);
497*9880d681SAndroid Build Coastguard Worker     } else {
498*9880d681SAndroid Build Coastguard Worker       H = MachO->MachOObjectFile::getHeader();
499*9880d681SAndroid Build Coastguard Worker       T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype);
500*9880d681SAndroid Build Coastguard Worker     }
501*9880d681SAndroid Build Coastguard Worker     unsigned i;
502*9880d681SAndroid Build Coastguard Worker     for (i = 0; i < ArchFlags.size(); ++i) {
503*9880d681SAndroid Build Coastguard Worker       if (ArchFlags[i] == T.getArchName())
504*9880d681SAndroid Build Coastguard Worker         ArchFound = true;
505*9880d681SAndroid Build Coastguard Worker       break;
506*9880d681SAndroid Build Coastguard Worker     }
507*9880d681SAndroid Build Coastguard Worker     if (!ArchFound) {
508*9880d681SAndroid Build Coastguard Worker       errs() << ToolName << ": file: " << file
509*9880d681SAndroid Build Coastguard Worker              << " does not contain architecture: " << ArchFlags[i] << ".\n";
510*9880d681SAndroid Build Coastguard Worker       return false;
511*9880d681SAndroid Build Coastguard Worker     }
512*9880d681SAndroid Build Coastguard Worker   }
513*9880d681SAndroid Build Coastguard Worker   return true;
514*9880d681SAndroid Build Coastguard Worker }
515*9880d681SAndroid Build Coastguard Worker 
516*9880d681SAndroid Build Coastguard Worker /// Print the section sizes for @p file. If @p file is an archive, print the
517*9880d681SAndroid Build Coastguard Worker /// section sizes for each archive member.
printFileSectionSizes(StringRef file)518*9880d681SAndroid Build Coastguard Worker static void printFileSectionSizes(StringRef file) {
519*9880d681SAndroid Build Coastguard Worker 
520*9880d681SAndroid Build Coastguard Worker   // Attempt to open the binary.
521*9880d681SAndroid Build Coastguard Worker   Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
522*9880d681SAndroid Build Coastguard Worker   if (!BinaryOrErr) {
523*9880d681SAndroid Build Coastguard Worker     error(errorToErrorCode(BinaryOrErr.takeError()));
524*9880d681SAndroid Build Coastguard Worker     return;
525*9880d681SAndroid Build Coastguard Worker   }
526*9880d681SAndroid Build Coastguard Worker   Binary &Bin = *BinaryOrErr.get().getBinary();
527*9880d681SAndroid Build Coastguard Worker 
528*9880d681SAndroid Build Coastguard Worker   if (Archive *a = dyn_cast<Archive>(&Bin)) {
529*9880d681SAndroid Build Coastguard Worker     // This is an archive. Iterate over each member and display its sizes.
530*9880d681SAndroid Build Coastguard Worker     Error Err;
531*9880d681SAndroid Build Coastguard Worker     for (auto &C : a->children(Err)) {
532*9880d681SAndroid Build Coastguard Worker       Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
533*9880d681SAndroid Build Coastguard Worker       if (!ChildOrErr) {
534*9880d681SAndroid Build Coastguard Worker         if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
535*9880d681SAndroid Build Coastguard Worker           error(std::move(E), a->getFileName(), C);
536*9880d681SAndroid Build Coastguard Worker         continue;
537*9880d681SAndroid Build Coastguard Worker       }
538*9880d681SAndroid Build Coastguard Worker       if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
539*9880d681SAndroid Build Coastguard Worker         MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
540*9880d681SAndroid Build Coastguard Worker         if (!checkMachOAndArchFlags(o, file))
541*9880d681SAndroid Build Coastguard Worker           return;
542*9880d681SAndroid Build Coastguard Worker         if (OutputFormat == sysv)
543*9880d681SAndroid Build Coastguard Worker           outs() << o->getFileName() << "   (ex " << a->getFileName() << "):\n";
544*9880d681SAndroid Build Coastguard Worker         else if (MachO && OutputFormat == darwin)
545*9880d681SAndroid Build Coastguard Worker           outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
546*9880d681SAndroid Build Coastguard Worker         printObjectSectionSizes(o);
547*9880d681SAndroid Build Coastguard Worker         if (OutputFormat == berkeley) {
548*9880d681SAndroid Build Coastguard Worker           if (MachO)
549*9880d681SAndroid Build Coastguard Worker             outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
550*9880d681SAndroid Build Coastguard Worker           else
551*9880d681SAndroid Build Coastguard Worker             outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
552*9880d681SAndroid Build Coastguard Worker         }
553*9880d681SAndroid Build Coastguard Worker       }
554*9880d681SAndroid Build Coastguard Worker     }
555*9880d681SAndroid Build Coastguard Worker     if (Err)
556*9880d681SAndroid Build Coastguard Worker       error(std::move(Err), a->getFileName());
557*9880d681SAndroid Build Coastguard Worker   } else if (MachOUniversalBinary *UB =
558*9880d681SAndroid Build Coastguard Worker                  dyn_cast<MachOUniversalBinary>(&Bin)) {
559*9880d681SAndroid Build Coastguard Worker     // If we have a list of architecture flags specified dump only those.
560*9880d681SAndroid Build Coastguard Worker     if (!ArchAll && ArchFlags.size() != 0) {
561*9880d681SAndroid Build Coastguard Worker       // Look for a slice in the universal binary that matches each ArchFlag.
562*9880d681SAndroid Build Coastguard Worker       bool ArchFound;
563*9880d681SAndroid Build Coastguard Worker       for (unsigned i = 0; i < ArchFlags.size(); ++i) {
564*9880d681SAndroid Build Coastguard Worker         ArchFound = false;
565*9880d681SAndroid Build Coastguard Worker         for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
566*9880d681SAndroid Build Coastguard Worker                                                    E = UB->end_objects();
567*9880d681SAndroid Build Coastguard Worker              I != E; ++I) {
568*9880d681SAndroid Build Coastguard Worker           if (ArchFlags[i] == I->getArchTypeName()) {
569*9880d681SAndroid Build Coastguard Worker             ArchFound = true;
570*9880d681SAndroid Build Coastguard Worker             Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
571*9880d681SAndroid Build Coastguard Worker             if (UO) {
572*9880d681SAndroid Build Coastguard Worker               if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
573*9880d681SAndroid Build Coastguard Worker                 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
574*9880d681SAndroid Build Coastguard Worker                 if (OutputFormat == sysv)
575*9880d681SAndroid Build Coastguard Worker                   outs() << o->getFileName() << "  :\n";
576*9880d681SAndroid Build Coastguard Worker                 else if (MachO && OutputFormat == darwin) {
577*9880d681SAndroid Build Coastguard Worker                   if (MoreThanOneFile || ArchFlags.size() > 1)
578*9880d681SAndroid Build Coastguard Worker                     outs() << o->getFileName() << " (for architecture "
579*9880d681SAndroid Build Coastguard Worker                            << I->getArchTypeName() << "): \n";
580*9880d681SAndroid Build Coastguard Worker                 }
581*9880d681SAndroid Build Coastguard Worker                 printObjectSectionSizes(o);
582*9880d681SAndroid Build Coastguard Worker                 if (OutputFormat == berkeley) {
583*9880d681SAndroid Build Coastguard Worker                   if (!MachO || MoreThanOneFile || ArchFlags.size() > 1)
584*9880d681SAndroid Build Coastguard Worker                     outs() << o->getFileName() << " (for architecture "
585*9880d681SAndroid Build Coastguard Worker                            << I->getArchTypeName() << ")";
586*9880d681SAndroid Build Coastguard Worker                   outs() << "\n";
587*9880d681SAndroid Build Coastguard Worker                 }
588*9880d681SAndroid Build Coastguard Worker               }
589*9880d681SAndroid Build Coastguard Worker             } else if (auto E = isNotObjectErrorInvalidFileType(
590*9880d681SAndroid Build Coastguard Worker                        UO.takeError())) {
591*9880d681SAndroid Build Coastguard Worker               error(std::move(E), file, ArchFlags.size() > 1 ?
592*9880d681SAndroid Build Coastguard Worker                     StringRef(I->getArchTypeName()) : StringRef());
593*9880d681SAndroid Build Coastguard Worker               return;
594*9880d681SAndroid Build Coastguard Worker             } else if (Expected<std::unique_ptr<Archive>> AOrErr =
595*9880d681SAndroid Build Coastguard Worker                            I->getAsArchive()) {
596*9880d681SAndroid Build Coastguard Worker               std::unique_ptr<Archive> &UA = *AOrErr;
597*9880d681SAndroid Build Coastguard Worker               // This is an archive. Iterate over each member and display its
598*9880d681SAndroid Build Coastguard Worker               // sizes.
599*9880d681SAndroid Build Coastguard Worker               Error Err;
600*9880d681SAndroid Build Coastguard Worker               for (auto &C : UA->children(Err)) {
601*9880d681SAndroid Build Coastguard Worker                 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
602*9880d681SAndroid Build Coastguard Worker                 if (!ChildOrErr) {
603*9880d681SAndroid Build Coastguard Worker                   if (auto E = isNotObjectErrorInvalidFileType(
604*9880d681SAndroid Build Coastguard Worker                                     ChildOrErr.takeError()))
605*9880d681SAndroid Build Coastguard Worker                     error(std::move(E), UA->getFileName(), C,
606*9880d681SAndroid Build Coastguard Worker                           ArchFlags.size() > 1 ?
607*9880d681SAndroid Build Coastguard Worker                           StringRef(I->getArchTypeName()) : StringRef());
608*9880d681SAndroid Build Coastguard Worker                   continue;
609*9880d681SAndroid Build Coastguard Worker                 }
610*9880d681SAndroid Build Coastguard Worker                 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
611*9880d681SAndroid Build Coastguard Worker                   MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
612*9880d681SAndroid Build Coastguard Worker                   if (OutputFormat == sysv)
613*9880d681SAndroid Build Coastguard Worker                     outs() << o->getFileName() << "   (ex " << UA->getFileName()
614*9880d681SAndroid Build Coastguard Worker                            << "):\n";
615*9880d681SAndroid Build Coastguard Worker                   else if (MachO && OutputFormat == darwin)
616*9880d681SAndroid Build Coastguard Worker                     outs() << UA->getFileName() << "(" << o->getFileName()
617*9880d681SAndroid Build Coastguard Worker                            << ")"
618*9880d681SAndroid Build Coastguard Worker                            << " (for architecture " << I->getArchTypeName()
619*9880d681SAndroid Build Coastguard Worker                            << "):\n";
620*9880d681SAndroid Build Coastguard Worker                   printObjectSectionSizes(o);
621*9880d681SAndroid Build Coastguard Worker                   if (OutputFormat == berkeley) {
622*9880d681SAndroid Build Coastguard Worker                     if (MachO) {
623*9880d681SAndroid Build Coastguard Worker                       outs() << UA->getFileName() << "(" << o->getFileName()
624*9880d681SAndroid Build Coastguard Worker                              << ")";
625*9880d681SAndroid Build Coastguard Worker                       if (ArchFlags.size() > 1)
626*9880d681SAndroid Build Coastguard Worker                         outs() << " (for architecture " << I->getArchTypeName()
627*9880d681SAndroid Build Coastguard Worker                                << ")";
628*9880d681SAndroid Build Coastguard Worker                       outs() << "\n";
629*9880d681SAndroid Build Coastguard Worker                     } else
630*9880d681SAndroid Build Coastguard Worker                       outs() << o->getFileName() << " (ex " << UA->getFileName()
631*9880d681SAndroid Build Coastguard Worker                              << ")\n";
632*9880d681SAndroid Build Coastguard Worker                   }
633*9880d681SAndroid Build Coastguard Worker                 }
634*9880d681SAndroid Build Coastguard Worker               }
635*9880d681SAndroid Build Coastguard Worker               if (Err)
636*9880d681SAndroid Build Coastguard Worker                 error(std::move(Err), UA->getFileName());
637*9880d681SAndroid Build Coastguard Worker             } else {
638*9880d681SAndroid Build Coastguard Worker               consumeError(AOrErr.takeError());
639*9880d681SAndroid Build Coastguard Worker               error("Mach-O universal file: " + file + " for architecture " +
640*9880d681SAndroid Build Coastguard Worker                     StringRef(I->getArchTypeName()) +
641*9880d681SAndroid Build Coastguard Worker                     " is not a Mach-O file or an archive file");
642*9880d681SAndroid Build Coastguard Worker             }
643*9880d681SAndroid Build Coastguard Worker           }
644*9880d681SAndroid Build Coastguard Worker         }
645*9880d681SAndroid Build Coastguard Worker         if (!ArchFound) {
646*9880d681SAndroid Build Coastguard Worker           errs() << ToolName << ": file: " << file
647*9880d681SAndroid Build Coastguard Worker                  << " does not contain architecture" << ArchFlags[i] << ".\n";
648*9880d681SAndroid Build Coastguard Worker           return;
649*9880d681SAndroid Build Coastguard Worker         }
650*9880d681SAndroid Build Coastguard Worker       }
651*9880d681SAndroid Build Coastguard Worker       return;
652*9880d681SAndroid Build Coastguard Worker     }
653*9880d681SAndroid Build Coastguard Worker     // No architecture flags were specified so if this contains a slice that
654*9880d681SAndroid Build Coastguard Worker     // matches the host architecture dump only that.
655*9880d681SAndroid Build Coastguard Worker     if (!ArchAll) {
656*9880d681SAndroid Build Coastguard Worker       StringRef HostArchName = MachOObjectFile::getHostArch().getArchName();
657*9880d681SAndroid Build Coastguard Worker       for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
658*9880d681SAndroid Build Coastguard Worker                                                  E = UB->end_objects();
659*9880d681SAndroid Build Coastguard Worker            I != E; ++I) {
660*9880d681SAndroid Build Coastguard Worker         if (HostArchName == I->getArchTypeName()) {
661*9880d681SAndroid Build Coastguard Worker           Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
662*9880d681SAndroid Build Coastguard Worker           if (UO) {
663*9880d681SAndroid Build Coastguard Worker             if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
664*9880d681SAndroid Build Coastguard Worker               MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
665*9880d681SAndroid Build Coastguard Worker               if (OutputFormat == sysv)
666*9880d681SAndroid Build Coastguard Worker                 outs() << o->getFileName() << "  :\n";
667*9880d681SAndroid Build Coastguard Worker               else if (MachO && OutputFormat == darwin) {
668*9880d681SAndroid Build Coastguard Worker                 if (MoreThanOneFile)
669*9880d681SAndroid Build Coastguard Worker                   outs() << o->getFileName() << " (for architecture "
670*9880d681SAndroid Build Coastguard Worker                          << I->getArchTypeName() << "):\n";
671*9880d681SAndroid Build Coastguard Worker               }
672*9880d681SAndroid Build Coastguard Worker               printObjectSectionSizes(o);
673*9880d681SAndroid Build Coastguard Worker               if (OutputFormat == berkeley) {
674*9880d681SAndroid Build Coastguard Worker                 if (!MachO || MoreThanOneFile)
675*9880d681SAndroid Build Coastguard Worker                   outs() << o->getFileName() << " (for architecture "
676*9880d681SAndroid Build Coastguard Worker                          << I->getArchTypeName() << ")";
677*9880d681SAndroid Build Coastguard Worker                 outs() << "\n";
678*9880d681SAndroid Build Coastguard Worker               }
679*9880d681SAndroid Build Coastguard Worker             }
680*9880d681SAndroid Build Coastguard Worker           } else if (auto E = isNotObjectErrorInvalidFileType(UO.takeError())) {
681*9880d681SAndroid Build Coastguard Worker             error(std::move(E), file);
682*9880d681SAndroid Build Coastguard Worker             return;
683*9880d681SAndroid Build Coastguard Worker           } else if (Expected<std::unique_ptr<Archive>> AOrErr =
684*9880d681SAndroid Build Coastguard Worker                          I->getAsArchive()) {
685*9880d681SAndroid Build Coastguard Worker             std::unique_ptr<Archive> &UA = *AOrErr;
686*9880d681SAndroid Build Coastguard Worker             // This is an archive. Iterate over each member and display its
687*9880d681SAndroid Build Coastguard Worker             // sizes.
688*9880d681SAndroid Build Coastguard Worker             Error Err;
689*9880d681SAndroid Build Coastguard Worker             for (auto &C : UA->children(Err)) {
690*9880d681SAndroid Build Coastguard Worker               Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
691*9880d681SAndroid Build Coastguard Worker               if (!ChildOrErr) {
692*9880d681SAndroid Build Coastguard Worker                 if (auto E = isNotObjectErrorInvalidFileType(
693*9880d681SAndroid Build Coastguard Worker                                 ChildOrErr.takeError()))
694*9880d681SAndroid Build Coastguard Worker                   error(std::move(E), UA->getFileName(), C);
695*9880d681SAndroid Build Coastguard Worker                 continue;
696*9880d681SAndroid Build Coastguard Worker               }
697*9880d681SAndroid Build Coastguard Worker               if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
698*9880d681SAndroid Build Coastguard Worker                 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
699*9880d681SAndroid Build Coastguard Worker                 if (OutputFormat == sysv)
700*9880d681SAndroid Build Coastguard Worker                   outs() << o->getFileName() << "   (ex " << UA->getFileName()
701*9880d681SAndroid Build Coastguard Worker                          << "):\n";
702*9880d681SAndroid Build Coastguard Worker                 else if (MachO && OutputFormat == darwin)
703*9880d681SAndroid Build Coastguard Worker                   outs() << UA->getFileName() << "(" << o->getFileName() << ")"
704*9880d681SAndroid Build Coastguard Worker                          << " (for architecture " << I->getArchTypeName()
705*9880d681SAndroid Build Coastguard Worker                          << "):\n";
706*9880d681SAndroid Build Coastguard Worker                 printObjectSectionSizes(o);
707*9880d681SAndroid Build Coastguard Worker                 if (OutputFormat == berkeley) {
708*9880d681SAndroid Build Coastguard Worker                   if (MachO)
709*9880d681SAndroid Build Coastguard Worker                     outs() << UA->getFileName() << "(" << o->getFileName()
710*9880d681SAndroid Build Coastguard Worker                            << ")\n";
711*9880d681SAndroid Build Coastguard Worker                   else
712*9880d681SAndroid Build Coastguard Worker                     outs() << o->getFileName() << " (ex " << UA->getFileName()
713*9880d681SAndroid Build Coastguard Worker                            << ")\n";
714*9880d681SAndroid Build Coastguard Worker                 }
715*9880d681SAndroid Build Coastguard Worker               }
716*9880d681SAndroid Build Coastguard Worker             }
717*9880d681SAndroid Build Coastguard Worker             if (Err)
718*9880d681SAndroid Build Coastguard Worker               error(std::move(Err), UA->getFileName());
719*9880d681SAndroid Build Coastguard Worker           } else {
720*9880d681SAndroid Build Coastguard Worker             consumeError(AOrErr.takeError());
721*9880d681SAndroid Build Coastguard Worker             error("Mach-O universal file: " + file + " for architecture " +
722*9880d681SAndroid Build Coastguard Worker                    StringRef(I->getArchTypeName()) +
723*9880d681SAndroid Build Coastguard Worker                    " is not a Mach-O file or an archive file");
724*9880d681SAndroid Build Coastguard Worker           }
725*9880d681SAndroid Build Coastguard Worker           return;
726*9880d681SAndroid Build Coastguard Worker         }
727*9880d681SAndroid Build Coastguard Worker       }
728*9880d681SAndroid Build Coastguard Worker     }
729*9880d681SAndroid Build Coastguard Worker     // Either all architectures have been specified or none have been specified
730*9880d681SAndroid Build Coastguard Worker     // and this does not contain the host architecture so dump all the slices.
731*9880d681SAndroid Build Coastguard Worker     bool MoreThanOneArch = UB->getNumberOfObjects() > 1;
732*9880d681SAndroid Build Coastguard Worker     for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
733*9880d681SAndroid Build Coastguard Worker                                                E = UB->end_objects();
734*9880d681SAndroid Build Coastguard Worker          I != E; ++I) {
735*9880d681SAndroid Build Coastguard Worker       Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
736*9880d681SAndroid Build Coastguard Worker       if (UO) {
737*9880d681SAndroid Build Coastguard Worker         if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
738*9880d681SAndroid Build Coastguard Worker           MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
739*9880d681SAndroid Build Coastguard Worker           if (OutputFormat == sysv)
740*9880d681SAndroid Build Coastguard Worker             outs() << o->getFileName() << "  :\n";
741*9880d681SAndroid Build Coastguard Worker           else if (MachO && OutputFormat == darwin) {
742*9880d681SAndroid Build Coastguard Worker             if (MoreThanOneFile || MoreThanOneArch)
743*9880d681SAndroid Build Coastguard Worker               outs() << o->getFileName() << " (for architecture "
744*9880d681SAndroid Build Coastguard Worker                      << I->getArchTypeName() << "):";
745*9880d681SAndroid Build Coastguard Worker             outs() << "\n";
746*9880d681SAndroid Build Coastguard Worker           }
747*9880d681SAndroid Build Coastguard Worker           printObjectSectionSizes(o);
748*9880d681SAndroid Build Coastguard Worker           if (OutputFormat == berkeley) {
749*9880d681SAndroid Build Coastguard Worker             if (!MachO || MoreThanOneFile || MoreThanOneArch)
750*9880d681SAndroid Build Coastguard Worker               outs() << o->getFileName() << " (for architecture "
751*9880d681SAndroid Build Coastguard Worker                      << I->getArchTypeName() << ")";
752*9880d681SAndroid Build Coastguard Worker             outs() << "\n";
753*9880d681SAndroid Build Coastguard Worker           }
754*9880d681SAndroid Build Coastguard Worker         }
755*9880d681SAndroid Build Coastguard Worker       } else if (auto E = isNotObjectErrorInvalidFileType(UO.takeError())) {
756*9880d681SAndroid Build Coastguard Worker         error(std::move(E), file, MoreThanOneArch ?
757*9880d681SAndroid Build Coastguard Worker               StringRef(I->getArchTypeName()) : StringRef());
758*9880d681SAndroid Build Coastguard Worker         return;
759*9880d681SAndroid Build Coastguard Worker       } else if (Expected<std::unique_ptr<Archive>> AOrErr =
760*9880d681SAndroid Build Coastguard Worker                          I->getAsArchive()) {
761*9880d681SAndroid Build Coastguard Worker         std::unique_ptr<Archive> &UA = *AOrErr;
762*9880d681SAndroid Build Coastguard Worker         // This is an archive. Iterate over each member and display its sizes.
763*9880d681SAndroid Build Coastguard Worker         Error Err;
764*9880d681SAndroid Build Coastguard Worker         for (auto &C : UA->children(Err)) {
765*9880d681SAndroid Build Coastguard Worker           Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
766*9880d681SAndroid Build Coastguard Worker           if (!ChildOrErr) {
767*9880d681SAndroid Build Coastguard Worker             if (auto E = isNotObjectErrorInvalidFileType(
768*9880d681SAndroid Build Coastguard Worker                               ChildOrErr.takeError()))
769*9880d681SAndroid Build Coastguard Worker               error(std::move(E), UA->getFileName(), C, MoreThanOneArch ?
770*9880d681SAndroid Build Coastguard Worker                     StringRef(I->getArchTypeName()) : StringRef());
771*9880d681SAndroid Build Coastguard Worker             continue;
772*9880d681SAndroid Build Coastguard Worker           }
773*9880d681SAndroid Build Coastguard Worker           if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
774*9880d681SAndroid Build Coastguard Worker             MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
775*9880d681SAndroid Build Coastguard Worker             if (OutputFormat == sysv)
776*9880d681SAndroid Build Coastguard Worker               outs() << o->getFileName() << "   (ex " << UA->getFileName()
777*9880d681SAndroid Build Coastguard Worker                      << "):\n";
778*9880d681SAndroid Build Coastguard Worker             else if (MachO && OutputFormat == darwin)
779*9880d681SAndroid Build Coastguard Worker               outs() << UA->getFileName() << "(" << o->getFileName() << ")"
780*9880d681SAndroid Build Coastguard Worker                      << " (for architecture " << I->getArchTypeName() << "):\n";
781*9880d681SAndroid Build Coastguard Worker             printObjectSectionSizes(o);
782*9880d681SAndroid Build Coastguard Worker             if (OutputFormat == berkeley) {
783*9880d681SAndroid Build Coastguard Worker               if (MachO)
784*9880d681SAndroid Build Coastguard Worker                 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
785*9880d681SAndroid Build Coastguard Worker                        << " (for architecture " << I->getArchTypeName()
786*9880d681SAndroid Build Coastguard Worker                        << ")\n";
787*9880d681SAndroid Build Coastguard Worker               else
788*9880d681SAndroid Build Coastguard Worker                 outs() << o->getFileName() << " (ex " << UA->getFileName()
789*9880d681SAndroid Build Coastguard Worker                        << ")\n";
790*9880d681SAndroid Build Coastguard Worker             }
791*9880d681SAndroid Build Coastguard Worker           }
792*9880d681SAndroid Build Coastguard Worker         }
793*9880d681SAndroid Build Coastguard Worker         if (Err)
794*9880d681SAndroid Build Coastguard Worker           error(std::move(Err), UA->getFileName());
795*9880d681SAndroid Build Coastguard Worker       } else {
796*9880d681SAndroid Build Coastguard Worker         consumeError(AOrErr.takeError());
797*9880d681SAndroid Build Coastguard Worker         error("Mach-O universal file: " + file + " for architecture " +
798*9880d681SAndroid Build Coastguard Worker                StringRef(I->getArchTypeName()) +
799*9880d681SAndroid Build Coastguard Worker                " is not a Mach-O file or an archive file");
800*9880d681SAndroid Build Coastguard Worker       }
801*9880d681SAndroid Build Coastguard Worker     }
802*9880d681SAndroid Build Coastguard Worker   } else if (ObjectFile *o = dyn_cast<ObjectFile>(&Bin)) {
803*9880d681SAndroid Build Coastguard Worker     if (!checkMachOAndArchFlags(o, file))
804*9880d681SAndroid Build Coastguard Worker       return;
805*9880d681SAndroid Build Coastguard Worker     if (OutputFormat == sysv)
806*9880d681SAndroid Build Coastguard Worker       outs() << o->getFileName() << "  :\n";
807*9880d681SAndroid Build Coastguard Worker     printObjectSectionSizes(o);
808*9880d681SAndroid Build Coastguard Worker     if (OutputFormat == berkeley) {
809*9880d681SAndroid Build Coastguard Worker       MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
810*9880d681SAndroid Build Coastguard Worker       if (!MachO || MoreThanOneFile)
811*9880d681SAndroid Build Coastguard Worker         outs() << o->getFileName();
812*9880d681SAndroid Build Coastguard Worker       outs() << "\n";
813*9880d681SAndroid Build Coastguard Worker     }
814*9880d681SAndroid Build Coastguard Worker   } else {
815*9880d681SAndroid Build Coastguard Worker     errs() << ToolName << ": " << file << ": "
816*9880d681SAndroid Build Coastguard Worker            << "Unrecognized file type.\n";
817*9880d681SAndroid Build Coastguard Worker   }
818*9880d681SAndroid Build Coastguard Worker   // System V adds an extra newline at the end of each file.
819*9880d681SAndroid Build Coastguard Worker   if (OutputFormat == sysv)
820*9880d681SAndroid Build Coastguard Worker     outs() << "\n";
821*9880d681SAndroid Build Coastguard Worker }
822*9880d681SAndroid Build Coastguard Worker 
main(int argc,char ** argv)823*9880d681SAndroid Build Coastguard Worker int main(int argc, char **argv) {
824*9880d681SAndroid Build Coastguard Worker   // Print a stack trace if we signal out.
825*9880d681SAndroid Build Coastguard Worker   sys::PrintStackTraceOnErrorSignal(argv[0]);
826*9880d681SAndroid Build Coastguard Worker   PrettyStackTraceProgram X(argc, argv);
827*9880d681SAndroid Build Coastguard Worker 
828*9880d681SAndroid Build Coastguard Worker   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
829*9880d681SAndroid Build Coastguard Worker   cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n");
830*9880d681SAndroid Build Coastguard Worker 
831*9880d681SAndroid Build Coastguard Worker   ToolName = argv[0];
832*9880d681SAndroid Build Coastguard Worker   if (OutputFormatShort.getNumOccurrences())
833*9880d681SAndroid Build Coastguard Worker     OutputFormat = static_cast<OutputFormatTy>(OutputFormatShort);
834*9880d681SAndroid Build Coastguard Worker   if (RadixShort.getNumOccurrences())
835*9880d681SAndroid Build Coastguard Worker     Radix = RadixShort;
836*9880d681SAndroid Build Coastguard Worker 
837*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < ArchFlags.size(); ++i) {
838*9880d681SAndroid Build Coastguard Worker     if (ArchFlags[i] == "all") {
839*9880d681SAndroid Build Coastguard Worker       ArchAll = true;
840*9880d681SAndroid Build Coastguard Worker     } else {
841*9880d681SAndroid Build Coastguard Worker       if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
842*9880d681SAndroid Build Coastguard Worker         outs() << ToolName << ": for the -arch option: Unknown architecture "
843*9880d681SAndroid Build Coastguard Worker                << "named '" << ArchFlags[i] << "'";
844*9880d681SAndroid Build Coastguard Worker         return 1;
845*9880d681SAndroid Build Coastguard Worker       }
846*9880d681SAndroid Build Coastguard Worker     }
847*9880d681SAndroid Build Coastguard Worker   }
848*9880d681SAndroid Build Coastguard Worker 
849*9880d681SAndroid Build Coastguard Worker   if (InputFilenames.size() == 0)
850*9880d681SAndroid Build Coastguard Worker     InputFilenames.push_back("a.out");
851*9880d681SAndroid Build Coastguard Worker 
852*9880d681SAndroid Build Coastguard Worker   MoreThanOneFile = InputFilenames.size() > 1;
853*9880d681SAndroid Build Coastguard Worker   std::for_each(InputFilenames.begin(), InputFilenames.end(),
854*9880d681SAndroid Build Coastguard Worker                 printFileSectionSizes);
855*9880d681SAndroid Build Coastguard Worker 
856*9880d681SAndroid Build Coastguard Worker   if (HadError)
857*9880d681SAndroid Build Coastguard Worker     return 1;
858*9880d681SAndroid Build Coastguard Worker }
859