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