Merging r259798, r259835:
[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       if (i->getError()) {
432         errs() << ToolName << ": " << file << ": " << i->getError().message()
433                << ".\n";
434         exit(1);
435       }
436       auto &c = i->get();
437       ErrorOr<std::unique_ptr<Binary>> ChildOrErr = c.getAsBinary();
438       if (std::error_code EC = ChildOrErr.getError()) {
439         errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
440         continue;
441       }
442       if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
443         MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
444         if (!checkMachOAndArchFlags(o, file))
445           return;
446         if (OutputFormat == sysv)
447           outs() << o->getFileName() << "   (ex " << a->getFileName() << "):\n";
448         else if (MachO && OutputFormat == darwin)
449           outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
450         PrintObjectSectionSizes(o);
451         if (OutputFormat == berkeley) {
452           if (MachO)
453             outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
454           else
455             outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
456         }
457       }
458     }
459   } else if (MachOUniversalBinary *UB =
460                  dyn_cast<MachOUniversalBinary>(&Bin)) {
461     // If we have a list of architecture flags specified dump only those.
462     if (!ArchAll && ArchFlags.size() != 0) {
463       // Look for a slice in the universal binary that matches each ArchFlag.
464       bool ArchFound;
465       for (unsigned i = 0; i < ArchFlags.size(); ++i) {
466         ArchFound = false;
467         for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
468                                                    E = UB->end_objects();
469              I != E; ++I) {
470           if (ArchFlags[i] == I->getArchTypeName()) {
471             ArchFound = true;
472             ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
473             if (UO) {
474               if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
475                 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
476                 if (OutputFormat == sysv)
477                   outs() << o->getFileName() << "  :\n";
478                 else if (MachO && OutputFormat == darwin) {
479                   if (moreThanOneFile || ArchFlags.size() > 1)
480                     outs() << o->getFileName() << " (for architecture "
481                            << I->getArchTypeName() << "): \n";
482                 }
483                 PrintObjectSectionSizes(o);
484                 if (OutputFormat == berkeley) {
485                   if (!MachO || moreThanOneFile || ArchFlags.size() > 1)
486                     outs() << o->getFileName() << " (for architecture "
487                            << I->getArchTypeName() << ")";
488                   outs() << "\n";
489                 }
490               }
491             } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
492                            I->getAsArchive()) {
493               std::unique_ptr<Archive> &UA = *AOrErr;
494               // This is an archive. Iterate over each member and display its
495               // sizes.
496               for (object::Archive::child_iterator i = UA->child_begin(),
497                                                    e = UA->child_end();
498                    i != e; ++i) {
499                 if (std::error_code EC = i->getError()) {
500                   errs() << ToolName << ": " << file << ": " << EC.message()
501                          << ".\n";
502                   exit(1);
503                 }
504                 auto &c = i->get();
505                 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = c.getAsBinary();
506                 if (std::error_code EC = ChildOrErr.getError()) {
507                   errs() << ToolName << ": " << file << ": " << EC.message()
508                          << ".\n";
509                   continue;
510                 }
511                 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
512                   MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
513                   if (OutputFormat == sysv)
514                     outs() << o->getFileName() << "   (ex " << UA->getFileName()
515                            << "):\n";
516                   else if (MachO && OutputFormat == darwin)
517                     outs() << UA->getFileName() << "(" << o->getFileName()
518                            << ")"
519                            << " (for architecture " << I->getArchTypeName()
520                            << "):\n";
521                   PrintObjectSectionSizes(o);
522                   if (OutputFormat == berkeley) {
523                     if (MachO) {
524                       outs() << UA->getFileName() << "(" << o->getFileName()
525                              << ")";
526                       if (ArchFlags.size() > 1)
527                         outs() << " (for architecture " << I->getArchTypeName()
528                                << ")";
529                       outs() << "\n";
530                     } else
531                       outs() << o->getFileName() << " (ex " << UA->getFileName()
532                              << ")\n";
533                   }
534                 }
535               }
536             }
537           }
538         }
539         if (!ArchFound) {
540           errs() << ToolName << ": file: " << file
541                  << " does not contain architecture" << ArchFlags[i] << ".\n";
542           return;
543         }
544       }
545       return;
546     }
547     // No architecture flags were specified so if this contains a slice that
548     // matches the host architecture dump only that.
549     if (!ArchAll) {
550       StringRef HostArchName = MachOObjectFile::getHostArch().getArchName();
551       for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
552                                                  E = UB->end_objects();
553            I != E; ++I) {
554         if (HostArchName == I->getArchTypeName()) {
555           ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
556           if (UO) {
557             if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
558               MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
559               if (OutputFormat == sysv)
560                 outs() << o->getFileName() << "  :\n";
561               else if (MachO && OutputFormat == darwin) {
562                 if (moreThanOneFile)
563                   outs() << o->getFileName() << " (for architecture "
564                          << I->getArchTypeName() << "):\n";
565               }
566               PrintObjectSectionSizes(o);
567               if (OutputFormat == berkeley) {
568                 if (!MachO || moreThanOneFile)
569                   outs() << o->getFileName() << " (for architecture "
570                          << I->getArchTypeName() << ")";
571                 outs() << "\n";
572               }
573             }
574           } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
575                          I->getAsArchive()) {
576             std::unique_ptr<Archive> &UA = *AOrErr;
577             // This is an archive. Iterate over each member and display its
578             // sizes.
579             for (object::Archive::child_iterator i = UA->child_begin(),
580                                                  e = UA->child_end();
581                  i != e; ++i) {
582               if (std::error_code EC = i->getError()) {
583                 errs() << ToolName << ": " << file << ": " << EC.message()
584                        << ".\n";
585                 exit(1);
586               }
587               auto &c = i->get();
588               ErrorOr<std::unique_ptr<Binary>> ChildOrErr = c.getAsBinary();
589               if (std::error_code EC = ChildOrErr.getError()) {
590                 errs() << ToolName << ": " << file << ": " << EC.message()
591                        << ".\n";
592                 continue;
593               }
594               if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
595                 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
596                 if (OutputFormat == sysv)
597                   outs() << o->getFileName() << "   (ex " << UA->getFileName()
598                          << "):\n";
599                 else if (MachO && OutputFormat == darwin)
600                   outs() << UA->getFileName() << "(" << o->getFileName() << ")"
601                          << " (for architecture " << I->getArchTypeName()
602                          << "):\n";
603                 PrintObjectSectionSizes(o);
604                 if (OutputFormat == berkeley) {
605                   if (MachO)
606                     outs() << UA->getFileName() << "(" << o->getFileName()
607                            << ")\n";
608                   else
609                     outs() << o->getFileName() << " (ex " << UA->getFileName()
610                            << ")\n";
611                 }
612               }
613             }
614           }
615           return;
616         }
617       }
618     }
619     // Either all architectures have been specified or none have been specified
620     // and this does not contain the host architecture so dump all the slices.
621     bool moreThanOneArch = UB->getNumberOfObjects() > 1;
622     for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
623                                                E = UB->end_objects();
624          I != E; ++I) {
625       ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
626       if (UO) {
627         if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
628           MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
629           if (OutputFormat == sysv)
630             outs() << o->getFileName() << "  :\n";
631           else if (MachO && OutputFormat == darwin) {
632             if (moreThanOneFile || moreThanOneArch)
633               outs() << o->getFileName() << " (for architecture "
634                      << I->getArchTypeName() << "):";
635             outs() << "\n";
636           }
637           PrintObjectSectionSizes(o);
638           if (OutputFormat == berkeley) {
639             if (!MachO || moreThanOneFile || moreThanOneArch)
640               outs() << o->getFileName() << " (for architecture "
641                      << I->getArchTypeName() << ")";
642             outs() << "\n";
643           }
644         }
645       } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
646                          I->getAsArchive()) {
647         std::unique_ptr<Archive> &UA = *AOrErr;
648         // This is an archive. Iterate over each member and display its sizes.
649         for (object::Archive::child_iterator i = UA->child_begin(),
650                                              e = UA->child_end();
651              i != e; ++i) {
652           if (std::error_code EC = i->getError()) {
653             errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
654             exit(1);
655           }
656           auto &c = i->get();
657           ErrorOr<std::unique_ptr<Binary>> ChildOrErr = c.getAsBinary();
658           if (std::error_code EC = ChildOrErr.getError()) {
659             errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
660             continue;
661           }
662           if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
663             MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
664             if (OutputFormat == sysv)
665               outs() << o->getFileName() << "   (ex " << UA->getFileName()
666                      << "):\n";
667             else if (MachO && OutputFormat == darwin)
668               outs() << UA->getFileName() << "(" << o->getFileName() << ")"
669                      << " (for architecture " << I->getArchTypeName() << "):\n";
670             PrintObjectSectionSizes(o);
671             if (OutputFormat == berkeley) {
672               if (MachO)
673                 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
674                        << " (for architecture " << I->getArchTypeName()
675                        << ")\n";
676               else
677                 outs() << o->getFileName() << " (ex " << UA->getFileName()
678                        << ")\n";
679             }
680           }
681         }
682       }
683     }
684   } else if (ObjectFile *o = dyn_cast<ObjectFile>(&Bin)) {
685     if (!checkMachOAndArchFlags(o, file))
686       return;
687     if (OutputFormat == sysv)
688       outs() << o->getFileName() << "  :\n";
689     PrintObjectSectionSizes(o);
690     if (OutputFormat == berkeley) {
691       MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
692       if (!MachO || moreThanOneFile)
693         outs() << o->getFileName();
694       outs() << "\n";
695     }
696   } else {
697     errs() << ToolName << ": " << file << ": "
698            << "Unrecognized file type.\n";
699   }
700   // System V adds an extra newline at the end of each file.
701   if (OutputFormat == sysv)
702     outs() << "\n";
703 }
704
705 int main(int argc, char **argv) {
706   // Print a stack trace if we signal out.
707   sys::PrintStackTraceOnErrorSignal();
708   PrettyStackTraceProgram X(argc, argv);
709
710   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
711   cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n");
712
713   ToolName = argv[0];
714   if (OutputFormatShort.getNumOccurrences())
715     OutputFormat = static_cast<OutputFormatTy>(OutputFormatShort);
716   if (RadixShort.getNumOccurrences())
717     Radix = RadixShort;
718
719   for (unsigned i = 0; i < ArchFlags.size(); ++i) {
720     if (ArchFlags[i] == "all") {
721       ArchAll = true;
722     } else {
723       if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
724         outs() << ToolName << ": for the -arch option: Unknown architecture "
725                << "named '" << ArchFlags[i] << "'";
726         return 1;
727       }
728     }
729   }
730
731   if (InputFilenames.size() == 0)
732     InputFilenames.push_back("a.out");
733
734   moreThanOneFile = InputFilenames.size() > 1;
735   std::for_each(InputFilenames.begin(), InputFilenames.end(),
736                 PrintFileSectionSizes);
737
738   return 0;
739 }