xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- llvm-readobj.cpp - Dump contents of an Object File -----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This is a tool similar to readelf, except it works on multiple object file
100b57cec5SDimitry Andric // formats. The main purpose of this tool is to provide detailed output suitable
110b57cec5SDimitry Andric // for FileCheck.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric // Flags should be similar to readelf where supported, but the output format
140b57cec5SDimitry Andric // does not need to be identical. The point is to not make users learn yet
150b57cec5SDimitry Andric // another set of flags.
160b57cec5SDimitry Andric //
170b57cec5SDimitry Andric // Output should be specialized for each format where appropriate.
180b57cec5SDimitry Andric //
190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #include "llvm-readobj.h"
220b57cec5SDimitry Andric #include "ObjDumper.h"
230b57cec5SDimitry Andric #include "WindowsResourceDumper.h"
240b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
250b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
26349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
270b57cec5SDimitry Andric #include "llvm/Object/Archive.h"
280b57cec5SDimitry Andric #include "llvm/Object/COFFImportFile.h"
29e8d8bef9SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
300b57cec5SDimitry Andric #include "llvm/Object/MachOUniversal.h"
310b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
32e8d8bef9SDimitry Andric #include "llvm/Object/Wasm.h"
330b57cec5SDimitry Andric #include "llvm/Object/WindowsResource.h"
34e8d8bef9SDimitry Andric #include "llvm/Object/XCOFFObjectFile.h"
35fe6060f1SDimitry Andric #include "llvm/Option/Arg.h"
36fe6060f1SDimitry Andric #include "llvm/Option/ArgList.h"
37fe6060f1SDimitry Andric #include "llvm/Option/Option.h"
380b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
390b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
400b57cec5SDimitry Andric #include "llvm/Support/DataTypes.h"
410b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
42e8d8bef9SDimitry Andric #include "llvm/Support/Errc.h"
430b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
440b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h"
4506c3fb27SDimitry Andric #include "llvm/Support/LLVMDriver.h"
460b57cec5SDimitry Andric #include "llvm/Support/Path.h"
470b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
480b57cec5SDimitry Andric #include "llvm/Support/WithColor.h"
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric using namespace llvm;
510b57cec5SDimitry Andric using namespace llvm::object;
520b57cec5SDimitry Andric 
53fe6060f1SDimitry Andric namespace {
54fe6060f1SDimitry Andric using namespace llvm::opt; // for HelpHidden in Opts.inc
55fe6060f1SDimitry Andric enum ID {
56fe6060f1SDimitry Andric   OPT_INVALID = 0, // This is not an option ID.
575f757f3fSDimitry Andric #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
58fe6060f1SDimitry Andric #include "Opts.inc"
59fe6060f1SDimitry Andric #undef OPTION
60fe6060f1SDimitry Andric };
61fe6060f1SDimitry Andric 
62bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE)                                                    \
63bdd1243dSDimitry Andric   static constexpr StringLiteral NAME##_init[] = VALUE;                        \
64bdd1243dSDimitry Andric   static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
65bdd1243dSDimitry Andric                                                 std::size(NAME##_init) - 1);
66fe6060f1SDimitry Andric #include "Opts.inc"
67fe6060f1SDimitry Andric #undef PREFIX
68fe6060f1SDimitry Andric 
69bdd1243dSDimitry Andric static constexpr opt::OptTable::Info InfoTable[] = {
705f757f3fSDimitry Andric #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
71fe6060f1SDimitry Andric #include "Opts.inc"
72fe6060f1SDimitry Andric #undef OPTION
73fe6060f1SDimitry Andric };
74fe6060f1SDimitry Andric 
75bdd1243dSDimitry Andric class ReadobjOptTable : public opt::GenericOptTable {
76fe6060f1SDimitry Andric public:
77bdd1243dSDimitry Andric   ReadobjOptTable() : opt::GenericOptTable(InfoTable) {
78bdd1243dSDimitry Andric     setGroupedShortOptions(true);
79bdd1243dSDimitry Andric   }
80fe6060f1SDimitry Andric };
81fe6060f1SDimitry Andric 
82fe6060f1SDimitry Andric enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
8381ad6265SDimitry Andric 
8481ad6265SDimitry Andric enum SortSymbolKeyTy {
8581ad6265SDimitry Andric   NAME = 0,
8681ad6265SDimitry Andric   TYPE = 1,
8781ad6265SDimitry Andric   UNKNOWN = 100,
8881ad6265SDimitry Andric   // TODO: add ADDRESS, SIZE as needed.
8981ad6265SDimitry Andric };
9081ad6265SDimitry Andric 
91fe6060f1SDimitry Andric } // namespace
92fe6060f1SDimitry Andric 
930b57cec5SDimitry Andric namespace opts {
94fe6060f1SDimitry Andric static bool Addrsig;
95fe6060f1SDimitry Andric static bool All;
96fe6060f1SDimitry Andric static bool ArchSpecificInfo;
97fe6060f1SDimitry Andric static bool BBAddrMap;
98*0fca6ea1SDimitry Andric static bool PrettyPGOAnalysisMap;
99fe6060f1SDimitry Andric bool ExpandRelocs;
100fe6060f1SDimitry Andric static bool CGProfile;
1014c2d3b02SDimitry Andric static bool Decompress;
102fe6060f1SDimitry Andric bool Demangle;
103fe6060f1SDimitry Andric static bool DependentLibraries;
104fe6060f1SDimitry Andric static bool DynRelocs;
105fe6060f1SDimitry Andric static bool DynamicSymbols;
1065f757f3fSDimitry Andric static bool ExtraSymInfo;
107fe6060f1SDimitry Andric static bool FileHeaders;
108fe6060f1SDimitry Andric static bool Headers;
109fe6060f1SDimitry Andric static std::vector<std::string> HexDump;
1100eae32dcSDimitry Andric static bool PrettyPrint;
111fe6060f1SDimitry Andric static bool PrintStackMap;
112fe6060f1SDimitry Andric static bool PrintStackSizes;
113fe6060f1SDimitry Andric static bool Relocations;
114fe6060f1SDimitry Andric bool SectionData;
115fe6060f1SDimitry Andric static bool SectionDetails;
116fe6060f1SDimitry Andric static bool SectionHeaders;
117fe6060f1SDimitry Andric bool SectionRelocations;
118fe6060f1SDimitry Andric bool SectionSymbols;
119fe6060f1SDimitry Andric static std::vector<std::string> StringDump;
120fe6060f1SDimitry Andric static bool StringTable;
121fe6060f1SDimitry Andric static bool Symbols;
122fe6060f1SDimitry Andric static bool UnwindInfo;
123fe6060f1SDimitry Andric static cl::boolOrDefault SectionMapping;
12481ad6265SDimitry Andric static SmallVector<SortSymbolKeyTy> SortKeys;
1250b57cec5SDimitry Andric 
126fe6060f1SDimitry Andric // ELF specific options.
127fe6060f1SDimitry Andric static bool DynamicTable;
128fe6060f1SDimitry Andric static bool ELFLinkerOptions;
129fe6060f1SDimitry Andric static bool GnuHashTable;
130fe6060f1SDimitry Andric static bool HashSymbols;
131fe6060f1SDimitry Andric static bool HashTable;
132fe6060f1SDimitry Andric static bool HashHistogram;
13306c3fb27SDimitry Andric static bool Memtag;
134fe6060f1SDimitry Andric static bool NeededLibraries;
135fe6060f1SDimitry Andric static bool Notes;
136fe6060f1SDimitry Andric static bool ProgramHeaders;
137fe6060f1SDimitry Andric static bool SectionGroups;
138fe6060f1SDimitry Andric static bool VersionInfo;
1390b57cec5SDimitry Andric 
140fe6060f1SDimitry Andric // Mach-O specific options.
141fe6060f1SDimitry Andric static bool MachODataInCode;
142fe6060f1SDimitry Andric static bool MachODysymtab;
143fe6060f1SDimitry Andric static bool MachOIndirectSymbols;
144fe6060f1SDimitry Andric static bool MachOLinkerOptions;
145fe6060f1SDimitry Andric static bool MachOSegment;
146fe6060f1SDimitry Andric static bool MachOVersionMin;
147480093f4SDimitry Andric 
148fe6060f1SDimitry Andric // PE/COFF specific options.
149fe6060f1SDimitry Andric static bool CodeView;
150fe6060f1SDimitry Andric static bool CodeViewEnableGHash;
151fe6060f1SDimitry Andric static bool CodeViewMergedTypes;
152fe6060f1SDimitry Andric bool CodeViewSubsectionBytes;
153fe6060f1SDimitry Andric static bool COFFBaseRelocs;
154fe6060f1SDimitry Andric static bool COFFDebugDirectory;
155fe6060f1SDimitry Andric static bool COFFDirectives;
156fe6060f1SDimitry Andric static bool COFFExports;
157fe6060f1SDimitry Andric static bool COFFImports;
158fe6060f1SDimitry Andric static bool COFFLoadConfig;
159fe6060f1SDimitry Andric static bool COFFResources;
160fe6060f1SDimitry Andric static bool COFFTLSDirectory;
1610b57cec5SDimitry Andric 
162349cc55cSDimitry Andric // XCOFF specific options.
163349cc55cSDimitry Andric static bool XCOFFAuxiliaryHeader;
164bdd1243dSDimitry Andric static bool XCOFFLoaderSectionHeader;
165bdd1243dSDimitry Andric static bool XCOFFLoaderSectionSymbol;
166bdd1243dSDimitry Andric static bool XCOFFLoaderSectionRelocation;
167bdd1243dSDimitry Andric static bool XCOFFExceptionSection;
168349cc55cSDimitry Andric 
169fe6060f1SDimitry Andric OutputStyleTy Output = OutputStyleTy::LLVM;
170fe6060f1SDimitry Andric static std::vector<std::string> InputFilenames;
1710b57cec5SDimitry Andric } // namespace opts
1720b57cec5SDimitry Andric 
1738bcb0991SDimitry Andric static StringRef ToolName;
1748bcb0991SDimitry Andric 
1750b57cec5SDimitry Andric namespace llvm {
1760b57cec5SDimitry Andric 
177349cc55cSDimitry Andric [[noreturn]] static void error(Twine Msg) {
1788bcb0991SDimitry Andric   // Flush the standard output to print the error at a
1798bcb0991SDimitry Andric   // proper place.
1800b57cec5SDimitry Andric   fouts().flush();
1818bcb0991SDimitry Andric   WithColor::error(errs(), ToolName) << Msg << "\n";
1820b57cec5SDimitry Andric   exit(1);
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
185349cc55cSDimitry Andric [[noreturn]] void reportError(Error Err, StringRef Input) {
1868bcb0991SDimitry Andric   assert(Err);
1870b57cec5SDimitry Andric   if (Input == "-")
1880b57cec5SDimitry Andric     Input = "<stdin>";
1898bcb0991SDimitry Andric   handleAllErrors(createFileError(Input, std::move(Err)),
1908bcb0991SDimitry Andric                   [&](const ErrorInfoBase &EI) { error(EI.message()); });
1918bcb0991SDimitry Andric   llvm_unreachable("error() call should never return");
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric 
1948bcb0991SDimitry Andric void reportWarning(Error Err, StringRef Input) {
1958bcb0991SDimitry Andric   assert(Err);
1968bcb0991SDimitry Andric   if (Input == "-")
1978bcb0991SDimitry Andric     Input = "<stdin>";
1988bcb0991SDimitry Andric 
1998bcb0991SDimitry Andric   // Flush the standard output to print the warning at a
2008bcb0991SDimitry Andric   // proper place.
2010b57cec5SDimitry Andric   fouts().flush();
2028bcb0991SDimitry Andric   handleAllErrors(
2038bcb0991SDimitry Andric       createFileError(Input, std::move(Err)), [&](const ErrorInfoBase &EI) {
2048bcb0991SDimitry Andric         WithColor::warning(errs(), ToolName) << EI.message() << "\n";
2050b57cec5SDimitry Andric       });
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric } // namespace llvm
2090b57cec5SDimitry Andric 
210fe6060f1SDimitry Andric static void parseOptions(const opt::InputArgList &Args) {
211fe6060f1SDimitry Andric   opts::Addrsig = Args.hasArg(OPT_addrsig);
212fe6060f1SDimitry Andric   opts::All = Args.hasArg(OPT_all);
213fe6060f1SDimitry Andric   opts::ArchSpecificInfo = Args.hasArg(OPT_arch_specific);
214fe6060f1SDimitry Andric   opts::BBAddrMap = Args.hasArg(OPT_bb_addr_map);
215*0fca6ea1SDimitry Andric   opts::PrettyPGOAnalysisMap = Args.hasArg(OPT_pretty_pgo_analysis_map);
216*0fca6ea1SDimitry Andric   if (opts::PrettyPGOAnalysisMap && !opts::BBAddrMap)
217*0fca6ea1SDimitry Andric     WithColor::warning(errs(), ToolName)
218*0fca6ea1SDimitry Andric         << "--bb-addr-map must be enabled for --pretty-pgo-analysis-map to "
219*0fca6ea1SDimitry Andric            "have an effect\n";
220fe6060f1SDimitry Andric   opts::CGProfile = Args.hasArg(OPT_cg_profile);
2214c2d3b02SDimitry Andric   opts::Decompress = Args.hasArg(OPT_decompress);
222fe6060f1SDimitry Andric   opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
223fe6060f1SDimitry Andric   opts::DependentLibraries = Args.hasArg(OPT_dependent_libraries);
224fe6060f1SDimitry Andric   opts::DynRelocs = Args.hasArg(OPT_dyn_relocations);
225fe6060f1SDimitry Andric   opts::DynamicSymbols = Args.hasArg(OPT_dyn_syms);
226fe6060f1SDimitry Andric   opts::ExpandRelocs = Args.hasArg(OPT_expand_relocs);
2275f757f3fSDimitry Andric   opts::ExtraSymInfo = Args.hasArg(OPT_extra_sym_info);
228fe6060f1SDimitry Andric   opts::FileHeaders = Args.hasArg(OPT_file_header);
229fe6060f1SDimitry Andric   opts::Headers = Args.hasArg(OPT_headers);
230fe6060f1SDimitry Andric   opts::HexDump = Args.getAllArgValues(OPT_hex_dump_EQ);
231fe6060f1SDimitry Andric   opts::Relocations = Args.hasArg(OPT_relocs);
232fe6060f1SDimitry Andric   opts::SectionData = Args.hasArg(OPT_section_data);
233fe6060f1SDimitry Andric   opts::SectionDetails = Args.hasArg(OPT_section_details);
234fe6060f1SDimitry Andric   opts::SectionHeaders = Args.hasArg(OPT_section_headers);
235fe6060f1SDimitry Andric   opts::SectionRelocations = Args.hasArg(OPT_section_relocations);
236fe6060f1SDimitry Andric   opts::SectionSymbols = Args.hasArg(OPT_section_symbols);
237fe6060f1SDimitry Andric   if (Args.hasArg(OPT_section_mapping))
238fe6060f1SDimitry Andric     opts::SectionMapping = cl::BOU_TRUE;
239fe6060f1SDimitry Andric   else if (Args.hasArg(OPT_section_mapping_EQ_false))
240fe6060f1SDimitry Andric     opts::SectionMapping = cl::BOU_FALSE;
241fe6060f1SDimitry Andric   else
242fe6060f1SDimitry Andric     opts::SectionMapping = cl::BOU_UNSET;
243fe6060f1SDimitry Andric   opts::PrintStackSizes = Args.hasArg(OPT_stack_sizes);
244fe6060f1SDimitry Andric   opts::PrintStackMap = Args.hasArg(OPT_stackmap);
245fe6060f1SDimitry Andric   opts::StringDump = Args.getAllArgValues(OPT_string_dump_EQ);
246fe6060f1SDimitry Andric   opts::StringTable = Args.hasArg(OPT_string_table);
247fe6060f1SDimitry Andric   opts::Symbols = Args.hasArg(OPT_symbols);
248fe6060f1SDimitry Andric   opts::UnwindInfo = Args.hasArg(OPT_unwind);
249fe6060f1SDimitry Andric 
250fe6060f1SDimitry Andric   // ELF specific options.
251fe6060f1SDimitry Andric   opts::DynamicTable = Args.hasArg(OPT_dynamic_table);
252fe6060f1SDimitry Andric   opts::ELFLinkerOptions = Args.hasArg(OPT_elf_linker_options);
253fe6060f1SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_elf_output_style_EQ)) {
2540eae32dcSDimitry Andric     std::string OutputStyleChoice = A->getValue();
2550eae32dcSDimitry Andric     opts::Output = StringSwitch<opts::OutputStyleTy>(OutputStyleChoice)
2560eae32dcSDimitry Andric                        .Case("LLVM", opts::OutputStyleTy::LLVM)
2570eae32dcSDimitry Andric                        .Case("GNU", opts::OutputStyleTy::GNU)
2580eae32dcSDimitry Andric                        .Case("JSON", opts::OutputStyleTy::JSON)
2590eae32dcSDimitry Andric                        .Default(opts::OutputStyleTy::UNKNOWN);
2600eae32dcSDimitry Andric     if (opts::Output == opts::OutputStyleTy::UNKNOWN) {
2610eae32dcSDimitry Andric       error("--elf-output-style value should be either 'LLVM', 'GNU', or "
2620eae32dcSDimitry Andric             "'JSON', but was '" +
2630eae32dcSDimitry Andric             OutputStyleChoice + "'");
2640eae32dcSDimitry Andric     }
265fe6060f1SDimitry Andric   }
266fe6060f1SDimitry Andric   opts::GnuHashTable = Args.hasArg(OPT_gnu_hash_table);
267fe6060f1SDimitry Andric   opts::HashSymbols = Args.hasArg(OPT_hash_symbols);
268fe6060f1SDimitry Andric   opts::HashTable = Args.hasArg(OPT_hash_table);
269fe6060f1SDimitry Andric   opts::HashHistogram = Args.hasArg(OPT_histogram);
27006c3fb27SDimitry Andric   opts::Memtag = Args.hasArg(OPT_memtag);
271fe6060f1SDimitry Andric   opts::NeededLibraries = Args.hasArg(OPT_needed_libs);
272fe6060f1SDimitry Andric   opts::Notes = Args.hasArg(OPT_notes);
2730eae32dcSDimitry Andric   opts::PrettyPrint = Args.hasArg(OPT_pretty_print);
274fe6060f1SDimitry Andric   opts::ProgramHeaders = Args.hasArg(OPT_program_headers);
275fe6060f1SDimitry Andric   opts::SectionGroups = Args.hasArg(OPT_section_groups);
27681ad6265SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_sort_symbols_EQ)) {
27781ad6265SDimitry Andric     std::string SortKeysString = A->getValue();
27881ad6265SDimitry Andric     for (StringRef KeyStr : llvm::split(A->getValue(), ",")) {
27981ad6265SDimitry Andric       SortSymbolKeyTy KeyType = StringSwitch<SortSymbolKeyTy>(KeyStr)
28081ad6265SDimitry Andric                                     .Case("name", SortSymbolKeyTy::NAME)
28181ad6265SDimitry Andric                                     .Case("type", SortSymbolKeyTy::TYPE)
28281ad6265SDimitry Andric                                     .Default(SortSymbolKeyTy::UNKNOWN);
28381ad6265SDimitry Andric       if (KeyType == SortSymbolKeyTy::UNKNOWN)
28481ad6265SDimitry Andric         error("--sort-symbols value should be 'name' or 'type', but was '" +
28581ad6265SDimitry Andric               Twine(KeyStr) + "'");
28681ad6265SDimitry Andric       opts::SortKeys.push_back(KeyType);
28781ad6265SDimitry Andric     }
28881ad6265SDimitry Andric   }
289fe6060f1SDimitry Andric   opts::VersionInfo = Args.hasArg(OPT_version_info);
290fe6060f1SDimitry Andric 
291fe6060f1SDimitry Andric   // Mach-O specific options.
292fe6060f1SDimitry Andric   opts::MachODataInCode = Args.hasArg(OPT_macho_data_in_code);
293fe6060f1SDimitry Andric   opts::MachODysymtab = Args.hasArg(OPT_macho_dysymtab);
294fe6060f1SDimitry Andric   opts::MachOIndirectSymbols = Args.hasArg(OPT_macho_indirect_symbols);
295fe6060f1SDimitry Andric   opts::MachOLinkerOptions = Args.hasArg(OPT_macho_linker_options);
296fe6060f1SDimitry Andric   opts::MachOSegment = Args.hasArg(OPT_macho_segment);
297fe6060f1SDimitry Andric   opts::MachOVersionMin = Args.hasArg(OPT_macho_version_min);
298fe6060f1SDimitry Andric 
299fe6060f1SDimitry Andric   // PE/COFF specific options.
300fe6060f1SDimitry Andric   opts::CodeView = Args.hasArg(OPT_codeview);
301fe6060f1SDimitry Andric   opts::CodeViewEnableGHash = Args.hasArg(OPT_codeview_ghash);
302fe6060f1SDimitry Andric   opts::CodeViewMergedTypes = Args.hasArg(OPT_codeview_merged_types);
303fe6060f1SDimitry Andric   opts::CodeViewSubsectionBytes = Args.hasArg(OPT_codeview_subsection_bytes);
304fe6060f1SDimitry Andric   opts::COFFBaseRelocs = Args.hasArg(OPT_coff_basereloc);
305fe6060f1SDimitry Andric   opts::COFFDebugDirectory = Args.hasArg(OPT_coff_debug_directory);
306fe6060f1SDimitry Andric   opts::COFFDirectives = Args.hasArg(OPT_coff_directives);
307fe6060f1SDimitry Andric   opts::COFFExports = Args.hasArg(OPT_coff_exports);
308fe6060f1SDimitry Andric   opts::COFFImports = Args.hasArg(OPT_coff_imports);
309fe6060f1SDimitry Andric   opts::COFFLoadConfig = Args.hasArg(OPT_coff_load_config);
310fe6060f1SDimitry Andric   opts::COFFResources = Args.hasArg(OPT_coff_resources);
311fe6060f1SDimitry Andric   opts::COFFTLSDirectory = Args.hasArg(OPT_coff_tls_directory);
312fe6060f1SDimitry Andric 
313349cc55cSDimitry Andric   // XCOFF specific options.
314349cc55cSDimitry Andric   opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header);
315bdd1243dSDimitry Andric   opts::XCOFFLoaderSectionHeader = Args.hasArg(OPT_loader_section_header);
316bdd1243dSDimitry Andric   opts::XCOFFLoaderSectionSymbol = Args.hasArg(OPT_loader_section_symbols);
317bdd1243dSDimitry Andric   opts::XCOFFLoaderSectionRelocation =
318bdd1243dSDimitry Andric       Args.hasArg(OPT_loader_section_relocations);
319bdd1243dSDimitry Andric   opts::XCOFFExceptionSection = Args.hasArg(OPT_exception_section);
320349cc55cSDimitry Andric 
321fe6060f1SDimitry Andric   opts::InputFilenames = Args.getAllArgValues(OPT_INPUT);
322fe6060f1SDimitry Andric }
323fe6060f1SDimitry Andric 
3240b57cec5SDimitry Andric namespace {
3250b57cec5SDimitry Andric struct ReadObjTypeTableBuilder {
3260b57cec5SDimitry Andric   ReadObjTypeTableBuilder()
32704eeddc0SDimitry Andric       : IDTable(Allocator), TypeTable(Allocator), GlobalIDTable(Allocator),
32804eeddc0SDimitry Andric         GlobalTypeTable(Allocator) {}
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   llvm::BumpPtrAllocator Allocator;
3310b57cec5SDimitry Andric   llvm::codeview::MergingTypeTableBuilder IDTable;
3320b57cec5SDimitry Andric   llvm::codeview::MergingTypeTableBuilder TypeTable;
3330b57cec5SDimitry Andric   llvm::codeview::GlobalTypeTableBuilder GlobalIDTable;
3340b57cec5SDimitry Andric   llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable;
3350b57cec5SDimitry Andric   std::vector<OwningBinary<Binary>> Binaries;
3360b57cec5SDimitry Andric };
3370b57cec5SDimitry Andric } // namespace
3380b57cec5SDimitry Andric static ReadObjTypeTableBuilder CVTypes;
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric /// Creates an format-specific object file dumper.
341e8d8bef9SDimitry Andric static Expected<std::unique_ptr<ObjDumper>>
342e8d8bef9SDimitry Andric createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) {
343e8d8bef9SDimitry Andric   if (const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(&Obj))
344e8d8bef9SDimitry Andric     return createCOFFDumper(*COFFObj, Writer);
3450b57cec5SDimitry Andric 
346e8d8bef9SDimitry Andric   if (const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
347e8d8bef9SDimitry Andric     return createELFDumper(*ELFObj, Writer);
3480b57cec5SDimitry Andric 
349e8d8bef9SDimitry Andric   if (const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(&Obj))
350e8d8bef9SDimitry Andric     return createMachODumper(*MachOObj, Writer);
351e8d8bef9SDimitry Andric 
352e8d8bef9SDimitry Andric   if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj))
353e8d8bef9SDimitry Andric     return createWasmDumper(*WasmObj, Writer);
354e8d8bef9SDimitry Andric 
355e8d8bef9SDimitry Andric   if (const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(&Obj))
356e8d8bef9SDimitry Andric     return createXCOFFDumper(*XObj, Writer);
357e8d8bef9SDimitry Andric 
358e8d8bef9SDimitry Andric   return createStringError(errc::invalid_argument,
359e8d8bef9SDimitry Andric                            "unsupported object file format");
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric /// Dumps the specified object file.
363e8d8bef9SDimitry Andric static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
3640b57cec5SDimitry Andric                        const Archive *A = nullptr) {
3650b57cec5SDimitry Andric   std::string FileStr =
366e8d8bef9SDimitry Andric       A ? Twine(A->getFileName() + "(" + Obj.getFileName() + ")").str()
367e8d8bef9SDimitry Andric         : Obj.getFileName().str();
3680b57cec5SDimitry Andric 
369e8d8bef9SDimitry Andric   std::string ContentErrString;
370e8d8bef9SDimitry Andric   if (Error ContentErr = Obj.initContent())
371e8d8bef9SDimitry Andric     ContentErrString = "unable to continue dumping, the file is corrupt: " +
372e8d8bef9SDimitry Andric                        toString(std::move(ContentErr));
373e8d8bef9SDimitry Andric 
374e8d8bef9SDimitry Andric   ObjDumper *Dumper;
375bdd1243dSDimitry Andric   std::optional<SymbolComparator> SymComp;
376e8d8bef9SDimitry Andric   Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer);
377e8d8bef9SDimitry Andric   if (!DumperOrErr)
378e8d8bef9SDimitry Andric     reportError(DumperOrErr.takeError(), FileStr);
379e8d8bef9SDimitry Andric   Dumper = (*DumperOrErr).get();
3800b57cec5SDimitry Andric 
38181ad6265SDimitry Andric   if (!opts::SortKeys.empty()) {
38281ad6265SDimitry Andric     if (Dumper->canCompareSymbols()) {
38381ad6265SDimitry Andric       SymComp = SymbolComparator();
38481ad6265SDimitry Andric       for (SortSymbolKeyTy Key : opts::SortKeys) {
38581ad6265SDimitry Andric         switch (Key) {
38681ad6265SDimitry Andric         case NAME:
38781ad6265SDimitry Andric           SymComp->addPredicate([Dumper](SymbolRef LHS, SymbolRef RHS) {
38881ad6265SDimitry Andric             return Dumper->compareSymbolsByName(LHS, RHS);
38981ad6265SDimitry Andric           });
39081ad6265SDimitry Andric           break;
39181ad6265SDimitry Andric         case TYPE:
39281ad6265SDimitry Andric           SymComp->addPredicate([Dumper](SymbolRef LHS, SymbolRef RHS) {
39381ad6265SDimitry Andric             return Dumper->compareSymbolsByType(LHS, RHS);
39481ad6265SDimitry Andric           });
39581ad6265SDimitry Andric           break;
39681ad6265SDimitry Andric         case UNKNOWN:
39781ad6265SDimitry Andric           llvm_unreachable("Unsupported sort key");
39881ad6265SDimitry Andric         }
39981ad6265SDimitry Andric       }
40081ad6265SDimitry Andric 
40181ad6265SDimitry Andric     } else {
40281ad6265SDimitry Andric       reportWarning(createStringError(
40381ad6265SDimitry Andric                         errc::invalid_argument,
40481ad6265SDimitry Andric                         "--sort-symbols is not supported yet for this format"),
40581ad6265SDimitry Andric                     FileStr);
40681ad6265SDimitry Andric     }
40781ad6265SDimitry Andric   }
4080eae32dcSDimitry Andric   Dumper->printFileSummary(FileStr, Obj, opts::InputFilenames, A);
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   if (opts::FileHeaders)
4110b57cec5SDimitry Andric     Dumper->printFileHeaders();
412e8d8bef9SDimitry Andric 
413bdd1243dSDimitry Andric   // Auxiliary header in XOCFF is right after the file header, so print the data
414bdd1243dSDimitry Andric   // here.
415349cc55cSDimitry Andric   if (Obj.isXCOFF() && opts::XCOFFAuxiliaryHeader)
416349cc55cSDimitry Andric     Dumper->printAuxiliaryHeader();
417349cc55cSDimitry Andric 
418e8d8bef9SDimitry Andric   // This is only used for ELF currently. In some cases, when an object is
419e8d8bef9SDimitry Andric   // corrupt (e.g. truncated), we can't dump anything except the file header.
420e8d8bef9SDimitry Andric   if (!ContentErrString.empty())
421e8d8bef9SDimitry Andric     reportError(createError(ContentErrString), FileStr);
422e8d8bef9SDimitry Andric 
423e8d8bef9SDimitry Andric   if (opts::SectionDetails || opts::SectionHeaders) {
424e8d8bef9SDimitry Andric     if (opts::Output == opts::GNU && opts::SectionDetails)
425e8d8bef9SDimitry Andric       Dumper->printSectionDetails();
426e8d8bef9SDimitry Andric     else
4270b57cec5SDimitry Andric       Dumper->printSectionHeaders();
428e8d8bef9SDimitry Andric   }
429e8d8bef9SDimitry Andric 
4300b57cec5SDimitry Andric   if (opts::HashSymbols)
4310b57cec5SDimitry Andric     Dumper->printHashSymbols();
4325ffd83dbSDimitry Andric   if (opts::ProgramHeaders || opts::SectionMapping == cl::BOU_TRUE)
4335ffd83dbSDimitry Andric     Dumper->printProgramHeaders(opts::ProgramHeaders, opts::SectionMapping);
4340b57cec5SDimitry Andric   if (opts::DynamicTable)
4350b57cec5SDimitry Andric     Dumper->printDynamicTable();
4360b57cec5SDimitry Andric   if (opts::NeededLibraries)
4370b57cec5SDimitry Andric     Dumper->printNeededLibraries();
4385ffd83dbSDimitry Andric   if (opts::Relocations)
4395ffd83dbSDimitry Andric     Dumper->printRelocations();
4405ffd83dbSDimitry Andric   if (opts::DynRelocs)
4415ffd83dbSDimitry Andric     Dumper->printDynamicRelocations();
4425ffd83dbSDimitry Andric   if (opts::UnwindInfo)
4435ffd83dbSDimitry Andric     Dumper->printUnwindInfo();
4445ffd83dbSDimitry Andric   if (opts::Symbols || opts::DynamicSymbols)
4455f757f3fSDimitry Andric     Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols,
4465f757f3fSDimitry Andric                          opts::ExtraSymInfo, SymComp);
4470b57cec5SDimitry Andric   if (!opts::StringDump.empty())
4484c2d3b02SDimitry Andric     Dumper->printSectionsAsString(Obj, opts::StringDump, opts::Decompress);
4490b57cec5SDimitry Andric   if (!opts::HexDump.empty())
4504c2d3b02SDimitry Andric     Dumper->printSectionsAsHex(Obj, opts::HexDump, opts::Decompress);
4510b57cec5SDimitry Andric   if (opts::HashTable)
4520b57cec5SDimitry Andric     Dumper->printHashTable();
4530b57cec5SDimitry Andric   if (opts::GnuHashTable)
454e8d8bef9SDimitry Andric     Dumper->printGnuHashTable();
4550b57cec5SDimitry Andric   if (opts::VersionInfo)
4560b57cec5SDimitry Andric     Dumper->printVersionInfo();
457fe6060f1SDimitry Andric   if (opts::StringTable)
458fe6060f1SDimitry Andric     Dumper->printStringTable();
459e8d8bef9SDimitry Andric   if (Obj.isELF()) {
460480093f4SDimitry Andric     if (opts::DependentLibraries)
461480093f4SDimitry Andric       Dumper->printDependentLibs();
4620b57cec5SDimitry Andric     if (opts::ELFLinkerOptions)
4630b57cec5SDimitry Andric       Dumper->printELFLinkerOptions();
4648bcb0991SDimitry Andric     if (opts::ArchSpecificInfo)
4658bcb0991SDimitry Andric       Dumper->printArchSpecificInfo();
4660b57cec5SDimitry Andric     if (opts::SectionGroups)
4670b57cec5SDimitry Andric       Dumper->printGroupSections();
4680b57cec5SDimitry Andric     if (opts::HashHistogram)
4695ffd83dbSDimitry Andric       Dumper->printHashHistograms();
4700b57cec5SDimitry Andric     if (opts::CGProfile)
4710b57cec5SDimitry Andric       Dumper->printCGProfile();
472fe6060f1SDimitry Andric     if (opts::BBAddrMap)
473*0fca6ea1SDimitry Andric       Dumper->printBBAddrMaps(opts::PrettyPGOAnalysisMap);
4740b57cec5SDimitry Andric     if (opts::Addrsig)
4750b57cec5SDimitry Andric       Dumper->printAddrsig();
4760b57cec5SDimitry Andric     if (opts::Notes)
4770b57cec5SDimitry Andric       Dumper->printNotes();
47806c3fb27SDimitry Andric     if (opts::Memtag)
47906c3fb27SDimitry Andric       Dumper->printMemtag();
4800b57cec5SDimitry Andric   }
481e8d8bef9SDimitry Andric   if (Obj.isCOFF()) {
4820b57cec5SDimitry Andric     if (opts::COFFImports)
4830b57cec5SDimitry Andric       Dumper->printCOFFImports();
4840b57cec5SDimitry Andric     if (opts::COFFExports)
4850b57cec5SDimitry Andric       Dumper->printCOFFExports();
4860b57cec5SDimitry Andric     if (opts::COFFDirectives)
4870b57cec5SDimitry Andric       Dumper->printCOFFDirectives();
4880b57cec5SDimitry Andric     if (opts::COFFBaseRelocs)
4890b57cec5SDimitry Andric       Dumper->printCOFFBaseReloc();
4900b57cec5SDimitry Andric     if (opts::COFFDebugDirectory)
4910b57cec5SDimitry Andric       Dumper->printCOFFDebugDirectory();
492e8d8bef9SDimitry Andric     if (opts::COFFTLSDirectory)
493e8d8bef9SDimitry Andric       Dumper->printCOFFTLSDirectory();
4940b57cec5SDimitry Andric     if (opts::COFFResources)
4950b57cec5SDimitry Andric       Dumper->printCOFFResources();
4960b57cec5SDimitry Andric     if (opts::COFFLoadConfig)
4970b57cec5SDimitry Andric       Dumper->printCOFFLoadConfig();
4985ffd83dbSDimitry Andric     if (opts::CGProfile)
4995ffd83dbSDimitry Andric       Dumper->printCGProfile();
5000b57cec5SDimitry Andric     if (opts::Addrsig)
5010b57cec5SDimitry Andric       Dumper->printAddrsig();
5020b57cec5SDimitry Andric     if (opts::CodeView)
5030b57cec5SDimitry Andric       Dumper->printCodeViewDebugInfo();
5040b57cec5SDimitry Andric     if (opts::CodeViewMergedTypes)
5050b57cec5SDimitry Andric       Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable,
5060b57cec5SDimitry Andric                                  CVTypes.GlobalIDTable, CVTypes.GlobalTypeTable,
5070b57cec5SDimitry Andric                                  opts::CodeViewEnableGHash);
5080b57cec5SDimitry Andric   }
509e8d8bef9SDimitry Andric   if (Obj.isMachO()) {
5100b57cec5SDimitry Andric     if (opts::MachODataInCode)
5110b57cec5SDimitry Andric       Dumper->printMachODataInCode();
5120b57cec5SDimitry Andric     if (opts::MachOIndirectSymbols)
5130b57cec5SDimitry Andric       Dumper->printMachOIndirectSymbols();
5140b57cec5SDimitry Andric     if (opts::MachOLinkerOptions)
5150b57cec5SDimitry Andric       Dumper->printMachOLinkerOptions();
5160b57cec5SDimitry Andric     if (opts::MachOSegment)
5170b57cec5SDimitry Andric       Dumper->printMachOSegment();
5180b57cec5SDimitry Andric     if (opts::MachOVersionMin)
5190b57cec5SDimitry Andric       Dumper->printMachOVersionMin();
5200b57cec5SDimitry Andric     if (opts::MachODysymtab)
5210b57cec5SDimitry Andric       Dumper->printMachODysymtab();
52204eeddc0SDimitry Andric     if (opts::CGProfile)
52304eeddc0SDimitry Andric       Dumper->printCGProfile();
5240b57cec5SDimitry Andric   }
525bdd1243dSDimitry Andric 
526bdd1243dSDimitry Andric   if (Obj.isXCOFF()) {
527bdd1243dSDimitry Andric     if (opts::XCOFFLoaderSectionHeader || opts::XCOFFLoaderSectionSymbol ||
528bdd1243dSDimitry Andric         opts::XCOFFLoaderSectionRelocation)
529bdd1243dSDimitry Andric       Dumper->printLoaderSection(opts::XCOFFLoaderSectionHeader,
530bdd1243dSDimitry Andric                                  opts::XCOFFLoaderSectionSymbol,
531bdd1243dSDimitry Andric                                  opts::XCOFFLoaderSectionRelocation);
532bdd1243dSDimitry Andric 
533bdd1243dSDimitry Andric     if (opts::XCOFFExceptionSection)
534bdd1243dSDimitry Andric       Dumper->printExceptionSection();
535bdd1243dSDimitry Andric   }
536bdd1243dSDimitry Andric 
5370b57cec5SDimitry Andric   if (opts::PrintStackMap)
5380b57cec5SDimitry Andric     Dumper->printStackMap();
5398bcb0991SDimitry Andric   if (opts::PrintStackSizes)
5408bcb0991SDimitry Andric     Dumper->printStackSizes();
5410b57cec5SDimitry Andric }
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric /// Dumps each object file in \a Arc;
5440b57cec5SDimitry Andric static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) {
5450b57cec5SDimitry Andric   Error Err = Error::success();
5460b57cec5SDimitry Andric   for (auto &Child : Arc->children(Err)) {
5470b57cec5SDimitry Andric     Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
5480b57cec5SDimitry Andric     if (!ChildOrErr) {
5498bcb0991SDimitry Andric       if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
5508bcb0991SDimitry Andric         reportError(std::move(E), Arc->getFileName());
5510b57cec5SDimitry Andric       continue;
5520b57cec5SDimitry Andric     }
553e8d8bef9SDimitry Andric 
554e8d8bef9SDimitry Andric     Binary *Bin = ChildOrErr->get();
555e8d8bef9SDimitry Andric     if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin))
556e8d8bef9SDimitry Andric       dumpObject(*Obj, Writer, Arc);
557e8d8bef9SDimitry Andric     else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(Bin))
5580b57cec5SDimitry Andric       dumpCOFFImportFile(Imp, Writer);
5590b57cec5SDimitry Andric     else
560e8d8bef9SDimitry Andric       reportWarning(createStringError(errc::invalid_argument,
561e8d8bef9SDimitry Andric                                       Bin->getFileName() +
562e8d8bef9SDimitry Andric                                           " has an unsupported file type"),
5638bcb0991SDimitry Andric                     Arc->getFileName());
5640b57cec5SDimitry Andric   }
5650b57cec5SDimitry Andric   if (Err)
5668bcb0991SDimitry Andric     reportError(std::move(Err), Arc->getFileName());
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric /// Dumps each object file in \a MachO Universal Binary;
5700b57cec5SDimitry Andric static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
5710b57cec5SDimitry Andric                                      ScopedPrinter &Writer) {
5720b57cec5SDimitry Andric   for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) {
5730b57cec5SDimitry Andric     Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile();
5740b57cec5SDimitry Andric     if (ObjOrErr)
575e8d8bef9SDimitry Andric       dumpObject(*ObjOrErr.get(), Writer);
5768bcb0991SDimitry Andric     else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
5778bcb0991SDimitry Andric       reportError(ObjOrErr.takeError(), UBinary->getFileName());
5780b57cec5SDimitry Andric     else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive())
5790b57cec5SDimitry Andric       dumpArchive(&*AOrErr.get(), Writer);
5800b57cec5SDimitry Andric   }
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric /// Dumps \a WinRes, Windows Resource (.res) file;
5840b57cec5SDimitry Andric static void dumpWindowsResourceFile(WindowsResource *WinRes,
5850b57cec5SDimitry Andric                                     ScopedPrinter &Printer) {
5860b57cec5SDimitry Andric   WindowsRes::Dumper Dumper(WinRes, Printer);
5870b57cec5SDimitry Andric   if (auto Err = Dumper.printData())
5888bcb0991SDimitry Andric     reportError(std::move(Err), WinRes->getFileName());
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric /// Opens \a File and dumps it.
5930b57cec5SDimitry Andric static void dumpInput(StringRef File, ScopedPrinter &Writer) {
594fe6060f1SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
595fe6060f1SDimitry Andric       MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false,
596fe6060f1SDimitry Andric                                    /*RequiresNullTerminator=*/false);
597fe6060f1SDimitry Andric   if (std::error_code EC = FileOrErr.getError())
598fe6060f1SDimitry Andric     return reportError(errorCodeToError(EC), File);
599fe6060f1SDimitry Andric 
600fe6060f1SDimitry Andric   std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
601fe6060f1SDimitry Andric   file_magic Type = identify_magic(Buffer->getBuffer());
602fe6060f1SDimitry Andric   if (Type == file_magic::bitcode) {
603fe6060f1SDimitry Andric     reportWarning(createStringError(errc::invalid_argument,
604fe6060f1SDimitry Andric                                     "bitcode files are not supported"),
605fe6060f1SDimitry Andric                   File);
606fe6060f1SDimitry Andric     return;
607fe6060f1SDimitry Andric   }
608fe6060f1SDimitry Andric 
609fe6060f1SDimitry Andric   Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary(
610fe6060f1SDimitry Andric       Buffer->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
6110b57cec5SDimitry Andric   if (!BinaryOrErr)
6128bcb0991SDimitry Andric     reportError(BinaryOrErr.takeError(), File);
6130b57cec5SDimitry Andric 
614fe6060f1SDimitry Andric   std::unique_ptr<Binary> Bin = std::move(*BinaryOrErr);
615fe6060f1SDimitry Andric   if (Archive *Arc = dyn_cast<Archive>(Bin.get()))
6160b57cec5SDimitry Andric     dumpArchive(Arc, Writer);
6170b57cec5SDimitry Andric   else if (MachOUniversalBinary *UBinary =
618fe6060f1SDimitry Andric                dyn_cast<MachOUniversalBinary>(Bin.get()))
6190b57cec5SDimitry Andric     dumpMachOUniversalBinary(UBinary, Writer);
620fe6060f1SDimitry Andric   else if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin.get()))
621e8d8bef9SDimitry Andric     dumpObject(*Obj, Writer);
622fe6060f1SDimitry Andric   else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(Bin.get()))
6230b57cec5SDimitry Andric     dumpCOFFImportFile(Import, Writer);
624fe6060f1SDimitry Andric   else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(Bin.get()))
6250b57cec5SDimitry Andric     dumpWindowsResourceFile(WinRes, Writer);
6260b57cec5SDimitry Andric   else
627e8d8bef9SDimitry Andric     llvm_unreachable("unrecognized file type");
6280b57cec5SDimitry Andric 
629fe6060f1SDimitry Andric   CVTypes.Binaries.push_back(
630fe6060f1SDimitry Andric       OwningBinary<Binary>(std::move(Bin), std::move(Buffer)));
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric 
6330eae32dcSDimitry Andric std::unique_ptr<ScopedPrinter> createWriter() {
6340eae32dcSDimitry Andric   if (opts::Output == opts::JSON)
6350eae32dcSDimitry Andric     return std::make_unique<JSONScopedPrinter>(
6360eae32dcSDimitry Andric         fouts(), opts::PrettyPrint ? 2 : 0, std::make_unique<ListScope>());
6370eae32dcSDimitry Andric   return std::make_unique<ScopedPrinter>(fouts());
6380eae32dcSDimitry Andric }
6390eae32dcSDimitry Andric 
64006c3fb27SDimitry Andric int llvm_readobj_main(int argc, char **argv, const llvm::ToolContext &) {
641fe6060f1SDimitry Andric   BumpPtrAllocator A;
642fe6060f1SDimitry Andric   StringSaver Saver(A);
643fe6060f1SDimitry Andric   ReadobjOptTable Tbl;
6448bcb0991SDimitry Andric   ToolName = argv[0];
645fe6060f1SDimitry Andric   opt::InputArgList Args =
646fe6060f1SDimitry Andric       Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
647fe6060f1SDimitry Andric         error(Msg);
648fe6060f1SDimitry Andric         exit(1);
649fe6060f1SDimitry Andric       });
650fe6060f1SDimitry Andric   if (Args.hasArg(OPT_help)) {
651fe6060f1SDimitry Andric     Tbl.printHelp(
652fe6060f1SDimitry Andric         outs(),
653fe6060f1SDimitry Andric         (Twine(ToolName) + " [options] <input object files>").str().c_str(),
654fe6060f1SDimitry Andric         "LLVM Object Reader");
655fe6060f1SDimitry Andric     // TODO Replace this with OptTable API once it adds extrahelp support.
656fe6060f1SDimitry Andric     outs() << "\nPass @FILE as argument to read options from FILE.\n";
657fe6060f1SDimitry Andric     return 0;
658fe6060f1SDimitry Andric   }
659fe6060f1SDimitry Andric   if (Args.hasArg(OPT_version)) {
660fe6060f1SDimitry Andric     cl::PrintVersionMessage();
661fe6060f1SDimitry Andric     return 0;
6620b57cec5SDimitry Andric   }
6630b57cec5SDimitry Andric 
664fe6060f1SDimitry Andric   if (sys::path::stem(argv[0]).contains("readelf"))
665fe6060f1SDimitry Andric     opts::Output = opts::GNU;
666fe6060f1SDimitry Andric   parseOptions(Args);
6670b57cec5SDimitry Andric 
668e8d8bef9SDimitry Andric   // Default to print error if no filename is specified.
669e8d8bef9SDimitry Andric   if (opts::InputFilenames.empty()) {
670e8d8bef9SDimitry Andric     error("no input files specified");
671e8d8bef9SDimitry Andric   }
672e8d8bef9SDimitry Andric 
6730b57cec5SDimitry Andric   if (opts::All) {
6740b57cec5SDimitry Andric     opts::FileHeaders = true;
675349cc55cSDimitry Andric     opts::XCOFFAuxiliaryHeader = true;
6760b57cec5SDimitry Andric     opts::ProgramHeaders = true;
6770b57cec5SDimitry Andric     opts::SectionHeaders = true;
6780b57cec5SDimitry Andric     opts::Symbols = true;
6790b57cec5SDimitry Andric     opts::Relocations = true;
6800b57cec5SDimitry Andric     opts::DynamicTable = true;
6810b57cec5SDimitry Andric     opts::Notes = true;
6820b57cec5SDimitry Andric     opts::VersionInfo = true;
6830b57cec5SDimitry Andric     opts::UnwindInfo = true;
6840b57cec5SDimitry Andric     opts::SectionGroups = true;
6850b57cec5SDimitry Andric     opts::HashHistogram = true;
6868bcb0991SDimitry Andric     if (opts::Output == opts::LLVM) {
6878bcb0991SDimitry Andric       opts::Addrsig = true;
6888bcb0991SDimitry Andric       opts::PrintStackSizes = true;
6898bcb0991SDimitry Andric     }
69006c3fb27SDimitry Andric     opts::Memtag = true;
6910b57cec5SDimitry Andric   }
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   if (opts::Headers) {
6940b57cec5SDimitry Andric     opts::FileHeaders = true;
695349cc55cSDimitry Andric     opts::XCOFFAuxiliaryHeader = true;
6960b57cec5SDimitry Andric     opts::ProgramHeaders = true;
6970b57cec5SDimitry Andric     opts::SectionHeaders = true;
6980b57cec5SDimitry Andric   }
6990b57cec5SDimitry Andric 
7000eae32dcSDimitry Andric   std::unique_ptr<ScopedPrinter> Writer = createWriter();
7010eae32dcSDimitry Andric 
7020b57cec5SDimitry Andric   for (const std::string &I : opts::InputFilenames)
703*0fca6ea1SDimitry Andric     dumpInput(I, *Writer);
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   if (opts::CodeViewMergedTypes) {
7060b57cec5SDimitry Andric     if (opts::CodeViewEnableGHash)
707*0fca6ea1SDimitry Andric       dumpCodeViewMergedTypes(*Writer, CVTypes.GlobalIDTable.records(),
7080b57cec5SDimitry Andric                               CVTypes.GlobalTypeTable.records());
7090b57cec5SDimitry Andric     else
710*0fca6ea1SDimitry Andric       dumpCodeViewMergedTypes(*Writer, CVTypes.IDTable.records(),
7110b57cec5SDimitry Andric                               CVTypes.TypeTable.records());
7120b57cec5SDimitry Andric   }
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric   return 0;
7150b57cec5SDimitry Andric }
716