blob: 3cf76cd88643058baaf5d1e0fb0a42b12771b352 [file] [log] [blame]
Eugene Zelenkoffec81c2015-11-04 22:32:32 +00001//===-- llvm-size.cpp - Print the size of each object section ---*- C++ -*-===//
Michael J. Spencerc4ad4662011-09-28 20:57:46 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This program is a utility that works like traditional Unix "size",
11// that is, it prints out the size of each section, and the total size of all
12// sections.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/ADT/APInt.h"
17#include "llvm/Object/Archive.h"
Rafael Espindolaa0ff5562016-02-09 21:39:49 +000018#include "llvm/Object/ELFObjectFile.h"
Kevin Enderby246a4602014-06-17 17:54:13 +000019#include "llvm/Object/MachO.h"
Kevin Enderby4b8fc282014-06-18 22:04:40 +000020#include "llvm/Object/MachOUniversal.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000021#include "llvm/Object/ObjectFile.h"
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000022#include "llvm/Support/Casting.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/FileSystem.h"
25#include "llvm/Support/Format.h"
26#include "llvm/Support/ManagedStatic.h"
27#include "llvm/Support/MemoryBuffer.h"
28#include "llvm/Support/PrettyStackTrace.h"
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000029#include "llvm/Support/Signals.h"
Chandler Carruth4d88a1c2012-12-04 10:44:52 +000030#include "llvm/Support/raw_ostream.h"
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000031#include <algorithm>
32#include <string>
Rafael Espindolaa6e9c3e2014-06-12 17:38:55 +000033#include <system_error>
Eugene Zelenkoffec81c2015-11-04 22:32:32 +000034
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000035using namespace llvm;
36using namespace object;
37
Kevin Enderby10769742014-07-01 22:26:31 +000038enum OutputFormatTy { berkeley, sysv, darwin };
Michael J. Spencercc5f8d42011-09-29 00:59:18 +000039static cl::opt<OutputFormatTy>
Kevin Enderby10769742014-07-01 22:26:31 +000040OutputFormat("format", cl::desc("Specify output format"),
41 cl::values(clEnumVal(sysv, "System V format"),
42 clEnumVal(berkeley, "Berkeley format"),
43 clEnumVal(darwin, "Darwin -m format"), clEnumValEnd),
44 cl::init(berkeley));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000045
Kevin Enderby10769742014-07-01 22:26:31 +000046static cl::opt<OutputFormatTy> OutputFormatShort(
47 cl::desc("Specify output format"),
48 cl::values(clEnumValN(sysv, "A", "System V format"),
49 clEnumValN(berkeley, "B", "Berkeley format"),
50 clEnumValN(darwin, "m", "Darwin -m format"), clEnumValEnd),
51 cl::init(berkeley));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000052
Rafael Espindola1dc30a42016-02-09 21:35:14 +000053static bool BerkeleyHeaderPrinted = false;
54static bool MoreThanOneFile = false;
Hemant Kulkarni5f4ca2f2016-09-12 17:08:28 +000055static uint64_t TotalObjectText = 0;
56static uint64_t TotalObjectData = 0;
57static uint64_t TotalObjectBss = 0;
58static uint64_t TotalObjectTotal = 0;
Kevin Enderby246a4602014-06-17 17:54:13 +000059
Kevin Enderby10769742014-07-01 22:26:31 +000060cl::opt<bool>
61DarwinLongFormat("l", cl::desc("When format is darwin, use long format "
62 "to include addresses and offsets."));
Kevin Enderby246a4602014-06-17 17:54:13 +000063
Hemant Kulkarni274457e2016-03-28 16:48:10 +000064cl::opt<bool>
65 ELFCommons("common",
66 cl::desc("Print common symbols in the ELF file. When using "
67 "Berkely format, this is added to bss."),
68 cl::init(false));
69
Kevin Enderbyafef4c92014-07-01 17:19:10 +000070static cl::list<std::string>
Kevin Enderby10769742014-07-01 22:26:31 +000071ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
72 cl::ZeroOrMore);
Kevin Enderbyafef4c92014-07-01 17:19:10 +000073bool ArchAll = false;
74
Kevin Enderby10769742014-07-01 22:26:31 +000075enum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 };
Michael J. Spencercc5f8d42011-09-29 00:59:18 +000076static cl::opt<unsigned int>
Kevin Enderby10769742014-07-01 22:26:31 +000077Radix("-radix", cl::desc("Print size in radix. Only 8, 10, and 16 are valid"),
78 cl::init(decimal));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000079
Michael J. Spencercc5f8d42011-09-29 00:59:18 +000080static cl::opt<RadixTy>
Kevin Enderby10769742014-07-01 22:26:31 +000081RadixShort(cl::desc("Print size in radix:"),
82 cl::values(clEnumValN(octal, "o", "Print size in octal"),
83 clEnumValN(decimal, "d", "Print size in decimal"),
84 clEnumValN(hexadecimal, "x", "Print size in hexadecimal"),
85 clEnumValEnd),
86 cl::init(decimal));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000087
Hemant Kulkarni5f4ca2f2016-09-12 17:08:28 +000088static cl::opt<bool>
89 TotalSizes("totals",
90 cl::desc("Print totals of all objects - Berkeley format only"),
91 cl::init(false));
92
93static cl::alias TotalSizesShort("t", cl::desc("Short for --totals"),
94 cl::aliasopt(TotalSizes));
95
Michael J. Spencercc5f8d42011-09-29 00:59:18 +000096static cl::list<std::string>
Kevin Enderby10769742014-07-01 22:26:31 +000097InputFilenames(cl::Positional, cl::desc("<input files>"), cl::ZeroOrMore);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000098
Kevin Enderby64f7a992016-05-02 21:41:03 +000099bool HadError = false;
100
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000101static std::string ToolName;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000102
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000103/// If ec is not success, print the error and return true.
Rafael Espindola4453e42942014-06-13 03:07:50 +0000104static bool error(std::error_code ec) {
Kevin Enderby10769742014-07-01 22:26:31 +0000105 if (!ec)
106 return false;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000107
Kevin Enderby64f7a992016-05-02 21:41:03 +0000108 HadError = true;
Davide Italiano911eb312016-01-25 01:24:15 +0000109 errs() << ToolName << ": error reading file: " << ec.message() << ".\n";
110 errs().flush();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000111 return true;
112}
113
Kevin Enderby42398052016-06-28 23:16:13 +0000114static bool error(Twine Message) {
115 HadError = true;
116 errs() << ToolName << ": " << Message << ".\n";
117 errs().flush();
118 return true;
119}
120
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000121// This version of error() prints the archive name and member name, for example:
122// "libx.a(foo.o)" after the ToolName before the error message. It sets
Hemant Kulkarni5f4ca2f2016-09-12 17:08:28 +0000123// HadError but returns allowing the code to move on to other archive members.
Kevin Enderby9acb1092016-05-31 20:35:34 +0000124static void error(llvm::Error E, StringRef FileName, const Archive::Child &C,
125 StringRef ArchitectureName = StringRef()) {
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000126 HadError = true;
127 errs() << ToolName << ": " << FileName;
128
Kevin Enderbyf4586032016-07-29 17:44:13 +0000129 Expected<StringRef> NameOrErr = C.getName();
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000130 // TODO: if we have a error getting the name then it would be nice to print
131 // the index of which archive member this is and or its offset in the
132 // archive instead of "???" as the name.
Kevin Enderbyf4586032016-07-29 17:44:13 +0000133 if (!NameOrErr) {
134 consumeError(NameOrErr.takeError());
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000135 errs() << "(" << "???" << ")";
Kevin Enderbyf4586032016-07-29 17:44:13 +0000136 } else
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000137 errs() << "(" << NameOrErr.get() << ")";
138
Kevin Enderby9acb1092016-05-31 20:35:34 +0000139 if (!ArchitectureName.empty())
140 errs() << " (for architecture " << ArchitectureName << ") ";
141
142 std::string Buf;
143 raw_string_ostream OS(Buf);
144 logAllUnhandledErrors(std::move(E), OS, "");
145 OS.flush();
146 errs() << " " << Buf << "\n";
147}
148
149// 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
150// before the error message. It sets HadError but returns allowing the code to
Hemant Kulkarni5f4ca2f2016-09-12 17:08:28 +0000151// move on to other architecture slices.
Kevin Enderby9acb1092016-05-31 20:35:34 +0000152static void error(llvm::Error E, StringRef FileName,
153 StringRef ArchitectureName = StringRef()) {
154 HadError = true;
155 errs() << ToolName << ": " << FileName;
156
157 if (!ArchitectureName.empty())
158 errs() << " (for architecture " << ArchitectureName << ") ";
159
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000160 std::string Buf;
161 raw_string_ostream OS(Buf);
162 logAllUnhandledErrors(std::move(E), OS, "");
163 OS.flush();
164 errs() << " " << Buf << "\n";
165}
166
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000167/// Get the length of the string that represents @p num in Radix including the
168/// leading 0x or 0 for hexadecimal and octal respectively.
Andrew Trick7dc278d2011-09-29 01:22:31 +0000169static size_t getNumLengthAsString(uint64_t num) {
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000170 APInt conv(64, num);
171 SmallString<32> result;
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000172 conv.toString(result, Radix, false, true);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000173 return result.size();
174}
175
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000176/// Return the printing format for the Radix.
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000177static const char *getRadixFmt() {
Kevin Enderby246a4602014-06-17 17:54:13 +0000178 switch (Radix) {
179 case octal:
180 return PRIo64;
181 case decimal:
182 return PRIu64;
183 case hexadecimal:
184 return PRIx64;
185 }
186 return nullptr;
187}
188
Rafael Espindolaa0ff5562016-02-09 21:39:49 +0000189/// Remove unneeded ELF sections from calculation
190static bool considerForSize(ObjectFile *Obj, SectionRef Section) {
191 if (!Obj->isELF())
192 return true;
193 switch (static_cast<ELFSectionRef>(Section).getType()) {
194 case ELF::SHT_NULL:
195 case ELF::SHT_SYMTAB:
196 case ELF::SHT_STRTAB:
197 case ELF::SHT_REL:
198 case ELF::SHT_RELA:
199 return false;
200 }
201 return true;
202}
203
Hemant Kulkarni274457e2016-03-28 16:48:10 +0000204/// Total size of all ELF common symbols
205static uint64_t getCommonSize(ObjectFile *Obj) {
206 uint64_t TotalCommons = 0;
207 for (auto &Sym : Obj->symbols())
208 if (Obj->getSymbolFlags(Sym.getRawDataRefImpl()) & SymbolRef::SF_Common)
209 TotalCommons += Obj->getCommonSymbolSize(Sym.getRawDataRefImpl());
210 return TotalCommons;
211}
212
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000213/// Print the size of each Mach-O segment and section in @p MachO.
Kevin Enderby246a4602014-06-17 17:54:13 +0000214///
215/// This is when used when @c OutputFormat is darwin and produces the same
216/// output as darwin's size(1) -m output.
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000217static void printDarwinSectionSizes(MachOObjectFile *MachO) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000218 std::string fmtbuf;
219 raw_string_ostream fmt(fmtbuf);
220 const char *radix_fmt = getRadixFmt();
221 if (Radix == hexadecimal)
222 fmt << "0x";
223 fmt << "%" << radix_fmt;
224
Kevin Enderby246a4602014-06-17 17:54:13 +0000225 uint32_t Filetype = MachO->getHeader().filetype;
Kevin Enderby246a4602014-06-17 17:54:13 +0000226
227 uint64_t total = 0;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000228 for (const auto &Load : MachO->load_commands()) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000229 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
230 MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
231 outs() << "Segment " << Seg.segname << ": "
232 << format(fmt.str().c_str(), Seg.vmsize);
233 if (DarwinLongFormat)
Kevin Enderby10769742014-07-01 22:26:31 +0000234 outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr) << " fileoff "
235 << Seg.fileoff << ")";
Kevin Enderby246a4602014-06-17 17:54:13 +0000236 outs() << "\n";
237 total += Seg.vmsize;
238 uint64_t sec_total = 0;
239 for (unsigned J = 0; J < Seg.nsects; ++J) {
240 MachO::section_64 Sec = MachO->getSection64(Load, J);
241 if (Filetype == MachO::MH_OBJECT)
242 outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
243 << format("%.16s", &Sec.sectname) << "): ";
244 else
245 outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
246 outs() << format(fmt.str().c_str(), Sec.size);
247 if (DarwinLongFormat)
Kevin Enderby10769742014-07-01 22:26:31 +0000248 outs() << " (addr 0x" << format("%" PRIx64, Sec.addr) << " offset "
249 << Sec.offset << ")";
Kevin Enderby246a4602014-06-17 17:54:13 +0000250 outs() << "\n";
251 sec_total += Sec.size;
252 }
253 if (Seg.nsects != 0)
254 outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000255 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000256 MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
Kevin Enderby2058e9d2016-02-09 18:33:15 +0000257 uint64_t Seg_vmsize = Seg.vmsize;
Kevin Enderby246a4602014-06-17 17:54:13 +0000258 outs() << "Segment " << Seg.segname << ": "
Kevin Enderby2058e9d2016-02-09 18:33:15 +0000259 << format(fmt.str().c_str(), Seg_vmsize);
Kevin Enderby246a4602014-06-17 17:54:13 +0000260 if (DarwinLongFormat)
Kevin Enderby2058e9d2016-02-09 18:33:15 +0000261 outs() << " (vmaddr 0x" << format("%" PRIx32, Seg.vmaddr) << " fileoff "
Kevin Enderby10769742014-07-01 22:26:31 +0000262 << Seg.fileoff << ")";
Kevin Enderby246a4602014-06-17 17:54:13 +0000263 outs() << "\n";
264 total += Seg.vmsize;
265 uint64_t sec_total = 0;
266 for (unsigned J = 0; J < Seg.nsects; ++J) {
267 MachO::section Sec = MachO->getSection(Load, J);
268 if (Filetype == MachO::MH_OBJECT)
269 outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
270 << format("%.16s", &Sec.sectname) << "): ";
271 else
272 outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
Kevin Enderby2058e9d2016-02-09 18:33:15 +0000273 uint64_t Sec_size = Sec.size;
274 outs() << format(fmt.str().c_str(), Sec_size);
Kevin Enderby246a4602014-06-17 17:54:13 +0000275 if (DarwinLongFormat)
Kevin Enderby2058e9d2016-02-09 18:33:15 +0000276 outs() << " (addr 0x" << format("%" PRIx32, Sec.addr) << " offset "
Kevin Enderby10769742014-07-01 22:26:31 +0000277 << Sec.offset << ")";
Kevin Enderby246a4602014-06-17 17:54:13 +0000278 outs() << "\n";
279 sec_total += Sec.size;
280 }
281 if (Seg.nsects != 0)
282 outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
283 }
Kevin Enderby246a4602014-06-17 17:54:13 +0000284 }
285 outs() << "total " << format(fmt.str().c_str(), total) << "\n";
286}
287
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000288/// Print the summary sizes of the standard Mach-O segments in @p MachO.
Kevin Enderby246a4602014-06-17 17:54:13 +0000289///
290/// This is when used when @c OutputFormat is berkeley with a Mach-O file and
291/// produces the same output as darwin's size(1) default output.
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000292static void printDarwinSegmentSizes(MachOObjectFile *MachO) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000293 uint64_t total_text = 0;
294 uint64_t total_data = 0;
295 uint64_t total_objc = 0;
296 uint64_t total_others = 0;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000297 for (const auto &Load : MachO->load_commands()) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000298 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
299 MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
300 if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
301 for (unsigned J = 0; J < Seg.nsects; ++J) {
302 MachO::section_64 Sec = MachO->getSection64(Load, J);
303 StringRef SegmentName = StringRef(Sec.segname);
304 if (SegmentName == "__TEXT")
305 total_text += Sec.size;
306 else if (SegmentName == "__DATA")
307 total_data += Sec.size;
308 else if (SegmentName == "__OBJC")
309 total_objc += Sec.size;
310 else
311 total_others += Sec.size;
Kevin Enderby10769742014-07-01 22:26:31 +0000312 }
Kevin Enderby246a4602014-06-17 17:54:13 +0000313 } else {
314 StringRef SegmentName = StringRef(Seg.segname);
315 if (SegmentName == "__TEXT")
316 total_text += Seg.vmsize;
317 else if (SegmentName == "__DATA")
318 total_data += Seg.vmsize;
319 else if (SegmentName == "__OBJC")
320 total_objc += Seg.vmsize;
321 else
322 total_others += Seg.vmsize;
323 }
Kevin Enderby10769742014-07-01 22:26:31 +0000324 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000325 MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
326 if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
327 for (unsigned J = 0; J < Seg.nsects; ++J) {
328 MachO::section Sec = MachO->getSection(Load, J);
329 StringRef SegmentName = StringRef(Sec.segname);
330 if (SegmentName == "__TEXT")
331 total_text += Sec.size;
332 else if (SegmentName == "__DATA")
333 total_data += Sec.size;
334 else if (SegmentName == "__OBJC")
335 total_objc += Sec.size;
336 else
337 total_others += Sec.size;
Kevin Enderby10769742014-07-01 22:26:31 +0000338 }
Kevin Enderby246a4602014-06-17 17:54:13 +0000339 } else {
340 StringRef SegmentName = StringRef(Seg.segname);
341 if (SegmentName == "__TEXT")
342 total_text += Seg.vmsize;
343 else if (SegmentName == "__DATA")
344 total_data += Seg.vmsize;
345 else if (SegmentName == "__OBJC")
346 total_objc += Seg.vmsize;
347 else
348 total_others += Seg.vmsize;
349 }
350 }
Kevin Enderby246a4602014-06-17 17:54:13 +0000351 }
352 uint64_t total = total_text + total_data + total_objc + total_others;
353
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000354 if (!BerkeleyHeaderPrinted) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000355 outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000356 BerkeleyHeaderPrinted = true;
Kevin Enderby246a4602014-06-17 17:54:13 +0000357 }
358 outs() << total_text << "\t" << total_data << "\t" << total_objc << "\t"
359 << total_others << "\t" << total << "\t" << format("%" PRIx64, total)
360 << "\t";
361}
362
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000363/// Print the size of each section in @p Obj.
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000364///
365/// The format used is determined by @c OutputFormat and @c Radix.
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000366static void printObjectSectionSizes(ObjectFile *Obj) {
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000367 uint64_t total = 0;
368 std::string fmtbuf;
369 raw_string_ostream fmt(fmtbuf);
Kevin Enderby246a4602014-06-17 17:54:13 +0000370 const char *radix_fmt = getRadixFmt();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000371
Kevin Enderby246a4602014-06-17 17:54:13 +0000372 // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
373 // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
374 // let it fall through to OutputFormat berkeley.
375 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
376 if (OutputFormat == darwin && MachO)
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000377 printDarwinSectionSizes(MachO);
Kevin Enderby246a4602014-06-17 17:54:13 +0000378 // If we have a MachOObjectFile and the OutputFormat is berkeley print as
379 // darwin's default berkeley format for Mach-O files.
380 else if (MachO && OutputFormat == berkeley)
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000381 printDarwinSegmentSizes(MachO);
Kevin Enderby246a4602014-06-17 17:54:13 +0000382 else if (OutputFormat == sysv) {
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000383 // Run two passes over all sections. The first gets the lengths needed for
384 // formatting the output. The second actually does the output.
385 std::size_t max_name_len = strlen("section");
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000386 std::size_t max_size_len = strlen("size");
387 std::size_t max_addr_len = strlen("addr");
Alexey Samsonov48803e52014-03-13 14:37:36 +0000388 for (const SectionRef &Section : Obj->sections()) {
Rafael Espindolaa0ff5562016-02-09 21:39:49 +0000389 if (!considerForSize(Obj, Section))
390 continue;
Rafael Espindola80291272014-10-08 15:28:58 +0000391 uint64_t size = Section.getSize();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000392 total += size;
393
394 StringRef name;
Alexey Samsonov48803e52014-03-13 14:37:36 +0000395 if (error(Section.getName(name)))
396 return;
Rafael Espindola80291272014-10-08 15:28:58 +0000397 uint64_t addr = Section.getAddress();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000398 max_name_len = std::max(max_name_len, name.size());
Andrew Trick7dc278d2011-09-29 01:22:31 +0000399 max_size_len = std::max(max_size_len, getNumLengthAsString(size));
400 max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000401 }
402
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000403 // Add extra padding.
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000404 max_name_len += 2;
405 max_size_len += 2;
406 max_addr_len += 2;
407
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000408 // Setup header format.
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000409 fmt << "%-" << max_name_len << "s "
410 << "%" << max_size_len << "s "
411 << "%" << max_addr_len << "s\n";
412
413 // Print header
Kevin Enderby10769742014-07-01 22:26:31 +0000414 outs() << format(fmt.str().c_str(), static_cast<const char *>("section"),
415 static_cast<const char *>("size"),
416 static_cast<const char *>("addr"));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000417 fmtbuf.clear();
418
419 // Setup per section format.
420 fmt << "%-" << max_name_len << "s "
421 << "%#" << max_size_len << radix_fmt << " "
422 << "%#" << max_addr_len << radix_fmt << "\n";
423
424 // Print each section.
Alexey Samsonov48803e52014-03-13 14:37:36 +0000425 for (const SectionRef &Section : Obj->sections()) {
Rafael Espindolaa0ff5562016-02-09 21:39:49 +0000426 if (!considerForSize(Obj, Section))
427 continue;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000428 StringRef name;
Alexey Samsonov48803e52014-03-13 14:37:36 +0000429 if (error(Section.getName(name)))
430 return;
Rafael Espindola80291272014-10-08 15:28:58 +0000431 uint64_t size = Section.getSize();
432 uint64_t addr = Section.getAddress();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000433 std::string namestr = name;
434
Alexey Samsonov48803e52014-03-13 14:37:36 +0000435 outs() << format(fmt.str().c_str(), namestr.c_str(), size, addr);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000436 }
437
Hemant Kulkarni274457e2016-03-28 16:48:10 +0000438 if (ELFCommons) {
439 uint64_t CommonSize = getCommonSize(Obj);
440 total += CommonSize;
441 outs() << format(fmt.str().c_str(), std::string("*COM*").c_str(),
442 CommonSize, static_cast<uint64_t>(0));
443 }
444
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000445 // Print total.
446 fmtbuf.clear();
447 fmt << "%-" << max_name_len << "s "
448 << "%#" << max_size_len << radix_fmt << "\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000449 outs() << format(fmt.str().c_str(), static_cast<const char *>("Total"),
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000450 total);
451 } else {
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000452 // The Berkeley format does not display individual section sizes. It
453 // displays the cumulative size for each section type.
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000454 uint64_t total_text = 0;
455 uint64_t total_data = 0;
456 uint64_t total_bss = 0;
457
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000458 // Make one pass over the section table to calculate sizes.
Alexey Samsonov48803e52014-03-13 14:37:36 +0000459 for (const SectionRef &Section : Obj->sections()) {
Rafael Espindola80291272014-10-08 15:28:58 +0000460 uint64_t size = Section.getSize();
461 bool isText = Section.isText();
462 bool isData = Section.isData();
463 bool isBSS = Section.isBSS();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000464 if (isText)
465 total_text += size;
466 else if (isData)
467 total_data += size;
468 else if (isBSS)
469 total_bss += size;
470 }
471
Hemant Kulkarni274457e2016-03-28 16:48:10 +0000472 if (ELFCommons)
473 total_bss += getCommonSize(Obj);
474
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000475 total = total_text + total_data + total_bss;
476
Hemant Kulkarni5f4ca2f2016-09-12 17:08:28 +0000477 if (TotalSizes) {
478 TotalObjectText += total_text;
479 TotalObjectData += total_data;
480 TotalObjectBss += total_bss;
481 TotalObjectTotal += total;
482 }
483
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000484 if (!BerkeleyHeaderPrinted) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000485 outs() << " text data bss "
Kevin Enderby10769742014-07-01 22:26:31 +0000486 << (Radix == octal ? "oct" : "dec") << " hex filename\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000487 BerkeleyHeaderPrinted = true;
Kevin Enderby246a4602014-06-17 17:54:13 +0000488 }
489
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000490 // Print result.
491 fmt << "%#7" << radix_fmt << " "
492 << "%#7" << radix_fmt << " "
493 << "%#7" << radix_fmt << " ";
Kevin Enderby10769742014-07-01 22:26:31 +0000494 outs() << format(fmt.str().c_str(), total_text, total_data, total_bss);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000495 fmtbuf.clear();
Benjamin Kramerf3da5292011-11-05 08:57:40 +0000496 fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << " "
497 << "%7" PRIx64 " ";
Kevin Enderby10769742014-07-01 22:26:31 +0000498 outs() << format(fmt.str().c_str(), total, total);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000499 }
500}
501
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000502/// Checks to see if the @p o ObjectFile is a Mach-O file and if it is and there
503/// is a list of architecture flags specified then check to make sure this
504/// Mach-O file is one of those architectures or all architectures was
505/// specificed. If not then an error is generated and this routine returns
506/// false. Else it returns true.
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000507static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) {
508 if (isa<MachOObjectFile>(o) && !ArchAll && ArchFlags.size() != 0) {
509 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
510 bool ArchFound = false;
511 MachO::mach_header H;
512 MachO::mach_header_64 H_64;
513 Triple T;
514 if (MachO->is64Bit()) {
515 H_64 = MachO->MachOObjectFile::getHeader64();
Tim Northover9e8eb412016-04-22 23:21:13 +0000516 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000517 } else {
518 H = MachO->MachOObjectFile::getHeader();
Tim Northover9e8eb412016-04-22 23:21:13 +0000519 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000520 }
521 unsigned i;
Kevin Enderby10769742014-07-01 22:26:31 +0000522 for (i = 0; i < ArchFlags.size(); ++i) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000523 if (ArchFlags[i] == T.getArchName())
524 ArchFound = true;
525 break;
526 }
527 if (!ArchFound) {
528 errs() << ToolName << ": file: " << file
529 << " does not contain architecture: " << ArchFlags[i] << ".\n";
530 return false;
531 }
532 }
533 return true;
534}
535
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000536/// Print the section sizes for @p file. If @p file is an archive, print the
537/// section sizes for each archive member.
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000538static void printFileSectionSizes(StringRef file) {
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000539
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000540 // Attempt to open the binary.
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000541 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
542 if (!BinaryOrErr) {
Kevin Enderby600fb3f2016-08-05 18:19:40 +0000543 error(BinaryOrErr.takeError(), file);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000544 return;
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000545 }
Rafael Espindola48af1c22014-08-19 18:44:46 +0000546 Binary &Bin = *BinaryOrErr.get().getBinary();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000547
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000548 if (Archive *a = dyn_cast<Archive>(&Bin)) {
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000549 // This is an archive. Iterate over each member and display its sizes.
Lang Hamesfc209622016-07-14 02:24:01 +0000550 Error Err;
551 for (auto &C : a->children(Err)) {
552 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000553 if (!ChildOrErr) {
554 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
Lang Hamesfc209622016-07-14 02:24:01 +0000555 error(std::move(E), a->getFileName(), C);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000556 continue;
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000557 }
Rafael Espindolaae460022014-06-16 16:08:36 +0000558 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000559 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000560 if (!checkMachOAndArchFlags(o, file))
561 return;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000562 if (OutputFormat == sysv)
Kevin Enderby10769742014-07-01 22:26:31 +0000563 outs() << o->getFileName() << " (ex " << a->getFileName() << "):\n";
564 else if (MachO && OutputFormat == darwin)
565 outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000566 printObjectSectionSizes(o);
Kevin Enderby246a4602014-06-17 17:54:13 +0000567 if (OutputFormat == berkeley) {
568 if (MachO)
569 outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
570 else
571 outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
572 }
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000573 }
574 }
Lang Hamesfc209622016-07-14 02:24:01 +0000575 if (Err)
576 error(std::move(Err), a->getFileName());
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000577 } else if (MachOUniversalBinary *UB =
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000578 dyn_cast<MachOUniversalBinary>(&Bin)) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000579 // If we have a list of architecture flags specified dump only those.
580 if (!ArchAll && ArchFlags.size() != 0) {
581 // Look for a slice in the universal binary that matches each ArchFlag.
582 bool ArchFound;
Kevin Enderby10769742014-07-01 22:26:31 +0000583 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000584 ArchFound = false;
585 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
586 E = UB->end_objects();
587 I != E; ++I) {
Kevin Enderby10769742014-07-01 22:26:31 +0000588 if (ArchFlags[i] == I->getArchTypeName()) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000589 ArchFound = true;
Kevin Enderby9acb1092016-05-31 20:35:34 +0000590 Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000591 if (UO) {
592 if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
593 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
594 if (OutputFormat == sysv)
595 outs() << o->getFileName() << " :\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000596 else if (MachO && OutputFormat == darwin) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000597 if (MoreThanOneFile || ArchFlags.size() > 1)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000598 outs() << o->getFileName() << " (for architecture "
599 << I->getArchTypeName() << "): \n";
600 }
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000601 printObjectSectionSizes(o);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000602 if (OutputFormat == berkeley) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000603 if (!MachO || MoreThanOneFile || ArchFlags.size() > 1)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000604 outs() << o->getFileName() << " (for architecture "
605 << I->getArchTypeName() << ")";
606 outs() << "\n";
607 }
608 }
Kevin Enderby9acb1092016-05-31 20:35:34 +0000609 } else if (auto E = isNotObjectErrorInvalidFileType(
610 UO.takeError())) {
611 error(std::move(E), file, ArchFlags.size() > 1 ?
612 StringRef(I->getArchTypeName()) : StringRef());
613 return;
Kevin Enderby42398052016-06-28 23:16:13 +0000614 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
Rafael Espindola0bfe8282014-12-09 21:05:36 +0000615 I->getAsArchive()) {
616 std::unique_ptr<Archive> &UA = *AOrErr;
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000617 // This is an archive. Iterate over each member and display its
Kevin Enderby10769742014-07-01 22:26:31 +0000618 // sizes.
Lang Hamesfc209622016-07-14 02:24:01 +0000619 Error Err;
620 for (auto &C : UA->children(Err)) {
621 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000622 if (!ChildOrErr) {
Kevin Enderby9acb1092016-05-31 20:35:34 +0000623 if (auto E = isNotObjectErrorInvalidFileType(
624 ChildOrErr.takeError()))
Lang Hamesfc209622016-07-14 02:24:01 +0000625 error(std::move(E), UA->getFileName(), C,
Kevin Enderby9acb1092016-05-31 20:35:34 +0000626 ArchFlags.size() > 1 ?
627 StringRef(I->getArchTypeName()) : StringRef());
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000628 continue;
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000629 }
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000630 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
631 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
632 if (OutputFormat == sysv)
633 outs() << o->getFileName() << " (ex " << UA->getFileName()
634 << "):\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000635 else if (MachO && OutputFormat == darwin)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000636 outs() << UA->getFileName() << "(" << o->getFileName()
Kevin Enderby10769742014-07-01 22:26:31 +0000637 << ")"
638 << " (for architecture " << I->getArchTypeName()
639 << "):\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000640 printObjectSectionSizes(o);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000641 if (OutputFormat == berkeley) {
642 if (MachO) {
643 outs() << UA->getFileName() << "(" << o->getFileName()
644 << ")";
645 if (ArchFlags.size() > 1)
Kevin Enderby10769742014-07-01 22:26:31 +0000646 outs() << " (for architecture " << I->getArchTypeName()
647 << ")";
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000648 outs() << "\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000649 } else
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000650 outs() << o->getFileName() << " (ex " << UA->getFileName()
651 << ")\n";
652 }
653 }
654 }
Lang Hamesfc209622016-07-14 02:24:01 +0000655 if (Err)
656 error(std::move(Err), UA->getFileName());
Kevin Enderby42398052016-06-28 23:16:13 +0000657 } else {
658 consumeError(AOrErr.takeError());
659 error("Mach-O universal file: " + file + " for architecture " +
660 StringRef(I->getArchTypeName()) +
661 " is not a Mach-O file or an archive file");
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000662 }
663 }
664 }
665 if (!ArchFound) {
666 errs() << ToolName << ": file: " << file
667 << " does not contain architecture" << ArchFlags[i] << ".\n";
668 return;
669 }
670 }
671 return;
672 }
673 // No architecture flags were specified so if this contains a slice that
674 // matches the host architecture dump only that.
675 if (!ArchAll) {
Kevin Enderby10769742014-07-01 22:26:31 +0000676 StringRef HostArchName = MachOObjectFile::getHostArch().getArchName();
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000677 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
678 E = UB->end_objects();
679 I != E; ++I) {
Kevin Enderby10769742014-07-01 22:26:31 +0000680 if (HostArchName == I->getArchTypeName()) {
Kevin Enderby9acb1092016-05-31 20:35:34 +0000681 Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000682 if (UO) {
683 if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
684 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
685 if (OutputFormat == sysv)
686 outs() << o->getFileName() << " :\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000687 else if (MachO && OutputFormat == darwin) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000688 if (MoreThanOneFile)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000689 outs() << o->getFileName() << " (for architecture "
690 << I->getArchTypeName() << "):\n";
691 }
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000692 printObjectSectionSizes(o);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000693 if (OutputFormat == berkeley) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000694 if (!MachO || MoreThanOneFile)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000695 outs() << o->getFileName() << " (for architecture "
696 << I->getArchTypeName() << ")";
697 outs() << "\n";
698 }
699 }
Kevin Enderby9acb1092016-05-31 20:35:34 +0000700 } else if (auto E = isNotObjectErrorInvalidFileType(UO.takeError())) {
701 error(std::move(E), file);
702 return;
Kevin Enderby42398052016-06-28 23:16:13 +0000703 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
Rafael Espindola0bfe8282014-12-09 21:05:36 +0000704 I->getAsArchive()) {
705 std::unique_ptr<Archive> &UA = *AOrErr;
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000706 // This is an archive. Iterate over each member and display its
707 // sizes.
Lang Hamesfc209622016-07-14 02:24:01 +0000708 Error Err;
709 for (auto &C : UA->children(Err)) {
710 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000711 if (!ChildOrErr) {
Kevin Enderby9acb1092016-05-31 20:35:34 +0000712 if (auto E = isNotObjectErrorInvalidFileType(
713 ChildOrErr.takeError()))
Lang Hamesfc209622016-07-14 02:24:01 +0000714 error(std::move(E), UA->getFileName(), C);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000715 continue;
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000716 }
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000717 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
718 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
719 if (OutputFormat == sysv)
720 outs() << o->getFileName() << " (ex " << UA->getFileName()
721 << "):\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000722 else if (MachO && OutputFormat == darwin)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000723 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
724 << " (for architecture " << I->getArchTypeName()
725 << "):\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000726 printObjectSectionSizes(o);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000727 if (OutputFormat == berkeley) {
728 if (MachO)
729 outs() << UA->getFileName() << "(" << o->getFileName()
730 << ")\n";
731 else
732 outs() << o->getFileName() << " (ex " << UA->getFileName()
733 << ")\n";
734 }
735 }
736 }
Lang Hamesfc209622016-07-14 02:24:01 +0000737 if (Err)
738 error(std::move(Err), UA->getFileName());
Kevin Enderby42398052016-06-28 23:16:13 +0000739 } else {
740 consumeError(AOrErr.takeError());
741 error("Mach-O universal file: " + file + " for architecture " +
742 StringRef(I->getArchTypeName()) +
743 " is not a Mach-O file or an archive file");
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000744 }
745 return;
746 }
747 }
748 }
749 // Either all architectures have been specified or none have been specified
750 // and this does not contain the host architecture so dump all the slices.
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000751 bool MoreThanOneArch = UB->getNumberOfObjects() > 1;
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000752 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
753 E = UB->end_objects();
754 I != E; ++I) {
Kevin Enderby9acb1092016-05-31 20:35:34 +0000755 Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
Rafael Espindola4f7932b2014-06-23 20:41:02 +0000756 if (UO) {
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000757 if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
Kevin Enderby1983fcf2014-06-19 22:03:18 +0000758 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000759 if (OutputFormat == sysv)
760 outs() << o->getFileName() << " :\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000761 else if (MachO && OutputFormat == darwin) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000762 if (MoreThanOneFile || MoreThanOneArch)
Kevin Enderby1983fcf2014-06-19 22:03:18 +0000763 outs() << o->getFileName() << " (for architecture "
764 << I->getArchTypeName() << "):";
765 outs() << "\n";
766 }
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000767 printObjectSectionSizes(o);
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000768 if (OutputFormat == berkeley) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000769 if (!MachO || MoreThanOneFile || MoreThanOneArch)
Kevin Enderby1983fcf2014-06-19 22:03:18 +0000770 outs() << o->getFileName() << " (for architecture "
771 << I->getArchTypeName() << ")";
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000772 outs() << "\n";
773 }
774 }
Kevin Enderby9acb1092016-05-31 20:35:34 +0000775 } else if (auto E = isNotObjectErrorInvalidFileType(UO.takeError())) {
776 error(std::move(E), file, MoreThanOneArch ?
777 StringRef(I->getArchTypeName()) : StringRef());
778 return;
Kevin Enderby42398052016-06-28 23:16:13 +0000779 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
Rafael Espindola0bfe8282014-12-09 21:05:36 +0000780 I->getAsArchive()) {
781 std::unique_ptr<Archive> &UA = *AOrErr;
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000782 // This is an archive. Iterate over each member and display its sizes.
Lang Hamesfc209622016-07-14 02:24:01 +0000783 Error Err;
784 for (auto &C : UA->children(Err)) {
785 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000786 if (!ChildOrErr) {
Kevin Enderby9acb1092016-05-31 20:35:34 +0000787 if (auto E = isNotObjectErrorInvalidFileType(
788 ChildOrErr.takeError()))
Lang Hamesfc209622016-07-14 02:24:01 +0000789 error(std::move(E), UA->getFileName(), C, MoreThanOneArch ?
Kevin Enderby9acb1092016-05-31 20:35:34 +0000790 StringRef(I->getArchTypeName()) : StringRef());
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000791 continue;
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000792 }
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000793 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
794 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
795 if (OutputFormat == sysv)
796 outs() << o->getFileName() << " (ex " << UA->getFileName()
797 << "):\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000798 else if (MachO && OutputFormat == darwin)
Kevin Enderby1983fcf2014-06-19 22:03:18 +0000799 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
Kevin Enderby10769742014-07-01 22:26:31 +0000800 << " (for architecture " << I->getArchTypeName() << "):\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000801 printObjectSectionSizes(o);
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000802 if (OutputFormat == berkeley) {
803 if (MachO)
Kevin Enderby1983fcf2014-06-19 22:03:18 +0000804 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
805 << " (for architecture " << I->getArchTypeName()
806 << ")\n";
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000807 else
808 outs() << o->getFileName() << " (ex " << UA->getFileName()
809 << ")\n";
810 }
811 }
812 }
Lang Hamesfc209622016-07-14 02:24:01 +0000813 if (Err)
814 error(std::move(Err), UA->getFileName());
Kevin Enderby42398052016-06-28 23:16:13 +0000815 } else {
816 consumeError(AOrErr.takeError());
817 error("Mach-O universal file: " + file + " for architecture " +
818 StringRef(I->getArchTypeName()) +
819 " is not a Mach-O file or an archive file");
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000820 }
821 }
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000822 } else if (ObjectFile *o = dyn_cast<ObjectFile>(&Bin)) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000823 if (!checkMachOAndArchFlags(o, file))
824 return;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000825 if (OutputFormat == sysv)
826 outs() << o->getFileName() << " :\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000827 printObjectSectionSizes(o);
Kevin Enderby246a4602014-06-17 17:54:13 +0000828 if (OutputFormat == berkeley) {
829 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000830 if (!MachO || MoreThanOneFile)
Kevin Enderby246a4602014-06-17 17:54:13 +0000831 outs() << o->getFileName();
832 outs() << "\n";
833 }
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000834 } else {
Kevin Enderby10769742014-07-01 22:26:31 +0000835 errs() << ToolName << ": " << file << ": "
836 << "Unrecognized file type.\n";
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000837 }
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000838 // System V adds an extra newline at the end of each file.
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000839 if (OutputFormat == sysv)
840 outs() << "\n";
841}
842
Hemant Kulkarni5f4ca2f2016-09-12 17:08:28 +0000843static void printBerkelyTotals() {
844 std::string fmtbuf;
845 raw_string_ostream fmt(fmtbuf);
846 const char *radix_fmt = getRadixFmt();
847 fmt << "%#7" << radix_fmt << " "
848 << "%#7" << radix_fmt << " "
849 << "%#7" << radix_fmt << " ";
850 outs() << format(fmt.str().c_str(), TotalObjectText, TotalObjectData,
851 TotalObjectBss);
852 fmtbuf.clear();
853 fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << " "
854 << "%7" PRIx64 " ";
855 outs() << format(fmt.str().c_str(), TotalObjectTotal, TotalObjectTotal)
856 << "(TOTALS)\n";
857}
858
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000859int main(int argc, char **argv) {
860 // Print a stack trace if we signal out.
Richard Smith2ad6d482016-06-09 00:53:21 +0000861 sys::PrintStackTraceOnErrorSignal(argv[0]);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000862 PrettyStackTraceProgram X(argc, argv);
863
Kevin Enderby10769742014-07-01 22:26:31 +0000864 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000865 cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n");
866
867 ToolName = argv[0];
868 if (OutputFormatShort.getNumOccurrences())
Chris Bienemane71fb5c2015-01-22 01:49:59 +0000869 OutputFormat = static_cast<OutputFormatTy>(OutputFormatShort);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000870 if (RadixShort.getNumOccurrences())
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000871 Radix = RadixShort;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000872
Kevin Enderby10769742014-07-01 22:26:31 +0000873 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000874 if (ArchFlags[i] == "all") {
875 ArchAll = true;
Kevin Enderby10769742014-07-01 22:26:31 +0000876 } else {
Rafael Espindola72318b42014-08-08 16:30:17 +0000877 if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000878 outs() << ToolName << ": for the -arch option: Unknown architecture "
879 << "named '" << ArchFlags[i] << "'";
880 return 1;
881 }
882 }
883 }
884
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000885 if (InputFilenames.size() == 0)
886 InputFilenames.push_back("a.out");
887
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000888 MoreThanOneFile = InputFilenames.size() > 1;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000889 std::for_each(InputFilenames.begin(), InputFilenames.end(),
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000890 printFileSectionSizes);
Hemant Kulkarni5f4ca2f2016-09-12 17:08:28 +0000891 if (OutputFormat == berkeley && TotalSizes)
892 printBerkelyTotals();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000893
Kevin Enderby64f7a992016-05-02 21:41:03 +0000894 if (HadError)
895 return 1;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000896}