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