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/InitLLVM.h"
27 #include "llvm/Support/MemoryBuffer.h"
28 #include "llvm/Support/raw_ostream.h"
31 #include <system_error>
34 using namespace object
;
36 enum OutputFormatTy
{ berkeley
, sysv
, darwin
};
37 static cl::opt
<OutputFormatTy
>
38 OutputFormat("format", cl::desc("Specify output format"),
39 cl::values(clEnumVal(sysv
, "System V format"),
40 clEnumVal(berkeley
, "Berkeley format"),
41 clEnumVal(darwin
, "Darwin -m format")),
44 static cl::opt
<OutputFormatTy
> OutputFormatShort(
45 cl::desc("Specify output format"),
46 cl::values(clEnumValN(sysv
, "A", "System V format"),
47 clEnumValN(berkeley
, "B", "Berkeley format"),
48 clEnumValN(darwin
, "m", "Darwin -m format")),
51 static bool BerkeleyHeaderPrinted
= false;
52 static bool MoreThanOneFile
= false;
53 static uint64_t TotalObjectText
= 0;
54 static uint64_t TotalObjectData
= 0;
55 static uint64_t TotalObjectBss
= 0;
56 static uint64_t TotalObjectTotal
= 0;
59 DarwinLongFormat("l", cl::desc("When format is darwin, use long format "
60 "to include addresses and offsets."));
64 cl::desc("Print common symbols in the ELF file. When using "
65 "Berkely format, this is added to bss."),
68 static cl::list
<std::string
>
69 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
71 static bool ArchAll
= false;
73 enum RadixTy
{ octal
= 8, decimal
= 10, hexadecimal
= 16 };
74 static cl::opt
<unsigned int>
75 Radix("radix", cl::desc("Print size in radix. Only 8, 10, and 16 are valid"),
78 static cl::opt
<RadixTy
>
79 RadixShort(cl::desc("Print size in radix:"),
80 cl::values(clEnumValN(octal
, "o", "Print size in octal"),
81 clEnumValN(decimal
, "d", "Print size in decimal"),
82 clEnumValN(hexadecimal
, "x", "Print size in hexadecimal")),
87 cl::desc("Print totals of all objects - Berkeley format only"),
90 static cl::alias
TotalSizesShort("t", cl::desc("Short for --totals"),
91 cl::aliasopt(TotalSizes
));
93 static cl::list
<std::string
>
94 InputFilenames(cl::Positional
, cl::desc("<input files>"), cl::ZeroOrMore
);
96 static bool HadError
= false;
98 static std::string ToolName
;
100 /// If ec is not success, print the error and return true.
101 static bool error(std::error_code ec
) {
106 errs() << ToolName
<< ": error reading file: " << ec
.message() << ".\n";
111 static bool error(Twine Message
) {
113 errs() << ToolName
<< ": " << Message
<< ".\n";
118 // This version of error() prints the archive name and member name, for example:
119 // "libx.a(foo.o)" after the ToolName before the error message. It sets
120 // HadError but returns allowing the code to move on to other archive members.
121 static void error(llvm::Error E
, StringRef FileName
, const Archive::Child
&C
,
122 StringRef ArchitectureName
= StringRef()) {
124 errs() << ToolName
<< ": " << FileName
;
126 Expected
<StringRef
> NameOrErr
= C
.getName();
127 // TODO: if we have a error getting the name then it would be nice to print
128 // the index of which archive member this is and or its offset in the
129 // archive instead of "???" as the name.
131 consumeError(NameOrErr
.takeError());
132 errs() << "(" << "???" << ")";
134 errs() << "(" << NameOrErr
.get() << ")";
136 if (!ArchitectureName
.empty())
137 errs() << " (for architecture " << ArchitectureName
<< ") ";
140 raw_string_ostream
OS(Buf
);
141 logAllUnhandledErrors(std::move(E
), OS
, "");
143 errs() << " " << Buf
<< "\n";
146 // 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
147 // before the error message. It sets HadError but returns allowing the code to
148 // move on to other architecture slices.
149 static void error(llvm::Error E
, StringRef FileName
,
150 StringRef ArchitectureName
= StringRef()) {
152 errs() << ToolName
<< ": " << FileName
;
154 if (!ArchitectureName
.empty())
155 errs() << " (for architecture " << ArchitectureName
<< ") ";
158 raw_string_ostream
OS(Buf
);
159 logAllUnhandledErrors(std::move(E
), OS
, "");
161 errs() << " " << Buf
<< "\n";
164 /// Get the length of the string that represents @p num in Radix including the
165 /// leading 0x or 0 for hexadecimal and octal respectively.
166 static size_t getNumLengthAsString(uint64_t num
) {
168 SmallString
<32> result
;
169 conv
.toString(result
, Radix
, false, true);
170 return result
.size();
173 /// Return the printing format for the Radix.
174 static const char *getRadixFmt() {
186 /// Remove unneeded ELF sections from calculation
187 static bool considerForSize(ObjectFile
*Obj
, SectionRef Section
) {
190 switch (static_cast<ELFSectionRef
>(Section
).getType()) {
192 case ELF::SHT_SYMTAB
:
193 case ELF::SHT_STRTAB
:
201 /// Total size of all ELF common symbols
202 static uint64_t getCommonSize(ObjectFile
*Obj
) {
203 uint64_t TotalCommons
= 0;
204 for (auto &Sym
: Obj
->symbols())
205 if (Obj
->getSymbolFlags(Sym
.getRawDataRefImpl()) & SymbolRef::SF_Common
)
206 TotalCommons
+= Obj
->getCommonSymbolSize(Sym
.getRawDataRefImpl());
210 /// Print the size of each Mach-O segment and section in @p MachO.
212 /// This is when used when @c OutputFormat is darwin and produces the same
213 /// output as darwin's size(1) -m output.
214 static void printDarwinSectionSizes(MachOObjectFile
*MachO
) {
216 raw_string_ostream
fmt(fmtbuf
);
217 const char *radix_fmt
= getRadixFmt();
218 if (Radix
== hexadecimal
)
220 fmt
<< "%" << radix_fmt
;
222 uint32_t Filetype
= MachO
->getHeader().filetype
;
225 for (const auto &Load
: MachO
->load_commands()) {
226 if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
227 MachO::segment_command_64 Seg
= MachO
->getSegment64LoadCommand(Load
);
228 outs() << "Segment " << Seg
.segname
<< ": "
229 << format(fmt
.str().c_str(), Seg
.vmsize
);
230 if (DarwinLongFormat
)
231 outs() << " (vmaddr 0x" << format("%" PRIx64
, Seg
.vmaddr
) << " fileoff "
232 << Seg
.fileoff
<< ")";
235 uint64_t sec_total
= 0;
236 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
237 MachO::section_64 Sec
= MachO
->getSection64(Load
, J
);
238 if (Filetype
== MachO::MH_OBJECT
)
239 outs() << "\tSection (" << format("%.16s", &Sec
.segname
) << ", "
240 << format("%.16s", &Sec
.sectname
) << "): ";
242 outs() << "\tSection " << format("%.16s", &Sec
.sectname
) << ": ";
243 outs() << format(fmt
.str().c_str(), Sec
.size
);
244 if (DarwinLongFormat
)
245 outs() << " (addr 0x" << format("%" PRIx64
, Sec
.addr
) << " offset "
246 << Sec
.offset
<< ")";
248 sec_total
+= Sec
.size
;
251 outs() << "\ttotal " << format(fmt
.str().c_str(), sec_total
) << "\n";
252 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
253 MachO::segment_command Seg
= MachO
->getSegmentLoadCommand(Load
);
254 uint64_t Seg_vmsize
= Seg
.vmsize
;
255 outs() << "Segment " << Seg
.segname
<< ": "
256 << format(fmt
.str().c_str(), Seg_vmsize
);
257 if (DarwinLongFormat
)
258 outs() << " (vmaddr 0x" << format("%" PRIx32
, Seg
.vmaddr
) << " fileoff "
259 << Seg
.fileoff
<< ")";
262 uint64_t sec_total
= 0;
263 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
264 MachO::section Sec
= MachO
->getSection(Load
, J
);
265 if (Filetype
== MachO::MH_OBJECT
)
266 outs() << "\tSection (" << format("%.16s", &Sec
.segname
) << ", "
267 << format("%.16s", &Sec
.sectname
) << "): ";
269 outs() << "\tSection " << format("%.16s", &Sec
.sectname
) << ": ";
270 uint64_t Sec_size
= Sec
.size
;
271 outs() << format(fmt
.str().c_str(), Sec_size
);
272 if (DarwinLongFormat
)
273 outs() << " (addr 0x" << format("%" PRIx32
, Sec
.addr
) << " offset "
274 << Sec
.offset
<< ")";
276 sec_total
+= Sec
.size
;
279 outs() << "\ttotal " << format(fmt
.str().c_str(), sec_total
) << "\n";
282 outs() << "total " << format(fmt
.str().c_str(), total
) << "\n";
285 /// Print the summary sizes of the standard Mach-O segments in @p MachO.
287 /// This is when used when @c OutputFormat is berkeley with a Mach-O file and
288 /// produces the same output as darwin's size(1) default output.
289 static void printDarwinSegmentSizes(MachOObjectFile
*MachO
) {
290 uint64_t total_text
= 0;
291 uint64_t total_data
= 0;
292 uint64_t total_objc
= 0;
293 uint64_t total_others
= 0;
294 for (const auto &Load
: MachO
->load_commands()) {
295 if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
296 MachO::segment_command_64 Seg
= MachO
->getSegment64LoadCommand(Load
);
297 if (MachO
->getHeader().filetype
== MachO::MH_OBJECT
) {
298 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
299 MachO::section_64 Sec
= MachO
->getSection64(Load
, J
);
300 StringRef SegmentName
= StringRef(Sec
.segname
);
301 if (SegmentName
== "__TEXT")
302 total_text
+= Sec
.size
;
303 else if (SegmentName
== "__DATA")
304 total_data
+= Sec
.size
;
305 else if (SegmentName
== "__OBJC")
306 total_objc
+= Sec
.size
;
308 total_others
+= Sec
.size
;
311 StringRef SegmentName
= StringRef(Seg
.segname
);
312 if (SegmentName
== "__TEXT")
313 total_text
+= Seg
.vmsize
;
314 else if (SegmentName
== "__DATA")
315 total_data
+= Seg
.vmsize
;
316 else if (SegmentName
== "__OBJC")
317 total_objc
+= Seg
.vmsize
;
319 total_others
+= Seg
.vmsize
;
321 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
322 MachO::segment_command Seg
= MachO
->getSegmentLoadCommand(Load
);
323 if (MachO
->getHeader().filetype
== MachO::MH_OBJECT
) {
324 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
325 MachO::section Sec
= MachO
->getSection(Load
, J
);
326 StringRef SegmentName
= StringRef(Sec
.segname
);
327 if (SegmentName
== "__TEXT")
328 total_text
+= Sec
.size
;
329 else if (SegmentName
== "__DATA")
330 total_data
+= Sec
.size
;
331 else if (SegmentName
== "__OBJC")
332 total_objc
+= Sec
.size
;
334 total_others
+= Sec
.size
;
337 StringRef SegmentName
= StringRef(Seg
.segname
);
338 if (SegmentName
== "__TEXT")
339 total_text
+= Seg
.vmsize
;
340 else if (SegmentName
== "__DATA")
341 total_data
+= Seg
.vmsize
;
342 else if (SegmentName
== "__OBJC")
343 total_objc
+= Seg
.vmsize
;
345 total_others
+= Seg
.vmsize
;
349 uint64_t total
= total_text
+ total_data
+ total_objc
+ total_others
;
351 if (!BerkeleyHeaderPrinted
) {
352 outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
353 BerkeleyHeaderPrinted
= true;
355 outs() << total_text
<< "\t" << total_data
<< "\t" << total_objc
<< "\t"
356 << total_others
<< "\t" << total
<< "\t" << format("%" PRIx64
, total
)
360 /// Print the size of each section in @p Obj.
362 /// The format used is determined by @c OutputFormat and @c Radix.
363 static void printObjectSectionSizes(ObjectFile
*Obj
) {
366 raw_string_ostream
fmt(fmtbuf
);
367 const char *radix_fmt
= getRadixFmt();
369 // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
370 // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
371 // let it fall through to OutputFormat berkeley.
372 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(Obj
);
373 if (OutputFormat
== darwin
&& MachO
)
374 printDarwinSectionSizes(MachO
);
375 // If we have a MachOObjectFile and the OutputFormat is berkeley print as
376 // darwin's default berkeley format for Mach-O files.
377 else if (MachO
&& OutputFormat
== berkeley
)
378 printDarwinSegmentSizes(MachO
);
379 else if (OutputFormat
== sysv
) {
380 // Run two passes over all sections. The first gets the lengths needed for
381 // formatting the output. The second actually does the output.
382 std::size_t max_name_len
= strlen("section");
383 std::size_t max_size_len
= strlen("size");
384 std::size_t max_addr_len
= strlen("addr");
385 for (const SectionRef
&Section
: Obj
->sections()) {
386 if (!considerForSize(Obj
, Section
))
388 uint64_t size
= Section
.getSize();
392 if (error(Section
.getName(name
)))
394 uint64_t addr
= Section
.getAddress();
395 max_name_len
= std::max(max_name_len
, name
.size());
396 max_size_len
= std::max(max_size_len
, getNumLengthAsString(size
));
397 max_addr_len
= std::max(max_addr_len
, getNumLengthAsString(addr
));
400 // Add extra padding.
405 // Setup header format.
406 fmt
<< "%-" << max_name_len
<< "s "
407 << "%" << max_size_len
<< "s "
408 << "%" << max_addr_len
<< "s\n";
411 outs() << format(fmt
.str().c_str(), static_cast<const char *>("section"),
412 static_cast<const char *>("size"),
413 static_cast<const char *>("addr"));
416 // Setup per section format.
417 fmt
<< "%-" << max_name_len
<< "s "
418 << "%#" << max_size_len
<< radix_fmt
<< " "
419 << "%#" << max_addr_len
<< radix_fmt
<< "\n";
421 // Print each section.
422 for (const SectionRef
&Section
: Obj
->sections()) {
423 if (!considerForSize(Obj
, Section
))
426 if (error(Section
.getName(name
)))
428 uint64_t size
= Section
.getSize();
429 uint64_t addr
= Section
.getAddress();
430 std::string namestr
= name
;
432 outs() << format(fmt
.str().c_str(), namestr
.c_str(), size
, addr
);
436 uint64_t CommonSize
= getCommonSize(Obj
);
438 outs() << format(fmt
.str().c_str(), std::string("*COM*").c_str(),
439 CommonSize
, static_cast<uint64_t>(0));
444 fmt
<< "%-" << max_name_len
<< "s "
445 << "%#" << max_size_len
<< radix_fmt
<< "\n";
446 outs() << format(fmt
.str().c_str(), static_cast<const char *>("Total"),
449 // The Berkeley format does not display individual section sizes. It
450 // displays the cumulative size for each section type.
451 uint64_t total_text
= 0;
452 uint64_t total_data
= 0;
453 uint64_t total_bss
= 0;
455 // Make one pass over the section table to calculate sizes.
456 for (const SectionRef
&Section
: Obj
->sections()) {
457 uint64_t size
= Section
.getSize();
458 bool isText
= Section
.isText();
459 bool isData
= Section
.isData();
460 bool isBSS
= Section
.isBSS();
470 total_bss
+= getCommonSize(Obj
);
472 total
= total_text
+ total_data
+ total_bss
;
475 TotalObjectText
+= total_text
;
476 TotalObjectData
+= total_data
;
477 TotalObjectBss
+= total_bss
;
478 TotalObjectTotal
+= total
;
481 if (!BerkeleyHeaderPrinted
) {
482 outs() << " text data bss "
483 << (Radix
== octal
? "oct" : "dec") << " hex filename\n";
484 BerkeleyHeaderPrinted
= true;
488 fmt
<< "%#7" << radix_fmt
<< " "
489 << "%#7" << radix_fmt
<< " "
490 << "%#7" << radix_fmt
<< " ";
491 outs() << format(fmt
.str().c_str(), total_text
, total_data
, total_bss
);
493 fmt
<< "%7" << (Radix
== octal
? PRIo64
: PRIu64
) << " "
495 outs() << format(fmt
.str().c_str(), total
, total
);
499 /// Checks to see if the @p O ObjectFile is a Mach-O file and if it is and there
500 /// is a list of architecture flags specified then check to make sure this
501 /// Mach-O file is one of those architectures or all architectures was
502 /// specificed. If not then an error is generated and this routine returns
503 /// false. Else it returns true.
504 static bool checkMachOAndArchFlags(ObjectFile
*O
, StringRef Filename
) {
505 auto *MachO
= dyn_cast
<MachOObjectFile
>(O
);
507 if (!MachO
|| ArchAll
|| ArchFlags
.empty())
510 MachO::mach_header H
;
511 MachO::mach_header_64 H_64
;
513 if (MachO
->is64Bit()) {
514 H_64
= MachO
->MachOObjectFile::getHeader64();
515 T
= MachOObjectFile::getArchTriple(H_64
.cputype
, H_64
.cpusubtype
);
517 H
= MachO
->MachOObjectFile::getHeader();
518 T
= MachOObjectFile::getArchTriple(H
.cputype
, H
.cpusubtype
);
520 if (none_of(ArchFlags
, [&](const std::string
&Name
) {
521 return Name
== T
.getArchName();
523 error(Filename
+ ": No architecture specified");
529 /// Print the section sizes for @p file. If @p file is an archive, print the
530 /// section sizes for each archive member.
531 static void printFileSectionSizes(StringRef file
) {
533 // Attempt to open the binary.
534 Expected
<OwningBinary
<Binary
>> BinaryOrErr
= createBinary(file
);
536 error(BinaryOrErr
.takeError(), file
);
539 Binary
&Bin
= *BinaryOrErr
.get().getBinary();
541 if (Archive
*a
= dyn_cast
<Archive
>(&Bin
)) {
542 // This is an archive. Iterate over each member and display its sizes.
543 Error Err
= Error::success();
544 for (auto &C
: a
->children(Err
)) {
545 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
547 if (auto E
= isNotObjectErrorInvalidFileType(ChildOrErr
.takeError()))
548 error(std::move(E
), a
->getFileName(), C
);
551 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
552 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
553 if (!checkMachOAndArchFlags(o
, file
))
555 if (OutputFormat
== sysv
)
556 outs() << o
->getFileName() << " (ex " << a
->getFileName() << "):\n";
557 else if (MachO
&& OutputFormat
== darwin
)
558 outs() << a
->getFileName() << "(" << o
->getFileName() << "):\n";
559 printObjectSectionSizes(o
);
560 if (OutputFormat
== berkeley
) {
562 outs() << a
->getFileName() << "(" << o
->getFileName() << ")\n";
564 outs() << o
->getFileName() << " (ex " << a
->getFileName() << ")\n";
569 error(std::move(Err
), a
->getFileName());
570 } else if (MachOUniversalBinary
*UB
=
571 dyn_cast
<MachOUniversalBinary
>(&Bin
)) {
572 // If we have a list of architecture flags specified dump only those.
573 if (!ArchAll
&& ArchFlags
.size() != 0) {
574 // Look for a slice in the universal binary that matches each ArchFlag.
576 for (unsigned i
= 0; i
< ArchFlags
.size(); ++i
) {
578 for (MachOUniversalBinary::object_iterator I
= UB
->begin_objects(),
579 E
= UB
->end_objects();
581 if (ArchFlags
[i
] == I
->getArchFlagName()) {
583 Expected
<std::unique_ptr
<ObjectFile
>> UO
= I
->getAsObjectFile();
585 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*UO
.get())) {
586 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
587 if (OutputFormat
== sysv
)
588 outs() << o
->getFileName() << " :\n";
589 else if (MachO
&& OutputFormat
== darwin
) {
590 if (MoreThanOneFile
|| ArchFlags
.size() > 1)
591 outs() << o
->getFileName() << " (for architecture "
592 << I
->getArchFlagName() << "): \n";
594 printObjectSectionSizes(o
);
595 if (OutputFormat
== berkeley
) {
596 if (!MachO
|| MoreThanOneFile
|| ArchFlags
.size() > 1)
597 outs() << o
->getFileName() << " (for architecture "
598 << I
->getArchFlagName() << ")";
602 } else if (auto E
= isNotObjectErrorInvalidFileType(
604 error(std::move(E
), file
, ArchFlags
.size() > 1 ?
605 StringRef(I
->getArchFlagName()) : StringRef());
607 } else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
=
609 std::unique_ptr
<Archive
> &UA
= *AOrErr
;
610 // This is an archive. Iterate over each member and display its
612 Error Err
= Error::success();
613 for (auto &C
: UA
->children(Err
)) {
614 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
616 if (auto E
= isNotObjectErrorInvalidFileType(
617 ChildOrErr
.takeError()))
618 error(std::move(E
), UA
->getFileName(), C
,
619 ArchFlags
.size() > 1 ?
620 StringRef(I
->getArchFlagName()) : StringRef());
623 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
624 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
625 if (OutputFormat
== sysv
)
626 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
628 else if (MachO
&& OutputFormat
== darwin
)
629 outs() << UA
->getFileName() << "(" << o
->getFileName()
631 << " (for architecture " << I
->getArchFlagName()
633 printObjectSectionSizes(o
);
634 if (OutputFormat
== berkeley
) {
636 outs() << UA
->getFileName() << "(" << o
->getFileName()
638 if (ArchFlags
.size() > 1)
639 outs() << " (for architecture " << I
->getArchFlagName()
643 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
649 error(std::move(Err
), UA
->getFileName());
651 consumeError(AOrErr
.takeError());
652 error("Mach-O universal file: " + file
+ " for architecture " +
653 StringRef(I
->getArchFlagName()) +
654 " is not a Mach-O file or an archive file");
659 errs() << ToolName
<< ": file: " << file
660 << " does not contain architecture" << ArchFlags
[i
] << ".\n";
666 // No architecture flags were specified so if this contains a slice that
667 // matches the host architecture dump only that.
669 StringRef HostArchName
= MachOObjectFile::getHostArch().getArchName();
670 for (MachOUniversalBinary::object_iterator I
= UB
->begin_objects(),
671 E
= UB
->end_objects();
673 if (HostArchName
== I
->getArchFlagName()) {
674 Expected
<std::unique_ptr
<ObjectFile
>> UO
= I
->getAsObjectFile();
676 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*UO
.get())) {
677 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
678 if (OutputFormat
== sysv
)
679 outs() << o
->getFileName() << " :\n";
680 else if (MachO
&& OutputFormat
== darwin
) {
682 outs() << o
->getFileName() << " (for architecture "
683 << I
->getArchFlagName() << "):\n";
685 printObjectSectionSizes(o
);
686 if (OutputFormat
== berkeley
) {
687 if (!MachO
|| MoreThanOneFile
)
688 outs() << o
->getFileName() << " (for architecture "
689 << I
->getArchFlagName() << ")";
693 } else if (auto E
= isNotObjectErrorInvalidFileType(UO
.takeError())) {
694 error(std::move(E
), file
);
696 } else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
=
698 std::unique_ptr
<Archive
> &UA
= *AOrErr
;
699 // This is an archive. Iterate over each member and display its
701 Error Err
= Error::success();
702 for (auto &C
: UA
->children(Err
)) {
703 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
705 if (auto E
= isNotObjectErrorInvalidFileType(
706 ChildOrErr
.takeError()))
707 error(std::move(E
), UA
->getFileName(), C
);
710 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
711 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
712 if (OutputFormat
== sysv
)
713 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
715 else if (MachO
&& OutputFormat
== darwin
)
716 outs() << UA
->getFileName() << "(" << o
->getFileName() << ")"
717 << " (for architecture " << I
->getArchFlagName()
719 printObjectSectionSizes(o
);
720 if (OutputFormat
== berkeley
) {
722 outs() << UA
->getFileName() << "(" << o
->getFileName()
725 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
731 error(std::move(Err
), UA
->getFileName());
733 consumeError(AOrErr
.takeError());
734 error("Mach-O universal file: " + file
+ " for architecture " +
735 StringRef(I
->getArchFlagName()) +
736 " is not a Mach-O file or an archive file");
742 // Either all architectures have been specified or none have been specified
743 // and this does not contain the host architecture so dump all the slices.
744 bool MoreThanOneArch
= UB
->getNumberOfObjects() > 1;
745 for (MachOUniversalBinary::object_iterator I
= UB
->begin_objects(),
746 E
= UB
->end_objects();
748 Expected
<std::unique_ptr
<ObjectFile
>> UO
= I
->getAsObjectFile();
750 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*UO
.get())) {
751 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
752 if (OutputFormat
== sysv
)
753 outs() << o
->getFileName() << " :\n";
754 else if (MachO
&& OutputFormat
== darwin
) {
755 if (MoreThanOneFile
|| MoreThanOneArch
)
756 outs() << o
->getFileName() << " (for architecture "
757 << I
->getArchFlagName() << "):";
760 printObjectSectionSizes(o
);
761 if (OutputFormat
== berkeley
) {
762 if (!MachO
|| MoreThanOneFile
|| MoreThanOneArch
)
763 outs() << o
->getFileName() << " (for architecture "
764 << I
->getArchFlagName() << ")";
768 } else if (auto E
= isNotObjectErrorInvalidFileType(UO
.takeError())) {
769 error(std::move(E
), file
, MoreThanOneArch
?
770 StringRef(I
->getArchFlagName()) : StringRef());
772 } else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
=
774 std::unique_ptr
<Archive
> &UA
= *AOrErr
;
775 // This is an archive. Iterate over each member and display its sizes.
776 Error Err
= Error::success();
777 for (auto &C
: UA
->children(Err
)) {
778 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
780 if (auto E
= isNotObjectErrorInvalidFileType(
781 ChildOrErr
.takeError()))
782 error(std::move(E
), UA
->getFileName(), C
, MoreThanOneArch
?
783 StringRef(I
->getArchFlagName()) : StringRef());
786 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
787 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
788 if (OutputFormat
== sysv
)
789 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
791 else if (MachO
&& OutputFormat
== darwin
)
792 outs() << UA
->getFileName() << "(" << o
->getFileName() << ")"
793 << " (for architecture " << I
->getArchFlagName() << "):\n";
794 printObjectSectionSizes(o
);
795 if (OutputFormat
== berkeley
) {
797 outs() << UA
->getFileName() << "(" << o
->getFileName() << ")"
798 << " (for architecture " << I
->getArchFlagName()
801 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
807 error(std::move(Err
), UA
->getFileName());
809 consumeError(AOrErr
.takeError());
810 error("Mach-O universal file: " + file
+ " for architecture " +
811 StringRef(I
->getArchFlagName()) +
812 " is not a Mach-O file or an archive file");
815 } else if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&Bin
)) {
816 if (!checkMachOAndArchFlags(o
, file
))
818 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
819 if (OutputFormat
== sysv
)
820 outs() << o
->getFileName() << " :\n";
821 else if (MachO
&& OutputFormat
== darwin
&& MoreThanOneFile
)
822 outs() << o
->getFileName() << ":\n";
823 printObjectSectionSizes(o
);
824 if (OutputFormat
== berkeley
) {
825 if (!MachO
|| MoreThanOneFile
)
826 outs() << o
->getFileName();
830 errs() << ToolName
<< ": " << file
<< ": "
831 << "Unrecognized file type.\n";
833 // System V adds an extra newline at the end of each file.
834 if (OutputFormat
== sysv
)
838 static void printBerkelyTotals() {
840 raw_string_ostream
fmt(fmtbuf
);
841 const char *radix_fmt
= getRadixFmt();
842 fmt
<< "%#7" << radix_fmt
<< " "
843 << "%#7" << radix_fmt
<< " "
844 << "%#7" << radix_fmt
<< " ";
845 outs() << format(fmt
.str().c_str(), TotalObjectText
, TotalObjectData
,
848 fmt
<< "%7" << (Radix
== octal
? PRIo64
: PRIu64
) << " "
850 outs() << format(fmt
.str().c_str(), TotalObjectTotal
, TotalObjectTotal
)
854 int main(int argc
, char **argv
) {
855 InitLLVM
X(argc
, argv
);
856 cl::ParseCommandLineOptions(argc
, argv
, "llvm object size dumper\n");
859 if (OutputFormatShort
.getNumOccurrences())
860 OutputFormat
= static_cast<OutputFormatTy
>(OutputFormatShort
);
861 if (RadixShort
.getNumOccurrences())
864 for (unsigned i
= 0; i
< ArchFlags
.size(); ++i
) {
865 if (ArchFlags
[i
] == "all") {
868 if (!MachOObjectFile::isValidArch(ArchFlags
[i
])) {
869 outs() << ToolName
<< ": for the -arch option: Unknown architecture "
870 << "named '" << ArchFlags
[i
] << "'";
876 if (InputFilenames
.size() == 0)
877 InputFilenames
.push_back("a.out");
879 MoreThanOneFile
= InputFilenames
.size() > 1;
880 llvm::for_each(InputFilenames
, printFileSectionSizes
);
881 if (OutputFormat
== berkeley
&& TotalSizes
)
882 printBerkelyTotals();