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"
18c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#include "llvm/Object/MachO.h"
19c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#include "llvm/Object/MachOUniversal.h"
20ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/Object/ObjectFile.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>
32c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#include <system_error>
3332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencerusing namespace llvm;
3432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencerusing namespace object;
3532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
36c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesenum OutputFormatTy { berkeley, sysv, darwin };
3775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencerstatic cl::opt<OutputFormatTy>
38c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesOutputFormat("format", cl::desc("Specify output format"),
39c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines             cl::values(clEnumVal(sysv, "System V format"),
40c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                        clEnumVal(berkeley, "Berkeley format"),
41c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                        clEnumVal(darwin, "Darwin -m format"), clEnumValEnd),
42c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines             cl::init(berkeley));
43c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
44c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic cl::opt<OutputFormatTy> OutputFormatShort(
45c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    cl::desc("Specify output format"),
46c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    cl::values(clEnumValN(sysv, "A", "System V format"),
47c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines               clEnumValN(berkeley, "B", "Berkeley format"),
48c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines               clEnumValN(darwin, "m", "Darwin -m format"), clEnumValEnd),
49c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    cl::init(berkeley));
50c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
51c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic bool berkeleyHeaderPrinted = false;
52c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic bool moreThanOneFile = false;
53c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
54c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinescl::opt<bool>
55c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesDarwinLongFormat("l", cl::desc("When format is darwin, use long format "
56c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                               "to include addresses and offsets."));
5775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer
58c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic cl::list<std::string>
59c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
60c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          cl::ZeroOrMore);
61c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesbool ArchAll = false;
6275c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer
63c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesenum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 };
6475c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencerstatic cl::opt<unsigned int>
65c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesRadix("-radix", cl::desc("Print size in radix. Only 8, 10, and 16 are valid"),
66c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      cl::init(decimal));
6775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer
6875c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencerstatic cl::opt<RadixTy>
69c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesRadixShort(cl::desc("Print size in radix:"),
70c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines           cl::values(clEnumValN(octal, "o", "Print size in octal"),
71c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                      clEnumValN(decimal, "d", "Print size in decimal"),
72c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                      clEnumValN(hexadecimal, "x", "Print size in hexadecimal"),
73c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                      clEnumValEnd),
74c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines           cl::init(decimal));
7575c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer
7675c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencerstatic cl::list<std::string>
77c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen 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.
82c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic bool error(std::error_code ec) {
83c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  if (!ec)
84c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen 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
100c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines/// @brief Return the the printing format for the Radix.
101c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic const char *getRadixFmt(void) {
102c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  switch (Radix) {
103c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  case octal:
104c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    return PRIo64;
105c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  case decimal:
106c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    return PRIu64;
107c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  case hexadecimal:
108c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    return PRIx64;
109c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  }
110c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  return nullptr;
111c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines}
112c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
113c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines/// @brief Print the size of each Mach-O segment and section in @p MachO.
114c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines///
115c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines/// This is when used when @c OutputFormat is darwin and produces the same
116c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines/// output as darwin's size(1) -m output.
117c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic void PrintDarwinSectionSizes(MachOObjectFile *MachO) {
118c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  std::string fmtbuf;
119c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  raw_string_ostream fmt(fmtbuf);
120c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  const char *radix_fmt = getRadixFmt();
121c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  if (Radix == hexadecimal)
122c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    fmt << "0x";
123c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  fmt << "%" << radix_fmt;
124c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
125c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  uint32_t LoadCommandCount = MachO->getHeader().ncmds;
126c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  uint32_t Filetype = MachO->getHeader().filetype;
127c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
128c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
129c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  uint64_t total = 0;
130c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  for (unsigned I = 0;; ++I) {
131c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
132c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
133c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      outs() << "Segment " << Seg.segname << ": "
134c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines             << format(fmt.str().c_str(), Seg.vmsize);
135c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (DarwinLongFormat)
136c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr) << " fileoff "
137c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines               << Seg.fileoff << ")";
138c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      outs() << "\n";
139c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      total += Seg.vmsize;
140c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      uint64_t sec_total = 0;
141c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      for (unsigned J = 0; J < Seg.nsects; ++J) {
142c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        MachO::section_64 Sec = MachO->getSection64(Load, J);
143c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (Filetype == MachO::MH_OBJECT)
144c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
145c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                 << format("%.16s", &Sec.sectname) << "): ";
146c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        else
147c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
148c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        outs() << format(fmt.str().c_str(), Sec.size);
149c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (DarwinLongFormat)
150c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          outs() << " (addr 0x" << format("%" PRIx64, Sec.addr) << " offset "
151c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                 << Sec.offset << ")";
152c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        outs() << "\n";
153c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        sec_total += Sec.size;
154c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      }
155c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (Seg.nsects != 0)
156c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
157c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
158c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
159c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      outs() << "Segment " << Seg.segname << ": "
160c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines             << format(fmt.str().c_str(), Seg.vmsize);
161c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (DarwinLongFormat)
162c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr) << " fileoff "
163c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines               << Seg.fileoff << ")";
164c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      outs() << "\n";
165c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      total += Seg.vmsize;
166c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      uint64_t sec_total = 0;
167c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      for (unsigned J = 0; J < Seg.nsects; ++J) {
168c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        MachO::section Sec = MachO->getSection(Load, J);
169c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (Filetype == MachO::MH_OBJECT)
170c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
171c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                 << format("%.16s", &Sec.sectname) << "): ";
172c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        else
173c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
174c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        outs() << format(fmt.str().c_str(), Sec.size);
175c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (DarwinLongFormat)
176c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          outs() << " (addr 0x" << format("%" PRIx64, Sec.addr) << " offset "
177c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                 << Sec.offset << ")";
178c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        outs() << "\n";
179c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        sec_total += Sec.size;
180c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      }
181c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (Seg.nsects != 0)
182c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
183c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
184c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (I == LoadCommandCount - 1)
185c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      break;
186c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    else
187c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      Load = MachO->getNextLoadCommandInfo(Load);
188c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  }
189c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  outs() << "total " << format(fmt.str().c_str(), total) << "\n";
190c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines}
191c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
192c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines/// @brief Print the summary sizes of the standard Mach-O segments in @p MachO.
193c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines///
194c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines/// This is when used when @c OutputFormat is berkeley with a Mach-O file and
195c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines/// produces the same output as darwin's size(1) default output.
196c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic void PrintDarwinSegmentSizes(MachOObjectFile *MachO) {
197c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  uint32_t LoadCommandCount = MachO->getHeader().ncmds;
198c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
199c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
200c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  uint64_t total_text = 0;
201c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  uint64_t total_data = 0;
202c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  uint64_t total_objc = 0;
203c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  uint64_t total_others = 0;
204c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  for (unsigned I = 0;; ++I) {
205c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
206c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
207c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
208c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        for (unsigned J = 0; J < Seg.nsects; ++J) {
209c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          MachO::section_64 Sec = MachO->getSection64(Load, J);
210c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          StringRef SegmentName = StringRef(Sec.segname);
211c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          if (SegmentName == "__TEXT")
212c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            total_text += Sec.size;
213c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          else if (SegmentName == "__DATA")
214c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            total_data += Sec.size;
215c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          else if (SegmentName == "__OBJC")
216c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            total_objc += Sec.size;
217c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          else
218c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            total_others += Sec.size;
219c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
220c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      } else {
221c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        StringRef SegmentName = StringRef(Seg.segname);
222c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (SegmentName == "__TEXT")
223c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          total_text += Seg.vmsize;
224c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        else if (SegmentName == "__DATA")
225c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          total_data += Seg.vmsize;
226c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        else if (SegmentName == "__OBJC")
227c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          total_objc += Seg.vmsize;
228c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        else
229c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          total_others += Seg.vmsize;
230c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      }
231c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
232c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
233c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
234c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        for (unsigned J = 0; J < Seg.nsects; ++J) {
235c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          MachO::section Sec = MachO->getSection(Load, J);
236c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          StringRef SegmentName = StringRef(Sec.segname);
237c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          if (SegmentName == "__TEXT")
238c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            total_text += Sec.size;
239c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          else if (SegmentName == "__DATA")
240c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            total_data += Sec.size;
241c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          else if (SegmentName == "__OBJC")
242c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            total_objc += Sec.size;
243c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          else
244c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            total_others += Sec.size;
245c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
246c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      } else {
247c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        StringRef SegmentName = StringRef(Seg.segname);
248c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (SegmentName == "__TEXT")
249c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          total_text += Seg.vmsize;
250c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        else if (SegmentName == "__DATA")
251c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          total_data += Seg.vmsize;
252c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        else if (SegmentName == "__OBJC")
253c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          total_objc += Seg.vmsize;
254c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        else
255c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          total_others += Seg.vmsize;
256c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      }
257c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
258c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (I == LoadCommandCount - 1)
259c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      break;
260c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    else
261c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      Load = MachO->getNextLoadCommandInfo(Load);
262c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  }
263c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  uint64_t total = total_text + total_data + total_objc + total_others;
264c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
265c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  if (!berkeleyHeaderPrinted) {
266c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
267c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    berkeleyHeaderPrinted = true;
268c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  }
269c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  outs() << total_text << "\t" << total_data << "\t" << total_objc << "\t"
270c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines         << total_others << "\t" << total << "\t" << format("%" PRIx64, total)
271c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines         << "\t";
272c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines}
273c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen 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);
281c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  const char *radix_fmt = getRadixFmt();
282c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
283c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
284c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
285c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  // let it fall through to OutputFormat berkeley.
286c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
287c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  if (OutputFormat == darwin && MachO)
288c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    PrintDarwinSectionSizes(MachO);
289c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  // If we have a MachOObjectFile and the OutputFormat is berkeley print as
290c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  // darwin's default berkeley format for Mach-O files.
291c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  else if (MachO && OutputFormat == berkeley)
292c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    PrintDarwinSegmentSizes(MachO);
293c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen 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()) {
30037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      uint64_t size = Section.getSize();
30132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      total += size;
30232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
30332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      StringRef name;
30436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.getName(name)))
30536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
30637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      uint64_t addr = Section.getAddress();
30732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      max_name_len = std::max(max_name_len, name.size());
308f47e870015439b1b47562533689a9dec17879befAndrew Trick      max_size_len = std::max(max_size_len, getNumLengthAsString(size));
309f47e870015439b1b47562533689a9dec17879befAndrew Trick      max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr));
31032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    }
31132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
31275c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // Add extra padding.
31332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    max_name_len += 2;
31432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    max_size_len += 2;
31532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    max_addr_len += 2;
31632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
31775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // Setup header format.
31832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmt << "%-" << max_name_len << "s "
31932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%" << max_size_len << "s "
32032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%" << max_addr_len << "s\n";
32132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
32232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Print header
323c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    outs() << format(fmt.str().c_str(), static_cast<const char *>("section"),
324c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                     static_cast<const char *>("size"),
325c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                     static_cast<const char *>("addr"));
32632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmtbuf.clear();
32732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
32832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Setup per section format.
32932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmt << "%-" << max_name_len << "s "
33032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%#" << max_size_len << radix_fmt << " "
33132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%#" << max_addr_len << radix_fmt << "\n";
33232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
33332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Print each section.
33436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (const SectionRef &Section : Obj->sections()) {
33532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      StringRef name;
33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section.getName(name)))
33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
33837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      uint64_t size = Section.getSize();
33937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      uint64_t addr = Section.getAddress();
34032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      std::string namestr = name;
34132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
34236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      outs() << format(fmt.str().c_str(), namestr.c_str(), size, addr);
34332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    }
34432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
34532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Print total.
34632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmtbuf.clear();
34732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmt << "%-" << max_name_len << "s "
34832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%#" << max_size_len << radix_fmt << "\n";
349c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    outs() << format(fmt.str().c_str(), static_cast<const char *>("Total"),
35032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer                     total);
35132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  } else {
35275c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // The Berkeley format does not display individual section sizes. It
35375c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // displays the cumulative size for each section type.
35432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    uint64_t total_text = 0;
35532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    uint64_t total_data = 0;
35632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    uint64_t total_bss = 0;
35732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
35875c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // Make one pass over the section table to calculate sizes.
35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (const SectionRef &Section : Obj->sections()) {
36037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      uint64_t size = Section.getSize();
36137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      bool isText = Section.isText();
36237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      bool isData = Section.isData();
36337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      bool isBSS = Section.isBSS();
36432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      if (isText)
36532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        total_text += size;
36632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      else if (isData)
36732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        total_data += size;
36832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      else if (isBSS)
36932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        total_bss += size;
37032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    }
37132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
37232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    total = total_text + total_data + total_bss;
37332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
374c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (!berkeleyHeaderPrinted) {
375c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      outs() << "   text    data     bss     "
376c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines             << (Radix == octal ? "oct" : "dec") << "     hex filename\n";
377c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      berkeleyHeaderPrinted = true;
378c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
379c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
38032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    // Print result.
38132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmt << "%#7" << radix_fmt << " "
38232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%#7" << radix_fmt << " "
38332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        << "%#7" << radix_fmt << " ";
384c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    outs() << format(fmt.str().c_str(), total_text, total_data, total_bss);
38532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    fmtbuf.clear();
38641a964931a0e0943ceef28b0c691843bf8ca87b7Benjamin Kramer    fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << " "
38741a964931a0e0943ceef28b0c691843bf8ca87b7Benjamin Kramer        << "%7" PRIx64 " ";
388c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    outs() << format(fmt.str().c_str(), total, total);
389c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  }
390c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines}
391c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
392c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines/// @brief Checks to see if the @p o ObjectFile is a Mach-O file and if it is
393c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines///        and there is a list of architecture flags specified then check to
394c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines///        make sure this Mach-O file is one of those architectures or all
395c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines///        architectures was specificed.  If not then an error is generated and
396c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines///        this routine returns false.  Else it returns true.
397c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) {
398c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  if (isa<MachOObjectFile>(o) && !ArchAll && ArchFlags.size() != 0) {
399c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
400c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    bool ArchFound = false;
401c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    MachO::mach_header H;
402c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    MachO::mach_header_64 H_64;
403c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    Triple T;
404c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (MachO->is64Bit()) {
405c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      H_64 = MachO->MachOObjectFile::getHeader64();
406c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype);
407c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    } else {
408c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      H = MachO->MachOObjectFile::getHeader();
409c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      T = MachOObjectFile::getArch(H.cputype, H.cpusubtype);
410c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
411c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    unsigned i;
412c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    for (i = 0; i < ArchFlags.size(); ++i) {
413c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (ArchFlags[i] == T.getArchName())
414c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        ArchFound = true;
415c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      break;
416c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
417c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (!ArchFound) {
418c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      errs() << ToolName << ": file: " << file
419c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines             << " does not contain architecture: " << ArchFlags[i] << ".\n";
420c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      return false;
421c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
42232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  }
423c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  return true;
42432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer}
42532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
42675c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer/// @brief Print the section sizes for @p file. If @p file is an archive, print
42775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer///        the section sizes for each archive member.
42832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencerstatic void PrintFileSectionSizes(StringRef file) {
42932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  // If file is not stdin, check that it exists.
43032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (file != "-") {
43137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (!sys::fs::exists(file)) {
432c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      errs() << ToolName << ": '" << file << "': "
433c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines             << "No such file\n";
43432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      return;
43532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    }
43632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  }
43732a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
43875c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer  // Attempt to open the binary.
43937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
440c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  if (std::error_code EC = BinaryOrErr.getError()) {
44136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
44232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    return;
44332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  }
44437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  Binary &Bin = *BinaryOrErr.get().getBinary();
44532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
44637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (Archive *a = dyn_cast<Archive>(&Bin)) {
44775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    // This is an archive. Iterate over each member and display its sizes.
44836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (object::Archive::child_iterator i = a->child_begin(),
449c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                                         e = a->child_end();
450c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines         i != e; ++i) {
451c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
452c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (std::error_code EC = ChildOrErr.getError()) {
453c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
45432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        continue;
45532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      }
456c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
457c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
458c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (!checkMachOAndArchFlags(o, file))
459c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          return;
46032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        if (OutputFormat == sysv)
461c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          outs() << o->getFileName() << "   (ex " << a->getFileName() << "):\n";
462c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        else if (MachO && OutputFormat == darwin)
463c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
46432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer        PrintObjectSectionSizes(o);
465c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (OutputFormat == berkeley) {
466c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          if (MachO)
467c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
468c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          else
469c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
470c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
471c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      }
472c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
473c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  } else if (MachOUniversalBinary *UB =
47437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                 dyn_cast<MachOUniversalBinary>(&Bin)) {
475c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    // If we have a list of architecture flags specified dump only those.
476c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (!ArchAll && ArchFlags.size() != 0) {
477c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // Look for a slice in the universal binary that matches each ArchFlag.
478c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      bool ArchFound;
479c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      for (unsigned i = 0; i < ArchFlags.size(); ++i) {
480c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        ArchFound = false;
481c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
482c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                                                   E = UB->end_objects();
483c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines             I != E; ++I) {
484c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          if (ArchFlags[i] == I->getArchTypeName()) {
485c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            ArchFound = true;
486c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
487c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            if (UO) {
488c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
489c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
490c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                if (OutputFormat == sysv)
491c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  outs() << o->getFileName() << "  :\n";
492c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                else if (MachO && OutputFormat == darwin) {
493c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  if (moreThanOneFile || ArchFlags.size() > 1)
494c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                    outs() << o->getFileName() << " (for architecture "
495c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                           << I->getArchTypeName() << "): \n";
496c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                }
497c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                PrintObjectSectionSizes(o);
498c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                if (OutputFormat == berkeley) {
499c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  if (!MachO || moreThanOneFile || ArchFlags.size() > 1)
500c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                    outs() << o->getFileName() << " (for architecture "
501c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                           << I->getArchTypeName() << ")";
502c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  outs() << "\n";
503c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                }
504c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              }
505ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines            } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
506ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines                           I->getAsArchive()) {
507ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines              std::unique_ptr<Archive> &UA = *AOrErr;
508c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              // This is an archive. Iterate over each member and display its
509c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              // sizes.
510c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              for (object::Archive::child_iterator i = UA->child_begin(),
511c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                                                   e = UA->child_end();
512c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                   i != e; ++i) {
513c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
514c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                if (std::error_code EC = ChildOrErr.getError()) {
515c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  errs() << ToolName << ": " << file << ": " << EC.message()
516c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                         << ".\n";
517c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  continue;
518c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                }
519c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
520c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
521c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  if (OutputFormat == sysv)
522c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                    outs() << o->getFileName() << "   (ex " << UA->getFileName()
523c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                           << "):\n";
524c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  else if (MachO && OutputFormat == darwin)
525c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                    outs() << UA->getFileName() << "(" << o->getFileName()
526c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                           << ")"
527c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                           << " (for architecture " << I->getArchTypeName()
528c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                           << "):\n";
529c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  PrintObjectSectionSizes(o);
530c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  if (OutputFormat == berkeley) {
531c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                    if (MachO) {
532c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                      outs() << UA->getFileName() << "(" << o->getFileName()
533c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                             << ")";
534c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                      if (ArchFlags.size() > 1)
535c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                        outs() << " (for architecture " << I->getArchTypeName()
536c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                               << ")";
537c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                      outs() << "\n";
538c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                    } else
539c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                      outs() << o->getFileName() << " (ex " << UA->getFileName()
540c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                             << ")\n";
541c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  }
542c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                }
543c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              }
544c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            }
545c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          }
546c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
547c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (!ArchFound) {
548c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          errs() << ToolName << ": file: " << file
549c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                 << " does not contain architecture" << ArchFlags[i] << ".\n";
550c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          return;
551c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
552c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      }
553c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      return;
554c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
555c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    // No architecture flags were specified so if this contains a slice that
556c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    // matches the host architecture dump only that.
557c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (!ArchAll) {
558c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      StringRef HostArchName = MachOObjectFile::getHostArch().getArchName();
559c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
560c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                                                 E = UB->end_objects();
561c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines           I != E; ++I) {
562c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (HostArchName == I->getArchTypeName()) {
563c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
564c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          if (UO) {
565c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
566c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
567c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              if (OutputFormat == sysv)
568c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                outs() << o->getFileName() << "  :\n";
569c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              else if (MachO && OutputFormat == darwin) {
570c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                if (moreThanOneFile)
571c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  outs() << o->getFileName() << " (for architecture "
572c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                         << I->getArchTypeName() << "):\n";
573c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              }
574c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              PrintObjectSectionSizes(o);
575c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              if (OutputFormat == berkeley) {
576c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                if (!MachO || moreThanOneFile)
577c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  outs() << o->getFileName() << " (for architecture "
578c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                         << I->getArchTypeName() << ")";
579c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                outs() << "\n";
580c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              }
581c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            }
582ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines          } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
583ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines                         I->getAsArchive()) {
584ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines            std::unique_ptr<Archive> &UA = *AOrErr;
585c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            // This is an archive. Iterate over each member and display its
586c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            // sizes.
587c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            for (object::Archive::child_iterator i = UA->child_begin(),
588c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                                                 e = UA->child_end();
589c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                 i != e; ++i) {
590c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
591c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              if (std::error_code EC = ChildOrErr.getError()) {
592c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                errs() << ToolName << ": " << file << ": " << EC.message()
593c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                       << ".\n";
594c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                continue;
595c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              }
596c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
597c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
598c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                if (OutputFormat == sysv)
599c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  outs() << o->getFileName() << "   (ex " << UA->getFileName()
600c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                         << "):\n";
601c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                else if (MachO && OutputFormat == darwin)
602c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  outs() << UA->getFileName() << "(" << o->getFileName() << ")"
603c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                         << " (for architecture " << I->getArchTypeName()
604c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                         << "):\n";
605c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                PrintObjectSectionSizes(o);
606c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                if (OutputFormat == berkeley) {
607c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  if (MachO)
608c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                    outs() << UA->getFileName() << "(" << o->getFileName()
609c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                           << ")\n";
610c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                  else
611c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                    outs() << o->getFileName() << " (ex " << UA->getFileName()
612c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                           << ")\n";
613c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                }
614c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              }
615c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            }
616c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          }
617c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          return;
618c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
619c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      }
620c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
621c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    // Either all architectures have been specified or none have been specified
622c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    // and this does not contain the host architecture so dump all the slices.
623c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    bool moreThanOneArch = UB->getNumberOfObjects() > 1;
624c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
625c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                                               E = UB->end_objects();
626c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines         I != E; ++I) {
627c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
628c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (UO) {
629c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
630c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
631c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          if (OutputFormat == sysv)
632c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            outs() << o->getFileName() << "  :\n";
633c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          else if (MachO && OutputFormat == darwin) {
634c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            if (moreThanOneFile || moreThanOneArch)
635c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              outs() << o->getFileName() << " (for architecture "
636c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                     << I->getArchTypeName() << "):";
637c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            outs() << "\n";
638c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          }
639c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          PrintObjectSectionSizes(o);
640c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          if (OutputFormat == berkeley) {
641c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            if (!MachO || moreThanOneFile || moreThanOneArch)
642c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              outs() << o->getFileName() << " (for architecture "
643c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                     << I->getArchTypeName() << ")";
644c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            outs() << "\n";
645c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          }
646c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
647ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
648ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines                         I->getAsArchive()) {
649ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines        std::unique_ptr<Archive> &UA = *AOrErr;
650c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        // This is an archive. Iterate over each member and display its sizes.
651c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        for (object::Archive::child_iterator i = UA->child_begin(),
652c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                                             e = UA->child_end();
653c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines             i != e; ++i) {
654c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
655c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          if (std::error_code EC = ChildOrErr.getError()) {
656c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
657c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            continue;
658c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          }
659c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
660c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
661c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            if (OutputFormat == sysv)
662c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              outs() << o->getFileName() << "   (ex " << UA->getFileName()
663c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                     << "):\n";
664c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            else if (MachO && OutputFormat == darwin)
665c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              outs() << UA->getFileName() << "(" << o->getFileName() << ")"
666c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                     << " (for architecture " << I->getArchTypeName() << "):\n";
667c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            PrintObjectSectionSizes(o);
668c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            if (OutputFormat == berkeley) {
669c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              if (MachO)
670c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                outs() << UA->getFileName() << "(" << o->getFileName() << ")"
671c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                       << " (for architecture " << I->getArchTypeName()
672c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                       << ")\n";
673c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines              else
674c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                outs() << o->getFileName() << " (ex " << UA->getFileName()
675c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                       << ")\n";
676c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            }
677c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          }
678c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
67932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      }
68032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    }
68137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  } else if (ObjectFile *o = dyn_cast<ObjectFile>(&Bin)) {
682c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (!checkMachOAndArchFlags(o, file))
683c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      return;
68432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    if (OutputFormat == sysv)
68532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer      outs() << o->getFileName() << "  :\n";
68632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    PrintObjectSectionSizes(o);
687c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (OutputFormat == berkeley) {
688c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
689c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      if (!MachO || moreThanOneFile)
690c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        outs() << o->getFileName();
691c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      outs() << "\n";
692c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
69332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  } else {
694c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    errs() << ToolName << ": " << file << ": "
695c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines           << "Unrecognized file type.\n";
69632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  }
69775c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer  // System V adds an extra newline at the end of each file.
69832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (OutputFormat == sysv)
69932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    outs() << "\n";
70032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer}
70132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
70232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencerint main(int argc, char **argv) {
70332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  // Print a stack trace if we signal out.
70432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  sys::PrintStackTraceOnErrorSignal();
70532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  PrettyStackTraceProgram X(argc, argv);
70632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
707c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
70832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n");
70932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
71032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  ToolName = argv[0];
71132a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (OutputFormatShort.getNumOccurrences())
712ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    OutputFormat = static_cast<OutputFormatTy>(OutputFormatShort);
71332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (RadixShort.getNumOccurrences())
71475c4abacaa8047f4e2971e98f093c6b731e3b0a8Michael J. Spencer    Radix = RadixShort;
71532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
716c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  for (unsigned i = 0; i < ArchFlags.size(); ++i) {
717c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (ArchFlags[i] == "all") {
718c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      ArchAll = true;
719c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    } else {
72037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
721c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        outs() << ToolName << ": for the -arch option: Unknown architecture "
722c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines               << "named '" << ArchFlags[i] << "'";
723c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        return 1;
724c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      }
725c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
726c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  }
727c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
72832a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  if (InputFilenames.size() == 0)
72932a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer    InputFilenames.push_back("a.out");
73032a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
731c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  moreThanOneFile = InputFilenames.size() > 1;
73232a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  std::for_each(InputFilenames.begin(), InputFilenames.end(),
73332a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer                PrintFileSectionSizes);
73432a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer
73532a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer  return 0;
73632a12ba8c0736a74681563a8f5ec8d81108514b5Michael J. Spencer}
737