llvm-size.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  1. //===-- llvm-size.cpp - Print the size of each object section ---*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This program is a utility that works like traditional Unix "size",
  10. // that is, it prints out the size of each section, and the total size of all
  11. // sections.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/ADT/APInt.h"
  15. #include "llvm/Object/Archive.h"
  16. #include "llvm/Object/ELFObjectFile.h"
  17. #include "llvm/Object/MachO.h"
  18. #include "llvm/Object/MachOUniversal.h"
  19. #include "llvm/Object/ObjectFile.h"
  20. #include "llvm/Option/Arg.h"
  21. #include "llvm/Option/ArgList.h"
  22. #include "llvm/Option/Option.h"
  23. #include "llvm/Support/Casting.h"
  24. #include "llvm/Support/CommandLine.h"
  25. #include "llvm/Support/FileSystem.h"
  26. #include "llvm/Support/Format.h"
  27. #include "llvm/Support/InitLLVM.h"
  28. #include "llvm/Support/MemoryBuffer.h"
  29. #include "llvm/Support/WithColor.h"
  30. #include "llvm/Support/raw_ostream.h"
  31. #include <algorithm>
  32. #include <string>
  33. #include <system_error>
  34. using namespace llvm;
  35. using namespace object;
  36. namespace {
  37. using namespace llvm::opt; // for HelpHidden in Opts.inc
  38. enum ID {
  39. OPT_INVALID = 0, // This is not an option ID.
  40. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  41. HELPTEXT, METAVAR, VALUES) \
  42. OPT_##ID,
  43. #include "Opts.inc"
  44. #undef OPTION
  45. };
  46. #define PREFIX(NAME, VALUE) \
  47. static constexpr StringLiteral NAME##_init[] = VALUE; \
  48. static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
  49. std::size(NAME##_init) - 1);
  50. #include "Opts.inc"
  51. #undef PREFIX
  52. static constexpr opt::OptTable::Info InfoTable[] = {
  53. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  54. HELPTEXT, METAVAR, VALUES) \
  55. { \
  56. PREFIX, NAME, HELPTEXT, \
  57. METAVAR, OPT_##ID, opt::Option::KIND##Class, \
  58. PARAM, FLAGS, OPT_##GROUP, \
  59. OPT_##ALIAS, ALIASARGS, VALUES},
  60. #include "Opts.inc"
  61. #undef OPTION
  62. };
  63. class SizeOptTable : public opt::GenericOptTable {
  64. public:
  65. SizeOptTable() : GenericOptTable(InfoTable) { setGroupedShortOptions(true); }
  66. };
  67. enum OutputFormatTy { berkeley, sysv, darwin };
  68. enum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 };
  69. } // namespace
  70. static bool ArchAll = false;
  71. static std::vector<StringRef> ArchFlags;
  72. static bool ELFCommons;
  73. static OutputFormatTy OutputFormat;
  74. static bool DarwinLongFormat;
  75. static RadixTy Radix;
  76. static bool TotalSizes;
  77. static std::vector<std::string> InputFilenames;
  78. static std::string ToolName;
  79. // States
  80. static bool HadError = false;
  81. static bool BerkeleyHeaderPrinted = false;
  82. static bool MoreThanOneFile = false;
  83. static uint64_t TotalObjectText = 0;
  84. static uint64_t TotalObjectData = 0;
  85. static uint64_t TotalObjectBss = 0;
  86. static uint64_t TotalObjectTotal = 0;
  87. static void error(const Twine &Message, StringRef File = "") {
  88. HadError = true;
  89. if (File.empty())
  90. WithColor::error(errs(), ToolName) << Message << '\n';
  91. else
  92. WithColor::error(errs(), ToolName)
  93. << "'" << File << "': " << Message << '\n';
  94. }
  95. // This version of error() prints the archive name and member name, for example:
  96. // "libx.a(foo.o)" after the ToolName before the error message. It sets
  97. // HadError but returns allowing the code to move on to other archive members.
  98. static void error(llvm::Error E, StringRef FileName, const Archive::Child &C,
  99. StringRef ArchitectureName = StringRef()) {
  100. HadError = true;
  101. WithColor::error(errs(), ToolName) << "'" << FileName << "'";
  102. Expected<StringRef> NameOrErr = C.getName();
  103. // TODO: if we have a error getting the name then it would be nice to print
  104. // the index of which archive member this is and or its offset in the
  105. // archive instead of "???" as the name.
  106. if (!NameOrErr) {
  107. consumeError(NameOrErr.takeError());
  108. errs() << "(" << "???" << ")";
  109. } else
  110. errs() << "(" << NameOrErr.get() << ")";
  111. if (!ArchitectureName.empty())
  112. errs() << " (for architecture " << ArchitectureName << ") ";
  113. std::string Buf;
  114. raw_string_ostream OS(Buf);
  115. logAllUnhandledErrors(std::move(E), OS);
  116. OS.flush();
  117. errs() << ": " << Buf << "\n";
  118. }
  119. // 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
  120. // before the error message. It sets HadError but returns allowing the code to
  121. // move on to other architecture slices.
  122. static void error(llvm::Error E, StringRef FileName,
  123. StringRef ArchitectureName = StringRef()) {
  124. HadError = true;
  125. WithColor::error(errs(), ToolName) << "'" << FileName << "'";
  126. if (!ArchitectureName.empty())
  127. errs() << " (for architecture " << ArchitectureName << ") ";
  128. std::string Buf;
  129. raw_string_ostream OS(Buf);
  130. logAllUnhandledErrors(std::move(E), OS);
  131. OS.flush();
  132. errs() << ": " << Buf << "\n";
  133. }
  134. /// Get the length of the string that represents @p num in Radix including the
  135. /// leading 0x or 0 for hexadecimal and octal respectively.
  136. static size_t getNumLengthAsString(uint64_t num) {
  137. APInt conv(64, num);
  138. SmallString<32> result;
  139. conv.toString(result, Radix, false, true);
  140. return result.size();
  141. }
  142. /// Return the printing format for the Radix.
  143. static const char *getRadixFmt() {
  144. switch (Radix) {
  145. case octal:
  146. return PRIo64;
  147. case decimal:
  148. return PRIu64;
  149. case hexadecimal:
  150. return PRIx64;
  151. }
  152. return nullptr;
  153. }
  154. /// Remove unneeded ELF sections from calculation
  155. static bool considerForSize(ObjectFile *Obj, SectionRef Section) {
  156. if (!Obj->isELF())
  157. return true;
  158. switch (static_cast<ELFSectionRef>(Section).getType()) {
  159. case ELF::SHT_NULL:
  160. case ELF::SHT_SYMTAB:
  161. return false;
  162. case ELF::SHT_STRTAB:
  163. case ELF::SHT_REL:
  164. case ELF::SHT_RELA:
  165. return static_cast<ELFSectionRef>(Section).getFlags() & ELF::SHF_ALLOC;
  166. }
  167. return true;
  168. }
  169. /// Total size of all ELF common symbols
  170. static Expected<uint64_t> getCommonSize(ObjectFile *Obj) {
  171. uint64_t TotalCommons = 0;
  172. for (auto &Sym : Obj->symbols()) {
  173. Expected<uint32_t> SymFlagsOrErr =
  174. Obj->getSymbolFlags(Sym.getRawDataRefImpl());
  175. if (!SymFlagsOrErr)
  176. return SymFlagsOrErr.takeError();
  177. if (*SymFlagsOrErr & SymbolRef::SF_Common)
  178. TotalCommons += Obj->getCommonSymbolSize(Sym.getRawDataRefImpl());
  179. }
  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. Expected<StringRef> name_or_err = Section.getName();
  357. if (!name_or_err) {
  358. error(name_or_err.takeError(), Obj->getFileName());
  359. return;
  360. }
  361. uint64_t addr = Section.getAddress();
  362. max_name_len = std::max(max_name_len, name_or_err->size());
  363. max_size_len = std::max(max_size_len, getNumLengthAsString(size));
  364. max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr));
  365. }
  366. // Add extra padding.
  367. max_name_len += 2;
  368. max_size_len += 2;
  369. max_addr_len += 2;
  370. // Setup header format.
  371. fmt << "%-" << max_name_len << "s "
  372. << "%" << max_size_len << "s "
  373. << "%" << max_addr_len << "s\n";
  374. // Print header
  375. outs() << format(fmt.str().c_str(), static_cast<const char *>("section"),
  376. static_cast<const char *>("size"),
  377. static_cast<const char *>("addr"));
  378. fmtbuf.clear();
  379. // Setup per section format.
  380. fmt << "%-" << max_name_len << "s "
  381. << "%#" << max_size_len << radix_fmt << " "
  382. << "%#" << max_addr_len << radix_fmt << "\n";
  383. // Print each section.
  384. for (const SectionRef &Section : Obj->sections()) {
  385. if (!considerForSize(Obj, Section))
  386. continue;
  387. Expected<StringRef> name_or_err = Section.getName();
  388. if (!name_or_err) {
  389. error(name_or_err.takeError(), Obj->getFileName());
  390. return;
  391. }
  392. uint64_t size = Section.getSize();
  393. uint64_t addr = Section.getAddress();
  394. outs() << format(fmt.str().c_str(), name_or_err->str().c_str(), size, addr);
  395. }
  396. if (ELFCommons) {
  397. if (Expected<uint64_t> CommonSizeOrErr = getCommonSize(Obj)) {
  398. total += *CommonSizeOrErr;
  399. outs() << format(fmt.str().c_str(), std::string("*COM*").c_str(),
  400. *CommonSizeOrErr, static_cast<uint64_t>(0));
  401. } else {
  402. error(CommonSizeOrErr.takeError(), Obj->getFileName());
  403. return;
  404. }
  405. }
  406. // Print total.
  407. fmtbuf.clear();
  408. fmt << "%-" << max_name_len << "s "
  409. << "%#" << max_size_len << radix_fmt << "\n";
  410. outs() << format(fmt.str().c_str(), static_cast<const char *>("Total"),
  411. total)
  412. << "\n\n";
  413. } else {
  414. // The Berkeley format does not display individual section sizes. It
  415. // displays the cumulative size for each section type.
  416. uint64_t total_text = 0;
  417. uint64_t total_data = 0;
  418. uint64_t total_bss = 0;
  419. // Make one pass over the section table to calculate sizes.
  420. for (const SectionRef &Section : Obj->sections()) {
  421. uint64_t size = Section.getSize();
  422. bool isText = Section.isBerkeleyText();
  423. bool isData = Section.isBerkeleyData();
  424. bool isBSS = Section.isBSS();
  425. if (isText)
  426. total_text += size;
  427. else if (isData)
  428. total_data += size;
  429. else if (isBSS)
  430. total_bss += size;
  431. }
  432. if (ELFCommons) {
  433. if (Expected<uint64_t> CommonSizeOrErr = getCommonSize(Obj))
  434. total_bss += *CommonSizeOrErr;
  435. else {
  436. error(CommonSizeOrErr.takeError(), Obj->getFileName());
  437. return;
  438. }
  439. }
  440. total = total_text + total_data + total_bss;
  441. if (TotalSizes) {
  442. TotalObjectText += total_text;
  443. TotalObjectData += total_data;
  444. TotalObjectBss += total_bss;
  445. TotalObjectTotal += total;
  446. }
  447. if (!BerkeleyHeaderPrinted) {
  448. outs() << " text\t"
  449. " data\t"
  450. " bss\t"
  451. " "
  452. << (Radix == octal ? "oct" : "dec")
  453. << "\t"
  454. " hex\t"
  455. "filename\n";
  456. BerkeleyHeaderPrinted = true;
  457. }
  458. // Print result.
  459. fmt << "%#7" << radix_fmt << "\t"
  460. << "%#7" << radix_fmt << "\t"
  461. << "%#7" << radix_fmt << "\t";
  462. outs() << format(fmt.str().c_str(), total_text, total_data, total_bss);
  463. fmtbuf.clear();
  464. fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << "\t"
  465. << "%7" PRIx64 "\t";
  466. outs() << format(fmt.str().c_str(), total, total);
  467. }
  468. }
  469. /// Checks to see if the @p O ObjectFile is a Mach-O file and if it is and there
  470. /// is a list of architecture flags specified then check to make sure this
  471. /// Mach-O file is one of those architectures or all architectures was
  472. /// specificed. If not then an error is generated and this routine returns
  473. /// false. Else it returns true.
  474. static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
  475. auto *MachO = dyn_cast<MachOObjectFile>(O);
  476. if (!MachO || ArchAll || ArchFlags.empty())
  477. return true;
  478. MachO::mach_header H;
  479. MachO::mach_header_64 H_64;
  480. Triple T;
  481. if (MachO->is64Bit()) {
  482. H_64 = MachO->MachOObjectFile::getHeader64();
  483. T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype);
  484. } else {
  485. H = MachO->MachOObjectFile::getHeader();
  486. T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype);
  487. }
  488. if (!is_contained(ArchFlags, T.getArchName())) {
  489. error("no architecture specified", Filename);
  490. return false;
  491. }
  492. return true;
  493. }
  494. /// Print the section sizes for @p file. If @p file is an archive, print the
  495. /// section sizes for each archive member.
  496. static void printFileSectionSizes(StringRef file) {
  497. // Attempt to open the binary.
  498. Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
  499. if (!BinaryOrErr) {
  500. error(BinaryOrErr.takeError(), file);
  501. return;
  502. }
  503. Binary &Bin = *BinaryOrErr.get().getBinary();
  504. if (Archive *a = dyn_cast<Archive>(&Bin)) {
  505. // This is an archive. Iterate over each member and display its sizes.
  506. Error Err = Error::success();
  507. for (auto &C : a->children(Err)) {
  508. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  509. if (!ChildOrErr) {
  510. if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
  511. error(std::move(E), a->getFileName(), C);
  512. continue;
  513. }
  514. if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
  515. MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
  516. if (!checkMachOAndArchFlags(o, file))
  517. return;
  518. if (OutputFormat == sysv)
  519. outs() << o->getFileName() << " (ex " << a->getFileName() << "):\n";
  520. else if (MachO && OutputFormat == darwin)
  521. outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
  522. printObjectSectionSizes(o);
  523. if (!MachO && OutputFormat == darwin)
  524. outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
  525. if (OutputFormat == berkeley) {
  526. if (MachO)
  527. outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
  528. else
  529. outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
  530. }
  531. }
  532. }
  533. if (Err)
  534. error(std::move(Err), a->getFileName());
  535. } else if (MachOUniversalBinary *UB =
  536. dyn_cast<MachOUniversalBinary>(&Bin)) {
  537. // If we have a list of architecture flags specified dump only those.
  538. if (!ArchAll && !ArchFlags.empty()) {
  539. // Look for a slice in the universal binary that matches each ArchFlag.
  540. bool ArchFound;
  541. for (unsigned i = 0; i < ArchFlags.size(); ++i) {
  542. ArchFound = false;
  543. for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
  544. E = UB->end_objects();
  545. I != E; ++I) {
  546. if (ArchFlags[i] == I->getArchFlagName()) {
  547. ArchFound = true;
  548. Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
  549. if (UO) {
  550. if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
  551. MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
  552. if (OutputFormat == sysv)
  553. outs() << o->getFileName() << " :\n";
  554. else if (MachO && OutputFormat == darwin) {
  555. if (MoreThanOneFile || ArchFlags.size() > 1)
  556. outs() << o->getFileName() << " (for architecture "
  557. << I->getArchFlagName() << "): \n";
  558. }
  559. printObjectSectionSizes(o);
  560. if (OutputFormat == berkeley) {
  561. if (!MachO || MoreThanOneFile || ArchFlags.size() > 1)
  562. outs() << o->getFileName() << " (for architecture "
  563. << I->getArchFlagName() << ")";
  564. outs() << "\n";
  565. }
  566. }
  567. } else if (auto E = isNotObjectErrorInvalidFileType(
  568. UO.takeError())) {
  569. error(std::move(E), file, ArchFlags.size() > 1 ?
  570. StringRef(I->getArchFlagName()) : StringRef());
  571. return;
  572. } else if (Expected<std::unique_ptr<Archive>> AOrErr =
  573. I->getAsArchive()) {
  574. std::unique_ptr<Archive> &UA = *AOrErr;
  575. // This is an archive. Iterate over each member and display its
  576. // sizes.
  577. Error Err = Error::success();
  578. for (auto &C : UA->children(Err)) {
  579. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  580. if (!ChildOrErr) {
  581. if (auto E = isNotObjectErrorInvalidFileType(
  582. ChildOrErr.takeError()))
  583. error(std::move(E), UA->getFileName(), C,
  584. ArchFlags.size() > 1 ?
  585. StringRef(I->getArchFlagName()) : StringRef());
  586. continue;
  587. }
  588. if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
  589. MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
  590. if (OutputFormat == sysv)
  591. outs() << o->getFileName() << " (ex " << UA->getFileName()
  592. << "):\n";
  593. else if (MachO && OutputFormat == darwin)
  594. outs() << UA->getFileName() << "(" << o->getFileName()
  595. << ")"
  596. << " (for architecture " << I->getArchFlagName()
  597. << "):\n";
  598. printObjectSectionSizes(o);
  599. if (OutputFormat == berkeley) {
  600. if (MachO) {
  601. outs() << UA->getFileName() << "(" << o->getFileName()
  602. << ")";
  603. if (ArchFlags.size() > 1)
  604. outs() << " (for architecture " << I->getArchFlagName()
  605. << ")";
  606. outs() << "\n";
  607. } else
  608. outs() << o->getFileName() << " (ex " << UA->getFileName()
  609. << ")\n";
  610. }
  611. }
  612. }
  613. if (Err)
  614. error(std::move(Err), UA->getFileName());
  615. } else {
  616. consumeError(AOrErr.takeError());
  617. error("mach-o universal file for architecture " +
  618. StringRef(I->getArchFlagName()) +
  619. " is not a mach-o file or an archive file",
  620. file);
  621. }
  622. }
  623. }
  624. if (!ArchFound) {
  625. error("file does not contain architecture " + ArchFlags[i], file);
  626. return;
  627. }
  628. }
  629. return;
  630. }
  631. // No architecture flags were specified so if this contains a slice that
  632. // matches the host architecture dump only that.
  633. if (!ArchAll) {
  634. StringRef HostArchName = MachOObjectFile::getHostArch().getArchName();
  635. for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
  636. E = UB->end_objects();
  637. I != E; ++I) {
  638. if (HostArchName == I->getArchFlagName()) {
  639. Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
  640. if (UO) {
  641. if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
  642. MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
  643. if (OutputFormat == sysv)
  644. outs() << o->getFileName() << " :\n";
  645. else if (MachO && OutputFormat == darwin) {
  646. if (MoreThanOneFile)
  647. outs() << o->getFileName() << " (for architecture "
  648. << I->getArchFlagName() << "):\n";
  649. }
  650. printObjectSectionSizes(o);
  651. if (OutputFormat == berkeley) {
  652. if (!MachO || MoreThanOneFile)
  653. outs() << o->getFileName() << " (for architecture "
  654. << I->getArchFlagName() << ")";
  655. outs() << "\n";
  656. }
  657. }
  658. } else if (auto E = isNotObjectErrorInvalidFileType(UO.takeError())) {
  659. error(std::move(E), file);
  660. return;
  661. } else if (Expected<std::unique_ptr<Archive>> AOrErr =
  662. I->getAsArchive()) {
  663. std::unique_ptr<Archive> &UA = *AOrErr;
  664. // This is an archive. Iterate over each member and display its
  665. // sizes.
  666. Error Err = Error::success();
  667. for (auto &C : UA->children(Err)) {
  668. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  669. if (!ChildOrErr) {
  670. if (auto E = isNotObjectErrorInvalidFileType(
  671. ChildOrErr.takeError()))
  672. error(std::move(E), UA->getFileName(), C);
  673. continue;
  674. }
  675. if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
  676. MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
  677. if (OutputFormat == sysv)
  678. outs() << o->getFileName() << " (ex " << UA->getFileName()
  679. << "):\n";
  680. else if (MachO && OutputFormat == darwin)
  681. outs() << UA->getFileName() << "(" << o->getFileName() << ")"
  682. << " (for architecture " << I->getArchFlagName()
  683. << "):\n";
  684. printObjectSectionSizes(o);
  685. if (OutputFormat == berkeley) {
  686. if (MachO)
  687. outs() << UA->getFileName() << "(" << o->getFileName()
  688. << ")\n";
  689. else
  690. outs() << o->getFileName() << " (ex " << UA->getFileName()
  691. << ")\n";
  692. }
  693. }
  694. }
  695. if (Err)
  696. error(std::move(Err), UA->getFileName());
  697. } else {
  698. consumeError(AOrErr.takeError());
  699. error("mach-o universal file for architecture " +
  700. StringRef(I->getArchFlagName()) +
  701. " is not a mach-o file or an archive file",
  702. file);
  703. }
  704. return;
  705. }
  706. }
  707. }
  708. // Either all architectures have been specified or none have been specified
  709. // and this does not contain the host architecture so dump all the slices.
  710. bool MoreThanOneArch = UB->getNumberOfObjects() > 1;
  711. for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
  712. E = UB->end_objects();
  713. I != E; ++I) {
  714. Expected<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
  715. if (UO) {
  716. if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
  717. MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
  718. if (OutputFormat == sysv)
  719. outs() << o->getFileName() << " :\n";
  720. else if (MachO && OutputFormat == darwin) {
  721. if (MoreThanOneFile || MoreThanOneArch)
  722. outs() << o->getFileName() << " (for architecture "
  723. << I->getArchFlagName() << "):";
  724. outs() << "\n";
  725. }
  726. printObjectSectionSizes(o);
  727. if (OutputFormat == berkeley) {
  728. if (!MachO || MoreThanOneFile || MoreThanOneArch)
  729. outs() << o->getFileName() << " (for architecture "
  730. << I->getArchFlagName() << ")";
  731. outs() << "\n";
  732. }
  733. }
  734. } else if (auto E = isNotObjectErrorInvalidFileType(UO.takeError())) {
  735. error(std::move(E), file, MoreThanOneArch ?
  736. StringRef(I->getArchFlagName()) : StringRef());
  737. return;
  738. } else if (Expected<std::unique_ptr<Archive>> AOrErr =
  739. I->getAsArchive()) {
  740. std::unique_ptr<Archive> &UA = *AOrErr;
  741. // This is an archive. Iterate over each member and display its sizes.
  742. Error Err = Error::success();
  743. for (auto &C : UA->children(Err)) {
  744. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  745. if (!ChildOrErr) {
  746. if (auto E = isNotObjectErrorInvalidFileType(
  747. ChildOrErr.takeError()))
  748. error(std::move(E), UA->getFileName(), C, MoreThanOneArch ?
  749. StringRef(I->getArchFlagName()) : StringRef());
  750. continue;
  751. }
  752. if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
  753. MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
  754. if (OutputFormat == sysv)
  755. outs() << o->getFileName() << " (ex " << UA->getFileName()
  756. << "):\n";
  757. else if (MachO && OutputFormat == darwin)
  758. outs() << UA->getFileName() << "(" << o->getFileName() << ")"
  759. << " (for architecture " << I->getArchFlagName() << "):\n";
  760. printObjectSectionSizes(o);
  761. if (OutputFormat == berkeley) {
  762. if (MachO)
  763. outs() << UA->getFileName() << "(" << o->getFileName() << ")"
  764. << " (for architecture " << I->getArchFlagName()
  765. << ")\n";
  766. else
  767. outs() << o->getFileName() << " (ex " << UA->getFileName()
  768. << ")\n";
  769. }
  770. }
  771. }
  772. if (Err)
  773. error(std::move(Err), UA->getFileName());
  774. } else {
  775. consumeError(AOrErr.takeError());
  776. error("mach-o universal file for architecture " +
  777. StringRef(I->getArchFlagName()) +
  778. " is not a mach-o file or an archive file",
  779. file);
  780. }
  781. }
  782. } else if (ObjectFile *o = dyn_cast<ObjectFile>(&Bin)) {
  783. if (!checkMachOAndArchFlags(o, file))
  784. return;
  785. MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
  786. if (OutputFormat == sysv)
  787. outs() << o->getFileName() << " :\n";
  788. else if (MachO && OutputFormat == darwin && MoreThanOneFile)
  789. outs() << o->getFileName() << ":\n";
  790. printObjectSectionSizes(o);
  791. if (!MachO && OutputFormat == darwin)
  792. outs() << o->getFileName() << "\n";
  793. if (OutputFormat == berkeley) {
  794. if (!MachO || MoreThanOneFile)
  795. outs() << o->getFileName();
  796. outs() << "\n";
  797. }
  798. } else {
  799. error("unsupported file type", file);
  800. }
  801. }
  802. static void printBerkeleyTotals() {
  803. std::string fmtbuf;
  804. raw_string_ostream fmt(fmtbuf);
  805. const char *radix_fmt = getRadixFmt();
  806. fmt << "%#7" << radix_fmt << "\t"
  807. << "%#7" << radix_fmt << "\t"
  808. << "%#7" << radix_fmt << "\t";
  809. outs() << format(fmt.str().c_str(), TotalObjectText, TotalObjectData,
  810. TotalObjectBss);
  811. fmtbuf.clear();
  812. fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << "\t"
  813. << "%7" PRIx64 "\t";
  814. outs() << format(fmt.str().c_str(), TotalObjectTotal, TotalObjectTotal)
  815. << "(TOTALS)\n";
  816. }
  817. int llvm_size_main(int argc, char **argv) {
  818. InitLLVM X(argc, argv);
  819. BumpPtrAllocator A;
  820. StringSaver Saver(A);
  821. SizeOptTable Tbl;
  822. ToolName = argv[0];
  823. opt::InputArgList Args =
  824. Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
  825. error(Msg);
  826. exit(1);
  827. });
  828. if (Args.hasArg(OPT_help)) {
  829. Tbl.printHelp(
  830. outs(),
  831. (Twine(ToolName) + " [options] <input object files>").str().c_str(),
  832. "LLVM object size dumper");
  833. // TODO Replace this with OptTable API once it adds extrahelp support.
  834. outs() << "\nPass @FILE as argument to read options from FILE.\n";
  835. return 0;
  836. }
  837. if (Args.hasArg(OPT_version)) {
  838. outs() << ToolName << '\n';
  839. cl::PrintVersionMessage();
  840. return 0;
  841. }
  842. ELFCommons = Args.hasArg(OPT_common);
  843. DarwinLongFormat = Args.hasArg(OPT_l);
  844. TotalSizes = Args.hasArg(OPT_totals);
  845. StringRef V = Args.getLastArgValue(OPT_format_EQ, "berkeley");
  846. if (V == "berkeley")
  847. OutputFormat = berkeley;
  848. else if (V == "darwin")
  849. OutputFormat = darwin;
  850. else if (V == "sysv")
  851. OutputFormat = sysv;
  852. else
  853. error("--format value should be one of: 'berkeley', 'darwin', 'sysv'");
  854. V = Args.getLastArgValue(OPT_radix_EQ, "10");
  855. if (V == "8")
  856. Radix = RadixTy::octal;
  857. else if (V == "10")
  858. Radix = RadixTy::decimal;
  859. else if (V == "16")
  860. Radix = RadixTy::hexadecimal;
  861. else
  862. error("--radix value should be one of: 8, 10, 16 ");
  863. for (const auto *A : Args.filtered(OPT_arch_EQ)) {
  864. SmallVector<StringRef, 2> Values;
  865. llvm::SplitString(A->getValue(), Values, ",");
  866. for (StringRef V : Values) {
  867. if (V == "all")
  868. ArchAll = true;
  869. else if (MachOObjectFile::isValidArch(V))
  870. ArchFlags.push_back(V);
  871. else {
  872. outs() << ToolName << ": for the -arch option: Unknown architecture "
  873. << "named '" << V << "'";
  874. return 1;
  875. }
  876. }
  877. }
  878. InputFilenames = Args.getAllArgValues(OPT_INPUT);
  879. if (InputFilenames.empty())
  880. InputFilenames.push_back("a.out");
  881. MoreThanOneFile = InputFilenames.size() > 1;
  882. llvm::for_each(InputFilenames, printFileSectionSizes);
  883. if (OutputFormat == berkeley && TotalSizes)
  884. printBerkeleyTotals();
  885. if (HadError)
  886. return 1;
  887. return 0;
  888. }