llvm-readobj.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. //===- llvm-readobj.cpp - Dump contents of an Object File -----------------===//
  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 is a tool similar to readelf, except it works on multiple object file
  10. // formats. The main purpose of this tool is to provide detailed output suitable
  11. // for FileCheck.
  12. //
  13. // Flags should be similar to readelf where supported, but the output format
  14. // does not need to be identical. The point is to not make users learn yet
  15. // another set of flags.
  16. //
  17. // Output should be specialized for each format where appropriate.
  18. //
  19. //===----------------------------------------------------------------------===//
  20. #include "llvm-readobj.h"
  21. #include "ObjDumper.h"
  22. #include "WindowsResourceDumper.h"
  23. #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
  24. #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
  25. #include "llvm/MC/TargetRegistry.h"
  26. #include "llvm/Object/Archive.h"
  27. #include "llvm/Object/COFFImportFile.h"
  28. #include "llvm/Object/ELFObjectFile.h"
  29. #include "llvm/Object/MachOUniversal.h"
  30. #include "llvm/Object/ObjectFile.h"
  31. #include "llvm/Object/Wasm.h"
  32. #include "llvm/Object/WindowsResource.h"
  33. #include "llvm/Object/XCOFFObjectFile.h"
  34. #include "llvm/Option/Arg.h"
  35. #include "llvm/Option/ArgList.h"
  36. #include "llvm/Option/Option.h"
  37. #include "llvm/Support/Casting.h"
  38. #include "llvm/Support/CommandLine.h"
  39. #include "llvm/Support/DataTypes.h"
  40. #include "llvm/Support/Debug.h"
  41. #include "llvm/Support/Errc.h"
  42. #include "llvm/Support/FileSystem.h"
  43. #include "llvm/Support/FormatVariadic.h"
  44. #include "llvm/Support/InitLLVM.h"
  45. #include "llvm/Support/Path.h"
  46. #include "llvm/Support/ScopedPrinter.h"
  47. #include "llvm/Support/WithColor.h"
  48. using namespace llvm;
  49. using namespace llvm::object;
  50. namespace {
  51. using namespace llvm::opt; // for HelpHidden in Opts.inc
  52. enum ID {
  53. OPT_INVALID = 0, // This is not an option ID.
  54. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  55. HELPTEXT, METAVAR, VALUES) \
  56. OPT_##ID,
  57. #include "Opts.inc"
  58. #undef OPTION
  59. };
  60. #define PREFIX(NAME, VALUE) \
  61. static constexpr StringLiteral NAME##_init[] = VALUE; \
  62. static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
  63. std::size(NAME##_init) - 1);
  64. #include "Opts.inc"
  65. #undef PREFIX
  66. static constexpr opt::OptTable::Info InfoTable[] = {
  67. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  68. HELPTEXT, METAVAR, VALUES) \
  69. { \
  70. PREFIX, NAME, HELPTEXT, \
  71. METAVAR, OPT_##ID, opt::Option::KIND##Class, \
  72. PARAM, FLAGS, OPT_##GROUP, \
  73. OPT_##ALIAS, ALIASARGS, VALUES},
  74. #include "Opts.inc"
  75. #undef OPTION
  76. };
  77. class ReadobjOptTable : public opt::GenericOptTable {
  78. public:
  79. ReadobjOptTable() : opt::GenericOptTable(InfoTable) {
  80. setGroupedShortOptions(true);
  81. }
  82. };
  83. enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
  84. enum SortSymbolKeyTy {
  85. NAME = 0,
  86. TYPE = 1,
  87. UNKNOWN = 100,
  88. // TODO: add ADDRESS, SIZE as needed.
  89. };
  90. } // namespace
  91. namespace opts {
  92. static bool Addrsig;
  93. static bool All;
  94. static bool ArchSpecificInfo;
  95. static bool BBAddrMap;
  96. bool ExpandRelocs;
  97. static bool CGProfile;
  98. bool Demangle;
  99. static bool DependentLibraries;
  100. static bool DynRelocs;
  101. static bool DynamicSymbols;
  102. static bool FileHeaders;
  103. static bool Headers;
  104. static std::vector<std::string> HexDump;
  105. static bool PrettyPrint;
  106. static bool PrintStackMap;
  107. static bool PrintStackSizes;
  108. static bool Relocations;
  109. bool SectionData;
  110. static bool SectionDetails;
  111. static bool SectionHeaders;
  112. bool SectionRelocations;
  113. bool SectionSymbols;
  114. static std::vector<std::string> StringDump;
  115. static bool StringTable;
  116. static bool Symbols;
  117. static bool UnwindInfo;
  118. static cl::boolOrDefault SectionMapping;
  119. static SmallVector<SortSymbolKeyTy> SortKeys;
  120. // ELF specific options.
  121. static bool DynamicTable;
  122. static bool ELFLinkerOptions;
  123. static bool GnuHashTable;
  124. static bool HashSymbols;
  125. static bool HashTable;
  126. static bool HashHistogram;
  127. static bool NeededLibraries;
  128. static bool Notes;
  129. static bool ProgramHeaders;
  130. bool RawRelr;
  131. static bool SectionGroups;
  132. static bool VersionInfo;
  133. // Mach-O specific options.
  134. static bool MachODataInCode;
  135. static bool MachODysymtab;
  136. static bool MachOIndirectSymbols;
  137. static bool MachOLinkerOptions;
  138. static bool MachOSegment;
  139. static bool MachOVersionMin;
  140. // PE/COFF specific options.
  141. static bool CodeView;
  142. static bool CodeViewEnableGHash;
  143. static bool CodeViewMergedTypes;
  144. bool CodeViewSubsectionBytes;
  145. static bool COFFBaseRelocs;
  146. static bool COFFDebugDirectory;
  147. static bool COFFDirectives;
  148. static bool COFFExports;
  149. static bool COFFImports;
  150. static bool COFFLoadConfig;
  151. static bool COFFResources;
  152. static bool COFFTLSDirectory;
  153. // XCOFF specific options.
  154. static bool XCOFFAuxiliaryHeader;
  155. static bool XCOFFLoaderSectionHeader;
  156. static bool XCOFFLoaderSectionSymbol;
  157. static bool XCOFFLoaderSectionRelocation;
  158. static bool XCOFFExceptionSection;
  159. OutputStyleTy Output = OutputStyleTy::LLVM;
  160. static std::vector<std::string> InputFilenames;
  161. } // namespace opts
  162. static StringRef ToolName;
  163. namespace llvm {
  164. [[noreturn]] static void error(Twine Msg) {
  165. // Flush the standard output to print the error at a
  166. // proper place.
  167. fouts().flush();
  168. WithColor::error(errs(), ToolName) << Msg << "\n";
  169. exit(1);
  170. }
  171. [[noreturn]] void reportError(Error Err, StringRef Input) {
  172. assert(Err);
  173. if (Input == "-")
  174. Input = "<stdin>";
  175. handleAllErrors(createFileError(Input, std::move(Err)),
  176. [&](const ErrorInfoBase &EI) { error(EI.message()); });
  177. llvm_unreachable("error() call should never return");
  178. }
  179. void reportWarning(Error Err, StringRef Input) {
  180. assert(Err);
  181. if (Input == "-")
  182. Input = "<stdin>";
  183. // Flush the standard output to print the warning at a
  184. // proper place.
  185. fouts().flush();
  186. handleAllErrors(
  187. createFileError(Input, std::move(Err)), [&](const ErrorInfoBase &EI) {
  188. WithColor::warning(errs(), ToolName) << EI.message() << "\n";
  189. });
  190. }
  191. } // namespace llvm
  192. static void parseOptions(const opt::InputArgList &Args) {
  193. opts::Addrsig = Args.hasArg(OPT_addrsig);
  194. opts::All = Args.hasArg(OPT_all);
  195. opts::ArchSpecificInfo = Args.hasArg(OPT_arch_specific);
  196. opts::BBAddrMap = Args.hasArg(OPT_bb_addr_map);
  197. opts::CGProfile = Args.hasArg(OPT_cg_profile);
  198. opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
  199. opts::DependentLibraries = Args.hasArg(OPT_dependent_libraries);
  200. opts::DynRelocs = Args.hasArg(OPT_dyn_relocations);
  201. opts::DynamicSymbols = Args.hasArg(OPT_dyn_syms);
  202. opts::ExpandRelocs = Args.hasArg(OPT_expand_relocs);
  203. opts::FileHeaders = Args.hasArg(OPT_file_header);
  204. opts::Headers = Args.hasArg(OPT_headers);
  205. opts::HexDump = Args.getAllArgValues(OPT_hex_dump_EQ);
  206. opts::Relocations = Args.hasArg(OPT_relocs);
  207. opts::SectionData = Args.hasArg(OPT_section_data);
  208. opts::SectionDetails = Args.hasArg(OPT_section_details);
  209. opts::SectionHeaders = Args.hasArg(OPT_section_headers);
  210. opts::SectionRelocations = Args.hasArg(OPT_section_relocations);
  211. opts::SectionSymbols = Args.hasArg(OPT_section_symbols);
  212. if (Args.hasArg(OPT_section_mapping))
  213. opts::SectionMapping = cl::BOU_TRUE;
  214. else if (Args.hasArg(OPT_section_mapping_EQ_false))
  215. opts::SectionMapping = cl::BOU_FALSE;
  216. else
  217. opts::SectionMapping = cl::BOU_UNSET;
  218. opts::PrintStackSizes = Args.hasArg(OPT_stack_sizes);
  219. opts::PrintStackMap = Args.hasArg(OPT_stackmap);
  220. opts::StringDump = Args.getAllArgValues(OPT_string_dump_EQ);
  221. opts::StringTable = Args.hasArg(OPT_string_table);
  222. opts::Symbols = Args.hasArg(OPT_symbols);
  223. opts::UnwindInfo = Args.hasArg(OPT_unwind);
  224. // ELF specific options.
  225. opts::DynamicTable = Args.hasArg(OPT_dynamic_table);
  226. opts::ELFLinkerOptions = Args.hasArg(OPT_elf_linker_options);
  227. if (Arg *A = Args.getLastArg(OPT_elf_output_style_EQ)) {
  228. std::string OutputStyleChoice = A->getValue();
  229. opts::Output = StringSwitch<opts::OutputStyleTy>(OutputStyleChoice)
  230. .Case("LLVM", opts::OutputStyleTy::LLVM)
  231. .Case("GNU", opts::OutputStyleTy::GNU)
  232. .Case("JSON", opts::OutputStyleTy::JSON)
  233. .Default(opts::OutputStyleTy::UNKNOWN);
  234. if (opts::Output == opts::OutputStyleTy::UNKNOWN) {
  235. error("--elf-output-style value should be either 'LLVM', 'GNU', or "
  236. "'JSON', but was '" +
  237. OutputStyleChoice + "'");
  238. }
  239. }
  240. opts::GnuHashTable = Args.hasArg(OPT_gnu_hash_table);
  241. opts::HashSymbols = Args.hasArg(OPT_hash_symbols);
  242. opts::HashTable = Args.hasArg(OPT_hash_table);
  243. opts::HashHistogram = Args.hasArg(OPT_histogram);
  244. opts::NeededLibraries = Args.hasArg(OPT_needed_libs);
  245. opts::Notes = Args.hasArg(OPT_notes);
  246. opts::PrettyPrint = Args.hasArg(OPT_pretty_print);
  247. opts::ProgramHeaders = Args.hasArg(OPT_program_headers);
  248. opts::RawRelr = Args.hasArg(OPT_raw_relr);
  249. opts::SectionGroups = Args.hasArg(OPT_section_groups);
  250. if (Arg *A = Args.getLastArg(OPT_sort_symbols_EQ)) {
  251. std::string SortKeysString = A->getValue();
  252. for (StringRef KeyStr : llvm::split(A->getValue(), ",")) {
  253. SortSymbolKeyTy KeyType = StringSwitch<SortSymbolKeyTy>(KeyStr)
  254. .Case("name", SortSymbolKeyTy::NAME)
  255. .Case("type", SortSymbolKeyTy::TYPE)
  256. .Default(SortSymbolKeyTy::UNKNOWN);
  257. if (KeyType == SortSymbolKeyTy::UNKNOWN)
  258. error("--sort-symbols value should be 'name' or 'type', but was '" +
  259. Twine(KeyStr) + "'");
  260. opts::SortKeys.push_back(KeyType);
  261. }
  262. }
  263. opts::VersionInfo = Args.hasArg(OPT_version_info);
  264. // Mach-O specific options.
  265. opts::MachODataInCode = Args.hasArg(OPT_macho_data_in_code);
  266. opts::MachODysymtab = Args.hasArg(OPT_macho_dysymtab);
  267. opts::MachOIndirectSymbols = Args.hasArg(OPT_macho_indirect_symbols);
  268. opts::MachOLinkerOptions = Args.hasArg(OPT_macho_linker_options);
  269. opts::MachOSegment = Args.hasArg(OPT_macho_segment);
  270. opts::MachOVersionMin = Args.hasArg(OPT_macho_version_min);
  271. // PE/COFF specific options.
  272. opts::CodeView = Args.hasArg(OPT_codeview);
  273. opts::CodeViewEnableGHash = Args.hasArg(OPT_codeview_ghash);
  274. opts::CodeViewMergedTypes = Args.hasArg(OPT_codeview_merged_types);
  275. opts::CodeViewSubsectionBytes = Args.hasArg(OPT_codeview_subsection_bytes);
  276. opts::COFFBaseRelocs = Args.hasArg(OPT_coff_basereloc);
  277. opts::COFFDebugDirectory = Args.hasArg(OPT_coff_debug_directory);
  278. opts::COFFDirectives = Args.hasArg(OPT_coff_directives);
  279. opts::COFFExports = Args.hasArg(OPT_coff_exports);
  280. opts::COFFImports = Args.hasArg(OPT_coff_imports);
  281. opts::COFFLoadConfig = Args.hasArg(OPT_coff_load_config);
  282. opts::COFFResources = Args.hasArg(OPT_coff_resources);
  283. opts::COFFTLSDirectory = Args.hasArg(OPT_coff_tls_directory);
  284. // XCOFF specific options.
  285. opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header);
  286. opts::XCOFFLoaderSectionHeader = Args.hasArg(OPT_loader_section_header);
  287. opts::XCOFFLoaderSectionSymbol = Args.hasArg(OPT_loader_section_symbols);
  288. opts::XCOFFLoaderSectionRelocation =
  289. Args.hasArg(OPT_loader_section_relocations);
  290. opts::XCOFFExceptionSection = Args.hasArg(OPT_exception_section);
  291. opts::InputFilenames = Args.getAllArgValues(OPT_INPUT);
  292. }
  293. namespace {
  294. struct ReadObjTypeTableBuilder {
  295. ReadObjTypeTableBuilder()
  296. : IDTable(Allocator), TypeTable(Allocator), GlobalIDTable(Allocator),
  297. GlobalTypeTable(Allocator) {}
  298. llvm::BumpPtrAllocator Allocator;
  299. llvm::codeview::MergingTypeTableBuilder IDTable;
  300. llvm::codeview::MergingTypeTableBuilder TypeTable;
  301. llvm::codeview::GlobalTypeTableBuilder GlobalIDTable;
  302. llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable;
  303. std::vector<OwningBinary<Binary>> Binaries;
  304. };
  305. } // namespace
  306. static ReadObjTypeTableBuilder CVTypes;
  307. /// Creates an format-specific object file dumper.
  308. static Expected<std::unique_ptr<ObjDumper>>
  309. createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) {
  310. if (const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(&Obj))
  311. return createCOFFDumper(*COFFObj, Writer);
  312. if (const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
  313. return createELFDumper(*ELFObj, Writer);
  314. if (const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(&Obj))
  315. return createMachODumper(*MachOObj, Writer);
  316. if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj))
  317. return createWasmDumper(*WasmObj, Writer);
  318. if (const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(&Obj))
  319. return createXCOFFDumper(*XObj, Writer);
  320. return createStringError(errc::invalid_argument,
  321. "unsupported object file format");
  322. }
  323. /// Dumps the specified object file.
  324. static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
  325. const Archive *A = nullptr) {
  326. std::string FileStr =
  327. A ? Twine(A->getFileName() + "(" + Obj.getFileName() + ")").str()
  328. : Obj.getFileName().str();
  329. std::string ContentErrString;
  330. if (Error ContentErr = Obj.initContent())
  331. ContentErrString = "unable to continue dumping, the file is corrupt: " +
  332. toString(std::move(ContentErr));
  333. ObjDumper *Dumper;
  334. std::optional<SymbolComparator> SymComp;
  335. Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer);
  336. if (!DumperOrErr)
  337. reportError(DumperOrErr.takeError(), FileStr);
  338. Dumper = (*DumperOrErr).get();
  339. if (!opts::SortKeys.empty()) {
  340. if (Dumper->canCompareSymbols()) {
  341. SymComp = SymbolComparator();
  342. for (SortSymbolKeyTy Key : opts::SortKeys) {
  343. switch (Key) {
  344. case NAME:
  345. SymComp->addPredicate([Dumper](SymbolRef LHS, SymbolRef RHS) {
  346. return Dumper->compareSymbolsByName(LHS, RHS);
  347. });
  348. break;
  349. case TYPE:
  350. SymComp->addPredicate([Dumper](SymbolRef LHS, SymbolRef RHS) {
  351. return Dumper->compareSymbolsByType(LHS, RHS);
  352. });
  353. break;
  354. case UNKNOWN:
  355. llvm_unreachable("Unsupported sort key");
  356. }
  357. }
  358. } else {
  359. reportWarning(createStringError(
  360. errc::invalid_argument,
  361. "--sort-symbols is not supported yet for this format"),
  362. FileStr);
  363. }
  364. }
  365. Dumper->printFileSummary(FileStr, Obj, opts::InputFilenames, A);
  366. if (opts::FileHeaders)
  367. Dumper->printFileHeaders();
  368. // Auxiliary header in XOCFF is right after the file header, so print the data
  369. // here.
  370. if (Obj.isXCOFF() && opts::XCOFFAuxiliaryHeader)
  371. Dumper->printAuxiliaryHeader();
  372. // This is only used for ELF currently. In some cases, when an object is
  373. // corrupt (e.g. truncated), we can't dump anything except the file header.
  374. if (!ContentErrString.empty())
  375. reportError(createError(ContentErrString), FileStr);
  376. if (opts::SectionDetails || opts::SectionHeaders) {
  377. if (opts::Output == opts::GNU && opts::SectionDetails)
  378. Dumper->printSectionDetails();
  379. else
  380. Dumper->printSectionHeaders();
  381. }
  382. if (opts::HashSymbols)
  383. Dumper->printHashSymbols();
  384. if (opts::ProgramHeaders || opts::SectionMapping == cl::BOU_TRUE)
  385. Dumper->printProgramHeaders(opts::ProgramHeaders, opts::SectionMapping);
  386. if (opts::DynamicTable)
  387. Dumper->printDynamicTable();
  388. if (opts::NeededLibraries)
  389. Dumper->printNeededLibraries();
  390. if (opts::Relocations)
  391. Dumper->printRelocations();
  392. if (opts::DynRelocs)
  393. Dumper->printDynamicRelocations();
  394. if (opts::UnwindInfo)
  395. Dumper->printUnwindInfo();
  396. if (opts::Symbols || opts::DynamicSymbols)
  397. Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols, SymComp);
  398. if (!opts::StringDump.empty())
  399. Dumper->printSectionsAsString(Obj, opts::StringDump);
  400. if (!opts::HexDump.empty())
  401. Dumper->printSectionsAsHex(Obj, opts::HexDump);
  402. if (opts::HashTable)
  403. Dumper->printHashTable();
  404. if (opts::GnuHashTable)
  405. Dumper->printGnuHashTable();
  406. if (opts::VersionInfo)
  407. Dumper->printVersionInfo();
  408. if (opts::StringTable)
  409. Dumper->printStringTable();
  410. if (Obj.isELF()) {
  411. if (opts::DependentLibraries)
  412. Dumper->printDependentLibs();
  413. if (opts::ELFLinkerOptions)
  414. Dumper->printELFLinkerOptions();
  415. if (opts::ArchSpecificInfo)
  416. Dumper->printArchSpecificInfo();
  417. if (opts::SectionGroups)
  418. Dumper->printGroupSections();
  419. if (opts::HashHistogram)
  420. Dumper->printHashHistograms();
  421. if (opts::CGProfile)
  422. Dumper->printCGProfile();
  423. if (opts::BBAddrMap)
  424. Dumper->printBBAddrMaps();
  425. if (opts::Addrsig)
  426. Dumper->printAddrsig();
  427. if (opts::Notes)
  428. Dumper->printNotes();
  429. }
  430. if (Obj.isCOFF()) {
  431. if (opts::COFFImports)
  432. Dumper->printCOFFImports();
  433. if (opts::COFFExports)
  434. Dumper->printCOFFExports();
  435. if (opts::COFFDirectives)
  436. Dumper->printCOFFDirectives();
  437. if (opts::COFFBaseRelocs)
  438. Dumper->printCOFFBaseReloc();
  439. if (opts::COFFDebugDirectory)
  440. Dumper->printCOFFDebugDirectory();
  441. if (opts::COFFTLSDirectory)
  442. Dumper->printCOFFTLSDirectory();
  443. if (opts::COFFResources)
  444. Dumper->printCOFFResources();
  445. if (opts::COFFLoadConfig)
  446. Dumper->printCOFFLoadConfig();
  447. if (opts::CGProfile)
  448. Dumper->printCGProfile();
  449. if (opts::Addrsig)
  450. Dumper->printAddrsig();
  451. if (opts::CodeView)
  452. Dumper->printCodeViewDebugInfo();
  453. if (opts::CodeViewMergedTypes)
  454. Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable,
  455. CVTypes.GlobalIDTable, CVTypes.GlobalTypeTable,
  456. opts::CodeViewEnableGHash);
  457. }
  458. if (Obj.isMachO()) {
  459. if (opts::MachODataInCode)
  460. Dumper->printMachODataInCode();
  461. if (opts::MachOIndirectSymbols)
  462. Dumper->printMachOIndirectSymbols();
  463. if (opts::MachOLinkerOptions)
  464. Dumper->printMachOLinkerOptions();
  465. if (opts::MachOSegment)
  466. Dumper->printMachOSegment();
  467. if (opts::MachOVersionMin)
  468. Dumper->printMachOVersionMin();
  469. if (opts::MachODysymtab)
  470. Dumper->printMachODysymtab();
  471. if (opts::CGProfile)
  472. Dumper->printCGProfile();
  473. }
  474. if (Obj.isXCOFF()) {
  475. if (opts::XCOFFLoaderSectionHeader || opts::XCOFFLoaderSectionSymbol ||
  476. opts::XCOFFLoaderSectionRelocation)
  477. Dumper->printLoaderSection(opts::XCOFFLoaderSectionHeader,
  478. opts::XCOFFLoaderSectionSymbol,
  479. opts::XCOFFLoaderSectionRelocation);
  480. if (opts::XCOFFExceptionSection)
  481. Dumper->printExceptionSection();
  482. }
  483. if (opts::PrintStackMap)
  484. Dumper->printStackMap();
  485. if (opts::PrintStackSizes)
  486. Dumper->printStackSizes();
  487. }
  488. /// Dumps each object file in \a Arc;
  489. static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) {
  490. Error Err = Error::success();
  491. for (auto &Child : Arc->children(Err)) {
  492. Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
  493. if (!ChildOrErr) {
  494. if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
  495. reportError(std::move(E), Arc->getFileName());
  496. continue;
  497. }
  498. Binary *Bin = ChildOrErr->get();
  499. if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin))
  500. dumpObject(*Obj, Writer, Arc);
  501. else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(Bin))
  502. dumpCOFFImportFile(Imp, Writer);
  503. else
  504. reportWarning(createStringError(errc::invalid_argument,
  505. Bin->getFileName() +
  506. " has an unsupported file type"),
  507. Arc->getFileName());
  508. }
  509. if (Err)
  510. reportError(std::move(Err), Arc->getFileName());
  511. }
  512. /// Dumps each object file in \a MachO Universal Binary;
  513. static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
  514. ScopedPrinter &Writer) {
  515. for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) {
  516. Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile();
  517. if (ObjOrErr)
  518. dumpObject(*ObjOrErr.get(), Writer);
  519. else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
  520. reportError(ObjOrErr.takeError(), UBinary->getFileName());
  521. else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive())
  522. dumpArchive(&*AOrErr.get(), Writer);
  523. }
  524. }
  525. /// Dumps \a WinRes, Windows Resource (.res) file;
  526. static void dumpWindowsResourceFile(WindowsResource *WinRes,
  527. ScopedPrinter &Printer) {
  528. WindowsRes::Dumper Dumper(WinRes, Printer);
  529. if (auto Err = Dumper.printData())
  530. reportError(std::move(Err), WinRes->getFileName());
  531. }
  532. /// Opens \a File and dumps it.
  533. static void dumpInput(StringRef File, ScopedPrinter &Writer) {
  534. ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
  535. MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false,
  536. /*RequiresNullTerminator=*/false);
  537. if (std::error_code EC = FileOrErr.getError())
  538. return reportError(errorCodeToError(EC), File);
  539. std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
  540. file_magic Type = identify_magic(Buffer->getBuffer());
  541. if (Type == file_magic::bitcode) {
  542. reportWarning(createStringError(errc::invalid_argument,
  543. "bitcode files are not supported"),
  544. File);
  545. return;
  546. }
  547. Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary(
  548. Buffer->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
  549. if (!BinaryOrErr)
  550. reportError(BinaryOrErr.takeError(), File);
  551. std::unique_ptr<Binary> Bin = std::move(*BinaryOrErr);
  552. if (Archive *Arc = dyn_cast<Archive>(Bin.get()))
  553. dumpArchive(Arc, Writer);
  554. else if (MachOUniversalBinary *UBinary =
  555. dyn_cast<MachOUniversalBinary>(Bin.get()))
  556. dumpMachOUniversalBinary(UBinary, Writer);
  557. else if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin.get()))
  558. dumpObject(*Obj, Writer);
  559. else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(Bin.get()))
  560. dumpCOFFImportFile(Import, Writer);
  561. else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(Bin.get()))
  562. dumpWindowsResourceFile(WinRes, Writer);
  563. else
  564. llvm_unreachable("unrecognized file type");
  565. CVTypes.Binaries.push_back(
  566. OwningBinary<Binary>(std::move(Bin), std::move(Buffer)));
  567. }
  568. std::unique_ptr<ScopedPrinter> createWriter() {
  569. if (opts::Output == opts::JSON)
  570. return std::make_unique<JSONScopedPrinter>(
  571. fouts(), opts::PrettyPrint ? 2 : 0, std::make_unique<ListScope>());
  572. return std::make_unique<ScopedPrinter>(fouts());
  573. }
  574. int llvm_readobj_main(int argc, char **argv) {
  575. InitLLVM X(argc, argv);
  576. BumpPtrAllocator A;
  577. StringSaver Saver(A);
  578. ReadobjOptTable Tbl;
  579. ToolName = argv[0];
  580. opt::InputArgList Args =
  581. Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
  582. error(Msg);
  583. exit(1);
  584. });
  585. if (Args.hasArg(OPT_help)) {
  586. Tbl.printHelp(
  587. outs(),
  588. (Twine(ToolName) + " [options] <input object files>").str().c_str(),
  589. "LLVM Object Reader");
  590. // TODO Replace this with OptTable API once it adds extrahelp support.
  591. outs() << "\nPass @FILE as argument to read options from FILE.\n";
  592. return 0;
  593. }
  594. if (Args.hasArg(OPT_version)) {
  595. cl::PrintVersionMessage();
  596. return 0;
  597. }
  598. if (sys::path::stem(argv[0]).contains("readelf"))
  599. opts::Output = opts::GNU;
  600. parseOptions(Args);
  601. // Default to print error if no filename is specified.
  602. if (opts::InputFilenames.empty()) {
  603. error("no input files specified");
  604. }
  605. if (opts::All) {
  606. opts::FileHeaders = true;
  607. opts::XCOFFAuxiliaryHeader = true;
  608. opts::ProgramHeaders = true;
  609. opts::SectionHeaders = true;
  610. opts::Symbols = true;
  611. opts::Relocations = true;
  612. opts::DynamicTable = true;
  613. opts::Notes = true;
  614. opts::VersionInfo = true;
  615. opts::UnwindInfo = true;
  616. opts::SectionGroups = true;
  617. opts::HashHistogram = true;
  618. if (opts::Output == opts::LLVM) {
  619. opts::Addrsig = true;
  620. opts::PrintStackSizes = true;
  621. }
  622. }
  623. if (opts::Headers) {
  624. opts::FileHeaders = true;
  625. opts::XCOFFAuxiliaryHeader = true;
  626. opts::ProgramHeaders = true;
  627. opts::SectionHeaders = true;
  628. }
  629. std::unique_ptr<ScopedPrinter> Writer = createWriter();
  630. for (const std::string &I : opts::InputFilenames)
  631. dumpInput(I, *Writer.get());
  632. if (opts::CodeViewMergedTypes) {
  633. if (opts::CodeViewEnableGHash)
  634. dumpCodeViewMergedTypes(*Writer.get(), CVTypes.GlobalIDTable.records(),
  635. CVTypes.GlobalTypeTable.records());
  636. else
  637. dumpCodeViewMergedTypes(*Writer.get(), CVTypes.IDTable.records(),
  638. CVTypes.TypeTable.records());
  639. }
  640. return 0;
  641. }