123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710 |
- //===- llvm-readobj.cpp - Dump contents of an Object File -----------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This is a tool similar to readelf, except it works on multiple object file
- // formats. The main purpose of this tool is to provide detailed output suitable
- // for FileCheck.
- //
- // Flags should be similar to readelf where supported, but the output format
- // does not need to be identical. The point is to not make users learn yet
- // another set of flags.
- //
- // Output should be specialized for each format where appropriate.
- //
- //===----------------------------------------------------------------------===//
- #include "llvm-readobj.h"
- #include "ObjDumper.h"
- #include "WindowsResourceDumper.h"
- #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
- #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
- #include "llvm/MC/TargetRegistry.h"
- #include "llvm/Object/Archive.h"
- #include "llvm/Object/COFFImportFile.h"
- #include "llvm/Object/ELFObjectFile.h"
- #include "llvm/Object/MachOUniversal.h"
- #include "llvm/Object/ObjectFile.h"
- #include "llvm/Object/Wasm.h"
- #include "llvm/Object/WindowsResource.h"
- #include "llvm/Object/XCOFFObjectFile.h"
- #include "llvm/Option/Arg.h"
- #include "llvm/Option/ArgList.h"
- #include "llvm/Option/Option.h"
- #include "llvm/Support/Casting.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/DataTypes.h"
- #include "llvm/Support/Debug.h"
- #include "llvm/Support/Errc.h"
- #include "llvm/Support/FileSystem.h"
- #include "llvm/Support/FormatVariadic.h"
- #include "llvm/Support/InitLLVM.h"
- #include "llvm/Support/Path.h"
- #include "llvm/Support/ScopedPrinter.h"
- #include "llvm/Support/WithColor.h"
- using namespace llvm;
- using namespace llvm::object;
- namespace {
- using namespace llvm::opt; // for HelpHidden in Opts.inc
- enum ID {
- OPT_INVALID = 0, // This is not an option ID.
- #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- OPT_##ID,
- #include "Opts.inc"
- #undef OPTION
- };
- #define PREFIX(NAME, VALUE) \
- static constexpr StringLiteral NAME##_init[] = VALUE; \
- static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
- std::size(NAME##_init) - 1);
- #include "Opts.inc"
- #undef PREFIX
- static constexpr opt::OptTable::Info InfoTable[] = {
- #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- { \
- PREFIX, NAME, HELPTEXT, \
- METAVAR, OPT_##ID, opt::Option::KIND##Class, \
- PARAM, FLAGS, OPT_##GROUP, \
- OPT_##ALIAS, ALIASARGS, VALUES},
- #include "Opts.inc"
- #undef OPTION
- };
- class ReadobjOptTable : public opt::GenericOptTable {
- public:
- ReadobjOptTable() : opt::GenericOptTable(InfoTable) {
- setGroupedShortOptions(true);
- }
- };
- enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
- enum SortSymbolKeyTy {
- NAME = 0,
- TYPE = 1,
- UNKNOWN = 100,
- // TODO: add ADDRESS, SIZE as needed.
- };
- } // namespace
- namespace opts {
- static bool Addrsig;
- static bool All;
- static bool ArchSpecificInfo;
- static bool BBAddrMap;
- bool ExpandRelocs;
- static bool CGProfile;
- bool Demangle;
- static bool DependentLibraries;
- static bool DynRelocs;
- static bool DynamicSymbols;
- static bool FileHeaders;
- static bool Headers;
- static std::vector<std::string> HexDump;
- static bool PrettyPrint;
- static bool PrintStackMap;
- static bool PrintStackSizes;
- static bool Relocations;
- bool SectionData;
- static bool SectionDetails;
- static bool SectionHeaders;
- bool SectionRelocations;
- bool SectionSymbols;
- static std::vector<std::string> StringDump;
- static bool StringTable;
- static bool Symbols;
- static bool UnwindInfo;
- static cl::boolOrDefault SectionMapping;
- static SmallVector<SortSymbolKeyTy> SortKeys;
- // ELF specific options.
- static bool DynamicTable;
- static bool ELFLinkerOptions;
- static bool GnuHashTable;
- static bool HashSymbols;
- static bool HashTable;
- static bool HashHistogram;
- static bool NeededLibraries;
- static bool Notes;
- static bool ProgramHeaders;
- bool RawRelr;
- static bool SectionGroups;
- static bool VersionInfo;
- // Mach-O specific options.
- static bool MachODataInCode;
- static bool MachODysymtab;
- static bool MachOIndirectSymbols;
- static bool MachOLinkerOptions;
- static bool MachOSegment;
- static bool MachOVersionMin;
- // PE/COFF specific options.
- static bool CodeView;
- static bool CodeViewEnableGHash;
- static bool CodeViewMergedTypes;
- bool CodeViewSubsectionBytes;
- static bool COFFBaseRelocs;
- static bool COFFDebugDirectory;
- static bool COFFDirectives;
- static bool COFFExports;
- static bool COFFImports;
- static bool COFFLoadConfig;
- static bool COFFResources;
- static bool COFFTLSDirectory;
- // XCOFF specific options.
- static bool XCOFFAuxiliaryHeader;
- static bool XCOFFLoaderSectionHeader;
- static bool XCOFFLoaderSectionSymbol;
- static bool XCOFFLoaderSectionRelocation;
- static bool XCOFFExceptionSection;
- OutputStyleTy Output = OutputStyleTy::LLVM;
- static std::vector<std::string> InputFilenames;
- } // namespace opts
- static StringRef ToolName;
- namespace llvm {
- [[noreturn]] static void error(Twine Msg) {
- // Flush the standard output to print the error at a
- // proper place.
- fouts().flush();
- WithColor::error(errs(), ToolName) << Msg << "\n";
- exit(1);
- }
- [[noreturn]] void reportError(Error Err, StringRef Input) {
- assert(Err);
- if (Input == "-")
- Input = "<stdin>";
- handleAllErrors(createFileError(Input, std::move(Err)),
- [&](const ErrorInfoBase &EI) { error(EI.message()); });
- llvm_unreachable("error() call should never return");
- }
- void reportWarning(Error Err, StringRef Input) {
- assert(Err);
- if (Input == "-")
- Input = "<stdin>";
- // Flush the standard output to print the warning at a
- // proper place.
- fouts().flush();
- handleAllErrors(
- createFileError(Input, std::move(Err)), [&](const ErrorInfoBase &EI) {
- WithColor::warning(errs(), ToolName) << EI.message() << "\n";
- });
- }
- } // namespace llvm
- static void parseOptions(const opt::InputArgList &Args) {
- opts::Addrsig = Args.hasArg(OPT_addrsig);
- opts::All = Args.hasArg(OPT_all);
- opts::ArchSpecificInfo = Args.hasArg(OPT_arch_specific);
- opts::BBAddrMap = Args.hasArg(OPT_bb_addr_map);
- opts::CGProfile = Args.hasArg(OPT_cg_profile);
- opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
- opts::DependentLibraries = Args.hasArg(OPT_dependent_libraries);
- opts::DynRelocs = Args.hasArg(OPT_dyn_relocations);
- opts::DynamicSymbols = Args.hasArg(OPT_dyn_syms);
- opts::ExpandRelocs = Args.hasArg(OPT_expand_relocs);
- opts::FileHeaders = Args.hasArg(OPT_file_header);
- opts::Headers = Args.hasArg(OPT_headers);
- opts::HexDump = Args.getAllArgValues(OPT_hex_dump_EQ);
- opts::Relocations = Args.hasArg(OPT_relocs);
- opts::SectionData = Args.hasArg(OPT_section_data);
- opts::SectionDetails = Args.hasArg(OPT_section_details);
- opts::SectionHeaders = Args.hasArg(OPT_section_headers);
- opts::SectionRelocations = Args.hasArg(OPT_section_relocations);
- opts::SectionSymbols = Args.hasArg(OPT_section_symbols);
- if (Args.hasArg(OPT_section_mapping))
- opts::SectionMapping = cl::BOU_TRUE;
- else if (Args.hasArg(OPT_section_mapping_EQ_false))
- opts::SectionMapping = cl::BOU_FALSE;
- else
- opts::SectionMapping = cl::BOU_UNSET;
- opts::PrintStackSizes = Args.hasArg(OPT_stack_sizes);
- opts::PrintStackMap = Args.hasArg(OPT_stackmap);
- opts::StringDump = Args.getAllArgValues(OPT_string_dump_EQ);
- opts::StringTable = Args.hasArg(OPT_string_table);
- opts::Symbols = Args.hasArg(OPT_symbols);
- opts::UnwindInfo = Args.hasArg(OPT_unwind);
- // ELF specific options.
- opts::DynamicTable = Args.hasArg(OPT_dynamic_table);
- opts::ELFLinkerOptions = Args.hasArg(OPT_elf_linker_options);
- if (Arg *A = Args.getLastArg(OPT_elf_output_style_EQ)) {
- std::string OutputStyleChoice = A->getValue();
- opts::Output = StringSwitch<opts::OutputStyleTy>(OutputStyleChoice)
- .Case("LLVM", opts::OutputStyleTy::LLVM)
- .Case("GNU", opts::OutputStyleTy::GNU)
- .Case("JSON", opts::OutputStyleTy::JSON)
- .Default(opts::OutputStyleTy::UNKNOWN);
- if (opts::Output == opts::OutputStyleTy::UNKNOWN) {
- error("--elf-output-style value should be either 'LLVM', 'GNU', or "
- "'JSON', but was '" +
- OutputStyleChoice + "'");
- }
- }
- opts::GnuHashTable = Args.hasArg(OPT_gnu_hash_table);
- opts::HashSymbols = Args.hasArg(OPT_hash_symbols);
- opts::HashTable = Args.hasArg(OPT_hash_table);
- opts::HashHistogram = Args.hasArg(OPT_histogram);
- opts::NeededLibraries = Args.hasArg(OPT_needed_libs);
- opts::Notes = Args.hasArg(OPT_notes);
- opts::PrettyPrint = Args.hasArg(OPT_pretty_print);
- opts::ProgramHeaders = Args.hasArg(OPT_program_headers);
- opts::RawRelr = Args.hasArg(OPT_raw_relr);
- opts::SectionGroups = Args.hasArg(OPT_section_groups);
- if (Arg *A = Args.getLastArg(OPT_sort_symbols_EQ)) {
- std::string SortKeysString = A->getValue();
- for (StringRef KeyStr : llvm::split(A->getValue(), ",")) {
- SortSymbolKeyTy KeyType = StringSwitch<SortSymbolKeyTy>(KeyStr)
- .Case("name", SortSymbolKeyTy::NAME)
- .Case("type", SortSymbolKeyTy::TYPE)
- .Default(SortSymbolKeyTy::UNKNOWN);
- if (KeyType == SortSymbolKeyTy::UNKNOWN)
- error("--sort-symbols value should be 'name' or 'type', but was '" +
- Twine(KeyStr) + "'");
- opts::SortKeys.push_back(KeyType);
- }
- }
- opts::VersionInfo = Args.hasArg(OPT_version_info);
- // Mach-O specific options.
- opts::MachODataInCode = Args.hasArg(OPT_macho_data_in_code);
- opts::MachODysymtab = Args.hasArg(OPT_macho_dysymtab);
- opts::MachOIndirectSymbols = Args.hasArg(OPT_macho_indirect_symbols);
- opts::MachOLinkerOptions = Args.hasArg(OPT_macho_linker_options);
- opts::MachOSegment = Args.hasArg(OPT_macho_segment);
- opts::MachOVersionMin = Args.hasArg(OPT_macho_version_min);
- // PE/COFF specific options.
- opts::CodeView = Args.hasArg(OPT_codeview);
- opts::CodeViewEnableGHash = Args.hasArg(OPT_codeview_ghash);
- opts::CodeViewMergedTypes = Args.hasArg(OPT_codeview_merged_types);
- opts::CodeViewSubsectionBytes = Args.hasArg(OPT_codeview_subsection_bytes);
- opts::COFFBaseRelocs = Args.hasArg(OPT_coff_basereloc);
- opts::COFFDebugDirectory = Args.hasArg(OPT_coff_debug_directory);
- opts::COFFDirectives = Args.hasArg(OPT_coff_directives);
- opts::COFFExports = Args.hasArg(OPT_coff_exports);
- opts::COFFImports = Args.hasArg(OPT_coff_imports);
- opts::COFFLoadConfig = Args.hasArg(OPT_coff_load_config);
- opts::COFFResources = Args.hasArg(OPT_coff_resources);
- opts::COFFTLSDirectory = Args.hasArg(OPT_coff_tls_directory);
- // XCOFF specific options.
- opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header);
- opts::XCOFFLoaderSectionHeader = Args.hasArg(OPT_loader_section_header);
- opts::XCOFFLoaderSectionSymbol = Args.hasArg(OPT_loader_section_symbols);
- opts::XCOFFLoaderSectionRelocation =
- Args.hasArg(OPT_loader_section_relocations);
- opts::XCOFFExceptionSection = Args.hasArg(OPT_exception_section);
- opts::InputFilenames = Args.getAllArgValues(OPT_INPUT);
- }
- namespace {
- struct ReadObjTypeTableBuilder {
- ReadObjTypeTableBuilder()
- : IDTable(Allocator), TypeTable(Allocator), GlobalIDTable(Allocator),
- GlobalTypeTable(Allocator) {}
- llvm::BumpPtrAllocator Allocator;
- llvm::codeview::MergingTypeTableBuilder IDTable;
- llvm::codeview::MergingTypeTableBuilder TypeTable;
- llvm::codeview::GlobalTypeTableBuilder GlobalIDTable;
- llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable;
- std::vector<OwningBinary<Binary>> Binaries;
- };
- } // namespace
- static ReadObjTypeTableBuilder CVTypes;
- /// Creates an format-specific object file dumper.
- static Expected<std::unique_ptr<ObjDumper>>
- createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) {
- if (const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(&Obj))
- return createCOFFDumper(*COFFObj, Writer);
- if (const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
- return createELFDumper(*ELFObj, Writer);
- if (const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(&Obj))
- return createMachODumper(*MachOObj, Writer);
- if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj))
- return createWasmDumper(*WasmObj, Writer);
- if (const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(&Obj))
- return createXCOFFDumper(*XObj, Writer);
- return createStringError(errc::invalid_argument,
- "unsupported object file format");
- }
- /// Dumps the specified object file.
- static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
- const Archive *A = nullptr) {
- std::string FileStr =
- A ? Twine(A->getFileName() + "(" + Obj.getFileName() + ")").str()
- : Obj.getFileName().str();
- std::string ContentErrString;
- if (Error ContentErr = Obj.initContent())
- ContentErrString = "unable to continue dumping, the file is corrupt: " +
- toString(std::move(ContentErr));
- ObjDumper *Dumper;
- std::optional<SymbolComparator> SymComp;
- Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer);
- if (!DumperOrErr)
- reportError(DumperOrErr.takeError(), FileStr);
- Dumper = (*DumperOrErr).get();
- if (!opts::SortKeys.empty()) {
- if (Dumper->canCompareSymbols()) {
- SymComp = SymbolComparator();
- for (SortSymbolKeyTy Key : opts::SortKeys) {
- switch (Key) {
- case NAME:
- SymComp->addPredicate([Dumper](SymbolRef LHS, SymbolRef RHS) {
- return Dumper->compareSymbolsByName(LHS, RHS);
- });
- break;
- case TYPE:
- SymComp->addPredicate([Dumper](SymbolRef LHS, SymbolRef RHS) {
- return Dumper->compareSymbolsByType(LHS, RHS);
- });
- break;
- case UNKNOWN:
- llvm_unreachable("Unsupported sort key");
- }
- }
- } else {
- reportWarning(createStringError(
- errc::invalid_argument,
- "--sort-symbols is not supported yet for this format"),
- FileStr);
- }
- }
- Dumper->printFileSummary(FileStr, Obj, opts::InputFilenames, A);
- if (opts::FileHeaders)
- Dumper->printFileHeaders();
- // Auxiliary header in XOCFF is right after the file header, so print the data
- // here.
- if (Obj.isXCOFF() && opts::XCOFFAuxiliaryHeader)
- Dumper->printAuxiliaryHeader();
- // This is only used for ELF currently. In some cases, when an object is
- // corrupt (e.g. truncated), we can't dump anything except the file header.
- if (!ContentErrString.empty())
- reportError(createError(ContentErrString), FileStr);
- if (opts::SectionDetails || opts::SectionHeaders) {
- if (opts::Output == opts::GNU && opts::SectionDetails)
- Dumper->printSectionDetails();
- else
- Dumper->printSectionHeaders();
- }
- if (opts::HashSymbols)
- Dumper->printHashSymbols();
- if (opts::ProgramHeaders || opts::SectionMapping == cl::BOU_TRUE)
- Dumper->printProgramHeaders(opts::ProgramHeaders, opts::SectionMapping);
- if (opts::DynamicTable)
- Dumper->printDynamicTable();
- if (opts::NeededLibraries)
- Dumper->printNeededLibraries();
- if (opts::Relocations)
- Dumper->printRelocations();
- if (opts::DynRelocs)
- Dumper->printDynamicRelocations();
- if (opts::UnwindInfo)
- Dumper->printUnwindInfo();
- if (opts::Symbols || opts::DynamicSymbols)
- Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols, SymComp);
- if (!opts::StringDump.empty())
- Dumper->printSectionsAsString(Obj, opts::StringDump);
- if (!opts::HexDump.empty())
- Dumper->printSectionsAsHex(Obj, opts::HexDump);
- if (opts::HashTable)
- Dumper->printHashTable();
- if (opts::GnuHashTable)
- Dumper->printGnuHashTable();
- if (opts::VersionInfo)
- Dumper->printVersionInfo();
- if (opts::StringTable)
- Dumper->printStringTable();
- if (Obj.isELF()) {
- if (opts::DependentLibraries)
- Dumper->printDependentLibs();
- if (opts::ELFLinkerOptions)
- Dumper->printELFLinkerOptions();
- if (opts::ArchSpecificInfo)
- Dumper->printArchSpecificInfo();
- if (opts::SectionGroups)
- Dumper->printGroupSections();
- if (opts::HashHistogram)
- Dumper->printHashHistograms();
- if (opts::CGProfile)
- Dumper->printCGProfile();
- if (opts::BBAddrMap)
- Dumper->printBBAddrMaps();
- if (opts::Addrsig)
- Dumper->printAddrsig();
- if (opts::Notes)
- Dumper->printNotes();
- }
- if (Obj.isCOFF()) {
- if (opts::COFFImports)
- Dumper->printCOFFImports();
- if (opts::COFFExports)
- Dumper->printCOFFExports();
- if (opts::COFFDirectives)
- Dumper->printCOFFDirectives();
- if (opts::COFFBaseRelocs)
- Dumper->printCOFFBaseReloc();
- if (opts::COFFDebugDirectory)
- Dumper->printCOFFDebugDirectory();
- if (opts::COFFTLSDirectory)
- Dumper->printCOFFTLSDirectory();
- if (opts::COFFResources)
- Dumper->printCOFFResources();
- if (opts::COFFLoadConfig)
- Dumper->printCOFFLoadConfig();
- if (opts::CGProfile)
- Dumper->printCGProfile();
- if (opts::Addrsig)
- Dumper->printAddrsig();
- if (opts::CodeView)
- Dumper->printCodeViewDebugInfo();
- if (opts::CodeViewMergedTypes)
- Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable,
- CVTypes.GlobalIDTable, CVTypes.GlobalTypeTable,
- opts::CodeViewEnableGHash);
- }
- if (Obj.isMachO()) {
- if (opts::MachODataInCode)
- Dumper->printMachODataInCode();
- if (opts::MachOIndirectSymbols)
- Dumper->printMachOIndirectSymbols();
- if (opts::MachOLinkerOptions)
- Dumper->printMachOLinkerOptions();
- if (opts::MachOSegment)
- Dumper->printMachOSegment();
- if (opts::MachOVersionMin)
- Dumper->printMachOVersionMin();
- if (opts::MachODysymtab)
- Dumper->printMachODysymtab();
- if (opts::CGProfile)
- Dumper->printCGProfile();
- }
- if (Obj.isXCOFF()) {
- if (opts::XCOFFLoaderSectionHeader || opts::XCOFFLoaderSectionSymbol ||
- opts::XCOFFLoaderSectionRelocation)
- Dumper->printLoaderSection(opts::XCOFFLoaderSectionHeader,
- opts::XCOFFLoaderSectionSymbol,
- opts::XCOFFLoaderSectionRelocation);
- if (opts::XCOFFExceptionSection)
- Dumper->printExceptionSection();
- }
- if (opts::PrintStackMap)
- Dumper->printStackMap();
- if (opts::PrintStackSizes)
- Dumper->printStackSizes();
- }
- /// Dumps each object file in \a Arc;
- static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) {
- Error Err = Error::success();
- for (auto &Child : Arc->children(Err)) {
- Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
- if (!ChildOrErr) {
- if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
- reportError(std::move(E), Arc->getFileName());
- continue;
- }
- Binary *Bin = ChildOrErr->get();
- if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin))
- dumpObject(*Obj, Writer, Arc);
- else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(Bin))
- dumpCOFFImportFile(Imp, Writer);
- else
- reportWarning(createStringError(errc::invalid_argument,
- Bin->getFileName() +
- " has an unsupported file type"),
- Arc->getFileName());
- }
- if (Err)
- reportError(std::move(Err), Arc->getFileName());
- }
- /// Dumps each object file in \a MachO Universal Binary;
- static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
- ScopedPrinter &Writer) {
- for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) {
- Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile();
- if (ObjOrErr)
- dumpObject(*ObjOrErr.get(), Writer);
- else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
- reportError(ObjOrErr.takeError(), UBinary->getFileName());
- else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive())
- dumpArchive(&*AOrErr.get(), Writer);
- }
- }
- /// Dumps \a WinRes, Windows Resource (.res) file;
- static void dumpWindowsResourceFile(WindowsResource *WinRes,
- ScopedPrinter &Printer) {
- WindowsRes::Dumper Dumper(WinRes, Printer);
- if (auto Err = Dumper.printData())
- reportError(std::move(Err), WinRes->getFileName());
- }
- /// Opens \a File and dumps it.
- static void dumpInput(StringRef File, ScopedPrinter &Writer) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
- MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false,
- /*RequiresNullTerminator=*/false);
- if (std::error_code EC = FileOrErr.getError())
- return reportError(errorCodeToError(EC), File);
- std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
- file_magic Type = identify_magic(Buffer->getBuffer());
- if (Type == file_magic::bitcode) {
- reportWarning(createStringError(errc::invalid_argument,
- "bitcode files are not supported"),
- File);
- return;
- }
- Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary(
- Buffer->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
- if (!BinaryOrErr)
- reportError(BinaryOrErr.takeError(), File);
- std::unique_ptr<Binary> Bin = std::move(*BinaryOrErr);
- if (Archive *Arc = dyn_cast<Archive>(Bin.get()))
- dumpArchive(Arc, Writer);
- else if (MachOUniversalBinary *UBinary =
- dyn_cast<MachOUniversalBinary>(Bin.get()))
- dumpMachOUniversalBinary(UBinary, Writer);
- else if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin.get()))
- dumpObject(*Obj, Writer);
- else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(Bin.get()))
- dumpCOFFImportFile(Import, Writer);
- else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(Bin.get()))
- dumpWindowsResourceFile(WinRes, Writer);
- else
- llvm_unreachable("unrecognized file type");
- CVTypes.Binaries.push_back(
- OwningBinary<Binary>(std::move(Bin), std::move(Buffer)));
- }
- std::unique_ptr<ScopedPrinter> createWriter() {
- if (opts::Output == opts::JSON)
- return std::make_unique<JSONScopedPrinter>(
- fouts(), opts::PrettyPrint ? 2 : 0, std::make_unique<ListScope>());
- return std::make_unique<ScopedPrinter>(fouts());
- }
- int llvm_readobj_main(int argc, char **argv) {
- InitLLVM X(argc, argv);
- BumpPtrAllocator A;
- StringSaver Saver(A);
- ReadobjOptTable Tbl;
- ToolName = argv[0];
- opt::InputArgList Args =
- Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
- error(Msg);
- exit(1);
- });
- if (Args.hasArg(OPT_help)) {
- Tbl.printHelp(
- outs(),
- (Twine(ToolName) + " [options] <input object files>").str().c_str(),
- "LLVM Object Reader");
- // TODO Replace this with OptTable API once it adds extrahelp support.
- outs() << "\nPass @FILE as argument to read options from FILE.\n";
- return 0;
- }
- if (Args.hasArg(OPT_version)) {
- cl::PrintVersionMessage();
- return 0;
- }
- if (sys::path::stem(argv[0]).contains("readelf"))
- opts::Output = opts::GNU;
- parseOptions(Args);
- // Default to print error if no filename is specified.
- if (opts::InputFilenames.empty()) {
- error("no input files specified");
- }
- if (opts::All) {
- opts::FileHeaders = true;
- opts::XCOFFAuxiliaryHeader = true;
- opts::ProgramHeaders = true;
- opts::SectionHeaders = true;
- opts::Symbols = true;
- opts::Relocations = true;
- opts::DynamicTable = true;
- opts::Notes = true;
- opts::VersionInfo = true;
- opts::UnwindInfo = true;
- opts::SectionGroups = true;
- opts::HashHistogram = true;
- if (opts::Output == opts::LLVM) {
- opts::Addrsig = true;
- opts::PrintStackSizes = true;
- }
- }
- if (opts::Headers) {
- opts::FileHeaders = true;
- opts::XCOFFAuxiliaryHeader = true;
- opts::ProgramHeaders = true;
- opts::SectionHeaders = true;
- }
- std::unique_ptr<ScopedPrinter> Writer = createWriter();
- for (const std::string &I : opts::InputFilenames)
- dumpInput(I, *Writer.get());
- if (opts::CodeViewMergedTypes) {
- if (opts::CodeViewEnableGHash)
- dumpCodeViewMergedTypes(*Writer.get(), CVTypes.GlobalIDTable.records(),
- CVTypes.GlobalTypeTable.records());
- else
- dumpCodeViewMergedTypes(*Writer.get(), CVTypes.IDTable.records(),
- CVTypes.TypeTable.records());
- }
- return 0;
- }
|