brintos

brintos / llvm-project-archived public Read only

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