llvm-size.cpp 34 KB

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