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