1 //===-- llvm-size.cpp - Print the size of each object section -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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
14 //===----------------------------------------------------------------------===//
16 #include "llvm/ADT/APInt.h"
17 #include "llvm/Object/Archive.h"
18 #include "llvm/Object/ObjectFile.h"
19 #include "llvm/Object/MachO.h"
20 #include "llvm/Object/MachOUniversal.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"
32 #include <system_error>
34 using namespace object;
36 enum OutputFormatTy {berkeley, sysv, darwin};
37 static cl::opt<OutputFormatTy>
38 OutputFormat("format",
39 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),
45 static cl::opt<OutputFormatTy>
46 OutputFormatShort(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"),
53 static bool berkeleyHeaderPrinted = false;
54 static bool moreThanOneFile = false;
56 cl::opt<bool> DarwinLongFormat("l",
57 cl::desc("When format is darwin, use long format "
58 "to include addresses and offsets."));
60 static cl::list<std::string>
62 cl::desc("architecture(s) from a Mach-O file to dump"),
66 enum RadixTy {octal = 8, decimal = 10, hexadecimal = 16};
67 static cl::opt<unsigned int>
69 cl::desc("Print size in radix. Only 8, 10, and 16 are valid"),
72 static cl::opt<RadixTy>
73 RadixShort(cl::desc("Print size in radix:"),
74 cl::values(clEnumValN(octal, "o", "Print size in octal"),
75 clEnumValN(decimal, "d", "Print size in decimal"),
76 clEnumValN(hexadecimal, "x", "Print size in hexadecimal"),
80 static cl::list<std::string>
81 InputFilenames(cl::Positional, cl::desc("<input files>"),
84 static std::string ToolName;
86 /// @brief If ec is not success, print the error and return true.
87 static bool error(std::error_code ec) {
88 if (!ec) return false;
90 outs() << ToolName << ": error reading file: " << ec.message() << ".\n";
95 /// @brief Get the length of the string that represents @p num in Radix
96 /// including the leading 0x or 0 for hexadecimal and octal respectively.
97 static size_t getNumLengthAsString(uint64_t num) {
99 SmallString<32> result;
100 conv.toString(result, Radix, false, true);
101 return result.size();
104 /// @brief Return the the printing format for the Radix.
105 static const char * getRadixFmt(void) {
117 /// @brief Print the size of each Mach-O segment and section in @p MachO.
119 /// This is when used when @c OutputFormat is darwin and produces the same
120 /// output as darwin's size(1) -m output.
121 static void PrintDarwinSectionSizes(MachOObjectFile *MachO) {
123 raw_string_ostream fmt(fmtbuf);
124 const char *radix_fmt = getRadixFmt();
125 if (Radix == hexadecimal)
127 fmt << "%" << radix_fmt;
129 uint32_t LoadCommandCount = MachO->getHeader().ncmds;
130 uint32_t Filetype = MachO->getHeader().filetype;
131 MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
134 for (unsigned I = 0; ; ++I) {
135 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
136 MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
137 outs() << "Segment " << Seg.segname << ": "
138 << format(fmt.str().c_str(), Seg.vmsize);
139 if (DarwinLongFormat)
140 outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr)
141 << " fileoff " << Seg.fileoff << ")";
144 uint64_t sec_total = 0;
145 for (unsigned J = 0; J < Seg.nsects; ++J) {
146 MachO::section_64 Sec = MachO->getSection64(Load, J);
147 if (Filetype == MachO::MH_OBJECT)
148 outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
149 << format("%.16s", &Sec.sectname) << "): ";
151 outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
152 outs() << format(fmt.str().c_str(), Sec.size);
153 if (DarwinLongFormat)
154 outs() << " (addr 0x" << format("%" PRIx64, Sec.addr)
155 << " offset " << Sec.offset << ")";
157 sec_total += Sec.size;
160 outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
162 else if (Load.C.cmd == MachO::LC_SEGMENT) {
163 MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
164 outs() << "Segment " << Seg.segname << ": "
165 << format(fmt.str().c_str(), Seg.vmsize);
166 if (DarwinLongFormat)
167 outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr)
168 << " fileoff " << Seg.fileoff << ")";
171 uint64_t sec_total = 0;
172 for (unsigned J = 0; J < Seg.nsects; ++J) {
173 MachO::section Sec = MachO->getSection(Load, J);
174 if (Filetype == MachO::MH_OBJECT)
175 outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
176 << format("%.16s", &Sec.sectname) << "): ";
178 outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
179 outs() << format(fmt.str().c_str(), Sec.size);
180 if (DarwinLongFormat)
181 outs() << " (addr 0x" << format("%" PRIx64, Sec.addr)
182 << " offset " << Sec.offset << ")";
184 sec_total += Sec.size;
187 outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
189 if (I == LoadCommandCount - 1)
192 Load = MachO->getNextLoadCommandInfo(Load);
194 outs() << "total " << format(fmt.str().c_str(), total) << "\n";
197 /// @brief Print the summary sizes of the standard Mach-O segments in @p MachO.
199 /// This is when used when @c OutputFormat is berkeley with a Mach-O file and
200 /// produces the same output as darwin's size(1) default output.
201 static void PrintDarwinSegmentSizes(MachOObjectFile *MachO) {
202 uint32_t LoadCommandCount = MachO->getHeader().ncmds;
203 MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
205 uint64_t total_text = 0;
206 uint64_t total_data = 0;
207 uint64_t total_objc = 0;
208 uint64_t total_others = 0;
209 for (unsigned I = 0; ; ++I) {
210 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
211 MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
212 if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
213 for (unsigned J = 0; J < Seg.nsects; ++J) {
214 MachO::section_64 Sec = MachO->getSection64(Load, J);
215 StringRef SegmentName = StringRef(Sec.segname);
216 if (SegmentName == "__TEXT")
217 total_text += Sec.size;
218 else if (SegmentName == "__DATA")
219 total_data += Sec.size;
220 else if (SegmentName == "__OBJC")
221 total_objc += Sec.size;
223 total_others += Sec.size;
226 StringRef SegmentName = StringRef(Seg.segname);
227 if (SegmentName == "__TEXT")
228 total_text += Seg.vmsize;
229 else if (SegmentName == "__DATA")
230 total_data += Seg.vmsize;
231 else if (SegmentName == "__OBJC")
232 total_objc += Seg.vmsize;
234 total_others += Seg.vmsize;
237 else if (Load.C.cmd == MachO::LC_SEGMENT) {
238 MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
239 if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
240 for (unsigned J = 0; J < Seg.nsects; ++J) {
241 MachO::section Sec = MachO->getSection(Load, J);
242 StringRef SegmentName = StringRef(Sec.segname);
243 if (SegmentName == "__TEXT")
244 total_text += Sec.size;
245 else if (SegmentName == "__DATA")
246 total_data += Sec.size;
247 else if (SegmentName == "__OBJC")
248 total_objc += Sec.size;
250 total_others += Sec.size;
253 StringRef SegmentName = StringRef(Seg.segname);
254 if (SegmentName == "__TEXT")
255 total_text += Seg.vmsize;
256 else if (SegmentName == "__DATA")
257 total_data += Seg.vmsize;
258 else if (SegmentName == "__OBJC")
259 total_objc += Seg.vmsize;
261 total_others += Seg.vmsize;
264 if (I == LoadCommandCount - 1)
267 Load = MachO->getNextLoadCommandInfo(Load);
269 uint64_t total = total_text + total_data + total_objc + total_others;
271 if (!berkeleyHeaderPrinted) {
272 outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
273 berkeleyHeaderPrinted = true;
275 outs() << total_text << "\t" << total_data << "\t" << total_objc << "\t"
276 << total_others << "\t" << total << "\t" << format("%" PRIx64, total)
280 /// @brief Print the size of each section in @p Obj.
282 /// The format used is determined by @c OutputFormat and @c Radix.
283 static void PrintObjectSectionSizes(ObjectFile *Obj) {
286 raw_string_ostream fmt(fmtbuf);
287 const char *radix_fmt = getRadixFmt();
289 // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
290 // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
291 // let it fall through to OutputFormat berkeley.
292 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
293 if (OutputFormat == darwin && MachO)
294 PrintDarwinSectionSizes(MachO);
295 // If we have a MachOObjectFile and the OutputFormat is berkeley print as
296 // darwin's default berkeley format for Mach-O files.
297 else if (MachO && OutputFormat == berkeley)
298 PrintDarwinSegmentSizes(MachO);
299 else if (OutputFormat == sysv) {
300 // Run two passes over all sections. The first gets the lengths needed for
301 // formatting the output. The second actually does the output.
302 std::size_t max_name_len = strlen("section");
303 std::size_t max_size_len = strlen("size");
304 std::size_t max_addr_len = strlen("addr");
305 for (const SectionRef &Section : Obj->sections()) {
307 if (error(Section.getSize(size)))
313 if (error(Section.getName(name)))
315 if (error(Section.getAddress(addr)))
317 max_name_len = std::max(max_name_len, name.size());
318 max_size_len = std::max(max_size_len, getNumLengthAsString(size));
319 max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr));
322 // Add extra padding.
327 // Setup header format.
328 fmt << "%-" << max_name_len << "s "
329 << "%" << max_size_len << "s "
330 << "%" << max_addr_len << "s\n";
333 outs() << format(fmt.str().c_str(),
334 static_cast<const char*>("section"),
335 static_cast<const char*>("size"),
336 static_cast<const char*>("addr"));
339 // Setup per section format.
340 fmt << "%-" << max_name_len << "s "
341 << "%#" << max_size_len << radix_fmt << " "
342 << "%#" << max_addr_len << radix_fmt << "\n";
344 // Print each section.
345 for (const SectionRef &Section : Obj->sections()) {
349 if (error(Section.getName(name)))
351 if (error(Section.getSize(size)))
353 if (error(Section.getAddress(addr)))
355 std::string namestr = name;
357 outs() << format(fmt.str().c_str(), namestr.c_str(), size, addr);
362 fmt << "%-" << max_name_len << "s "
363 << "%#" << max_size_len << radix_fmt << "\n";
364 outs() << format(fmt.str().c_str(),
365 static_cast<const char*>("Total"),
368 // The Berkeley format does not display individual section sizes. It
369 // displays the cumulative size for each section type.
370 uint64_t total_text = 0;
371 uint64_t total_data = 0;
372 uint64_t total_bss = 0;
374 // Make one pass over the section table to calculate sizes.
375 for (const SectionRef &Section : Obj->sections()) {
380 if (error(Section.getSize(size)))
382 if (error(Section.isText(isText)))
384 if (error(Section.isData(isData)))
386 if (error(Section.isBSS(isBSS)))
396 total = total_text + total_data + total_bss;
398 if (!berkeleyHeaderPrinted) {
399 outs() << " text data bss "
400 << (Radix == octal ? "oct" : "dec")
401 << " hex filename\n";
402 berkeleyHeaderPrinted = true;
406 fmt << "%#7" << radix_fmt << " "
407 << "%#7" << radix_fmt << " "
408 << "%#7" << radix_fmt << " ";
409 outs() << format(fmt.str().c_str(),
414 fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << " "
416 outs() << format(fmt.str().c_str(),
422 /// @brief Checks to see if the @p o ObjectFile is a Mach-O file and if it is
423 /// and there is a list of architecture flags specified then check to
424 /// make sure this Mach-O file is one of those architectures or all
425 /// architectures was specificed. If not then an error is generated and
426 /// this routine returns false. Else it returns true.
427 static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) {
428 if (isa<MachOObjectFile>(o) && !ArchAll && ArchFlags.size() != 0) {
429 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
430 bool ArchFound = false;
431 MachO::mach_header H;
432 MachO::mach_header_64 H_64;
434 if (MachO->is64Bit()) {
435 H_64 = MachO->MachOObjectFile::getHeader64();
436 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype);
438 H = MachO->MachOObjectFile::getHeader();
439 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype);
442 for (i = 0; i < ArchFlags.size(); ++i){
443 if (ArchFlags[i] == T.getArchName())
448 errs() << ToolName << ": file: " << file
449 << " does not contain architecture: " << ArchFlags[i] << ".\n";
456 /// @brief Print the section sizes for @p file. If @p file is an archive, print
457 /// the section sizes for each archive member.
458 static void PrintFileSectionSizes(StringRef file) {
459 // If file is not stdin, check that it exists.
462 if (sys::fs::exists(file, exists) || !exists) {
463 errs() << ToolName << ": '" << file << "': " << "No such file\n";
468 // Attempt to open the binary.
469 ErrorOr<Binary *> BinaryOrErr = createBinary(file);
470 if (std::error_code EC = BinaryOrErr.getError()) {
471 errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
474 std::unique_ptr<Binary> binary(BinaryOrErr.get());
476 if (Archive *a = dyn_cast<Archive>(binary.get())) {
477 // This is an archive. Iterate over each member and display its sizes.
478 for (object::Archive::child_iterator i = a->child_begin(),
479 e = a->child_end(); i != e; ++i) {
480 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
481 if (std::error_code EC = ChildOrErr.getError()) {
482 errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
485 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
486 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
487 if (!checkMachOAndArchFlags(o, file))
489 if (OutputFormat == sysv)
490 outs() << o->getFileName() << " (ex " << a->getFileName()
492 else if(MachO && OutputFormat == darwin)
493 outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
494 PrintObjectSectionSizes(o);
495 if (OutputFormat == berkeley) {
497 outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
499 outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
503 } else if (MachOUniversalBinary *UB =
504 dyn_cast<MachOUniversalBinary>(binary.get())) {
505 // If we have a list of architecture flags specified dump only those.
506 if (!ArchAll && ArchFlags.size() != 0) {
507 // Look for a slice in the universal binary that matches each ArchFlag.
509 for (unsigned i = 0; i < ArchFlags.size(); ++i){
511 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
512 E = UB->end_objects();
514 if (ArchFlags[i] == I->getArchTypeName()){
516 ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
517 std::unique_ptr<Archive> UA;
519 if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
520 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
521 if (OutputFormat == sysv)
522 outs() << o->getFileName() << " :\n";
523 else if(MachO && OutputFormat == darwin) {
524 if (moreThanOneFile || ArchFlags.size() > 1)
525 outs() << o->getFileName() << " (for architecture "
526 << I->getArchTypeName() << "): \n";
528 PrintObjectSectionSizes(o);
529 if (OutputFormat == berkeley) {
530 if (!MachO || moreThanOneFile || ArchFlags.size() > 1)
531 outs() << o->getFileName() << " (for architecture "
532 << I->getArchTypeName() << ")";
537 else if (!I->getAsArchive(UA)) {
538 // This is an archive. Iterate over each member and display its
540 for (object::Archive::child_iterator i = UA->child_begin(),
543 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
544 if (std::error_code EC = ChildOrErr.getError()) {
545 errs() << ToolName << ": " << file << ": " << EC.message()
549 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
550 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
551 if (OutputFormat == sysv)
552 outs() << o->getFileName() << " (ex " << UA->getFileName()
554 else if(MachO && OutputFormat == darwin)
555 outs() << UA->getFileName() << "(" << o->getFileName()
556 << ")" << " (for architecture "
557 << I->getArchTypeName() << "):\n";
558 PrintObjectSectionSizes(o);
559 if (OutputFormat == berkeley) {
561 outs() << UA->getFileName() << "(" << o->getFileName()
563 if (ArchFlags.size() > 1)
564 outs() << " (for architecture "
565 << I->getArchTypeName() << ")";
569 outs() << o->getFileName() << " (ex " << UA->getFileName()
578 errs() << ToolName << ": file: " << file
579 << " does not contain architecture" << ArchFlags[i] << ".\n";
585 // No architecture flags were specified so if this contains a slice that
586 // matches the host architecture dump only that.
588 StringRef HostArchName =
589 MachOObjectFile::getHostArch().getArchName();
590 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
591 E = UB->end_objects();
593 if (HostArchName == I->getArchTypeName()){
594 ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
595 std::unique_ptr<Archive> UA;
597 if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
598 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
599 if (OutputFormat == sysv)
600 outs() << o->getFileName() << " :\n";
601 else if(MachO && OutputFormat == darwin) {
603 outs() << o->getFileName() << " (for architecture "
604 << I->getArchTypeName() << "):\n";
606 PrintObjectSectionSizes(o);
607 if (OutputFormat == berkeley) {
608 if (!MachO || moreThanOneFile)
609 outs() << o->getFileName() << " (for architecture "
610 << I->getArchTypeName() << ")";
615 else if (!I->getAsArchive(UA)) {
616 // This is an archive. Iterate over each member and display its
618 for (object::Archive::child_iterator i = UA->child_begin(),
621 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
622 if (std::error_code EC = ChildOrErr.getError()) {
623 errs() << ToolName << ": " << file << ": " << EC.message()
627 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
628 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
629 if (OutputFormat == sysv)
630 outs() << o->getFileName() << " (ex " << UA->getFileName()
632 else if(MachO && OutputFormat == darwin)
633 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
634 << " (for architecture " << I->getArchTypeName()
636 PrintObjectSectionSizes(o);
637 if (OutputFormat == berkeley) {
639 outs() << UA->getFileName() << "(" << o->getFileName()
642 outs() << o->getFileName() << " (ex " << UA->getFileName()
652 // Either all architectures have been specified or none have been specified
653 // and this does not contain the host architecture so dump all the slices.
654 bool moreThanOneArch = UB->getNumberOfObjects() > 1;
655 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
656 E = UB->end_objects();
658 ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
659 std::unique_ptr<Archive> UA;
661 if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
662 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
663 if (OutputFormat == sysv)
664 outs() << o->getFileName() << " :\n";
665 else if(MachO && OutputFormat == darwin) {
666 if (moreThanOneFile || moreThanOneArch)
667 outs() << o->getFileName() << " (for architecture "
668 << I->getArchTypeName() << "):";
671 PrintObjectSectionSizes(o);
672 if (OutputFormat == berkeley) {
673 if (!MachO || moreThanOneFile || moreThanOneArch)
674 outs() << o->getFileName() << " (for architecture "
675 << I->getArchTypeName() << ")";
680 else if (!I->getAsArchive(UA)) {
681 // This is an archive. Iterate over each member and display its sizes.
682 for (object::Archive::child_iterator i = UA->child_begin(),
683 e = UA->child_end(); i != e; ++i) {
684 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
685 if (std::error_code EC = ChildOrErr.getError()) {
686 errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
689 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
690 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
691 if (OutputFormat == sysv)
692 outs() << o->getFileName() << " (ex " << UA->getFileName()
694 else if(MachO && OutputFormat == darwin)
695 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
696 << " (for architecture " << I->getArchTypeName()
698 PrintObjectSectionSizes(o);
699 if (OutputFormat == berkeley) {
701 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
702 << " (for architecture " << I->getArchTypeName()
705 outs() << o->getFileName() << " (ex " << UA->getFileName()
712 } else if (ObjectFile *o = dyn_cast<ObjectFile>(binary.get())) {
713 if (!checkMachOAndArchFlags(o, file))
715 if (OutputFormat == sysv)
716 outs() << o->getFileName() << " :\n";
717 PrintObjectSectionSizes(o);
718 if (OutputFormat == berkeley) {
719 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
720 if (!MachO || moreThanOneFile)
721 outs() << o->getFileName();
725 errs() << ToolName << ": " << file << ": " << "Unrecognized file type.\n";
727 // System V adds an extra newline at the end of each file.
728 if (OutputFormat == sysv)
732 int main(int argc, char **argv) {
733 // Print a stack trace if we signal out.
734 sys::PrintStackTraceOnErrorSignal();
735 PrettyStackTraceProgram X(argc, argv);
737 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
738 cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n");
741 if (OutputFormatShort.getNumOccurrences())
742 OutputFormat = OutputFormatShort;
743 if (RadixShort.getNumOccurrences())
746 for (unsigned i = 0; i < ArchFlags.size(); ++i){
747 if (ArchFlags[i] == "all") {
751 Triple T = MachOObjectFile::getArch(ArchFlags[i]);
752 if (T.getArch() == Triple::UnknownArch){
753 outs() << ToolName << ": for the -arch option: Unknown architecture "
754 << "named '" << ArchFlags[i] << "'";
760 if (InputFilenames.size() == 0)
761 InputFilenames.push_back("a.out");
763 moreThanOneFile = InputFilenames.size() > 1;
764 std::for_each(InputFilenames.begin(), InputFilenames.end(),
765 PrintFileSectionSizes);