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