//===-- llvm-objdump.cpp - Object file dumping utility for llvm -----------===//
//
// 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 program is a utility that works like binutils "objdump", that is, it
// dumps out a plethora of information about an object file depending on the
// flags.
//
// The flags and output of this program should be near identical to those of
// binutils objdump.
//
//===----------------------------------------------------------------------===//

#include "llvm-objdump.h"
#include "COFFDump.h"
#include "ELFDump.h"
#include "MachODump.h"
#include "ObjdumpOptID.h"
#include "OffloadDump.h"
#include "SourcePrinter.h"
#include "WasmDump.h"
#include "XCOFFDump.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/DebugInfo/BTF/BTFParser.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
#include "llvm/Debuginfod/BuildIDFetcher.h"
#include "llvm/Debuginfod/Debuginfod.h"
#include "llvm/Debuginfod/HTTPClient.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/BuildID.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/COFFImportFile.h"
#include "llvm/Object/DXContainer.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/Object/FaultMapParser.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/OffloadBinary.h"
#include "llvm/Object/Wasm.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cctype>
#include <cstring>
#include <optional>
#include <set>
#include <system_error>
#include <unordered_map>
#include <utility>

using namespace llvm;
using namespace llvm::object;
using namespace llvm::objdump;
using namespace llvm::opt;

namespace {

class CommonOptTable : public opt::GenericOptTable {
public:
  CommonOptTable(const StringTable &StrTable,
                 ArrayRef<StringTable::Offset> PrefixesTable,
                 ArrayRef<Info> OptionInfos, const char *Usage,
                 const char *Description)
      : opt::GenericOptTable(StrTable, PrefixesTable, OptionInfos),
        Usage(Usage), Description(Description) {
    setGroupedShortOptions(true);
  }

  void printHelp(StringRef Argv0, bool ShowHidden = false) const {
    Argv0 = sys::path::filename(Argv0);
    opt::GenericOptTable::printHelp(outs(), (Argv0 + Usage).str().c_str(),
                                    Description, ShowHidden, ShowHidden);
    // TODO Replace this with OptTable API once it adds extrahelp support.
    outs() << "\nPass @FILE as argument to read options from FILE.\n";
  }

private:
  const char *Usage;
  const char *Description;
};

// ObjdumpOptID is in ObjdumpOptID.h
namespace objdump_opt {
#define OPTTABLE_STR_TABLE_CODE
#include "ObjdumpOpts.inc"
#undef OPTTABLE_STR_TABLE_CODE

#define OPTTABLE_PREFIXES_TABLE_CODE
#include "ObjdumpOpts.inc"
#undef OPTTABLE_PREFIXES_TABLE_CODE

static constexpr opt::OptTable::Info ObjdumpInfoTable[] = {
#define OPTION(...)                                                            \
  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJDUMP_, __VA_ARGS__),
#include "ObjdumpOpts.inc"
#undef OPTION
};
} // namespace objdump_opt

class ObjdumpOptTable : public CommonOptTable {
public:
  ObjdumpOptTable()
      : CommonOptTable(
            objdump_opt::OptionStrTable, objdump_opt::OptionPrefixesTable,
            objdump_opt::ObjdumpInfoTable, " [options] <input object files>",
            "llvm object file dumper") {}
};

enum OtoolOptID {
  OTOOL_INVALID = 0, // This is not an option ID.
#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OTOOL_, __VA_ARGS__),
#include "OtoolOpts.inc"
#undef OPTION
};

namespace otool {
#define OPTTABLE_STR_TABLE_CODE
#include "OtoolOpts.inc"
#undef OPTTABLE_STR_TABLE_CODE

#define OPTTABLE_PREFIXES_TABLE_CODE
#include "OtoolOpts.inc"
#undef OPTTABLE_PREFIXES_TABLE_CODE

static constexpr opt::OptTable::Info OtoolInfoTable[] = {
#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OTOOL_, __VA_ARGS__),
#include "OtoolOpts.inc"
#undef OPTION
};
} // namespace otool

class OtoolOptTable : public CommonOptTable {
public:
  OtoolOptTable()
      : CommonOptTable(otool::OptionStrTable, otool::OptionPrefixesTable,
                       otool::OtoolInfoTable, " [option...] [file...]",
                       "Mach-O object file displaying tool") {}
};

struct BBAddrMapLabel {
  std::string BlockLabel;
  std::string PGOAnalysis;
};

// This class represents the BBAddrMap and PGOMap associated with a single
// function.
class BBAddrMapFunctionEntry {
public:
  BBAddrMapFunctionEntry(BBAddrMap AddrMap, PGOAnalysisMap PGOMap)
      : AddrMap(std::move(AddrMap)), PGOMap(std::move(PGOMap)) {}

  const BBAddrMap &getAddrMap() const { return AddrMap; }

  // Returns the PGO string associated with the entry of index `PGOBBEntryIndex`
  // in `PGOMap`. If PrettyPGOAnalysis is true, prints BFI as relative frequency
  // and BPI as percentage. Otherwise raw values are displayed.
  std::string constructPGOLabelString(size_t PGOBBEntryIndex,
                                      bool PrettyPGOAnalysis) const {
    if (!PGOMap.FeatEnable.hasPGOAnalysis())
      return "";
    std::string PGOString;
    raw_string_ostream PGOSS(PGOString);

    PGOSS << " (";
    if (PGOMap.FeatEnable.FuncEntryCount && PGOBBEntryIndex == 0) {
      PGOSS << "Entry count: " << Twine(PGOMap.FuncEntryCount);
      if (PGOMap.FeatEnable.hasPGOAnalysisBBData()) {
        PGOSS << ", ";
      }
    }

    if (PGOMap.FeatEnable.hasPGOAnalysisBBData()) {

      assert(PGOBBEntryIndex < PGOMap.BBEntries.size() &&
             "Expected PGOAnalysisMap and BBAddrMap to have the same entries");
      const PGOAnalysisMap::PGOBBEntry &PGOBBEntry =
          PGOMap.BBEntries[PGOBBEntryIndex];

      if (PGOMap.FeatEnable.BBFreq) {
        PGOSS << "Frequency: ";
        if (PrettyPGOAnalysis)
          printRelativeBlockFreq(PGOSS, PGOMap.BBEntries.front().BlockFreq,
                                 PGOBBEntry.BlockFreq);
        else
          PGOSS << Twine(PGOBBEntry.BlockFreq.getFrequency());
        if (PGOMap.FeatEnable.BrProb && PGOBBEntry.Successors.size() > 0) {
          PGOSS << ", ";
        }
      }
      if (PGOMap.FeatEnable.BrProb && PGOBBEntry.Successors.size() > 0) {
        PGOSS << "Successors: ";
        interleaveComma(
            PGOBBEntry.Successors, PGOSS,
            [&](const PGOAnalysisMap::PGOBBEntry::SuccessorEntry &SE) {
              PGOSS << "BB" << SE.ID << ":";
              if (PrettyPGOAnalysis)
                PGOSS << "[" << SE.Prob << "]";
              else
                PGOSS.write_hex(SE.Prob.getNumerator());
            });
      }
    }
    PGOSS << ")";

    return PGOString;
  }

private:
  const BBAddrMap AddrMap;
  const PGOAnalysisMap PGOMap;
};

// This class represents the BBAddrMap and PGOMap of potentially multiple
// functions in a section.
class BBAddrMapInfo {
public:
  void clear() {
    FunctionAddrToMap.clear();
    RangeBaseAddrToFunctionAddr.clear();
  }

  bool empty() const { return FunctionAddrToMap.empty(); }

  void AddFunctionEntry(BBAddrMap AddrMap, PGOAnalysisMap PGOMap) {
    uint64_t FunctionAddr = AddrMap.getFunctionAddress();
    for (size_t I = 1; I < AddrMap.BBRanges.size(); ++I)
      RangeBaseAddrToFunctionAddr.emplace(AddrMap.BBRanges[I].BaseAddress,
                                          FunctionAddr);
    [[maybe_unused]] auto R = FunctionAddrToMap.try_emplace(
        FunctionAddr, std::move(AddrMap), std::move(PGOMap));
    assert(R.second && "duplicate function address");
  }

  // Returns the BBAddrMap entry for the function associated with `BaseAddress`.
  // `BaseAddress` could be the function address or the address of a range
  // associated with that function. Returns `nullptr` if `BaseAddress` is not
  // mapped to any entry.
  const BBAddrMapFunctionEntry *getEntryForAddress(uint64_t BaseAddress) const {
    uint64_t FunctionAddr = BaseAddress;
    auto S = RangeBaseAddrToFunctionAddr.find(BaseAddress);
    if (S != RangeBaseAddrToFunctionAddr.end())
      FunctionAddr = S->second;
    auto R = FunctionAddrToMap.find(FunctionAddr);
    if (R == FunctionAddrToMap.end())
      return nullptr;
    return &R->second;
  }

private:
  std::unordered_map<uint64_t, BBAddrMapFunctionEntry> FunctionAddrToMap;
  std::unordered_map<uint64_t, uint64_t> RangeBaseAddrToFunctionAddr;
};

} // namespace

#define DEBUG_TYPE "objdump"

enum class ColorOutput {
  Auto,
  Enable,
  Disable,
  Invalid,
};

static uint64_t AdjustVMA;
static bool AllHeaders;
static std::string ArchName;
bool objdump::ArchiveHeaders;
bool objdump::Demangle;
bool objdump::Disassemble;
bool objdump::DisassembleAll;
std::vector<std::string> objdump::DisassemblerOptions;
bool objdump::SymbolDescription;
bool objdump::TracebackTable;
static std::vector<std::string> DisassembleSymbols;
static bool DisassembleZeroes;
static ColorOutput DisassemblyColor;
DIDumpType objdump::DwarfDumpType;
static bool DynamicRelocations;
static bool FaultMapSection;
static bool FileHeaders;
bool objdump::SectionContents;
static std::vector<std::string> InputFilenames;
bool objdump::PrintLines;
static bool MachOOpt;
std::string objdump::MCPU;
std::vector<std::string> objdump::MAttrs;
bool objdump::ShowRawInsn;
bool objdump::LeadingAddr;
static bool Offloading;
static bool RawClangAST;
bool objdump::Relocations;
bool objdump::PrintImmHex;
bool objdump::PrivateHeaders;
std::vector<std::string> objdump::FilterSections;
bool objdump::SectionHeaders;
static bool ShowAllSymbols;
static bool ShowLMA;
bool objdump::PrintSource;

static uint64_t StartAddress;
static bool HasStartAddressFlag;
static uint64_t StopAddress = UINT64_MAX;
static bool HasStopAddressFlag;

bool objdump::SymbolTable;
static bool SymbolizeOperands;
static bool PrettyPGOAnalysisMap;
static bool DynamicSymbolTable;
std::string objdump::TripleName;
bool objdump::UnwindInfo;
static bool Wide;
std::string objdump::Prefix;
uint32_t objdump::PrefixStrip;

DebugFormat objdump::DbgVariables = DFDisabled;
DebugFormat objdump::DbgInlinedFunctions = DFDisabled;

int objdump::DbgIndent = 52;

static StringSet<> DisasmSymbolSet;
StringSet<> objdump::FoundSectionSet;
static StringRef ToolName;

std::unique_ptr<BuildIDFetcher> BIDFetcher;

Dumper::Dumper(const object::ObjectFile &O) : O(O), OS(outs()) {
  WarningHandler = [this](const Twine &Msg) {
    if (Warnings.insert(Msg.str()).second)
      reportWarning(Msg, this->O.getFileName());
    return Error::success();
  };
}

void Dumper::reportUniqueWarning(Error Err) {
  reportUniqueWarning(toString(std::move(Err)));
}

void Dumper::reportUniqueWarning(const Twine &Msg) {
  cantFail(WarningHandler(Msg));
}

static Expected<std::unique_ptr<Dumper>> createDumper(const ObjectFile &Obj) {
  if (const auto *O = dyn_cast<COFFObjectFile>(&Obj))
    return createCOFFDumper(*O);
  if (const auto *O = dyn_cast<ELFObjectFileBase>(&Obj))
    return createELFDumper(*O);
  if (const auto *O = dyn_cast<MachOObjectFile>(&Obj))
    return createMachODumper(*O);
  if (const auto *O = dyn_cast<WasmObjectFile>(&Obj))
    return createWasmDumper(*O);
  if (const auto *O = dyn_cast<XCOFFObjectFile>(&Obj))
    return createXCOFFDumper(*O);
  if (const auto *O = dyn_cast<DXContainerObjectFile>(&Obj))
    return createDXContainerDumper(*O);

  return createStringError(errc::invalid_argument,
                           "unsupported object file format");
}

namespace {
struct FilterResult {
  // True if the section should not be skipped.
  bool Keep;

  // True if the index counter should be incremented, even if the section should
  // be skipped. For example, sections may be skipped if they are not included
  // in the --section flag, but we still want those to count toward the section
  // count.
  bool IncrementIndex;
};
} // namespace

static FilterResult checkSectionFilter(object::SectionRef S) {
  if (FilterSections.empty())
    return {/*Keep=*/true, /*IncrementIndex=*/true};

  Expected<StringRef> SecNameOrErr = S.getName();
  if (!SecNameOrErr) {
    consumeError(SecNameOrErr.takeError());
    return {/*Keep=*/false, /*IncrementIndex=*/false};
  }
  StringRef SecName = *SecNameOrErr;

  // StringSet does not allow empty key so avoid adding sections with
  // no name (such as the section with index 0) here.
  if (!SecName.empty())
    FoundSectionSet.insert(SecName);

  // Only show the section if it's in the FilterSections list, but always
  // increment so the indexing is stable.
  return {/*Keep=*/is_contained(FilterSections, SecName),
          /*IncrementIndex=*/true};
}

SectionFilter objdump::ToolSectionFilter(object::ObjectFile const &O,
                                         uint64_t *Idx) {
  // Start at UINT64_MAX so that the first index returned after an increment is
  // zero (after the unsigned wrap).
  if (Idx)
    *Idx = UINT64_MAX;
  return SectionFilter(
      [Idx](object::SectionRef S) {
        FilterResult Result = checkSectionFilter(S);
        if (Idx != nullptr && Result.IncrementIndex)
          *Idx += 1;
        return Result.Keep;
      },
      O);
}

std::string objdump::getFileNameForError(const object::Archive::Child &C,
                                         unsigned Index) {
  Expected<StringRef> NameOrErr = C.getName();
  if (NameOrErr)
    return std::string(NameOrErr.get());
  // If we have an error getting the name then we print the index of the archive
  // member. Since we are already in an error state, we just ignore this error.
  consumeError(NameOrErr.takeError());
  return "<file index: " + std::to_string(Index) + ">";
}

void objdump::reportWarning(const Twine &Message, StringRef File) {
  // Output order between errs() and outs() matters especially for archive
  // files where the output is per member object.
  outs().flush();
  WithColor::warning(errs(), ToolName)
      << "'" << File << "': " << Message << "\n";
}

[[noreturn]] void objdump::reportError(StringRef File, const Twine &Message) {
  outs().flush();
  WithColor::error(errs(), ToolName) << "'" << File << "': " << Message << "\n";
  exit(1);
}

[[noreturn]] void objdump::reportError(Error E, StringRef FileName,
                                       StringRef ArchiveName,
                                       StringRef ArchitectureName) {
  assert(E);
  outs().flush();
  WithColor::error(errs(), ToolName);
  if (ArchiveName != "")
    errs() << ArchiveName << "(" << FileName << ")";
  else
    errs() << "'" << FileName << "'";
  if (!ArchitectureName.empty())
    errs() << " (for architecture " << ArchitectureName << ")";
  errs() << ": ";
  logAllUnhandledErrors(std::move(E), errs());
  exit(1);
}

static void reportCmdLineWarning(const Twine &Message) {
  WithColor::warning(errs(), ToolName) << Message << "\n";
}

[[noreturn]] static void reportCmdLineError(const Twine &Message) {
  WithColor::error(errs(), ToolName) << Message << "\n";
  exit(1);
}

static void warnOnNoMatchForSections() {
  SetVector<StringRef> MissingSections;
  for (StringRef S : FilterSections) {
    if (FoundSectionSet.count(S))
      return;
    // User may specify a unnamed section. Don't warn for it.
    if (!S.empty())
      MissingSections.insert(S);
  }

  // Warn only if no section in FilterSections is matched.
  for (StringRef S : MissingSections)
    reportCmdLineWarning("section '" + S +
                         "' mentioned in a -j/--section option, but not "
                         "found in any input file");
}

static const Target *getTarget(const ObjectFile *Obj) {
  // Figure out the target triple.
  Triple TheTriple("unknown-unknown-unknown");
  if (TripleName.empty()) {
    TheTriple = Obj->makeTriple();
  } else {
    TheTriple.setTriple(Triple::normalize(TripleName));
    auto Arch = Obj->getArch();
    if (Arch == Triple::arm || Arch == Triple::armeb)
      Obj->setARMSubArch(TheTriple);
  }

  // Get the target specific parser.
  std::string Error;
  const Target *TheTarget =
      TargetRegistry::lookupTarget(ArchName, TheTriple, Error);
  if (!TheTarget)
    reportError(Obj->getFileName(), "can't find target: " + Error);

  // Update the triple name and return the found target.
  TripleName = TheTriple.getTriple();
  return TheTarget;
}

bool objdump::isRelocAddressLess(RelocationRef A, RelocationRef B) {
  return A.getOffset() < B.getOffset();
}

static Error getRelocationValueString(const RelocationRef &Rel,
                                      bool SymbolDescription,
                                      SmallVectorImpl<char> &Result) {
  const ObjectFile *Obj = Rel.getObject();
  if (auto *ELF = dyn_cast<ELFObjectFileBase>(Obj))
    return getELFRelocationValueString(ELF, Rel, Result);
  if (auto *COFF = dyn_cast<COFFObjectFile>(Obj))
    return getCOFFRelocationValueString(COFF, Rel, Result);
  if (auto *Wasm = dyn_cast<WasmObjectFile>(Obj))
    return getWasmRelocationValueString(Wasm, Rel, Result);
  if (auto *MachO = dyn_cast<MachOObjectFile>(Obj))
    return getMachORelocationValueString(MachO, Rel, Result);
  if (auto *XCOFF = dyn_cast<XCOFFObjectFile>(Obj))
    return getXCOFFRelocationValueString(*XCOFF, Rel, SymbolDescription,
                                         Result);
  llvm_unreachable("unknown object file format");
}

/// Indicates whether this relocation should hidden when listing
/// relocations, usually because it is the trailing part of a multipart
/// relocation that will be printed as part of the leading relocation.
static bool getHidden(RelocationRef RelRef) {
  auto *MachO = dyn_cast<MachOObjectFile>(RelRef.getObject());
  if (!MachO)
    return false;

  unsigned Arch = MachO->getArch();
  DataRefImpl Rel = RelRef.getRawDataRefImpl();
  uint64_t Type = MachO->getRelocationType(Rel);

  // On arches that use the generic relocations, GENERIC_RELOC_PAIR
  // is always hidden.
  if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc)
    return Type == MachO::GENERIC_RELOC_PAIR;

  if (Arch == Triple::x86_64) {
    // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
    // an X86_64_RELOC_SUBTRACTOR.
    if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
      DataRefImpl RelPrev = Rel;
      RelPrev.d.a--;
      uint64_t PrevType = MachO->getRelocationType(RelPrev);
      if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
        return true;
    }
  }

  return false;
}

/// Get the column at which we want to start printing the instruction
/// disassembly, taking into account anything which appears to the left of it.
unsigned objdump::getInstStartColumn(const MCSubtargetInfo &STI) {
  return !ShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;
}

static void AlignToInstStartColumn(size_t Start, const MCSubtargetInfo &STI,
                                   raw_ostream &OS) {
  // The output of printInst starts with a tab. Print some spaces so that
  // the tab has 1 column and advances to the target tab stop.
  unsigned TabStop = getInstStartColumn(STI);
  unsigned Column = OS.tell() - Start;
  OS.indent(Column < TabStop - 1 ? TabStop - 1 - Column : 7 - Column % 8);
}

void objdump::printRawData(ArrayRef<uint8_t> Bytes, uint64_t Address,
                           formatted_raw_ostream &OS,
                           MCSubtargetInfo const &STI) {
  size_t Start = OS.tell();
  if (LeadingAddr)
    OS << format("%8" PRIx64 ":", Address);
  if (ShowRawInsn) {
    OS << ' ';
    dumpBytes(Bytes, OS);
  }
  AlignToInstStartColumn(Start, STI, OS);
}

namespace {

static bool isAArch64Elf(const ObjectFile &Obj) {
  const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj);
  return Elf && Elf->getEMachine() == ELF::EM_AARCH64;
}

static bool isArmElf(const ObjectFile &Obj) {
  const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj);
  return Elf && Elf->getEMachine() == ELF::EM_ARM;
}

static bool isCSKYElf(const ObjectFile &Obj) {
  const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj);
  return Elf && Elf->getEMachine() == ELF::EM_CSKY;
}

static bool isRISCVElf(const ObjectFile &Obj) {
  const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj);
  return Elf && Elf->getEMachine() == ELF::EM_RISCV;
}

static bool hasMappingSymbols(const ObjectFile &Obj) {
  return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj) ||
         isRISCVElf(Obj);
}

static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,
                            const RelocationRef &Rel, uint64_t Address,
                            bool Is64Bits) {
  StringRef Fmt = Is64Bits ? "%016" PRIx64 ":  " : "%08" PRIx64 ":  ";
  SmallString<16> Name;
  SmallString<32> Val;
  Rel.getTypeName(Name);
  if (Error E = getRelocationValueString(Rel, SymbolDescription, Val))
    reportError(std::move(E), FileName);
  OS << (Is64Bits || !LeadingAddr ? "\t\t" : "\t\t\t");
  if (LeadingAddr)
    OS << format(Fmt.data(), Address);
  OS << Name << "\t" << Val;
}

static void printBTFRelocation(formatted_raw_ostream &FOS, llvm::BTFParser &BTF,
                               object::SectionedAddress Address,
                               LiveElementPrinter &LEP) {
  const llvm::BTF::BPFFieldReloc *Reloc = BTF.findFieldReloc(Address);
  if (!Reloc)
    return;

  SmallString<64> Val;
  BTF.symbolize(Reloc, Val);
  FOS << "\t\t";
  if (LeadingAddr)
    FOS << format("%016" PRIx64 ":  ", Address.Address + AdjustVMA);
  FOS << "CO-RE " << Val;
  LEP.printAfterOtherLine(FOS, true);
}

class PrettyPrinter {
public:
  virtual ~PrettyPrinter() = default;
  virtual void
  printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
            object::SectionedAddress Address, formatted_raw_ostream &OS,
            StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
            StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
            LiveElementPrinter &LEP) {
    if (SP && (PrintSource || PrintLines))
      SP->printSourceLine(OS, Address, ObjectFilename, LEP);
    LEP.printBoundaryLine(OS, Address, false);
    LEP.printBetweenInsts(OS, false);

    printRawData(Bytes, Address.Address, OS, STI);

    if (MI) {
      // See MCInstPrinter::printInst. On targets where a PC relative immediate
      // is relative to the next instruction and the length of a MCInst is
      // difficult to measure (x86), this is the address of the next
      // instruction.
      uint64_t Addr =
          Address.Address + (STI.getTargetTriple().isX86() ? Bytes.size() : 0);
      IP.printInst(MI, Addr, "", STI, OS);
    } else
      OS << "\t<unknown>";
  }

  virtual void emitPostInstructionInfo(formatted_raw_ostream &FOS,
                                       const MCAsmInfo &MAI,
                                       const MCSubtargetInfo &STI,
                                       StringRef Comments,
                                       LiveElementPrinter &LEP) {
    do {
      if (!Comments.empty()) {
        // Emit a line of comments.
        StringRef Comment;
        std::tie(Comment, Comments) = Comments.split('\n');
        // MAI.getCommentColumn() assumes that instructions are printed at the
        // position of 8, while getInstStartColumn() returns the actual
        // position.
        unsigned CommentColumn =
            MAI.getCommentColumn() - 8 + getInstStartColumn(STI);
        FOS.PadToColumn(CommentColumn);
        FOS << MAI.getCommentString() << ' ' << Comment;
      }
      LEP.printAfterInst(FOS);
      FOS << "\n";
    } while (!Comments.empty());
    FOS.flush();
  }

  // Hook invoked when starting to disassemble a symbol at the current position.
  // Default is no-op.
  virtual void onSymbolStart() {}
};
PrettyPrinter PrettyPrinterInst;

class HexagonPrettyPrinter : public PrettyPrinter {
public:
  void onSymbolStart() override { reset(); }

  void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address,
                 formatted_raw_ostream &OS) {
    if (LeadingAddr)
      OS << format("%8" PRIx64 ":", Address);
    if (ShowRawInsn) {
      OS << "\t";
      if (Bytes.size() >= 4) {
        dumpBytes(Bytes.slice(0, 4), OS);
        uint32_t opcode =
            (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0];
        OS << format("\t%08" PRIx32, opcode);
      } else {
        dumpBytes(Bytes, OS);
      }
    }
  }

  std::string getInstructionSeparator() const {
    SmallString<40> Separator;
    raw_svector_ostream OS(Separator);
    if (ShouldClosePacket) {
      OS << " }";
      if (IsLoop0 || IsLoop1)
        OS << "  ";
      if (IsLoop0)
        OS << (IsLoop1 ? ":endloop01" : ":endloop0");
      else if (IsLoop1)
        OS << ":endloop1";
    }
    OS << '\n';
    return OS.str().str();
  }

  void emitPostInstructionInfo(formatted_raw_ostream &FOS, const MCAsmInfo &MAI,
                               const MCSubtargetInfo &STI, StringRef Comments,
                               LiveElementPrinter &LEP) override {
    // Hexagon does not write anything to the comment stream, so we can just
    // print the separator.
    LEP.printAfterInst(FOS);
    FOS << getInstructionSeparator();
    FOS.flush();
    if (ShouldClosePacket)
      reset();
  }

  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
                 object::SectionedAddress Address, formatted_raw_ostream &OS,
                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
                 LiveElementPrinter &LEP) override {
    if (SP && (PrintSource || PrintLines))
      SP->printSourceLine(OS, Address, ObjectFilename, LEP, "");
    if (!MI) {
      printLead(Bytes, Address.Address, OS);
      OS << " <unknown>";
      reset();
      return;
    }

    StringRef Preamble = IsStartOfBundle ? " { " : "   ";

    if (SP && (PrintSource || PrintLines))
      SP->printSourceLine(OS, Address, ObjectFilename, LEP, "");
    printLead(Bytes, Address.Address, OS);
    OS << Preamble;
    std::string Buf;
    {
      raw_string_ostream TempStream(Buf);
      IP.printInst(MI, Address.Address, "", STI, TempStream);
    }
    StringRef Contents(Buf);

    auto Duplex = Contents.split('\v');
    bool HasDuplex = !Duplex.second.empty();
    if (HasDuplex) {
      OS << Duplex.first;
      OS << "; ";
      OS << Duplex.second;
    } else {
      OS << Duplex.first;
    }

    uint32_t Instruction = support::endian::read32le(Bytes.data());

    uint32_t ParseMask = 0x0000c000;
    uint32_t PacketEndMask = 0x0000c000;
    uint32_t LoopEndMask = 0x00008000;
    uint32_t ParseBits = Instruction & ParseMask;

    if (ParseBits == LoopEndMask) {
      if (IsStartOfBundle)
        IsLoop0 = true;
      else
        IsLoop1 = true;
    }

    IsStartOfBundle = false;

    if (ParseBits == PacketEndMask || HasDuplex)
      ShouldClosePacket = true;
  }

private:
  bool IsStartOfBundle = true;
  bool IsLoop0 = false;
  bool IsLoop1 = false;
  bool ShouldClosePacket = false;

  void reset() {
    IsStartOfBundle = true;
    IsLoop0 = false;
    IsLoop1 = false;
    ShouldClosePacket = false;
  }
};
HexagonPrettyPrinter HexagonPrettyPrinterInst;

class AMDGCNPrettyPrinter : public PrettyPrinter {
public:
  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
                 object::SectionedAddress Address, formatted_raw_ostream &OS,
                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
                 LiveElementPrinter &LEP) override {
    if (SP && (PrintSource || PrintLines))
      SP->printSourceLine(OS, Address, ObjectFilename, LEP);

    if (MI) {
      SmallString<40> InstStr;
      raw_svector_ostream IS(InstStr);

      IP.printInst(MI, Address.Address, "", STI, IS);

      OS << left_justify(IS.str(), 60);
    } else {
      // an unrecognized encoding - this is probably data so represent it
      // using the .long directive, or .byte directive if fewer than 4 bytes
      // remaining
      if (Bytes.size() >= 4) {
        OS << format(
            "\t.long 0x%08" PRIx32 " ",
            support::endian::read32<llvm::endianness::little>(Bytes.data()));
        OS.indent(42);
      } else {
        OS << format("\t.byte 0x%02" PRIx8, Bytes[0]);
        for (unsigned int i = 1; i < Bytes.size(); i++)
          OS << format(", 0x%02" PRIx8, Bytes[i]);
        OS.indent(55 - (6 * Bytes.size()));
      }
    }

    OS << format("// %012" PRIX64 ":", Address.Address);
    if (Bytes.size() >= 4) {
      // D should be casted to uint32_t here as it is passed by format to
      // snprintf as vararg.
      for (uint32_t D :
           ArrayRef(reinterpret_cast<const support::little32_t *>(Bytes.data()),
                    Bytes.size() / 4))
        OS << format(" %08" PRIX32, D);
    } else {
      for (unsigned char B : Bytes)
        OS << format(" %02" PRIX8, B);
    }

    if (!Annot.empty())
      OS << " // " << Annot;
  }
};
AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst;

class BPFPrettyPrinter : public PrettyPrinter {
public:
  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
                 object::SectionedAddress Address, formatted_raw_ostream &OS,
                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
                 LiveElementPrinter &LEP) override {
    if (SP && (PrintSource || PrintLines))
      SP->printSourceLine(OS, Address, ObjectFilename, LEP);
    if (LeadingAddr)
      OS << format("%8" PRId64 ":", Address.Address / 8);
    if (ShowRawInsn) {
      OS << "\t";
      dumpBytes(Bytes, OS);
    }
    if (MI)
      IP.printInst(MI, Address.Address, "", STI, OS);
    else
      OS << "\t<unknown>";
  }
};
BPFPrettyPrinter BPFPrettyPrinterInst;

class ARMPrettyPrinter : public PrettyPrinter {
public:
  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
                 object::SectionedAddress Address, formatted_raw_ostream &OS,
                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
                 LiveElementPrinter &LEP) override {
    if (SP && (PrintSource || PrintLines))
      SP->printSourceLine(OS, Address, ObjectFilename, LEP);
    LEP.printBoundaryLine(OS, Address, false);
    LEP.printBetweenInsts(OS, false);

    size_t Start = OS.tell();
    if (LeadingAddr)
      OS << format("%8" PRIx64 ":", Address.Address);
    if (ShowRawInsn) {
      size_t Pos = 0, End = Bytes.size();
      if (STI.checkFeatures("+thumb-mode")) {
        for (; Pos + 2 <= End; Pos += 2)
          OS << ' '
             << format_hex_no_prefix(
                    llvm::support::endian::read<uint16_t>(
                        Bytes.data() + Pos, InstructionEndianness),
                    4);
      } else {
        for (; Pos + 4 <= End; Pos += 4)
          OS << ' '
             << format_hex_no_prefix(
                    llvm::support::endian::read<uint32_t>(
                        Bytes.data() + Pos, InstructionEndianness),
                    8);
      }
      if (Pos < End) {
        OS << ' ';
        dumpBytes(Bytes.slice(Pos), OS);
      }
    }

    AlignToInstStartColumn(Start, STI, OS);

    if (MI) {
      IP.printInst(MI, Address.Address, "", STI, OS);
    } else
      OS << "\t<unknown>";
  }

  void setInstructionEndianness(llvm::endianness Endianness) {
    InstructionEndianness = Endianness;
  }

private:
  llvm::endianness InstructionEndianness = llvm::endianness::little;
};
ARMPrettyPrinter ARMPrettyPrinterInst;

class AArch64PrettyPrinter : public PrettyPrinter {
public:
  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
                 object::SectionedAddress Address, formatted_raw_ostream &OS,
                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
                 LiveElementPrinter &LEP) override {
    if (SP && (PrintSource || PrintLines))
      SP->printSourceLine(OS, Address, ObjectFilename, LEP);
    LEP.printBoundaryLine(OS, Address, false);
    LEP.printBetweenInsts(OS, false);

    size_t Start = OS.tell();
    if (LeadingAddr)
      OS << format("%8" PRIx64 ":", Address.Address);
    if (ShowRawInsn) {
      size_t Pos = 0, End = Bytes.size();
      for (; Pos + 4 <= End; Pos += 4)
        OS << ' '
           << format_hex_no_prefix(
                  llvm::support::endian::read<uint32_t>(
                      Bytes.data() + Pos, llvm::endianness::little),
                  8);
      if (Pos < End) {
        OS << ' ';
        dumpBytes(Bytes.slice(Pos), OS);
      }
    }

    AlignToInstStartColumn(Start, STI, OS);

    if (MI) {
      IP.printInst(MI, Address.Address, "", STI, OS);
    } else
      OS << "\t<unknown>";
  }
};
AArch64PrettyPrinter AArch64PrettyPrinterInst;

class RISCVPrettyPrinter : public PrettyPrinter {
public:
  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
                 object::SectionedAddress Address, formatted_raw_ostream &OS,
                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
                 LiveElementPrinter &LEP) override {
    if (SP && (PrintSource || PrintLines))
      SP->printSourceLine(OS, Address, ObjectFilename, LEP);
    LEP.printBoundaryLine(OS, Address, false);
    LEP.printBetweenInsts(OS, false);

    size_t Start = OS.tell();
    if (LeadingAddr)
      OS << format("%8" PRIx64 ":", Address.Address);
    if (ShowRawInsn) {
      size_t Pos = 0, End = Bytes.size();
      if (End % 4 == 0) {
        // 32-bit and 64-bit instructions.
        for (; Pos + 4 <= End; Pos += 4)
          OS << ' '
             << format_hex_no_prefix(
                    llvm::support::endian::read<uint32_t>(
                        Bytes.data() + Pos, llvm::endianness::little),
                    8);
      } else if (End % 2 == 0) {
        // 16-bit and 48-bits instructions.
        for (; Pos + 2 <= End; Pos += 2)
          OS << ' '
             << format_hex_no_prefix(
                    llvm::support::endian::read<uint16_t>(
                        Bytes.data() + Pos, llvm::endianness::little),
                    4);
      }
      if (Pos < End) {
        OS << ' ';
        dumpBytes(Bytes.slice(Pos), OS);
      }
    }

    AlignToInstStartColumn(Start, STI, OS);

    if (MI) {
      IP.printInst(MI, Address.Address, "", STI, OS);
    } else
      OS << "\t<unknown>";
  }
};
RISCVPrettyPrinter RISCVPrettyPrinterInst;

PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
  switch (Triple.getArch()) {
  default:
    return PrettyPrinterInst;
  case Triple::hexagon:
    return HexagonPrettyPrinterInst;
  case Triple::amdgcn:
    return AMDGCNPrettyPrinterInst;
  case Triple::bpfel:
  case Triple::bpfeb:
    return BPFPrettyPrinterInst;
  case Triple::arm:
  case Triple::armeb:
  case Triple::thumb:
  case Triple::thumbeb:
    return ARMPrettyPrinterInst;
  case Triple::aarch64:
  case Triple::aarch64_be:
  case Triple::aarch64_32:
    return AArch64PrettyPrinterInst;
  case Triple::riscv32:
  case Triple::riscv64:
    return RISCVPrettyPrinterInst;
  }
}

class DisassemblerTarget {
public:
  const Target *TheTarget;
  const Triple TheTriple;
  std::unique_ptr<const MCSubtargetInfo> SubtargetInfo;
  std::shared_ptr<MCContext> Context;
  std::unique_ptr<MCDisassembler> DisAsm;
  std::shared_ptr<MCInstrAnalysis> InstrAnalysis;
  std::shared_ptr<MCInstPrinter> InstPrinter;
  PrettyPrinter *Printer;

  DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,
                     StringRef TripleName, StringRef MCPU,
                     SubtargetFeatures &Features);
  DisassemblerTarget(DisassemblerTarget &Other, SubtargetFeatures &Features);

private:
  MCTargetOptions Options;
  std::shared_ptr<const MCRegisterInfo> RegisterInfo;
  std::shared_ptr<const MCAsmInfo> AsmInfo;
  std::shared_ptr<const MCInstrInfo> InstrInfo;
  std::shared_ptr<MCObjectFileInfo> ObjectFileInfo;
};

DisassemblerTarget::DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,
                                       StringRef TripleName, StringRef MCPU,
                                       SubtargetFeatures &Features)
    : TheTarget(TheTarget), TheTriple(TripleName),
      Printer(&selectPrettyPrinter(TheTriple)),
      RegisterInfo(TheTarget->createMCRegInfo(TheTriple)) {
  if (!RegisterInfo)
    reportError(Obj.getFileName(), "no register info for target " + TripleName);

  // Set up disassembler.
  AsmInfo.reset(TheTarget->createMCAsmInfo(*RegisterInfo, TheTriple, Options));
  if (!AsmInfo)
    reportError(Obj.getFileName(), "no assembly info for target " + TripleName);

  SubtargetInfo.reset(
      TheTarget->createMCSubtargetInfo(TheTriple, MCPU, Features.getString()));
  if (!SubtargetInfo)
    reportError(Obj.getFileName(),
                "no subtarget info for target " + TripleName);
  InstrInfo.reset(TheTarget->createMCInstrInfo());
  if (!InstrInfo)
    reportError(Obj.getFileName(),
                "no instruction info for target " + TripleName);
  Context = std::make_shared<MCContext>(
      TheTriple, AsmInfo.get(), RegisterInfo.get(), SubtargetInfo.get());

  // FIXME: for now initialize MCObjectFileInfo with default values
  ObjectFileInfo.reset(
      TheTarget->createMCObjectFileInfo(*Context, /*PIC=*/false));
  Context->setObjectFileInfo(ObjectFileInfo.get());

  DisAsm.reset(TheTarget->createMCDisassembler(*SubtargetInfo, *Context));
  if (!DisAsm)
    reportError(Obj.getFileName(), "no disassembler for target " + TripleName);

  if (auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
    DisAsm->setABIVersion(ELFObj->getEIdentABIVersion());

  InstrAnalysis.reset(TheTarget->createMCInstrAnalysis(InstrInfo.get()));

  int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
  InstPrinter.reset(TheTarget->createMCInstPrinter(
      TheTriple, AsmPrinterVariant, *AsmInfo, *InstrInfo, *RegisterInfo));
  if (!InstPrinter)
    reportError(Obj.getFileName(),
                "no instruction printer for target " + TripleName);
  InstPrinter->setPrintImmHex(PrintImmHex);
  InstPrinter->setPrintBranchImmAsAddress(true);
  InstPrinter->setSymbolizeOperands(SymbolizeOperands);
  InstPrinter->setMCInstrAnalysis(InstrAnalysis.get());

  switch (DisassemblyColor) {
  case ColorOutput::Enable:
    InstPrinter->setUseColor(true);
    break;
  case ColorOutput::Auto:
    InstPrinter->setUseColor(outs().has_colors());
    break;
  case ColorOutput::Disable:
  case ColorOutput::Invalid:
    InstPrinter->setUseColor(false);
    break;
  };
}

DisassemblerTarget::DisassemblerTarget(DisassemblerTarget &Other,
                                       SubtargetFeatures &Features)
    : TheTarget(Other.TheTarget), TheTriple(Other.TheTriple),
      SubtargetInfo(TheTarget->createMCSubtargetInfo(TheTriple, MCPU,
                                                     Features.getString())),
      Context(Other.Context),
      DisAsm(TheTarget->createMCDisassembler(*SubtargetInfo, *Context)),
      InstrAnalysis(Other.InstrAnalysis), InstPrinter(Other.InstPrinter),
      Printer(Other.Printer), RegisterInfo(Other.RegisterInfo),
      AsmInfo(Other.AsmInfo), InstrInfo(Other.InstrInfo),
      ObjectFileInfo(Other.ObjectFileInfo) {}
} // namespace

static uint8_t getElfSymbolType(const ObjectFile &Obj, const SymbolRef &Sym) {
  assert(Obj.isELF());
  if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(&Obj))
    return unwrapOrError(Elf32LEObj->getSymbol(Sym.getRawDataRefImpl()),
                         Obj.getFileName())
        ->getType();
  if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(&Obj))
    return unwrapOrError(Elf64LEObj->getSymbol(Sym.getRawDataRefImpl()),
                         Obj.getFileName())
        ->getType();
  if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(&Obj))
    return unwrapOrError(Elf32BEObj->getSymbol(Sym.getRawDataRefImpl()),
                         Obj.getFileName())
        ->getType();
  if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(&Obj))
    return unwrapOrError(Elf64BEObj->getSymbol(Sym.getRawDataRefImpl()),
                         Obj.getFileName())
        ->getType();
  llvm_unreachable("Unsupported binary format");
}

template <class ELFT>
static void
addDynamicElfSymbols(const ELFObjectFile<ELFT> &Obj,
                     std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {
  for (auto Symbol : Obj.getDynamicSymbolIterators()) {
    uint8_t SymbolType = Symbol.getELFType();
    if (SymbolType == ELF::STT_SECTION)
      continue;

    uint64_t Address = unwrapOrError(Symbol.getAddress(), Obj.getFileName());
    // ELFSymbolRef::getAddress() returns size instead of value for common
    // symbols which is not desirable for disassembly output. Overriding.
    if (SymbolType == ELF::STT_COMMON)
      Address = unwrapOrError(Obj.getSymbol(Symbol.getRawDataRefImpl()),
                              Obj.getFileName())
                    ->st_value;

    StringRef Name = unwrapOrError(Symbol.getName(), Obj.getFileName());
    if (Name.empty())
      continue;

    section_iterator SecI =
        unwrapOrError(Symbol.getSection(), Obj.getFileName());
    if (SecI == Obj.section_end())
      continue;

    AllSymbols[*SecI].emplace_back(Address, Name, SymbolType);
  }
}

static void
addDynamicElfSymbols(const ELFObjectFileBase &Obj,
                     std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {
  if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(&Obj))
    addDynamicElfSymbols(*Elf32LEObj, AllSymbols);
  else if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(&Obj))
    addDynamicElfSymbols(*Elf64LEObj, AllSymbols);
  else if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(&Obj))
    addDynamicElfSymbols(*Elf32BEObj, AllSymbols);
  else if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(&Obj))
    addDynamicElfSymbols(*Elf64BEObj, AllSymbols);
  else
    llvm_unreachable("Unsupported binary format");
}

static std::optional<SectionRef> getWasmCodeSection(const WasmObjectFile &Obj) {
  for (auto SecI : Obj.sections()) {
    const WasmSection &Section = Obj.getWasmSection(SecI);
    if (Section.Type == wasm::WASM_SEC_CODE)
      return SecI;
  }
  return std::nullopt;
}

static void
addMissingWasmCodeSymbols(const WasmObjectFile &Obj,
                          std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {
  std::optional<SectionRef> Section = getWasmCodeSection(Obj);
  if (!Section)
    return;
  SectionSymbolsTy &Symbols = AllSymbols[*Section];

  std::set<uint64_t> SymbolAddresses;
  for (const auto &Sym : Symbols)
    SymbolAddresses.insert(Sym.Addr);

  for (const wasm::WasmFunction &Function : Obj.functions()) {
    // This adjustment mirrors the one in WasmObjectFile::getSymbolAddress.
    uint32_t Adjustment = Obj.isRelocatableObject() || Obj.isSharedObject()
                              ? 0
                              : Section->getAddress();
    uint64_t Address = Function.CodeSectionOffset + Adjustment;
    // Only add fallback symbols for functions not already present in the symbol
    // table.
    if (SymbolAddresses.count(Address))
      continue;
    // This function has no symbol, so it should have no SymbolName.
    assert(Function.SymbolName.empty());
    // We use DebugName for the name, though it may be empty if there is no
    // "name" custom section, or that section is missing a name for this
    // function.
    StringRef Name = Function.DebugName;
    Symbols.emplace_back(Address, Name, ELF::STT_NOTYPE);
  }
}

static DenseMap<StringRef, SectionRef> getSectionNames(const ObjectFile &Obj) {
  DenseMap<StringRef, SectionRef> Sections;
  for (SectionRef Section : Obj.sections()) {
    Expected<StringRef> SecNameOrErr = Section.getName();
    if (!SecNameOrErr) {
      consumeError(SecNameOrErr.takeError());
      continue;
    }
    Sections[*SecNameOrErr] = Section;
  }
  return Sections;
}

static void addPltEntries(const MCSubtargetInfo &STI, const ObjectFile &Obj,
                          DenseMap<StringRef, SectionRef> &SectionNames,
                          std::map<SectionRef, SectionSymbolsTy> &AllSymbols,
                          StringSaver &Saver) {
  auto *ElfObj = dyn_cast<ELFObjectFileBase>(&Obj);
  if (!ElfObj)
    return;
  for (auto Plt : ElfObj->getPltEntries(STI)) {
    if (Plt.Symbol) {
      SymbolRef Symbol(*Plt.Symbol, ElfObj);
      uint8_t SymbolType = getElfSymbolType(Obj, Symbol);
      if (Expected<StringRef> NameOrErr = Symbol.getName()) {
        if (!NameOrErr->empty())
          AllSymbols[SectionNames[Plt.Section]].emplace_back(
              Plt.Address, Saver.save((*NameOrErr + "@plt").str()), SymbolType);
        continue;
      } else {
        // The warning has been reported in disassembleObject().
        consumeError(NameOrErr.takeError());
      }
    }
    reportWarning("PLT entry at 0x" + Twine::utohexstr(Plt.Address) +
                      " references an invalid symbol",
                  Obj.getFileName());
  }
}

// Normally the disassembly output will skip blocks of zeroes. This function
// returns the number of zero bytes that can be skipped when dumping the
// disassembly of the instructions in Buf.
static size_t countSkippableZeroBytes(ArrayRef<uint8_t> Buf) {
  // Find the number of leading zeroes.
  size_t N = 0;
  while (N < Buf.size() && !Buf[N])
    ++N;

  // We may want to skip blocks of zero bytes, but unless we see
  // at least 8 of them in a row.
  if (N < 8)
    return 0;

  // We skip zeroes in multiples of 4 because do not want to truncate an
  // instruction if it starts with a zero byte.
  return N & ~0x3;
}

// Returns a map from sections to their relocations.
static std::map<SectionRef, std::vector<RelocationRef>>
getRelocsMap(object::ObjectFile const &Obj) {
  std::map<SectionRef, std::vector<RelocationRef>> Ret;
  uint64_t I = (uint64_t)-1;
  for (SectionRef Sec : Obj.sections()) {
    ++I;
    Expected<section_iterator> RelocatedOrErr = Sec.getRelocatedSection();
    if (!RelocatedOrErr)
      reportError(Obj.getFileName(),
                  "section (" + Twine(I) +
                      "): failed to get a relocated section: " +
                      toString(RelocatedOrErr.takeError()));

    section_iterator Relocated = *RelocatedOrErr;
    if (Relocated == Obj.section_end() || !checkSectionFilter(*Relocated).Keep)
      continue;
    std::vector<RelocationRef> &V = Ret[*Relocated];
    append_range(V, Sec.relocations());
    // Sort relocations by address.
    llvm::stable_sort(V, isRelocAddressLess);
  }
  return Ret;
}

// Used for --adjust-vma to check if address should be adjusted by the
// specified value for a given section.
// For ELF we do not adjust non-allocatable sections like debug ones,
// because they are not loadable.
// TODO: implement for other file formats.
static bool shouldAdjustVA(const SectionRef &Section) {
  const ObjectFile *Obj = Section.getObject();
  if (Obj->isELF())
    return ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC;
  return false;
}

typedef std::pair<uint64_t, char> MappingSymbolPair;
static char getMappingSymbolKind(ArrayRef<MappingSymbolPair> MappingSymbols,
                                 uint64_t Address) {
  auto It =
      partition_point(MappingSymbols, [Address](const MappingSymbolPair &Val) {
        return Val.first <= Address;
      });
  // Return zero for any address before the first mapping symbol; this means
  // we should use the default disassembly mode, depending on the target.
  if (It == MappingSymbols.begin())
    return '\x00';
  return (It - 1)->second;
}

static uint64_t dumpARMELFData(uint64_t SectionAddr, uint64_t Index,
                               uint64_t End, const ObjectFile &Obj,
                               ArrayRef<uint8_t> Bytes,
                               ArrayRef<MappingSymbolPair> MappingSymbols,
                               const MCSubtargetInfo &STI, raw_ostream &OS) {
  llvm::endianness Endian =
      Obj.isLittleEndian() ? llvm::endianness::little : llvm::endianness::big;
  size_t Start = OS.tell();
  OS << format("%8" PRIx64 ": ", SectionAddr + Index);
  if (Index + 4 <= End) {
    dumpBytes(Bytes.slice(Index, 4), OS);
    AlignToInstStartColumn(Start, STI, OS);
    OS << "\t.word\t"
       << format_hex(support::endian::read32(Bytes.data() + Index, Endian), 10);
    return 4;
  }
  if (Index + 2 <= End) {
    dumpBytes(Bytes.slice(Index, 2), OS);
    AlignToInstStartColumn(Start, STI, OS);
    OS << "\t.short\t"
       << format_hex(support::endian::read16(Bytes.data() + Index, Endian), 6);
    return 2;
  }
  dumpBytes(Bytes.slice(Index, 1), OS);
  AlignToInstStartColumn(Start, STI, OS);
  OS << "\t.byte\t" << format_hex(Bytes[Index], 4);
  return 1;
}

static void dumpELFData(uint64_t SectionAddr, uint64_t Index, uint64_t End,
                        ArrayRef<uint8_t> Bytes, raw_ostream &OS) {
  // print out data up to 8 bytes at a time in hex and ascii
  uint8_t AsciiData[9] = {'\0'};
  uint8_t Byte;
  int NumBytes = 0;

  for (; Index < End; ++Index) {
    if (NumBytes == 0)
      OS << format("%8" PRIx64 ":", SectionAddr + Index);
    Byte = Bytes.slice(Index)[0];
    OS << format(" %02x", Byte);
    AsciiData[NumBytes] = isPrint(Byte) ? Byte : '.';

    uint8_t IndentOffset = 0;
    NumBytes++;
    if (Index == End - 1 || NumBytes > 8) {
      // Indent the space for less than 8 bytes data.
      // 2 spaces for byte and one for space between bytes
      IndentOffset = 3 * (8 - NumBytes);
      for (int Excess = NumBytes; Excess < 8; Excess++)
        AsciiData[Excess] = '\0';
      NumBytes = 8;
    }
    if (NumBytes == 8) {
      AsciiData[8] = '\0';
      OS << std::string(IndentOffset, ' ') << "         ";
      OS << reinterpret_cast<char *>(AsciiData);
      OS << '\n';
      NumBytes = 0;
    }
  }
}

SymbolInfoTy objdump::createSymbolInfo(const ObjectFile &Obj,
                                       const SymbolRef &Symbol,
                                       bool IsMappingSymbol) {
  const StringRef FileName = Obj.getFileName();
  const uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
  const StringRef Name = unwrapOrError(Symbol.getName(), FileName);

  if (Obj.isXCOFF() && (SymbolDescription || TracebackTable)) {
    const auto &XCOFFObj = cast<XCOFFObjectFile>(Obj);
    DataRefImpl SymbolDRI = Symbol.getRawDataRefImpl();

    const uint32_t SymbolIndex = XCOFFObj.getSymbolIndex(SymbolDRI.p);
    std::optional<XCOFF::StorageMappingClass> Smc =
        getXCOFFSymbolCsectSMC(XCOFFObj, Symbol);
    return SymbolInfoTy(Smc, Addr, Name, SymbolIndex,
                        isLabel(XCOFFObj, Symbol));
  } else if (Obj.isXCOFF()) {
    const SymbolRef::Type SymType = unwrapOrError(Symbol.getType(), FileName);
    return SymbolInfoTy(Addr, Name, SymType, /*IsMappingSymbol=*/false,
                        /*IsXCOFF=*/true);
  } else if (Obj.isWasm()) {
    uint8_t SymType =
        cast<WasmObjectFile>(&Obj)->getWasmSymbol(Symbol).Info.Kind;
    return SymbolInfoTy(Addr, Name, SymType, false);
  } else {
    uint8_t Type =
        Obj.isELF() ? getElfSymbolType(Obj, Symbol) : (uint8_t)ELF::STT_NOTYPE;
    return SymbolInfoTy(Addr, Name, Type, IsMappingSymbol);
  }
}

static SymbolInfoTy createDummySymbolInfo(const ObjectFile &Obj,
                                          const uint64_t Addr, StringRef &Name,
                                          uint8_t Type) {
  if (Obj.isXCOFF() && (SymbolDescription || TracebackTable))
    return SymbolInfoTy(std::nullopt, Addr, Name, std::nullopt, false);
  if (Obj.isWasm())
    return SymbolInfoTy(Addr, Name, wasm::WASM_SYMBOL_TYPE_SECTION);
  return SymbolInfoTy(Addr, Name, Type);
}

static void collectBBAddrMapLabels(
    const BBAddrMapInfo &FullAddrMap, uint64_t SectionAddr, uint64_t Start,
    uint64_t End,
    std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> &Labels) {
  if (FullAddrMap.empty())
    return;
  Labels.clear();
  uint64_t StartAddress = SectionAddr + Start;
  uint64_t EndAddress = SectionAddr + End;
  const BBAddrMapFunctionEntry *FunctionMap =
      FullAddrMap.getEntryForAddress(StartAddress);
  if (!FunctionMap)
    return;
  std::optional<size_t> BBRangeIndex =
      FunctionMap->getAddrMap().getBBRangeIndexForBaseAddress(StartAddress);
  if (!BBRangeIndex)
    return;
  size_t NumBBEntriesBeforeRange = 0;
  for (size_t I = 0; I < *BBRangeIndex; ++I)
    NumBBEntriesBeforeRange +=
        FunctionMap->getAddrMap().BBRanges[I].BBEntries.size();
  const auto &BBRange = FunctionMap->getAddrMap().BBRanges[*BBRangeIndex];
  for (size_t I = 0; I < BBRange.BBEntries.size(); ++I) {
    const BBAddrMap::BBEntry &BBEntry = BBRange.BBEntries[I];
    uint64_t BBAddress = BBEntry.Offset + BBRange.BaseAddress;
    if (BBAddress >= EndAddress)
      continue;

    std::string LabelString = ("BB" + Twine(BBEntry.ID)).str();
    Labels[BBAddress].push_back(
        {LabelString, FunctionMap->constructPGOLabelString(
                          NumBBEntriesBeforeRange + I, PrettyPGOAnalysisMap)});
  }
}

static void
collectLocalBranchTargets(ArrayRef<uint8_t> Bytes, MCInstrAnalysis *MIA,
                          MCDisassembler *DisAsm, MCInstPrinter *IP,
                          const MCSubtargetInfo *STI, uint64_t SectionAddr,
                          uint64_t Start, uint64_t End,
                          std::unordered_map<uint64_t, std::string> &Labels) {
  // Supported by certain targets.
  const bool isPPC = STI->getTargetTriple().isPPC();
  const bool isX86 = STI->getTargetTriple().isX86();
  const bool isAArch64 = STI->getTargetTriple().isAArch64();
  const bool isBPF = STI->getTargetTriple().isBPF();
  if (!isPPC && !isX86 && !isAArch64 && !isBPF)
    return;

  if (MIA)
    MIA->resetState();

  std::set<uint64_t> Targets;
  Start += SectionAddr;
  End += SectionAddr;
  const bool isXCOFF = STI->getTargetTriple().isOSBinFormatXCOFF();
  for (uint64_t Index = Start; Index < End;) {
    // Disassemble a real instruction and record function-local branch labels.
    MCInst Inst;
    uint64_t Size;
    ArrayRef<uint8_t> ThisBytes = Bytes.slice(Index - SectionAddr);
    bool Disassembled =
        DisAsm->getInstruction(Inst, Size, ThisBytes, Index, nulls());
    if (Size == 0)
      Size = std::min<uint64_t>(ThisBytes.size(),
                                DisAsm->suggestBytesToSkip(ThisBytes, Index));

    if (MIA) {
      if (Disassembled) {
        uint64_t Target;
        bool TargetKnown = MIA->evaluateBranch(Inst, Index, Size, Target);
        if (TargetKnown && (Target >= Start && Target < End) &&
            !Targets.count(Target)) {
          // On PowerPC and AIX, a function call is encoded as a branch to 0.
          // On other PowerPC platforms (ELF), a function call is encoded as
          // a branch to self. Do not add a label for these cases.
          if (!(isPPC &&
                ((Target == 0 && isXCOFF) || (Target == Index && !isXCOFF))))
            Targets.insert(Target);
        }
        MIA->updateState(Inst, Index);
      } else
        MIA->resetState();
    }
    Index += Size;
  }

  Labels.clear();
  for (auto [Idx, Target] : enumerate(Targets))
    Labels[Target] = ("L" + Twine(Idx)).str();
}

// Create an MCSymbolizer for the target and add it to the MCDisassembler.
// This is currently only used on AMDGPU, and assumes the format of the
// void * argument passed to AMDGPU's createMCSymbolizer.
static void addSymbolizer(
    MCContext &Ctx, const Target *Target, const Triple &TheTriple,
    MCDisassembler *DisAsm, uint64_t SectionAddr, ArrayRef<uint8_t> Bytes,
    SectionSymbolsTy &Symbols,
    std::vector<std::unique_ptr<std::string>> &SynthesizedLabelNames) {

  std::unique_ptr<MCRelocationInfo> RelInfo(
      Target->createMCRelocationInfo(TheTriple, Ctx));
  if (!RelInfo)
    return;
  std::unique_ptr<MCSymbolizer> Symbolizer(Target->createMCSymbolizer(
      TheTriple, nullptr, nullptr, &Symbols, &Ctx, std::move(RelInfo)));
  MCSymbolizer *SymbolizerPtr = &*Symbolizer;
  DisAsm->setSymbolizer(std::move(Symbolizer));

  if (!SymbolizeOperands)
    return;

  // Synthesize labels referenced by branch instructions by
  // disassembling, discarding the output, and collecting the referenced
  // addresses from the symbolizer.
  for (size_t Index = 0; Index != Bytes.size();) {
    MCInst Inst;
    uint64_t Size;
    ArrayRef<uint8_t> ThisBytes = Bytes.slice(Index);
    const uint64_t ThisAddr = SectionAddr + Index;
    DisAsm->getInstruction(Inst, Size, ThisBytes, ThisAddr, nulls());
    if (Size == 0)
      Size = std::min<uint64_t>(ThisBytes.size(),
                                DisAsm->suggestBytesToSkip(ThisBytes, Index));
    Index += Size;
  }
  ArrayRef<uint64_t> LabelAddrsRef = SymbolizerPtr->getReferencedAddresses();
  // Copy and sort to remove duplicates.
  std::vector<uint64_t> LabelAddrs;
  llvm::append_range(LabelAddrs, LabelAddrsRef);
  llvm::sort(LabelAddrs);
  LabelAddrs.resize(llvm::unique(LabelAddrs) - LabelAddrs.begin());
  // Add the labels.
  for (unsigned LabelNum = 0; LabelNum != LabelAddrs.size(); ++LabelNum) {
    auto Name = std::make_unique<std::string>();
    *Name = (Twine("L") + Twine(LabelNum)).str();
    SynthesizedLabelNames.push_back(std::move(Name));
    Symbols.push_back(SymbolInfoTy(
        LabelAddrs[LabelNum], *SynthesizedLabelNames.back(), ELF::STT_NOTYPE));
  }
  llvm::stable_sort(Symbols);
  // Recreate the symbolizer with the new symbols list.
  RelInfo.reset(Target->createMCRelocationInfo(TheTriple, Ctx));
  Symbolizer.reset(Target->createMCSymbolizer(
      TheTriple, nullptr, nullptr, &Symbols, &Ctx, std::move(RelInfo)));
  DisAsm->setSymbolizer(std::move(Symbolizer));
}

static StringRef getSegmentName(const MachOObjectFile *MachO,
                                const SectionRef &Section) {
  if (MachO) {
    DataRefImpl DR = Section.getRawDataRefImpl();
    StringRef SegmentName = MachO->getSectionFinalSegmentName(DR);
    return SegmentName;
  }
  return "";
}

static void createFakeELFSections(ObjectFile &Obj) {
  assert(Obj.isELF());
  if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(&Obj))
    Elf32LEObj->createFakeSections();
  else if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(&Obj))
    Elf64LEObj->createFakeSections();
  else if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(&Obj))
    Elf32BEObj->createFakeSections();
  else if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(&Obj))
    Elf64BEObj->createFakeSections();
  else
    llvm_unreachable("Unsupported binary format");
}

// Tries to fetch a more complete version of the given object file using its
// Build ID. Returns std::nullopt if nothing was found.
static std::optional<OwningBinary<Binary>>
fetchBinaryByBuildID(const ObjectFile &Obj) {
  object::BuildIDRef BuildID = getBuildID(&Obj);
  if (BuildID.empty())
    return std::nullopt;
  std::optional<std::string> Path = BIDFetcher->fetch(BuildID);
  if (!Path)
    return std::nullopt;
  Expected<OwningBinary<Binary>> DebugBinary = createBinary(*Path);
  if (!DebugBinary) {
    reportWarning(toString(DebugBinary.takeError()), *Path);
    return std::nullopt;
  }
  return std::move(*DebugBinary);
}

static void
disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
                  DisassemblerTarget &PrimaryTarget,
                  std::optional<DisassemblerTarget> &SecondaryTarget,
                  SourcePrinter &SP, bool InlineRelocs, raw_ostream &OS) {
  DisassemblerTarget *DT = &PrimaryTarget;
  bool PrimaryIsThumb = false;
  SmallVector<std::pair<uint64_t, uint64_t>, 0> CHPECodeMap;

  if (SecondaryTarget) {
    if (isArmElf(Obj)) {
      PrimaryIsThumb =
          PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode");
    } else if (const auto *COFFObj = dyn_cast<COFFObjectFile>(&Obj)) {
      const chpe_metadata *CHPEMetadata = COFFObj->getCHPEMetadata();
      if (CHPEMetadata && CHPEMetadata->CodeMapCount) {
        uintptr_t CodeMapInt;
        cantFail(COFFObj->getRvaPtr(CHPEMetadata->CodeMap, CodeMapInt));
        auto CodeMap = reinterpret_cast<const chpe_range_entry *>(CodeMapInt);

        for (uint32_t i = 0; i < CHPEMetadata->CodeMapCount; ++i) {
          if (CodeMap[i].getType() == chpe_range_type::Amd64 &&
              CodeMap[i].Length) {
            // Store x86_64 CHPE code ranges.
            uint64_t Start = CodeMap[i].getStart() + COFFObj->getImageBase();
            CHPECodeMap.emplace_back(Start, Start + CodeMap[i].Length);
          }
        }
        llvm::sort(CHPECodeMap);
      }
    }
  }

  std::map<SectionRef, std::vector<RelocationRef>> RelocMap;
  if (InlineRelocs || Obj.isXCOFF())
    RelocMap = getRelocsMap(Obj);
  bool Is64Bits = Obj.getBytesInAddress() > 4;

  // Create a mapping from virtual address to symbol name.  This is used to
  // pretty print the symbols while disassembling.
  std::map<SectionRef, SectionSymbolsTy> AllSymbols;
  std::map<SectionRef, SmallVector<MappingSymbolPair, 0>> AllMappingSymbols;
  SectionSymbolsTy AbsoluteSymbols;
  const StringRef FileName = Obj.getFileName();
  const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(&Obj);
  for (const SymbolRef &Symbol : Obj.symbols()) {
    Expected<StringRef> NameOrErr = Symbol.getName();
    if (!NameOrErr) {
      reportWarning(toString(NameOrErr.takeError()), FileName);
      continue;
    }
    if (NameOrErr->empty() && !(Obj.isXCOFF() && SymbolDescription))
      continue;

    if (Obj.isELF() &&
        (cantFail(Symbol.getFlags()) & SymbolRef::SF_FormatSpecific)) {
      // Symbol is intended not to be displayed by default (STT_FILE,
      // STT_SECTION, or a mapping symbol). Ignore STT_SECTION symbols. We will
      // synthesize a section symbol if no symbol is defined at offset 0.
      //
      // For a mapping symbol, store it within both AllSymbols and
      // AllMappingSymbols. If --show-all-symbols is unspecified, its label will
      // not be printed in disassembly listing.
      if (getElfSymbolType(Obj, Symbol) != ELF::STT_SECTION &&
          hasMappingSymbols(Obj)) {
        section_iterator SecI = unwrapOrError(Symbol.getSection(), FileName);
        if (SecI != Obj.section_end()) {
          uint64_t SectionAddr = SecI->getAddress();
          uint64_t Address = cantFail(Symbol.getAddress());
          StringRef Name = *NameOrErr;
          if (Name.consume_front("$") && Name.size() &&
              strchr("adtx", Name[0])) {
            AllMappingSymbols[*SecI].emplace_back(Address - SectionAddr,
                                                  Name[0]);
            AllSymbols[*SecI].push_back(
                createSymbolInfo(Obj, Symbol, /*MappingSymbol=*/true));
          }
        }
      }
      continue;
    }

    if (MachO) {
      // __mh_(execute|dylib|dylinker|bundle|preload|object)_header are special
      // symbols that support MachO header introspection. They do not bind to
      // code locations and are irrelevant for disassembly.
      if (NameOrErr->starts_with("__mh_") && NameOrErr->ends_with("_header"))
        continue;
      // Don't ask a Mach-O STAB symbol for its section unless you know that
      // STAB symbol's section field refers to a valid section index. Otherwise
      // the symbol may error trying to load a section that does not exist.
      DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
      uint8_t NType =
          (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type
                            : MachO->getSymbolTableEntry(SymDRI).n_type);
      if (NType & MachO::N_STAB)
        continue;
    }

    section_iterator SecI = unwrapOrError(Symbol.getSection(), FileName);
    if (SecI != Obj.section_end())
      AllSymbols[*SecI].push_back(createSymbolInfo(Obj, Symbol));
    else
      AbsoluteSymbols.push_back(createSymbolInfo(Obj, Symbol));
  }

  if (AllSymbols.empty() && Obj.isELF())
    addDynamicElfSymbols(cast<ELFObjectFileBase>(Obj), AllSymbols);

  if (Obj.isWasm())
    addMissingWasmCodeSymbols(cast<WasmObjectFile>(Obj), AllSymbols);

  if (Obj.isELF() && Obj.sections().empty())
    createFakeELFSections(Obj);

  DisassemblerTarget *PltTarget = DT;
  auto SectionNames = getSectionNames(Obj);
  if (SecondaryTarget && isArmElf(Obj)) {
    auto PltSectionRef = SectionNames.find(".plt");
    if (PltSectionRef != SectionNames.end()) {
      bool PltIsThumb = false;
      for (auto [Addr, SymbolName] : AllMappingSymbols[PltSectionRef->second]) {
        if (Addr != 0)
          continue;

        if (SymbolName == 't') {
          PltIsThumb = true;
          break;
        }
        if (SymbolName == 'a')
          break;
      }

      if (PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode"))
        PltTarget = PltIsThumb ? &PrimaryTarget : &*SecondaryTarget;
      else
        PltTarget = PltIsThumb ? &*SecondaryTarget : &PrimaryTarget;
    }
  }
  BumpPtrAllocator A;
  StringSaver Saver(A);
  addPltEntries(*PltTarget->SubtargetInfo, Obj, SectionNames, AllSymbols,
                Saver);

  // Create a mapping from virtual address to section. An empty section can
  // cause more than one section at the same address. Sort such sections to be
  // before same-addressed non-empty sections so that symbol lookups prefer the
  // non-empty section.
  std::vector<std::pair<uint64_t, SectionRef>> SectionAddresses;
  for (SectionRef Sec : Obj.sections())
    SectionAddresses.emplace_back(Sec.getAddress(), Sec);
  llvm::stable_sort(SectionAddresses, [](const auto &LHS, const auto &RHS) {
    if (LHS.first != RHS.first)
      return LHS.first < RHS.first;
    return LHS.second.getSize() < RHS.second.getSize();
  });

  // Linked executables (.exe and .dll files) typically don't include a real
  // symbol table but they might contain an export table.
  if (const auto *COFFObj = dyn_cast<COFFObjectFile>(&Obj)) {
    for (const auto &ExportEntry : COFFObj->export_directories()) {
      StringRef Name;
      if (Error E = ExportEntry.getSymbolName(Name))
        reportError(std::move(E), Obj.getFileName());
      if (Name.empty())
        continue;

      uint32_t RVA;
      if (Error E = ExportEntry.getExportRVA(RVA))
        reportError(std::move(E), Obj.getFileName());

      uint64_t VA = COFFObj->getImageBase() + RVA;
      auto Sec = partition_point(
          SectionAddresses, [VA](const std::pair<uint64_t, SectionRef> &O) {
            return O.first <= VA;
          });
      if (Sec != SectionAddresses.begin()) {
        --Sec;
        AllSymbols[Sec->second].emplace_back(VA, Name, ELF::STT_NOTYPE);
      } else
        AbsoluteSymbols.emplace_back(VA, Name, ELF::STT_NOTYPE);
    }
  }

  // Sort all the symbols, this allows us to use a simple binary search to find
  // Multiple symbols can have the same address. Use a stable sort to stabilize
  // the output.
  StringSet<> FoundDisasmSymbolSet;
  for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols)
    llvm::stable_sort(SecSyms.second);
  llvm::stable_sort(AbsoluteSymbols);

  std::unique_ptr<DWARFContext> DICtx;
  LiveElementPrinter LEP(*DT->Context->getRegisterInfo(), *DT->SubtargetInfo);

  if (DbgVariables != DFDisabled || DbgInlinedFunctions != DFDisabled) {
    DICtx = DWARFContext::create(DbgObj);
    for (const std::unique_ptr<DWARFUnit> &CU : DICtx->compile_units())
      LEP.addCompileUnit(CU->getUnitDIE(false));
  }

  LLVM_DEBUG(LEP.dump());

  BBAddrMapInfo FullAddrMap;
  auto ReadBBAddrMap = [&](std::optional<unsigned> SectionIndex =
                               std::nullopt) {
    FullAddrMap.clear();
    if (const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj)) {
      std::vector<PGOAnalysisMap> PGOAnalyses;
      auto BBAddrMapsOrErr = Elf->readBBAddrMap(SectionIndex, &PGOAnalyses);
      if (!BBAddrMapsOrErr) {
        reportWarning(toString(BBAddrMapsOrErr.takeError()), Obj.getFileName());
        return;
      }
      for (auto &&[FunctionBBAddrMap, FunctionPGOAnalysis] :
           zip_equal(*std::move(BBAddrMapsOrErr), std::move(PGOAnalyses))) {
        FullAddrMap.AddFunctionEntry(std::move(FunctionBBAddrMap),
                                     std::move(FunctionPGOAnalysis));
      }
    }
  };

  // For non-relocatable objects, Read all LLVM_BB_ADDR_MAP sections into a
  // single mapping, since they don't have any conflicts.
  if (SymbolizeOperands && !Obj.isRelocatableObject())
    ReadBBAddrMap();

  std::optional<llvm::BTFParser> BTF;
  if (InlineRelocs && BTFParser::hasBTFSections(Obj)) {
    BTF.emplace();
    BTFParser::ParseOptions Opts = {};
    Opts.LoadTypes = true;
    Opts.LoadRelocs = true;
    if (Error E = BTF->parse(Obj, Opts))
      WithColor::defaultErrorHandler(std::move(E));
  }

  for (const SectionRef &Section : ToolSectionFilter(Obj)) {
    if (FilterSections.empty() && !DisassembleAll &&
        (!Section.isText() || Section.isVirtual()))
      continue;

    uint64_t SectionAddr = Section.getAddress();
    uint64_t SectSize = Section.getSize();
    if (!SectSize)
      continue;

    // For relocatable object files, read the LLVM_BB_ADDR_MAP section
    // corresponding to this section, if present.
    if (SymbolizeOperands && Obj.isRelocatableObject())
      ReadBBAddrMap(Section.getIndex());

    // Get the list of all the symbols in this section.
    SectionSymbolsTy &Symbols = AllSymbols[Section];
    auto &MappingSymbols = AllMappingSymbols[Section];
    llvm::sort(MappingSymbols);

    ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(
        unwrapOrError(Section.getContents(), Obj.getFileName()));

    std::vector<std::unique_ptr<std::string>> SynthesizedLabelNames;
    if (Obj.isELF() && Obj.getArch() == Triple::amdgcn) {
      // AMDGPU disassembler uses symbolizer for printing labels
      addSymbolizer(*DT->Context, DT->TheTarget, DT->TheTriple,
                    DT->DisAsm.get(), SectionAddr, Bytes, Symbols,
                    SynthesizedLabelNames);
    }

    StringRef SegmentName = getSegmentName(MachO, Section);
    StringRef SectionName = unwrapOrError(Section.getName(), Obj.getFileName());
    // If the section has no symbol at the start, just insert a dummy one.
    // Without --show-all-symbols, also insert one if all symbols at the start
    // are mapping symbols.
    bool CreateDummy = Symbols.empty();
    if (!CreateDummy) {
      CreateDummy = true;
      for (auto &Sym : Symbols) {
        if (Sym.Addr != SectionAddr)
          break;
        if (!Sym.IsMappingSymbol || ShowAllSymbols)
          CreateDummy = false;
      }
    }
    if (CreateDummy) {
      SymbolInfoTy Sym = createDummySymbolInfo(
          Obj, SectionAddr, SectionName,
          Section.isText() ? ELF::STT_FUNC : ELF::STT_OBJECT);
      if (Obj.isXCOFF())
        Symbols.insert(Symbols.begin(), Sym);
      else
        Symbols.insert(llvm::lower_bound(Symbols, Sym), Sym);
    }

    SmallString<40> Comments;
    raw_svector_ostream CommentStream(Comments);

    uint64_t VMAAdjustment = 0;
    if (shouldAdjustVA(Section))
      VMAAdjustment = AdjustVMA;

    // In executable and shared objects, r_offset holds a virtual address.
    // Subtract SectionAddr from the r_offset field of a relocation to get
    // the section offset.
    uint64_t RelAdjustment = Obj.isRelocatableObject() ? 0 : SectionAddr;
    uint64_t Size;
    uint64_t Index;
    bool PrintedSection = false;
    std::vector<RelocationRef> Rels = RelocMap[Section];
    std::vector<RelocationRef>::const_iterator RelCur = Rels.begin();
    std::vector<RelocationRef>::const_iterator RelEnd = Rels.end();

    // Loop over each chunk of code between two points where at least
    // one symbol is defined.
    for (size_t SI = 0, SE = Symbols.size(); SI != SE;) {
      // Advance SI past all the symbols starting at the same address,
      // and make an ArrayRef of them.
      unsigned FirstSI = SI;
      uint64_t Start = Symbols[SI].Addr;
      ArrayRef<SymbolInfoTy> SymbolsHere;
      while (SI != SE && Symbols[SI].Addr == Start)
        ++SI;
      SymbolsHere = ArrayRef<SymbolInfoTy>(&Symbols[FirstSI], SI - FirstSI);

      // Get the demangled names of all those symbols. We end up with a vector
      // of StringRef that holds the names we're going to use, and a vector of
      // std::string that stores the new strings returned by demangle(), if
      // any. If we don't call demangle() then that vector can stay empty.
      std::vector<StringRef> SymNamesHere;
      std::vector<std::string> DemangledSymNamesHere;
      if (Demangle) {
        // Fetch the demangled names and store them locally.
        for (const SymbolInfoTy &Symbol : SymbolsHere)
          DemangledSymNamesHere.push_back(demangle(Symbol.Name));
        // Now we've finished modifying that vector, it's safe to make
        // a vector of StringRefs pointing into it.
        SymNamesHere.insert(SymNamesHere.begin(), DemangledSymNamesHere.begin(),
                            DemangledSymNamesHere.end());
      } else {
        for (const SymbolInfoTy &Symbol : SymbolsHere)
          SymNamesHere.push_back(Symbol.Name);
      }

      // Distinguish ELF data from code symbols, which will be used later on to
      // decide whether to 'disassemble' this chunk as a data declaration via
      // dumpELFData(), or whether to treat it as code.
      //
      // If data _and_ code symbols are defined at the same address, the code
      // takes priority, on the grounds that disassembling code is our main
      // purpose here, and it would be a worse failure to _not_ interpret
      // something that _was_ meaningful as code than vice versa.
      //
      // Any ELF symbol type that is not clearly data will be regarded as code.
      // In particular, one of the uses of STT_NOTYPE is for branch targets
      // inside functions, for which STT_FUNC would be inaccurate.
      //
      // So here, we spot whether there's any non-data symbol present at all,
      // and only set the DisassembleAsELFData flag if there isn't. Also, we use
      // this distinction to inform the decision of which symbol to print at
      // the head of the section, so that if we're printing code, we print a
      // code-related symbol name to go with it.
      bool DisassembleAsELFData = false;
      size_t DisplaySymIndex = SymbolsHere.size() - 1;
      if (Obj.isELF() && !DisassembleAll && Section.isText()) {
        DisassembleAsELFData = true; // unless we find a code symbol below

        for (size_t i = 0; i < SymbolsHere.size(); ++i) {
          uint8_t SymTy = SymbolsHere[i].Type;
          if (SymTy != ELF::STT_OBJECT && SymTy != ELF::STT_COMMON) {
            DisassembleAsELFData = false;
            DisplaySymIndex = i;
          }
        }
      }

      // Decide which symbol(s) from this collection we're going to print.
      std::vector<bool> SymsToPrint(SymbolsHere.size(), false);
      // If the user has given the --disassemble-symbols option, then we must
      // display every symbol in that set, and no others.
      if (!DisasmSymbolSet.empty()) {
        bool FoundAny = false;
        for (size_t i = 0; i < SymbolsHere.size(); ++i) {
          if (DisasmSymbolSet.count(SymNamesHere[i])) {
            SymsToPrint[i] = true;
            FoundAny = true;
          }
        }

        // And if none of the symbols here is one that the user asked for, skip
        // disassembling this entire chunk of code.
        if (!FoundAny)
          continue;
      } else if (!SymbolsHere[DisplaySymIndex].IsMappingSymbol) {
        // Otherwise, print whichever symbol at this location is last in the
        // Symbols array, because that array is pre-sorted in a way intended to
        // correlate with priority of which symbol to display.
        SymsToPrint[DisplaySymIndex] = true;
      }

      // Now that we know we're disassembling this section, override the choice
      // of which symbols to display by printing _all_ of them at this address
      // if the user asked for all symbols.
      //
      // That way, '--show-all-symbols --disassemble-symbol=foo' will print
      // only the chunk of code headed by 'foo', but also show any other
      // symbols defined at that address, such as aliases for 'foo', or the ARM
      // mapping symbol preceding its code.
      if (ShowAllSymbols) {
        for (size_t i = 0; i < SymbolsHere.size(); ++i)
          SymsToPrint[i] = true;
      }

      if (Start < SectionAddr || StopAddress <= Start)
        continue;

      FoundDisasmSymbolSet.insert_range(SymNamesHere);

      // The end is the section end, the beginning of the next symbol, or
      // --stop-address.
      uint64_t End = std::min<uint64_t>(SectionAddr + SectSize, StopAddress);
      if (SI < SE)
        End = std::min(End, Symbols[SI].Addr);
      if (Start >= End || End <= StartAddress)
        continue;
      Start -= SectionAddr;
      End -= SectionAddr;

      if (!PrintedSection) {
        PrintedSection = true;
        OS << "\nDisassembly of section ";
        if (!SegmentName.empty())
          OS << SegmentName << ",";
        OS << SectionName << ":\n";
      }

      bool PrintedLabel = false;
      for (size_t i = 0; i < SymbolsHere.size(); ++i) {
        if (!SymsToPrint[i])
          continue;

        const SymbolInfoTy &Symbol = SymbolsHere[i];
        const StringRef SymbolName = SymNamesHere[i];

        if (!PrintedLabel) {
          OS << '\n';
          PrintedLabel = true;
        }
        if (LeadingAddr)
          OS << format(Is64Bits ? "%016" PRIx64 " " : "%08" PRIx64 " ",
                       SectionAddr + Start + VMAAdjustment);
        if (Obj.isXCOFF() && SymbolDescription) {
          OS << getXCOFFSymbolDescription(Symbol, SymbolName) << ":\n";
        } else
          OS << '<' << SymbolName << ">:\n";
      }

      // Don't print raw contents of a virtual section. A virtual section
      // doesn't have any contents in the file.
      if (Section.isVirtual()) {
        OS << "...\n";
        continue;
      }

      // See if any of the symbols defined at this location triggers target-
      // specific disassembly behavior, e.g. of special descriptors or function
      // prelude information.
      //
      // We stop this loop at the first symbol that triggers some kind of
      // interesting behavior (if any), on the assumption that if two symbols
      // defined at the same address trigger two conflicting symbol handlers,
      // the object file is probably confused anyway, and it would make even
      // less sense to present the output of _both_ handlers, because that
      // would describe the same data twice.
      for (size_t SHI = 0; SHI < SymbolsHere.size(); ++SHI) {
        SymbolInfoTy Symbol = SymbolsHere[SHI];

        Expected<bool> RespondedOrErr = DT->DisAsm->onSymbolStart(
            Symbol, Size, Bytes.slice(Start, End - Start), SectionAddr + Start);

        if (RespondedOrErr && !*RespondedOrErr) {
          // This symbol didn't trigger any interesting handling. Try the other
          // symbols defined at this address.
          continue;
        }

        // If onSymbolStart returned an Error, that means it identified some
        // kind of special data at this address, but wasn't able to disassemble
        // it meaningfully. So we fall back to printing the error out and
        // disassembling the failed region as bytes, assuming that the target
        // detected the failure before printing anything.
        if (!RespondedOrErr) {
          std::string ErrMsgStr = toString(RespondedOrErr.takeError());
          StringRef ErrMsg = ErrMsgStr;
          do {
            StringRef Line;
            std::tie(Line, ErrMsg) = ErrMsg.split('\n');
            OS << DT->Context->getAsmInfo()->getCommentString()
               << " error decoding " << SymNamesHere[SHI] << ": " << Line
               << '\n';
          } while (!ErrMsg.empty());

          if (Size) {
            OS << DT->Context->getAsmInfo()->getCommentString()
               << " decoding failed region as bytes\n";
            for (uint64_t I = 0; I < Size; ++I)
              OS << "\t.byte\t " << format_hex(Bytes[I], 1, /*Upper=*/true)
                 << '\n';
          }
        }

        // Regardless of whether onSymbolStart returned an Error or true, 'Size'
        // will have been set to the amount of data covered by whatever prologue
        // the target identified. So we advance our own position to beyond that.
        // Sometimes that will be the entire distance to the next symbol, and
        // sometimes it will be just a prologue and we should start
        // disassembling instructions from where it left off.
        Start += Size;
        break;
      }
      // Allow targets to reset any per-symbol state.
      DT->Printer->onSymbolStart();
      formatted_raw_ostream FOS(OS);
      Index = Start;
      if (SectionAddr < StartAddress)
        Index = std::max<uint64_t>(Index, StartAddress - SectionAddr);

      if (DisassembleAsELFData) {
        dumpELFData(SectionAddr, Index, End, Bytes, FOS);
        Index = End;
        continue;
      }

      // Skip relocations from symbols that are not dumped.
      for (; RelCur != RelEnd; ++RelCur) {
        uint64_t Offset = RelCur->getOffset() - RelAdjustment;
        if (Index <= Offset)
          break;
      }

      bool DumpARMELFData = false;
      bool DumpTracebackTableForXCOFFFunction =
          Obj.isXCOFF() && Section.isText() && TracebackTable &&
          Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass &&
          (*Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass == XCOFF::XMC_PR);

      std::unordered_map<uint64_t, std::string> AllLabels;
      std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> BBAddrMapLabels;
      if (SymbolizeOperands) {
        collectLocalBranchTargets(Bytes, DT->InstrAnalysis.get(),
                                  DT->DisAsm.get(), DT->InstPrinter.get(),
                                  PrimaryTarget.SubtargetInfo.get(),
                                  SectionAddr, Index, End, AllLabels);
        collectBBAddrMapLabels(FullAddrMap, SectionAddr, Index, End,
                               BBAddrMapLabels);
      }

      if (DT->InstrAnalysis)
        DT->InstrAnalysis->resetState();

      while (Index < End) {
        uint64_t RelOffset;

        // ARM and AArch64 ELF binaries can interleave data and text in the
        // same section. We rely on the markers introduced to understand what
        // we need to dump. If the data marker is within a function, it is
        // denoted as a word/short etc.
        if (!MappingSymbols.empty()) {
          char Kind = getMappingSymbolKind(MappingSymbols, Index);
          DumpARMELFData = Kind == 'd';
          if (SecondaryTarget) {
            if (Kind == 'a') {
              DT = PrimaryIsThumb ? &*SecondaryTarget : &PrimaryTarget;
            } else if (Kind == 't') {
              DT = PrimaryIsThumb ? &PrimaryTarget : &*SecondaryTarget;
            }
          }
        } else if (!CHPECodeMap.empty()) {
          uint64_t Address = SectionAddr + Index;
          auto It = partition_point(
              CHPECodeMap,
              [Address](const std::pair<uint64_t, uint64_t> &Entry) {
                return Entry.first <= Address;
              });
          if (It != CHPECodeMap.begin() && Address < (It - 1)->second) {
            DT = &*SecondaryTarget;
          } else {
            DT = &PrimaryTarget;
            // X64 disassembler range may have left Index unaligned, so
            // make sure that it's aligned when we switch back to ARM64
            // code.
            Index = llvm::alignTo(Index, 4);
            if (Index >= End)
              break;
          }
        }

        auto findRel = [&]() {
          while (RelCur != RelEnd) {
            RelOffset = RelCur->getOffset() - RelAdjustment;
            // If this relocation is hidden, skip it.
            if (getHidden(*RelCur) || SectionAddr + RelOffset < StartAddress) {
              ++RelCur;
              continue;
            }

            // Stop when RelCur's offset is past the disassembled
            // instruction/data.
            if (RelOffset >= Index + Size)
              return false;
            if (RelOffset >= Index)
              return true;
            ++RelCur;
          }
          return false;
        };

        // When -z or --disassemble-zeroes are given we always dissasemble
        // them. Otherwise we might want to skip zero bytes we see.
        if (!DisassembleZeroes) {
          uint64_t MaxOffset = End - Index;
          // For --reloc: print zero blocks patched by relocations, so that
          // relocations can be shown in the dump.
          if (InlineRelocs && RelCur != RelEnd)
            MaxOffset = std::min(RelCur->getOffset() - RelAdjustment - Index,
                                 MaxOffset);

          if (size_t N =
                  countSkippableZeroBytes(Bytes.slice(Index, MaxOffset))) {
            FOS << "\t\t..." << '\n';
            Index += N;
            continue;
          }
        }

        if (DumpARMELFData) {
          Size = dumpARMELFData(SectionAddr, Index, End, Obj, Bytes,
                                MappingSymbols, *DT->SubtargetInfo, FOS);
        } else {

          if (DumpTracebackTableForXCOFFFunction &&
              doesXCOFFTracebackTableBegin(Bytes.slice(Index, 4))) {
            dumpTracebackTable(Bytes.slice(Index),
                               SectionAddr + Index + VMAAdjustment, FOS,
                               SectionAddr + End + VMAAdjustment,
                               *DT->SubtargetInfo, cast<XCOFFObjectFile>(&Obj));
            Index = End;
            continue;
          }

          // Print local label if there's any.
          auto Iter1 = BBAddrMapLabels.find(SectionAddr + Index);
          if (Iter1 != BBAddrMapLabels.end()) {
            for (const auto &BBLabel : Iter1->second)
              FOS << "<" << BBLabel.BlockLabel << ">" << BBLabel.PGOAnalysis
                  << ":\n";
          } else {
            auto Iter2 = AllLabels.find(SectionAddr + Index);
            if (Iter2 != AllLabels.end())
              FOS << "<" << Iter2->second << ">:\n";
          }

          // Disassemble a real instruction or a data when disassemble all is
          // provided
          MCInst Inst;
          ArrayRef<uint8_t> ThisBytes = Bytes.slice(Index);
          uint64_t ThisAddr = SectionAddr + Index + VMAAdjustment;
          bool Disassembled = DT->DisAsm->getInstruction(
              Inst, Size, ThisBytes, ThisAddr, CommentStream);
          if (Size == 0)
            Size = std::min<uint64_t>(
                ThisBytes.size(),
                DT->DisAsm->suggestBytesToSkip(ThisBytes, ThisAddr));

          LEP.update({ThisAddr, Section.getIndex()},
                     {ThisAddr + Size, Section.getIndex()},
                     Index + Size != End);

          DT->InstPrinter->setCommentStream(CommentStream);

          DT->Printer->printInst(
              *DT->InstPrinter, Disassembled ? &Inst : nullptr,
              Bytes.slice(Index, Size),
              {SectionAddr + Index + VMAAdjustment, Section.getIndex()}, FOS,
              "", *DT->SubtargetInfo, &SP, Obj.getFileName(), &Rels, LEP);

          DT->InstPrinter->setCommentStream(llvm::nulls());

          // If disassembly succeeds, we try to resolve the target address
          // (jump target or memory operand address) and print it to the
          // right of the instruction.
          //
          // Otherwise, we don't print anything else so that we avoid
          // analyzing invalid or incomplete instruction information.
          if (Disassembled && DT->InstrAnalysis) {
            llvm::raw_ostream *TargetOS = &FOS;
            uint64_t Target;
            bool PrintTarget = DT->InstrAnalysis->evaluateBranch(
                Inst, SectionAddr + Index, Size, Target);

            if (!PrintTarget) {
              if (std::optional<uint64_t> MaybeTarget =
                      DT->InstrAnalysis->evaluateMemoryOperandAddress(
                          Inst, DT->SubtargetInfo.get(), SectionAddr + Index,
                          Size)) {
                Target = *MaybeTarget;
                PrintTarget = true;
                // Do not print real address when symbolizing.
                if (!SymbolizeOperands) {
                  // Memory operand addresses are printed as comments.
                  TargetOS = &CommentStream;
                  *TargetOS << "0x" << Twine::utohexstr(Target);
                }
              }
            }

            if (PrintTarget) {
              // In a relocatable object, the target's section must reside in
              // the same section as the call instruction or it is accessed
              // through a relocation.
              //
              // In a non-relocatable object, the target may be in any section.
              // In that case, locate the section(s) containing the target
              // address and find the symbol in one of those, if possible.
              //
              // N.B. Except for XCOFF, we don't walk the relocations in the
              // relocatable case yet.
              std::vector<const SectionSymbolsTy *> TargetSectionSymbols;
              if (!Obj.isRelocatableObject()) {
                auto It = llvm::partition_point(
                    SectionAddresses,
                    [=](const std::pair<uint64_t, SectionRef> &O) {
                      return O.first <= Target;
                    });
                uint64_t TargetSecAddr = 0;
                while (It != SectionAddresses.begin()) {
                  --It;
                  if (TargetSecAddr == 0)
                    TargetSecAddr = It->first;
                  if (It->first != TargetSecAddr)
                    break;
                  TargetSectionSymbols.push_back(&AllSymbols[It->second]);
                }
              } else {
                TargetSectionSymbols.push_back(&Symbols);
              }
              TargetSectionSymbols.push_back(&AbsoluteSymbols);

              // Find the last symbol in the first candidate section whose
              // offset is less than or equal to the target. If there are no
              // such symbols, try in the next section and so on, before finally
              // using the nearest preceding absolute symbol (if any), if there
              // are no other valid symbols.
              const SymbolInfoTy *TargetSym = nullptr;
              for (const SectionSymbolsTy *TargetSymbols :
                   TargetSectionSymbols) {
                auto It = llvm::partition_point(
                    *TargetSymbols,
                    [=](const SymbolInfoTy &O) { return O.Addr <= Target; });
                while (It != TargetSymbols->begin()) {
                  --It;
                  // Skip mapping symbols to avoid possible ambiguity as they
                  // do not allow uniquely identifying the target address.
                  if (!It->IsMappingSymbol) {
                    TargetSym = &*It;
                    break;
                  }
                }
                if (TargetSym)
                  break;
              }

              // Branch targets are printed just after the instructions.
              // Print the labels corresponding to the target if there's any.
              bool BBAddrMapLabelAvailable = BBAddrMapLabels.count(Target);
              bool LabelAvailable = AllLabels.count(Target);

              if (TargetSym != nullptr) {
                uint64_t TargetAddress = TargetSym->Addr;
                uint64_t Disp = Target - TargetAddress;
                std::string TargetName = Demangle ? demangle(TargetSym->Name)
                                                  : TargetSym->Name.str();
                bool RelFixedUp = false;
                SmallString<32> Val;

                *TargetOS << " <";
                // On XCOFF, we use relocations, even without -r, so we
                // can print the correct name for an extern function call.
                if (Obj.isXCOFF() && findRel()) {
                  // Check for possible branch relocations and
                  // branches to fixup code.
                  bool BranchRelocationType = true;
                  XCOFF::RelocationType RelocType;
                  if (Obj.is64Bit()) {
                    const XCOFFRelocation64 *Reloc =
                        reinterpret_cast<XCOFFRelocation64 *>(
                            RelCur->getRawDataRefImpl().p);
                    RelFixedUp = Reloc->isFixupIndicated();
                    RelocType = Reloc->Type;
                  } else {
                    const XCOFFRelocation32 *Reloc =
                        reinterpret_cast<XCOFFRelocation32 *>(
                            RelCur->getRawDataRefImpl().p);
                    RelFixedUp = Reloc->isFixupIndicated();
                    RelocType = Reloc->Type;
                  }
                  BranchRelocationType =
                      RelocType == XCOFF::R_BA || RelocType == XCOFF::R_BR ||
                      RelocType == XCOFF::R_RBA || RelocType == XCOFF::R_RBR;

                  // If we have a valid relocation, try to print its
                  // corresponding symbol name. Multiple relocations on the
                  // same instruction are not handled.
                  // Branches to fixup code will have the RelFixedUp flag set in
                  // the RLD. For these instructions, we print the correct
                  // branch target, but print the referenced symbol as a
                  // comment.
                  if (Error E = getRelocationValueString(*RelCur, false, Val)) {
                    // If -r was used, this error will be printed later.
                    // Otherwise, we ignore the error and print what
                    // would have been printed without using relocations.
                    consumeError(std::move(E));
                    *TargetOS << TargetName;
                    RelFixedUp = false; // Suppress comment for RLD sym name
                  } else if (BranchRelocationType && !RelFixedUp)
                    *TargetOS << Val;
                  else
                    *TargetOS << TargetName;
                  if (Disp)
                    *TargetOS << "+0x" << Twine::utohexstr(Disp);
                } else if (!Disp) {
                  *TargetOS << TargetName;
                } else if (BBAddrMapLabelAvailable) {
                  *TargetOS << BBAddrMapLabels[Target].front().BlockLabel;
                } else if (LabelAvailable) {
                  *TargetOS << AllLabels[Target];
                } else {
                  // Always Print the binary symbol plus an offset if there's no
                  // local label corresponding to the target address.
                  *TargetOS << TargetName << "+0x" << Twine::utohexstr(Disp);
                }
                *TargetOS << ">";
                if (RelFixedUp && !InlineRelocs) {
                  // We have fixup code for a relocation. We print the
                  // referenced symbol as a comment.
                  *TargetOS << "\t# " << Val;
                }

              } else if (BBAddrMapLabelAvailable) {
                *TargetOS << " <" << BBAddrMapLabels[Target].front().BlockLabel
                          << ">";
              } else if (LabelAvailable) {
                *TargetOS << " <" << AllLabels[Target] << ">";
              }
              // By convention, each record in the comment stream should be
              // terminated.
              if (TargetOS == &CommentStream)
                *TargetOS << "\n";
            }

            DT->InstrAnalysis->updateState(Inst, SectionAddr + Index);
          } else if (!Disassembled && DT->InstrAnalysis) {
            DT->InstrAnalysis->resetState();
          }
        }

        assert(DT->Context->getAsmInfo());
        DT->Printer->emitPostInstructionInfo(FOS, *DT->Context->getAsmInfo(),
                                             *DT->SubtargetInfo,
                                             CommentStream.str(), LEP);
        Comments.clear();

        if (BTF)
          printBTFRelocation(FOS, *BTF, {Index, Section.getIndex()}, LEP);

        if (InlineRelocs) {
          while (findRel()) {
            // When --adjust-vma is used, update the address printed.
            printRelocation(FOS, Obj.getFileName(), *RelCur,
                            SectionAddr + RelOffset + VMAAdjustment, Is64Bits);
            LEP.printAfterOtherLine(FOS, true);
            ++RelCur;
          }
        }

        object::SectionedAddress NextAddr = {
            SectionAddr + Index + VMAAdjustment + Size, Section.getIndex()};
        LEP.printBoundaryLine(FOS, NextAddr, true);

        Index += Size;
      }
    }
  }
  StringSet<> MissingDisasmSymbolSet =
      set_difference(DisasmSymbolSet, FoundDisasmSymbolSet);
  for (StringRef Sym : MissingDisasmSymbolSet.keys())
    reportWarning("failed to disassemble missing symbol " + Sym, FileName);
}

static void disassembleObject(ObjectFile *Obj, bool InlineRelocs,
                              raw_ostream &OS) {
  // If information useful for showing the disassembly is missing, try to find a
  // more complete binary and disassemble that instead.
  OwningBinary<Binary> FetchedBinary;
  if (Obj->symbols().empty()) {
    if (std::optional<OwningBinary<Binary>> FetchedBinaryOpt =
            fetchBinaryByBuildID(*Obj)) {
      if (auto *O = dyn_cast<ObjectFile>(FetchedBinaryOpt->getBinary())) {
        if (!O->symbols().empty() ||
            (!O->sections().empty() && Obj->sections().empty())) {
          FetchedBinary = std::move(*FetchedBinaryOpt);
          Obj = O;
        }
      }
    }
  }

  const Target *TheTarget = getTarget(Obj);

  // Package up features to be passed to target/subtarget
  Expected<SubtargetFeatures> FeaturesValue = Obj->getFeatures();
  if (!FeaturesValue)
    reportError(FeaturesValue.takeError(), Obj->getFileName());
  SubtargetFeatures Features = *FeaturesValue;
  if (!MAttrs.empty()) {
    for (unsigned I = 0; I != MAttrs.size(); ++I)
      Features.AddFeature(MAttrs[I]);
  } else if (MCPU.empty() && Obj->makeTriple().isAArch64()) {
    Features.AddFeature("+all");
  }

  if (MCPU.empty())
    MCPU = Obj->tryGetCPUName().value_or("").str();

  if (isArmElf(*Obj)) {
    // When disassembling big-endian Arm ELF, the instruction endianness is
    // determined in a complex way. In relocatable objects, AAELF32 mandates
    // that instruction endianness matches the ELF file endianness; in
    // executable images, that's true unless the file header has the EF_ARM_BE8
    // flag, in which case instructions are little-endian regardless of data
    // endianness.
    //
    // We must set the big-endian-instructions SubtargetFeature to make the
    // disassembler read the instructions the right way round, and also tell
    // our own prettyprinter to retrieve the encodings the same way to print in
    // hex.
    const auto *Elf32BE = dyn_cast<ELF32BEObjectFile>(Obj);

    if (Elf32BE && (Elf32BE->isRelocatableObject() ||
                    !(Elf32BE->getPlatformFlags() & ELF::EF_ARM_BE8))) {
      Features.AddFeature("+big-endian-instructions");
      ARMPrettyPrinterInst.setInstructionEndianness(llvm::endianness::big);
    } else {
      ARMPrettyPrinterInst.setInstructionEndianness(llvm::endianness::little);
    }
  }

  DisassemblerTarget PrimaryTarget(TheTarget, *Obj, TripleName, MCPU, Features);

  // If we have an ARM object file, we need a second disassembler, because
  // ARM CPUs have two different instruction sets: ARM mode, and Thumb mode.
  // We use mapping symbols to switch between the two assemblers, where
  // appropriate.
  std::optional<DisassemblerTarget> SecondaryTarget;

  if (isArmElf(*Obj)) {
    if (!PrimaryTarget.SubtargetInfo->checkFeatures("+mclass")) {
      if (PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode"))
        Features.AddFeature("-thumb-mode");
      else
        Features.AddFeature("+thumb-mode");
      SecondaryTarget.emplace(PrimaryTarget, Features);
    }
  } else if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Obj)) {
    const chpe_metadata *CHPEMetadata = COFFObj->getCHPEMetadata();
    if (CHPEMetadata && CHPEMetadata->CodeMapCount) {
      // Set up x86_64 disassembler for ARM64EC binaries.
      Triple X64Triple(TripleName);
      X64Triple.setArch(Triple::ArchType::x86_64);

      std::string Error;
      const Target *X64Target =
          TargetRegistry::lookupTarget("", X64Triple, Error);
      if (X64Target) {
        SubtargetFeatures X64Features;
        SecondaryTarget.emplace(X64Target, *Obj, X64Triple.getTriple(), "",
                                X64Features);
      } else {
        reportWarning(Error, Obj->getFileName());
      }
    }
  }

  const ObjectFile *DbgObj = Obj;
  if (!FetchedBinary.getBinary() && !Obj->hasDebugInfo()) {
    if (std::optional<OwningBinary<Binary>> DebugBinaryOpt =
            fetchBinaryByBuildID(*Obj)) {
      if (auto *FetchedObj =
              dyn_cast<const ObjectFile>(DebugBinaryOpt->getBinary())) {
        if (FetchedObj->hasDebugInfo()) {
          FetchedBinary = std::move(*DebugBinaryOpt);
          DbgObj = FetchedObj;
        }
      }
    }
  }

  std::unique_ptr<object::Binary> DSYMBinary;
  std::unique_ptr<MemoryBuffer> DSYMBuf;
  if (!DbgObj->hasDebugInfo()) {
    if (const MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*Obj)) {
      DbgObj = objdump::getMachODSymObject(MachOOF, Obj->getFileName(),
                                           DSYMBinary, DSYMBuf);
      if (!DbgObj)
        return;
    }
  }

  SourcePrinter SP(DbgObj, TheTarget->getName());

  for (StringRef Opt : DisassemblerOptions)
    if (!PrimaryTarget.InstPrinter->applyTargetSpecificCLOption(Opt))
      reportError(Obj->getFileName(),
                  "Unrecognized disassembler option: " + Opt);

  disassembleObject(*Obj, *DbgObj, PrimaryTarget, SecondaryTarget, SP,
                    InlineRelocs, OS);
}

void Dumper::printRelocations() {
  StringRef Fmt = O.getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;

  // Build a mapping from relocation target to a vector of relocation
  // sections. Usually, there is an only one relocation section for
  // each relocated section.
  MapVector<SectionRef, std::vector<SectionRef>> SecToRelSec;
  uint64_t Ndx;
  for (const SectionRef &Section : ToolSectionFilter(O, &Ndx)) {
    if (O.isELF() && (ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC))
      continue;
    if (Section.relocations().empty())
      continue;
    Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
    if (!SecOrErr)
      reportError(O.getFileName(),
                  "section (" + Twine(Ndx) +
                      "): unable to get a relocation target: " +
                      toString(SecOrErr.takeError()));
    SecToRelSec[**SecOrErr].push_back(Section);
  }

  for (std::pair<SectionRef, std::vector<SectionRef>> &P : SecToRelSec) {
    StringRef SecName = unwrapOrError(P.first.getName(), O.getFileName());
    outs() << "\nRELOCATION RECORDS FOR [" << SecName << "]:\n";
    uint32_t OffsetPadding = (O.getBytesInAddress() > 4 ? 16 : 8);
    uint32_t TypePadding = 24;
    outs() << left_justify("OFFSET", OffsetPadding) << " "
           << left_justify("TYPE", TypePadding) << " "
           << "VALUE\n";

    for (SectionRef Section : P.second) {
      // CREL sections require decoding, each section may have its own specific
      // decode problems.
      if (O.isELF() && ELFSectionRef(Section).getType() == ELF::SHT_CREL) {
        StringRef Err =
            cast<const ELFObjectFileBase>(O).getCrelDecodeProblem(Section);
        if (!Err.empty()) {
          reportUniqueWarning(Err);
          continue;
        }
      }
      for (const RelocationRef &Reloc : Section.relocations()) {
        uint64_t Address = Reloc.getOffset();
        SmallString<32> RelocName;
        SmallString<32> ValueStr;
        if (Address < StartAddress || Address > StopAddress || getHidden(Reloc))
          continue;
        Reloc.getTypeName(RelocName);
        if (Error E =
                getRelocationValueString(Reloc, SymbolDescription, ValueStr))
          reportUniqueWarning(std::move(E));

        outs() << format(Fmt.data(), Address) << " "
               << left_justify(RelocName, TypePadding) << " " << ValueStr
               << "\n";
      }
    }
  }
}

// Returns true if we need to show LMA column when dumping section headers. We
// show it only when the platform is ELF and either we have at least one section
// whose VMA and LMA are different and/or when --show-lma flag is used.
static bool shouldDisplayLMA(const ObjectFile &Obj) {
  if (!Obj.isELF())
    return false;
  for (const SectionRef &S : ToolSectionFilter(Obj))
    if (S.getAddress() != getELFSectionLMA(S))
      return true;
  return ShowLMA;
}

static size_t getMaxSectionNameWidth(const ObjectFile &Obj) {
  // Default column width for names is 13 even if no names are that long.
  size_t MaxWidth = 13;
  for (const SectionRef &Section : ToolSectionFilter(Obj)) {
    StringRef Name = unwrapOrError(Section.getName(), Obj.getFileName());
    MaxWidth = std::max(MaxWidth, Name.size());
  }
  return MaxWidth;
}

void objdump::printSectionHeaders(ObjectFile &Obj) {
  if (Obj.isELF() && Obj.sections().empty())
    createFakeELFSections(Obj);

  size_t NameWidth = getMaxSectionNameWidth(Obj);
  size_t AddressWidth = 2 * Obj.getBytesInAddress();
  bool HasLMAColumn = shouldDisplayLMA(Obj);
  outs() << "\nSections:\n";
  if (HasLMAColumn)
    outs() << "Idx " << left_justify("Name", NameWidth) << " Size     "
           << left_justify("VMA", AddressWidth) << " "
           << left_justify("LMA", AddressWidth) << " Type\n";
  else
    outs() << "Idx " << left_justify("Name", NameWidth) << " Size     "
           << left_justify("VMA", AddressWidth) << " Type\n";

  uint64_t Idx;
  for (const SectionRef &Section : ToolSectionFilter(Obj, &Idx)) {
    StringRef Name = unwrapOrError(Section.getName(), Obj.getFileName());
    uint64_t VMA = Section.getAddress();
    if (shouldAdjustVA(Section))
      VMA += AdjustVMA;

    uint64_t Size = Section.getSize();

    std::string Type = Section.isText() ? "TEXT" : "";
    if (Section.isData())
      Type += Type.empty() ? "DATA" : ", DATA";
    if (Section.isBSS())
      Type += Type.empty() ? "BSS" : ", BSS";
    if (Section.isDebugSection())
      Type += Type.empty() ? "DEBUG" : ", DEBUG";

    if (HasLMAColumn)
      outs() << format("%3" PRIu64 " %-*s %08" PRIx64 " ", Idx, NameWidth,
                       Name.str().c_str(), Size)
             << format_hex_no_prefix(VMA, AddressWidth) << " "
             << format_hex_no_prefix(getELFSectionLMA(Section), AddressWidth)
             << " " << Type << "\n";
    else
      outs() << format("%3" PRIu64 " %-*s %08" PRIx64 " ", Idx, NameWidth,
                       Name.str().c_str(), Size)
             << format_hex_no_prefix(VMA, AddressWidth) << " " << Type << "\n";
  }
}

void objdump::printSectionContents(const ObjectFile *Obj) {
  const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj);

  for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
    StringRef Name = unwrapOrError(Section.getName(), Obj->getFileName());
    uint64_t BaseAddr = Section.getAddress();
    uint64_t Size = Section.getSize();
    if (!Size)
      continue;

    outs() << "Contents of section ";
    StringRef SegmentName = getSegmentName(MachO, Section);
    if (!SegmentName.empty())
      outs() << SegmentName << ",";
    outs() << Name << ":\n";
    if (Section.isBSS()) {
      outs() << format("<skipping contents of bss section at [%04" PRIx64
                       ", %04" PRIx64 ")>\n",
                       BaseAddr, BaseAddr + Size);
      continue;
    }

    StringRef Contents =
        unwrapOrError(Section.getContents(), Obj->getFileName());

    // Dump out the content as hex and printable ascii characters.
    for (std::size_t Addr = 0, End = Contents.size(); Addr < End; Addr += 16) {
      outs() << format(" %04" PRIx64 " ", BaseAddr + Addr);
      // Dump line of hex.
      for (std::size_t I = 0; I < 16; ++I) {
        if (I != 0 && I % 4 == 0)
          outs() << ' ';
        if (Addr + I < End)
          outs() << hexdigit((Contents[Addr + I] >> 4) & 0xF, true)
                 << hexdigit(Contents[Addr + I] & 0xF, true);
        else
          outs() << "  ";
      }
      // Print ascii.
      outs() << "  ";
      for (std::size_t I = 0; I < 16 && Addr + I < End; ++I) {
        if (isPrint(static_cast<unsigned char>(Contents[Addr + I]) & 0xFF))
          outs() << Contents[Addr + I];
        else
          outs() << ".";
      }
      outs() << "\n";
    }
  }
}

void Dumper::printSymbolTable(StringRef ArchiveName, StringRef ArchitectureName,
                              bool DumpDynamic) {
  if (O.isCOFF() && !DumpDynamic) {
    outs() << "\nSYMBOL TABLE:\n";
    printCOFFSymbolTable(cast<const COFFObjectFile>(O));
    return;
  }

  const StringRef FileName = O.getFileName();

  if (!DumpDynamic) {
    outs() << "\nSYMBOL TABLE:\n";
    for (auto I = O.symbol_begin(); I != O.symbol_end(); ++I)
      printSymbol(*I, {}, FileName, ArchiveName, ArchitectureName, DumpDynamic);
    return;
  }

  outs() << "\nDYNAMIC SYMBOL TABLE:\n";
  if (!O.isELF()) {
    reportWarning(
        "this operation is not currently supported for this file format",
        FileName);
    return;
  }

  const ELFObjectFileBase *ELF = cast<const ELFObjectFileBase>(&O);
  auto Symbols = ELF->getDynamicSymbolIterators();
  Expected<std::vector<VersionEntry>> SymbolVersionsOrErr =
      ELF->readDynsymVersions();
  if (!SymbolVersionsOrErr) {
    reportWarning(toString(SymbolVersionsOrErr.takeError()), FileName);
    SymbolVersionsOrErr = std::vector<VersionEntry>();
    (void)!SymbolVersionsOrErr;
  }
  for (auto &Sym : Symbols)
    printSymbol(Sym, *SymbolVersionsOrErr, FileName, ArchiveName,
                ArchitectureName, DumpDynamic);
}

void Dumper::printSymbol(const SymbolRef &Symbol,
                         ArrayRef<VersionEntry> SymbolVersions,
                         StringRef FileName, StringRef ArchiveName,
                         StringRef ArchitectureName, bool DumpDynamic) {
  const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(&O);
  Expected<uint64_t> AddrOrErr = Symbol.getAddress();
  if (!AddrOrErr) {
    reportUniqueWarning(AddrOrErr.takeError());
    return;
  }

  // Don't ask a Mach-O STAB symbol for its section unless you know that
  // STAB symbol's section field refers to a valid section index. Otherwise
  // the symbol may error trying to load a section that does not exist.
  bool IsSTAB = false;
  if (MachO) {
    DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
    uint8_t NType =
        (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type
                          : MachO->getSymbolTableEntry(SymDRI).n_type);
    if (NType & MachO::N_STAB)
      IsSTAB = true;
  }
  section_iterator Section = IsSTAB
                                 ? O.section_end()
                                 : unwrapOrError(Symbol.getSection(), FileName,
                                                 ArchiveName, ArchitectureName);

  uint64_t Address = *AddrOrErr;
  if (Section != O.section_end() && shouldAdjustVA(*Section))
    Address += AdjustVMA;
  if ((Address < StartAddress) || (Address > StopAddress))
    return;
  SymbolRef::Type Type =
      unwrapOrError(Symbol.getType(), FileName, ArchiveName, ArchitectureName);
  uint32_t Flags =
      unwrapOrError(Symbol.getFlags(), FileName, ArchiveName, ArchitectureName);

  StringRef Name;
  if (Type == SymbolRef::ST_Debug && Section != O.section_end()) {
    if (Expected<StringRef> NameOrErr = Section->getName())
      Name = *NameOrErr;
    else
      consumeError(NameOrErr.takeError());

  } else {
    Name = unwrapOrError(Symbol.getName(), FileName, ArchiveName,
                         ArchitectureName);
  }

  bool Global = Flags & SymbolRef::SF_Global;
  bool Weak = Flags & SymbolRef::SF_Weak;
  bool Absolute = Flags & SymbolRef::SF_Absolute;
  bool Common = Flags & SymbolRef::SF_Common;
  bool Hidden = Flags & SymbolRef::SF_Hidden;

  char GlobLoc = ' ';
  if ((Section != O.section_end() || Absolute) && !Weak)
    GlobLoc = Global ? 'g' : 'l';
  char IFunc = ' ';
  if (O.isELF()) {
    if (ELFSymbolRef(Symbol).getELFType() == ELF::STT_GNU_IFUNC)
      IFunc = 'i';
    if (ELFSymbolRef(Symbol).getBinding() == ELF::STB_GNU_UNIQUE)
      GlobLoc = 'u';
  }

  char Debug = ' ';
  if (DumpDynamic)
    Debug = 'D';
  else if (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)
    Debug = 'd';

  char FileFunc = ' ';
  if (Type == SymbolRef::ST_File)
    FileFunc = 'f';
  else if (Type == SymbolRef::ST_Function)
    FileFunc = 'F';
  else if (Type == SymbolRef::ST_Data)
    FileFunc = 'O';

  const char *Fmt = O.getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;

  outs() << format(Fmt, Address) << " "
         << GlobLoc            // Local -> 'l', Global -> 'g', Neither -> ' '
         << (Weak ? 'w' : ' ') // Weak?
         << ' '                // Constructor. Not supported yet.
         << ' '                // Warning. Not supported yet.
         << IFunc              // Indirect reference to another symbol.
         << Debug              // Debugging (d) or dynamic (D) symbol.
         << FileFunc           // Name of function (F), file (f) or object (O).
         << ' ';
  if (Absolute) {
    outs() << "*ABS*";
  } else if (Common) {
    outs() << "*COM*";
  } else if (Section == O.section_end()) {
    if (O.isXCOFF()) {
      XCOFFSymbolRef XCOFFSym = cast<const XCOFFObjectFile>(O).toSymbolRef(
          Symbol.getRawDataRefImpl());
      if (XCOFF::N_DEBUG == XCOFFSym.getSectionNumber())
        outs() << "*DEBUG*";
      else
        outs() << "*UND*";
    } else
      outs() << "*UND*";
  } else {
    StringRef SegmentName = getSegmentName(MachO, *Section);
    if (!SegmentName.empty())
      outs() << SegmentName << ",";
    StringRef SectionName = unwrapOrError(Section->getName(), FileName);
    outs() << SectionName;
    if (O.isXCOFF()) {
      std::optional<SymbolRef> SymRef =
          getXCOFFSymbolContainingSymbolRef(cast<XCOFFObjectFile>(O), Symbol);
      if (SymRef) {

        Expected<StringRef> NameOrErr = SymRef->getName();

        if (NameOrErr) {
          outs() << " (csect:";
          std::string SymName =
              Demangle ? demangle(*NameOrErr) : NameOrErr->str();

          if (SymbolDescription)
            SymName = getXCOFFSymbolDescription(createSymbolInfo(O, *SymRef),
                                                SymName);

          outs() << ' ' << SymName;
          outs() << ") ";
        } else
          reportWarning(toString(NameOrErr.takeError()), FileName);
      }
    }
  }

  if (Common)
    outs() << '\t' << format(Fmt, static_cast<uint64_t>(Symbol.getAlignment()));
  else if (O.isXCOFF())
    outs() << '\t'
           << format(Fmt, cast<XCOFFObjectFile>(O).getSymbolSize(
                              Symbol.getRawDataRefImpl()));
  else if (O.isELF())
    outs() << '\t' << format(Fmt, ELFSymbolRef(Symbol).getSize());
  else if (O.isWasm())
    outs() << '\t'
           << format(Fmt, static_cast<uint64_t>(
                              cast<WasmObjectFile>(O).getSymbolSize(Symbol)));

  if (O.isELF()) {
    if (!SymbolVersions.empty()) {
      const VersionEntry &Ver =
          SymbolVersions[Symbol.getRawDataRefImpl().d.b - 1];
      std::string Str;
      if (!Ver.Name.empty())
        Str = Ver.IsVerDef ? ' ' + Ver.Name : '(' + Ver.Name + ')';
      outs() << ' ' << left_justify(Str, 12);
    }

    uint8_t Other = ELFSymbolRef(Symbol).getOther();
    switch (Other) {
    case ELF::STV_DEFAULT:
      break;
    case ELF::STV_INTERNAL:
      outs() << " .internal";
      break;
    case ELF::STV_HIDDEN:
      outs() << " .hidden";
      break;
    case ELF::STV_PROTECTED:
      outs() << " .protected";
      break;
    default:
      outs() << format(" 0x%02x", Other);
      break;
    }
  } else if (Hidden) {
    outs() << " .hidden";
  }

  std::string SymName = Demangle ? demangle(Name) : Name.str();
  if (O.isXCOFF() && SymbolDescription)
    SymName = getXCOFFSymbolDescription(createSymbolInfo(O, Symbol), SymName);

  outs() << ' ' << SymName << '\n';
}

static void printUnwindInfo(const ObjectFile *O) {
  outs() << "Unwind info:\n\n";

  if (const COFFObjectFile *Coff = dyn_cast<COFFObjectFile>(O))
    printCOFFUnwindInfo(Coff);
  else if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O))
    printMachOUnwindInfo(MachO);
  else
    // TODO: Extract DWARF dump tool to objdump.
    WithColor::error(errs(), ToolName)
        << "This operation is only currently supported "
           "for COFF and MachO object files.\n";
}

/// Dump the raw contents of the __clangast section so the output can be piped
/// into llvm-bcanalyzer.
static void printRawClangAST(const ObjectFile *Obj) {
  if (outs().is_displayed()) {
    WithColor::error(errs(), ToolName)
        << "The -raw-clang-ast option will dump the raw binary contents of "
           "the clang ast section.\n"
           "Please redirect the output to a file or another program such as "
           "llvm-bcanalyzer.\n";
    return;
  }

  StringRef ClangASTSectionName("__clangast");
  if (Obj->isCOFF()) {
    ClangASTSectionName = "clangast";
  }

  std::optional<object::SectionRef> ClangASTSection;
  for (auto Sec : ToolSectionFilter(*Obj)) {
    StringRef Name;
    if (Expected<StringRef> NameOrErr = Sec.getName())
      Name = *NameOrErr;
    else
      consumeError(NameOrErr.takeError());

    if (Name == ClangASTSectionName) {
      ClangASTSection = Sec;
      break;
    }
  }
  if (!ClangASTSection)
    return;

  StringRef ClangASTContents =
      unwrapOrError(ClangASTSection->getContents(), Obj->getFileName());
  outs().write(ClangASTContents.data(), ClangASTContents.size());
}

static void printFaultMaps(const ObjectFile *Obj) {
  StringRef FaultMapSectionName;

  if (Obj->isELF()) {
    FaultMapSectionName = ".llvm_faultmaps";
  } else if (Obj->isMachO()) {
    FaultMapSectionName = "__llvm_faultmaps";
  } else {
    WithColor::error(errs(), ToolName)
        << "This operation is only currently supported "
           "for ELF and Mach-O executable files.\n";
    return;
  }

  std::optional<object::SectionRef> FaultMapSection;

  for (auto Sec : ToolSectionFilter(*Obj)) {
    StringRef Name;
    if (Expected<StringRef> NameOrErr = Sec.getName())
      Name = *NameOrErr;
    else
      consumeError(NameOrErr.takeError());

    if (Name == FaultMapSectionName) {
      FaultMapSection = Sec;
      break;
    }
  }

  outs() << "FaultMap table:\n";

  if (!FaultMapSection) {
    outs() << "<not found>\n";
    return;
  }

  StringRef FaultMapContents =
      unwrapOrError(FaultMapSection->getContents(), Obj->getFileName());
  FaultMapParser FMP(FaultMapContents.bytes_begin(),
                     FaultMapContents.bytes_end());

  outs() << FMP;
}

void Dumper::printPrivateHeaders() {
  reportError(O.getFileName(), "Invalid/Unsupported object file format");
}

static void printFileHeaders(const ObjectFile *O) {
  if (!O->isELF() && !O->isCOFF() && !O->isXCOFF())
    reportError(O->getFileName(), "Invalid/Unsupported object file format");

  Triple::ArchType AT = O->getArch();
  outs() << "architecture: " << Triple::getArchTypeName(AT) << "\n";
  uint64_t Address = unwrapOrError(O->getStartAddress(), O->getFileName());

  StringRef Fmt = O->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
  outs() << "start address: "
         << "0x" << format(Fmt.data(), Address) << "\n";
}

static void printArchiveChild(StringRef Filename, const Archive::Child &C) {
  Expected<sys::fs::perms> ModeOrErr = C.getAccessMode();
  if (!ModeOrErr) {
    WithColor::error(errs(), ToolName) << "ill-formed archive entry.\n";
    consumeError(ModeOrErr.takeError());
    return;
  }
  sys::fs::perms Mode = ModeOrErr.get();
  outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
  outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
  outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
  outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
  outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
  outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
  outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
  outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
  outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");

  outs() << " ";

  outs() << format("%d/%d %6" PRId64 " ", unwrapOrError(C.getUID(), Filename),
                   unwrapOrError(C.getGID(), Filename),
                   unwrapOrError(C.getRawSize(), Filename));

  StringRef RawLastModified = C.getRawLastModified();
  unsigned Seconds;
  if (RawLastModified.getAsInteger(10, Seconds))
    outs() << "(date: \"" << RawLastModified
           << "\" contains non-decimal chars) ";
  else {
    // Since ctime(3) returns a 26 character string of the form:
    // "Sun Sep 16 01:03:52 1973\n\0"
    // just print 24 characters.
    time_t t = Seconds;
    outs() << format("%.24s ", ctime(&t));
  }

  StringRef Name = "";
  Expected<StringRef> NameOrErr = C.getName();
  if (!NameOrErr) {
    consumeError(NameOrErr.takeError());
    Name = unwrapOrError(C.getRawName(), Filename);
  } else {
    Name = NameOrErr.get();
  }
  outs() << Name << "\n";
}

// For ELF only now.
static bool shouldWarnForInvalidStartStopAddress(ObjectFile *Obj) {
  if (const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj)) {
    if (Elf->getEType() != ELF::ET_REL)
      return true;
  }
  return false;
}

static void checkForInvalidStartStopAddress(ObjectFile *Obj, uint64_t Start,
                                            uint64_t Stop) {
  if (!shouldWarnForInvalidStartStopAddress(Obj))
    return;

  for (const SectionRef &Section : Obj->sections())
    if (ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC) {
      uint64_t BaseAddr = Section.getAddress();
      uint64_t Size = Section.getSize();
      if ((Start < BaseAddr + Size) && Stop > BaseAddr)
        return;
    }

  if (!HasStartAddressFlag)
    reportWarning("no section has address less than 0x" +
                      Twine::utohexstr(Stop) + " specified by --stop-address",
                  Obj->getFileName());
  else if (!HasStopAddressFlag)
    reportWarning("no section has address greater than or equal to 0x" +
                      Twine::utohexstr(Start) + " specified by --start-address",
                  Obj->getFileName());
  else
    reportWarning("no section overlaps the range [0x" +
                      Twine::utohexstr(Start) + ",0x" + Twine::utohexstr(Stop) +
                      ") specified by --start-address/--stop-address",
                  Obj->getFileName());
}

static void dumpObject(ObjectFile *O, const Archive *A = nullptr,
                       const Archive::Child *C = nullptr) {
  Expected<std::unique_ptr<Dumper>> DumperOrErr = createDumper(*O);
  if (!DumperOrErr) {
    reportError(DumperOrErr.takeError(), O->getFileName(),
                A ? A->getFileName() : "");
    return;
  }
  Dumper &D = **DumperOrErr;

  // Avoid other output when using a raw option.
  if (!RawClangAST) {
    outs() << '\n';
    if (A)
      outs() << A->getFileName() << "(" << O->getFileName() << ")";
    else
      outs() << O->getFileName();
    outs() << ":\tfile format " << O->getFileFormatName().lower() << "\n";
  }

  if (HasStartAddressFlag || HasStopAddressFlag)
    checkForInvalidStartStopAddress(O, StartAddress, StopAddress);

  // TODO: Change print* free functions to Dumper member functions to utilitize
  // stateful functions like reportUniqueWarning.

  // Note: the order here matches GNU objdump for compatability.
  StringRef ArchiveName = A ? A->getFileName() : "";
  if (ArchiveHeaders && !MachOOpt && C)
    printArchiveChild(ArchiveName, *C);
  if (FileHeaders)
    printFileHeaders(O);
  if (PrivateHeaders || FirstPrivateHeader)
    D.printPrivateHeaders();
  if (SectionHeaders)
    printSectionHeaders(*O);
  if (SymbolTable)
    D.printSymbolTable(ArchiveName);
  if (DynamicSymbolTable)
    D.printSymbolTable(ArchiveName, /*ArchitectureName=*/"",
                       /*DumpDynamic=*/true);
  if (DwarfDumpType != DIDT_Null) {
    std::unique_ptr<DIContext> DICtx = DWARFContext::create(*O);
    // Dump the complete DWARF structure.
    DIDumpOptions DumpOpts;
    DumpOpts.DumpType = DwarfDumpType;
    DICtx->dump(outs(), DumpOpts);
  }
  if (Relocations && !Disassemble)
    D.printRelocations();
  if (DynamicRelocations)
    D.printDynamicRelocations();
  if (SectionContents)
    printSectionContents(O);
  if (Disassemble)
    disassembleObject(O, Relocations, outs());
  if (UnwindInfo)
    printUnwindInfo(O);

  // Mach-O specific options:
  if (ExportsTrie)
    printExportsTrie(O);
  if (Rebase)
    printRebaseTable(O);
  if (Bind)
    printBindTable(O);
  if (LazyBind)
    printLazyBindTable(O);
  if (WeakBind)
    printWeakBindTable(O);

  // Other special sections:
  if (RawClangAST)
    printRawClangAST(O);
  if (FaultMapSection)
    printFaultMaps(O);
  if (Offloading)
    dumpOffloadBinary(*O, StringRef(ArchName));
}

static void dumpObject(const COFFImportFile *I, const Archive *A,
                       const Archive::Child *C = nullptr) {
  StringRef ArchiveName = A ? A->getFileName() : "";

  // Avoid other output when using a raw option.
  if (!RawClangAST)
    outs() << '\n'
           << ArchiveName << "(" << I->getFileName() << ")"
           << ":\tfile format COFF-import-file"
           << "\n\n";

  if (ArchiveHeaders && !MachOOpt && C)
    printArchiveChild(ArchiveName, *C);
  if (SymbolTable)
    printCOFFSymbolTable(*I);
}

/// Dump each object file in \a a;
static void dumpArchive(const Archive *A) {
  Error Err = Error::success();
  unsigned I = -1;
  for (auto &C : A->children(Err)) {
    ++I;
    Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
    if (!ChildOrErr) {
      if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
        reportError(std::move(E), getFileNameForError(C, I), A->getFileName());
      continue;
    }
    if (ObjectFile *O = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
      dumpObject(O, A, &C);
    else if (COFFImportFile *I = dyn_cast<COFFImportFile>(&*ChildOrErr.get()))
      dumpObject(I, A, &C);
    else
      reportError(errorCodeToError(object_error::invalid_file_type),
                  A->getFileName());
  }
  if (Err)
    reportError(std::move(Err), A->getFileName());
}

/// Open file and figure out how to dump it.
static void dumpInput(StringRef file) {
  // If we are using the Mach-O specific object file parser, then let it parse
  // the file and process the command line options.  So the -arch flags can
  // be used to select specific slices, etc.
  if (MachOOpt) {
    parseInputMachO(file);
    return;
  }

  // Attempt to open the binary.
  OwningBinary<Binary> OBinary = unwrapOrError(createBinary(file), file);
  Binary &Binary = *OBinary.getBinary();

  if (Archive *A = dyn_cast<Archive>(&Binary))
    dumpArchive(A);
  else if (ObjectFile *O = dyn_cast<ObjectFile>(&Binary))
    dumpObject(O);
  else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Binary))
    parseInputMachO(UB);
  else if (OffloadBinary *OB = dyn_cast<OffloadBinary>(&Binary))
    dumpOffloadSections(*OB);
  else
    reportError(errorCodeToError(object_error::invalid_file_type), file);
}

template <typename T>
static void parseIntArg(const llvm::opt::InputArgList &InputArgs, int ID,
                        T &Value) {
  if (const opt::Arg *A = InputArgs.getLastArg(ID)) {
    StringRef V(A->getValue());
    if (!llvm::to_integer(V, Value, 0)) {
      reportCmdLineError(A->getSpelling() +
                         ": expected a non-negative integer, but got '" + V +
                         "'");
    }
  }
}

static object::BuildID parseBuildIDArg(const opt::Arg *A) {
  StringRef V(A->getValue());
  object::BuildID BID = parseBuildID(V);
  if (BID.empty())
    reportCmdLineError(A->getSpelling() + ": expected a build ID, but got '" +
                       V + "'");
  return BID;
}

void objdump::invalidArgValue(const opt::Arg *A) {
  reportCmdLineError("'" + StringRef(A->getValue()) +
                     "' is not a valid value for '" + A->getSpelling() + "'");
}

static std::vector<std::string>
commaSeparatedValues(const llvm::opt::InputArgList &InputArgs, int ID) {
  std::vector<std::string> Values;
  for (StringRef Value : InputArgs.getAllArgValues(ID)) {
    llvm::SmallVector<StringRef, 2> SplitValues;
    llvm::SplitString(Value, SplitValues, ",");
    for (StringRef SplitValue : SplitValues)
      Values.push_back(SplitValue.str());
  }
  return Values;
}

static void mcpuHelp() {
  Triple TheTriple;

  if (!TripleName.empty()) {
    TheTriple.setTriple(TripleName);
  } else {
    assert(!InputFilenames.empty());
    Expected<OwningBinary<Binary>> OBinary = createBinary(InputFilenames[0]);
    if (Error E = OBinary.takeError()) {
      reportError(InputFilenames[0], "triple was not specified and could not "
                                     "be inferred from the input file: " +
                                         toString(std::move(E)));
    }

    Binary *Bin = OBinary->getBinary();
    if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin)) {
      TheTriple = Obj->makeTriple();
    } else if (Archive *A = dyn_cast<Archive>(Bin)) {
      Error Err = Error::success();
      unsigned I = -1;
      for (auto &C : A->children(Err)) {
        ++I;
        Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
        if (!ChildOrErr) {
          if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
            reportError(std::move(E), getFileNameForError(C, I),
                        A->getFileName());
          continue;
        }
        if (ObjectFile *Obj = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
          TheTriple = Obj->makeTriple();
          break;
        }
      }
      if (Err)
        reportError(std::move(Err), A->getFileName());
    }
    if (TheTriple.empty())
      reportError(InputFilenames[0],
                  "target triple could not be derived from input file");
  }

  std::string ErrMessage;
  const Target *DummyTarget =
      TargetRegistry::lookupTarget(TheTriple, ErrMessage);
  if (!DummyTarget)
    reportCmdLineError(ErrMessage);
  // We need to access the Help() through the corresponding MCSubtargetInfo.
  DummyTarget->createMCSubtargetInfo(TheTriple, "help", "");
}

static void parseOtoolOptions(const llvm::opt::InputArgList &InputArgs) {
  MachOOpt = true;
  FullLeadingAddr = true;
  PrintImmHex = true;

  ArchName = InputArgs.getLastArgValue(OTOOL_arch).str();
  LinkOptHints = InputArgs.hasArg(OTOOL_C);
  if (InputArgs.hasArg(OTOOL_d))
    FilterSections.push_back("__DATA,__data");
  DylibId = InputArgs.hasArg(OTOOL_D);
  UniversalHeaders = InputArgs.hasArg(OTOOL_f);
  DataInCode = InputArgs.hasArg(OTOOL_G);
  FirstPrivateHeader = InputArgs.hasArg(OTOOL_h);
  IndirectSymbols = InputArgs.hasArg(OTOOL_I);
  ShowRawInsn = InputArgs.hasArg(OTOOL_j);
  PrivateHeaders = InputArgs.hasArg(OTOOL_l);
  DylibsUsed = InputArgs.hasArg(OTOOL_L);
  MCPU = InputArgs.getLastArgValue(OTOOL_mcpu_EQ).str();
  ObjcMetaData = InputArgs.hasArg(OTOOL_o);
  DisSymName = InputArgs.getLastArgValue(OTOOL_p).str();
  InfoPlist = InputArgs.hasArg(OTOOL_P);
  Relocations = InputArgs.hasArg(OTOOL_r);
  if (const Arg *A = InputArgs.getLastArg(OTOOL_s)) {
    auto Filter = (A->getValue(0) + StringRef(",") + A->getValue(1)).str();
    FilterSections.push_back(Filter);
  }
  if (InputArgs.hasArg(OTOOL_t))
    FilterSections.push_back("__TEXT,__text");
  Verbose = InputArgs.hasArg(OTOOL_v) || InputArgs.hasArg(OTOOL_V) ||
            InputArgs.hasArg(OTOOL_o);
  SymbolicOperands = InputArgs.hasArg(OTOOL_V);
  if (InputArgs.hasArg(OTOOL_x))
    FilterSections.push_back(",__text");
  LeadingAddr = LeadingHeaders = !InputArgs.hasArg(OTOOL_X);

  ChainedFixups = InputArgs.hasArg(OTOOL_chained_fixups);
  DyldInfo = InputArgs.hasArg(OTOOL_dyld_info);

  InputFilenames = InputArgs.getAllArgValues(OTOOL_INPUT);
  if (InputFilenames.empty())
    reportCmdLineError("no input file");

  for (const Arg *A : InputArgs) {
    const Option &O = A->getOption();
    if (O.getGroup().isValid() && O.getGroup().getID() == OTOOL_grp_obsolete) {
      reportCmdLineWarning(O.getPrefixedName() +
                           " is obsolete and not implemented");
    }
  }
}

static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
  parseIntArg(InputArgs, OBJDUMP_adjust_vma_EQ, AdjustVMA);
  AllHeaders = InputArgs.hasArg(OBJDUMP_all_headers);
  ArchName = InputArgs.getLastArgValue(OBJDUMP_arch_name_EQ).str();
  ArchiveHeaders = InputArgs.hasArg(OBJDUMP_archive_headers);
  Demangle = InputArgs.hasArg(OBJDUMP_demangle);
  Disassemble = InputArgs.hasArg(OBJDUMP_disassemble);
  DisassembleAll = InputArgs.hasArg(OBJDUMP_disassemble_all);
  SymbolDescription = InputArgs.hasArg(OBJDUMP_symbol_description);
  TracebackTable = InputArgs.hasArg(OBJDUMP_traceback_table);
  DisassembleSymbols =
      commaSeparatedValues(InputArgs, OBJDUMP_disassemble_symbols_EQ);
  DisassembleZeroes = InputArgs.hasArg(OBJDUMP_disassemble_zeroes);
  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_dwarf_EQ)) {
    DwarfDumpType = StringSwitch<DIDumpType>(A->getValue())
                        .Case("frames", DIDT_DebugFrame)
                        .Default(DIDT_Null);
    if (DwarfDumpType == DIDT_Null)
      invalidArgValue(A);
  }
  DynamicRelocations = InputArgs.hasArg(OBJDUMP_dynamic_reloc);
  FaultMapSection = InputArgs.hasArg(OBJDUMP_fault_map_section);
  Offloading = InputArgs.hasArg(OBJDUMP_offloading);
  FileHeaders = InputArgs.hasArg(OBJDUMP_file_headers);
  SectionContents = InputArgs.hasArg(OBJDUMP_full_contents);
  PrintLines = InputArgs.hasArg(OBJDUMP_line_numbers);
  InputFilenames = InputArgs.getAllArgValues(OBJDUMP_INPUT);
  MachOOpt = InputArgs.hasArg(OBJDUMP_macho);
  MCPU = InputArgs.getLastArgValue(OBJDUMP_mcpu_EQ).str();
  MAttrs = commaSeparatedValues(InputArgs, OBJDUMP_mattr_EQ);
  ShowRawInsn = !InputArgs.hasArg(OBJDUMP_no_show_raw_insn);
  LeadingAddr = !InputArgs.hasArg(OBJDUMP_no_leading_addr);
  RawClangAST = InputArgs.hasArg(OBJDUMP_raw_clang_ast);
  Relocations = InputArgs.hasArg(OBJDUMP_reloc);
  PrintImmHex =
      InputArgs.hasFlag(OBJDUMP_print_imm_hex, OBJDUMP_no_print_imm_hex, true);
  PrivateHeaders = InputArgs.hasArg(OBJDUMP_private_headers);
  FilterSections = InputArgs.getAllArgValues(OBJDUMP_section_EQ);
  SectionHeaders = InputArgs.hasArg(OBJDUMP_section_headers);
  ShowAllSymbols = InputArgs.hasArg(OBJDUMP_show_all_symbols);
  ShowLMA = InputArgs.hasArg(OBJDUMP_show_lma);
  PrintSource = InputArgs.hasArg(OBJDUMP_source);
  parseIntArg(InputArgs, OBJDUMP_start_address_EQ, StartAddress);
  HasStartAddressFlag = InputArgs.hasArg(OBJDUMP_start_address_EQ);
  parseIntArg(InputArgs, OBJDUMP_stop_address_EQ, StopAddress);
  HasStopAddressFlag = InputArgs.hasArg(OBJDUMP_stop_address_EQ);
  SymbolTable = InputArgs.hasArg(OBJDUMP_syms);
  SymbolizeOperands = InputArgs.hasArg(OBJDUMP_symbolize_operands);
  PrettyPGOAnalysisMap = InputArgs.hasArg(OBJDUMP_pretty_pgo_analysis_map);
  if (PrettyPGOAnalysisMap && !SymbolizeOperands)
    reportCmdLineWarning("--symbolize-operands must be enabled for "
                         "--pretty-pgo-analysis-map to have an effect");
  DynamicSymbolTable = InputArgs.hasArg(OBJDUMP_dynamic_syms);
  TripleName = InputArgs.getLastArgValue(OBJDUMP_triple_EQ).str();
  UnwindInfo = InputArgs.hasArg(OBJDUMP_unwind_info);
  Wide = InputArgs.hasArg(OBJDUMP_wide);
  Prefix = InputArgs.getLastArgValue(OBJDUMP_prefix).str();
  parseIntArg(InputArgs, OBJDUMP_prefix_strip, PrefixStrip);
  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_debug_vars_EQ)) {
    DbgVariables = StringSwitch<DebugFormat>(A->getValue())
                       .Case("ascii", DFASCII)
                       .Case("unicode", DFUnicode)
                       .Default(DFInvalid);
    if (DbgVariables == DFInvalid)
      invalidArgValue(A);
  }

  if (const opt::Arg *A =
          InputArgs.getLastArg(OBJDUMP_debug_inlined_funcs_EQ)) {
    DbgInlinedFunctions = StringSwitch<DebugFormat>(A->getValue())
                              .Case("ascii", DFASCII)
                              .Case("limits-only", DFLimitsOnly)
                              .Case("unicode", DFUnicode)
                              .Default(DFInvalid);
    if (DbgInlinedFunctions == DFInvalid)
      invalidArgValue(A);
  }

  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_disassembler_color_EQ)) {
    DisassemblyColor = StringSwitch<ColorOutput>(A->getValue())
                           .Case("on", ColorOutput::Enable)
                           .Case("off", ColorOutput::Disable)
                           .Case("terminal", ColorOutput::Auto)
                           .Default(ColorOutput::Invalid);
    if (DisassemblyColor == ColorOutput::Invalid)
      invalidArgValue(A);
  }

  parseIntArg(InputArgs, OBJDUMP_debug_indent_EQ, DbgIndent);

  parseMachOOptions(InputArgs);

  // Parse -M (--disassembler-options) and deprecated
  // --x86-asm-syntax={att,intel}.
  //
  // Note, for x86, the asm dialect (AssemblerDialect) is initialized when the
  // MCAsmInfo is constructed. MCInstPrinter::applyTargetSpecificCLOption is
  // called too late. For now we have to use the internal cl::opt option.
  const char *AsmSyntax = nullptr;
  for (const auto *A : InputArgs.filtered(OBJDUMP_disassembler_options_EQ,
                                          OBJDUMP_x86_asm_syntax_att,
                                          OBJDUMP_x86_asm_syntax_intel)) {
    switch (A->getOption().getID()) {
    case OBJDUMP_x86_asm_syntax_att:
      AsmSyntax = "--x86-asm-syntax=att";
      continue;
    case OBJDUMP_x86_asm_syntax_intel:
      AsmSyntax = "--x86-asm-syntax=intel";
      continue;
    }

    SmallVector<StringRef, 2> Values;
    llvm::SplitString(A->getValue(), Values, ",");
    for (StringRef V : Values) {
      if (V == "att")
        AsmSyntax = "--x86-asm-syntax=att";
      else if (V == "intel")
        AsmSyntax = "--x86-asm-syntax=intel";
      else
        DisassemblerOptions.push_back(V.str());
    }
  }
  SmallVector<const char *> Args = {"llvm-objdump"};
  for (const opt::Arg *A : InputArgs.filtered(OBJDUMP_mllvm))
    Args.push_back(A->getValue());
  if (AsmSyntax)
    Args.push_back(AsmSyntax);
  if (Args.size() > 1)
    llvm::cl::ParseCommandLineOptions(Args.size(), Args.data());

  // Look up any provided build IDs, then append them to the input filenames.
  for (const opt::Arg *A : InputArgs.filtered(OBJDUMP_build_id)) {
    object::BuildID BuildID = parseBuildIDArg(A);
    std::optional<std::string> Path = BIDFetcher->fetch(BuildID);
    if (!Path) {
      reportCmdLineError(A->getSpelling() + ": could not find build ID '" +
                         A->getValue() + "'");
    }
    InputFilenames.push_back(std::move(*Path));
  }

  // objdump defaults to a.out if no filenames specified.
  if (InputFilenames.empty())
    InputFilenames.push_back("a.out");
}

int llvm_objdump_main(int argc, char **argv, const llvm::ToolContext &) {
  using namespace llvm;

  ToolName = argv[0];
  std::unique_ptr<CommonOptTable> T;
  OptSpecifier Unknown, HelpFlag, HelpHiddenFlag, VersionFlag;

  StringRef Stem = sys::path::stem(ToolName);
  auto Is = [=](StringRef Tool) {
    // We need to recognize the following filenames:
    //
    // llvm-objdump -> objdump
    // llvm-otool-10.exe -> otool
    // powerpc64-unknown-freebsd13-objdump -> objdump
    auto I = Stem.rfind_insensitive(Tool);
    return I != StringRef::npos &&
           (I + Tool.size() == Stem.size() || !isAlnum(Stem[I + Tool.size()]));
  };
  if (Is("otool")) {
    T = std::make_unique<OtoolOptTable>();
    Unknown = OTOOL_UNKNOWN;
    HelpFlag = OTOOL_help;
    HelpHiddenFlag = OTOOL_help_hidden;
    VersionFlag = OTOOL_version;
  } else {
    T = std::make_unique<ObjdumpOptTable>();
    Unknown = OBJDUMP_UNKNOWN;
    HelpFlag = OBJDUMP_help;
    HelpHiddenFlag = OBJDUMP_help_hidden;
    VersionFlag = OBJDUMP_version;
  }

  BumpPtrAllocator A;
  StringSaver Saver(A);
  opt::InputArgList InputArgs =
      T->parseArgs(argc, argv, Unknown, Saver,
                   [&](StringRef Msg) { reportCmdLineError(Msg); });

  if (InputArgs.size() == 0 || InputArgs.hasArg(HelpFlag)) {
    T->printHelp(ToolName);
    return 0;
  }
  if (InputArgs.hasArg(HelpHiddenFlag)) {
    T->printHelp(ToolName, /*ShowHidden=*/true);
    return 0;
  }

  // Initialize targets and assembly printers/parsers.
  InitializeAllTargetInfos();
  InitializeAllTargetMCs();
  InitializeAllDisassemblers();

  if (InputArgs.hasArg(VersionFlag)) {
    cl::PrintVersionMessage();
    if (!Is("otool")) {
      outs() << '\n';
      TargetRegistry::printRegisteredTargetsForVersion(outs());
    }
    return 0;
  }

  // Initialize debuginfod.
  const bool ShouldUseDebuginfodByDefault =
      InputArgs.hasArg(OBJDUMP_build_id) || canUseDebuginfod();
  std::vector<std::string> DebugFileDirectories =
      InputArgs.getAllArgValues(OBJDUMP_debug_file_directory);
  if (InputArgs.hasFlag(OBJDUMP_debuginfod, OBJDUMP_no_debuginfod,
                        ShouldUseDebuginfodByDefault)) {
    HTTPClient::initialize();
    BIDFetcher =
        std::make_unique<DebuginfodFetcher>(std::move(DebugFileDirectories));
  } else {
    BIDFetcher =
        std::make_unique<BuildIDFetcher>(std::move(DebugFileDirectories));
  }

  if (Is("otool"))
    parseOtoolOptions(InputArgs);
  else
    parseObjdumpOptions(InputArgs);

  if (StartAddress >= StopAddress)
    reportCmdLineError("start address should be less than stop address");

  // Removes trailing separators from prefix.
  while (!Prefix.empty() && sys::path::is_separator(Prefix.back()))
    Prefix.pop_back();

  if (AllHeaders)
    ArchiveHeaders = FileHeaders = PrivateHeaders = Relocations =
        SectionHeaders = SymbolTable = true;

  if (DisassembleAll || PrintSource || PrintLines || TracebackTable ||
      !DisassembleSymbols.empty())
    Disassemble = true;

  const bool PrintCpuHelp = (MCPU == "help" || is_contained(MAttrs, "help"));

  const bool ShouldDump =
      ArchiveHeaders || Disassemble || DwarfDumpType != DIDT_Null ||
      DynamicRelocations || FileHeaders || PrivateHeaders || RawClangAST ||
      Relocations || SectionHeaders || SectionContents || SymbolTable ||
      DynamicSymbolTable || UnwindInfo || FaultMapSection || Offloading ||
      (MachOOpt &&
       (Bind || DataInCode || ChainedFixups || DyldInfo || DylibId ||
        DylibsUsed || ExportsTrie || FirstPrivateHeader ||
        FunctionStartsType != FunctionStartsMode::None || IndirectSymbols ||
        InfoPlist || LazyBind || LinkOptHints || ObjcMetaData || Rebase ||
        Rpaths || UniversalHeaders || WeakBind || !FilterSections.empty()));

  if (!ShouldDump && !PrintCpuHelp) {
    T->printHelp(ToolName);
    return 2;
  }

  if (PrintCpuHelp) {
    mcpuHelp();
    if (!ShouldDump)
      return EXIT_SUCCESS;
  }

  DisasmSymbolSet.insert_range(DisassembleSymbols);

  llvm::for_each(InputFilenames, dumpInput);

  warnOnNoMatchForSections();

  return EXIT_SUCCESS;
}
