llvm-size.cpp 33 KB

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