xref: /minix3/external/bsd/llvm/dist/llvm/tools/llvm-size/llvm-size.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===-- llvm-size.cpp - Print the size of each object section -------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This program is a utility that works like traditional Unix "size",
11f4a2713aSLionel Sambuc // that is, it prints out the size of each section, and the total size of all
12f4a2713aSLionel Sambuc // sections.
13f4a2713aSLionel Sambuc //
14f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
15f4a2713aSLionel Sambuc 
16f4a2713aSLionel Sambuc #include "llvm/ADT/APInt.h"
17f4a2713aSLionel Sambuc #include "llvm/Object/Archive.h"
18*0a6a1f1dSLionel Sambuc #include "llvm/Object/MachO.h"
19*0a6a1f1dSLionel Sambuc #include "llvm/Object/MachOUniversal.h"
20f4a2713aSLionel Sambuc #include "llvm/Object/ObjectFile.h"
21f4a2713aSLionel Sambuc #include "llvm/Support/Casting.h"
22f4a2713aSLionel Sambuc #include "llvm/Support/CommandLine.h"
23f4a2713aSLionel Sambuc #include "llvm/Support/FileSystem.h"
24f4a2713aSLionel Sambuc #include "llvm/Support/Format.h"
25f4a2713aSLionel Sambuc #include "llvm/Support/ManagedStatic.h"
26f4a2713aSLionel Sambuc #include "llvm/Support/MemoryBuffer.h"
27f4a2713aSLionel Sambuc #include "llvm/Support/PrettyStackTrace.h"
28f4a2713aSLionel Sambuc #include "llvm/Support/Signals.h"
29f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
30f4a2713aSLionel Sambuc #include <algorithm>
31f4a2713aSLionel Sambuc #include <string>
32*0a6a1f1dSLionel Sambuc #include <system_error>
33f4a2713aSLionel Sambuc using namespace llvm;
34f4a2713aSLionel Sambuc using namespace object;
35f4a2713aSLionel Sambuc 
36*0a6a1f1dSLionel Sambuc enum OutputFormatTy { berkeley, sysv, darwin };
37f4a2713aSLionel Sambuc static cl::opt<OutputFormatTy>
38*0a6a1f1dSLionel Sambuc OutputFormat("format", cl::desc("Specify output format"),
39f4a2713aSLionel Sambuc              cl::values(clEnumVal(sysv, "System V format"),
40f4a2713aSLionel Sambuc                         clEnumVal(berkeley, "Berkeley format"),
41*0a6a1f1dSLionel Sambuc                         clEnumVal(darwin, "Darwin -m format"), clEnumValEnd),
42f4a2713aSLionel Sambuc              cl::init(berkeley));
43f4a2713aSLionel Sambuc 
44*0a6a1f1dSLionel Sambuc static cl::opt<OutputFormatTy> OutputFormatShort(
45*0a6a1f1dSLionel Sambuc     cl::desc("Specify output format"),
46f4a2713aSLionel Sambuc     cl::values(clEnumValN(sysv, "A", "System V format"),
47f4a2713aSLionel Sambuc                clEnumValN(berkeley, "B", "Berkeley format"),
48*0a6a1f1dSLionel Sambuc                clEnumValN(darwin, "m", "Darwin -m format"), clEnumValEnd),
49f4a2713aSLionel Sambuc     cl::init(berkeley));
50f4a2713aSLionel Sambuc 
51*0a6a1f1dSLionel Sambuc static bool berkeleyHeaderPrinted = false;
52*0a6a1f1dSLionel Sambuc static bool moreThanOneFile = false;
53*0a6a1f1dSLionel Sambuc 
54*0a6a1f1dSLionel Sambuc cl::opt<bool>
55*0a6a1f1dSLionel Sambuc DarwinLongFormat("l", cl::desc("When format is darwin, use long format "
56*0a6a1f1dSLionel Sambuc                                "to include addresses and offsets."));
57*0a6a1f1dSLionel Sambuc 
58*0a6a1f1dSLionel Sambuc static cl::list<std::string>
59*0a6a1f1dSLionel Sambuc ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
60*0a6a1f1dSLionel Sambuc           cl::ZeroOrMore);
61*0a6a1f1dSLionel Sambuc bool ArchAll = false;
62*0a6a1f1dSLionel Sambuc 
63f4a2713aSLionel Sambuc enum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 };
64f4a2713aSLionel Sambuc static cl::opt<unsigned int>
65*0a6a1f1dSLionel Sambuc Radix("-radix", cl::desc("Print size in radix. Only 8, 10, and 16 are valid"),
66f4a2713aSLionel Sambuc       cl::init(decimal));
67f4a2713aSLionel Sambuc 
68f4a2713aSLionel Sambuc static cl::opt<RadixTy>
69f4a2713aSLionel Sambuc RadixShort(cl::desc("Print size in radix:"),
70f4a2713aSLionel Sambuc            cl::values(clEnumValN(octal, "o", "Print size in octal"),
71f4a2713aSLionel Sambuc                       clEnumValN(decimal, "d", "Print size in decimal"),
72f4a2713aSLionel Sambuc                       clEnumValN(hexadecimal, "x", "Print size in hexadecimal"),
73f4a2713aSLionel Sambuc                       clEnumValEnd),
74f4a2713aSLionel Sambuc            cl::init(decimal));
75f4a2713aSLionel Sambuc 
76f4a2713aSLionel Sambuc static cl::list<std::string>
77*0a6a1f1dSLionel Sambuc InputFilenames(cl::Positional, cl::desc("<input files>"), cl::ZeroOrMore);
78f4a2713aSLionel Sambuc 
79f4a2713aSLionel Sambuc static std::string ToolName;
80f4a2713aSLionel Sambuc 
81f4a2713aSLionel Sambuc ///  @brief If ec is not success, print the error and return true.
error(std::error_code ec)82*0a6a1f1dSLionel Sambuc static bool error(std::error_code ec) {
83*0a6a1f1dSLionel Sambuc   if (!ec)
84*0a6a1f1dSLionel Sambuc     return false;
85f4a2713aSLionel Sambuc 
86f4a2713aSLionel Sambuc   outs() << ToolName << ": error reading file: " << ec.message() << ".\n";
87f4a2713aSLionel Sambuc   outs().flush();
88f4a2713aSLionel Sambuc   return true;
89f4a2713aSLionel Sambuc }
90f4a2713aSLionel Sambuc 
91f4a2713aSLionel Sambuc /// @brief Get the length of the string that represents @p num in Radix
92f4a2713aSLionel Sambuc ///        including the leading 0x or 0 for hexadecimal and octal respectively.
getNumLengthAsString(uint64_t num)93f4a2713aSLionel Sambuc static size_t getNumLengthAsString(uint64_t num) {
94f4a2713aSLionel Sambuc   APInt conv(64, num);
95f4a2713aSLionel Sambuc   SmallString<32> result;
96f4a2713aSLionel Sambuc   conv.toString(result, Radix, false, true);
97f4a2713aSLionel Sambuc   return result.size();
98f4a2713aSLionel Sambuc }
99f4a2713aSLionel Sambuc 
100*0a6a1f1dSLionel Sambuc /// @brief Return the the printing format for the Radix.
getRadixFmt(void)101*0a6a1f1dSLionel Sambuc static const char *getRadixFmt(void) {
102*0a6a1f1dSLionel Sambuc   switch (Radix) {
103*0a6a1f1dSLionel Sambuc   case octal:
104*0a6a1f1dSLionel Sambuc     return PRIo64;
105*0a6a1f1dSLionel Sambuc   case decimal:
106*0a6a1f1dSLionel Sambuc     return PRIu64;
107*0a6a1f1dSLionel Sambuc   case hexadecimal:
108*0a6a1f1dSLionel Sambuc     return PRIx64;
109*0a6a1f1dSLionel Sambuc   }
110*0a6a1f1dSLionel Sambuc   return nullptr;
111*0a6a1f1dSLionel Sambuc }
112*0a6a1f1dSLionel Sambuc 
113*0a6a1f1dSLionel Sambuc /// @brief Print the size of each Mach-O segment and section in @p MachO.
114*0a6a1f1dSLionel Sambuc ///
115*0a6a1f1dSLionel Sambuc /// This is when used when @c OutputFormat is darwin and produces the same
116*0a6a1f1dSLionel Sambuc /// output as darwin's size(1) -m output.
PrintDarwinSectionSizes(MachOObjectFile * MachO)117*0a6a1f1dSLionel Sambuc static void PrintDarwinSectionSizes(MachOObjectFile *MachO) {
118*0a6a1f1dSLionel Sambuc   std::string fmtbuf;
119*0a6a1f1dSLionel Sambuc   raw_string_ostream fmt(fmtbuf);
120*0a6a1f1dSLionel Sambuc   const char *radix_fmt = getRadixFmt();
121*0a6a1f1dSLionel Sambuc   if (Radix == hexadecimal)
122*0a6a1f1dSLionel Sambuc     fmt << "0x";
123*0a6a1f1dSLionel Sambuc   fmt << "%" << radix_fmt;
124*0a6a1f1dSLionel Sambuc 
125*0a6a1f1dSLionel Sambuc   uint32_t LoadCommandCount = MachO->getHeader().ncmds;
126*0a6a1f1dSLionel Sambuc   uint32_t Filetype = MachO->getHeader().filetype;
127*0a6a1f1dSLionel Sambuc   MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
128*0a6a1f1dSLionel Sambuc 
129*0a6a1f1dSLionel Sambuc   uint64_t total = 0;
130*0a6a1f1dSLionel Sambuc   for (unsigned I = 0;; ++I) {
131*0a6a1f1dSLionel Sambuc     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
132*0a6a1f1dSLionel Sambuc       MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
133*0a6a1f1dSLionel Sambuc       outs() << "Segment " << Seg.segname << ": "
134*0a6a1f1dSLionel Sambuc              << format(fmt.str().c_str(), Seg.vmsize);
135*0a6a1f1dSLionel Sambuc       if (DarwinLongFormat)
136*0a6a1f1dSLionel Sambuc         outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr) << " fileoff "
137*0a6a1f1dSLionel Sambuc                << Seg.fileoff << ")";
138*0a6a1f1dSLionel Sambuc       outs() << "\n";
139*0a6a1f1dSLionel Sambuc       total += Seg.vmsize;
140*0a6a1f1dSLionel Sambuc       uint64_t sec_total = 0;
141*0a6a1f1dSLionel Sambuc       for (unsigned J = 0; J < Seg.nsects; ++J) {
142*0a6a1f1dSLionel Sambuc         MachO::section_64 Sec = MachO->getSection64(Load, J);
143*0a6a1f1dSLionel Sambuc         if (Filetype == MachO::MH_OBJECT)
144*0a6a1f1dSLionel Sambuc           outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
145*0a6a1f1dSLionel Sambuc                  << format("%.16s", &Sec.sectname) << "): ";
146*0a6a1f1dSLionel Sambuc         else
147*0a6a1f1dSLionel Sambuc           outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
148*0a6a1f1dSLionel Sambuc         outs() << format(fmt.str().c_str(), Sec.size);
149*0a6a1f1dSLionel Sambuc         if (DarwinLongFormat)
150*0a6a1f1dSLionel Sambuc           outs() << " (addr 0x" << format("%" PRIx64, Sec.addr) << " offset "
151*0a6a1f1dSLionel Sambuc                  << Sec.offset << ")";
152*0a6a1f1dSLionel Sambuc         outs() << "\n";
153*0a6a1f1dSLionel Sambuc         sec_total += Sec.size;
154*0a6a1f1dSLionel Sambuc       }
155*0a6a1f1dSLionel Sambuc       if (Seg.nsects != 0)
156*0a6a1f1dSLionel Sambuc         outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
157*0a6a1f1dSLionel Sambuc     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
158*0a6a1f1dSLionel Sambuc       MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
159*0a6a1f1dSLionel Sambuc       outs() << "Segment " << Seg.segname << ": "
160*0a6a1f1dSLionel Sambuc              << format(fmt.str().c_str(), Seg.vmsize);
161*0a6a1f1dSLionel Sambuc       if (DarwinLongFormat)
162*0a6a1f1dSLionel Sambuc         outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr) << " fileoff "
163*0a6a1f1dSLionel Sambuc                << Seg.fileoff << ")";
164*0a6a1f1dSLionel Sambuc       outs() << "\n";
165*0a6a1f1dSLionel Sambuc       total += Seg.vmsize;
166*0a6a1f1dSLionel Sambuc       uint64_t sec_total = 0;
167*0a6a1f1dSLionel Sambuc       for (unsigned J = 0; J < Seg.nsects; ++J) {
168*0a6a1f1dSLionel Sambuc         MachO::section Sec = MachO->getSection(Load, J);
169*0a6a1f1dSLionel Sambuc         if (Filetype == MachO::MH_OBJECT)
170*0a6a1f1dSLionel Sambuc           outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
171*0a6a1f1dSLionel Sambuc                  << format("%.16s", &Sec.sectname) << "): ";
172*0a6a1f1dSLionel Sambuc         else
173*0a6a1f1dSLionel Sambuc           outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
174*0a6a1f1dSLionel Sambuc         outs() << format(fmt.str().c_str(), Sec.size);
175*0a6a1f1dSLionel Sambuc         if (DarwinLongFormat)
176*0a6a1f1dSLionel Sambuc           outs() << " (addr 0x" << format("%" PRIx64, Sec.addr) << " offset "
177*0a6a1f1dSLionel Sambuc                  << Sec.offset << ")";
178*0a6a1f1dSLionel Sambuc         outs() << "\n";
179*0a6a1f1dSLionel Sambuc         sec_total += Sec.size;
180*0a6a1f1dSLionel Sambuc       }
181*0a6a1f1dSLionel Sambuc       if (Seg.nsects != 0)
182*0a6a1f1dSLionel Sambuc         outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
183*0a6a1f1dSLionel Sambuc     }
184*0a6a1f1dSLionel Sambuc     if (I == LoadCommandCount - 1)
185*0a6a1f1dSLionel Sambuc       break;
186*0a6a1f1dSLionel Sambuc     else
187*0a6a1f1dSLionel Sambuc       Load = MachO->getNextLoadCommandInfo(Load);
188*0a6a1f1dSLionel Sambuc   }
189*0a6a1f1dSLionel Sambuc   outs() << "total " << format(fmt.str().c_str(), total) << "\n";
190*0a6a1f1dSLionel Sambuc }
191*0a6a1f1dSLionel Sambuc 
192*0a6a1f1dSLionel Sambuc /// @brief Print the summary sizes of the standard Mach-O segments in @p MachO.
193*0a6a1f1dSLionel Sambuc ///
194*0a6a1f1dSLionel Sambuc /// This is when used when @c OutputFormat is berkeley with a Mach-O file and
195*0a6a1f1dSLionel Sambuc /// produces the same output as darwin's size(1) default output.
PrintDarwinSegmentSizes(MachOObjectFile * MachO)196*0a6a1f1dSLionel Sambuc static void PrintDarwinSegmentSizes(MachOObjectFile *MachO) {
197*0a6a1f1dSLionel Sambuc   uint32_t LoadCommandCount = MachO->getHeader().ncmds;
198*0a6a1f1dSLionel Sambuc   MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
199*0a6a1f1dSLionel Sambuc 
200*0a6a1f1dSLionel Sambuc   uint64_t total_text = 0;
201*0a6a1f1dSLionel Sambuc   uint64_t total_data = 0;
202*0a6a1f1dSLionel Sambuc   uint64_t total_objc = 0;
203*0a6a1f1dSLionel Sambuc   uint64_t total_others = 0;
204*0a6a1f1dSLionel Sambuc   for (unsigned I = 0;; ++I) {
205*0a6a1f1dSLionel Sambuc     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
206*0a6a1f1dSLionel Sambuc       MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
207*0a6a1f1dSLionel Sambuc       if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
208*0a6a1f1dSLionel Sambuc         for (unsigned J = 0; J < Seg.nsects; ++J) {
209*0a6a1f1dSLionel Sambuc           MachO::section_64 Sec = MachO->getSection64(Load, J);
210*0a6a1f1dSLionel Sambuc           StringRef SegmentName = StringRef(Sec.segname);
211*0a6a1f1dSLionel Sambuc           if (SegmentName == "__TEXT")
212*0a6a1f1dSLionel Sambuc             total_text += Sec.size;
213*0a6a1f1dSLionel Sambuc           else if (SegmentName == "__DATA")
214*0a6a1f1dSLionel Sambuc             total_data += Sec.size;
215*0a6a1f1dSLionel Sambuc           else if (SegmentName == "__OBJC")
216*0a6a1f1dSLionel Sambuc             total_objc += Sec.size;
217*0a6a1f1dSLionel Sambuc           else
218*0a6a1f1dSLionel Sambuc             total_others += Sec.size;
219*0a6a1f1dSLionel Sambuc         }
220*0a6a1f1dSLionel Sambuc       } else {
221*0a6a1f1dSLionel Sambuc         StringRef SegmentName = StringRef(Seg.segname);
222*0a6a1f1dSLionel Sambuc         if (SegmentName == "__TEXT")
223*0a6a1f1dSLionel Sambuc           total_text += Seg.vmsize;
224*0a6a1f1dSLionel Sambuc         else if (SegmentName == "__DATA")
225*0a6a1f1dSLionel Sambuc           total_data += Seg.vmsize;
226*0a6a1f1dSLionel Sambuc         else if (SegmentName == "__OBJC")
227*0a6a1f1dSLionel Sambuc           total_objc += Seg.vmsize;
228*0a6a1f1dSLionel Sambuc         else
229*0a6a1f1dSLionel Sambuc           total_others += Seg.vmsize;
230*0a6a1f1dSLionel Sambuc       }
231*0a6a1f1dSLionel Sambuc     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
232*0a6a1f1dSLionel Sambuc       MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
233*0a6a1f1dSLionel Sambuc       if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
234*0a6a1f1dSLionel Sambuc         for (unsigned J = 0; J < Seg.nsects; ++J) {
235*0a6a1f1dSLionel Sambuc           MachO::section Sec = MachO->getSection(Load, J);
236*0a6a1f1dSLionel Sambuc           StringRef SegmentName = StringRef(Sec.segname);
237*0a6a1f1dSLionel Sambuc           if (SegmentName == "__TEXT")
238*0a6a1f1dSLionel Sambuc             total_text += Sec.size;
239*0a6a1f1dSLionel Sambuc           else if (SegmentName == "__DATA")
240*0a6a1f1dSLionel Sambuc             total_data += Sec.size;
241*0a6a1f1dSLionel Sambuc           else if (SegmentName == "__OBJC")
242*0a6a1f1dSLionel Sambuc             total_objc += Sec.size;
243*0a6a1f1dSLionel Sambuc           else
244*0a6a1f1dSLionel Sambuc             total_others += Sec.size;
245*0a6a1f1dSLionel Sambuc         }
246*0a6a1f1dSLionel Sambuc       } else {
247*0a6a1f1dSLionel Sambuc         StringRef SegmentName = StringRef(Seg.segname);
248*0a6a1f1dSLionel Sambuc         if (SegmentName == "__TEXT")
249*0a6a1f1dSLionel Sambuc           total_text += Seg.vmsize;
250*0a6a1f1dSLionel Sambuc         else if (SegmentName == "__DATA")
251*0a6a1f1dSLionel Sambuc           total_data += Seg.vmsize;
252*0a6a1f1dSLionel Sambuc         else if (SegmentName == "__OBJC")
253*0a6a1f1dSLionel Sambuc           total_objc += Seg.vmsize;
254*0a6a1f1dSLionel Sambuc         else
255*0a6a1f1dSLionel Sambuc           total_others += Seg.vmsize;
256*0a6a1f1dSLionel Sambuc       }
257*0a6a1f1dSLionel Sambuc     }
258*0a6a1f1dSLionel Sambuc     if (I == LoadCommandCount - 1)
259*0a6a1f1dSLionel Sambuc       break;
260*0a6a1f1dSLionel Sambuc     else
261*0a6a1f1dSLionel Sambuc       Load = MachO->getNextLoadCommandInfo(Load);
262*0a6a1f1dSLionel Sambuc   }
263*0a6a1f1dSLionel Sambuc   uint64_t total = total_text + total_data + total_objc + total_others;
264*0a6a1f1dSLionel Sambuc 
265*0a6a1f1dSLionel Sambuc   if (!berkeleyHeaderPrinted) {
266*0a6a1f1dSLionel Sambuc     outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
267*0a6a1f1dSLionel Sambuc     berkeleyHeaderPrinted = true;
268*0a6a1f1dSLionel Sambuc   }
269*0a6a1f1dSLionel Sambuc   outs() << total_text << "\t" << total_data << "\t" << total_objc << "\t"
270*0a6a1f1dSLionel Sambuc          << total_others << "\t" << total << "\t" << format("%" PRIx64, total)
271*0a6a1f1dSLionel Sambuc          << "\t";
272*0a6a1f1dSLionel Sambuc }
273*0a6a1f1dSLionel Sambuc 
274*0a6a1f1dSLionel Sambuc /// @brief Print the size of each section in @p Obj.
275f4a2713aSLionel Sambuc ///
276f4a2713aSLionel Sambuc /// The format used is determined by @c OutputFormat and @c Radix.
PrintObjectSectionSizes(ObjectFile * Obj)277*0a6a1f1dSLionel Sambuc static void PrintObjectSectionSizes(ObjectFile *Obj) {
278f4a2713aSLionel Sambuc   uint64_t total = 0;
279f4a2713aSLionel Sambuc   std::string fmtbuf;
280f4a2713aSLionel Sambuc   raw_string_ostream fmt(fmtbuf);
281*0a6a1f1dSLionel Sambuc   const char *radix_fmt = getRadixFmt();
282f4a2713aSLionel Sambuc 
283*0a6a1f1dSLionel Sambuc   // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
284*0a6a1f1dSLionel Sambuc   // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
285*0a6a1f1dSLionel Sambuc   // let it fall through to OutputFormat berkeley.
286*0a6a1f1dSLionel Sambuc   MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
287*0a6a1f1dSLionel Sambuc   if (OutputFormat == darwin && MachO)
288*0a6a1f1dSLionel Sambuc     PrintDarwinSectionSizes(MachO);
289*0a6a1f1dSLionel Sambuc   // If we have a MachOObjectFile and the OutputFormat is berkeley print as
290*0a6a1f1dSLionel Sambuc   // darwin's default berkeley format for Mach-O files.
291*0a6a1f1dSLionel Sambuc   else if (MachO && OutputFormat == berkeley)
292*0a6a1f1dSLionel Sambuc     PrintDarwinSegmentSizes(MachO);
293*0a6a1f1dSLionel Sambuc   else if (OutputFormat == sysv) {
294f4a2713aSLionel Sambuc     // Run two passes over all sections. The first gets the lengths needed for
295f4a2713aSLionel Sambuc     // formatting the output. The second actually does the output.
296f4a2713aSLionel Sambuc     std::size_t max_name_len = strlen("section");
297f4a2713aSLionel Sambuc     std::size_t max_size_len = strlen("size");
298f4a2713aSLionel Sambuc     std::size_t max_addr_len = strlen("addr");
299*0a6a1f1dSLionel Sambuc     for (const SectionRef &Section : Obj->sections()) {
300*0a6a1f1dSLionel Sambuc       uint64_t size = Section.getSize();
301f4a2713aSLionel Sambuc       total += size;
302f4a2713aSLionel Sambuc 
303f4a2713aSLionel Sambuc       StringRef name;
304*0a6a1f1dSLionel Sambuc       if (error(Section.getName(name)))
305*0a6a1f1dSLionel Sambuc         return;
306*0a6a1f1dSLionel Sambuc       uint64_t addr = Section.getAddress();
307f4a2713aSLionel Sambuc       max_name_len = std::max(max_name_len, name.size());
308f4a2713aSLionel Sambuc       max_size_len = std::max(max_size_len, getNumLengthAsString(size));
309f4a2713aSLionel Sambuc       max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr));
310f4a2713aSLionel Sambuc     }
311f4a2713aSLionel Sambuc 
312f4a2713aSLionel Sambuc     // Add extra padding.
313f4a2713aSLionel Sambuc     max_name_len += 2;
314f4a2713aSLionel Sambuc     max_size_len += 2;
315f4a2713aSLionel Sambuc     max_addr_len += 2;
316f4a2713aSLionel Sambuc 
317f4a2713aSLionel Sambuc     // Setup header format.
318f4a2713aSLionel Sambuc     fmt << "%-" << max_name_len << "s "
319f4a2713aSLionel Sambuc         << "%" << max_size_len << "s "
320f4a2713aSLionel Sambuc         << "%" << max_addr_len << "s\n";
321f4a2713aSLionel Sambuc 
322f4a2713aSLionel Sambuc     // Print header
323*0a6a1f1dSLionel Sambuc     outs() << format(fmt.str().c_str(), static_cast<const char *>("section"),
324f4a2713aSLionel Sambuc                      static_cast<const char *>("size"),
325f4a2713aSLionel Sambuc                      static_cast<const char *>("addr"));
326f4a2713aSLionel Sambuc     fmtbuf.clear();
327f4a2713aSLionel Sambuc 
328f4a2713aSLionel Sambuc     // Setup per section format.
329f4a2713aSLionel Sambuc     fmt << "%-" << max_name_len << "s "
330f4a2713aSLionel Sambuc         << "%#" << max_size_len << radix_fmt << " "
331f4a2713aSLionel Sambuc         << "%#" << max_addr_len << radix_fmt << "\n";
332f4a2713aSLionel Sambuc 
333f4a2713aSLionel Sambuc     // Print each section.
334*0a6a1f1dSLionel Sambuc     for (const SectionRef &Section : Obj->sections()) {
335f4a2713aSLionel Sambuc       StringRef name;
336*0a6a1f1dSLionel Sambuc       if (error(Section.getName(name)))
337*0a6a1f1dSLionel Sambuc         return;
338*0a6a1f1dSLionel Sambuc       uint64_t size = Section.getSize();
339*0a6a1f1dSLionel Sambuc       uint64_t addr = Section.getAddress();
340f4a2713aSLionel Sambuc       std::string namestr = name;
341f4a2713aSLionel Sambuc 
342*0a6a1f1dSLionel Sambuc       outs() << format(fmt.str().c_str(), namestr.c_str(), size, addr);
343f4a2713aSLionel Sambuc     }
344f4a2713aSLionel Sambuc 
345f4a2713aSLionel Sambuc     // Print total.
346f4a2713aSLionel Sambuc     fmtbuf.clear();
347f4a2713aSLionel Sambuc     fmt << "%-" << max_name_len << "s "
348f4a2713aSLionel Sambuc         << "%#" << max_size_len << radix_fmt << "\n";
349*0a6a1f1dSLionel Sambuc     outs() << format(fmt.str().c_str(), static_cast<const char *>("Total"),
350f4a2713aSLionel Sambuc                      total);
351f4a2713aSLionel Sambuc   } else {
352f4a2713aSLionel Sambuc     // The Berkeley format does not display individual section sizes. It
353f4a2713aSLionel Sambuc     // displays the cumulative size for each section type.
354f4a2713aSLionel Sambuc     uint64_t total_text = 0;
355f4a2713aSLionel Sambuc     uint64_t total_data = 0;
356f4a2713aSLionel Sambuc     uint64_t total_bss = 0;
357f4a2713aSLionel Sambuc 
358f4a2713aSLionel Sambuc     // Make one pass over the section table to calculate sizes.
359*0a6a1f1dSLionel Sambuc     for (const SectionRef &Section : Obj->sections()) {
360*0a6a1f1dSLionel Sambuc       uint64_t size = Section.getSize();
361*0a6a1f1dSLionel Sambuc       bool isText = Section.isText();
362*0a6a1f1dSLionel Sambuc       bool isData = Section.isData();
363*0a6a1f1dSLionel Sambuc       bool isBSS = Section.isBSS();
364f4a2713aSLionel Sambuc       if (isText)
365f4a2713aSLionel Sambuc         total_text += size;
366f4a2713aSLionel Sambuc       else if (isData)
367f4a2713aSLionel Sambuc         total_data += size;
368f4a2713aSLionel Sambuc       else if (isBSS)
369f4a2713aSLionel Sambuc         total_bss += size;
370f4a2713aSLionel Sambuc     }
371f4a2713aSLionel Sambuc 
372f4a2713aSLionel Sambuc     total = total_text + total_data + total_bss;
373f4a2713aSLionel Sambuc 
374*0a6a1f1dSLionel Sambuc     if (!berkeleyHeaderPrinted) {
375*0a6a1f1dSLionel Sambuc       outs() << "   text    data     bss     "
376*0a6a1f1dSLionel Sambuc              << (Radix == octal ? "oct" : "dec") << "     hex filename\n";
377*0a6a1f1dSLionel Sambuc       berkeleyHeaderPrinted = true;
378*0a6a1f1dSLionel Sambuc     }
379*0a6a1f1dSLionel Sambuc 
380f4a2713aSLionel Sambuc     // Print result.
381f4a2713aSLionel Sambuc     fmt << "%#7" << radix_fmt << " "
382f4a2713aSLionel Sambuc         << "%#7" << radix_fmt << " "
383f4a2713aSLionel Sambuc         << "%#7" << radix_fmt << " ";
384*0a6a1f1dSLionel Sambuc     outs() << format(fmt.str().c_str(), total_text, total_data, total_bss);
385f4a2713aSLionel Sambuc     fmtbuf.clear();
386f4a2713aSLionel Sambuc     fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << " "
387f4a2713aSLionel Sambuc         << "%7" PRIx64 " ";
388*0a6a1f1dSLionel Sambuc     outs() << format(fmt.str().c_str(), total, total);
389f4a2713aSLionel Sambuc   }
390f4a2713aSLionel Sambuc }
391f4a2713aSLionel Sambuc 
392*0a6a1f1dSLionel Sambuc /// @brief Checks to see if the @p o ObjectFile is a Mach-O file and if it is
393*0a6a1f1dSLionel Sambuc ///        and there is a list of architecture flags specified then check to
394*0a6a1f1dSLionel Sambuc ///        make sure this Mach-O file is one of those architectures or all
395*0a6a1f1dSLionel Sambuc ///        architectures was specificed.  If not then an error is generated and
396*0a6a1f1dSLionel Sambuc ///        this routine returns false.  Else it returns true.
checkMachOAndArchFlags(ObjectFile * o,StringRef file)397*0a6a1f1dSLionel Sambuc static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) {
398*0a6a1f1dSLionel Sambuc   if (isa<MachOObjectFile>(o) && !ArchAll && ArchFlags.size() != 0) {
399*0a6a1f1dSLionel Sambuc     MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
400*0a6a1f1dSLionel Sambuc     bool ArchFound = false;
401*0a6a1f1dSLionel Sambuc     MachO::mach_header H;
402*0a6a1f1dSLionel Sambuc     MachO::mach_header_64 H_64;
403*0a6a1f1dSLionel Sambuc     Triple T;
404*0a6a1f1dSLionel Sambuc     if (MachO->is64Bit()) {
405*0a6a1f1dSLionel Sambuc       H_64 = MachO->MachOObjectFile::getHeader64();
406*0a6a1f1dSLionel Sambuc       T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype);
407*0a6a1f1dSLionel Sambuc     } else {
408*0a6a1f1dSLionel Sambuc       H = MachO->MachOObjectFile::getHeader();
409*0a6a1f1dSLionel Sambuc       T = MachOObjectFile::getArch(H.cputype, H.cpusubtype);
410*0a6a1f1dSLionel Sambuc     }
411*0a6a1f1dSLionel Sambuc     unsigned i;
412*0a6a1f1dSLionel Sambuc     for (i = 0; i < ArchFlags.size(); ++i) {
413*0a6a1f1dSLionel Sambuc       if (ArchFlags[i] == T.getArchName())
414*0a6a1f1dSLionel Sambuc         ArchFound = true;
415*0a6a1f1dSLionel Sambuc       break;
416*0a6a1f1dSLionel Sambuc     }
417*0a6a1f1dSLionel Sambuc     if (!ArchFound) {
418*0a6a1f1dSLionel Sambuc       errs() << ToolName << ": file: " << file
419*0a6a1f1dSLionel Sambuc              << " does not contain architecture: " << ArchFlags[i] << ".\n";
420*0a6a1f1dSLionel Sambuc       return false;
421*0a6a1f1dSLionel Sambuc     }
422*0a6a1f1dSLionel Sambuc   }
423*0a6a1f1dSLionel Sambuc   return true;
424*0a6a1f1dSLionel Sambuc }
425*0a6a1f1dSLionel Sambuc 
426f4a2713aSLionel Sambuc /// @brief Print the section sizes for @p file. If @p file is an archive, print
427f4a2713aSLionel Sambuc ///        the section sizes for each archive member.
PrintFileSectionSizes(StringRef file)428f4a2713aSLionel Sambuc static void PrintFileSectionSizes(StringRef file) {
429f4a2713aSLionel Sambuc   // If file is not stdin, check that it exists.
430f4a2713aSLionel Sambuc   if (file != "-") {
431*0a6a1f1dSLionel Sambuc     if (!sys::fs::exists(file)) {
432*0a6a1f1dSLionel Sambuc       errs() << ToolName << ": '" << file << "': "
433*0a6a1f1dSLionel Sambuc              << "No such file\n";
434f4a2713aSLionel Sambuc       return;
435f4a2713aSLionel Sambuc     }
436f4a2713aSLionel Sambuc   }
437f4a2713aSLionel Sambuc 
438f4a2713aSLionel Sambuc   // Attempt to open the binary.
439*0a6a1f1dSLionel Sambuc   ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
440*0a6a1f1dSLionel Sambuc   if (std::error_code EC = BinaryOrErr.getError()) {
441*0a6a1f1dSLionel Sambuc     errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
442f4a2713aSLionel Sambuc     return;
443f4a2713aSLionel Sambuc   }
444*0a6a1f1dSLionel Sambuc   Binary &Bin = *BinaryOrErr.get().getBinary();
445f4a2713aSLionel Sambuc 
446*0a6a1f1dSLionel Sambuc   if (Archive *a = dyn_cast<Archive>(&Bin)) {
447f4a2713aSLionel Sambuc     // This is an archive. Iterate over each member and display its sizes.
448*0a6a1f1dSLionel Sambuc     for (object::Archive::child_iterator i = a->child_begin(),
449*0a6a1f1dSLionel Sambuc                                          e = a->child_end();
450*0a6a1f1dSLionel Sambuc          i != e; ++i) {
451*0a6a1f1dSLionel Sambuc       ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
452*0a6a1f1dSLionel Sambuc       if (std::error_code EC = ChildOrErr.getError()) {
453*0a6a1f1dSLionel Sambuc         errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
454f4a2713aSLionel Sambuc         continue;
455f4a2713aSLionel Sambuc       }
456*0a6a1f1dSLionel Sambuc       if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
457*0a6a1f1dSLionel Sambuc         MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
458*0a6a1f1dSLionel Sambuc         if (!checkMachOAndArchFlags(o, file))
459*0a6a1f1dSLionel Sambuc           return;
460f4a2713aSLionel Sambuc         if (OutputFormat == sysv)
461*0a6a1f1dSLionel Sambuc           outs() << o->getFileName() << "   (ex " << a->getFileName() << "):\n";
462*0a6a1f1dSLionel Sambuc         else if (MachO && OutputFormat == darwin)
463*0a6a1f1dSLionel Sambuc           outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
464f4a2713aSLionel Sambuc         PrintObjectSectionSizes(o);
465*0a6a1f1dSLionel Sambuc         if (OutputFormat == berkeley) {
466*0a6a1f1dSLionel Sambuc           if (MachO)
467*0a6a1f1dSLionel Sambuc             outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
468*0a6a1f1dSLionel Sambuc           else
469f4a2713aSLionel Sambuc             outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
470f4a2713aSLionel Sambuc         }
471f4a2713aSLionel Sambuc       }
472*0a6a1f1dSLionel Sambuc     }
473*0a6a1f1dSLionel Sambuc   } else if (MachOUniversalBinary *UB =
474*0a6a1f1dSLionel Sambuc                  dyn_cast<MachOUniversalBinary>(&Bin)) {
475*0a6a1f1dSLionel Sambuc     // If we have a list of architecture flags specified dump only those.
476*0a6a1f1dSLionel Sambuc     if (!ArchAll && ArchFlags.size() != 0) {
477*0a6a1f1dSLionel Sambuc       // Look for a slice in the universal binary that matches each ArchFlag.
478*0a6a1f1dSLionel Sambuc       bool ArchFound;
479*0a6a1f1dSLionel Sambuc       for (unsigned i = 0; i < ArchFlags.size(); ++i) {
480*0a6a1f1dSLionel Sambuc         ArchFound = false;
481*0a6a1f1dSLionel Sambuc         for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
482*0a6a1f1dSLionel Sambuc                                                    E = UB->end_objects();
483*0a6a1f1dSLionel Sambuc              I != E; ++I) {
484*0a6a1f1dSLionel Sambuc           if (ArchFlags[i] == I->getArchTypeName()) {
485*0a6a1f1dSLionel Sambuc             ArchFound = true;
486*0a6a1f1dSLionel Sambuc             ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
487*0a6a1f1dSLionel Sambuc             if (UO) {
488*0a6a1f1dSLionel Sambuc               if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
489*0a6a1f1dSLionel Sambuc                 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
490*0a6a1f1dSLionel Sambuc                 if (OutputFormat == sysv)
491*0a6a1f1dSLionel Sambuc                   outs() << o->getFileName() << "  :\n";
492*0a6a1f1dSLionel Sambuc                 else if (MachO && OutputFormat == darwin) {
493*0a6a1f1dSLionel Sambuc                   if (moreThanOneFile || ArchFlags.size() > 1)
494*0a6a1f1dSLionel Sambuc                     outs() << o->getFileName() << " (for architecture "
495*0a6a1f1dSLionel Sambuc                            << I->getArchTypeName() << "): \n";
496*0a6a1f1dSLionel Sambuc                 }
497*0a6a1f1dSLionel Sambuc                 PrintObjectSectionSizes(o);
498*0a6a1f1dSLionel Sambuc                 if (OutputFormat == berkeley) {
499*0a6a1f1dSLionel Sambuc                   if (!MachO || moreThanOneFile || ArchFlags.size() > 1)
500*0a6a1f1dSLionel Sambuc                     outs() << o->getFileName() << " (for architecture "
501*0a6a1f1dSLionel Sambuc                            << I->getArchTypeName() << ")";
502*0a6a1f1dSLionel Sambuc                   outs() << "\n";
503*0a6a1f1dSLionel Sambuc                 }
504*0a6a1f1dSLionel Sambuc               }
505*0a6a1f1dSLionel Sambuc             } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
506*0a6a1f1dSLionel Sambuc                            I->getAsArchive()) {
507*0a6a1f1dSLionel Sambuc               std::unique_ptr<Archive> &UA = *AOrErr;
508*0a6a1f1dSLionel Sambuc               // This is an archive. Iterate over each member and display its
509*0a6a1f1dSLionel Sambuc               // sizes.
510*0a6a1f1dSLionel Sambuc               for (object::Archive::child_iterator i = UA->child_begin(),
511*0a6a1f1dSLionel Sambuc                                                    e = UA->child_end();
512*0a6a1f1dSLionel Sambuc                    i != e; ++i) {
513*0a6a1f1dSLionel Sambuc                 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
514*0a6a1f1dSLionel Sambuc                 if (std::error_code EC = ChildOrErr.getError()) {
515*0a6a1f1dSLionel Sambuc                   errs() << ToolName << ": " << file << ": " << EC.message()
516*0a6a1f1dSLionel Sambuc                          << ".\n";
517*0a6a1f1dSLionel Sambuc                   continue;
518*0a6a1f1dSLionel Sambuc                 }
519*0a6a1f1dSLionel Sambuc                 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
520*0a6a1f1dSLionel Sambuc                   MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
521*0a6a1f1dSLionel Sambuc                   if (OutputFormat == sysv)
522*0a6a1f1dSLionel Sambuc                     outs() << o->getFileName() << "   (ex " << UA->getFileName()
523*0a6a1f1dSLionel Sambuc                            << "):\n";
524*0a6a1f1dSLionel Sambuc                   else if (MachO && OutputFormat == darwin)
525*0a6a1f1dSLionel Sambuc                     outs() << UA->getFileName() << "(" << o->getFileName()
526*0a6a1f1dSLionel Sambuc                            << ")"
527*0a6a1f1dSLionel Sambuc                            << " (for architecture " << I->getArchTypeName()
528*0a6a1f1dSLionel Sambuc                            << "):\n";
529*0a6a1f1dSLionel Sambuc                   PrintObjectSectionSizes(o);
530*0a6a1f1dSLionel Sambuc                   if (OutputFormat == berkeley) {
531*0a6a1f1dSLionel Sambuc                     if (MachO) {
532*0a6a1f1dSLionel Sambuc                       outs() << UA->getFileName() << "(" << o->getFileName()
533*0a6a1f1dSLionel Sambuc                              << ")";
534*0a6a1f1dSLionel Sambuc                       if (ArchFlags.size() > 1)
535*0a6a1f1dSLionel Sambuc                         outs() << " (for architecture " << I->getArchTypeName()
536*0a6a1f1dSLionel Sambuc                                << ")";
537*0a6a1f1dSLionel Sambuc                       outs() << "\n";
538*0a6a1f1dSLionel Sambuc                     } else
539*0a6a1f1dSLionel Sambuc                       outs() << o->getFileName() << " (ex " << UA->getFileName()
540*0a6a1f1dSLionel Sambuc                              << ")\n";
541*0a6a1f1dSLionel Sambuc                   }
542*0a6a1f1dSLionel Sambuc                 }
543*0a6a1f1dSLionel Sambuc               }
544*0a6a1f1dSLionel Sambuc             }
545*0a6a1f1dSLionel Sambuc           }
546*0a6a1f1dSLionel Sambuc         }
547*0a6a1f1dSLionel Sambuc         if (!ArchFound) {
548*0a6a1f1dSLionel Sambuc           errs() << ToolName << ": file: " << file
549*0a6a1f1dSLionel Sambuc                  << " does not contain architecture" << ArchFlags[i] << ".\n";
550*0a6a1f1dSLionel Sambuc           return;
551*0a6a1f1dSLionel Sambuc         }
552*0a6a1f1dSLionel Sambuc       }
553*0a6a1f1dSLionel Sambuc       return;
554*0a6a1f1dSLionel Sambuc     }
555*0a6a1f1dSLionel Sambuc     // No architecture flags were specified so if this contains a slice that
556*0a6a1f1dSLionel Sambuc     // matches the host architecture dump only that.
557*0a6a1f1dSLionel Sambuc     if (!ArchAll) {
558*0a6a1f1dSLionel Sambuc       StringRef HostArchName = MachOObjectFile::getHostArch().getArchName();
559*0a6a1f1dSLionel Sambuc       for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
560*0a6a1f1dSLionel Sambuc                                                  E = UB->end_objects();
561*0a6a1f1dSLionel Sambuc            I != E; ++I) {
562*0a6a1f1dSLionel Sambuc         if (HostArchName == I->getArchTypeName()) {
563*0a6a1f1dSLionel Sambuc           ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
564*0a6a1f1dSLionel Sambuc           if (UO) {
565*0a6a1f1dSLionel Sambuc             if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
566*0a6a1f1dSLionel Sambuc               MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
567*0a6a1f1dSLionel Sambuc               if (OutputFormat == sysv)
568*0a6a1f1dSLionel Sambuc                 outs() << o->getFileName() << "  :\n";
569*0a6a1f1dSLionel Sambuc               else if (MachO && OutputFormat == darwin) {
570*0a6a1f1dSLionel Sambuc                 if (moreThanOneFile)
571*0a6a1f1dSLionel Sambuc                   outs() << o->getFileName() << " (for architecture "
572*0a6a1f1dSLionel Sambuc                          << I->getArchTypeName() << "):\n";
573*0a6a1f1dSLionel Sambuc               }
574*0a6a1f1dSLionel Sambuc               PrintObjectSectionSizes(o);
575*0a6a1f1dSLionel Sambuc               if (OutputFormat == berkeley) {
576*0a6a1f1dSLionel Sambuc                 if (!MachO || moreThanOneFile)
577*0a6a1f1dSLionel Sambuc                   outs() << o->getFileName() << " (for architecture "
578*0a6a1f1dSLionel Sambuc                          << I->getArchTypeName() << ")";
579*0a6a1f1dSLionel Sambuc                 outs() << "\n";
580*0a6a1f1dSLionel Sambuc               }
581*0a6a1f1dSLionel Sambuc             }
582*0a6a1f1dSLionel Sambuc           } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
583*0a6a1f1dSLionel Sambuc                          I->getAsArchive()) {
584*0a6a1f1dSLionel Sambuc             std::unique_ptr<Archive> &UA = *AOrErr;
585*0a6a1f1dSLionel Sambuc             // This is an archive. Iterate over each member and display its
586*0a6a1f1dSLionel Sambuc             // sizes.
587*0a6a1f1dSLionel Sambuc             for (object::Archive::child_iterator i = UA->child_begin(),
588*0a6a1f1dSLionel Sambuc                                                  e = UA->child_end();
589*0a6a1f1dSLionel Sambuc                  i != e; ++i) {
590*0a6a1f1dSLionel Sambuc               ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
591*0a6a1f1dSLionel Sambuc               if (std::error_code EC = ChildOrErr.getError()) {
592*0a6a1f1dSLionel Sambuc                 errs() << ToolName << ": " << file << ": " << EC.message()
593*0a6a1f1dSLionel Sambuc                        << ".\n";
594*0a6a1f1dSLionel Sambuc                 continue;
595*0a6a1f1dSLionel Sambuc               }
596*0a6a1f1dSLionel Sambuc               if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
597*0a6a1f1dSLionel Sambuc                 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
598*0a6a1f1dSLionel Sambuc                 if (OutputFormat == sysv)
599*0a6a1f1dSLionel Sambuc                   outs() << o->getFileName() << "   (ex " << UA->getFileName()
600*0a6a1f1dSLionel Sambuc                          << "):\n";
601*0a6a1f1dSLionel Sambuc                 else if (MachO && OutputFormat == darwin)
602*0a6a1f1dSLionel Sambuc                   outs() << UA->getFileName() << "(" << o->getFileName() << ")"
603*0a6a1f1dSLionel Sambuc                          << " (for architecture " << I->getArchTypeName()
604*0a6a1f1dSLionel Sambuc                          << "):\n";
605*0a6a1f1dSLionel Sambuc                 PrintObjectSectionSizes(o);
606*0a6a1f1dSLionel Sambuc                 if (OutputFormat == berkeley) {
607*0a6a1f1dSLionel Sambuc                   if (MachO)
608*0a6a1f1dSLionel Sambuc                     outs() << UA->getFileName() << "(" << o->getFileName()
609*0a6a1f1dSLionel Sambuc                            << ")\n";
610*0a6a1f1dSLionel Sambuc                   else
611*0a6a1f1dSLionel Sambuc                     outs() << o->getFileName() << " (ex " << UA->getFileName()
612*0a6a1f1dSLionel Sambuc                            << ")\n";
613*0a6a1f1dSLionel Sambuc                 }
614*0a6a1f1dSLionel Sambuc               }
615*0a6a1f1dSLionel Sambuc             }
616*0a6a1f1dSLionel Sambuc           }
617*0a6a1f1dSLionel Sambuc           return;
618*0a6a1f1dSLionel Sambuc         }
619*0a6a1f1dSLionel Sambuc       }
620*0a6a1f1dSLionel Sambuc     }
621*0a6a1f1dSLionel Sambuc     // Either all architectures have been specified or none have been specified
622*0a6a1f1dSLionel Sambuc     // and this does not contain the host architecture so dump all the slices.
623*0a6a1f1dSLionel Sambuc     bool moreThanOneArch = UB->getNumberOfObjects() > 1;
624*0a6a1f1dSLionel Sambuc     for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
625*0a6a1f1dSLionel Sambuc                                                E = UB->end_objects();
626*0a6a1f1dSLionel Sambuc          I != E; ++I) {
627*0a6a1f1dSLionel Sambuc       ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
628*0a6a1f1dSLionel Sambuc       if (UO) {
629*0a6a1f1dSLionel Sambuc         if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
630*0a6a1f1dSLionel Sambuc           MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
631*0a6a1f1dSLionel Sambuc           if (OutputFormat == sysv)
632*0a6a1f1dSLionel Sambuc             outs() << o->getFileName() << "  :\n";
633*0a6a1f1dSLionel Sambuc           else if (MachO && OutputFormat == darwin) {
634*0a6a1f1dSLionel Sambuc             if (moreThanOneFile || moreThanOneArch)
635*0a6a1f1dSLionel Sambuc               outs() << o->getFileName() << " (for architecture "
636*0a6a1f1dSLionel Sambuc                      << I->getArchTypeName() << "):";
637*0a6a1f1dSLionel Sambuc             outs() << "\n";
638*0a6a1f1dSLionel Sambuc           }
639*0a6a1f1dSLionel Sambuc           PrintObjectSectionSizes(o);
640*0a6a1f1dSLionel Sambuc           if (OutputFormat == berkeley) {
641*0a6a1f1dSLionel Sambuc             if (!MachO || moreThanOneFile || moreThanOneArch)
642*0a6a1f1dSLionel Sambuc               outs() << o->getFileName() << " (for architecture "
643*0a6a1f1dSLionel Sambuc                      << I->getArchTypeName() << ")";
644*0a6a1f1dSLionel Sambuc             outs() << "\n";
645*0a6a1f1dSLionel Sambuc           }
646*0a6a1f1dSLionel Sambuc         }
647*0a6a1f1dSLionel Sambuc       } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
648*0a6a1f1dSLionel Sambuc                          I->getAsArchive()) {
649*0a6a1f1dSLionel Sambuc         std::unique_ptr<Archive> &UA = *AOrErr;
650*0a6a1f1dSLionel Sambuc         // This is an archive. Iterate over each member and display its sizes.
651*0a6a1f1dSLionel Sambuc         for (object::Archive::child_iterator i = UA->child_begin(),
652*0a6a1f1dSLionel Sambuc                                              e = UA->child_end();
653*0a6a1f1dSLionel Sambuc              i != e; ++i) {
654*0a6a1f1dSLionel Sambuc           ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
655*0a6a1f1dSLionel Sambuc           if (std::error_code EC = ChildOrErr.getError()) {
656*0a6a1f1dSLionel Sambuc             errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
657*0a6a1f1dSLionel Sambuc             continue;
658*0a6a1f1dSLionel Sambuc           }
659*0a6a1f1dSLionel Sambuc           if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
660*0a6a1f1dSLionel Sambuc             MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
661*0a6a1f1dSLionel Sambuc             if (OutputFormat == sysv)
662*0a6a1f1dSLionel Sambuc               outs() << o->getFileName() << "   (ex " << UA->getFileName()
663*0a6a1f1dSLionel Sambuc                      << "):\n";
664*0a6a1f1dSLionel Sambuc             else if (MachO && OutputFormat == darwin)
665*0a6a1f1dSLionel Sambuc               outs() << UA->getFileName() << "(" << o->getFileName() << ")"
666*0a6a1f1dSLionel Sambuc                      << " (for architecture " << I->getArchTypeName() << "):\n";
667*0a6a1f1dSLionel Sambuc             PrintObjectSectionSizes(o);
668*0a6a1f1dSLionel Sambuc             if (OutputFormat == berkeley) {
669*0a6a1f1dSLionel Sambuc               if (MachO)
670*0a6a1f1dSLionel Sambuc                 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
671*0a6a1f1dSLionel Sambuc                        << " (for architecture " << I->getArchTypeName()
672*0a6a1f1dSLionel Sambuc                        << ")\n";
673*0a6a1f1dSLionel Sambuc               else
674*0a6a1f1dSLionel Sambuc                 outs() << o->getFileName() << " (ex " << UA->getFileName()
675*0a6a1f1dSLionel Sambuc                        << ")\n";
676*0a6a1f1dSLionel Sambuc             }
677*0a6a1f1dSLionel Sambuc           }
678*0a6a1f1dSLionel Sambuc         }
679*0a6a1f1dSLionel Sambuc       }
680*0a6a1f1dSLionel Sambuc     }
681*0a6a1f1dSLionel Sambuc   } else if (ObjectFile *o = dyn_cast<ObjectFile>(&Bin)) {
682*0a6a1f1dSLionel Sambuc     if (!checkMachOAndArchFlags(o, file))
683*0a6a1f1dSLionel Sambuc       return;
684f4a2713aSLionel Sambuc     if (OutputFormat == sysv)
685f4a2713aSLionel Sambuc       outs() << o->getFileName() << "  :\n";
686f4a2713aSLionel Sambuc     PrintObjectSectionSizes(o);
687*0a6a1f1dSLionel Sambuc     if (OutputFormat == berkeley) {
688*0a6a1f1dSLionel Sambuc       MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
689*0a6a1f1dSLionel Sambuc       if (!MachO || moreThanOneFile)
690*0a6a1f1dSLionel Sambuc         outs() << o->getFileName();
691*0a6a1f1dSLionel Sambuc       outs() << "\n";
692*0a6a1f1dSLionel Sambuc     }
693f4a2713aSLionel Sambuc   } else {
694*0a6a1f1dSLionel Sambuc     errs() << ToolName << ": " << file << ": "
695*0a6a1f1dSLionel Sambuc            << "Unrecognized file type.\n";
696f4a2713aSLionel Sambuc   }
697f4a2713aSLionel Sambuc   // System V adds an extra newline at the end of each file.
698f4a2713aSLionel Sambuc   if (OutputFormat == sysv)
699f4a2713aSLionel Sambuc     outs() << "\n";
700f4a2713aSLionel Sambuc }
701f4a2713aSLionel Sambuc 
main(int argc,char ** argv)702f4a2713aSLionel Sambuc int main(int argc, char **argv) {
703f4a2713aSLionel Sambuc   // Print a stack trace if we signal out.
704f4a2713aSLionel Sambuc   sys::PrintStackTraceOnErrorSignal();
705f4a2713aSLionel Sambuc   PrettyStackTraceProgram X(argc, argv);
706f4a2713aSLionel Sambuc 
707f4a2713aSLionel Sambuc   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
708f4a2713aSLionel Sambuc   cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n");
709f4a2713aSLionel Sambuc 
710f4a2713aSLionel Sambuc   ToolName = argv[0];
711f4a2713aSLionel Sambuc   if (OutputFormatShort.getNumOccurrences())
712f4a2713aSLionel Sambuc     OutputFormat = OutputFormatShort;
713f4a2713aSLionel Sambuc   if (RadixShort.getNumOccurrences())
714f4a2713aSLionel Sambuc     Radix = RadixShort;
715f4a2713aSLionel Sambuc 
716*0a6a1f1dSLionel Sambuc   for (unsigned i = 0; i < ArchFlags.size(); ++i) {
717*0a6a1f1dSLionel Sambuc     if (ArchFlags[i] == "all") {
718*0a6a1f1dSLionel Sambuc       ArchAll = true;
719*0a6a1f1dSLionel Sambuc     } else {
720*0a6a1f1dSLionel Sambuc       if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
721*0a6a1f1dSLionel Sambuc         outs() << ToolName << ": for the -arch option: Unknown architecture "
722*0a6a1f1dSLionel Sambuc                << "named '" << ArchFlags[i] << "'";
723*0a6a1f1dSLionel Sambuc         return 1;
724*0a6a1f1dSLionel Sambuc       }
725*0a6a1f1dSLionel Sambuc     }
726*0a6a1f1dSLionel Sambuc   }
727*0a6a1f1dSLionel Sambuc 
728f4a2713aSLionel Sambuc   if (InputFilenames.size() == 0)
729f4a2713aSLionel Sambuc     InputFilenames.push_back("a.out");
730f4a2713aSLionel Sambuc 
731*0a6a1f1dSLionel Sambuc   moreThanOneFile = InputFilenames.size() > 1;
732f4a2713aSLionel Sambuc   std::for_each(InputFilenames.begin(), InputFilenames.end(),
733f4a2713aSLionel Sambuc                 PrintFileSectionSizes);
734f4a2713aSLionel Sambuc 
735f4a2713aSLionel Sambuc   return 0;
736f4a2713aSLionel Sambuc }
737