132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer//===-- llvm-size.cpp - Print the size of each object section -------------===//
232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer//
332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer//                     The LLVM Compiler Infrastructure
432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer//
532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer// This file is distributed under the University of Illinois Open Source
632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer// License. See LICENSE.TXT for details.
732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer//
832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer//===----------------------------------------------------------------------===//
932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer//
1032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer// This program is a utility that works like traditional Unix "size",
1132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer// that is, it prints out the size of each section, and the total size of all
1232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer// sections.
1332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer//
1432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer//===----------------------------------------------------------------------===//
1532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
1632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/ADT/APInt.h"
1732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/Object/Archive.h"
1832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/Object/ObjectFile.h"
19cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Object/MachO.h"
20cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Object/MachOUniversal.h"
2132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/Support/Casting.h"
2232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/Support/CommandLine.h"
2332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/Support/FileSystem.h"
2432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/Support/Format.h"
2532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/Support/ManagedStatic.h"
2632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/Support/MemoryBuffer.h"
2732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/Support/PrettyStackTrace.h"
2832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include "llvm/Support/Signals.h"
29f010c464a11444733ec67e31aace8bcebeaf2588Chandler Carruth#include "llvm/Support/raw_ostream.h"
3032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include <algorithm>
3132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer#include <string>
32cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include <system_error>
3332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencerusing namespace llvm;
3432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencerusing namespace object;
3532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
36cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesenum OutputFormatTy { berkeley, sysv, darwin };
3775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencerstatic cl::opt<OutputFormatTy>
38cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesOutputFormat("format", cl::desc("Specify output format"),
39cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines             cl::values(clEnumVal(sysv, "System V format"),
40cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                        clEnumVal(berkeley, "Berkeley format"),
41cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                        clEnumVal(darwin, "Darwin -m format"), clEnumValEnd),
42cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines             cl::init(berkeley));
43cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
44cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic cl::opt<OutputFormatTy> OutputFormatShort(
45cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    cl::desc("Specify output format"),
46cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    cl::values(clEnumValN(sysv, "A", "System V format"),
47cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               clEnumValN(berkeley, "B", "Berkeley format"),
48cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               clEnumValN(darwin, "m", "Darwin -m format"), clEnumValEnd),
49cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    cl::init(berkeley));
50cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
51cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic bool berkeleyHeaderPrinted = false;
52cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic bool moreThanOneFile = false;
53cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
54cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinescl::opt<bool>
55cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesDarwinLongFormat("l", cl::desc("When format is darwin, use long format "
56cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                               "to include addresses and offsets."));
5775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer
58cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic cl::list<std::string>
59cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
60cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          cl::ZeroOrMore);
61cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool ArchAll = false;
6275c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer
63cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesenum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 };
6475c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencerstatic cl::opt<unsigned int>
65cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesRadix("-radix", cl::desc("Print size in radix. Only 8, 10, and 16 are valid"),
66cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      cl::init(decimal));
6775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer
6875c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencerstatic cl::opt<RadixTy>
69cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesRadixShort(cl::desc("Print size in radix:"),
70cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines           cl::values(clEnumValN(octal, "o", "Print size in octal"),
71cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                      clEnumValN(decimal, "d", "Print size in decimal"),
72cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                      clEnumValN(hexadecimal, "x", "Print size in hexadecimal"),
73cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                      clEnumValEnd),
74cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines           cl::init(decimal));
7575c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer
7675c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencerstatic cl::list<std::string>
77cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesInputFilenames(cl::Positional, cl::desc("<input files>"), cl::ZeroOrMore);
7875c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer
7975c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencerstatic std::string ToolName;
8075c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer
8175c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer///  @brief If ec is not success, print the error and return true.
82cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic bool error(std::error_code ec) {
83cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (!ec)
84cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return false;
8532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
8632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  outs() << ToolName << ": error reading file: " << ec.message() << ".\n";
8732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  outs().flush();
8832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  return true;
8932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer}
9032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
9175c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer/// @brief Get the length of the string that represents @p num in Radix
9275c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer///        including the leading 0x or 0 for hexadecimal and octal respectively.
93f47e870015439b1b47562533689a9dec17879befAndrew Trickstatic size_t getNumLengthAsString(uint64_t num) {
9432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  APInt conv(64, num);
9532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  SmallString<32> result;
9675c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer  conv.toString(result, Radix, false, true);
9732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  return result.size();
9832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer}
9932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
100cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines/// @brief Return the the printing format for the Radix.
101cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic const char *getRadixFmt(void) {
102cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  switch (Radix) {
103cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  case octal:
104cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return PRIo64;
105cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  case decimal:
106cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return PRIu64;
107cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  case hexadecimal:
108cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return PRIx64;
109cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
110cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return nullptr;
111cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
112cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
113cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines/// @brief Print the size of each Mach-O segment and section in @p MachO.
114cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines///
115cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines/// This is when used when @c OutputFormat is darwin and produces the same
116cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines/// output as darwin's size(1) -m output.
117cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic void PrintDarwinSectionSizes(MachOObjectFile *MachO) {
118cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  std::string fmtbuf;
119cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  raw_string_ostream fmt(fmtbuf);
120cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  const char *radix_fmt = getRadixFmt();
121cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (Radix == hexadecimal)
122cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    fmt << "0x";
123cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  fmt << "%" << radix_fmt;
124cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
125cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint32_t LoadCommandCount = MachO->getHeader().ncmds;
126cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint32_t Filetype = MachO->getHeader().filetype;
127cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
128cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
129cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t total = 0;
130cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (unsigned I = 0;; ++I) {
131cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
132cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
133cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      outs() << "Segment " << Seg.segname << ": "
134cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines             << format(fmt.str().c_str(), Seg.vmsize);
135cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (DarwinLongFormat)
136cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr) << " fileoff "
137cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               << Seg.fileoff << ")";
138cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      outs() << "\n";
139cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      total += Seg.vmsize;
140cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      uint64_t sec_total = 0;
141cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      for (unsigned J = 0; J < Seg.nsects; ++J) {
142cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        MachO::section_64 Sec = MachO->getSection64(Load, J);
143cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (Filetype == MachO::MH_OBJECT)
144cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
145cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                 << format("%.16s", &Sec.sectname) << "): ";
146cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        else
147cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
148cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        outs() << format(fmt.str().c_str(), Sec.size);
149cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (DarwinLongFormat)
150cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          outs() << " (addr 0x" << format("%" PRIx64, Sec.addr) << " offset "
151cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                 << Sec.offset << ")";
152cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        outs() << "\n";
153cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        sec_total += Sec.size;
154cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      }
155cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (Seg.nsects != 0)
156cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
157cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
158cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
159cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      outs() << "Segment " << Seg.segname << ": "
160cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines             << format(fmt.str().c_str(), Seg.vmsize);
161cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (DarwinLongFormat)
162cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr) << " fileoff "
163cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               << Seg.fileoff << ")";
164cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      outs() << "\n";
165cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      total += Seg.vmsize;
166cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      uint64_t sec_total = 0;
167cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      for (unsigned J = 0; J < Seg.nsects; ++J) {
168cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        MachO::section Sec = MachO->getSection(Load, J);
169cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (Filetype == MachO::MH_OBJECT)
170cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
171cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                 << format("%.16s", &Sec.sectname) << "): ";
172cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        else
173cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
174cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        outs() << format(fmt.str().c_str(), Sec.size);
175cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (DarwinLongFormat)
176cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          outs() << " (addr 0x" << format("%" PRIx64, Sec.addr) << " offset "
177cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                 << Sec.offset << ")";
178cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        outs() << "\n";
179cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        sec_total += Sec.size;
180cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      }
181cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (Seg.nsects != 0)
182cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
183cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
184cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (I == LoadCommandCount - 1)
185cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      break;
186cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    else
187cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      Load = MachO->getNextLoadCommandInfo(Load);
188cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
189cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  outs() << "total " << format(fmt.str().c_str(), total) << "\n";
190cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
191cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
192cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines/// @brief Print the summary sizes of the standard Mach-O segments in @p MachO.
193cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines///
194cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines/// This is when used when @c OutputFormat is berkeley with a Mach-O file and
195cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines/// produces the same output as darwin's size(1) default output.
196cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic void PrintDarwinSegmentSizes(MachOObjectFile *MachO) {
197cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint32_t LoadCommandCount = MachO->getHeader().ncmds;
198cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
199cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
200cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t total_text = 0;
201cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t total_data = 0;
202cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t total_objc = 0;
203cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t total_others = 0;
204cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (unsigned I = 0;; ++I) {
205cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
206cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
207cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
208cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        for (unsigned J = 0; J < Seg.nsects; ++J) {
209cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          MachO::section_64 Sec = MachO->getSection64(Load, J);
210cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          StringRef SegmentName = StringRef(Sec.segname);
211cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          if (SegmentName == "__TEXT")
212cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            total_text += Sec.size;
213cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          else if (SegmentName == "__DATA")
214cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            total_data += Sec.size;
215cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          else if (SegmentName == "__OBJC")
216cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            total_objc += Sec.size;
217cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          else
218cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            total_others += Sec.size;
219cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
220cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      } else {
221cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        StringRef SegmentName = StringRef(Seg.segname);
222cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (SegmentName == "__TEXT")
223cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          total_text += Seg.vmsize;
224cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        else if (SegmentName == "__DATA")
225cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          total_data += Seg.vmsize;
226cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        else if (SegmentName == "__OBJC")
227cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          total_objc += Seg.vmsize;
228cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        else
229cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          total_others += Seg.vmsize;
230cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      }
231cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
232cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
233cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
234cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        for (unsigned J = 0; J < Seg.nsects; ++J) {
235cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          MachO::section Sec = MachO->getSection(Load, J);
236cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          StringRef SegmentName = StringRef(Sec.segname);
237cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          if (SegmentName == "__TEXT")
238cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            total_text += Sec.size;
239cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          else if (SegmentName == "__DATA")
240cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            total_data += Sec.size;
241cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          else if (SegmentName == "__OBJC")
242cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            total_objc += Sec.size;
243cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          else
244cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            total_others += Sec.size;
245cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
246cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      } else {
247cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        StringRef SegmentName = StringRef(Seg.segname);
248cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (SegmentName == "__TEXT")
249cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          total_text += Seg.vmsize;
250cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        else if (SegmentName == "__DATA")
251cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          total_data += Seg.vmsize;
252cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        else if (SegmentName == "__OBJC")
253cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          total_objc += Seg.vmsize;
254cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        else
255cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          total_others += Seg.vmsize;
256cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      }
257cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
258cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (I == LoadCommandCount - 1)
259cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      break;
260cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    else
261cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      Load = MachO->getNextLoadCommandInfo(Load);
262cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
263cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t total = total_text + total_data + total_objc + total_others;
264cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
265cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (!berkeleyHeaderPrinted) {
266cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
267cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    berkeleyHeaderPrinted = true;
268cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
269cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  outs() << total_text << "\t" << total_data << "\t" << total_objc << "\t"
270cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines         << total_others << "\t" << total << "\t" << format("%" PRIx64, total)
271cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines         << "\t";
272cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
273cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
27436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// @brief Print the size of each section in @p Obj.
27575c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer///
27675c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer/// The format used is determined by @c OutputFormat and @c Radix.
27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void PrintObjectSectionSizes(ObjectFile *Obj) {
27832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  uint64_t total = 0;
27932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  std::string fmtbuf;
28032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  raw_string_ostream fmt(fmtbuf);
281cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  const char *radix_fmt = getRadixFmt();
282cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
283cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
284cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
285cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  // let it fall through to OutputFormat berkeley.
286cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
287cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (OutputFormat == darwin && MachO)
288cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    PrintDarwinSectionSizes(MachO);
289cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  // If we have a MachOObjectFile and the OutputFormat is berkeley print as
290cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  // darwin's default berkeley format for Mach-O files.
291cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  else if (MachO && OutputFormat == berkeley)
292cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    PrintDarwinSegmentSizes(MachO);
293cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  else if (OutputFormat == sysv) {
29432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Run two passes over all sections. The first gets the lengths needed for
29532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // formatting the output. The second actually does the output.
29632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    std::size_t max_name_len = strlen("section");
29775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    std::size_t max_size_len = strlen("size");
29875c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    std::size_t max_addr_len = strlen("addr");
29936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (const SectionRef &Section : Obj->sections()) {
30032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      uint64_t size = 0;
30136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.getSize(size)))
30232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        return;
30332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      total += size;
30432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
30532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      StringRef name;
30632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      uint64_t addr = 0;
30736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.getName(name)))
30836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
30936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.getAddress(addr)))
31036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
31132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      max_name_len = std::max(max_name_len, name.size());
312f47e870015439b1b47562533689a9dec17879befAndrew Trick      max_size_len = std::max(max_size_len, getNumLengthAsString(size));
313f47e870015439b1b47562533689a9dec17879befAndrew Trick      max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr));
31432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    }
31532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
31675c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // Add extra padding.
31732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    max_name_len += 2;
31832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    max_size_len += 2;
31932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    max_addr_len += 2;
32032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
32175c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // Setup header format.
32232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmt << "%-" << max_name_len << "s "
32332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%" << max_size_len << "s "
32432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%" << max_addr_len << "s\n";
32532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
32632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Print header
327cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    outs() << format(fmt.str().c_str(), static_cast<const char *>("section"),
328cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                     static_cast<const char *>("size"),
329cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                     static_cast<const char *>("addr"));
33032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmtbuf.clear();
33132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
33232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Setup per section format.
33332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmt << "%-" << max_name_len << "s "
33432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%#" << max_size_len << radix_fmt << " "
33532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%#" << max_addr_len << radix_fmt << "\n";
33632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
33732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Print each section.
33836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (const SectionRef &Section : Obj->sections()) {
33932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      StringRef name;
34032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      uint64_t size = 0;
34132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      uint64_t addr = 0;
34236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.getName(name)))
34336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
34436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.getSize(size)))
34536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
34636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.getAddress(addr)))
34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
34832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      std::string namestr = name;
34932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
35036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      outs() << format(fmt.str().c_str(), namestr.c_str(), size, addr);
35132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    }
35232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
35332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Print total.
35432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmtbuf.clear();
35532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmt << "%-" << max_name_len << "s "
35632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%#" << max_size_len << radix_fmt << "\n";
357cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    outs() << format(fmt.str().c_str(), static_cast<const char *>("Total"),
35832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer                     total);
35932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  } else {
36075c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // The Berkeley format does not display individual section sizes. It
36175c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // displays the cumulative size for each section type.
36232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    uint64_t total_text = 0;
36332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    uint64_t total_data = 0;
36432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    uint64_t total_bss = 0;
36532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
36675c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // Make one pass over the section table to calculate sizes.
36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (const SectionRef &Section : Obj->sections()) {
36832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      uint64_t size = 0;
36932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      bool isText = false;
37032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      bool isData = false;
37132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      bool isBSS = false;
37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.getSize(size)))
37336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
37436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.isText(isText)))
37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
37636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.isData(isData)))
37736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
37836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.isBSS(isBSS)))
37936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
38032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      if (isText)
38132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        total_text += size;
38232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      else if (isData)
38332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        total_data += size;
38432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      else if (isBSS)
38532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        total_bss += size;
38632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    }
38732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
38832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    total = total_text + total_data + total_bss;
38932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
390cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (!berkeleyHeaderPrinted) {
391cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      outs() << "   text    data     bss     "
392cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines             << (Radix == octal ? "oct" : "dec") << "     hex filename\n";
393cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      berkeleyHeaderPrinted = true;
394cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
395cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
39632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Print result.
39732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmt << "%#7" << radix_fmt << " "
39832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%#7" << radix_fmt << " "
39932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%#7" << radix_fmt << " ";
400cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    outs() << format(fmt.str().c_str(), total_text, total_data, total_bss);
40132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmtbuf.clear();
40241a964931a0e0943ceef28b0c691843bf8ca87b7Benjamin Kramer    fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << " "
40341a964931a0e0943ceef28b0c691843bf8ca87b7Benjamin Kramer        << "%7" PRIx64 " ";
404cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    outs() << format(fmt.str().c_str(), total, total);
405cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
406cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
407cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
408cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines/// @brief Checks to see if the @p o ObjectFile is a Mach-O file and if it is
409cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines///        and there is a list of architecture flags specified then check to
410cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines///        make sure this Mach-O file is one of those architectures or all
411cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines///        architectures was specificed.  If not then an error is generated and
412cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines///        this routine returns false.  Else it returns true.
413cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) {
414cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (isa<MachOObjectFile>(o) && !ArchAll && ArchFlags.size() != 0) {
415cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
416cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    bool ArchFound = false;
417cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    MachO::mach_header H;
418cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    MachO::mach_header_64 H_64;
419cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    Triple T;
420cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (MachO->is64Bit()) {
421cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      H_64 = MachO->MachOObjectFile::getHeader64();
422cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype);
423cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    } else {
424cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      H = MachO->MachOObjectFile::getHeader();
425cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      T = MachOObjectFile::getArch(H.cputype, H.cpusubtype);
426cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
427cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    unsigned i;
428cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    for (i = 0; i < ArchFlags.size(); ++i) {
429cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (ArchFlags[i] == T.getArchName())
430cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        ArchFound = true;
431cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      break;
432cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
433cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (!ArchFound) {
434cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      errs() << ToolName << ": file: " << file
435cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines             << " does not contain architecture: " << ArchFlags[i] << ".\n";
436cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return false;
437cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
43832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  }
439cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return true;
44032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer}
44132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
44275c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer/// @brief Print the section sizes for @p file. If @p file is an archive, print
44375c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer///        the section sizes for each archive member.
44432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencerstatic void PrintFileSectionSizes(StringRef file) {
44532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  // If file is not stdin, check that it exists.
44632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (file != "-") {
44732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    bool exists;
44832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    if (sys::fs::exists(file, exists) || !exists) {
449cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      errs() << ToolName << ": '" << file << "': "
450cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines             << "No such file\n";
45132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      return;
45232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    }
45332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  }
45432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
45575c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer  // Attempt to open the binary.
45636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  ErrorOr<Binary *> BinaryOrErr = createBinary(file);
457cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (std::error_code EC = BinaryOrErr.getError()) {
45836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
45932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    return;
46032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  }
46136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<Binary> binary(BinaryOrErr.get());
46232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
46332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (Archive *a = dyn_cast<Archive>(binary.get())) {
46475c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // This is an archive. Iterate over each member and display its sizes.
46536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (object::Archive::child_iterator i = a->child_begin(),
466cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                         e = a->child_end();
467cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines         i != e; ++i) {
468cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
469cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (std::error_code EC = ChildOrErr.getError()) {
470cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
47132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        continue;
47232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      }
473cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
474cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
475cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (!checkMachOAndArchFlags(o, file))
476cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          return;
47732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        if (OutputFormat == sysv)
478cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          outs() << o->getFileName() << "   (ex " << a->getFileName() << "):\n";
479cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        else if (MachO && OutputFormat == darwin)
480cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
48132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        PrintObjectSectionSizes(o);
482cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (OutputFormat == berkeley) {
483cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          if (MachO)
484cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
485cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          else
486cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
487cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
488cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      }
489cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
490cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  } else if (MachOUniversalBinary *UB =
491cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                 dyn_cast<MachOUniversalBinary>(binary.get())) {
492cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    // If we have a list of architecture flags specified dump only those.
493cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (!ArchAll && ArchFlags.size() != 0) {
494cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      // Look for a slice in the universal binary that matches each ArchFlag.
495cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      bool ArchFound;
496cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      for (unsigned i = 0; i < ArchFlags.size(); ++i) {
497cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        ArchFound = false;
498cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
499cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                   E = UB->end_objects();
500cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines             I != E; ++I) {
501cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          if (ArchFlags[i] == I->getArchTypeName()) {
502cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            ArchFound = true;
503cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
504cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            std::unique_ptr<Archive> UA;
505cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (UO) {
506cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
507cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
508cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                if (OutputFormat == sysv)
509cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  outs() << o->getFileName() << "  :\n";
510cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                else if (MachO && OutputFormat == darwin) {
511cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  if (moreThanOneFile || ArchFlags.size() > 1)
512cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    outs() << o->getFileName() << " (for architecture "
513cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           << I->getArchTypeName() << "): \n";
514cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                }
515cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                PrintObjectSectionSizes(o);
516cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                if (OutputFormat == berkeley) {
517cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  if (!MachO || moreThanOneFile || ArchFlags.size() > 1)
518cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    outs() << o->getFileName() << " (for architecture "
519cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           << I->getArchTypeName() << ")";
520cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  outs() << "\n";
521cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                }
522cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              }
523cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            } else if (!I->getAsArchive(UA)) {
524cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              // This is an archive. Iterate over each member and display its
525cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              // sizes.
526cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              for (object::Archive::child_iterator i = UA->child_begin(),
527cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                   e = UA->child_end();
528cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                   i != e; ++i) {
529cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
530cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                if (std::error_code EC = ChildOrErr.getError()) {
531cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  errs() << ToolName << ": " << file << ": " << EC.message()
532cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                         << ".\n";
533cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  continue;
534cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                }
535cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
536cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
537cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  if (OutputFormat == sysv)
538cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    outs() << o->getFileName() << "   (ex " << UA->getFileName()
539cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           << "):\n";
540cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  else if (MachO && OutputFormat == darwin)
541cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    outs() << UA->getFileName() << "(" << o->getFileName()
542cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           << ")"
543cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           << " (for architecture " << I->getArchTypeName()
544cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           << "):\n";
545cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  PrintObjectSectionSizes(o);
546cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  if (OutputFormat == berkeley) {
547cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    if (MachO) {
548cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                      outs() << UA->getFileName() << "(" << o->getFileName()
549cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                             << ")";
550cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                      if (ArchFlags.size() > 1)
551cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                        outs() << " (for architecture " << I->getArchTypeName()
552cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                               << ")";
553cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                      outs() << "\n";
554cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    } else
555cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                      outs() << o->getFileName() << " (ex " << UA->getFileName()
556cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                             << ")\n";
557cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  }
558cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                }
559cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              }
560cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
561cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          }
562cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
563cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (!ArchFound) {
564cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          errs() << ToolName << ": file: " << file
565cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                 << " does not contain architecture" << ArchFlags[i] << ".\n";
566cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          return;
567cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
568cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      }
569cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return;
570cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
571cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    // No architecture flags were specified so if this contains a slice that
572cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    // matches the host architecture dump only that.
573cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (!ArchAll) {
574cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      StringRef HostArchName = MachOObjectFile::getHostArch().getArchName();
575cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
576cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                 E = UB->end_objects();
577cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines           I != E; ++I) {
578cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (HostArchName == I->getArchTypeName()) {
579cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
580cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          std::unique_ptr<Archive> UA;
581cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          if (UO) {
582cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
583cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
584cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              if (OutputFormat == sysv)
585cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                outs() << o->getFileName() << "  :\n";
586cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              else if (MachO && OutputFormat == darwin) {
587cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                if (moreThanOneFile)
588cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  outs() << o->getFileName() << " (for architecture "
589cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                         << I->getArchTypeName() << "):\n";
590cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              }
591cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              PrintObjectSectionSizes(o);
592cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              if (OutputFormat == berkeley) {
593cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                if (!MachO || moreThanOneFile)
594cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  outs() << o->getFileName() << " (for architecture "
595cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                         << I->getArchTypeName() << ")";
596cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                outs() << "\n";
597cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              }
598cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
599cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          } else if (!I->getAsArchive(UA)) {
600cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            // This is an archive. Iterate over each member and display its
601cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            // sizes.
602cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            for (object::Archive::child_iterator i = UA->child_begin(),
603cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                 e = UA->child_end();
604cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                 i != e; ++i) {
605cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
606cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              if (std::error_code EC = ChildOrErr.getError()) {
607cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                errs() << ToolName << ": " << file << ": " << EC.message()
608cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                       << ".\n";
609cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                continue;
610cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              }
611cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
612cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
613cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                if (OutputFormat == sysv)
614cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  outs() << o->getFileName() << "   (ex " << UA->getFileName()
615cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                         << "):\n";
616cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                else if (MachO && OutputFormat == darwin)
617cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  outs() << UA->getFileName() << "(" << o->getFileName() << ")"
618cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                         << " (for architecture " << I->getArchTypeName()
619cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                         << "):\n";
620cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                PrintObjectSectionSizes(o);
621cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                if (OutputFormat == berkeley) {
622cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  if (MachO)
623cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    outs() << UA->getFileName() << "(" << o->getFileName()
624cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           << ")\n";
625cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  else
626cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    outs() << o->getFileName() << " (ex " << UA->getFileName()
627cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           << ")\n";
628cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                }
629cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              }
630cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
631cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          }
632cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          return;
633cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
634cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      }
635cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
636cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    // Either all architectures have been specified or none have been specified
637cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    // and this does not contain the host architecture so dump all the slices.
638cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    bool moreThanOneArch = UB->getNumberOfObjects() > 1;
639cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
640cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                               E = UB->end_objects();
641cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines         I != E; ++I) {
642cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
643cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      std::unique_ptr<Archive> UA;
644cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (UO) {
645cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
646cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
647cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          if (OutputFormat == sysv)
648cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            outs() << o->getFileName() << "  :\n";
649cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          else if (MachO && OutputFormat == darwin) {
650cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (moreThanOneFile || moreThanOneArch)
651cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              outs() << o->getFileName() << " (for architecture "
652cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                     << I->getArchTypeName() << "):";
653cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            outs() << "\n";
654cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          }
655cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          PrintObjectSectionSizes(o);
656cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          if (OutputFormat == berkeley) {
657cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (!MachO || moreThanOneFile || moreThanOneArch)
658cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              outs() << o->getFileName() << " (for architecture "
659cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                     << I->getArchTypeName() << ")";
660cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            outs() << "\n";
661cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          }
662cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
663cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      } else if (!I->getAsArchive(UA)) {
664cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        // This is an archive. Iterate over each member and display its sizes.
665cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        for (object::Archive::child_iterator i = UA->child_begin(),
666cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                             e = UA->child_end();
667cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines             i != e; ++i) {
668cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
669cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          if (std::error_code EC = ChildOrErr.getError()) {
670cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
671cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            continue;
672cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          }
673cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
674cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
675cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (OutputFormat == sysv)
676cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              outs() << o->getFileName() << "   (ex " << UA->getFileName()
677cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                     << "):\n";
678cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            else if (MachO && OutputFormat == darwin)
679cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              outs() << UA->getFileName() << "(" << o->getFileName() << ")"
680cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                     << " (for architecture " << I->getArchTypeName() << "):\n";
681cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            PrintObjectSectionSizes(o);
682cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (OutputFormat == berkeley) {
683cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              if (MachO)
684cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                outs() << UA->getFileName() << "(" << o->getFileName() << ")"
685cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                       << " (for architecture " << I->getArchTypeName()
686cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                       << ")\n";
687cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              else
688cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                outs() << o->getFileName() << " (ex " << UA->getFileName()
689cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                       << ")\n";
690cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
691cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          }
692cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
69332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      }
69432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    }
69532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  } else if (ObjectFile *o = dyn_cast<ObjectFile>(binary.get())) {
696cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (!checkMachOAndArchFlags(o, file))
697cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return;
69832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    if (OutputFormat == sysv)
69932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      outs() << o->getFileName() << "  :\n";
70032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    PrintObjectSectionSizes(o);
701cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (OutputFormat == berkeley) {
702cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
703cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (!MachO || moreThanOneFile)
704cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        outs() << o->getFileName();
705cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      outs() << "\n";
706cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
70732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  } else {
708cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    errs() << ToolName << ": " << file << ": "
709cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines           << "Unrecognized file type.\n";
71032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  }
71175c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer  // System V adds an extra newline at the end of each file.
71232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (OutputFormat == sysv)
71332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    outs() << "\n";
71432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer}
71532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
71632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencerint main(int argc, char **argv) {
71732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  // Print a stack trace if we signal out.
71832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  sys::PrintStackTraceOnErrorSignal();
71932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  PrettyStackTraceProgram X(argc, argv);
72032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
721cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
72232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n");
72332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
72432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  ToolName = argv[0];
72532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (OutputFormatShort.getNumOccurrences())
72632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    OutputFormat = OutputFormatShort;
72732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (RadixShort.getNumOccurrences())
72875c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    Radix = RadixShort;
72932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
730cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (unsigned i = 0; i < ArchFlags.size(); ++i) {
731cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (ArchFlags[i] == "all") {
732cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      ArchAll = true;
733cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    } else {
734cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      Triple T = MachOObjectFile::getArch(ArchFlags[i]);
735cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (T.getArch() == Triple::UnknownArch) {
736cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        outs() << ToolName << ": for the -arch option: Unknown architecture "
737cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               << "named '" << ArchFlags[i] << "'";
738cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        return 1;
739cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      }
740cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
741cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
742cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
74332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (InputFilenames.size() == 0)
74432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    InputFilenames.push_back("a.out");
74532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
746cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  moreThanOneFile = InputFilenames.size() > 1;
74732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  std::for_each(InputFilenames.begin(), InputFilenames.end(),
74832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer                PrintFileSectionSizes);
74932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
75032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  return 0;
75132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer}
752