llvm-readobj.cpp 22 KB

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