blob: 351a6b1bfbd937aab345a75ebcfdd69759a4b4f8 [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;
Kevin Enderby246a4602014-06-17 17:54:13 +000055
Kevin Enderby10769742014-07-01 22:26:31 +000056cl::opt<bool>
57DarwinLongFormat("l", cl::desc("When format is darwin, use long format "
58 "to include addresses and offsets."));
Kevin Enderby246a4602014-06-17 17:54:13 +000059
Hemant Kulkarni274457e2016-03-28 16:48:10 +000060cl::opt<bool>
61 ELFCommons("common",
62 cl::desc("Print common symbols in the ELF file. When using "
63 "Berkely format, this is added to bss."),
64 cl::init(false));
65
Kevin Enderbyafef4c92014-07-01 17:19:10 +000066static cl::list<std::string>
Kevin Enderby10769742014-07-01 22:26:31 +000067ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
68 cl::ZeroOrMore);
Kevin Enderbyafef4c92014-07-01 17:19:10 +000069bool ArchAll = false;
70
Kevin Enderby10769742014-07-01 22:26:31 +000071enum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 };
Michael J. Spencercc5f8d42011-09-29 00:59:18 +000072static cl::opt<unsigned int>
Kevin Enderby10769742014-07-01 22:26:31 +000073Radix("-radix", cl::desc("Print size in radix. Only 8, 10, and 16 are valid"),
74 cl::init(decimal));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000075
Michael J. Spencercc5f8d42011-09-29 00:59:18 +000076static cl::opt<RadixTy>
Kevin Enderby10769742014-07-01 22:26:31 +000077RadixShort(cl::desc("Print size in radix:"),
78 cl::values(clEnumValN(octal, "o", "Print size in octal"),
79 clEnumValN(decimal, "d", "Print size in decimal"),
80 clEnumValN(hexadecimal, "x", "Print size in hexadecimal"),
81 clEnumValEnd),
82 cl::init(decimal));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000083
Michael J. Spencercc5f8d42011-09-29 00:59:18 +000084static cl::list<std::string>
Kevin Enderby10769742014-07-01 22:26:31 +000085InputFilenames(cl::Positional, cl::desc("<input files>"), cl::ZeroOrMore);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000086
Kevin Enderby64f7a992016-05-02 21:41:03 +000087bool HadError = false;
88
Michael J. Spencercc5f8d42011-09-29 00:59:18 +000089static std::string ToolName;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000090
Rafael Espindola49a0e5e2016-02-09 21:32:56 +000091/// If ec is not success, print the error and return true.
Rafael Espindola4453e42942014-06-13 03:07:50 +000092static bool error(std::error_code ec) {
Kevin Enderby10769742014-07-01 22:26:31 +000093 if (!ec)
94 return false;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000095
Kevin Enderby64f7a992016-05-02 21:41:03 +000096 HadError = true;
Davide Italiano911eb312016-01-25 01:24:15 +000097 errs() << ToolName << ": error reading file: " << ec.message() << ".\n";
98 errs().flush();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +000099 return true;
100}
101
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000102// This version of error() prints the archive name and member name, for example:
103// "libx.a(foo.o)" after the ToolName before the error message. It sets
104// HadError but returns allowing the code to move on to other archive members.
105static void error(llvm::Error E, StringRef FileName, const Archive::Child &C) {
106 HadError = true;
107 errs() << ToolName << ": " << FileName;
108
109 ErrorOr<StringRef> NameOrErr = C.getName();
110 // TODO: if we have a error getting the name then it would be nice to print
111 // the index of which archive member this is and or its offset in the
112 // archive instead of "???" as the name.
113 if (NameOrErr.getError())
114 errs() << "(" << "???" << ")";
115 else
116 errs() << "(" << NameOrErr.get() << ")";
117
118 std::string Buf;
119 raw_string_ostream OS(Buf);
120 logAllUnhandledErrors(std::move(E), OS, "");
121 OS.flush();
122 errs() << " " << Buf << "\n";
123}
124
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000125/// Get the length of the string that represents @p num in Radix including the
126/// leading 0x or 0 for hexadecimal and octal respectively.
Andrew Trick7dc278d2011-09-29 01:22:31 +0000127static size_t getNumLengthAsString(uint64_t num) {
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000128 APInt conv(64, num);
129 SmallString<32> result;
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000130 conv.toString(result, Radix, false, true);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000131 return result.size();
132}
133
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000134/// Return the printing format for the Radix.
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000135static const char *getRadixFmt() {
Kevin Enderby246a4602014-06-17 17:54:13 +0000136 switch (Radix) {
137 case octal:
138 return PRIo64;
139 case decimal:
140 return PRIu64;
141 case hexadecimal:
142 return PRIx64;
143 }
144 return nullptr;
145}
146
Rafael Espindolaa0ff5562016-02-09 21:39:49 +0000147/// Remove unneeded ELF sections from calculation
148static bool considerForSize(ObjectFile *Obj, SectionRef Section) {
149 if (!Obj->isELF())
150 return true;
151 switch (static_cast<ELFSectionRef>(Section).getType()) {
152 case ELF::SHT_NULL:
153 case ELF::SHT_SYMTAB:
154 case ELF::SHT_STRTAB:
155 case ELF::SHT_REL:
156 case ELF::SHT_RELA:
157 return false;
158 }
159 return true;
160}
161
Hemant Kulkarni274457e2016-03-28 16:48:10 +0000162/// Total size of all ELF common symbols
163static uint64_t getCommonSize(ObjectFile *Obj) {
164 uint64_t TotalCommons = 0;
165 for (auto &Sym : Obj->symbols())
166 if (Obj->getSymbolFlags(Sym.getRawDataRefImpl()) & SymbolRef::SF_Common)
167 TotalCommons += Obj->getCommonSymbolSize(Sym.getRawDataRefImpl());
168 return TotalCommons;
169}
170
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000171/// Print the size of each Mach-O segment and section in @p MachO.
Kevin Enderby246a4602014-06-17 17:54:13 +0000172///
173/// This is when used when @c OutputFormat is darwin and produces the same
174/// output as darwin's size(1) -m output.
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000175static void printDarwinSectionSizes(MachOObjectFile *MachO) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000176 std::string fmtbuf;
177 raw_string_ostream fmt(fmtbuf);
178 const char *radix_fmt = getRadixFmt();
179 if (Radix == hexadecimal)
180 fmt << "0x";
181 fmt << "%" << radix_fmt;
182
Kevin Enderby246a4602014-06-17 17:54:13 +0000183 uint32_t Filetype = MachO->getHeader().filetype;
Kevin Enderby246a4602014-06-17 17:54:13 +0000184
185 uint64_t total = 0;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000186 for (const auto &Load : MachO->load_commands()) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000187 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
188 MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
189 outs() << "Segment " << Seg.segname << ": "
190 << format(fmt.str().c_str(), Seg.vmsize);
191 if (DarwinLongFormat)
Kevin Enderby10769742014-07-01 22:26:31 +0000192 outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr) << " fileoff "
193 << Seg.fileoff << ")";
Kevin Enderby246a4602014-06-17 17:54:13 +0000194 outs() << "\n";
195 total += Seg.vmsize;
196 uint64_t sec_total = 0;
197 for (unsigned J = 0; J < Seg.nsects; ++J) {
198 MachO::section_64 Sec = MachO->getSection64(Load, J);
199 if (Filetype == MachO::MH_OBJECT)
200 outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
201 << format("%.16s", &Sec.sectname) << "): ";
202 else
203 outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
204 outs() << format(fmt.str().c_str(), Sec.size);
205 if (DarwinLongFormat)
Kevin Enderby10769742014-07-01 22:26:31 +0000206 outs() << " (addr 0x" << format("%" PRIx64, Sec.addr) << " offset "
207 << Sec.offset << ")";
Kevin Enderby246a4602014-06-17 17:54:13 +0000208 outs() << "\n";
209 sec_total += Sec.size;
210 }
211 if (Seg.nsects != 0)
212 outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000213 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000214 MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
Kevin Enderby2058e9d2016-02-09 18:33:15 +0000215 uint64_t Seg_vmsize = Seg.vmsize;
Kevin Enderby246a4602014-06-17 17:54:13 +0000216 outs() << "Segment " << Seg.segname << ": "
Kevin Enderby2058e9d2016-02-09 18:33:15 +0000217 << format(fmt.str().c_str(), Seg_vmsize);
Kevin Enderby246a4602014-06-17 17:54:13 +0000218 if (DarwinLongFormat)
Kevin Enderby2058e9d2016-02-09 18:33:15 +0000219 outs() << " (vmaddr 0x" << format("%" PRIx32, Seg.vmaddr) << " fileoff "
Kevin Enderby10769742014-07-01 22:26:31 +0000220 << Seg.fileoff << ")";
Kevin Enderby246a4602014-06-17 17:54:13 +0000221 outs() << "\n";
222 total += Seg.vmsize;
223 uint64_t sec_total = 0;
224 for (unsigned J = 0; J < Seg.nsects; ++J) {
225 MachO::section Sec = MachO->getSection(Load, J);
226 if (Filetype == MachO::MH_OBJECT)
227 outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
228 << format("%.16s", &Sec.sectname) << "): ";
229 else
230 outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
Kevin Enderby2058e9d2016-02-09 18:33:15 +0000231 uint64_t Sec_size = Sec.size;
232 outs() << format(fmt.str().c_str(), Sec_size);
Kevin Enderby246a4602014-06-17 17:54:13 +0000233 if (DarwinLongFormat)
Kevin Enderby2058e9d2016-02-09 18:33:15 +0000234 outs() << " (addr 0x" << format("%" PRIx32, Sec.addr) << " offset "
Kevin Enderby10769742014-07-01 22:26:31 +0000235 << Sec.offset << ")";
Kevin Enderby246a4602014-06-17 17:54:13 +0000236 outs() << "\n";
237 sec_total += Sec.size;
238 }
239 if (Seg.nsects != 0)
240 outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
241 }
Kevin Enderby246a4602014-06-17 17:54:13 +0000242 }
243 outs() << "total " << format(fmt.str().c_str(), total) << "\n";
244}
245
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000246/// Print the summary sizes of the standard Mach-O segments in @p MachO.
Kevin Enderby246a4602014-06-17 17:54:13 +0000247///
248/// This is when used when @c OutputFormat is berkeley with a Mach-O file and
249/// produces the same output as darwin's size(1) default output.
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000250static void printDarwinSegmentSizes(MachOObjectFile *MachO) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000251 uint64_t total_text = 0;
252 uint64_t total_data = 0;
253 uint64_t total_objc = 0;
254 uint64_t total_others = 0;
Alexey Samsonovd319c4f2015-06-03 22:19:36 +0000255 for (const auto &Load : MachO->load_commands()) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000256 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
257 MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
258 if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
259 for (unsigned J = 0; J < Seg.nsects; ++J) {
260 MachO::section_64 Sec = MachO->getSection64(Load, J);
261 StringRef SegmentName = StringRef(Sec.segname);
262 if (SegmentName == "__TEXT")
263 total_text += Sec.size;
264 else if (SegmentName == "__DATA")
265 total_data += Sec.size;
266 else if (SegmentName == "__OBJC")
267 total_objc += Sec.size;
268 else
269 total_others += Sec.size;
Kevin Enderby10769742014-07-01 22:26:31 +0000270 }
Kevin Enderby246a4602014-06-17 17:54:13 +0000271 } else {
272 StringRef SegmentName = StringRef(Seg.segname);
273 if (SegmentName == "__TEXT")
274 total_text += Seg.vmsize;
275 else if (SegmentName == "__DATA")
276 total_data += Seg.vmsize;
277 else if (SegmentName == "__OBJC")
278 total_objc += Seg.vmsize;
279 else
280 total_others += Seg.vmsize;
281 }
Kevin Enderby10769742014-07-01 22:26:31 +0000282 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000283 MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
284 if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
285 for (unsigned J = 0; J < Seg.nsects; ++J) {
286 MachO::section Sec = MachO->getSection(Load, J);
287 StringRef SegmentName = StringRef(Sec.segname);
288 if (SegmentName == "__TEXT")
289 total_text += Sec.size;
290 else if (SegmentName == "__DATA")
291 total_data += Sec.size;
292 else if (SegmentName == "__OBJC")
293 total_objc += Sec.size;
294 else
295 total_others += Sec.size;
Kevin Enderby10769742014-07-01 22:26:31 +0000296 }
Kevin Enderby246a4602014-06-17 17:54:13 +0000297 } else {
298 StringRef SegmentName = StringRef(Seg.segname);
299 if (SegmentName == "__TEXT")
300 total_text += Seg.vmsize;
301 else if (SegmentName == "__DATA")
302 total_data += Seg.vmsize;
303 else if (SegmentName == "__OBJC")
304 total_objc += Seg.vmsize;
305 else
306 total_others += Seg.vmsize;
307 }
308 }
Kevin Enderby246a4602014-06-17 17:54:13 +0000309 }
310 uint64_t total = total_text + total_data + total_objc + total_others;
311
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000312 if (!BerkeleyHeaderPrinted) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000313 outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000314 BerkeleyHeaderPrinted = true;
Kevin Enderby246a4602014-06-17 17:54:13 +0000315 }
316 outs() << total_text << "\t" << total_data << "\t" << total_objc << "\t"
317 << total_others << "\t" << total << "\t" << format("%" PRIx64, total)
318 << "\t";
319}
320
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000321/// Print the size of each section in @p Obj.
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000322///
323/// The format used is determined by @c OutputFormat and @c Radix.
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000324static void printObjectSectionSizes(ObjectFile *Obj) {
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000325 uint64_t total = 0;
326 std::string fmtbuf;
327 raw_string_ostream fmt(fmtbuf);
Kevin Enderby246a4602014-06-17 17:54:13 +0000328 const char *radix_fmt = getRadixFmt();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000329
Kevin Enderby246a4602014-06-17 17:54:13 +0000330 // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
331 // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
332 // let it fall through to OutputFormat berkeley.
333 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
334 if (OutputFormat == darwin && MachO)
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000335 printDarwinSectionSizes(MachO);
Kevin Enderby246a4602014-06-17 17:54:13 +0000336 // If we have a MachOObjectFile and the OutputFormat is berkeley print as
337 // darwin's default berkeley format for Mach-O files.
338 else if (MachO && OutputFormat == berkeley)
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000339 printDarwinSegmentSizes(MachO);
Kevin Enderby246a4602014-06-17 17:54:13 +0000340 else if (OutputFormat == sysv) {
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000341 // Run two passes over all sections. The first gets the lengths needed for
342 // formatting the output. The second actually does the output.
343 std::size_t max_name_len = strlen("section");
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000344 std::size_t max_size_len = strlen("size");
345 std::size_t max_addr_len = strlen("addr");
Alexey Samsonov48803e52014-03-13 14:37:36 +0000346 for (const SectionRef &Section : Obj->sections()) {
Rafael Espindolaa0ff5562016-02-09 21:39:49 +0000347 if (!considerForSize(Obj, Section))
348 continue;
Rafael Espindola80291272014-10-08 15:28:58 +0000349 uint64_t size = Section.getSize();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000350 total += size;
351
352 StringRef name;
Alexey Samsonov48803e52014-03-13 14:37:36 +0000353 if (error(Section.getName(name)))
354 return;
Rafael Espindola80291272014-10-08 15:28:58 +0000355 uint64_t addr = Section.getAddress();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000356 max_name_len = std::max(max_name_len, name.size());
Andrew Trick7dc278d2011-09-29 01:22:31 +0000357 max_size_len = std::max(max_size_len, getNumLengthAsString(size));
358 max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000359 }
360
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000361 // Add extra padding.
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000362 max_name_len += 2;
363 max_size_len += 2;
364 max_addr_len += 2;
365
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000366 // Setup header format.
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000367 fmt << "%-" << max_name_len << "s "
368 << "%" << max_size_len << "s "
369 << "%" << max_addr_len << "s\n";
370
371 // Print header
Kevin Enderby10769742014-07-01 22:26:31 +0000372 outs() << format(fmt.str().c_str(), static_cast<const char *>("section"),
373 static_cast<const char *>("size"),
374 static_cast<const char *>("addr"));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000375 fmtbuf.clear();
376
377 // Setup per section format.
378 fmt << "%-" << max_name_len << "s "
379 << "%#" << max_size_len << radix_fmt << " "
380 << "%#" << max_addr_len << radix_fmt << "\n";
381
382 // Print each section.
Alexey Samsonov48803e52014-03-13 14:37:36 +0000383 for (const SectionRef &Section : Obj->sections()) {
Rafael Espindolaa0ff5562016-02-09 21:39:49 +0000384 if (!considerForSize(Obj, Section))
385 continue;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000386 StringRef name;
Alexey Samsonov48803e52014-03-13 14:37:36 +0000387 if (error(Section.getName(name)))
388 return;
Rafael Espindola80291272014-10-08 15:28:58 +0000389 uint64_t size = Section.getSize();
390 uint64_t addr = Section.getAddress();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000391 std::string namestr = name;
392
Alexey Samsonov48803e52014-03-13 14:37:36 +0000393 outs() << format(fmt.str().c_str(), namestr.c_str(), size, addr);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000394 }
395
Hemant Kulkarni274457e2016-03-28 16:48:10 +0000396 if (ELFCommons) {
397 uint64_t CommonSize = getCommonSize(Obj);
398 total += CommonSize;
399 outs() << format(fmt.str().c_str(), std::string("*COM*").c_str(),
400 CommonSize, static_cast<uint64_t>(0));
401 }
402
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000403 // Print total.
404 fmtbuf.clear();
405 fmt << "%-" << max_name_len << "s "
406 << "%#" << max_size_len << radix_fmt << "\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000407 outs() << format(fmt.str().c_str(), static_cast<const char *>("Total"),
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000408 total);
409 } else {
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000410 // The Berkeley format does not display individual section sizes. It
411 // displays the cumulative size for each section type.
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000412 uint64_t total_text = 0;
413 uint64_t total_data = 0;
414 uint64_t total_bss = 0;
415
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000416 // Make one pass over the section table to calculate sizes.
Alexey Samsonov48803e52014-03-13 14:37:36 +0000417 for (const SectionRef &Section : Obj->sections()) {
Rafael Espindola80291272014-10-08 15:28:58 +0000418 uint64_t size = Section.getSize();
419 bool isText = Section.isText();
420 bool isData = Section.isData();
421 bool isBSS = Section.isBSS();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000422 if (isText)
423 total_text += size;
424 else if (isData)
425 total_data += size;
426 else if (isBSS)
427 total_bss += size;
428 }
429
Hemant Kulkarni274457e2016-03-28 16:48:10 +0000430 if (ELFCommons)
431 total_bss += getCommonSize(Obj);
432
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000433 total = total_text + total_data + total_bss;
434
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000435 if (!BerkeleyHeaderPrinted) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000436 outs() << " text data bss "
Kevin Enderby10769742014-07-01 22:26:31 +0000437 << (Radix == octal ? "oct" : "dec") << " hex filename\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000438 BerkeleyHeaderPrinted = true;
Kevin Enderby246a4602014-06-17 17:54:13 +0000439 }
440
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000441 // Print result.
442 fmt << "%#7" << radix_fmt << " "
443 << "%#7" << radix_fmt << " "
444 << "%#7" << radix_fmt << " ";
Kevin Enderby10769742014-07-01 22:26:31 +0000445 outs() << format(fmt.str().c_str(), total_text, total_data, total_bss);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000446 fmtbuf.clear();
Benjamin Kramerf3da5292011-11-05 08:57:40 +0000447 fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << " "
448 << "%7" PRIx64 " ";
Kevin Enderby10769742014-07-01 22:26:31 +0000449 outs() << format(fmt.str().c_str(), total, total);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000450 }
451}
452
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000453/// Checks to see if the @p o ObjectFile is a Mach-O file and if it is and there
454/// is a list of architecture flags specified then check to make sure this
455/// Mach-O file is one of those architectures or all architectures was
456/// specificed. If not then an error is generated and this routine returns
457/// false. Else it returns true.
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000458static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) {
459 if (isa<MachOObjectFile>(o) && !ArchAll && ArchFlags.size() != 0) {
460 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
461 bool ArchFound = false;
462 MachO::mach_header H;
463 MachO::mach_header_64 H_64;
464 Triple T;
465 if (MachO->is64Bit()) {
466 H_64 = MachO->MachOObjectFile::getHeader64();
Tim Northover9e8eb412016-04-22 23:21:13 +0000467 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000468 } else {
469 H = MachO->MachOObjectFile::getHeader();
Tim Northover9e8eb412016-04-22 23:21:13 +0000470 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000471 }
472 unsigned i;
Kevin Enderby10769742014-07-01 22:26:31 +0000473 for (i = 0; i < ArchFlags.size(); ++i) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000474 if (ArchFlags[i] == T.getArchName())
475 ArchFound = true;
476 break;
477 }
478 if (!ArchFound) {
479 errs() << ToolName << ": file: " << file
480 << " does not contain architecture: " << ArchFlags[i] << ".\n";
481 return false;
482 }
483 }
484 return true;
485}
486
Rafael Espindola49a0e5e2016-02-09 21:32:56 +0000487/// Print the section sizes for @p file. If @p file is an archive, print the
488/// section sizes for each archive member.
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000489static void printFileSectionSizes(StringRef file) {
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000490
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000491 // Attempt to open the binary.
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000492 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
493 if (!BinaryOrErr) {
494 error(errorToErrorCode(BinaryOrErr.takeError()));
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000495 return;
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000496 }
Rafael Espindola48af1c22014-08-19 18:44:46 +0000497 Binary &Bin = *BinaryOrErr.get().getBinary();
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000498
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000499 if (Archive *a = dyn_cast<Archive>(&Bin)) {
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000500 // This is an archive. Iterate over each member and display its sizes.
Rafael Espindola23a97502014-01-21 16:09:45 +0000501 for (object::Archive::child_iterator i = a->child_begin(),
Kevin Enderby10769742014-07-01 22:26:31 +0000502 e = a->child_end();
503 i != e; ++i) {
Davide Italianoff11b902016-02-13 01:38:16 +0000504 if (error(i->getError()))
Kevin Enderby7a969422015-11-05 19:24:56 +0000505 exit(1);
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000506 Expected<std::unique_ptr<Binary>> ChildOrErr = i->get().getAsBinary();
507 if (!ChildOrErr) {
508 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
509 error(std::move(E), a->getFileName(), i->get());
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000510 continue;
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000511 }
Rafael Espindolaae460022014-06-16 16:08:36 +0000512 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
Kevin Enderby246a4602014-06-17 17:54:13 +0000513 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000514 if (!checkMachOAndArchFlags(o, file))
515 return;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000516 if (OutputFormat == sysv)
Kevin Enderby10769742014-07-01 22:26:31 +0000517 outs() << o->getFileName() << " (ex " << a->getFileName() << "):\n";
518 else if (MachO && OutputFormat == darwin)
519 outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000520 printObjectSectionSizes(o);
Kevin Enderby246a4602014-06-17 17:54:13 +0000521 if (OutputFormat == berkeley) {
522 if (MachO)
523 outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
524 else
525 outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
526 }
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000527 }
528 }
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000529 } else if (MachOUniversalBinary *UB =
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000530 dyn_cast<MachOUniversalBinary>(&Bin)) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000531 // If we have a list of architecture flags specified dump only those.
532 if (!ArchAll && ArchFlags.size() != 0) {
533 // Look for a slice in the universal binary that matches each ArchFlag.
534 bool ArchFound;
Kevin Enderby10769742014-07-01 22:26:31 +0000535 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000536 ArchFound = false;
537 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
538 E = UB->end_objects();
539 I != E; ++I) {
Kevin Enderby10769742014-07-01 22:26:31 +0000540 if (ArchFlags[i] == I->getArchTypeName()) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000541 ArchFound = true;
542 ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000543 if (UO) {
544 if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
545 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
546 if (OutputFormat == sysv)
547 outs() << o->getFileName() << " :\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000548 else if (MachO && OutputFormat == darwin) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000549 if (MoreThanOneFile || ArchFlags.size() > 1)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000550 outs() << o->getFileName() << " (for architecture "
551 << I->getArchTypeName() << "): \n";
552 }
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000553 printObjectSectionSizes(o);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000554 if (OutputFormat == berkeley) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000555 if (!MachO || MoreThanOneFile || ArchFlags.size() > 1)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000556 outs() << o->getFileName() << " (for architecture "
557 << I->getArchTypeName() << ")";
558 outs() << "\n";
559 }
560 }
Rafael Espindola0bfe8282014-12-09 21:05:36 +0000561 } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
562 I->getAsArchive()) {
563 std::unique_ptr<Archive> &UA = *AOrErr;
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000564 // This is an archive. Iterate over each member and display its
Kevin Enderby10769742014-07-01 22:26:31 +0000565 // sizes.
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000566 for (object::Archive::child_iterator i = UA->child_begin(),
567 e = UA->child_end();
Kevin Enderby10769742014-07-01 22:26:31 +0000568 i != e; ++i) {
Davide Italianoff11b902016-02-13 01:38:16 +0000569 if (error(i->getError()))
Kevin Enderby7a969422015-11-05 19:24:56 +0000570 exit(1);
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000571 Expected<std::unique_ptr<Binary>> ChildOrErr =
572 i->get().getAsBinary();
573 if (!ChildOrErr) {
574 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
575 error(std::move(E), a->getFileName(), i->get());
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000576 continue;
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000577 }
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000578 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
579 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
580 if (OutputFormat == sysv)
581 outs() << o->getFileName() << " (ex " << UA->getFileName()
582 << "):\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000583 else if (MachO && OutputFormat == darwin)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000584 outs() << UA->getFileName() << "(" << o->getFileName()
Kevin Enderby10769742014-07-01 22:26:31 +0000585 << ")"
586 << " (for architecture " << I->getArchTypeName()
587 << "):\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000588 printObjectSectionSizes(o);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000589 if (OutputFormat == berkeley) {
590 if (MachO) {
591 outs() << UA->getFileName() << "(" << o->getFileName()
592 << ")";
593 if (ArchFlags.size() > 1)
Kevin Enderby10769742014-07-01 22:26:31 +0000594 outs() << " (for architecture " << I->getArchTypeName()
595 << ")";
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000596 outs() << "\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000597 } else
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000598 outs() << o->getFileName() << " (ex " << UA->getFileName()
599 << ")\n";
600 }
601 }
602 }
603 }
604 }
605 }
606 if (!ArchFound) {
607 errs() << ToolName << ": file: " << file
608 << " does not contain architecture" << ArchFlags[i] << ".\n";
609 return;
610 }
611 }
612 return;
613 }
614 // No architecture flags were specified so if this contains a slice that
615 // matches the host architecture dump only that.
616 if (!ArchAll) {
Kevin Enderby10769742014-07-01 22:26:31 +0000617 StringRef HostArchName = MachOObjectFile::getHostArch().getArchName();
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000618 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
619 E = UB->end_objects();
620 I != E; ++I) {
Kevin Enderby10769742014-07-01 22:26:31 +0000621 if (HostArchName == I->getArchTypeName()) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000622 ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000623 if (UO) {
624 if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
625 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
626 if (OutputFormat == sysv)
627 outs() << o->getFileName() << " :\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000628 else if (MachO && OutputFormat == darwin) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000629 if (MoreThanOneFile)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000630 outs() << o->getFileName() << " (for architecture "
631 << I->getArchTypeName() << "):\n";
632 }
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000633 printObjectSectionSizes(o);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000634 if (OutputFormat == berkeley) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000635 if (!MachO || MoreThanOneFile)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000636 outs() << o->getFileName() << " (for architecture "
637 << I->getArchTypeName() << ")";
638 outs() << "\n";
639 }
640 }
Rafael Espindola0bfe8282014-12-09 21:05:36 +0000641 } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
642 I->getAsArchive()) {
643 std::unique_ptr<Archive> &UA = *AOrErr;
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000644 // This is an archive. Iterate over each member and display its
645 // sizes.
646 for (object::Archive::child_iterator i = UA->child_begin(),
647 e = UA->child_end();
Kevin Enderby10769742014-07-01 22:26:31 +0000648 i != e; ++i) {
Davide Italianoff11b902016-02-13 01:38:16 +0000649 if (error(i->getError()))
Kevin Enderby7a969422015-11-05 19:24:56 +0000650 exit(1);
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000651 Expected<std::unique_ptr<Binary>> ChildOrErr =
652 i->get().getAsBinary();
653 if (!ChildOrErr) {
654 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
655 error(std::move(E), a->getFileName(), i->get());
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000656 continue;
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000657 }
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000658 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
659 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
660 if (OutputFormat == sysv)
661 outs() << o->getFileName() << " (ex " << UA->getFileName()
662 << "):\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000663 else if (MachO && OutputFormat == darwin)
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000664 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
665 << " (for architecture " << I->getArchTypeName()
666 << "):\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000667 printObjectSectionSizes(o);
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000668 if (OutputFormat == berkeley) {
669 if (MachO)
670 outs() << UA->getFileName() << "(" << o->getFileName()
671 << ")\n";
672 else
673 outs() << o->getFileName() << " (ex " << UA->getFileName()
674 << ")\n";
675 }
676 }
677 }
678 }
679 return;
680 }
681 }
682 }
683 // Either all architectures have been specified or none have been specified
684 // and this does not contain the host architecture so dump all the slices.
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000685 bool MoreThanOneArch = UB->getNumberOfObjects() > 1;
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000686 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
687 E = UB->end_objects();
688 I != E; ++I) {
Rafael Espindola4f7932b2014-06-23 20:41:02 +0000689 ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
Rafael Espindola4f7932b2014-06-23 20:41:02 +0000690 if (UO) {
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000691 if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
Kevin Enderby1983fcf2014-06-19 22:03:18 +0000692 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000693 if (OutputFormat == sysv)
694 outs() << o->getFileName() << " :\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000695 else if (MachO && OutputFormat == darwin) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000696 if (MoreThanOneFile || MoreThanOneArch)
Kevin Enderby1983fcf2014-06-19 22:03:18 +0000697 outs() << o->getFileName() << " (for architecture "
698 << I->getArchTypeName() << "):";
699 outs() << "\n";
700 }
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000701 printObjectSectionSizes(o);
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000702 if (OutputFormat == berkeley) {
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000703 if (!MachO || MoreThanOneFile || MoreThanOneArch)
Kevin Enderby1983fcf2014-06-19 22:03:18 +0000704 outs() << o->getFileName() << " (for architecture "
705 << I->getArchTypeName() << ")";
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000706 outs() << "\n";
707 }
708 }
Rafael Espindola0bfe8282014-12-09 21:05:36 +0000709 } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
710 I->getAsArchive()) {
711 std::unique_ptr<Archive> &UA = *AOrErr;
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000712 // This is an archive. Iterate over each member and display its sizes.
713 for (object::Archive::child_iterator i = UA->child_begin(),
Kevin Enderby10769742014-07-01 22:26:31 +0000714 e = UA->child_end();
715 i != e; ++i) {
Davide Italianoff11b902016-02-13 01:38:16 +0000716 if (error(i->getError()))
Kevin Enderby7a969422015-11-05 19:24:56 +0000717 exit(1);
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000718 Expected<std::unique_ptr<Binary>> ChildOrErr = i->get().getAsBinary();
719 if (!ChildOrErr) {
720 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
721 error(std::move(E), UA->getFileName(), i->get());
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000722 continue;
Kevin Enderbyac9e1552016-05-17 17:10:12 +0000723 }
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000724 if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
725 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
726 if (OutputFormat == sysv)
727 outs() << o->getFileName() << " (ex " << UA->getFileName()
728 << "):\n";
Kevin Enderby10769742014-07-01 22:26:31 +0000729 else if (MachO && OutputFormat == darwin)
Kevin Enderby1983fcf2014-06-19 22:03:18 +0000730 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
Kevin Enderby10769742014-07-01 22:26:31 +0000731 << " (for architecture " << I->getArchTypeName() << "):\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000732 printObjectSectionSizes(o);
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000733 if (OutputFormat == berkeley) {
734 if (MachO)
Kevin Enderby1983fcf2014-06-19 22:03:18 +0000735 outs() << UA->getFileName() << "(" << o->getFileName() << ")"
736 << " (for architecture " << I->getArchTypeName()
737 << ")\n";
Kevin Enderby4b8fc282014-06-18 22:04:40 +0000738 else
739 outs() << o->getFileName() << " (ex " << UA->getFileName()
740 << ")\n";
741 }
742 }
743 }
744 }
745 }
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000746 } else if (ObjectFile *o = dyn_cast<ObjectFile>(&Bin)) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000747 if (!checkMachOAndArchFlags(o, file))
748 return;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000749 if (OutputFormat == sysv)
750 outs() << o->getFileName() << " :\n";
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000751 printObjectSectionSizes(o);
Kevin Enderby246a4602014-06-17 17:54:13 +0000752 if (OutputFormat == berkeley) {
753 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000754 if (!MachO || MoreThanOneFile)
Kevin Enderby246a4602014-06-17 17:54:13 +0000755 outs() << o->getFileName();
756 outs() << "\n";
757 }
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000758 } else {
Kevin Enderby10769742014-07-01 22:26:31 +0000759 errs() << ToolName << ": " << file << ": "
760 << "Unrecognized file type.\n";
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000761 }
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000762 // System V adds an extra newline at the end of each file.
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000763 if (OutputFormat == sysv)
764 outs() << "\n";
765}
766
767int main(int argc, char **argv) {
768 // Print a stack trace if we signal out.
769 sys::PrintStackTraceOnErrorSignal();
770 PrettyStackTraceProgram X(argc, argv);
771
Kevin Enderby10769742014-07-01 22:26:31 +0000772 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000773 cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n");
774
775 ToolName = argv[0];
776 if (OutputFormatShort.getNumOccurrences())
Chris Bienemane71fb5c2015-01-22 01:49:59 +0000777 OutputFormat = static_cast<OutputFormatTy>(OutputFormatShort);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000778 if (RadixShort.getNumOccurrences())
Michael J. Spencercc5f8d42011-09-29 00:59:18 +0000779 Radix = RadixShort;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000780
Kevin Enderby10769742014-07-01 22:26:31 +0000781 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000782 if (ArchFlags[i] == "all") {
783 ArchAll = true;
Kevin Enderby10769742014-07-01 22:26:31 +0000784 } else {
Rafael Espindola72318b42014-08-08 16:30:17 +0000785 if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
Kevin Enderbyafef4c92014-07-01 17:19:10 +0000786 outs() << ToolName << ": for the -arch option: Unknown architecture "
787 << "named '" << ArchFlags[i] << "'";
788 return 1;
789 }
790 }
791 }
792
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000793 if (InputFilenames.size() == 0)
794 InputFilenames.push_back("a.out");
795
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000796 MoreThanOneFile = InputFilenames.size() > 1;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000797 std::for_each(InputFilenames.begin(), InputFilenames.end(),
Rafael Espindola1dc30a42016-02-09 21:35:14 +0000798 printFileSectionSizes);
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000799
Kevin Enderby64f7a992016-05-02 21:41:03 +0000800 if (HadError)
801 return 1;
Michael J. Spencerc4ad4662011-09-28 20:57:46 +0000802}