1 //===-- llvm-size.cpp - Print the size of each object section ---*- C++ -*-===//
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/ELFObjectFile.h"
19 #include "llvm/Object/MachO.h"
20 #include "llvm/Object/MachOUniversal.h"
21 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/CommandLine.h"
24 #include "llvm/Support/FileSystem.h"
25 #include "llvm/Support/Format.h"
26 #include "llvm/Support/ManagedStatic.h"
27 #include "llvm/Support/MemoryBuffer.h"
28 #include "llvm/Support/PrettyStackTrace.h"
29 #include "llvm/Support/Signals.h"
30 #include "llvm/Support/raw_ostream.h"
33 #include <system_error>
36 using namespace object
;
38 enum OutputFormatTy
{ berkeley
, sysv
, darwin
};
39 static cl::opt
<OutputFormatTy
>
40 OutputFormat("format", cl::desc("Specify output format"),
41 cl::values(clEnumVal(sysv
, "System V format"),
42 clEnumVal(berkeley
, "Berkeley format"),
43 clEnumVal(darwin
, "Darwin -m format")),
46 static cl::opt
<OutputFormatTy
> OutputFormatShort(
47 cl::desc("Specify output format"),
48 cl::values(clEnumValN(sysv
, "A", "System V format"),
49 clEnumValN(berkeley
, "B", "Berkeley format"),
50 clEnumValN(darwin
, "m", "Darwin -m format")),
53 static bool BerkeleyHeaderPrinted
= false;
54 static bool MoreThanOneFile
= false;
55 static uint64_t TotalObjectText
= 0;
56 static uint64_t TotalObjectData
= 0;
57 static uint64_t TotalObjectBss
= 0;
58 static uint64_t TotalObjectTotal
= 0;
61 DarwinLongFormat("l", cl::desc("When format is darwin, use long format "
62 "to include addresses and offsets."));
66 cl::desc("Print common symbols in the ELF file. When using "
67 "Berkely format, this is added to bss."),
70 static cl::list
<std::string
>
71 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
75 enum RadixTy
{ octal
= 8, decimal
= 10, hexadecimal
= 16 };
76 static cl::opt
<unsigned int>
77 Radix("radix", cl::desc("Print size in radix. Only 8, 10, and 16 are valid"),
80 static cl::opt
<RadixTy
>
81 RadixShort(cl::desc("Print size in radix:"),
82 cl::values(clEnumValN(octal
, "o", "Print size in octal"),
83 clEnumValN(decimal
, "d", "Print size in decimal"),
84 clEnumValN(hexadecimal
, "x", "Print size in hexadecimal")),
89 cl::desc("Print totals of all objects - Berkeley format only"),
92 static cl::alias
TotalSizesShort("t", cl::desc("Short for --totals"),
93 cl::aliasopt(TotalSizes
));
95 static cl::list
<std::string
>
96 InputFilenames(cl::Positional
, cl::desc("<input files>"), cl::ZeroOrMore
);
98 bool HadError
= false;
100 static std::string ToolName
;
102 /// If ec is not success, print the error and return true.
103 static bool error(std::error_code ec
) {
108 errs() << ToolName
<< ": error reading file: " << ec
.message() << ".\n";
113 static bool error(Twine Message
) {
115 errs() << ToolName
<< ": " << Message
<< ".\n";
120 // This version of error() prints the archive name and member name, for example:
121 // "libx.a(foo.o)" after the ToolName before the error message. It sets
122 // HadError but returns allowing the code to move on to other archive members.
123 static void error(llvm::Error E
, StringRef FileName
, const Archive::Child
&C
,
124 StringRef ArchitectureName
= StringRef()) {
126 errs() << ToolName
<< ": " << FileName
;
128 Expected
<StringRef
> NameOrErr
= C
.getName();
129 // TODO: if we have a error getting the name then it would be nice to print
130 // the index of which archive member this is and or its offset in the
131 // archive instead of "???" as the name.
133 consumeError(NameOrErr
.takeError());
134 errs() << "(" << "???" << ")";
136 errs() << "(" << NameOrErr
.get() << ")";
138 if (!ArchitectureName
.empty())
139 errs() << " (for architecture " << ArchitectureName
<< ") ";
142 raw_string_ostream
OS(Buf
);
143 logAllUnhandledErrors(std::move(E
), OS
, "");
145 errs() << " " << Buf
<< "\n";
148 // 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
149 // before the error message. It sets HadError but returns allowing the code to
150 // move on to other architecture slices.
151 static void error(llvm::Error E
, StringRef FileName
,
152 StringRef ArchitectureName
= StringRef()) {
154 errs() << ToolName
<< ": " << FileName
;
156 if (!ArchitectureName
.empty())
157 errs() << " (for architecture " << ArchitectureName
<< ") ";
160 raw_string_ostream
OS(Buf
);
161 logAllUnhandledErrors(std::move(E
), OS
, "");
163 errs() << " " << Buf
<< "\n";
166 /// Get the length of the string that represents @p num in Radix including the
167 /// leading 0x or 0 for hexadecimal and octal respectively.
168 static size_t getNumLengthAsString(uint64_t num
) {
170 SmallString
<32> result
;
171 conv
.toString(result
, Radix
, false, true);
172 return result
.size();
175 /// Return the printing format for the Radix.
176 static const char *getRadixFmt() {
188 /// Remove unneeded ELF sections from calculation
189 static bool considerForSize(ObjectFile
*Obj
, SectionRef Section
) {
192 switch (static_cast<ELFSectionRef
>(Section
).getType()) {
194 case ELF::SHT_SYMTAB
:
195 case ELF::SHT_STRTAB
:
203 /// Total size of all ELF common symbols
204 static uint64_t getCommonSize(ObjectFile
*Obj
) {
205 uint64_t TotalCommons
= 0;
206 for (auto &Sym
: Obj
->symbols())
207 if (Obj
->getSymbolFlags(Sym
.getRawDataRefImpl()) & SymbolRef::SF_Common
)
208 TotalCommons
+= Obj
->getCommonSymbolSize(Sym
.getRawDataRefImpl());
212 /// Print the size of each Mach-O segment and section in @p MachO.
214 /// This is when used when @c OutputFormat is darwin and produces the same
215 /// output as darwin's size(1) -m output.
216 static void printDarwinSectionSizes(MachOObjectFile
*MachO
) {
218 raw_string_ostream
fmt(fmtbuf
);
219 const char *radix_fmt
= getRadixFmt();
220 if (Radix
== hexadecimal
)
222 fmt
<< "%" << radix_fmt
;
224 uint32_t Filetype
= MachO
->getHeader().filetype
;
227 for (const auto &Load
: MachO
->load_commands()) {
228 if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
229 MachO::segment_command_64 Seg
= MachO
->getSegment64LoadCommand(Load
);
230 outs() << "Segment " << Seg
.segname
<< ": "
231 << format(fmt
.str().c_str(), Seg
.vmsize
);
232 if (DarwinLongFormat
)
233 outs() << " (vmaddr 0x" << format("%" PRIx64
, Seg
.vmaddr
) << " fileoff "
234 << Seg
.fileoff
<< ")";
237 uint64_t sec_total
= 0;
238 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
239 MachO::section_64 Sec
= MachO
->getSection64(Load
, J
);
240 if (Filetype
== MachO::MH_OBJECT
)
241 outs() << "\tSection (" << format("%.16s", &Sec
.segname
) << ", "
242 << format("%.16s", &Sec
.sectname
) << "): ";
244 outs() << "\tSection " << format("%.16s", &Sec
.sectname
) << ": ";
245 outs() << format(fmt
.str().c_str(), Sec
.size
);
246 if (DarwinLongFormat
)
247 outs() << " (addr 0x" << format("%" PRIx64
, Sec
.addr
) << " offset "
248 << Sec
.offset
<< ")";
250 sec_total
+= Sec
.size
;
253 outs() << "\ttotal " << format(fmt
.str().c_str(), sec_total
) << "\n";
254 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
255 MachO::segment_command Seg
= MachO
->getSegmentLoadCommand(Load
);
256 uint64_t Seg_vmsize
= Seg
.vmsize
;
257 outs() << "Segment " << Seg
.segname
<< ": "
258 << format(fmt
.str().c_str(), Seg_vmsize
);
259 if (DarwinLongFormat
)
260 outs() << " (vmaddr 0x" << format("%" PRIx32
, Seg
.vmaddr
) << " fileoff "
261 << Seg
.fileoff
<< ")";
264 uint64_t sec_total
= 0;
265 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
266 MachO::section Sec
= MachO
->getSection(Load
, J
);
267 if (Filetype
== MachO::MH_OBJECT
)
268 outs() << "\tSection (" << format("%.16s", &Sec
.segname
) << ", "
269 << format("%.16s", &Sec
.sectname
) << "): ";
271 outs() << "\tSection " << format("%.16s", &Sec
.sectname
) << ": ";
272 uint64_t Sec_size
= Sec
.size
;
273 outs() << format(fmt
.str().c_str(), Sec_size
);
274 if (DarwinLongFormat
)
275 outs() << " (addr 0x" << format("%" PRIx32
, Sec
.addr
) << " offset "
276 << Sec
.offset
<< ")";
278 sec_total
+= Sec
.size
;
281 outs() << "\ttotal " << format(fmt
.str().c_str(), sec_total
) << "\n";
284 outs() << "total " << format(fmt
.str().c_str(), total
) << "\n";
287 /// Print the summary sizes of the standard Mach-O segments in @p MachO.
289 /// This is when used when @c OutputFormat is berkeley with a Mach-O file and
290 /// produces the same output as darwin's size(1) default output.
291 static void printDarwinSegmentSizes(MachOObjectFile
*MachO
) {
292 uint64_t total_text
= 0;
293 uint64_t total_data
= 0;
294 uint64_t total_objc
= 0;
295 uint64_t total_others
= 0;
296 for (const auto &Load
: MachO
->load_commands()) {
297 if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
298 MachO::segment_command_64 Seg
= MachO
->getSegment64LoadCommand(Load
);
299 if (MachO
->getHeader().filetype
== MachO::MH_OBJECT
) {
300 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
301 MachO::section_64 Sec
= MachO
->getSection64(Load
, J
);
302 StringRef SegmentName
= StringRef(Sec
.segname
);
303 if (SegmentName
== "__TEXT")
304 total_text
+= Sec
.size
;
305 else if (SegmentName
== "__DATA")
306 total_data
+= Sec
.size
;
307 else if (SegmentName
== "__OBJC")
308 total_objc
+= Sec
.size
;
310 total_others
+= Sec
.size
;
313 StringRef SegmentName
= StringRef(Seg
.segname
);
314 if (SegmentName
== "__TEXT")
315 total_text
+= Seg
.vmsize
;
316 else if (SegmentName
== "__DATA")
317 total_data
+= Seg
.vmsize
;
318 else if (SegmentName
== "__OBJC")
319 total_objc
+= Seg
.vmsize
;
321 total_others
+= Seg
.vmsize
;
323 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
324 MachO::segment_command Seg
= MachO
->getSegmentLoadCommand(Load
);
325 if (MachO
->getHeader().filetype
== MachO::MH_OBJECT
) {
326 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
327 MachO::section Sec
= MachO
->getSection(Load
, J
);
328 StringRef SegmentName
= StringRef(Sec
.segname
);
329 if (SegmentName
== "__TEXT")
330 total_text
+= Sec
.size
;
331 else if (SegmentName
== "__DATA")
332 total_data
+= Sec
.size
;
333 else if (SegmentName
== "__OBJC")
334 total_objc
+= Sec
.size
;
336 total_others
+= Sec
.size
;
339 StringRef SegmentName
= StringRef(Seg
.segname
);
340 if (SegmentName
== "__TEXT")
341 total_text
+= Seg
.vmsize
;
342 else if (SegmentName
== "__DATA")
343 total_data
+= Seg
.vmsize
;
344 else if (SegmentName
== "__OBJC")
345 total_objc
+= Seg
.vmsize
;
347 total_others
+= Seg
.vmsize
;
351 uint64_t total
= total_text
+ total_data
+ total_objc
+ total_others
;
353 if (!BerkeleyHeaderPrinted
) {
354 outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
355 BerkeleyHeaderPrinted
= true;
357 outs() << total_text
<< "\t" << total_data
<< "\t" << total_objc
<< "\t"
358 << total_others
<< "\t" << total
<< "\t" << format("%" PRIx64
, total
)
362 /// Print the size of each section in @p Obj.
364 /// The format used is determined by @c OutputFormat and @c Radix.
365 static void printObjectSectionSizes(ObjectFile
*Obj
) {
368 raw_string_ostream
fmt(fmtbuf
);
369 const char *radix_fmt
= getRadixFmt();
371 // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
372 // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
373 // let it fall through to OutputFormat berkeley.
374 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(Obj
);
375 if (OutputFormat
== darwin
&& MachO
)
376 printDarwinSectionSizes(MachO
);
377 // If we have a MachOObjectFile and the OutputFormat is berkeley print as
378 // darwin's default berkeley format for Mach-O files.
379 else if (MachO
&& OutputFormat
== berkeley
)
380 printDarwinSegmentSizes(MachO
);
381 else if (OutputFormat
== sysv
) {
382 // Run two passes over all sections. The first gets the lengths needed for
383 // formatting the output. The second actually does the output.
384 std::size_t max_name_len
= strlen("section");
385 std::size_t max_size_len
= strlen("size");
386 std::size_t max_addr_len
= strlen("addr");
387 for (const SectionRef
&Section
: Obj
->sections()) {
388 if (!considerForSize(Obj
, Section
))
390 uint64_t size
= Section
.getSize();
394 if (error(Section
.getName(name
)))
396 uint64_t addr
= Section
.getAddress();
397 max_name_len
= std::max(max_name_len
, name
.size());
398 max_size_len
= std::max(max_size_len
, getNumLengthAsString(size
));
399 max_addr_len
= std::max(max_addr_len
, getNumLengthAsString(addr
));
402 // Add extra padding.
407 // Setup header format.
408 fmt
<< "%-" << max_name_len
<< "s "
409 << "%" << max_size_len
<< "s "
410 << "%" << max_addr_len
<< "s\n";
413 outs() << format(fmt
.str().c_str(), static_cast<const char *>("section"),
414 static_cast<const char *>("size"),
415 static_cast<const char *>("addr"));
418 // Setup per section format.
419 fmt
<< "%-" << max_name_len
<< "s "
420 << "%#" << max_size_len
<< radix_fmt
<< " "
421 << "%#" << max_addr_len
<< radix_fmt
<< "\n";
423 // Print each section.
424 for (const SectionRef
&Section
: Obj
->sections()) {
425 if (!considerForSize(Obj
, Section
))
428 if (error(Section
.getName(name
)))
430 uint64_t size
= Section
.getSize();
431 uint64_t addr
= Section
.getAddress();
432 std::string namestr
= name
;
434 outs() << format(fmt
.str().c_str(), namestr
.c_str(), size
, addr
);
438 uint64_t CommonSize
= getCommonSize(Obj
);
440 outs() << format(fmt
.str().c_str(), std::string("*COM*").c_str(),
441 CommonSize
, static_cast<uint64_t>(0));
446 fmt
<< "%-" << max_name_len
<< "s "
447 << "%#" << max_size_len
<< radix_fmt
<< "\n";
448 outs() << format(fmt
.str().c_str(), static_cast<const char *>("Total"),
451 // The Berkeley format does not display individual section sizes. It
452 // displays the cumulative size for each section type.
453 uint64_t total_text
= 0;
454 uint64_t total_data
= 0;
455 uint64_t total_bss
= 0;
457 // Make one pass over the section table to calculate sizes.
458 for (const SectionRef
&Section
: Obj
->sections()) {
459 uint64_t size
= Section
.getSize();
460 bool isText
= Section
.isText();
461 bool isData
= Section
.isData();
462 bool isBSS
= Section
.isBSS();
472 total_bss
+= getCommonSize(Obj
);
474 total
= total_text
+ total_data
+ total_bss
;
477 TotalObjectText
+= total_text
;
478 TotalObjectData
+= total_data
;
479 TotalObjectBss
+= total_bss
;
480 TotalObjectTotal
+= total
;
483 if (!BerkeleyHeaderPrinted
) {
484 outs() << " text data bss "
485 << (Radix
== octal
? "oct" : "dec") << " hex filename\n";
486 BerkeleyHeaderPrinted
= true;
490 fmt
<< "%#7" << radix_fmt
<< " "
491 << "%#7" << radix_fmt
<< " "
492 << "%#7" << radix_fmt
<< " ";
493 outs() << format(fmt
.str().c_str(), total_text
, total_data
, total_bss
);
495 fmt
<< "%7" << (Radix
== octal
? PRIo64
: PRIu64
) << " "
497 outs() << format(fmt
.str().c_str(), total
, total
);
501 /// Checks to see if the @p O ObjectFile is a Mach-O file and if it is and there
502 /// is a list of architecture flags specified then check to make sure this
503 /// Mach-O file is one of those architectures or all architectures was
504 /// specificed. If not then an error is generated and this routine returns
505 /// false. Else it returns true.
506 static bool checkMachOAndArchFlags(ObjectFile
*O
, StringRef Filename
) {
507 auto *MachO
= dyn_cast
<MachOObjectFile
>(O
);
509 if (!MachO
|| ArchAll
|| ArchFlags
.empty())
512 MachO::mach_header H
;
513 MachO::mach_header_64 H_64
;
515 if (MachO
->is64Bit()) {
516 H_64
= MachO
->MachOObjectFile::getHeader64();
517 T
= MachOObjectFile::getArchTriple(H_64
.cputype
, H_64
.cpusubtype
);
519 H
= MachO
->MachOObjectFile::getHeader();
520 T
= MachOObjectFile::getArchTriple(H
.cputype
, H
.cpusubtype
);
522 if (none_of(ArchFlags
, [&](const std::string
&Name
) {
523 return Name
== T
.getArchName();
525 error(Filename
+ ": No architecture specified");
531 /// Print the section sizes for @p file. If @p file is an archive, print the
532 /// section sizes for each archive member.
533 static void printFileSectionSizes(StringRef file
) {
535 // Attempt to open the binary.
536 Expected
<OwningBinary
<Binary
>> BinaryOrErr
= createBinary(file
);
538 error(BinaryOrErr
.takeError(), file
);
541 Binary
&Bin
= *BinaryOrErr
.get().getBinary();
543 if (Archive
*a
= dyn_cast
<Archive
>(&Bin
)) {
544 // This is an archive. Iterate over each member and display its sizes.
545 Error Err
= Error::success();
546 for (auto &C
: a
->children(Err
)) {
547 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
549 if (auto E
= isNotObjectErrorInvalidFileType(ChildOrErr
.takeError()))
550 error(std::move(E
), a
->getFileName(), C
);
553 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
554 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
555 if (!checkMachOAndArchFlags(o
, file
))
557 if (OutputFormat
== sysv
)
558 outs() << o
->getFileName() << " (ex " << a
->getFileName() << "):\n";
559 else if (MachO
&& OutputFormat
== darwin
)
560 outs() << a
->getFileName() << "(" << o
->getFileName() << "):\n";
561 printObjectSectionSizes(o
);
562 if (OutputFormat
== berkeley
) {
564 outs() << a
->getFileName() << "(" << o
->getFileName() << ")\n";
566 outs() << o
->getFileName() << " (ex " << a
->getFileName() << ")\n";
571 error(std::move(Err
), a
->getFileName());
572 } else if (MachOUniversalBinary
*UB
=
573 dyn_cast
<MachOUniversalBinary
>(&Bin
)) {
574 // If we have a list of architecture flags specified dump only those.
575 if (!ArchAll
&& ArchFlags
.size() != 0) {
576 // Look for a slice in the universal binary that matches each ArchFlag.
578 for (unsigned i
= 0; i
< ArchFlags
.size(); ++i
) {
580 for (MachOUniversalBinary::object_iterator I
= UB
->begin_objects(),
581 E
= UB
->end_objects();
583 if (ArchFlags
[i
] == I
->getArchFlagName()) {
585 Expected
<std::unique_ptr
<ObjectFile
>> UO
= I
->getAsObjectFile();
587 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*UO
.get())) {
588 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
589 if (OutputFormat
== sysv
)
590 outs() << o
->getFileName() << " :\n";
591 else if (MachO
&& OutputFormat
== darwin
) {
592 if (MoreThanOneFile
|| ArchFlags
.size() > 1)
593 outs() << o
->getFileName() << " (for architecture "
594 << I
->getArchFlagName() << "): \n";
596 printObjectSectionSizes(o
);
597 if (OutputFormat
== berkeley
) {
598 if (!MachO
|| MoreThanOneFile
|| ArchFlags
.size() > 1)
599 outs() << o
->getFileName() << " (for architecture "
600 << I
->getArchFlagName() << ")";
604 } else if (auto E
= isNotObjectErrorInvalidFileType(
606 error(std::move(E
), file
, ArchFlags
.size() > 1 ?
607 StringRef(I
->getArchFlagName()) : StringRef());
609 } else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
=
611 std::unique_ptr
<Archive
> &UA
= *AOrErr
;
612 // This is an archive. Iterate over each member and display its
614 Error Err
= Error::success();
615 for (auto &C
: UA
->children(Err
)) {
616 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
618 if (auto E
= isNotObjectErrorInvalidFileType(
619 ChildOrErr
.takeError()))
620 error(std::move(E
), UA
->getFileName(), C
,
621 ArchFlags
.size() > 1 ?
622 StringRef(I
->getArchFlagName()) : StringRef());
625 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
626 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
627 if (OutputFormat
== sysv
)
628 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
630 else if (MachO
&& OutputFormat
== darwin
)
631 outs() << UA
->getFileName() << "(" << o
->getFileName()
633 << " (for architecture " << I
->getArchFlagName()
635 printObjectSectionSizes(o
);
636 if (OutputFormat
== berkeley
) {
638 outs() << UA
->getFileName() << "(" << o
->getFileName()
640 if (ArchFlags
.size() > 1)
641 outs() << " (for architecture " << I
->getArchFlagName()
645 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
651 error(std::move(Err
), UA
->getFileName());
653 consumeError(AOrErr
.takeError());
654 error("Mach-O universal file: " + file
+ " for architecture " +
655 StringRef(I
->getArchFlagName()) +
656 " is not a Mach-O file or an archive file");
661 errs() << ToolName
<< ": file: " << file
662 << " does not contain architecture" << ArchFlags
[i
] << ".\n";
668 // No architecture flags were specified so if this contains a slice that
669 // matches the host architecture dump only that.
671 StringRef HostArchName
= MachOObjectFile::getHostArch().getArchName();
672 for (MachOUniversalBinary::object_iterator I
= UB
->begin_objects(),
673 E
= UB
->end_objects();
675 if (HostArchName
== I
->getArchFlagName()) {
676 Expected
<std::unique_ptr
<ObjectFile
>> UO
= I
->getAsObjectFile();
678 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*UO
.get())) {
679 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
680 if (OutputFormat
== sysv
)
681 outs() << o
->getFileName() << " :\n";
682 else if (MachO
&& OutputFormat
== darwin
) {
684 outs() << o
->getFileName() << " (for architecture "
685 << I
->getArchFlagName() << "):\n";
687 printObjectSectionSizes(o
);
688 if (OutputFormat
== berkeley
) {
689 if (!MachO
|| MoreThanOneFile
)
690 outs() << o
->getFileName() << " (for architecture "
691 << I
->getArchFlagName() << ")";
695 } else if (auto E
= isNotObjectErrorInvalidFileType(UO
.takeError())) {
696 error(std::move(E
), file
);
698 } else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
=
700 std::unique_ptr
<Archive
> &UA
= *AOrErr
;
701 // This is an archive. Iterate over each member and display its
703 Error Err
= Error::success();
704 for (auto &C
: UA
->children(Err
)) {
705 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
707 if (auto E
= isNotObjectErrorInvalidFileType(
708 ChildOrErr
.takeError()))
709 error(std::move(E
), UA
->getFileName(), C
);
712 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
713 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
714 if (OutputFormat
== sysv
)
715 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
717 else if (MachO
&& OutputFormat
== darwin
)
718 outs() << UA
->getFileName() << "(" << o
->getFileName() << ")"
719 << " (for architecture " << I
->getArchFlagName()
721 printObjectSectionSizes(o
);
722 if (OutputFormat
== berkeley
) {
724 outs() << UA
->getFileName() << "(" << o
->getFileName()
727 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
733 error(std::move(Err
), UA
->getFileName());
735 consumeError(AOrErr
.takeError());
736 error("Mach-O universal file: " + file
+ " for architecture " +
737 StringRef(I
->getArchFlagName()) +
738 " is not a Mach-O file or an archive file");
744 // Either all architectures have been specified or none have been specified
745 // and this does not contain the host architecture so dump all the slices.
746 bool MoreThanOneArch
= UB
->getNumberOfObjects() > 1;
747 for (MachOUniversalBinary::object_iterator I
= UB
->begin_objects(),
748 E
= UB
->end_objects();
750 Expected
<std::unique_ptr
<ObjectFile
>> UO
= I
->getAsObjectFile();
752 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*UO
.get())) {
753 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
754 if (OutputFormat
== sysv
)
755 outs() << o
->getFileName() << " :\n";
756 else if (MachO
&& OutputFormat
== darwin
) {
757 if (MoreThanOneFile
|| MoreThanOneArch
)
758 outs() << o
->getFileName() << " (for architecture "
759 << I
->getArchFlagName() << "):";
762 printObjectSectionSizes(o
);
763 if (OutputFormat
== berkeley
) {
764 if (!MachO
|| MoreThanOneFile
|| MoreThanOneArch
)
765 outs() << o
->getFileName() << " (for architecture "
766 << I
->getArchFlagName() << ")";
770 } else if (auto E
= isNotObjectErrorInvalidFileType(UO
.takeError())) {
771 error(std::move(E
), file
, MoreThanOneArch
?
772 StringRef(I
->getArchFlagName()) : StringRef());
774 } else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
=
776 std::unique_ptr
<Archive
> &UA
= *AOrErr
;
777 // This is an archive. Iterate over each member and display its sizes.
778 Error Err
= Error::success();
779 for (auto &C
: UA
->children(Err
)) {
780 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
782 if (auto E
= isNotObjectErrorInvalidFileType(
783 ChildOrErr
.takeError()))
784 error(std::move(E
), UA
->getFileName(), C
, MoreThanOneArch
?
785 StringRef(I
->getArchFlagName()) : StringRef());
788 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
789 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
790 if (OutputFormat
== sysv
)
791 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
793 else if (MachO
&& OutputFormat
== darwin
)
794 outs() << UA
->getFileName() << "(" << o
->getFileName() << ")"
795 << " (for architecture " << I
->getArchFlagName() << "):\n";
796 printObjectSectionSizes(o
);
797 if (OutputFormat
== berkeley
) {
799 outs() << UA
->getFileName() << "(" << o
->getFileName() << ")"
800 << " (for architecture " << I
->getArchFlagName()
803 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
809 error(std::move(Err
), UA
->getFileName());
811 consumeError(AOrErr
.takeError());
812 error("Mach-O universal file: " + file
+ " for architecture " +
813 StringRef(I
->getArchFlagName()) +
814 " is not a Mach-O file or an archive file");
817 } else if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&Bin
)) {
818 if (!checkMachOAndArchFlags(o
, file
))
820 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
821 if (OutputFormat
== sysv
)
822 outs() << o
->getFileName() << " :\n";
823 else if (MachO
&& OutputFormat
== darwin
&& MoreThanOneFile
)
824 outs() << o
->getFileName() << ":\n";
825 printObjectSectionSizes(o
);
826 if (OutputFormat
== berkeley
) {
827 if (!MachO
|| MoreThanOneFile
)
828 outs() << o
->getFileName();
832 errs() << ToolName
<< ": " << file
<< ": "
833 << "Unrecognized file type.\n";
835 // System V adds an extra newline at the end of each file.
836 if (OutputFormat
== sysv
)
840 static void printBerkelyTotals() {
842 raw_string_ostream
fmt(fmtbuf
);
843 const char *radix_fmt
= getRadixFmt();
844 fmt
<< "%#7" << radix_fmt
<< " "
845 << "%#7" << radix_fmt
<< " "
846 << "%#7" << radix_fmt
<< " ";
847 outs() << format(fmt
.str().c_str(), TotalObjectText
, TotalObjectData
,
850 fmt
<< "%7" << (Radix
== octal
? PRIo64
: PRIu64
) << " "
852 outs() << format(fmt
.str().c_str(), TotalObjectTotal
, TotalObjectTotal
)
856 int main(int argc
, char **argv
) {
857 // Print a stack trace if we signal out.
858 sys::PrintStackTraceOnErrorSignal(argv
[0]);
859 PrettyStackTraceProgram
X(argc
, argv
);
861 llvm_shutdown_obj Y
; // Call llvm_shutdown() on exit.
862 cl::ParseCommandLineOptions(argc
, argv
, "llvm object size dumper\n");
865 if (OutputFormatShort
.getNumOccurrences())
866 OutputFormat
= static_cast<OutputFormatTy
>(OutputFormatShort
);
867 if (RadixShort
.getNumOccurrences())
870 for (unsigned i
= 0; i
< ArchFlags
.size(); ++i
) {
871 if (ArchFlags
[i
] == "all") {
874 if (!MachOObjectFile::isValidArch(ArchFlags
[i
])) {
875 outs() << ToolName
<< ": for the -arch option: Unknown architecture "
876 << "named '" << ArchFlags
[i
] << "'";
882 if (InputFilenames
.size() == 0)
883 InputFilenames
.push_back("a.out");
885 MoreThanOneFile
= InputFilenames
.size() > 1;
886 std::for_each(InputFilenames
.begin(), InputFilenames
.end(),
887 printFileSectionSizes
);
888 if (OutputFormat
== berkeley
&& TotalSizes
)
889 printBerkelyTotals();