1 //===-- llvm-size.cpp - Print the size of each object section ---*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This program is a utility that works like traditional Unix "size",
10 // that is, it prints out the size of each section, and the total size of all
13 //===----------------------------------------------------------------------===//
15 #include "llvm/ADT/APInt.h"
16 #include "llvm/Object/Archive.h"
17 #include "llvm/Object/ELFObjectFile.h"
18 #include "llvm/Object/MachO.h"
19 #include "llvm/Object/MachOUniversal.h"
20 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/Option/Arg.h"
22 #include "llvm/Option/ArgList.h"
23 #include "llvm/Option/Option.h"
24 #include "llvm/Support/Casting.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/FileSystem.h"
27 #include "llvm/Support/Format.h"
28 #include "llvm/Support/LLVMDriver.h"
29 #include "llvm/Support/MemoryBuffer.h"
30 #include "llvm/Support/WithColor.h"
31 #include "llvm/Support/raw_ostream.h"
34 #include <system_error>
37 using namespace object
;
40 using namespace llvm::opt
; // for HelpHidden in Opts.inc
42 OPT_INVALID
= 0, // This is not an option ID.
43 #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
48 #define OPTTABLE_STR_TABLE_CODE
50 #undef OPTTABLE_STR_TABLE_CODE
52 #define OPTTABLE_PREFIXES_TABLE_CODE
54 #undef OPTTABLE_PREFIXES_TABLE_CODE
56 static constexpr opt::OptTable::Info InfoTable
[] = {
57 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
62 class SizeOptTable
: public opt::GenericOptTable
{
65 : GenericOptTable(OptionStrTable
, OptionPrefixesTable
, InfoTable
) {
66 setGroupedShortOptions(true);
70 enum OutputFormatTy
{ berkeley
, sysv
, darwin
};
71 enum RadixTy
{ octal
= 8, decimal
= 10, hexadecimal
= 16 };
74 static bool ArchAll
= false;
75 static std::vector
<StringRef
> ArchFlags
;
76 static bool ELFCommons
;
77 static OutputFormatTy OutputFormat
;
78 static bool DarwinLongFormat
;
80 static bool TotalSizes
;
82 static std::vector
<std::string
> InputFilenames
;
84 static std::string ToolName
;
87 static bool HadError
= false;
88 static bool BerkeleyHeaderPrinted
= false;
89 static bool MoreThanOneFile
= false;
90 static uint64_t TotalObjectText
= 0;
91 static uint64_t TotalObjectData
= 0;
92 static uint64_t TotalObjectBss
= 0;
93 static uint64_t TotalObjectTotal
= 0;
95 static void error(const Twine
&Message
, StringRef File
= "") {
98 WithColor::error(errs(), ToolName
) << Message
<< '\n';
100 WithColor::error(errs(), ToolName
)
101 << "'" << File
<< "': " << Message
<< '\n';
104 // This version of error() prints the archive name and member name, for example:
105 // "libx.a(foo.o)" after the ToolName before the error message. It sets
106 // HadError but returns allowing the code to move on to other archive members.
107 static void error(llvm::Error E
, StringRef FileName
, const Archive::Child
&C
,
108 StringRef ArchitectureName
= StringRef()) {
110 WithColor::error(errs(), ToolName
) << "'" << FileName
<< "'";
112 Expected
<StringRef
> NameOrErr
= C
.getName();
113 // TODO: if we have a error getting the name then it would be nice to print
114 // the index of which archive member this is and or its offset in the
115 // archive instead of "???" as the name.
117 consumeError(NameOrErr
.takeError());
118 errs() << "(" << "???" << ")";
120 errs() << "(" << NameOrErr
.get() << ")";
122 if (!ArchitectureName
.empty())
123 errs() << " (for architecture " << ArchitectureName
<< ") ";
126 raw_string_ostream
OS(Buf
);
127 logAllUnhandledErrors(std::move(E
), OS
);
129 errs() << ": " << Buf
<< "\n";
132 // 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
133 // before the error message. It sets HadError but returns allowing the code to
134 // move on to other architecture slices.
135 static void error(llvm::Error E
, StringRef FileName
,
136 StringRef ArchitectureName
= StringRef()) {
138 WithColor::error(errs(), ToolName
) << "'" << FileName
<< "'";
140 if (!ArchitectureName
.empty())
141 errs() << " (for architecture " << ArchitectureName
<< ") ";
144 raw_string_ostream
OS(Buf
);
145 logAllUnhandledErrors(std::move(E
), OS
);
147 errs() << ": " << Buf
<< "\n";
150 /// Get the length of the string that represents @p num in Radix including the
151 /// leading 0x or 0 for hexadecimal and octal respectively.
152 static size_t getNumLengthAsString(uint64_t num
) {
154 SmallString
<32> result
;
155 conv
.toString(result
, Radix
, false, true);
156 return result
.size();
159 /// Return the printing format for the Radix.
160 static const char *getRadixFmt() {
172 /// Remove unneeded ELF sections from calculation
173 static bool considerForSize(ObjectFile
*Obj
, SectionRef Section
) {
176 switch (static_cast<ELFSectionRef
>(Section
).getType()) {
178 case ELF::SHT_SYMTAB
:
180 case ELF::SHT_STRTAB
:
183 return static_cast<ELFSectionRef
>(Section
).getFlags() & ELF::SHF_ALLOC
;
188 /// Total size of all ELF common symbols
189 static Expected
<uint64_t> getCommonSize(ObjectFile
*Obj
) {
190 uint64_t TotalCommons
= 0;
191 for (auto &Sym
: Obj
->symbols()) {
192 Expected
<uint32_t> SymFlagsOrErr
=
193 Obj
->getSymbolFlags(Sym
.getRawDataRefImpl());
195 return SymFlagsOrErr
.takeError();
196 if (*SymFlagsOrErr
& SymbolRef::SF_Common
)
197 TotalCommons
+= Obj
->getCommonSymbolSize(Sym
.getRawDataRefImpl());
202 /// Print the size of each Mach-O segment and section in @p MachO.
204 /// This is when used when @c OutputFormat is darwin and produces the same
205 /// output as darwin's size(1) -m output.
206 static void printDarwinSectionSizes(MachOObjectFile
*MachO
) {
208 raw_string_ostream
fmt(fmtbuf
);
209 const char *radix_fmt
= getRadixFmt();
210 if (Radix
== hexadecimal
)
212 fmt
<< "%" << radix_fmt
;
214 uint32_t Filetype
= MachO
->getHeader().filetype
;
217 for (const auto &Load
: MachO
->load_commands()) {
218 if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
219 MachO::segment_command_64 Seg
= MachO
->getSegment64LoadCommand(Load
);
220 outs() << "Segment " << Seg
.segname
<< ": "
221 << format(fmtbuf
.c_str(), Seg
.vmsize
);
222 if (DarwinLongFormat
)
223 outs() << " (vmaddr 0x" << format("%" PRIx64
, Seg
.vmaddr
) << " fileoff "
224 << Seg
.fileoff
<< ")";
227 uint64_t sec_total
= 0;
228 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
229 MachO::section_64 Sec
= MachO
->getSection64(Load
, J
);
230 if (Filetype
== MachO::MH_OBJECT
)
231 outs() << "\tSection (" << format("%.16s", &Sec
.segname
) << ", "
232 << format("%.16s", &Sec
.sectname
) << "): ";
234 outs() << "\tSection " << format("%.16s", &Sec
.sectname
) << ": ";
235 outs() << format(fmtbuf
.c_str(), Sec
.size
);
236 if (DarwinLongFormat
)
237 outs() << " (addr 0x" << format("%" PRIx64
, Sec
.addr
) << " offset "
238 << Sec
.offset
<< ")";
240 sec_total
+= Sec
.size
;
243 outs() << "\ttotal " << format(fmtbuf
.c_str(), sec_total
) << "\n";
244 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
245 MachO::segment_command Seg
= MachO
->getSegmentLoadCommand(Load
);
246 uint64_t Seg_vmsize
= Seg
.vmsize
;
247 outs() << "Segment " << Seg
.segname
<< ": "
248 << format(fmtbuf
.c_str(), Seg_vmsize
);
249 if (DarwinLongFormat
)
250 outs() << " (vmaddr 0x" << format("%" PRIx32
, Seg
.vmaddr
) << " fileoff "
251 << Seg
.fileoff
<< ")";
254 uint64_t sec_total
= 0;
255 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
256 MachO::section Sec
= MachO
->getSection(Load
, J
);
257 if (Filetype
== MachO::MH_OBJECT
)
258 outs() << "\tSection (" << format("%.16s", &Sec
.segname
) << ", "
259 << format("%.16s", &Sec
.sectname
) << "): ";
261 outs() << "\tSection " << format("%.16s", &Sec
.sectname
) << ": ";
262 uint64_t Sec_size
= Sec
.size
;
263 outs() << format(fmtbuf
.c_str(), Sec_size
);
264 if (DarwinLongFormat
)
265 outs() << " (addr 0x" << format("%" PRIx32
, Sec
.addr
) << " offset "
266 << Sec
.offset
<< ")";
268 sec_total
+= Sec
.size
;
271 outs() << "\ttotal " << format(fmtbuf
.c_str(), sec_total
) << "\n";
274 outs() << "total " << format(fmtbuf
.c_str(), total
) << "\n";
277 /// Print the summary sizes of the standard Mach-O segments in @p MachO.
279 /// This is when used when @c OutputFormat is berkeley with a Mach-O file and
280 /// produces the same output as darwin's size(1) default output.
281 static void printDarwinSegmentSizes(MachOObjectFile
*MachO
) {
282 uint64_t total_text
= 0;
283 uint64_t total_data
= 0;
284 uint64_t total_objc
= 0;
285 uint64_t total_others
= 0;
286 for (const auto &Load
: MachO
->load_commands()) {
287 if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
288 MachO::segment_command_64 Seg
= MachO
->getSegment64LoadCommand(Load
);
289 if (MachO
->getHeader().filetype
== MachO::MH_OBJECT
) {
290 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
291 MachO::section_64 Sec
= MachO
->getSection64(Load
, J
);
292 StringRef SegmentName
= StringRef(Sec
.segname
);
293 if (SegmentName
== "__TEXT")
294 total_text
+= Sec
.size
;
295 else if (SegmentName
== "__DATA")
296 total_data
+= Sec
.size
;
297 else if (SegmentName
== "__OBJC")
298 total_objc
+= Sec
.size
;
300 total_others
+= Sec
.size
;
303 StringRef SegmentName
= StringRef(Seg
.segname
);
304 if (SegmentName
== "__TEXT")
305 total_text
+= Seg
.vmsize
;
306 else if (SegmentName
== "__DATA")
307 total_data
+= Seg
.vmsize
;
308 else if (SegmentName
== "__OBJC")
309 total_objc
+= Seg
.vmsize
;
311 total_others
+= Seg
.vmsize
;
313 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
314 MachO::segment_command Seg
= MachO
->getSegmentLoadCommand(Load
);
315 if (MachO
->getHeader().filetype
== MachO::MH_OBJECT
) {
316 for (unsigned J
= 0; J
< Seg
.nsects
; ++J
) {
317 MachO::section Sec
= MachO
->getSection(Load
, J
);
318 StringRef SegmentName
= StringRef(Sec
.segname
);
319 if (SegmentName
== "__TEXT")
320 total_text
+= Sec
.size
;
321 else if (SegmentName
== "__DATA")
322 total_data
+= Sec
.size
;
323 else if (SegmentName
== "__OBJC")
324 total_objc
+= Sec
.size
;
326 total_others
+= Sec
.size
;
329 StringRef SegmentName
= StringRef(Seg
.segname
);
330 if (SegmentName
== "__TEXT")
331 total_text
+= Seg
.vmsize
;
332 else if (SegmentName
== "__DATA")
333 total_data
+= Seg
.vmsize
;
334 else if (SegmentName
== "__OBJC")
335 total_objc
+= Seg
.vmsize
;
337 total_others
+= Seg
.vmsize
;
341 uint64_t total
= total_text
+ total_data
+ total_objc
+ total_others
;
343 if (!BerkeleyHeaderPrinted
) {
344 outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
345 BerkeleyHeaderPrinted
= true;
347 outs() << total_text
<< "\t" << total_data
<< "\t" << total_objc
<< "\t"
348 << total_others
<< "\t" << total
<< "\t" << format("%" PRIx64
, total
)
352 /// Print the size of each section in @p Obj.
354 /// The format used is determined by @c OutputFormat and @c Radix.
355 static void printObjectSectionSizes(ObjectFile
*Obj
) {
358 raw_string_ostream
fmt(fmtbuf
);
359 const char *radix_fmt
= getRadixFmt();
361 // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
362 // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
363 // let it fall through to OutputFormat berkeley.
364 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(Obj
);
365 if (OutputFormat
== darwin
&& MachO
)
366 printDarwinSectionSizes(MachO
);
367 // If we have a MachOObjectFile and the OutputFormat is berkeley print as
368 // darwin's default berkeley format for Mach-O files.
369 else if (MachO
&& OutputFormat
== berkeley
)
370 printDarwinSegmentSizes(MachO
);
371 else if (OutputFormat
== sysv
) {
372 // Run two passes over all sections. The first gets the lengths needed for
373 // formatting the output. The second actually does the output.
374 std::size_t max_name_len
= strlen("section");
375 std::size_t max_size_len
= strlen("size");
376 std::size_t max_addr_len
= strlen("addr");
377 for (const SectionRef
&Section
: Obj
->sections()) {
378 if (!considerForSize(Obj
, Section
))
380 uint64_t size
= Section
.getSize();
383 Expected
<StringRef
> name_or_err
= Section
.getName();
385 error(name_or_err
.takeError(), Obj
->getFileName());
389 uint64_t addr
= Section
.getAddress();
390 max_name_len
= std::max(max_name_len
, name_or_err
->size());
391 max_size_len
= std::max(max_size_len
, getNumLengthAsString(size
));
392 max_addr_len
= std::max(max_addr_len
, getNumLengthAsString(addr
));
395 // Add extra padding.
400 // Setup header format.
401 fmt
<< "%-" << max_name_len
<< "s "
402 << "%" << max_size_len
<< "s "
403 << "%" << max_addr_len
<< "s\n";
406 outs() << format(fmtbuf
.c_str(), static_cast<const char *>("section"),
407 static_cast<const char *>("size"),
408 static_cast<const char *>("addr"));
411 // Setup per section format.
412 fmt
<< "%-" << max_name_len
<< "s "
413 << "%#" << max_size_len
<< radix_fmt
<< " "
414 << "%#" << max_addr_len
<< radix_fmt
<< "\n";
416 // Print each section.
417 for (const SectionRef
&Section
: Obj
->sections()) {
418 if (!considerForSize(Obj
, Section
))
421 Expected
<StringRef
> name_or_err
= Section
.getName();
423 error(name_or_err
.takeError(), Obj
->getFileName());
427 uint64_t size
= Section
.getSize();
428 uint64_t addr
= Section
.getAddress();
429 outs() << format(fmtbuf
.c_str(), name_or_err
->str().c_str(), size
, addr
);
433 if (Expected
<uint64_t> CommonSizeOrErr
= getCommonSize(Obj
)) {
434 total
+= *CommonSizeOrErr
;
435 outs() << format(fmtbuf
.c_str(), std::string("*COM*").c_str(),
436 *CommonSizeOrErr
, static_cast<uint64_t>(0));
438 error(CommonSizeOrErr
.takeError(), Obj
->getFileName());
445 fmt
<< "%-" << max_name_len
<< "s "
446 << "%#" << max_size_len
<< radix_fmt
<< "\n";
447 outs() << format(fmtbuf
.c_str(), static_cast<const char *>("Total"), total
)
450 // The Berkeley format does not display individual section sizes. It
451 // displays the cumulative size for each section type.
452 uint64_t total_text
= 0;
453 uint64_t total_data
= 0;
454 uint64_t total_bss
= 0;
456 // Make one pass over the section table to calculate sizes.
457 for (const SectionRef
&Section
: Obj
->sections()) {
458 uint64_t size
= Section
.getSize();
459 bool isText
= Section
.isBerkeleyText();
460 bool isData
= Section
.isBerkeleyData();
461 bool isBSS
= Section
.isBSS();
471 if (Expected
<uint64_t> CommonSizeOrErr
= getCommonSize(Obj
))
472 total_bss
+= *CommonSizeOrErr
;
474 error(CommonSizeOrErr
.takeError(), Obj
->getFileName());
479 total
= total_text
+ total_data
+ total_bss
;
482 TotalObjectText
+= total_text
;
483 TotalObjectData
+= total_data
;
484 TotalObjectBss
+= total_bss
;
485 TotalObjectTotal
+= total
;
488 if (!BerkeleyHeaderPrinted
) {
493 << (Radix
== octal
? "oct" : "dec")
497 BerkeleyHeaderPrinted
= true;
501 fmt
<< "%#7" << radix_fmt
<< "\t"
502 << "%#7" << radix_fmt
<< "\t"
503 << "%#7" << radix_fmt
<< "\t";
504 outs() << format(fmtbuf
.c_str(), total_text
, total_data
, total_bss
);
506 fmt
<< "%7" << (Radix
== octal
? PRIo64
: PRIu64
) << "\t"
508 outs() << format(fmtbuf
.c_str(), total
, total
);
512 /// Checks to see if the @p O ObjectFile is a Mach-O file and if it is and there
513 /// is a list of architecture flags specified then check to make sure this
514 /// Mach-O file is one of those architectures or all architectures was
515 /// specificed. If not then an error is generated and this routine returns
516 /// false. Else it returns true.
517 static bool checkMachOAndArchFlags(ObjectFile
*O
, StringRef Filename
) {
518 auto *MachO
= dyn_cast
<MachOObjectFile
>(O
);
520 if (!MachO
|| ArchAll
|| ArchFlags
.empty())
523 MachO::mach_header H
;
524 MachO::mach_header_64 H_64
;
526 if (MachO
->is64Bit()) {
527 H_64
= MachO
->MachOObjectFile::getHeader64();
528 T
= MachOObjectFile::getArchTriple(H_64
.cputype
, H_64
.cpusubtype
);
530 H
= MachO
->MachOObjectFile::getHeader();
531 T
= MachOObjectFile::getArchTriple(H
.cputype
, H
.cpusubtype
);
533 if (!is_contained(ArchFlags
, T
.getArchName())) {
534 error("no architecture specified", Filename
);
540 /// Print the section sizes for @p file. If @p file is an archive, print the
541 /// section sizes for each archive member.
542 static void printFileSectionSizes(StringRef file
) {
544 // Attempt to open the binary.
545 Expected
<OwningBinary
<Binary
>> BinaryOrErr
= createBinary(file
);
547 error(BinaryOrErr
.takeError(), file
);
550 Binary
&Bin
= *BinaryOrErr
.get().getBinary();
552 if (Archive
*a
= dyn_cast
<Archive
>(&Bin
)) {
553 // This is an archive. Iterate over each member and display its sizes.
554 Error Err
= Error::success();
555 for (auto &C
: a
->children(Err
)) {
556 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
558 if (auto E
= isNotObjectErrorInvalidFileType(ChildOrErr
.takeError()))
559 error(std::move(E
), a
->getFileName(), C
);
562 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
563 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
564 if (!checkMachOAndArchFlags(o
, file
))
566 if (OutputFormat
== sysv
)
567 outs() << o
->getFileName() << " (ex " << a
->getFileName() << "):\n";
568 else if (MachO
&& OutputFormat
== darwin
)
569 outs() << a
->getFileName() << "(" << o
->getFileName() << "):\n";
570 printObjectSectionSizes(o
);
571 if (!MachO
&& OutputFormat
== darwin
)
572 outs() << o
->getFileName() << " (ex " << a
->getFileName() << ")\n";
573 if (OutputFormat
== berkeley
) {
575 outs() << a
->getFileName() << "(" << o
->getFileName() << ")\n";
577 outs() << o
->getFileName() << " (ex " << a
->getFileName() << ")\n";
582 error(std::move(Err
), a
->getFileName());
583 } else if (MachOUniversalBinary
*UB
=
584 dyn_cast
<MachOUniversalBinary
>(&Bin
)) {
585 // If we have a list of architecture flags specified dump only those.
586 if (!ArchAll
&& !ArchFlags
.empty()) {
587 // Look for a slice in the universal binary that matches each ArchFlag.
589 for (unsigned i
= 0; i
< ArchFlags
.size(); ++i
) {
591 for (MachOUniversalBinary::object_iterator I
= UB
->begin_objects(),
592 E
= UB
->end_objects();
594 if (ArchFlags
[i
] == I
->getArchFlagName()) {
596 Expected
<std::unique_ptr
<ObjectFile
>> UO
= I
->getAsObjectFile();
598 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*UO
.get())) {
599 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
600 if (OutputFormat
== sysv
)
601 outs() << o
->getFileName() << " :\n";
602 else if (MachO
&& OutputFormat
== darwin
) {
603 if (MoreThanOneFile
|| ArchFlags
.size() > 1)
604 outs() << o
->getFileName() << " (for architecture "
605 << I
->getArchFlagName() << "): \n";
607 printObjectSectionSizes(o
);
608 if (OutputFormat
== berkeley
) {
609 if (!MachO
|| MoreThanOneFile
|| ArchFlags
.size() > 1)
610 outs() << o
->getFileName() << " (for architecture "
611 << I
->getArchFlagName() << ")";
615 } else if (auto E
= isNotObjectErrorInvalidFileType(
617 error(std::move(E
), file
, ArchFlags
.size() > 1 ?
618 StringRef(I
->getArchFlagName()) : StringRef());
620 } else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
=
622 std::unique_ptr
<Archive
> &UA
= *AOrErr
;
623 // This is an archive. Iterate over each member and display its
625 Error Err
= Error::success();
626 for (auto &C
: UA
->children(Err
)) {
627 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
629 if (auto E
= isNotObjectErrorInvalidFileType(
630 ChildOrErr
.takeError()))
631 error(std::move(E
), UA
->getFileName(), C
,
632 ArchFlags
.size() > 1 ?
633 StringRef(I
->getArchFlagName()) : StringRef());
636 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
637 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
638 if (OutputFormat
== sysv
)
639 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
641 else if (MachO
&& OutputFormat
== darwin
)
642 outs() << UA
->getFileName() << "(" << o
->getFileName()
644 << " (for architecture " << I
->getArchFlagName()
646 printObjectSectionSizes(o
);
647 if (OutputFormat
== berkeley
) {
649 outs() << UA
->getFileName() << "(" << o
->getFileName()
651 if (ArchFlags
.size() > 1)
652 outs() << " (for architecture " << I
->getArchFlagName()
656 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
662 error(std::move(Err
), UA
->getFileName());
664 consumeError(AOrErr
.takeError());
665 error("mach-o universal file for architecture " +
666 StringRef(I
->getArchFlagName()) +
667 " is not a mach-o file or an archive file",
673 error("file does not contain architecture " + ArchFlags
[i
], file
);
679 // No architecture flags were specified so if this contains a slice that
680 // matches the host architecture dump only that.
682 StringRef HostArchName
= MachOObjectFile::getHostArch().getArchName();
683 for (MachOUniversalBinary::object_iterator I
= UB
->begin_objects(),
684 E
= UB
->end_objects();
686 if (HostArchName
== I
->getArchFlagName()) {
687 Expected
<std::unique_ptr
<ObjectFile
>> UO
= I
->getAsObjectFile();
689 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*UO
.get())) {
690 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
691 if (OutputFormat
== sysv
)
692 outs() << o
->getFileName() << " :\n";
693 else if (MachO
&& OutputFormat
== darwin
) {
695 outs() << o
->getFileName() << " (for architecture "
696 << I
->getArchFlagName() << "):\n";
698 printObjectSectionSizes(o
);
699 if (OutputFormat
== berkeley
) {
700 if (!MachO
|| MoreThanOneFile
)
701 outs() << o
->getFileName() << " (for architecture "
702 << I
->getArchFlagName() << ")";
706 } else if (auto E
= isNotObjectErrorInvalidFileType(UO
.takeError())) {
707 error(std::move(E
), file
);
709 } else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
=
711 std::unique_ptr
<Archive
> &UA
= *AOrErr
;
712 // This is an archive. Iterate over each member and display its
714 Error Err
= Error::success();
715 for (auto &C
: UA
->children(Err
)) {
716 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
718 if (auto E
= isNotObjectErrorInvalidFileType(
719 ChildOrErr
.takeError()))
720 error(std::move(E
), UA
->getFileName(), C
);
723 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
724 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
725 if (OutputFormat
== sysv
)
726 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
728 else if (MachO
&& OutputFormat
== darwin
)
729 outs() << UA
->getFileName() << "(" << o
->getFileName() << ")"
730 << " (for architecture " << I
->getArchFlagName()
732 printObjectSectionSizes(o
);
733 if (OutputFormat
== berkeley
) {
735 outs() << UA
->getFileName() << "(" << o
->getFileName()
738 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
744 error(std::move(Err
), UA
->getFileName());
746 consumeError(AOrErr
.takeError());
747 error("mach-o universal file for architecture " +
748 StringRef(I
->getArchFlagName()) +
749 " is not a mach-o file or an archive file",
756 // Either all architectures have been specified or none have been specified
757 // and this does not contain the host architecture so dump all the slices.
758 bool MoreThanOneArch
= UB
->getNumberOfObjects() > 1;
759 for (MachOUniversalBinary::object_iterator I
= UB
->begin_objects(),
760 E
= UB
->end_objects();
762 Expected
<std::unique_ptr
<ObjectFile
>> UO
= I
->getAsObjectFile();
764 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*UO
.get())) {
765 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
766 if (OutputFormat
== sysv
)
767 outs() << o
->getFileName() << " :\n";
768 else if (MachO
&& OutputFormat
== darwin
) {
769 if (MoreThanOneFile
|| MoreThanOneArch
)
770 outs() << o
->getFileName() << " (for architecture "
771 << I
->getArchFlagName() << "):";
774 printObjectSectionSizes(o
);
775 if (OutputFormat
== berkeley
) {
776 if (!MachO
|| MoreThanOneFile
|| MoreThanOneArch
)
777 outs() << o
->getFileName() << " (for architecture "
778 << I
->getArchFlagName() << ")";
782 } else if (auto E
= isNotObjectErrorInvalidFileType(UO
.takeError())) {
783 error(std::move(E
), file
, MoreThanOneArch
?
784 StringRef(I
->getArchFlagName()) : StringRef());
786 } else if (Expected
<std::unique_ptr
<Archive
>> AOrErr
=
788 std::unique_ptr
<Archive
> &UA
= *AOrErr
;
789 // This is an archive. Iterate over each member and display its sizes.
790 Error Err
= Error::success();
791 for (auto &C
: UA
->children(Err
)) {
792 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= C
.getAsBinary();
794 if (auto E
= isNotObjectErrorInvalidFileType(
795 ChildOrErr
.takeError()))
796 error(std::move(E
), UA
->getFileName(), C
, MoreThanOneArch
?
797 StringRef(I
->getArchFlagName()) : StringRef());
800 if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&*ChildOrErr
.get())) {
801 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
802 if (OutputFormat
== sysv
)
803 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
805 else if (MachO
&& OutputFormat
== darwin
)
806 outs() << UA
->getFileName() << "(" << o
->getFileName() << ")"
807 << " (for architecture " << I
->getArchFlagName() << "):\n";
808 printObjectSectionSizes(o
);
809 if (OutputFormat
== berkeley
) {
811 outs() << UA
->getFileName() << "(" << o
->getFileName() << ")"
812 << " (for architecture " << I
->getArchFlagName()
815 outs() << o
->getFileName() << " (ex " << UA
->getFileName()
821 error(std::move(Err
), UA
->getFileName());
823 consumeError(AOrErr
.takeError());
824 error("mach-o universal file for architecture " +
825 StringRef(I
->getArchFlagName()) +
826 " is not a mach-o file or an archive file",
830 } else if (ObjectFile
*o
= dyn_cast
<ObjectFile
>(&Bin
)) {
831 if (!checkMachOAndArchFlags(o
, file
))
833 MachOObjectFile
*MachO
= dyn_cast
<MachOObjectFile
>(o
);
834 if (OutputFormat
== sysv
)
835 outs() << o
->getFileName() << " :\n";
836 else if (MachO
&& OutputFormat
== darwin
&& MoreThanOneFile
)
837 outs() << o
->getFileName() << ":\n";
838 printObjectSectionSizes(o
);
839 if (!MachO
&& OutputFormat
== darwin
)
840 outs() << o
->getFileName() << "\n";
841 if (OutputFormat
== berkeley
) {
842 if (!MachO
|| MoreThanOneFile
)
843 outs() << o
->getFileName();
847 error("unsupported file type", file
);
851 static void printBerkeleyTotals() {
853 raw_string_ostream
fmt(fmtbuf
);
854 const char *radix_fmt
= getRadixFmt();
855 fmt
<< "%#7" << radix_fmt
<< "\t"
856 << "%#7" << radix_fmt
<< "\t"
857 << "%#7" << radix_fmt
<< "\t";
858 outs() << format(fmtbuf
.c_str(), TotalObjectText
, TotalObjectData
,
861 fmt
<< "%7" << (Radix
== octal
? PRIo64
: PRIu64
) << "\t"
863 outs() << format(fmtbuf
.c_str(), TotalObjectTotal
, TotalObjectTotal
)
867 int llvm_size_main(int argc
, char **argv
, const llvm::ToolContext
&) {
869 StringSaver
Saver(A
);
872 opt::InputArgList Args
=
873 Tbl
.parseArgs(argc
, argv
, OPT_UNKNOWN
, Saver
, [&](StringRef Msg
) {
877 if (Args
.hasArg(OPT_help
)) {
880 (Twine(ToolName
) + " [options] <input object files>").str().c_str(),
881 "LLVM object size dumper");
882 // TODO Replace this with OptTable API once it adds extrahelp support.
883 outs() << "\nPass @FILE as argument to read options from FILE.\n";
886 if (Args
.hasArg(OPT_version
)) {
887 outs() << ToolName
<< '\n';
888 cl::PrintVersionMessage();
892 ELFCommons
= Args
.hasArg(OPT_common
);
893 DarwinLongFormat
= Args
.hasArg(OPT_l
);
894 TotalSizes
= Args
.hasArg(OPT_totals
);
895 StringRef V
= Args
.getLastArgValue(OPT_format_EQ
, "berkeley");
897 OutputFormat
= berkeley
;
898 else if (V
== "darwin")
899 OutputFormat
= darwin
;
900 else if (V
== "sysv")
903 error("--format value should be one of: 'berkeley', 'darwin', 'sysv'");
904 V
= Args
.getLastArgValue(OPT_radix_EQ
, "10");
906 Radix
= RadixTy::octal
;
908 Radix
= RadixTy::decimal
;
910 Radix
= RadixTy::hexadecimal
;
912 error("--radix value should be one of: 8, 10, 16 ");
914 for (const auto *A
: Args
.filtered(OPT_arch_EQ
)) {
915 SmallVector
<StringRef
, 2> Values
;
916 llvm::SplitString(A
->getValue(), Values
, ",");
917 for (StringRef V
: Values
) {
920 else if (MachOObjectFile::isValidArch(V
))
921 ArchFlags
.push_back(V
);
923 outs() << ToolName
<< ": for the -arch option: Unknown architecture "
924 << "named '" << V
<< "'";
930 InputFilenames
= Args
.getAllArgValues(OPT_INPUT
);
931 if (InputFilenames
.empty())
932 InputFilenames
.push_back("a.out");
934 MoreThanOneFile
= InputFilenames
.size() > 1;
935 llvm::for_each(InputFilenames
, printFileSectionSizes
);
936 if (OutputFormat
== berkeley
&& TotalSizes
)
937 printBerkeleyTotals();