llvm-size.cpp 28 KB

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