brintos

brintos / llvm-project-archived public Read only

0
0
Text · 139.9 KiB · 38c3f31 Raw
3851 lines · cpp
1//===-- llvm-objdump.cpp - Object file dumping utility for llvm -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This program is a utility that works like binutils "objdump", that is, it10// dumps out a plethora of information about an object file depending on the11// flags.12//13// The flags and output of this program should be near identical to those of14// binutils objdump.15//16//===----------------------------------------------------------------------===//17 18#include "llvm-objdump.h"19#include "COFFDump.h"20#include "ELFDump.h"21#include "MachODump.h"22#include "ObjdumpOptID.h"23#include "OffloadDump.h"24#include "SourcePrinter.h"25#include "WasmDump.h"26#include "XCOFFDump.h"27#include "llvm/ADT/STLExtras.h"28#include "llvm/ADT/SetOperations.h"29#include "llvm/ADT/StringExtras.h"30#include "llvm/ADT/Twine.h"31#include "llvm/BinaryFormat/Wasm.h"32#include "llvm/DebugInfo/BTF/BTFParser.h"33#include "llvm/DebugInfo/DWARF/DWARFContext.h"34#include "llvm/DebugInfo/Symbolize/Symbolize.h"35#include "llvm/Debuginfod/BuildIDFetcher.h"36#include "llvm/Debuginfod/Debuginfod.h"37#include "llvm/Debuginfod/HTTPClient.h"38#include "llvm/Demangle/Demangle.h"39#include "llvm/MC/MCAsmInfo.h"40#include "llvm/MC/MCContext.h"41#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"42#include "llvm/MC/MCInst.h"43#include "llvm/MC/MCInstPrinter.h"44#include "llvm/MC/MCInstrAnalysis.h"45#include "llvm/MC/MCInstrInfo.h"46#include "llvm/MC/MCObjectFileInfo.h"47#include "llvm/MC/MCRegisterInfo.h"48#include "llvm/MC/MCTargetOptions.h"49#include "llvm/MC/TargetRegistry.h"50#include "llvm/Object/BuildID.h"51#include "llvm/Object/COFF.h"52#include "llvm/Object/COFFImportFile.h"53#include "llvm/Object/DXContainer.h"54#include "llvm/Object/ELFObjectFile.h"55#include "llvm/Object/ELFTypes.h"56#include "llvm/Object/FaultMapParser.h"57#include "llvm/Object/MachO.h"58#include "llvm/Object/MachOUniversal.h"59#include "llvm/Object/OffloadBinary.h"60#include "llvm/Object/Wasm.h"61#include "llvm/Option/Arg.h"62#include "llvm/Option/ArgList.h"63#include "llvm/Option/Option.h"64#include "llvm/Support/Casting.h"65#include "llvm/Support/Debug.h"66#include "llvm/Support/Errc.h"67#include "llvm/Support/FileSystem.h"68#include "llvm/Support/Format.h"69#include "llvm/Support/LLVMDriver.h"70#include "llvm/Support/MemoryBuffer.h"71#include "llvm/Support/SourceMgr.h"72#include "llvm/Support/StringSaver.h"73#include "llvm/Support/TargetSelect.h"74#include "llvm/Support/WithColor.h"75#include "llvm/Support/raw_ostream.h"76#include "llvm/TargetParser/Host.h"77#include "llvm/TargetParser/Triple.h"78#include <algorithm>79#include <cctype>80#include <cstring>81#include <optional>82#include <set>83#include <system_error>84#include <unordered_map>85#include <utility>86 87using namespace llvm;88using namespace llvm::object;89using namespace llvm::objdump;90using namespace llvm::opt;91 92namespace {93 94class CommonOptTable : public opt::GenericOptTable {95public:96  CommonOptTable(const StringTable &StrTable,97                 ArrayRef<StringTable::Offset> PrefixesTable,98                 ArrayRef<Info> OptionInfos, const char *Usage,99                 const char *Description)100      : opt::GenericOptTable(StrTable, PrefixesTable, OptionInfos),101        Usage(Usage), Description(Description) {102    setGroupedShortOptions(true);103  }104 105  void printHelp(StringRef Argv0, bool ShowHidden = false) const {106    Argv0 = sys::path::filename(Argv0);107    opt::GenericOptTable::printHelp(outs(), (Argv0 + Usage).str().c_str(),108                                    Description, ShowHidden, ShowHidden);109    // TODO Replace this with OptTable API once it adds extrahelp support.110    outs() << "\nPass @FILE as argument to read options from FILE.\n";111  }112 113private:114  const char *Usage;115  const char *Description;116};117 118// ObjdumpOptID is in ObjdumpOptID.h119namespace objdump_opt {120#define OPTTABLE_STR_TABLE_CODE121#include "ObjdumpOpts.inc"122#undef OPTTABLE_STR_TABLE_CODE123 124#define OPTTABLE_PREFIXES_TABLE_CODE125#include "ObjdumpOpts.inc"126#undef OPTTABLE_PREFIXES_TABLE_CODE127 128static constexpr opt::OptTable::Info ObjdumpInfoTable[] = {129#define OPTION(...)                                                            \130  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJDUMP_, __VA_ARGS__),131#include "ObjdumpOpts.inc"132#undef OPTION133};134} // namespace objdump_opt135 136class ObjdumpOptTable : public CommonOptTable {137public:138  ObjdumpOptTable()139      : CommonOptTable(140            objdump_opt::OptionStrTable, objdump_opt::OptionPrefixesTable,141            objdump_opt::ObjdumpInfoTable, " [options] <input object files>",142            "llvm object file dumper") {}143};144 145enum OtoolOptID {146  OTOOL_INVALID = 0, // This is not an option ID.147#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OTOOL_, __VA_ARGS__),148#include "OtoolOpts.inc"149#undef OPTION150};151 152namespace otool {153#define OPTTABLE_STR_TABLE_CODE154#include "OtoolOpts.inc"155#undef OPTTABLE_STR_TABLE_CODE156 157#define OPTTABLE_PREFIXES_TABLE_CODE158#include "OtoolOpts.inc"159#undef OPTTABLE_PREFIXES_TABLE_CODE160 161static constexpr opt::OptTable::Info OtoolInfoTable[] = {162#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OTOOL_, __VA_ARGS__),163#include "OtoolOpts.inc"164#undef OPTION165};166} // namespace otool167 168class OtoolOptTable : public CommonOptTable {169public:170  OtoolOptTable()171      : CommonOptTable(otool::OptionStrTable, otool::OptionPrefixesTable,172                       otool::OtoolInfoTable, " [option...] [file...]",173                       "Mach-O object file displaying tool") {}174};175 176struct BBAddrMapLabel {177  std::string BlockLabel;178  std::string PGOAnalysis;179};180 181// This class represents the BBAddrMap and PGOMap associated with a single182// function.183class BBAddrMapFunctionEntry {184public:185  BBAddrMapFunctionEntry(BBAddrMap AddrMap, PGOAnalysisMap PGOMap)186      : AddrMap(std::move(AddrMap)), PGOMap(std::move(PGOMap)) {}187 188  const BBAddrMap &getAddrMap() const { return AddrMap; }189 190  // Returns the PGO string associated with the entry of index `PGOBBEntryIndex`191  // in `PGOMap`. If PrettyPGOAnalysis is true, prints BFI as relative frequency192  // and BPI as percentage. Otherwise raw values are displayed.193  std::string constructPGOLabelString(size_t PGOBBEntryIndex,194                                      bool PrettyPGOAnalysis) const {195    if (!PGOMap.FeatEnable.hasPGOAnalysis())196      return "";197    std::string PGOString;198    raw_string_ostream PGOSS(PGOString);199 200    PGOSS << " (";201    if (PGOMap.FeatEnable.FuncEntryCount && PGOBBEntryIndex == 0) {202      PGOSS << "Entry count: " << Twine(PGOMap.FuncEntryCount);203      if (PGOMap.FeatEnable.hasPGOAnalysisBBData()) {204        PGOSS << ", ";205      }206    }207 208    if (PGOMap.FeatEnable.hasPGOAnalysisBBData()) {209 210      assert(PGOBBEntryIndex < PGOMap.BBEntries.size() &&211             "Expected PGOAnalysisMap and BBAddrMap to have the same entries");212      const PGOAnalysisMap::PGOBBEntry &PGOBBEntry =213          PGOMap.BBEntries[PGOBBEntryIndex];214 215      if (PGOMap.FeatEnable.BBFreq) {216        PGOSS << "Frequency: ";217        if (PrettyPGOAnalysis)218          printRelativeBlockFreq(PGOSS, PGOMap.BBEntries.front().BlockFreq,219                                 PGOBBEntry.BlockFreq);220        else221          PGOSS << Twine(PGOBBEntry.BlockFreq.getFrequency());222        if (PGOMap.FeatEnable.BrProb && PGOBBEntry.Successors.size() > 0) {223          PGOSS << ", ";224        }225      }226      if (PGOMap.FeatEnable.BrProb && PGOBBEntry.Successors.size() > 0) {227        PGOSS << "Successors: ";228        interleaveComma(229            PGOBBEntry.Successors, PGOSS,230            [&](const PGOAnalysisMap::PGOBBEntry::SuccessorEntry &SE) {231              PGOSS << "BB" << SE.ID << ":";232              if (PrettyPGOAnalysis)233                PGOSS << "[" << SE.Prob << "]";234              else235                PGOSS.write_hex(SE.Prob.getNumerator());236            });237      }238    }239    PGOSS << ")";240 241    return PGOString;242  }243 244private:245  const BBAddrMap AddrMap;246  const PGOAnalysisMap PGOMap;247};248 249// This class represents the BBAddrMap and PGOMap of potentially multiple250// functions in a section.251class BBAddrMapInfo {252public:253  void clear() {254    FunctionAddrToMap.clear();255    RangeBaseAddrToFunctionAddr.clear();256  }257 258  bool empty() const { return FunctionAddrToMap.empty(); }259 260  void AddFunctionEntry(BBAddrMap AddrMap, PGOAnalysisMap PGOMap) {261    uint64_t FunctionAddr = AddrMap.getFunctionAddress();262    for (size_t I = 1; I < AddrMap.BBRanges.size(); ++I)263      RangeBaseAddrToFunctionAddr.emplace(AddrMap.BBRanges[I].BaseAddress,264                                          FunctionAddr);265    [[maybe_unused]] auto R = FunctionAddrToMap.try_emplace(266        FunctionAddr, std::move(AddrMap), std::move(PGOMap));267    assert(R.second && "duplicate function address");268  }269 270  // Returns the BBAddrMap entry for the function associated with `BaseAddress`.271  // `BaseAddress` could be the function address or the address of a range272  // associated with that function. Returns `nullptr` if `BaseAddress` is not273  // mapped to any entry.274  const BBAddrMapFunctionEntry *getEntryForAddress(uint64_t BaseAddress) const {275    uint64_t FunctionAddr = BaseAddress;276    auto S = RangeBaseAddrToFunctionAddr.find(BaseAddress);277    if (S != RangeBaseAddrToFunctionAddr.end())278      FunctionAddr = S->second;279    auto R = FunctionAddrToMap.find(FunctionAddr);280    if (R == FunctionAddrToMap.end())281      return nullptr;282    return &R->second;283  }284 285private:286  std::unordered_map<uint64_t, BBAddrMapFunctionEntry> FunctionAddrToMap;287  std::unordered_map<uint64_t, uint64_t> RangeBaseAddrToFunctionAddr;288};289 290} // namespace291 292#define DEBUG_TYPE "objdump"293 294enum class ColorOutput {295  Auto,296  Enable,297  Disable,298  Invalid,299};300 301static uint64_t AdjustVMA;302static bool AllHeaders;303static std::string ArchName;304bool objdump::ArchiveHeaders;305bool objdump::Demangle;306bool objdump::Disassemble;307bool objdump::DisassembleAll;308std::vector<std::string> objdump::DisassemblerOptions;309bool objdump::SymbolDescription;310bool objdump::TracebackTable;311static std::vector<std::string> DisassembleSymbols;312static bool DisassembleZeroes;313static ColorOutput DisassemblyColor;314DIDumpType objdump::DwarfDumpType;315static bool DynamicRelocations;316static bool FaultMapSection;317static bool FileHeaders;318bool objdump::SectionContents;319static std::vector<std::string> InputFilenames;320bool objdump::PrintLines;321static bool MachOOpt;322std::string objdump::MCPU;323std::vector<std::string> objdump::MAttrs;324bool objdump::ShowRawInsn;325bool objdump::LeadingAddr;326static bool Offloading;327static bool RawClangAST;328bool objdump::Relocations;329bool objdump::PrintImmHex;330bool objdump::PrivateHeaders;331std::vector<std::string> objdump::FilterSections;332bool objdump::SectionHeaders;333static bool ShowAllSymbols;334static bool ShowLMA;335bool objdump::PrintSource;336 337static uint64_t StartAddress;338static bool HasStartAddressFlag;339static uint64_t StopAddress = UINT64_MAX;340static bool HasStopAddressFlag;341 342bool objdump::SymbolTable;343static bool SymbolizeOperands;344static bool PrettyPGOAnalysisMap;345static bool DynamicSymbolTable;346std::string objdump::TripleName;347bool objdump::UnwindInfo;348static bool Wide;349std::string objdump::Prefix;350uint32_t objdump::PrefixStrip;351 352DebugFormat objdump::DbgVariables = DFDisabled;353DebugFormat objdump::DbgInlinedFunctions = DFDisabled;354 355int objdump::DbgIndent = 52;356 357static StringSet<> DisasmSymbolSet;358StringSet<> objdump::FoundSectionSet;359static StringRef ToolName;360 361std::unique_ptr<BuildIDFetcher> BIDFetcher;362 363Dumper::Dumper(const object::ObjectFile &O) : O(O), OS(outs()) {364  WarningHandler = [this](const Twine &Msg) {365    if (Warnings.insert(Msg.str()).second)366      reportWarning(Msg, this->O.getFileName());367    return Error::success();368  };369}370 371void Dumper::reportUniqueWarning(Error Err) {372  reportUniqueWarning(toString(std::move(Err)));373}374 375void Dumper::reportUniqueWarning(const Twine &Msg) {376  cantFail(WarningHandler(Msg));377}378 379static Expected<std::unique_ptr<Dumper>> createDumper(const ObjectFile &Obj) {380  if (const auto *O = dyn_cast<COFFObjectFile>(&Obj))381    return createCOFFDumper(*O);382  if (const auto *O = dyn_cast<ELFObjectFileBase>(&Obj))383    return createELFDumper(*O);384  if (const auto *O = dyn_cast<MachOObjectFile>(&Obj))385    return createMachODumper(*O);386  if (const auto *O = dyn_cast<WasmObjectFile>(&Obj))387    return createWasmDumper(*O);388  if (const auto *O = dyn_cast<XCOFFObjectFile>(&Obj))389    return createXCOFFDumper(*O);390  if (const auto *O = dyn_cast<DXContainerObjectFile>(&Obj))391    return createDXContainerDumper(*O);392 393  return createStringError(errc::invalid_argument,394                           "unsupported object file format");395}396 397namespace {398struct FilterResult {399  // True if the section should not be skipped.400  bool Keep;401 402  // True if the index counter should be incremented, even if the section should403  // be skipped. For example, sections may be skipped if they are not included404  // in the --section flag, but we still want those to count toward the section405  // count.406  bool IncrementIndex;407};408} // namespace409 410static FilterResult checkSectionFilter(object::SectionRef S) {411  if (FilterSections.empty())412    return {/*Keep=*/true, /*IncrementIndex=*/true};413 414  Expected<StringRef> SecNameOrErr = S.getName();415  if (!SecNameOrErr) {416    consumeError(SecNameOrErr.takeError());417    return {/*Keep=*/false, /*IncrementIndex=*/false};418  }419  StringRef SecName = *SecNameOrErr;420 421  // StringSet does not allow empty key so avoid adding sections with422  // no name (such as the section with index 0) here.423  if (!SecName.empty())424    FoundSectionSet.insert(SecName);425 426  // Only show the section if it's in the FilterSections list, but always427  // increment so the indexing is stable.428  return {/*Keep=*/is_contained(FilterSections, SecName),429          /*IncrementIndex=*/true};430}431 432SectionFilter objdump::ToolSectionFilter(object::ObjectFile const &O,433                                         uint64_t *Idx) {434  // Start at UINT64_MAX so that the first index returned after an increment is435  // zero (after the unsigned wrap).436  if (Idx)437    *Idx = UINT64_MAX;438  return SectionFilter(439      [Idx](object::SectionRef S) {440        FilterResult Result = checkSectionFilter(S);441        if (Idx != nullptr && Result.IncrementIndex)442          *Idx += 1;443        return Result.Keep;444      },445      O);446}447 448std::string objdump::getFileNameForError(const object::Archive::Child &C,449                                         unsigned Index) {450  Expected<StringRef> NameOrErr = C.getName();451  if (NameOrErr)452    return std::string(NameOrErr.get());453  // If we have an error getting the name then we print the index of the archive454  // member. Since we are already in an error state, we just ignore this error.455  consumeError(NameOrErr.takeError());456  return "<file index: " + std::to_string(Index) + ">";457}458 459void objdump::reportWarning(const Twine &Message, StringRef File) {460  // Output order between errs() and outs() matters especially for archive461  // files where the output is per member object.462  outs().flush();463  WithColor::warning(errs(), ToolName)464      << "'" << File << "': " << Message << "\n";465}466 467[[noreturn]] void objdump::reportError(StringRef File, const Twine &Message) {468  outs().flush();469  WithColor::error(errs(), ToolName) << "'" << File << "': " << Message << "\n";470  exit(1);471}472 473[[noreturn]] void objdump::reportError(Error E, StringRef FileName,474                                       StringRef ArchiveName,475                                       StringRef ArchitectureName) {476  assert(E);477  outs().flush();478  WithColor::error(errs(), ToolName);479  if (ArchiveName != "")480    errs() << ArchiveName << "(" << FileName << ")";481  else482    errs() << "'" << FileName << "'";483  if (!ArchitectureName.empty())484    errs() << " (for architecture " << ArchitectureName << ")";485  errs() << ": ";486  logAllUnhandledErrors(std::move(E), errs());487  exit(1);488}489 490static void reportCmdLineWarning(const Twine &Message) {491  WithColor::warning(errs(), ToolName) << Message << "\n";492}493 494[[noreturn]] static void reportCmdLineError(const Twine &Message) {495  WithColor::error(errs(), ToolName) << Message << "\n";496  exit(1);497}498 499static void warnOnNoMatchForSections() {500  SetVector<StringRef> MissingSections;501  for (StringRef S : FilterSections) {502    if (FoundSectionSet.count(S))503      return;504    // User may specify a unnamed section. Don't warn for it.505    if (!S.empty())506      MissingSections.insert(S);507  }508 509  // Warn only if no section in FilterSections is matched.510  for (StringRef S : MissingSections)511    reportCmdLineWarning("section '" + S +512                         "' mentioned in a -j/--section option, but not "513                         "found in any input file");514}515 516static const Target *getTarget(const ObjectFile *Obj) {517  // Figure out the target triple.518  Triple TheTriple("unknown-unknown-unknown");519  if (TripleName.empty()) {520    TheTriple = Obj->makeTriple();521  } else {522    TheTriple.setTriple(Triple::normalize(TripleName));523    auto Arch = Obj->getArch();524    if (Arch == Triple::arm || Arch == Triple::armeb)525      Obj->setARMSubArch(TheTriple);526  }527 528  // Get the target specific parser.529  std::string Error;530  const Target *TheTarget =531      TargetRegistry::lookupTarget(ArchName, TheTriple, Error);532  if (!TheTarget)533    reportError(Obj->getFileName(), "can't find target: " + Error);534 535  // Update the triple name and return the found target.536  TripleName = TheTriple.getTriple();537  return TheTarget;538}539 540bool objdump::isRelocAddressLess(RelocationRef A, RelocationRef B) {541  return A.getOffset() < B.getOffset();542}543 544static Error getRelocationValueString(const RelocationRef &Rel,545                                      bool SymbolDescription,546                                      SmallVectorImpl<char> &Result) {547  const ObjectFile *Obj = Rel.getObject();548  if (auto *ELF = dyn_cast<ELFObjectFileBase>(Obj))549    return getELFRelocationValueString(ELF, Rel, Result);550  if (auto *COFF = dyn_cast<COFFObjectFile>(Obj))551    return getCOFFRelocationValueString(COFF, Rel, Result);552  if (auto *Wasm = dyn_cast<WasmObjectFile>(Obj))553    return getWasmRelocationValueString(Wasm, Rel, Result);554  if (auto *MachO = dyn_cast<MachOObjectFile>(Obj))555    return getMachORelocationValueString(MachO, Rel, Result);556  if (auto *XCOFF = dyn_cast<XCOFFObjectFile>(Obj))557    return getXCOFFRelocationValueString(*XCOFF, Rel, SymbolDescription,558                                         Result);559  llvm_unreachable("unknown object file format");560}561 562/// Indicates whether this relocation should hidden when listing563/// relocations, usually because it is the trailing part of a multipart564/// relocation that will be printed as part of the leading relocation.565static bool getHidden(RelocationRef RelRef) {566  auto *MachO = dyn_cast<MachOObjectFile>(RelRef.getObject());567  if (!MachO)568    return false;569 570  unsigned Arch = MachO->getArch();571  DataRefImpl Rel = RelRef.getRawDataRefImpl();572  uint64_t Type = MachO->getRelocationType(Rel);573 574  // On arches that use the generic relocations, GENERIC_RELOC_PAIR575  // is always hidden.576  if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc)577    return Type == MachO::GENERIC_RELOC_PAIR;578 579  if (Arch == Triple::x86_64) {580    // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows581    // an X86_64_RELOC_SUBTRACTOR.582    if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {583      DataRefImpl RelPrev = Rel;584      RelPrev.d.a--;585      uint64_t PrevType = MachO->getRelocationType(RelPrev);586      if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)587        return true;588    }589  }590 591  return false;592}593 594/// Get the column at which we want to start printing the instruction595/// disassembly, taking into account anything which appears to the left of it.596unsigned objdump::getInstStartColumn(const MCSubtargetInfo &STI) {597  return !ShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;598}599 600static void AlignToInstStartColumn(size_t Start, const MCSubtargetInfo &STI,601                                   raw_ostream &OS) {602  // The output of printInst starts with a tab. Print some spaces so that603  // the tab has 1 column and advances to the target tab stop.604  unsigned TabStop = getInstStartColumn(STI);605  unsigned Column = OS.tell() - Start;606  OS.indent(Column < TabStop - 1 ? TabStop - 1 - Column : 7 - Column % 8);607}608 609void objdump::printRawData(ArrayRef<uint8_t> Bytes, uint64_t Address,610                           formatted_raw_ostream &OS,611                           MCSubtargetInfo const &STI) {612  size_t Start = OS.tell();613  if (LeadingAddr)614    OS << format("%8" PRIx64 ":", Address);615  if (ShowRawInsn) {616    OS << ' ';617    dumpBytes(Bytes, OS);618  }619  AlignToInstStartColumn(Start, STI, OS);620}621 622namespace {623 624static bool isAArch64Elf(const ObjectFile &Obj) {625  const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj);626  return Elf && Elf->getEMachine() == ELF::EM_AARCH64;627}628 629static bool isArmElf(const ObjectFile &Obj) {630  const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj);631  return Elf && Elf->getEMachine() == ELF::EM_ARM;632}633 634static bool isCSKYElf(const ObjectFile &Obj) {635  const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj);636  return Elf && Elf->getEMachine() == ELF::EM_CSKY;637}638 639static bool isRISCVElf(const ObjectFile &Obj) {640  const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj);641  return Elf && Elf->getEMachine() == ELF::EM_RISCV;642}643 644static bool hasMappingSymbols(const ObjectFile &Obj) {645  return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj) ||646         isRISCVElf(Obj);647}648 649static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,650                            const RelocationRef &Rel, uint64_t Address,651                            bool Is64Bits) {652  StringRef Fmt = Is64Bits ? "%016" PRIx64 ":  " : "%08" PRIx64 ":  ";653  SmallString<16> Name;654  SmallString<32> Val;655  Rel.getTypeName(Name);656  if (Error E = getRelocationValueString(Rel, SymbolDescription, Val))657    reportError(std::move(E), FileName);658  OS << (Is64Bits || !LeadingAddr ? "\t\t" : "\t\t\t");659  if (LeadingAddr)660    OS << format(Fmt.data(), Address);661  OS << Name << "\t" << Val;662}663 664static void printBTFRelocation(formatted_raw_ostream &FOS, llvm::BTFParser &BTF,665                               object::SectionedAddress Address,666                               LiveElementPrinter &LEP) {667  const llvm::BTF::BPFFieldReloc *Reloc = BTF.findFieldReloc(Address);668  if (!Reloc)669    return;670 671  SmallString<64> Val;672  BTF.symbolize(Reloc, Val);673  FOS << "\t\t";674  if (LeadingAddr)675    FOS << format("%016" PRIx64 ":  ", Address.Address + AdjustVMA);676  FOS << "CO-RE " << Val;677  LEP.printAfterOtherLine(FOS, true);678}679 680class PrettyPrinter {681public:682  virtual ~PrettyPrinter() = default;683  virtual void684  printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,685            object::SectionedAddress Address, formatted_raw_ostream &OS,686            StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,687            StringRef ObjectFilename, std::vector<RelocationRef> *Rels,688            LiveElementPrinter &LEP) {689    if (SP && (PrintSource || PrintLines))690      SP->printSourceLine(OS, Address, ObjectFilename, LEP);691    LEP.printBoundaryLine(OS, Address, false);692    LEP.printBetweenInsts(OS, false);693 694    printRawData(Bytes, Address.Address, OS, STI);695 696    if (MI) {697      // See MCInstPrinter::printInst. On targets where a PC relative immediate698      // is relative to the next instruction and the length of a MCInst is699      // difficult to measure (x86), this is the address of the next700      // instruction.701      uint64_t Addr =702          Address.Address + (STI.getTargetTriple().isX86() ? Bytes.size() : 0);703      IP.printInst(MI, Addr, "", STI, OS);704    } else705      OS << "\t<unknown>";706  }707 708  virtual void emitPostInstructionInfo(formatted_raw_ostream &FOS,709                                       const MCAsmInfo &MAI,710                                       const MCSubtargetInfo &STI,711                                       StringRef Comments,712                                       LiveElementPrinter &LEP) {713    do {714      if (!Comments.empty()) {715        // Emit a line of comments.716        StringRef Comment;717        std::tie(Comment, Comments) = Comments.split('\n');718        // MAI.getCommentColumn() assumes that instructions are printed at the719        // position of 8, while getInstStartColumn() returns the actual720        // position.721        unsigned CommentColumn =722            MAI.getCommentColumn() - 8 + getInstStartColumn(STI);723        FOS.PadToColumn(CommentColumn);724        FOS << MAI.getCommentString() << ' ' << Comment;725      }726      LEP.printAfterInst(FOS);727      FOS << "\n";728    } while (!Comments.empty());729    FOS.flush();730  }731 732  // Hook invoked when starting to disassemble a symbol at the current position.733  // Default is no-op.734  virtual void onSymbolStart() {}735};736PrettyPrinter PrettyPrinterInst;737 738class HexagonPrettyPrinter : public PrettyPrinter {739public:740  void onSymbolStart() override { reset(); }741 742  void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address,743                 formatted_raw_ostream &OS) {744    if (LeadingAddr)745      OS << format("%8" PRIx64 ":", Address);746    if (ShowRawInsn) {747      OS << "\t";748      if (Bytes.size() >= 4) {749        dumpBytes(Bytes.slice(0, 4), OS);750        uint32_t opcode =751            (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0];752        OS << format("\t%08" PRIx32, opcode);753      } else {754        dumpBytes(Bytes, OS);755      }756    }757  }758 759  std::string getInstructionSeparator() const {760    SmallString<40> Separator;761    raw_svector_ostream OS(Separator);762    if (ShouldClosePacket) {763      OS << " }";764      if (IsLoop0 || IsLoop1)765        OS << "  ";766      if (IsLoop0)767        OS << (IsLoop1 ? ":endloop01" : ":endloop0");768      else if (IsLoop1)769        OS << ":endloop1";770    }771    OS << '\n';772    return OS.str().str();773  }774 775  void emitPostInstructionInfo(formatted_raw_ostream &FOS, const MCAsmInfo &MAI,776                               const MCSubtargetInfo &STI, StringRef Comments,777                               LiveElementPrinter &LEP) override {778    // Hexagon does not write anything to the comment stream, so we can just779    // print the separator.780    LEP.printAfterInst(FOS);781    FOS << getInstructionSeparator();782    FOS.flush();783    if (ShouldClosePacket)784      reset();785  }786 787  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,788                 object::SectionedAddress Address, formatted_raw_ostream &OS,789                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,790                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,791                 LiveElementPrinter &LEP) override {792    if (SP && (PrintSource || PrintLines))793      SP->printSourceLine(OS, Address, ObjectFilename, LEP, "");794    if (!MI) {795      printLead(Bytes, Address.Address, OS);796      OS << " <unknown>";797      reset();798      return;799    }800 801    StringRef Preamble = IsStartOfBundle ? " { " : "   ";802 803    if (SP && (PrintSource || PrintLines))804      SP->printSourceLine(OS, Address, ObjectFilename, LEP, "");805    printLead(Bytes, Address.Address, OS);806    OS << Preamble;807    std::string Buf;808    {809      raw_string_ostream TempStream(Buf);810      IP.printInst(MI, Address.Address, "", STI, TempStream);811    }812    StringRef Contents(Buf);813 814    auto Duplex = Contents.split('\v');815    bool HasDuplex = !Duplex.second.empty();816    if (HasDuplex) {817      OS << Duplex.first;818      OS << "; ";819      OS << Duplex.second;820    } else {821      OS << Duplex.first;822    }823 824    uint32_t Instruction = support::endian::read32le(Bytes.data());825 826    uint32_t ParseMask = 0x0000c000;827    uint32_t PacketEndMask = 0x0000c000;828    uint32_t LoopEndMask = 0x00008000;829    uint32_t ParseBits = Instruction & ParseMask;830 831    if (ParseBits == LoopEndMask) {832      if (IsStartOfBundle)833        IsLoop0 = true;834      else835        IsLoop1 = true;836    }837 838    IsStartOfBundle = false;839 840    if (ParseBits == PacketEndMask || HasDuplex)841      ShouldClosePacket = true;842  }843 844private:845  bool IsStartOfBundle = true;846  bool IsLoop0 = false;847  bool IsLoop1 = false;848  bool ShouldClosePacket = false;849 850  void reset() {851    IsStartOfBundle = true;852    IsLoop0 = false;853    IsLoop1 = false;854    ShouldClosePacket = false;855  }856};857HexagonPrettyPrinter HexagonPrettyPrinterInst;858 859class AMDGCNPrettyPrinter : public PrettyPrinter {860public:861  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,862                 object::SectionedAddress Address, formatted_raw_ostream &OS,863                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,864                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,865                 LiveElementPrinter &LEP) override {866    if (SP && (PrintSource || PrintLines))867      SP->printSourceLine(OS, Address, ObjectFilename, LEP);868 869    if (MI) {870      SmallString<40> InstStr;871      raw_svector_ostream IS(InstStr);872 873      IP.printInst(MI, Address.Address, "", STI, IS);874 875      OS << left_justify(IS.str(), 60);876    } else {877      // an unrecognized encoding - this is probably data so represent it878      // using the .long directive, or .byte directive if fewer than 4 bytes879      // remaining880      if (Bytes.size() >= 4) {881        OS << format(882            "\t.long 0x%08" PRIx32 " ",883            support::endian::read32<llvm::endianness::little>(Bytes.data()));884        OS.indent(42);885      } else {886        OS << format("\t.byte 0x%02" PRIx8, Bytes[0]);887        for (unsigned int i = 1; i < Bytes.size(); i++)888          OS << format(", 0x%02" PRIx8, Bytes[i]);889        OS.indent(55 - (6 * Bytes.size()));890      }891    }892 893    OS << format("// %012" PRIX64 ":", Address.Address);894    if (Bytes.size() >= 4) {895      // D should be casted to uint32_t here as it is passed by format to896      // snprintf as vararg.897      for (uint32_t D :898           ArrayRef(reinterpret_cast<const support::little32_t *>(Bytes.data()),899                    Bytes.size() / 4))900        OS << format(" %08" PRIX32, D);901    } else {902      for (unsigned char B : Bytes)903        OS << format(" %02" PRIX8, B);904    }905 906    if (!Annot.empty())907      OS << " // " << Annot;908  }909};910AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst;911 912class BPFPrettyPrinter : public PrettyPrinter {913public:914  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,915                 object::SectionedAddress Address, formatted_raw_ostream &OS,916                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,917                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,918                 LiveElementPrinter &LEP) override {919    if (SP && (PrintSource || PrintLines))920      SP->printSourceLine(OS, Address, ObjectFilename, LEP);921    if (LeadingAddr)922      OS << format("%8" PRId64 ":", Address.Address / 8);923    if (ShowRawInsn) {924      OS << "\t";925      dumpBytes(Bytes, OS);926    }927    if (MI)928      IP.printInst(MI, Address.Address, "", STI, OS);929    else930      OS << "\t<unknown>";931  }932};933BPFPrettyPrinter BPFPrettyPrinterInst;934 935class ARMPrettyPrinter : public PrettyPrinter {936public:937  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,938                 object::SectionedAddress Address, formatted_raw_ostream &OS,939                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,940                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,941                 LiveElementPrinter &LEP) override {942    if (SP && (PrintSource || PrintLines))943      SP->printSourceLine(OS, Address, ObjectFilename, LEP);944    LEP.printBoundaryLine(OS, Address, false);945    LEP.printBetweenInsts(OS, false);946 947    size_t Start = OS.tell();948    if (LeadingAddr)949      OS << format("%8" PRIx64 ":", Address.Address);950    if (ShowRawInsn) {951      size_t Pos = 0, End = Bytes.size();952      if (STI.checkFeatures("+thumb-mode")) {953        for (; Pos + 2 <= End; Pos += 2)954          OS << ' '955             << format_hex_no_prefix(956                    llvm::support::endian::read<uint16_t>(957                        Bytes.data() + Pos, InstructionEndianness),958                    4);959      } else {960        for (; Pos + 4 <= End; Pos += 4)961          OS << ' '962             << format_hex_no_prefix(963                    llvm::support::endian::read<uint32_t>(964                        Bytes.data() + Pos, InstructionEndianness),965                    8);966      }967      if (Pos < End) {968        OS << ' ';969        dumpBytes(Bytes.slice(Pos), OS);970      }971    }972 973    AlignToInstStartColumn(Start, STI, OS);974 975    if (MI) {976      IP.printInst(MI, Address.Address, "", STI, OS);977    } else978      OS << "\t<unknown>";979  }980 981  void setInstructionEndianness(llvm::endianness Endianness) {982    InstructionEndianness = Endianness;983  }984 985private:986  llvm::endianness InstructionEndianness = llvm::endianness::little;987};988ARMPrettyPrinter ARMPrettyPrinterInst;989 990class AArch64PrettyPrinter : public PrettyPrinter {991public:992  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,993                 object::SectionedAddress Address, formatted_raw_ostream &OS,994                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,995                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,996                 LiveElementPrinter &LEP) override {997    if (SP && (PrintSource || PrintLines))998      SP->printSourceLine(OS, Address, ObjectFilename, LEP);999    LEP.printBoundaryLine(OS, Address, false);1000    LEP.printBetweenInsts(OS, false);1001 1002    size_t Start = OS.tell();1003    if (LeadingAddr)1004      OS << format("%8" PRIx64 ":", Address.Address);1005    if (ShowRawInsn) {1006      size_t Pos = 0, End = Bytes.size();1007      for (; Pos + 4 <= End; Pos += 4)1008        OS << ' '1009           << format_hex_no_prefix(1010                  llvm::support::endian::read<uint32_t>(1011                      Bytes.data() + Pos, llvm::endianness::little),1012                  8);1013      if (Pos < End) {1014        OS << ' ';1015        dumpBytes(Bytes.slice(Pos), OS);1016      }1017    }1018 1019    AlignToInstStartColumn(Start, STI, OS);1020 1021    if (MI) {1022      IP.printInst(MI, Address.Address, "", STI, OS);1023    } else1024      OS << "\t<unknown>";1025  }1026};1027AArch64PrettyPrinter AArch64PrettyPrinterInst;1028 1029class RISCVPrettyPrinter : public PrettyPrinter {1030public:1031  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,1032                 object::SectionedAddress Address, formatted_raw_ostream &OS,1033                 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,1034                 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,1035                 LiveElementPrinter &LEP) override {1036    if (SP && (PrintSource || PrintLines))1037      SP->printSourceLine(OS, Address, ObjectFilename, LEP);1038    LEP.printBoundaryLine(OS, Address, false);1039    LEP.printBetweenInsts(OS, false);1040 1041    size_t Start = OS.tell();1042    if (LeadingAddr)1043      OS << format("%8" PRIx64 ":", Address.Address);1044    if (ShowRawInsn) {1045      size_t Pos = 0, End = Bytes.size();1046      if (End % 4 == 0) {1047        // 32-bit and 64-bit instructions.1048        for (; Pos + 4 <= End; Pos += 4)1049          OS << ' '1050             << format_hex_no_prefix(1051                    llvm::support::endian::read<uint32_t>(1052                        Bytes.data() + Pos, llvm::endianness::little),1053                    8);1054      } else if (End % 2 == 0) {1055        // 16-bit and 48-bits instructions.1056        for (; Pos + 2 <= End; Pos += 2)1057          OS << ' '1058             << format_hex_no_prefix(1059                    llvm::support::endian::read<uint16_t>(1060                        Bytes.data() + Pos, llvm::endianness::little),1061                    4);1062      }1063      if (Pos < End) {1064        OS << ' ';1065        dumpBytes(Bytes.slice(Pos), OS);1066      }1067    }1068 1069    AlignToInstStartColumn(Start, STI, OS);1070 1071    if (MI) {1072      IP.printInst(MI, Address.Address, "", STI, OS);1073    } else1074      OS << "\t<unknown>";1075  }1076};1077RISCVPrettyPrinter RISCVPrettyPrinterInst;1078 1079PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {1080  switch (Triple.getArch()) {1081  default:1082    return PrettyPrinterInst;1083  case Triple::hexagon:1084    return HexagonPrettyPrinterInst;1085  case Triple::amdgcn:1086    return AMDGCNPrettyPrinterInst;1087  case Triple::bpfel:1088  case Triple::bpfeb:1089    return BPFPrettyPrinterInst;1090  case Triple::arm:1091  case Triple::armeb:1092  case Triple::thumb:1093  case Triple::thumbeb:1094    return ARMPrettyPrinterInst;1095  case Triple::aarch64:1096  case Triple::aarch64_be:1097  case Triple::aarch64_32:1098    return AArch64PrettyPrinterInst;1099  case Triple::riscv32:1100  case Triple::riscv64:1101    return RISCVPrettyPrinterInst;1102  }1103}1104 1105class DisassemblerTarget {1106public:1107  const Target *TheTarget;1108  const Triple TheTriple;1109  std::unique_ptr<const MCSubtargetInfo> SubtargetInfo;1110  std::shared_ptr<MCContext> Context;1111  std::unique_ptr<MCDisassembler> DisAsm;1112  std::shared_ptr<MCInstrAnalysis> InstrAnalysis;1113  std::shared_ptr<MCInstPrinter> InstPrinter;1114  PrettyPrinter *Printer;1115 1116  DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,1117                     StringRef TripleName, StringRef MCPU,1118                     SubtargetFeatures &Features);1119  DisassemblerTarget(DisassemblerTarget &Other, SubtargetFeatures &Features);1120 1121private:1122  MCTargetOptions Options;1123  std::shared_ptr<const MCRegisterInfo> RegisterInfo;1124  std::shared_ptr<const MCAsmInfo> AsmInfo;1125  std::shared_ptr<const MCInstrInfo> InstrInfo;1126  std::shared_ptr<MCObjectFileInfo> ObjectFileInfo;1127};1128 1129DisassemblerTarget::DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,1130                                       StringRef TripleName, StringRef MCPU,1131                                       SubtargetFeatures &Features)1132    : TheTarget(TheTarget), TheTriple(TripleName),1133      Printer(&selectPrettyPrinter(TheTriple)),1134      RegisterInfo(TheTarget->createMCRegInfo(TheTriple)) {1135  if (!RegisterInfo)1136    reportError(Obj.getFileName(), "no register info for target " + TripleName);1137 1138  // Set up disassembler.1139  AsmInfo.reset(TheTarget->createMCAsmInfo(*RegisterInfo, TheTriple, Options));1140  if (!AsmInfo)1141    reportError(Obj.getFileName(), "no assembly info for target " + TripleName);1142 1143  SubtargetInfo.reset(1144      TheTarget->createMCSubtargetInfo(TheTriple, MCPU, Features.getString()));1145  if (!SubtargetInfo)1146    reportError(Obj.getFileName(),1147                "no subtarget info for target " + TripleName);1148  InstrInfo.reset(TheTarget->createMCInstrInfo());1149  if (!InstrInfo)1150    reportError(Obj.getFileName(),1151                "no instruction info for target " + TripleName);1152  Context = std::make_shared<MCContext>(1153      TheTriple, AsmInfo.get(), RegisterInfo.get(), SubtargetInfo.get());1154 1155  // FIXME: for now initialize MCObjectFileInfo with default values1156  ObjectFileInfo.reset(1157      TheTarget->createMCObjectFileInfo(*Context, /*PIC=*/false));1158  Context->setObjectFileInfo(ObjectFileInfo.get());1159 1160  DisAsm.reset(TheTarget->createMCDisassembler(*SubtargetInfo, *Context));1161  if (!DisAsm)1162    reportError(Obj.getFileName(), "no disassembler for target " + TripleName);1163 1164  if (auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))1165    DisAsm->setABIVersion(ELFObj->getEIdentABIVersion());1166 1167  InstrAnalysis.reset(TheTarget->createMCInstrAnalysis(InstrInfo.get()));1168 1169  int AsmPrinterVariant = AsmInfo->getAssemblerDialect();1170  InstPrinter.reset(TheTarget->createMCInstPrinter(1171      TheTriple, AsmPrinterVariant, *AsmInfo, *InstrInfo, *RegisterInfo));1172  if (!InstPrinter)1173    reportError(Obj.getFileName(),1174                "no instruction printer for target " + TripleName);1175  InstPrinter->setPrintImmHex(PrintImmHex);1176  InstPrinter->setPrintBranchImmAsAddress(true);1177  InstPrinter->setSymbolizeOperands(SymbolizeOperands);1178  InstPrinter->setMCInstrAnalysis(InstrAnalysis.get());1179 1180  switch (DisassemblyColor) {1181  case ColorOutput::Enable:1182    InstPrinter->setUseColor(true);1183    break;1184  case ColorOutput::Auto:1185    InstPrinter->setUseColor(outs().has_colors());1186    break;1187  case ColorOutput::Disable:1188  case ColorOutput::Invalid:1189    InstPrinter->setUseColor(false);1190    break;1191  };1192}1193 1194DisassemblerTarget::DisassemblerTarget(DisassemblerTarget &Other,1195                                       SubtargetFeatures &Features)1196    : TheTarget(Other.TheTarget), TheTriple(Other.TheTriple),1197      SubtargetInfo(TheTarget->createMCSubtargetInfo(TheTriple, MCPU,1198                                                     Features.getString())),1199      Context(Other.Context),1200      DisAsm(TheTarget->createMCDisassembler(*SubtargetInfo, *Context)),1201      InstrAnalysis(Other.InstrAnalysis), InstPrinter(Other.InstPrinter),1202      Printer(Other.Printer), RegisterInfo(Other.RegisterInfo),1203      AsmInfo(Other.AsmInfo), InstrInfo(Other.InstrInfo),1204      ObjectFileInfo(Other.ObjectFileInfo) {}1205} // namespace1206 1207static uint8_t getElfSymbolType(const ObjectFile &Obj, const SymbolRef &Sym) {1208  assert(Obj.isELF());1209  if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(&Obj))1210    return unwrapOrError(Elf32LEObj->getSymbol(Sym.getRawDataRefImpl()),1211                         Obj.getFileName())1212        ->getType();1213  if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(&Obj))1214    return unwrapOrError(Elf64LEObj->getSymbol(Sym.getRawDataRefImpl()),1215                         Obj.getFileName())1216        ->getType();1217  if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(&Obj))1218    return unwrapOrError(Elf32BEObj->getSymbol(Sym.getRawDataRefImpl()),1219                         Obj.getFileName())1220        ->getType();1221  if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(&Obj))1222    return unwrapOrError(Elf64BEObj->getSymbol(Sym.getRawDataRefImpl()),1223                         Obj.getFileName())1224        ->getType();1225  llvm_unreachable("Unsupported binary format");1226}1227 1228template <class ELFT>1229static void1230addDynamicElfSymbols(const ELFObjectFile<ELFT> &Obj,1231                     std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {1232  for (auto Symbol : Obj.getDynamicSymbolIterators()) {1233    uint8_t SymbolType = Symbol.getELFType();1234    if (SymbolType == ELF::STT_SECTION)1235      continue;1236 1237    uint64_t Address = unwrapOrError(Symbol.getAddress(), Obj.getFileName());1238    // ELFSymbolRef::getAddress() returns size instead of value for common1239    // symbols which is not desirable for disassembly output. Overriding.1240    if (SymbolType == ELF::STT_COMMON)1241      Address = unwrapOrError(Obj.getSymbol(Symbol.getRawDataRefImpl()),1242                              Obj.getFileName())1243                    ->st_value;1244 1245    StringRef Name = unwrapOrError(Symbol.getName(), Obj.getFileName());1246    if (Name.empty())1247      continue;1248 1249    section_iterator SecI =1250        unwrapOrError(Symbol.getSection(), Obj.getFileName());1251    if (SecI == Obj.section_end())1252      continue;1253 1254    AllSymbols[*SecI].emplace_back(Address, Name, SymbolType);1255  }1256}1257 1258static void1259addDynamicElfSymbols(const ELFObjectFileBase &Obj,1260                     std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {1261  if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(&Obj))1262    addDynamicElfSymbols(*Elf32LEObj, AllSymbols);1263  else if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(&Obj))1264    addDynamicElfSymbols(*Elf64LEObj, AllSymbols);1265  else if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(&Obj))1266    addDynamicElfSymbols(*Elf32BEObj, AllSymbols);1267  else if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(&Obj))1268    addDynamicElfSymbols(*Elf64BEObj, AllSymbols);1269  else1270    llvm_unreachable("Unsupported binary format");1271}1272 1273static std::optional<SectionRef> getWasmCodeSection(const WasmObjectFile &Obj) {1274  for (auto SecI : Obj.sections()) {1275    const WasmSection &Section = Obj.getWasmSection(SecI);1276    if (Section.Type == wasm::WASM_SEC_CODE)1277      return SecI;1278  }1279  return std::nullopt;1280}1281 1282static void1283addMissingWasmCodeSymbols(const WasmObjectFile &Obj,1284                          std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {1285  std::optional<SectionRef> Section = getWasmCodeSection(Obj);1286  if (!Section)1287    return;1288  SectionSymbolsTy &Symbols = AllSymbols[*Section];1289 1290  std::set<uint64_t> SymbolAddresses;1291  for (const auto &Sym : Symbols)1292    SymbolAddresses.insert(Sym.Addr);1293 1294  for (const wasm::WasmFunction &Function : Obj.functions()) {1295    // This adjustment mirrors the one in WasmObjectFile::getSymbolAddress.1296    uint32_t Adjustment = Obj.isRelocatableObject() || Obj.isSharedObject()1297                              ? 01298                              : Section->getAddress();1299    uint64_t Address = Function.CodeSectionOffset + Adjustment;1300    // Only add fallback symbols for functions not already present in the symbol1301    // table.1302    if (SymbolAddresses.count(Address))1303      continue;1304    // This function has no symbol, so it should have no SymbolName.1305    assert(Function.SymbolName.empty());1306    // We use DebugName for the name, though it may be empty if there is no1307    // "name" custom section, or that section is missing a name for this1308    // function.1309    StringRef Name = Function.DebugName;1310    Symbols.emplace_back(Address, Name, ELF::STT_NOTYPE);1311  }1312}1313 1314static DenseMap<StringRef, SectionRef> getSectionNames(const ObjectFile &Obj) {1315  DenseMap<StringRef, SectionRef> Sections;1316  for (SectionRef Section : Obj.sections()) {1317    Expected<StringRef> SecNameOrErr = Section.getName();1318    if (!SecNameOrErr) {1319      consumeError(SecNameOrErr.takeError());1320      continue;1321    }1322    Sections[*SecNameOrErr] = Section;1323  }1324  return Sections;1325}1326 1327static void addPltEntries(const MCSubtargetInfo &STI, const ObjectFile &Obj,1328                          DenseMap<StringRef, SectionRef> &SectionNames,1329                          std::map<SectionRef, SectionSymbolsTy> &AllSymbols,1330                          StringSaver &Saver) {1331  auto *ElfObj = dyn_cast<ELFObjectFileBase>(&Obj);1332  if (!ElfObj)1333    return;1334  for (auto Plt : ElfObj->getPltEntries(STI)) {1335    if (Plt.Symbol) {1336      SymbolRef Symbol(*Plt.Symbol, ElfObj);1337      uint8_t SymbolType = getElfSymbolType(Obj, Symbol);1338      if (Expected<StringRef> NameOrErr = Symbol.getName()) {1339        if (!NameOrErr->empty())1340          AllSymbols[SectionNames[Plt.Section]].emplace_back(1341              Plt.Address, Saver.save((*NameOrErr + "@plt").str()), SymbolType);1342        continue;1343      } else {1344        // The warning has been reported in disassembleObject().1345        consumeError(NameOrErr.takeError());1346      }1347    }1348    reportWarning("PLT entry at 0x" + Twine::utohexstr(Plt.Address) +1349                      " references an invalid symbol",1350                  Obj.getFileName());1351  }1352}1353 1354// Normally the disassembly output will skip blocks of zeroes. This function1355// returns the number of zero bytes that can be skipped when dumping the1356// disassembly of the instructions in Buf.1357static size_t countSkippableZeroBytes(ArrayRef<uint8_t> Buf) {1358  // Find the number of leading zeroes.1359  size_t N = 0;1360  while (N < Buf.size() && !Buf[N])1361    ++N;1362 1363  // We may want to skip blocks of zero bytes, but unless we see1364  // at least 8 of them in a row.1365  if (N < 8)1366    return 0;1367 1368  // We skip zeroes in multiples of 4 because do not want to truncate an1369  // instruction if it starts with a zero byte.1370  return N & ~0x3;1371}1372 1373// Returns a map from sections to their relocations.1374static std::map<SectionRef, std::vector<RelocationRef>>1375getRelocsMap(object::ObjectFile const &Obj) {1376  std::map<SectionRef, std::vector<RelocationRef>> Ret;1377  uint64_t I = (uint64_t)-1;1378  for (SectionRef Sec : Obj.sections()) {1379    ++I;1380    Expected<section_iterator> RelocatedOrErr = Sec.getRelocatedSection();1381    if (!RelocatedOrErr)1382      reportError(Obj.getFileName(),1383                  "section (" + Twine(I) +1384                      "): failed to get a relocated section: " +1385                      toString(RelocatedOrErr.takeError()));1386 1387    section_iterator Relocated = *RelocatedOrErr;1388    if (Relocated == Obj.section_end() || !checkSectionFilter(*Relocated).Keep)1389      continue;1390    std::vector<RelocationRef> &V = Ret[*Relocated];1391    append_range(V, Sec.relocations());1392    // Sort relocations by address.1393    llvm::stable_sort(V, isRelocAddressLess);1394  }1395  return Ret;1396}1397 1398// Used for --adjust-vma to check if address should be adjusted by the1399// specified value for a given section.1400// For ELF we do not adjust non-allocatable sections like debug ones,1401// because they are not loadable.1402// TODO: implement for other file formats.1403static bool shouldAdjustVA(const SectionRef &Section) {1404  const ObjectFile *Obj = Section.getObject();1405  if (Obj->isELF())1406    return ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC;1407  return false;1408}1409 1410typedef std::pair<uint64_t, char> MappingSymbolPair;1411static char getMappingSymbolKind(ArrayRef<MappingSymbolPair> MappingSymbols,1412                                 uint64_t Address) {1413  auto It =1414      partition_point(MappingSymbols, [Address](const MappingSymbolPair &Val) {1415        return Val.first <= Address;1416      });1417  // Return zero for any address before the first mapping symbol; this means1418  // we should use the default disassembly mode, depending on the target.1419  if (It == MappingSymbols.begin())1420    return '\x00';1421  return (It - 1)->second;1422}1423 1424static uint64_t dumpARMELFData(uint64_t SectionAddr, uint64_t Index,1425                               uint64_t End, const ObjectFile &Obj,1426                               ArrayRef<uint8_t> Bytes,1427                               ArrayRef<MappingSymbolPair> MappingSymbols,1428                               const MCSubtargetInfo &STI, raw_ostream &OS) {1429  llvm::endianness Endian =1430      Obj.isLittleEndian() ? llvm::endianness::little : llvm::endianness::big;1431  size_t Start = OS.tell();1432  OS << format("%8" PRIx64 ": ", SectionAddr + Index);1433  if (Index + 4 <= End) {1434    dumpBytes(Bytes.slice(Index, 4), OS);1435    AlignToInstStartColumn(Start, STI, OS);1436    OS << "\t.word\t"1437       << format_hex(support::endian::read32(Bytes.data() + Index, Endian), 10);1438    return 4;1439  }1440  if (Index + 2 <= End) {1441    dumpBytes(Bytes.slice(Index, 2), OS);1442    AlignToInstStartColumn(Start, STI, OS);1443    OS << "\t.short\t"1444       << format_hex(support::endian::read16(Bytes.data() + Index, Endian), 6);1445    return 2;1446  }1447  dumpBytes(Bytes.slice(Index, 1), OS);1448  AlignToInstStartColumn(Start, STI, OS);1449  OS << "\t.byte\t" << format_hex(Bytes[Index], 4);1450  return 1;1451}1452 1453static void dumpELFData(uint64_t SectionAddr, uint64_t Index, uint64_t End,1454                        ArrayRef<uint8_t> Bytes, raw_ostream &OS) {1455  // print out data up to 8 bytes at a time in hex and ascii1456  uint8_t AsciiData[9] = {'\0'};1457  uint8_t Byte;1458  int NumBytes = 0;1459 1460  for (; Index < End; ++Index) {1461    if (NumBytes == 0)1462      OS << format("%8" PRIx64 ":", SectionAddr + Index);1463    Byte = Bytes.slice(Index)[0];1464    OS << format(" %02x", Byte);1465    AsciiData[NumBytes] = isPrint(Byte) ? Byte : '.';1466 1467    uint8_t IndentOffset = 0;1468    NumBytes++;1469    if (Index == End - 1 || NumBytes > 8) {1470      // Indent the space for less than 8 bytes data.1471      // 2 spaces for byte and one for space between bytes1472      IndentOffset = 3 * (8 - NumBytes);1473      for (int Excess = NumBytes; Excess < 8; Excess++)1474        AsciiData[Excess] = '\0';1475      NumBytes = 8;1476    }1477    if (NumBytes == 8) {1478      AsciiData[8] = '\0';1479      OS << std::string(IndentOffset, ' ') << "         ";1480      OS << reinterpret_cast<char *>(AsciiData);1481      OS << '\n';1482      NumBytes = 0;1483    }1484  }1485}1486 1487SymbolInfoTy objdump::createSymbolInfo(const ObjectFile &Obj,1488                                       const SymbolRef &Symbol,1489                                       bool IsMappingSymbol) {1490  const StringRef FileName = Obj.getFileName();1491  const uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);1492  const StringRef Name = unwrapOrError(Symbol.getName(), FileName);1493 1494  if (Obj.isXCOFF() && (SymbolDescription || TracebackTable)) {1495    const auto &XCOFFObj = cast<XCOFFObjectFile>(Obj);1496    DataRefImpl SymbolDRI = Symbol.getRawDataRefImpl();1497 1498    const uint32_t SymbolIndex = XCOFFObj.getSymbolIndex(SymbolDRI.p);1499    std::optional<XCOFF::StorageMappingClass> Smc =1500        getXCOFFSymbolCsectSMC(XCOFFObj, Symbol);1501    return SymbolInfoTy(Smc, Addr, Name, SymbolIndex,1502                        isLabel(XCOFFObj, Symbol));1503  } else if (Obj.isXCOFF()) {1504    const SymbolRef::Type SymType = unwrapOrError(Symbol.getType(), FileName);1505    return SymbolInfoTy(Addr, Name, SymType, /*IsMappingSymbol=*/false,1506                        /*IsXCOFF=*/true);1507  } else if (Obj.isWasm()) {1508    uint8_t SymType =1509        cast<WasmObjectFile>(&Obj)->getWasmSymbol(Symbol).Info.Kind;1510    return SymbolInfoTy(Addr, Name, SymType, false);1511  } else {1512    uint8_t Type =1513        Obj.isELF() ? getElfSymbolType(Obj, Symbol) : (uint8_t)ELF::STT_NOTYPE;1514    return SymbolInfoTy(Addr, Name, Type, IsMappingSymbol);1515  }1516}1517 1518static SymbolInfoTy createDummySymbolInfo(const ObjectFile &Obj,1519                                          const uint64_t Addr, StringRef &Name,1520                                          uint8_t Type) {1521  if (Obj.isXCOFF() && (SymbolDescription || TracebackTable))1522    return SymbolInfoTy(std::nullopt, Addr, Name, std::nullopt, false);1523  if (Obj.isWasm())1524    return SymbolInfoTy(Addr, Name, wasm::WASM_SYMBOL_TYPE_SECTION);1525  return SymbolInfoTy(Addr, Name, Type);1526}1527 1528static void collectBBAddrMapLabels(1529    const BBAddrMapInfo &FullAddrMap, uint64_t SectionAddr, uint64_t Start,1530    uint64_t End,1531    std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> &Labels) {1532  if (FullAddrMap.empty())1533    return;1534  Labels.clear();1535  uint64_t StartAddress = SectionAddr + Start;1536  uint64_t EndAddress = SectionAddr + End;1537  const BBAddrMapFunctionEntry *FunctionMap =1538      FullAddrMap.getEntryForAddress(StartAddress);1539  if (!FunctionMap)1540    return;1541  std::optional<size_t> BBRangeIndex =1542      FunctionMap->getAddrMap().getBBRangeIndexForBaseAddress(StartAddress);1543  if (!BBRangeIndex)1544    return;1545  size_t NumBBEntriesBeforeRange = 0;1546  for (size_t I = 0; I < *BBRangeIndex; ++I)1547    NumBBEntriesBeforeRange +=1548        FunctionMap->getAddrMap().BBRanges[I].BBEntries.size();1549  const auto &BBRange = FunctionMap->getAddrMap().BBRanges[*BBRangeIndex];1550  for (size_t I = 0; I < BBRange.BBEntries.size(); ++I) {1551    const BBAddrMap::BBEntry &BBEntry = BBRange.BBEntries[I];1552    uint64_t BBAddress = BBEntry.Offset + BBRange.BaseAddress;1553    if (BBAddress >= EndAddress)1554      continue;1555 1556    std::string LabelString = ("BB" + Twine(BBEntry.ID)).str();1557    Labels[BBAddress].push_back(1558        {LabelString, FunctionMap->constructPGOLabelString(1559                          NumBBEntriesBeforeRange + I, PrettyPGOAnalysisMap)});1560  }1561}1562 1563static void1564collectLocalBranchTargets(ArrayRef<uint8_t> Bytes, MCInstrAnalysis *MIA,1565                          MCDisassembler *DisAsm, MCInstPrinter *IP,1566                          const MCSubtargetInfo *STI, uint64_t SectionAddr,1567                          uint64_t Start, uint64_t End,1568                          std::unordered_map<uint64_t, std::string> &Labels) {1569  // Supported by certain targets.1570  const bool isPPC = STI->getTargetTriple().isPPC();1571  const bool isX86 = STI->getTargetTriple().isX86();1572  const bool isAArch64 = STI->getTargetTriple().isAArch64();1573  const bool isBPF = STI->getTargetTriple().isBPF();1574  if (!isPPC && !isX86 && !isAArch64 && !isBPF)1575    return;1576 1577  if (MIA)1578    MIA->resetState();1579 1580  std::set<uint64_t> Targets;1581  Start += SectionAddr;1582  End += SectionAddr;1583  const bool isXCOFF = STI->getTargetTriple().isOSBinFormatXCOFF();1584  for (uint64_t Index = Start; Index < End;) {1585    // Disassemble a real instruction and record function-local branch labels.1586    MCInst Inst;1587    uint64_t Size;1588    ArrayRef<uint8_t> ThisBytes = Bytes.slice(Index - SectionAddr);1589    bool Disassembled =1590        DisAsm->getInstruction(Inst, Size, ThisBytes, Index, nulls());1591    if (Size == 0)1592      Size = std::min<uint64_t>(ThisBytes.size(),1593                                DisAsm->suggestBytesToSkip(ThisBytes, Index));1594 1595    if (MIA) {1596      if (Disassembled) {1597        uint64_t Target;1598        bool TargetKnown = MIA->evaluateBranch(Inst, Index, Size, Target);1599        if (TargetKnown && (Target >= Start && Target < End) &&1600            !Targets.count(Target)) {1601          // On PowerPC and AIX, a function call is encoded as a branch to 0.1602          // On other PowerPC platforms (ELF), a function call is encoded as1603          // a branch to self. Do not add a label for these cases.1604          if (!(isPPC &&1605                ((Target == 0 && isXCOFF) || (Target == Index && !isXCOFF))))1606            Targets.insert(Target);1607        }1608        MIA->updateState(Inst, Index);1609      } else1610        MIA->resetState();1611    }1612    Index += Size;1613  }1614 1615  Labels.clear();1616  for (auto [Idx, Target] : enumerate(Targets))1617    Labels[Target] = ("L" + Twine(Idx)).str();1618}1619 1620// Create an MCSymbolizer for the target and add it to the MCDisassembler.1621// This is currently only used on AMDGPU, and assumes the format of the1622// void * argument passed to AMDGPU's createMCSymbolizer.1623static void addSymbolizer(1624    MCContext &Ctx, const Target *Target, const Triple &TheTriple,1625    MCDisassembler *DisAsm, uint64_t SectionAddr, ArrayRef<uint8_t> Bytes,1626    SectionSymbolsTy &Symbols,1627    std::vector<std::unique_ptr<std::string>> &SynthesizedLabelNames) {1628 1629  std::unique_ptr<MCRelocationInfo> RelInfo(1630      Target->createMCRelocationInfo(TheTriple, Ctx));1631  if (!RelInfo)1632    return;1633  std::unique_ptr<MCSymbolizer> Symbolizer(Target->createMCSymbolizer(1634      TheTriple, nullptr, nullptr, &Symbols, &Ctx, std::move(RelInfo)));1635  MCSymbolizer *SymbolizerPtr = &*Symbolizer;1636  DisAsm->setSymbolizer(std::move(Symbolizer));1637 1638  if (!SymbolizeOperands)1639    return;1640 1641  // Synthesize labels referenced by branch instructions by1642  // disassembling, discarding the output, and collecting the referenced1643  // addresses from the symbolizer.1644  for (size_t Index = 0; Index != Bytes.size();) {1645    MCInst Inst;1646    uint64_t Size;1647    ArrayRef<uint8_t> ThisBytes = Bytes.slice(Index);1648    const uint64_t ThisAddr = SectionAddr + Index;1649    DisAsm->getInstruction(Inst, Size, ThisBytes, ThisAddr, nulls());1650    if (Size == 0)1651      Size = std::min<uint64_t>(ThisBytes.size(),1652                                DisAsm->suggestBytesToSkip(ThisBytes, Index));1653    Index += Size;1654  }1655  ArrayRef<uint64_t> LabelAddrsRef = SymbolizerPtr->getReferencedAddresses();1656  // Copy and sort to remove duplicates.1657  std::vector<uint64_t> LabelAddrs;1658  llvm::append_range(LabelAddrs, LabelAddrsRef);1659  llvm::sort(LabelAddrs);1660  LabelAddrs.resize(llvm::unique(LabelAddrs) - LabelAddrs.begin());1661  // Add the labels.1662  for (unsigned LabelNum = 0; LabelNum != LabelAddrs.size(); ++LabelNum) {1663    auto Name = std::make_unique<std::string>();1664    *Name = (Twine("L") + Twine(LabelNum)).str();1665    SynthesizedLabelNames.push_back(std::move(Name));1666    Symbols.push_back(SymbolInfoTy(1667        LabelAddrs[LabelNum], *SynthesizedLabelNames.back(), ELF::STT_NOTYPE));1668  }1669  llvm::stable_sort(Symbols);1670  // Recreate the symbolizer with the new symbols list.1671  RelInfo.reset(Target->createMCRelocationInfo(TheTriple, Ctx));1672  Symbolizer.reset(Target->createMCSymbolizer(1673      TheTriple, nullptr, nullptr, &Symbols, &Ctx, std::move(RelInfo)));1674  DisAsm->setSymbolizer(std::move(Symbolizer));1675}1676 1677static StringRef getSegmentName(const MachOObjectFile *MachO,1678                                const SectionRef &Section) {1679  if (MachO) {1680    DataRefImpl DR = Section.getRawDataRefImpl();1681    StringRef SegmentName = MachO->getSectionFinalSegmentName(DR);1682    return SegmentName;1683  }1684  return "";1685}1686 1687static void createFakeELFSections(ObjectFile &Obj) {1688  assert(Obj.isELF());1689  if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(&Obj))1690    Elf32LEObj->createFakeSections();1691  else if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(&Obj))1692    Elf64LEObj->createFakeSections();1693  else if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(&Obj))1694    Elf32BEObj->createFakeSections();1695  else if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(&Obj))1696    Elf64BEObj->createFakeSections();1697  else1698    llvm_unreachable("Unsupported binary format");1699}1700 1701// Tries to fetch a more complete version of the given object file using its1702// Build ID. Returns std::nullopt if nothing was found.1703static std::optional<OwningBinary<Binary>>1704fetchBinaryByBuildID(const ObjectFile &Obj) {1705  object::BuildIDRef BuildID = getBuildID(&Obj);1706  if (BuildID.empty())1707    return std::nullopt;1708  std::optional<std::string> Path = BIDFetcher->fetch(BuildID);1709  if (!Path)1710    return std::nullopt;1711  Expected<OwningBinary<Binary>> DebugBinary = createBinary(*Path);1712  if (!DebugBinary) {1713    reportWarning(toString(DebugBinary.takeError()), *Path);1714    return std::nullopt;1715  }1716  return std::move(*DebugBinary);1717}1718 1719static void1720disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,1721                  DisassemblerTarget &PrimaryTarget,1722                  std::optional<DisassemblerTarget> &SecondaryTarget,1723                  SourcePrinter &SP, bool InlineRelocs, raw_ostream &OS) {1724  DisassemblerTarget *DT = &PrimaryTarget;1725  bool PrimaryIsThumb = false;1726  SmallVector<std::pair<uint64_t, uint64_t>, 0> CHPECodeMap;1727 1728  if (SecondaryTarget) {1729    if (isArmElf(Obj)) {1730      PrimaryIsThumb =1731          PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode");1732    } else if (const auto *COFFObj = dyn_cast<COFFObjectFile>(&Obj)) {1733      const chpe_metadata *CHPEMetadata = COFFObj->getCHPEMetadata();1734      if (CHPEMetadata && CHPEMetadata->CodeMapCount) {1735        uintptr_t CodeMapInt;1736        cantFail(COFFObj->getRvaPtr(CHPEMetadata->CodeMap, CodeMapInt));1737        auto CodeMap = reinterpret_cast<const chpe_range_entry *>(CodeMapInt);1738 1739        for (uint32_t i = 0; i < CHPEMetadata->CodeMapCount; ++i) {1740          if (CodeMap[i].getType() == chpe_range_type::Amd64 &&1741              CodeMap[i].Length) {1742            // Store x86_64 CHPE code ranges.1743            uint64_t Start = CodeMap[i].getStart() + COFFObj->getImageBase();1744            CHPECodeMap.emplace_back(Start, Start + CodeMap[i].Length);1745          }1746        }1747        llvm::sort(CHPECodeMap);1748      }1749    }1750  }1751 1752  std::map<SectionRef, std::vector<RelocationRef>> RelocMap;1753  if (InlineRelocs || Obj.isXCOFF())1754    RelocMap = getRelocsMap(Obj);1755  bool Is64Bits = Obj.getBytesInAddress() > 4;1756 1757  // Create a mapping from virtual address to symbol name.  This is used to1758  // pretty print the symbols while disassembling.1759  std::map<SectionRef, SectionSymbolsTy> AllSymbols;1760  std::map<SectionRef, SmallVector<MappingSymbolPair, 0>> AllMappingSymbols;1761  SectionSymbolsTy AbsoluteSymbols;1762  const StringRef FileName = Obj.getFileName();1763  const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(&Obj);1764  for (const SymbolRef &Symbol : Obj.symbols()) {1765    Expected<StringRef> NameOrErr = Symbol.getName();1766    if (!NameOrErr) {1767      reportWarning(toString(NameOrErr.takeError()), FileName);1768      continue;1769    }1770    if (NameOrErr->empty() && !(Obj.isXCOFF() && SymbolDescription))1771      continue;1772 1773    if (Obj.isELF() &&1774        (cantFail(Symbol.getFlags()) & SymbolRef::SF_FormatSpecific)) {1775      // Symbol is intended not to be displayed by default (STT_FILE,1776      // STT_SECTION, or a mapping symbol). Ignore STT_SECTION symbols. We will1777      // synthesize a section symbol if no symbol is defined at offset 0.1778      //1779      // For a mapping symbol, store it within both AllSymbols and1780      // AllMappingSymbols. If --show-all-symbols is unspecified, its label will1781      // not be printed in disassembly listing.1782      if (getElfSymbolType(Obj, Symbol) != ELF::STT_SECTION &&1783          hasMappingSymbols(Obj)) {1784        section_iterator SecI = unwrapOrError(Symbol.getSection(), FileName);1785        if (SecI != Obj.section_end()) {1786          uint64_t SectionAddr = SecI->getAddress();1787          uint64_t Address = cantFail(Symbol.getAddress());1788          StringRef Name = *NameOrErr;1789          if (Name.consume_front("$") && Name.size() &&1790              strchr("adtx", Name[0])) {1791            AllMappingSymbols[*SecI].emplace_back(Address - SectionAddr,1792                                                  Name[0]);1793            AllSymbols[*SecI].push_back(1794                createSymbolInfo(Obj, Symbol, /*MappingSymbol=*/true));1795          }1796        }1797      }1798      continue;1799    }1800 1801    if (MachO) {1802      // __mh_(execute|dylib|dylinker|bundle|preload|object)_header are special1803      // symbols that support MachO header introspection. They do not bind to1804      // code locations and are irrelevant for disassembly.1805      if (NameOrErr->starts_with("__mh_") && NameOrErr->ends_with("_header"))1806        continue;1807      // Don't ask a Mach-O STAB symbol for its section unless you know that1808      // STAB symbol's section field refers to a valid section index. Otherwise1809      // the symbol may error trying to load a section that does not exist.1810      DataRefImpl SymDRI = Symbol.getRawDataRefImpl();1811      uint8_t NType =1812          (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type1813                            : MachO->getSymbolTableEntry(SymDRI).n_type);1814      if (NType & MachO::N_STAB)1815        continue;1816    }1817 1818    section_iterator SecI = unwrapOrError(Symbol.getSection(), FileName);1819    if (SecI != Obj.section_end())1820      AllSymbols[*SecI].push_back(createSymbolInfo(Obj, Symbol));1821    else1822      AbsoluteSymbols.push_back(createSymbolInfo(Obj, Symbol));1823  }1824 1825  if (AllSymbols.empty() && Obj.isELF())1826    addDynamicElfSymbols(cast<ELFObjectFileBase>(Obj), AllSymbols);1827 1828  if (Obj.isWasm())1829    addMissingWasmCodeSymbols(cast<WasmObjectFile>(Obj), AllSymbols);1830 1831  if (Obj.isELF() && Obj.sections().empty())1832    createFakeELFSections(Obj);1833 1834  DisassemblerTarget *PltTarget = DT;1835  auto SectionNames = getSectionNames(Obj);1836  if (SecondaryTarget && isArmElf(Obj)) {1837    auto PltSectionRef = SectionNames.find(".plt");1838    if (PltSectionRef != SectionNames.end()) {1839      bool PltIsThumb = false;1840      for (auto [Addr, SymbolName] : AllMappingSymbols[PltSectionRef->second]) {1841        if (Addr != 0)1842          continue;1843 1844        if (SymbolName == 't') {1845          PltIsThumb = true;1846          break;1847        }1848        if (SymbolName == 'a')1849          break;1850      }1851 1852      if (PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode"))1853        PltTarget = PltIsThumb ? &PrimaryTarget : &*SecondaryTarget;1854      else1855        PltTarget = PltIsThumb ? &*SecondaryTarget : &PrimaryTarget;1856    }1857  }1858  BumpPtrAllocator A;1859  StringSaver Saver(A);1860  addPltEntries(*PltTarget->SubtargetInfo, Obj, SectionNames, AllSymbols,1861                Saver);1862 1863  // Create a mapping from virtual address to section. An empty section can1864  // cause more than one section at the same address. Sort such sections to be1865  // before same-addressed non-empty sections so that symbol lookups prefer the1866  // non-empty section.1867  std::vector<std::pair<uint64_t, SectionRef>> SectionAddresses;1868  for (SectionRef Sec : Obj.sections())1869    SectionAddresses.emplace_back(Sec.getAddress(), Sec);1870  llvm::stable_sort(SectionAddresses, [](const auto &LHS, const auto &RHS) {1871    if (LHS.first != RHS.first)1872      return LHS.first < RHS.first;1873    return LHS.second.getSize() < RHS.second.getSize();1874  });1875 1876  // Linked executables (.exe and .dll files) typically don't include a real1877  // symbol table but they might contain an export table.1878  if (const auto *COFFObj = dyn_cast<COFFObjectFile>(&Obj)) {1879    for (const auto &ExportEntry : COFFObj->export_directories()) {1880      StringRef Name;1881      if (Error E = ExportEntry.getSymbolName(Name))1882        reportError(std::move(E), Obj.getFileName());1883      if (Name.empty())1884        continue;1885 1886      uint32_t RVA;1887      if (Error E = ExportEntry.getExportRVA(RVA))1888        reportError(std::move(E), Obj.getFileName());1889 1890      uint64_t VA = COFFObj->getImageBase() + RVA;1891      auto Sec = partition_point(1892          SectionAddresses, [VA](const std::pair<uint64_t, SectionRef> &O) {1893            return O.first <= VA;1894          });1895      if (Sec != SectionAddresses.begin()) {1896        --Sec;1897        AllSymbols[Sec->second].emplace_back(VA, Name, ELF::STT_NOTYPE);1898      } else1899        AbsoluteSymbols.emplace_back(VA, Name, ELF::STT_NOTYPE);1900    }1901  }1902 1903  // Sort all the symbols, this allows us to use a simple binary search to find1904  // Multiple symbols can have the same address. Use a stable sort to stabilize1905  // the output.1906  StringSet<> FoundDisasmSymbolSet;1907  for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols)1908    llvm::stable_sort(SecSyms.second);1909  llvm::stable_sort(AbsoluteSymbols);1910 1911  std::unique_ptr<DWARFContext> DICtx;1912  LiveElementPrinter LEP(*DT->Context->getRegisterInfo(), *DT->SubtargetInfo);1913 1914  if (DbgVariables != DFDisabled || DbgInlinedFunctions != DFDisabled) {1915    DICtx = DWARFContext::create(DbgObj);1916    for (const std::unique_ptr<DWARFUnit> &CU : DICtx->compile_units())1917      LEP.addCompileUnit(CU->getUnitDIE(false));1918  }1919 1920  LLVM_DEBUG(LEP.dump());1921 1922  BBAddrMapInfo FullAddrMap;1923  auto ReadBBAddrMap = [&](std::optional<unsigned> SectionIndex =1924                               std::nullopt) {1925    FullAddrMap.clear();1926    if (const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj)) {1927      std::vector<PGOAnalysisMap> PGOAnalyses;1928      auto BBAddrMapsOrErr = Elf->readBBAddrMap(SectionIndex, &PGOAnalyses);1929      if (!BBAddrMapsOrErr) {1930        reportWarning(toString(BBAddrMapsOrErr.takeError()), Obj.getFileName());1931        return;1932      }1933      for (auto &&[FunctionBBAddrMap, FunctionPGOAnalysis] :1934           zip_equal(*std::move(BBAddrMapsOrErr), std::move(PGOAnalyses))) {1935        FullAddrMap.AddFunctionEntry(std::move(FunctionBBAddrMap),1936                                     std::move(FunctionPGOAnalysis));1937      }1938    }1939  };1940 1941  // For non-relocatable objects, Read all LLVM_BB_ADDR_MAP sections into a1942  // single mapping, since they don't have any conflicts.1943  if (SymbolizeOperands && !Obj.isRelocatableObject())1944    ReadBBAddrMap();1945 1946  std::optional<llvm::BTFParser> BTF;1947  if (InlineRelocs && BTFParser::hasBTFSections(Obj)) {1948    BTF.emplace();1949    BTFParser::ParseOptions Opts = {};1950    Opts.LoadTypes = true;1951    Opts.LoadRelocs = true;1952    if (Error E = BTF->parse(Obj, Opts))1953      WithColor::defaultErrorHandler(std::move(E));1954  }1955 1956  for (const SectionRef &Section : ToolSectionFilter(Obj)) {1957    if (FilterSections.empty() && !DisassembleAll &&1958        (!Section.isText() || Section.isVirtual()))1959      continue;1960 1961    uint64_t SectionAddr = Section.getAddress();1962    uint64_t SectSize = Section.getSize();1963    if (!SectSize)1964      continue;1965 1966    // For relocatable object files, read the LLVM_BB_ADDR_MAP section1967    // corresponding to this section, if present.1968    if (SymbolizeOperands && Obj.isRelocatableObject())1969      ReadBBAddrMap(Section.getIndex());1970 1971    // Get the list of all the symbols in this section.1972    SectionSymbolsTy &Symbols = AllSymbols[Section];1973    auto &MappingSymbols = AllMappingSymbols[Section];1974    llvm::sort(MappingSymbols);1975 1976    ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(1977        unwrapOrError(Section.getContents(), Obj.getFileName()));1978 1979    std::vector<std::unique_ptr<std::string>> SynthesizedLabelNames;1980    if (Obj.isELF() && Obj.getArch() == Triple::amdgcn) {1981      // AMDGPU disassembler uses symbolizer for printing labels1982      addSymbolizer(*DT->Context, DT->TheTarget, DT->TheTriple,1983                    DT->DisAsm.get(), SectionAddr, Bytes, Symbols,1984                    SynthesizedLabelNames);1985    }1986 1987    StringRef SegmentName = getSegmentName(MachO, Section);1988    StringRef SectionName = unwrapOrError(Section.getName(), Obj.getFileName());1989    // If the section has no symbol at the start, just insert a dummy one.1990    // Without --show-all-symbols, also insert one if all symbols at the start1991    // are mapping symbols.1992    bool CreateDummy = Symbols.empty();1993    if (!CreateDummy) {1994      CreateDummy = true;1995      for (auto &Sym : Symbols) {1996        if (Sym.Addr != SectionAddr)1997          break;1998        if (!Sym.IsMappingSymbol || ShowAllSymbols)1999          CreateDummy = false;2000      }2001    }2002    if (CreateDummy) {2003      SymbolInfoTy Sym = createDummySymbolInfo(2004          Obj, SectionAddr, SectionName,2005          Section.isText() ? ELF::STT_FUNC : ELF::STT_OBJECT);2006      if (Obj.isXCOFF())2007        Symbols.insert(Symbols.begin(), Sym);2008      else2009        Symbols.insert(llvm::lower_bound(Symbols, Sym), Sym);2010    }2011 2012    SmallString<40> Comments;2013    raw_svector_ostream CommentStream(Comments);2014 2015    uint64_t VMAAdjustment = 0;2016    if (shouldAdjustVA(Section))2017      VMAAdjustment = AdjustVMA;2018 2019    // In executable and shared objects, r_offset holds a virtual address.2020    // Subtract SectionAddr from the r_offset field of a relocation to get2021    // the section offset.2022    uint64_t RelAdjustment = Obj.isRelocatableObject() ? 0 : SectionAddr;2023    uint64_t Size;2024    uint64_t Index;2025    bool PrintedSection = false;2026    std::vector<RelocationRef> Rels = RelocMap[Section];2027    std::vector<RelocationRef>::const_iterator RelCur = Rels.begin();2028    std::vector<RelocationRef>::const_iterator RelEnd = Rels.end();2029 2030    // Loop over each chunk of code between two points where at least2031    // one symbol is defined.2032    for (size_t SI = 0, SE = Symbols.size(); SI != SE;) {2033      // Advance SI past all the symbols starting at the same address,2034      // and make an ArrayRef of them.2035      unsigned FirstSI = SI;2036      uint64_t Start = Symbols[SI].Addr;2037      ArrayRef<SymbolInfoTy> SymbolsHere;2038      while (SI != SE && Symbols[SI].Addr == Start)2039        ++SI;2040      SymbolsHere = ArrayRef<SymbolInfoTy>(&Symbols[FirstSI], SI - FirstSI);2041 2042      // Get the demangled names of all those symbols. We end up with a vector2043      // of StringRef that holds the names we're going to use, and a vector of2044      // std::string that stores the new strings returned by demangle(), if2045      // any. If we don't call demangle() then that vector can stay empty.2046      std::vector<StringRef> SymNamesHere;2047      std::vector<std::string> DemangledSymNamesHere;2048      if (Demangle) {2049        // Fetch the demangled names and store them locally.2050        for (const SymbolInfoTy &Symbol : SymbolsHere)2051          DemangledSymNamesHere.push_back(demangle(Symbol.Name));2052        // Now we've finished modifying that vector, it's safe to make2053        // a vector of StringRefs pointing into it.2054        SymNamesHere.insert(SymNamesHere.begin(), DemangledSymNamesHere.begin(),2055                            DemangledSymNamesHere.end());2056      } else {2057        for (const SymbolInfoTy &Symbol : SymbolsHere)2058          SymNamesHere.push_back(Symbol.Name);2059      }2060 2061      // Distinguish ELF data from code symbols, which will be used later on to2062      // decide whether to 'disassemble' this chunk as a data declaration via2063      // dumpELFData(), or whether to treat it as code.2064      //2065      // If data _and_ code symbols are defined at the same address, the code2066      // takes priority, on the grounds that disassembling code is our main2067      // purpose here, and it would be a worse failure to _not_ interpret2068      // something that _was_ meaningful as code than vice versa.2069      //2070      // Any ELF symbol type that is not clearly data will be regarded as code.2071      // In particular, one of the uses of STT_NOTYPE is for branch targets2072      // inside functions, for which STT_FUNC would be inaccurate.2073      //2074      // So here, we spot whether there's any non-data symbol present at all,2075      // and only set the DisassembleAsELFData flag if there isn't. Also, we use2076      // this distinction to inform the decision of which symbol to print at2077      // the head of the section, so that if we're printing code, we print a2078      // code-related symbol name to go with it.2079      bool DisassembleAsELFData = false;2080      size_t DisplaySymIndex = SymbolsHere.size() - 1;2081      if (Obj.isELF() && !DisassembleAll && Section.isText()) {2082        DisassembleAsELFData = true; // unless we find a code symbol below2083 2084        for (size_t i = 0; i < SymbolsHere.size(); ++i) {2085          uint8_t SymTy = SymbolsHere[i].Type;2086          if (SymTy != ELF::STT_OBJECT && SymTy != ELF::STT_COMMON) {2087            DisassembleAsELFData = false;2088            DisplaySymIndex = i;2089          }2090        }2091      }2092 2093      // Decide which symbol(s) from this collection we're going to print.2094      std::vector<bool> SymsToPrint(SymbolsHere.size(), false);2095      // If the user has given the --disassemble-symbols option, then we must2096      // display every symbol in that set, and no others.2097      if (!DisasmSymbolSet.empty()) {2098        bool FoundAny = false;2099        for (size_t i = 0; i < SymbolsHere.size(); ++i) {2100          if (DisasmSymbolSet.count(SymNamesHere[i])) {2101            SymsToPrint[i] = true;2102            FoundAny = true;2103          }2104        }2105 2106        // And if none of the symbols here is one that the user asked for, skip2107        // disassembling this entire chunk of code.2108        if (!FoundAny)2109          continue;2110      } else if (!SymbolsHere[DisplaySymIndex].IsMappingSymbol) {2111        // Otherwise, print whichever symbol at this location is last in the2112        // Symbols array, because that array is pre-sorted in a way intended to2113        // correlate with priority of which symbol to display.2114        SymsToPrint[DisplaySymIndex] = true;2115      }2116 2117      // Now that we know we're disassembling this section, override the choice2118      // of which symbols to display by printing _all_ of them at this address2119      // if the user asked for all symbols.2120      //2121      // That way, '--show-all-symbols --disassemble-symbol=foo' will print2122      // only the chunk of code headed by 'foo', but also show any other2123      // symbols defined at that address, such as aliases for 'foo', or the ARM2124      // mapping symbol preceding its code.2125      if (ShowAllSymbols) {2126        for (size_t i = 0; i < SymbolsHere.size(); ++i)2127          SymsToPrint[i] = true;2128      }2129 2130      if (Start < SectionAddr || StopAddress <= Start)2131        continue;2132 2133      FoundDisasmSymbolSet.insert_range(SymNamesHere);2134 2135      // The end is the section end, the beginning of the next symbol, or2136      // --stop-address.2137      uint64_t End = std::min<uint64_t>(SectionAddr + SectSize, StopAddress);2138      if (SI < SE)2139        End = std::min(End, Symbols[SI].Addr);2140      if (Start >= End || End <= StartAddress)2141        continue;2142      Start -= SectionAddr;2143      End -= SectionAddr;2144 2145      if (!PrintedSection) {2146        PrintedSection = true;2147        OS << "\nDisassembly of section ";2148        if (!SegmentName.empty())2149          OS << SegmentName << ",";2150        OS << SectionName << ":\n";2151      }2152 2153      bool PrintedLabel = false;2154      for (size_t i = 0; i < SymbolsHere.size(); ++i) {2155        if (!SymsToPrint[i])2156          continue;2157 2158        const SymbolInfoTy &Symbol = SymbolsHere[i];2159        const StringRef SymbolName = SymNamesHere[i];2160 2161        if (!PrintedLabel) {2162          OS << '\n';2163          PrintedLabel = true;2164        }2165        if (LeadingAddr)2166          OS << format(Is64Bits ? "%016" PRIx64 " " : "%08" PRIx64 " ",2167                       SectionAddr + Start + VMAAdjustment);2168        if (Obj.isXCOFF() && SymbolDescription) {2169          OS << getXCOFFSymbolDescription(Symbol, SymbolName) << ":\n";2170        } else2171          OS << '<' << SymbolName << ">:\n";2172      }2173 2174      // Don't print raw contents of a virtual section. A virtual section2175      // doesn't have any contents in the file.2176      if (Section.isVirtual()) {2177        OS << "...\n";2178        continue;2179      }2180 2181      // See if any of the symbols defined at this location triggers target-2182      // specific disassembly behavior, e.g. of special descriptors or function2183      // prelude information.2184      //2185      // We stop this loop at the first symbol that triggers some kind of2186      // interesting behavior (if any), on the assumption that if two symbols2187      // defined at the same address trigger two conflicting symbol handlers,2188      // the object file is probably confused anyway, and it would make even2189      // less sense to present the output of _both_ handlers, because that2190      // would describe the same data twice.2191      for (size_t SHI = 0; SHI < SymbolsHere.size(); ++SHI) {2192        SymbolInfoTy Symbol = SymbolsHere[SHI];2193 2194        Expected<bool> RespondedOrErr = DT->DisAsm->onSymbolStart(2195            Symbol, Size, Bytes.slice(Start, End - Start), SectionAddr + Start);2196 2197        if (RespondedOrErr && !*RespondedOrErr) {2198          // This symbol didn't trigger any interesting handling. Try the other2199          // symbols defined at this address.2200          continue;2201        }2202 2203        // If onSymbolStart returned an Error, that means it identified some2204        // kind of special data at this address, but wasn't able to disassemble2205        // it meaningfully. So we fall back to printing the error out and2206        // disassembling the failed region as bytes, assuming that the target2207        // detected the failure before printing anything.2208        if (!RespondedOrErr) {2209          std::string ErrMsgStr = toString(RespondedOrErr.takeError());2210          StringRef ErrMsg = ErrMsgStr;2211          do {2212            StringRef Line;2213            std::tie(Line, ErrMsg) = ErrMsg.split('\n');2214            OS << DT->Context->getAsmInfo()->getCommentString()2215               << " error decoding " << SymNamesHere[SHI] << ": " << Line2216               << '\n';2217          } while (!ErrMsg.empty());2218 2219          if (Size) {2220            OS << DT->Context->getAsmInfo()->getCommentString()2221               << " decoding failed region as bytes\n";2222            for (uint64_t I = 0; I < Size; ++I)2223              OS << "\t.byte\t " << format_hex(Bytes[I], 1, /*Upper=*/true)2224                 << '\n';2225          }2226        }2227 2228        // Regardless of whether onSymbolStart returned an Error or true, 'Size'2229        // will have been set to the amount of data covered by whatever prologue2230        // the target identified. So we advance our own position to beyond that.2231        // Sometimes that will be the entire distance to the next symbol, and2232        // sometimes it will be just a prologue and we should start2233        // disassembling instructions from where it left off.2234        Start += Size;2235        break;2236      }2237      // Allow targets to reset any per-symbol state.2238      DT->Printer->onSymbolStart();2239      formatted_raw_ostream FOS(OS);2240      Index = Start;2241      if (SectionAddr < StartAddress)2242        Index = std::max<uint64_t>(Index, StartAddress - SectionAddr);2243 2244      if (DisassembleAsELFData) {2245        dumpELFData(SectionAddr, Index, End, Bytes, FOS);2246        Index = End;2247        continue;2248      }2249 2250      // Skip relocations from symbols that are not dumped.2251      for (; RelCur != RelEnd; ++RelCur) {2252        uint64_t Offset = RelCur->getOffset() - RelAdjustment;2253        if (Index <= Offset)2254          break;2255      }2256 2257      bool DumpARMELFData = false;2258      bool DumpTracebackTableForXCOFFFunction =2259          Obj.isXCOFF() && Section.isText() && TracebackTable &&2260          Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass &&2261          (*Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass == XCOFF::XMC_PR);2262 2263      std::unordered_map<uint64_t, std::string> AllLabels;2264      std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> BBAddrMapLabels;2265      if (SymbolizeOperands) {2266        collectLocalBranchTargets(Bytes, DT->InstrAnalysis.get(),2267                                  DT->DisAsm.get(), DT->InstPrinter.get(),2268                                  PrimaryTarget.SubtargetInfo.get(),2269                                  SectionAddr, Index, End, AllLabels);2270        collectBBAddrMapLabels(FullAddrMap, SectionAddr, Index, End,2271                               BBAddrMapLabels);2272      }2273 2274      if (DT->InstrAnalysis)2275        DT->InstrAnalysis->resetState();2276 2277      while (Index < End) {2278        uint64_t RelOffset;2279 2280        // ARM and AArch64 ELF binaries can interleave data and text in the2281        // same section. We rely on the markers introduced to understand what2282        // we need to dump. If the data marker is within a function, it is2283        // denoted as a word/short etc.2284        if (!MappingSymbols.empty()) {2285          char Kind = getMappingSymbolKind(MappingSymbols, Index);2286          DumpARMELFData = Kind == 'd';2287          if (SecondaryTarget) {2288            if (Kind == 'a') {2289              DT = PrimaryIsThumb ? &*SecondaryTarget : &PrimaryTarget;2290            } else if (Kind == 't') {2291              DT = PrimaryIsThumb ? &PrimaryTarget : &*SecondaryTarget;2292            }2293          }2294        } else if (!CHPECodeMap.empty()) {2295          uint64_t Address = SectionAddr + Index;2296          auto It = partition_point(2297              CHPECodeMap,2298              [Address](const std::pair<uint64_t, uint64_t> &Entry) {2299                return Entry.first <= Address;2300              });2301          if (It != CHPECodeMap.begin() && Address < (It - 1)->second) {2302            DT = &*SecondaryTarget;2303          } else {2304            DT = &PrimaryTarget;2305            // X64 disassembler range may have left Index unaligned, so2306            // make sure that it's aligned when we switch back to ARM642307            // code.2308            Index = llvm::alignTo(Index, 4);2309            if (Index >= End)2310              break;2311          }2312        }2313 2314        auto findRel = [&]() {2315          while (RelCur != RelEnd) {2316            RelOffset = RelCur->getOffset() - RelAdjustment;2317            // If this relocation is hidden, skip it.2318            if (getHidden(*RelCur) || SectionAddr + RelOffset < StartAddress) {2319              ++RelCur;2320              continue;2321            }2322 2323            // Stop when RelCur's offset is past the disassembled2324            // instruction/data.2325            if (RelOffset >= Index + Size)2326              return false;2327            if (RelOffset >= Index)2328              return true;2329            ++RelCur;2330          }2331          return false;2332        };2333 2334        // When -z or --disassemble-zeroes are given we always dissasemble2335        // them. Otherwise we might want to skip zero bytes we see.2336        if (!DisassembleZeroes) {2337          uint64_t MaxOffset = End - Index;2338          // For --reloc: print zero blocks patched by relocations, so that2339          // relocations can be shown in the dump.2340          if (InlineRelocs && RelCur != RelEnd)2341            MaxOffset = std::min(RelCur->getOffset() - RelAdjustment - Index,2342                                 MaxOffset);2343 2344          if (size_t N =2345                  countSkippableZeroBytes(Bytes.slice(Index, MaxOffset))) {2346            FOS << "\t\t..." << '\n';2347            Index += N;2348            continue;2349          }2350        }2351 2352        if (DumpARMELFData) {2353          Size = dumpARMELFData(SectionAddr, Index, End, Obj, Bytes,2354                                MappingSymbols, *DT->SubtargetInfo, FOS);2355        } else {2356 2357          if (DumpTracebackTableForXCOFFFunction &&2358              doesXCOFFTracebackTableBegin(Bytes.slice(Index, 4))) {2359            dumpTracebackTable(Bytes.slice(Index),2360                               SectionAddr + Index + VMAAdjustment, FOS,2361                               SectionAddr + End + VMAAdjustment,2362                               *DT->SubtargetInfo, cast<XCOFFObjectFile>(&Obj));2363            Index = End;2364            continue;2365          }2366 2367          // Print local label if there's any.2368          auto Iter1 = BBAddrMapLabels.find(SectionAddr + Index);2369          if (Iter1 != BBAddrMapLabels.end()) {2370            for (const auto &BBLabel : Iter1->second)2371              FOS << "<" << BBLabel.BlockLabel << ">" << BBLabel.PGOAnalysis2372                  << ":\n";2373          } else {2374            auto Iter2 = AllLabels.find(SectionAddr + Index);2375            if (Iter2 != AllLabels.end())2376              FOS << "<" << Iter2->second << ">:\n";2377          }2378 2379          // Disassemble a real instruction or a data when disassemble all is2380          // provided2381          MCInst Inst;2382          ArrayRef<uint8_t> ThisBytes = Bytes.slice(Index);2383          uint64_t ThisAddr = SectionAddr + Index + VMAAdjustment;2384          bool Disassembled = DT->DisAsm->getInstruction(2385              Inst, Size, ThisBytes, ThisAddr, CommentStream);2386          if (Size == 0)2387            Size = std::min<uint64_t>(2388                ThisBytes.size(),2389                DT->DisAsm->suggestBytesToSkip(ThisBytes, ThisAddr));2390 2391          LEP.update({ThisAddr, Section.getIndex()},2392                     {ThisAddr + Size, Section.getIndex()},2393                     Index + Size != End);2394 2395          DT->InstPrinter->setCommentStream(CommentStream);2396 2397          DT->Printer->printInst(2398              *DT->InstPrinter, Disassembled ? &Inst : nullptr,2399              Bytes.slice(Index, Size),2400              {SectionAddr + Index + VMAAdjustment, Section.getIndex()}, FOS,2401              "", *DT->SubtargetInfo, &SP, Obj.getFileName(), &Rels, LEP);2402 2403          DT->InstPrinter->setCommentStream(llvm::nulls());2404 2405          // If disassembly succeeds, we try to resolve the target address2406          // (jump target or memory operand address) and print it to the2407          // right of the instruction.2408          //2409          // Otherwise, we don't print anything else so that we avoid2410          // analyzing invalid or incomplete instruction information.2411          if (Disassembled && DT->InstrAnalysis) {2412            llvm::raw_ostream *TargetOS = &FOS;2413            uint64_t Target;2414            bool PrintTarget = DT->InstrAnalysis->evaluateBranch(2415                Inst, SectionAddr + Index, Size, Target);2416 2417            if (!PrintTarget) {2418              if (std::optional<uint64_t> MaybeTarget =2419                      DT->InstrAnalysis->evaluateMemoryOperandAddress(2420                          Inst, DT->SubtargetInfo.get(), SectionAddr + Index,2421                          Size)) {2422                Target = *MaybeTarget;2423                PrintTarget = true;2424                // Do not print real address when symbolizing.2425                if (!SymbolizeOperands) {2426                  // Memory operand addresses are printed as comments.2427                  TargetOS = &CommentStream;2428                  *TargetOS << "0x" << Twine::utohexstr(Target);2429                }2430              }2431            }2432 2433            if (PrintTarget) {2434              // In a relocatable object, the target's section must reside in2435              // the same section as the call instruction or it is accessed2436              // through a relocation.2437              //2438              // In a non-relocatable object, the target may be in any section.2439              // In that case, locate the section(s) containing the target2440              // address and find the symbol in one of those, if possible.2441              //2442              // N.B. Except for XCOFF, we don't walk the relocations in the2443              // relocatable case yet.2444              std::vector<const SectionSymbolsTy *> TargetSectionSymbols;2445              if (!Obj.isRelocatableObject()) {2446                auto It = llvm::partition_point(2447                    SectionAddresses,2448                    [=](const std::pair<uint64_t, SectionRef> &O) {2449                      return O.first <= Target;2450                    });2451                uint64_t TargetSecAddr = 0;2452                while (It != SectionAddresses.begin()) {2453                  --It;2454                  if (TargetSecAddr == 0)2455                    TargetSecAddr = It->first;2456                  if (It->first != TargetSecAddr)2457                    break;2458                  TargetSectionSymbols.push_back(&AllSymbols[It->second]);2459                }2460              } else {2461                TargetSectionSymbols.push_back(&Symbols);2462              }2463              TargetSectionSymbols.push_back(&AbsoluteSymbols);2464 2465              // Find the last symbol in the first candidate section whose2466              // offset is less than or equal to the target. If there are no2467              // such symbols, try in the next section and so on, before finally2468              // using the nearest preceding absolute symbol (if any), if there2469              // are no other valid symbols.2470              const SymbolInfoTy *TargetSym = nullptr;2471              for (const SectionSymbolsTy *TargetSymbols :2472                   TargetSectionSymbols) {2473                auto It = llvm::partition_point(2474                    *TargetSymbols,2475                    [=](const SymbolInfoTy &O) { return O.Addr <= Target; });2476                while (It != TargetSymbols->begin()) {2477                  --It;2478                  // Skip mapping symbols to avoid possible ambiguity as they2479                  // do not allow uniquely identifying the target address.2480                  if (!It->IsMappingSymbol) {2481                    TargetSym = &*It;2482                    break;2483                  }2484                }2485                if (TargetSym)2486                  break;2487              }2488 2489              // Branch targets are printed just after the instructions.2490              // Print the labels corresponding to the target if there's any.2491              bool BBAddrMapLabelAvailable = BBAddrMapLabels.count(Target);2492              bool LabelAvailable = AllLabels.count(Target);2493 2494              if (TargetSym != nullptr) {2495                uint64_t TargetAddress = TargetSym->Addr;2496                uint64_t Disp = Target - TargetAddress;2497                std::string TargetName = Demangle ? demangle(TargetSym->Name)2498                                                  : TargetSym->Name.str();2499                bool RelFixedUp = false;2500                SmallString<32> Val;2501 2502                *TargetOS << " <";2503                // On XCOFF, we use relocations, even without -r, so we2504                // can print the correct name for an extern function call.2505                if (Obj.isXCOFF() && findRel()) {2506                  // Check for possible branch relocations and2507                  // branches to fixup code.2508                  bool BranchRelocationType = true;2509                  XCOFF::RelocationType RelocType;2510                  if (Obj.is64Bit()) {2511                    const XCOFFRelocation64 *Reloc =2512                        reinterpret_cast<XCOFFRelocation64 *>(2513                            RelCur->getRawDataRefImpl().p);2514                    RelFixedUp = Reloc->isFixupIndicated();2515                    RelocType = Reloc->Type;2516                  } else {2517                    const XCOFFRelocation32 *Reloc =2518                        reinterpret_cast<XCOFFRelocation32 *>(2519                            RelCur->getRawDataRefImpl().p);2520                    RelFixedUp = Reloc->isFixupIndicated();2521                    RelocType = Reloc->Type;2522                  }2523                  BranchRelocationType =2524                      RelocType == XCOFF::R_BA || RelocType == XCOFF::R_BR ||2525                      RelocType == XCOFF::R_RBA || RelocType == XCOFF::R_RBR;2526 2527                  // If we have a valid relocation, try to print its2528                  // corresponding symbol name. Multiple relocations on the2529                  // same instruction are not handled.2530                  // Branches to fixup code will have the RelFixedUp flag set in2531                  // the RLD. For these instructions, we print the correct2532                  // branch target, but print the referenced symbol as a2533                  // comment.2534                  if (Error E = getRelocationValueString(*RelCur, false, Val)) {2535                    // If -r was used, this error will be printed later.2536                    // Otherwise, we ignore the error and print what2537                    // would have been printed without using relocations.2538                    consumeError(std::move(E));2539                    *TargetOS << TargetName;2540                    RelFixedUp = false; // Suppress comment for RLD sym name2541                  } else if (BranchRelocationType && !RelFixedUp)2542                    *TargetOS << Val;2543                  else2544                    *TargetOS << TargetName;2545                  if (Disp)2546                    *TargetOS << "+0x" << Twine::utohexstr(Disp);2547                } else if (!Disp) {2548                  *TargetOS << TargetName;2549                } else if (BBAddrMapLabelAvailable) {2550                  *TargetOS << BBAddrMapLabels[Target].front().BlockLabel;2551                } else if (LabelAvailable) {2552                  *TargetOS << AllLabels[Target];2553                } else {2554                  // Always Print the binary symbol plus an offset if there's no2555                  // local label corresponding to the target address.2556                  *TargetOS << TargetName << "+0x" << Twine::utohexstr(Disp);2557                }2558                *TargetOS << ">";2559                if (RelFixedUp && !InlineRelocs) {2560                  // We have fixup code for a relocation. We print the2561                  // referenced symbol as a comment.2562                  *TargetOS << "\t# " << Val;2563                }2564 2565              } else if (BBAddrMapLabelAvailable) {2566                *TargetOS << " <" << BBAddrMapLabels[Target].front().BlockLabel2567                          << ">";2568              } else if (LabelAvailable) {2569                *TargetOS << " <" << AllLabels[Target] << ">";2570              }2571              // By convention, each record in the comment stream should be2572              // terminated.2573              if (TargetOS == &CommentStream)2574                *TargetOS << "\n";2575            }2576 2577            DT->InstrAnalysis->updateState(Inst, SectionAddr + Index);2578          } else if (!Disassembled && DT->InstrAnalysis) {2579            DT->InstrAnalysis->resetState();2580          }2581        }2582 2583        assert(DT->Context->getAsmInfo());2584        DT->Printer->emitPostInstructionInfo(FOS, *DT->Context->getAsmInfo(),2585                                             *DT->SubtargetInfo,2586                                             CommentStream.str(), LEP);2587        Comments.clear();2588 2589        if (BTF)2590          printBTFRelocation(FOS, *BTF, {Index, Section.getIndex()}, LEP);2591 2592        if (InlineRelocs) {2593          while (findRel()) {2594            // When --adjust-vma is used, update the address printed.2595            printRelocation(FOS, Obj.getFileName(), *RelCur,2596                            SectionAddr + RelOffset + VMAAdjustment, Is64Bits);2597            LEP.printAfterOtherLine(FOS, true);2598            ++RelCur;2599          }2600        }2601 2602        object::SectionedAddress NextAddr = {2603            SectionAddr + Index + VMAAdjustment + Size, Section.getIndex()};2604        LEP.printBoundaryLine(FOS, NextAddr, true);2605 2606        Index += Size;2607      }2608    }2609  }2610  StringSet<> MissingDisasmSymbolSet =2611      set_difference(DisasmSymbolSet, FoundDisasmSymbolSet);2612  for (StringRef Sym : MissingDisasmSymbolSet.keys())2613    reportWarning("failed to disassemble missing symbol " + Sym, FileName);2614}2615 2616static void disassembleObject(ObjectFile *Obj, bool InlineRelocs,2617                              raw_ostream &OS) {2618  // If information useful for showing the disassembly is missing, try to find a2619  // more complete binary and disassemble that instead.2620  OwningBinary<Binary> FetchedBinary;2621  if (Obj->symbols().empty()) {2622    if (std::optional<OwningBinary<Binary>> FetchedBinaryOpt =2623            fetchBinaryByBuildID(*Obj)) {2624      if (auto *O = dyn_cast<ObjectFile>(FetchedBinaryOpt->getBinary())) {2625        if (!O->symbols().empty() ||2626            (!O->sections().empty() && Obj->sections().empty())) {2627          FetchedBinary = std::move(*FetchedBinaryOpt);2628          Obj = O;2629        }2630      }2631    }2632  }2633 2634  const Target *TheTarget = getTarget(Obj);2635 2636  // Package up features to be passed to target/subtarget2637  Expected<SubtargetFeatures> FeaturesValue = Obj->getFeatures();2638  if (!FeaturesValue)2639    reportError(FeaturesValue.takeError(), Obj->getFileName());2640  SubtargetFeatures Features = *FeaturesValue;2641  if (!MAttrs.empty()) {2642    for (unsigned I = 0; I != MAttrs.size(); ++I)2643      Features.AddFeature(MAttrs[I]);2644  } else if (MCPU.empty() && Obj->makeTriple().isAArch64()) {2645    Features.AddFeature("+all");2646  }2647 2648  if (MCPU.empty())2649    MCPU = Obj->tryGetCPUName().value_or("").str();2650 2651  if (isArmElf(*Obj)) {2652    // When disassembling big-endian Arm ELF, the instruction endianness is2653    // determined in a complex way. In relocatable objects, AAELF32 mandates2654    // that instruction endianness matches the ELF file endianness; in2655    // executable images, that's true unless the file header has the EF_ARM_BE82656    // flag, in which case instructions are little-endian regardless of data2657    // endianness.2658    //2659    // We must set the big-endian-instructions SubtargetFeature to make the2660    // disassembler read the instructions the right way round, and also tell2661    // our own prettyprinter to retrieve the encodings the same way to print in2662    // hex.2663    const auto *Elf32BE = dyn_cast<ELF32BEObjectFile>(Obj);2664 2665    if (Elf32BE && (Elf32BE->isRelocatableObject() ||2666                    !(Elf32BE->getPlatformFlags() & ELF::EF_ARM_BE8))) {2667      Features.AddFeature("+big-endian-instructions");2668      ARMPrettyPrinterInst.setInstructionEndianness(llvm::endianness::big);2669    } else {2670      ARMPrettyPrinterInst.setInstructionEndianness(llvm::endianness::little);2671    }2672  }2673 2674  DisassemblerTarget PrimaryTarget(TheTarget, *Obj, TripleName, MCPU, Features);2675 2676  // If we have an ARM object file, we need a second disassembler, because2677  // ARM CPUs have two different instruction sets: ARM mode, and Thumb mode.2678  // We use mapping symbols to switch between the two assemblers, where2679  // appropriate.2680  std::optional<DisassemblerTarget> SecondaryTarget;2681 2682  if (isArmElf(*Obj)) {2683    if (!PrimaryTarget.SubtargetInfo->checkFeatures("+mclass")) {2684      if (PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode"))2685        Features.AddFeature("-thumb-mode");2686      else2687        Features.AddFeature("+thumb-mode");2688      SecondaryTarget.emplace(PrimaryTarget, Features);2689    }2690  } else if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Obj)) {2691    const chpe_metadata *CHPEMetadata = COFFObj->getCHPEMetadata();2692    if (CHPEMetadata && CHPEMetadata->CodeMapCount) {2693      // Set up x86_64 disassembler for ARM64EC binaries.2694      Triple X64Triple(TripleName);2695      X64Triple.setArch(Triple::ArchType::x86_64);2696 2697      std::string Error;2698      const Target *X64Target =2699          TargetRegistry::lookupTarget("", X64Triple, Error);2700      if (X64Target) {2701        SubtargetFeatures X64Features;2702        SecondaryTarget.emplace(X64Target, *Obj, X64Triple.getTriple(), "",2703                                X64Features);2704      } else {2705        reportWarning(Error, Obj->getFileName());2706      }2707    }2708  }2709 2710  const ObjectFile *DbgObj = Obj;2711  if (!FetchedBinary.getBinary() && !Obj->hasDebugInfo()) {2712    if (std::optional<OwningBinary<Binary>> DebugBinaryOpt =2713            fetchBinaryByBuildID(*Obj)) {2714      if (auto *FetchedObj =2715              dyn_cast<const ObjectFile>(DebugBinaryOpt->getBinary())) {2716        if (FetchedObj->hasDebugInfo()) {2717          FetchedBinary = std::move(*DebugBinaryOpt);2718          DbgObj = FetchedObj;2719        }2720      }2721    }2722  }2723 2724  std::unique_ptr<object::Binary> DSYMBinary;2725  std::unique_ptr<MemoryBuffer> DSYMBuf;2726  if (!DbgObj->hasDebugInfo()) {2727    if (const MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*Obj)) {2728      DbgObj = objdump::getMachODSymObject(MachOOF, Obj->getFileName(),2729                                           DSYMBinary, DSYMBuf);2730      if (!DbgObj)2731        return;2732    }2733  }2734 2735  SourcePrinter SP(DbgObj, TheTarget->getName());2736 2737  for (StringRef Opt : DisassemblerOptions)2738    if (!PrimaryTarget.InstPrinter->applyTargetSpecificCLOption(Opt))2739      reportError(Obj->getFileName(),2740                  "Unrecognized disassembler option: " + Opt);2741 2742  disassembleObject(*Obj, *DbgObj, PrimaryTarget, SecondaryTarget, SP,2743                    InlineRelocs, OS);2744}2745 2746void Dumper::printRelocations() {2747  StringRef Fmt = O.getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;2748 2749  // Build a mapping from relocation target to a vector of relocation2750  // sections. Usually, there is an only one relocation section for2751  // each relocated section.2752  MapVector<SectionRef, std::vector<SectionRef>> SecToRelSec;2753  uint64_t Ndx;2754  for (const SectionRef &Section : ToolSectionFilter(O, &Ndx)) {2755    if (O.isELF() && (ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC))2756      continue;2757    if (Section.relocations().empty())2758      continue;2759    Expected<section_iterator> SecOrErr = Section.getRelocatedSection();2760    if (!SecOrErr)2761      reportError(O.getFileName(),2762                  "section (" + Twine(Ndx) +2763                      "): unable to get a relocation target: " +2764                      toString(SecOrErr.takeError()));2765    SecToRelSec[**SecOrErr].push_back(Section);2766  }2767 2768  for (std::pair<SectionRef, std::vector<SectionRef>> &P : SecToRelSec) {2769    StringRef SecName = unwrapOrError(P.first.getName(), O.getFileName());2770    outs() << "\nRELOCATION RECORDS FOR [" << SecName << "]:\n";2771    uint32_t OffsetPadding = (O.getBytesInAddress() > 4 ? 16 : 8);2772    uint32_t TypePadding = 24;2773    outs() << left_justify("OFFSET", OffsetPadding) << " "2774           << left_justify("TYPE", TypePadding) << " "2775           << "VALUE\n";2776 2777    for (SectionRef Section : P.second) {2778      // CREL sections require decoding, each section may have its own specific2779      // decode problems.2780      if (O.isELF() && ELFSectionRef(Section).getType() == ELF::SHT_CREL) {2781        StringRef Err =2782            cast<const ELFObjectFileBase>(O).getCrelDecodeProblem(Section);2783        if (!Err.empty()) {2784          reportUniqueWarning(Err);2785          continue;2786        }2787      }2788      for (const RelocationRef &Reloc : Section.relocations()) {2789        uint64_t Address = Reloc.getOffset();2790        SmallString<32> RelocName;2791        SmallString<32> ValueStr;2792        if (Address < StartAddress || Address > StopAddress || getHidden(Reloc))2793          continue;2794        Reloc.getTypeName(RelocName);2795        if (Error E =2796                getRelocationValueString(Reloc, SymbolDescription, ValueStr))2797          reportUniqueWarning(std::move(E));2798 2799        outs() << format(Fmt.data(), Address) << " "2800               << left_justify(RelocName, TypePadding) << " " << ValueStr2801               << "\n";2802      }2803    }2804  }2805}2806 2807// Returns true if we need to show LMA column when dumping section headers. We2808// show it only when the platform is ELF and either we have at least one section2809// whose VMA and LMA are different and/or when --show-lma flag is used.2810static bool shouldDisplayLMA(const ObjectFile &Obj) {2811  if (!Obj.isELF())2812    return false;2813  for (const SectionRef &S : ToolSectionFilter(Obj))2814    if (S.getAddress() != getELFSectionLMA(S))2815      return true;2816  return ShowLMA;2817}2818 2819static size_t getMaxSectionNameWidth(const ObjectFile &Obj) {2820  // Default column width for names is 13 even if no names are that long.2821  size_t MaxWidth = 13;2822  for (const SectionRef &Section : ToolSectionFilter(Obj)) {2823    StringRef Name = unwrapOrError(Section.getName(), Obj.getFileName());2824    MaxWidth = std::max(MaxWidth, Name.size());2825  }2826  return MaxWidth;2827}2828 2829void objdump::printSectionHeaders(ObjectFile &Obj) {2830  if (Obj.isELF() && Obj.sections().empty())2831    createFakeELFSections(Obj);2832 2833  size_t NameWidth = getMaxSectionNameWidth(Obj);2834  size_t AddressWidth = 2 * Obj.getBytesInAddress();2835  bool HasLMAColumn = shouldDisplayLMA(Obj);2836  outs() << "\nSections:\n";2837  if (HasLMAColumn)2838    outs() << "Idx " << left_justify("Name", NameWidth) << " Size     "2839           << left_justify("VMA", AddressWidth) << " "2840           << left_justify("LMA", AddressWidth) << " Type\n";2841  else2842    outs() << "Idx " << left_justify("Name", NameWidth) << " Size     "2843           << left_justify("VMA", AddressWidth) << " Type\n";2844 2845  uint64_t Idx;2846  for (const SectionRef &Section : ToolSectionFilter(Obj, &Idx)) {2847    StringRef Name = unwrapOrError(Section.getName(), Obj.getFileName());2848    uint64_t VMA = Section.getAddress();2849    if (shouldAdjustVA(Section))2850      VMA += AdjustVMA;2851 2852    uint64_t Size = Section.getSize();2853 2854    std::string Type = Section.isText() ? "TEXT" : "";2855    if (Section.isData())2856      Type += Type.empty() ? "DATA" : ", DATA";2857    if (Section.isBSS())2858      Type += Type.empty() ? "BSS" : ", BSS";2859    if (Section.isDebugSection())2860      Type += Type.empty() ? "DEBUG" : ", DEBUG";2861 2862    if (HasLMAColumn)2863      outs() << format("%3" PRIu64 " %-*s %08" PRIx64 " ", Idx, NameWidth,2864                       Name.str().c_str(), Size)2865             << format_hex_no_prefix(VMA, AddressWidth) << " "2866             << format_hex_no_prefix(getELFSectionLMA(Section), AddressWidth)2867             << " " << Type << "\n";2868    else2869      outs() << format("%3" PRIu64 " %-*s %08" PRIx64 " ", Idx, NameWidth,2870                       Name.str().c_str(), Size)2871             << format_hex_no_prefix(VMA, AddressWidth) << " " << Type << "\n";2872  }2873}2874 2875void objdump::printSectionContents(const ObjectFile *Obj) {2876  const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj);2877 2878  for (const SectionRef &Section : ToolSectionFilter(*Obj)) {2879    StringRef Name = unwrapOrError(Section.getName(), Obj->getFileName());2880    uint64_t BaseAddr = Section.getAddress();2881    uint64_t Size = Section.getSize();2882    if (!Size)2883      continue;2884 2885    outs() << "Contents of section ";2886    StringRef SegmentName = getSegmentName(MachO, Section);2887    if (!SegmentName.empty())2888      outs() << SegmentName << ",";2889    outs() << Name << ":\n";2890    if (Section.isBSS()) {2891      outs() << format("<skipping contents of bss section at [%04" PRIx642892                       ", %04" PRIx64 ")>\n",2893                       BaseAddr, BaseAddr + Size);2894      continue;2895    }2896 2897    StringRef Contents =2898        unwrapOrError(Section.getContents(), Obj->getFileName());2899 2900    // Dump out the content as hex and printable ascii characters.2901    for (std::size_t Addr = 0, End = Contents.size(); Addr < End; Addr += 16) {2902      outs() << format(" %04" PRIx64 " ", BaseAddr + Addr);2903      // Dump line of hex.2904      for (std::size_t I = 0; I < 16; ++I) {2905        if (I != 0 && I % 4 == 0)2906          outs() << ' ';2907        if (Addr + I < End)2908          outs() << hexdigit((Contents[Addr + I] >> 4) & 0xF, true)2909                 << hexdigit(Contents[Addr + I] & 0xF, true);2910        else2911          outs() << "  ";2912      }2913      // Print ascii.2914      outs() << "  ";2915      for (std::size_t I = 0; I < 16 && Addr + I < End; ++I) {2916        if (isPrint(static_cast<unsigned char>(Contents[Addr + I]) & 0xFF))2917          outs() << Contents[Addr + I];2918        else2919          outs() << ".";2920      }2921      outs() << "\n";2922    }2923  }2924}2925 2926void Dumper::printSymbolTable(StringRef ArchiveName, StringRef ArchitectureName,2927                              bool DumpDynamic) {2928  if (O.isCOFF() && !DumpDynamic) {2929    outs() << "\nSYMBOL TABLE:\n";2930    printCOFFSymbolTable(cast<const COFFObjectFile>(O));2931    return;2932  }2933 2934  const StringRef FileName = O.getFileName();2935 2936  if (!DumpDynamic) {2937    outs() << "\nSYMBOL TABLE:\n";2938    for (auto I = O.symbol_begin(); I != O.symbol_end(); ++I)2939      printSymbol(*I, {}, FileName, ArchiveName, ArchitectureName, DumpDynamic);2940    return;2941  }2942 2943  outs() << "\nDYNAMIC SYMBOL TABLE:\n";2944  if (!O.isELF()) {2945    reportWarning(2946        "this operation is not currently supported for this file format",2947        FileName);2948    return;2949  }2950 2951  const ELFObjectFileBase *ELF = cast<const ELFObjectFileBase>(&O);2952  auto Symbols = ELF->getDynamicSymbolIterators();2953  Expected<std::vector<VersionEntry>> SymbolVersionsOrErr =2954      ELF->readDynsymVersions();2955  if (!SymbolVersionsOrErr) {2956    reportWarning(toString(SymbolVersionsOrErr.takeError()), FileName);2957    SymbolVersionsOrErr = std::vector<VersionEntry>();2958    (void)!SymbolVersionsOrErr;2959  }2960  for (auto &Sym : Symbols)2961    printSymbol(Sym, *SymbolVersionsOrErr, FileName, ArchiveName,2962                ArchitectureName, DumpDynamic);2963}2964 2965void Dumper::printSymbol(const SymbolRef &Symbol,2966                         ArrayRef<VersionEntry> SymbolVersions,2967                         StringRef FileName, StringRef ArchiveName,2968                         StringRef ArchitectureName, bool DumpDynamic) {2969  const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(&O);2970  Expected<uint64_t> AddrOrErr = Symbol.getAddress();2971  if (!AddrOrErr) {2972    reportUniqueWarning(AddrOrErr.takeError());2973    return;2974  }2975 2976  // Don't ask a Mach-O STAB symbol for its section unless you know that2977  // STAB symbol's section field refers to a valid section index. Otherwise2978  // the symbol may error trying to load a section that does not exist.2979  bool IsSTAB = false;2980  if (MachO) {2981    DataRefImpl SymDRI = Symbol.getRawDataRefImpl();2982    uint8_t NType =2983        (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type2984                          : MachO->getSymbolTableEntry(SymDRI).n_type);2985    if (NType & MachO::N_STAB)2986      IsSTAB = true;2987  }2988  section_iterator Section = IsSTAB2989                                 ? O.section_end()2990                                 : unwrapOrError(Symbol.getSection(), FileName,2991                                                 ArchiveName, ArchitectureName);2992 2993  uint64_t Address = *AddrOrErr;2994  if (Section != O.section_end() && shouldAdjustVA(*Section))2995    Address += AdjustVMA;2996  if ((Address < StartAddress) || (Address > StopAddress))2997    return;2998  SymbolRef::Type Type =2999      unwrapOrError(Symbol.getType(), FileName, ArchiveName, ArchitectureName);3000  uint32_t Flags =3001      unwrapOrError(Symbol.getFlags(), FileName, ArchiveName, ArchitectureName);3002 3003  StringRef Name;3004  if (Type == SymbolRef::ST_Debug && Section != O.section_end()) {3005    if (Expected<StringRef> NameOrErr = Section->getName())3006      Name = *NameOrErr;3007    else3008      consumeError(NameOrErr.takeError());3009 3010  } else {3011    Name = unwrapOrError(Symbol.getName(), FileName, ArchiveName,3012                         ArchitectureName);3013  }3014 3015  bool Global = Flags & SymbolRef::SF_Global;3016  bool Weak = Flags & SymbolRef::SF_Weak;3017  bool Absolute = Flags & SymbolRef::SF_Absolute;3018  bool Common = Flags & SymbolRef::SF_Common;3019  bool Hidden = Flags & SymbolRef::SF_Hidden;3020 3021  char GlobLoc = ' ';3022  if ((Section != O.section_end() || Absolute) && !Weak)3023    GlobLoc = Global ? 'g' : 'l';3024  char IFunc = ' ';3025  if (O.isELF()) {3026    if (ELFSymbolRef(Symbol).getELFType() == ELF::STT_GNU_IFUNC)3027      IFunc = 'i';3028    if (ELFSymbolRef(Symbol).getBinding() == ELF::STB_GNU_UNIQUE)3029      GlobLoc = 'u';3030  }3031 3032  char Debug = ' ';3033  if (DumpDynamic)3034    Debug = 'D';3035  else if (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)3036    Debug = 'd';3037 3038  char FileFunc = ' ';3039  if (Type == SymbolRef::ST_File)3040    FileFunc = 'f';3041  else if (Type == SymbolRef::ST_Function)3042    FileFunc = 'F';3043  else if (Type == SymbolRef::ST_Data)3044    FileFunc = 'O';3045 3046  const char *Fmt = O.getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;3047 3048  outs() << format(Fmt, Address) << " "3049         << GlobLoc            // Local -> 'l', Global -> 'g', Neither -> ' '3050         << (Weak ? 'w' : ' ') // Weak?3051         << ' '                // Constructor. Not supported yet.3052         << ' '                // Warning. Not supported yet.3053         << IFunc              // Indirect reference to another symbol.3054         << Debug              // Debugging (d) or dynamic (D) symbol.3055         << FileFunc           // Name of function (F), file (f) or object (O).3056         << ' ';3057  if (Absolute) {3058    outs() << "*ABS*";3059  } else if (Common) {3060    outs() << "*COM*";3061  } else if (Section == O.section_end()) {3062    if (O.isXCOFF()) {3063      XCOFFSymbolRef XCOFFSym = cast<const XCOFFObjectFile>(O).toSymbolRef(3064          Symbol.getRawDataRefImpl());3065      if (XCOFF::N_DEBUG == XCOFFSym.getSectionNumber())3066        outs() << "*DEBUG*";3067      else3068        outs() << "*UND*";3069    } else3070      outs() << "*UND*";3071  } else {3072    StringRef SegmentName = getSegmentName(MachO, *Section);3073    if (!SegmentName.empty())3074      outs() << SegmentName << ",";3075    StringRef SectionName = unwrapOrError(Section->getName(), FileName);3076    outs() << SectionName;3077    if (O.isXCOFF()) {3078      std::optional<SymbolRef> SymRef =3079          getXCOFFSymbolContainingSymbolRef(cast<XCOFFObjectFile>(O), Symbol);3080      if (SymRef) {3081 3082        Expected<StringRef> NameOrErr = SymRef->getName();3083 3084        if (NameOrErr) {3085          outs() << " (csect:";3086          std::string SymName =3087              Demangle ? demangle(*NameOrErr) : NameOrErr->str();3088 3089          if (SymbolDescription)3090            SymName = getXCOFFSymbolDescription(createSymbolInfo(O, *SymRef),3091                                                SymName);3092 3093          outs() << ' ' << SymName;3094          outs() << ") ";3095        } else3096          reportWarning(toString(NameOrErr.takeError()), FileName);3097      }3098    }3099  }3100 3101  if (Common)3102    outs() << '\t' << format(Fmt, static_cast<uint64_t>(Symbol.getAlignment()));3103  else if (O.isXCOFF())3104    outs() << '\t'3105           << format(Fmt, cast<XCOFFObjectFile>(O).getSymbolSize(3106                              Symbol.getRawDataRefImpl()));3107  else if (O.isELF())3108    outs() << '\t' << format(Fmt, ELFSymbolRef(Symbol).getSize());3109  else if (O.isWasm())3110    outs() << '\t'3111           << format(Fmt, static_cast<uint64_t>(3112                              cast<WasmObjectFile>(O).getSymbolSize(Symbol)));3113 3114  if (O.isELF()) {3115    if (!SymbolVersions.empty()) {3116      const VersionEntry &Ver =3117          SymbolVersions[Symbol.getRawDataRefImpl().d.b - 1];3118      std::string Str;3119      if (!Ver.Name.empty())3120        Str = Ver.IsVerDef ? ' ' + Ver.Name : '(' + Ver.Name + ')';3121      outs() << ' ' << left_justify(Str, 12);3122    }3123 3124    uint8_t Other = ELFSymbolRef(Symbol).getOther();3125    switch (Other) {3126    case ELF::STV_DEFAULT:3127      break;3128    case ELF::STV_INTERNAL:3129      outs() << " .internal";3130      break;3131    case ELF::STV_HIDDEN:3132      outs() << " .hidden";3133      break;3134    case ELF::STV_PROTECTED:3135      outs() << " .protected";3136      break;3137    default:3138      outs() << format(" 0x%02x", Other);3139      break;3140    }3141  } else if (Hidden) {3142    outs() << " .hidden";3143  }3144 3145  std::string SymName = Demangle ? demangle(Name) : Name.str();3146  if (O.isXCOFF() && SymbolDescription)3147    SymName = getXCOFFSymbolDescription(createSymbolInfo(O, Symbol), SymName);3148 3149  outs() << ' ' << SymName << '\n';3150}3151 3152static void printUnwindInfo(const ObjectFile *O) {3153  outs() << "Unwind info:\n\n";3154 3155  if (const COFFObjectFile *Coff = dyn_cast<COFFObjectFile>(O))3156    printCOFFUnwindInfo(Coff);3157  else if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O))3158    printMachOUnwindInfo(MachO);3159  else3160    // TODO: Extract DWARF dump tool to objdump.3161    WithColor::error(errs(), ToolName)3162        << "This operation is only currently supported "3163           "for COFF and MachO object files.\n";3164}3165 3166/// Dump the raw contents of the __clangast section so the output can be piped3167/// into llvm-bcanalyzer.3168static void printRawClangAST(const ObjectFile *Obj) {3169  if (outs().is_displayed()) {3170    WithColor::error(errs(), ToolName)3171        << "The -raw-clang-ast option will dump the raw binary contents of "3172           "the clang ast section.\n"3173           "Please redirect the output to a file or another program such as "3174           "llvm-bcanalyzer.\n";3175    return;3176  }3177 3178  StringRef ClangASTSectionName("__clangast");3179  if (Obj->isCOFF()) {3180    ClangASTSectionName = "clangast";3181  }3182 3183  std::optional<object::SectionRef> ClangASTSection;3184  for (auto Sec : ToolSectionFilter(*Obj)) {3185    StringRef Name;3186    if (Expected<StringRef> NameOrErr = Sec.getName())3187      Name = *NameOrErr;3188    else3189      consumeError(NameOrErr.takeError());3190 3191    if (Name == ClangASTSectionName) {3192      ClangASTSection = Sec;3193      break;3194    }3195  }3196  if (!ClangASTSection)3197    return;3198 3199  StringRef ClangASTContents =3200      unwrapOrError(ClangASTSection->getContents(), Obj->getFileName());3201  outs().write(ClangASTContents.data(), ClangASTContents.size());3202}3203 3204static void printFaultMaps(const ObjectFile *Obj) {3205  StringRef FaultMapSectionName;3206 3207  if (Obj->isELF()) {3208    FaultMapSectionName = ".llvm_faultmaps";3209  } else if (Obj->isMachO()) {3210    FaultMapSectionName = "__llvm_faultmaps";3211  } else {3212    WithColor::error(errs(), ToolName)3213        << "This operation is only currently supported "3214           "for ELF and Mach-O executable files.\n";3215    return;3216  }3217 3218  std::optional<object::SectionRef> FaultMapSection;3219 3220  for (auto Sec : ToolSectionFilter(*Obj)) {3221    StringRef Name;3222    if (Expected<StringRef> NameOrErr = Sec.getName())3223      Name = *NameOrErr;3224    else3225      consumeError(NameOrErr.takeError());3226 3227    if (Name == FaultMapSectionName) {3228      FaultMapSection = Sec;3229      break;3230    }3231  }3232 3233  outs() << "FaultMap table:\n";3234 3235  if (!FaultMapSection) {3236    outs() << "<not found>\n";3237    return;3238  }3239 3240  StringRef FaultMapContents =3241      unwrapOrError(FaultMapSection->getContents(), Obj->getFileName());3242  FaultMapParser FMP(FaultMapContents.bytes_begin(),3243                     FaultMapContents.bytes_end());3244 3245  outs() << FMP;3246}3247 3248void Dumper::printPrivateHeaders() {3249  reportError(O.getFileName(), "Invalid/Unsupported object file format");3250}3251 3252static void printFileHeaders(const ObjectFile *O) {3253  if (!O->isELF() && !O->isCOFF() && !O->isXCOFF())3254    reportError(O->getFileName(), "Invalid/Unsupported object file format");3255 3256  Triple::ArchType AT = O->getArch();3257  outs() << "architecture: " << Triple::getArchTypeName(AT) << "\n";3258  uint64_t Address = unwrapOrError(O->getStartAddress(), O->getFileName());3259 3260  StringRef Fmt = O->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;3261  outs() << "start address: "3262         << "0x" << format(Fmt.data(), Address) << "\n";3263}3264 3265static void printArchiveChild(StringRef Filename, const Archive::Child &C) {3266  Expected<sys::fs::perms> ModeOrErr = C.getAccessMode();3267  if (!ModeOrErr) {3268    WithColor::error(errs(), ToolName) << "ill-formed archive entry.\n";3269    consumeError(ModeOrErr.takeError());3270    return;3271  }3272  sys::fs::perms Mode = ModeOrErr.get();3273  outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");3274  outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");3275  outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");3276  outs() << ((Mode & sys::fs::group_read) ? "r" : "-");3277  outs() << ((Mode & sys::fs::group_write) ? "w" : "-");3278  outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");3279  outs() << ((Mode & sys::fs::others_read) ? "r" : "-");3280  outs() << ((Mode & sys::fs::others_write) ? "w" : "-");3281  outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");3282 3283  outs() << " ";3284 3285  outs() << format("%d/%d %6" PRId64 " ", unwrapOrError(C.getUID(), Filename),3286                   unwrapOrError(C.getGID(), Filename),3287                   unwrapOrError(C.getRawSize(), Filename));3288 3289  StringRef RawLastModified = C.getRawLastModified();3290  unsigned Seconds;3291  if (RawLastModified.getAsInteger(10, Seconds))3292    outs() << "(date: \"" << RawLastModified3293           << "\" contains non-decimal chars) ";3294  else {3295    // Since ctime(3) returns a 26 character string of the form:3296    // "Sun Sep 16 01:03:52 1973\n\0"3297    // just print 24 characters.3298    time_t t = Seconds;3299    outs() << format("%.24s ", ctime(&t));3300  }3301 3302  StringRef Name = "";3303  Expected<StringRef> NameOrErr = C.getName();3304  if (!NameOrErr) {3305    consumeError(NameOrErr.takeError());3306    Name = unwrapOrError(C.getRawName(), Filename);3307  } else {3308    Name = NameOrErr.get();3309  }3310  outs() << Name << "\n";3311}3312 3313// For ELF only now.3314static bool shouldWarnForInvalidStartStopAddress(ObjectFile *Obj) {3315  if (const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj)) {3316    if (Elf->getEType() != ELF::ET_REL)3317      return true;3318  }3319  return false;3320}3321 3322static void checkForInvalidStartStopAddress(ObjectFile *Obj, uint64_t Start,3323                                            uint64_t Stop) {3324  if (!shouldWarnForInvalidStartStopAddress(Obj))3325    return;3326 3327  for (const SectionRef &Section : Obj->sections())3328    if (ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC) {3329      uint64_t BaseAddr = Section.getAddress();3330      uint64_t Size = Section.getSize();3331      if ((Start < BaseAddr + Size) && Stop > BaseAddr)3332        return;3333    }3334 3335  if (!HasStartAddressFlag)3336    reportWarning("no section has address less than 0x" +3337                      Twine::utohexstr(Stop) + " specified by --stop-address",3338                  Obj->getFileName());3339  else if (!HasStopAddressFlag)3340    reportWarning("no section has address greater than or equal to 0x" +3341                      Twine::utohexstr(Start) + " specified by --start-address",3342                  Obj->getFileName());3343  else3344    reportWarning("no section overlaps the range [0x" +3345                      Twine::utohexstr(Start) + ",0x" + Twine::utohexstr(Stop) +3346                      ") specified by --start-address/--stop-address",3347                  Obj->getFileName());3348}3349 3350static void dumpObject(ObjectFile *O, const Archive *A = nullptr,3351                       const Archive::Child *C = nullptr) {3352  Expected<std::unique_ptr<Dumper>> DumperOrErr = createDumper(*O);3353  if (!DumperOrErr) {3354    reportError(DumperOrErr.takeError(), O->getFileName(),3355                A ? A->getFileName() : "");3356    return;3357  }3358  Dumper &D = **DumperOrErr;3359 3360  // Avoid other output when using a raw option.3361  if (!RawClangAST) {3362    outs() << '\n';3363    if (A)3364      outs() << A->getFileName() << "(" << O->getFileName() << ")";3365    else3366      outs() << O->getFileName();3367    outs() << ":\tfile format " << O->getFileFormatName().lower() << "\n";3368  }3369 3370  if (HasStartAddressFlag || HasStopAddressFlag)3371    checkForInvalidStartStopAddress(O, StartAddress, StopAddress);3372 3373  // TODO: Change print* free functions to Dumper member functions to utilitize3374  // stateful functions like reportUniqueWarning.3375 3376  // Note: the order here matches GNU objdump for compatability.3377  StringRef ArchiveName = A ? A->getFileName() : "";3378  if (ArchiveHeaders && !MachOOpt && C)3379    printArchiveChild(ArchiveName, *C);3380  if (FileHeaders)3381    printFileHeaders(O);3382  if (PrivateHeaders || FirstPrivateHeader)3383    D.printPrivateHeaders();3384  if (SectionHeaders)3385    printSectionHeaders(*O);3386  if (SymbolTable)3387    D.printSymbolTable(ArchiveName);3388  if (DynamicSymbolTable)3389    D.printSymbolTable(ArchiveName, /*ArchitectureName=*/"",3390                       /*DumpDynamic=*/true);3391  if (DwarfDumpType != DIDT_Null) {3392    std::unique_ptr<DIContext> DICtx = DWARFContext::create(*O);3393    // Dump the complete DWARF structure.3394    DIDumpOptions DumpOpts;3395    DumpOpts.DumpType = DwarfDumpType;3396    DICtx->dump(outs(), DumpOpts);3397  }3398  if (Relocations && !Disassemble)3399    D.printRelocations();3400  if (DynamicRelocations)3401    D.printDynamicRelocations();3402  if (SectionContents)3403    printSectionContents(O);3404  if (Disassemble)3405    disassembleObject(O, Relocations, outs());3406  if (UnwindInfo)3407    printUnwindInfo(O);3408 3409  // Mach-O specific options:3410  if (ExportsTrie)3411    printExportsTrie(O);3412  if (Rebase)3413    printRebaseTable(O);3414  if (Bind)3415    printBindTable(O);3416  if (LazyBind)3417    printLazyBindTable(O);3418  if (WeakBind)3419    printWeakBindTable(O);3420 3421  // Other special sections:3422  if (RawClangAST)3423    printRawClangAST(O);3424  if (FaultMapSection)3425    printFaultMaps(O);3426  if (Offloading)3427    dumpOffloadBinary(*O, StringRef(ArchName));3428}3429 3430static void dumpObject(const COFFImportFile *I, const Archive *A,3431                       const Archive::Child *C = nullptr) {3432  StringRef ArchiveName = A ? A->getFileName() : "";3433 3434  // Avoid other output when using a raw option.3435  if (!RawClangAST)3436    outs() << '\n'3437           << ArchiveName << "(" << I->getFileName() << ")"3438           << ":\tfile format COFF-import-file"3439           << "\n\n";3440 3441  if (ArchiveHeaders && !MachOOpt && C)3442    printArchiveChild(ArchiveName, *C);3443  if (SymbolTable)3444    printCOFFSymbolTable(*I);3445}3446 3447/// Dump each object file in \a a;3448static void dumpArchive(const Archive *A) {3449  Error Err = Error::success();3450  unsigned I = -1;3451  for (auto &C : A->children(Err)) {3452    ++I;3453    Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();3454    if (!ChildOrErr) {3455      if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))3456        reportError(std::move(E), getFileNameForError(C, I), A->getFileName());3457      continue;3458    }3459    if (ObjectFile *O = dyn_cast<ObjectFile>(&*ChildOrErr.get()))3460      dumpObject(O, A, &C);3461    else if (COFFImportFile *I = dyn_cast<COFFImportFile>(&*ChildOrErr.get()))3462      dumpObject(I, A, &C);3463    else3464      reportError(errorCodeToError(object_error::invalid_file_type),3465                  A->getFileName());3466  }3467  if (Err)3468    reportError(std::move(Err), A->getFileName());3469}3470 3471/// Open file and figure out how to dump it.3472static void dumpInput(StringRef file) {3473  // If we are using the Mach-O specific object file parser, then let it parse3474  // the file and process the command line options.  So the -arch flags can3475  // be used to select specific slices, etc.3476  if (MachOOpt) {3477    parseInputMachO(file);3478    return;3479  }3480 3481  // Attempt to open the binary.3482  OwningBinary<Binary> OBinary = unwrapOrError(createBinary(file), file);3483  Binary &Binary = *OBinary.getBinary();3484 3485  if (Archive *A = dyn_cast<Archive>(&Binary))3486    dumpArchive(A);3487  else if (ObjectFile *O = dyn_cast<ObjectFile>(&Binary))3488    dumpObject(O);3489  else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Binary))3490    parseInputMachO(UB);3491  else if (OffloadBinary *OB = dyn_cast<OffloadBinary>(&Binary))3492    dumpOffloadSections(*OB);3493  else3494    reportError(errorCodeToError(object_error::invalid_file_type), file);3495}3496 3497template <typename T>3498static void parseIntArg(const llvm::opt::InputArgList &InputArgs, int ID,3499                        T &Value) {3500  if (const opt::Arg *A = InputArgs.getLastArg(ID)) {3501    StringRef V(A->getValue());3502    if (!llvm::to_integer(V, Value, 0)) {3503      reportCmdLineError(A->getSpelling() +3504                         ": expected a non-negative integer, but got '" + V +3505                         "'");3506    }3507  }3508}3509 3510static object::BuildID parseBuildIDArg(const opt::Arg *A) {3511  StringRef V(A->getValue());3512  object::BuildID BID = parseBuildID(V);3513  if (BID.empty())3514    reportCmdLineError(A->getSpelling() + ": expected a build ID, but got '" +3515                       V + "'");3516  return BID;3517}3518 3519void objdump::invalidArgValue(const opt::Arg *A) {3520  reportCmdLineError("'" + StringRef(A->getValue()) +3521                     "' is not a valid value for '" + A->getSpelling() + "'");3522}3523 3524static std::vector<std::string>3525commaSeparatedValues(const llvm::opt::InputArgList &InputArgs, int ID) {3526  std::vector<std::string> Values;3527  for (StringRef Value : InputArgs.getAllArgValues(ID)) {3528    llvm::SmallVector<StringRef, 2> SplitValues;3529    llvm::SplitString(Value, SplitValues, ",");3530    for (StringRef SplitValue : SplitValues)3531      Values.push_back(SplitValue.str());3532  }3533  return Values;3534}3535 3536static void parseOtoolOptions(const llvm::opt::InputArgList &InputArgs) {3537  MachOOpt = true;3538  FullLeadingAddr = true;3539  PrintImmHex = true;3540 3541  ArchName = InputArgs.getLastArgValue(OTOOL_arch).str();3542  LinkOptHints = InputArgs.hasArg(OTOOL_C);3543  if (InputArgs.hasArg(OTOOL_d))3544    FilterSections.push_back("__DATA,__data");3545  DylibId = InputArgs.hasArg(OTOOL_D);3546  UniversalHeaders = InputArgs.hasArg(OTOOL_f);3547  DataInCode = InputArgs.hasArg(OTOOL_G);3548  FirstPrivateHeader = InputArgs.hasArg(OTOOL_h);3549  IndirectSymbols = InputArgs.hasArg(OTOOL_I);3550  ShowRawInsn = InputArgs.hasArg(OTOOL_j);3551  PrivateHeaders = InputArgs.hasArg(OTOOL_l);3552  DylibsUsed = InputArgs.hasArg(OTOOL_L);3553  MCPU = InputArgs.getLastArgValue(OTOOL_mcpu_EQ).str();3554  ObjcMetaData = InputArgs.hasArg(OTOOL_o);3555  DisSymName = InputArgs.getLastArgValue(OTOOL_p).str();3556  InfoPlist = InputArgs.hasArg(OTOOL_P);3557  Relocations = InputArgs.hasArg(OTOOL_r);3558  if (const Arg *A = InputArgs.getLastArg(OTOOL_s)) {3559    auto Filter = (A->getValue(0) + StringRef(",") + A->getValue(1)).str();3560    FilterSections.push_back(Filter);3561  }3562  if (InputArgs.hasArg(OTOOL_t))3563    FilterSections.push_back("__TEXT,__text");3564  Verbose = InputArgs.hasArg(OTOOL_v) || InputArgs.hasArg(OTOOL_V) ||3565            InputArgs.hasArg(OTOOL_o);3566  SymbolicOperands = InputArgs.hasArg(OTOOL_V);3567  if (InputArgs.hasArg(OTOOL_x))3568    FilterSections.push_back(",__text");3569  LeadingAddr = LeadingHeaders = !InputArgs.hasArg(OTOOL_X);3570 3571  ChainedFixups = InputArgs.hasArg(OTOOL_chained_fixups);3572  DyldInfo = InputArgs.hasArg(OTOOL_dyld_info);3573 3574  InputFilenames = InputArgs.getAllArgValues(OTOOL_INPUT);3575  if (InputFilenames.empty())3576    reportCmdLineError("no input file");3577 3578  for (const Arg *A : InputArgs) {3579    const Option &O = A->getOption();3580    if (O.getGroup().isValid() && O.getGroup().getID() == OTOOL_grp_obsolete) {3581      reportCmdLineWarning(O.getPrefixedName() +3582                           " is obsolete and not implemented");3583    }3584  }3585}3586 3587static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {3588  parseIntArg(InputArgs, OBJDUMP_adjust_vma_EQ, AdjustVMA);3589  AllHeaders = InputArgs.hasArg(OBJDUMP_all_headers);3590  ArchName = InputArgs.getLastArgValue(OBJDUMP_arch_name_EQ).str();3591  ArchiveHeaders = InputArgs.hasArg(OBJDUMP_archive_headers);3592  Demangle = InputArgs.hasArg(OBJDUMP_demangle);3593  Disassemble = InputArgs.hasArg(OBJDUMP_disassemble);3594  DisassembleAll = InputArgs.hasArg(OBJDUMP_disassemble_all);3595  SymbolDescription = InputArgs.hasArg(OBJDUMP_symbol_description);3596  TracebackTable = InputArgs.hasArg(OBJDUMP_traceback_table);3597  DisassembleSymbols =3598      commaSeparatedValues(InputArgs, OBJDUMP_disassemble_symbols_EQ);3599  DisassembleZeroes = InputArgs.hasArg(OBJDUMP_disassemble_zeroes);3600  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_dwarf_EQ)) {3601    DwarfDumpType = StringSwitch<DIDumpType>(A->getValue())3602                        .Case("frames", DIDT_DebugFrame)3603                        .Default(DIDT_Null);3604    if (DwarfDumpType == DIDT_Null)3605      invalidArgValue(A);3606  }3607  DynamicRelocations = InputArgs.hasArg(OBJDUMP_dynamic_reloc);3608  FaultMapSection = InputArgs.hasArg(OBJDUMP_fault_map_section);3609  Offloading = InputArgs.hasArg(OBJDUMP_offloading);3610  FileHeaders = InputArgs.hasArg(OBJDUMP_file_headers);3611  SectionContents = InputArgs.hasArg(OBJDUMP_full_contents);3612  PrintLines = InputArgs.hasArg(OBJDUMP_line_numbers);3613  InputFilenames = InputArgs.getAllArgValues(OBJDUMP_INPUT);3614  MachOOpt = InputArgs.hasArg(OBJDUMP_macho);3615  MCPU = InputArgs.getLastArgValue(OBJDUMP_mcpu_EQ).str();3616  MAttrs = commaSeparatedValues(InputArgs, OBJDUMP_mattr_EQ);3617  ShowRawInsn = !InputArgs.hasArg(OBJDUMP_no_show_raw_insn);3618  LeadingAddr = !InputArgs.hasArg(OBJDUMP_no_leading_addr);3619  RawClangAST = InputArgs.hasArg(OBJDUMP_raw_clang_ast);3620  Relocations = InputArgs.hasArg(OBJDUMP_reloc);3621  PrintImmHex =3622      InputArgs.hasFlag(OBJDUMP_print_imm_hex, OBJDUMP_no_print_imm_hex, true);3623  PrivateHeaders = InputArgs.hasArg(OBJDUMP_private_headers);3624  FilterSections = InputArgs.getAllArgValues(OBJDUMP_section_EQ);3625  SectionHeaders = InputArgs.hasArg(OBJDUMP_section_headers);3626  ShowAllSymbols = InputArgs.hasArg(OBJDUMP_show_all_symbols);3627  ShowLMA = InputArgs.hasArg(OBJDUMP_show_lma);3628  PrintSource = InputArgs.hasArg(OBJDUMP_source);3629  parseIntArg(InputArgs, OBJDUMP_start_address_EQ, StartAddress);3630  HasStartAddressFlag = InputArgs.hasArg(OBJDUMP_start_address_EQ);3631  parseIntArg(InputArgs, OBJDUMP_stop_address_EQ, StopAddress);3632  HasStopAddressFlag = InputArgs.hasArg(OBJDUMP_stop_address_EQ);3633  SymbolTable = InputArgs.hasArg(OBJDUMP_syms);3634  SymbolizeOperands = InputArgs.hasArg(OBJDUMP_symbolize_operands);3635  PrettyPGOAnalysisMap = InputArgs.hasArg(OBJDUMP_pretty_pgo_analysis_map);3636  if (PrettyPGOAnalysisMap && !SymbolizeOperands)3637    reportCmdLineWarning("--symbolize-operands must be enabled for "3638                         "--pretty-pgo-analysis-map to have an effect");3639  DynamicSymbolTable = InputArgs.hasArg(OBJDUMP_dynamic_syms);3640  TripleName = InputArgs.getLastArgValue(OBJDUMP_triple_EQ).str();3641  UnwindInfo = InputArgs.hasArg(OBJDUMP_unwind_info);3642  Wide = InputArgs.hasArg(OBJDUMP_wide);3643  Prefix = InputArgs.getLastArgValue(OBJDUMP_prefix).str();3644  parseIntArg(InputArgs, OBJDUMP_prefix_strip, PrefixStrip);3645  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_debug_vars_EQ)) {3646    DbgVariables = StringSwitch<DebugFormat>(A->getValue())3647                       .Case("ascii", DFASCII)3648                       .Case("unicode", DFUnicode)3649                       .Default(DFInvalid);3650    if (DbgVariables == DFInvalid)3651      invalidArgValue(A);3652  }3653 3654  if (const opt::Arg *A =3655          InputArgs.getLastArg(OBJDUMP_debug_inlined_funcs_EQ)) {3656    DbgInlinedFunctions = StringSwitch<DebugFormat>(A->getValue())3657                              .Case("ascii", DFASCII)3658                              .Case("limits-only", DFLimitsOnly)3659                              .Case("unicode", DFUnicode)3660                              .Default(DFInvalid);3661    if (DbgInlinedFunctions == DFInvalid)3662      invalidArgValue(A);3663  }3664 3665  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_disassembler_color_EQ)) {3666    DisassemblyColor = StringSwitch<ColorOutput>(A->getValue())3667                           .Case("on", ColorOutput::Enable)3668                           .Case("off", ColorOutput::Disable)3669                           .Case("terminal", ColorOutput::Auto)3670                           .Default(ColorOutput::Invalid);3671    if (DisassemblyColor == ColorOutput::Invalid)3672      invalidArgValue(A);3673  }3674 3675  parseIntArg(InputArgs, OBJDUMP_debug_indent_EQ, DbgIndent);3676 3677  parseMachOOptions(InputArgs);3678 3679  // Parse -M (--disassembler-options) and deprecated3680  // --x86-asm-syntax={att,intel}.3681  //3682  // Note, for x86, the asm dialect (AssemblerDialect) is initialized when the3683  // MCAsmInfo is constructed. MCInstPrinter::applyTargetSpecificCLOption is3684  // called too late. For now we have to use the internal cl::opt option.3685  const char *AsmSyntax = nullptr;3686  for (const auto *A : InputArgs.filtered(OBJDUMP_disassembler_options_EQ,3687                                          OBJDUMP_x86_asm_syntax_att,3688                                          OBJDUMP_x86_asm_syntax_intel)) {3689    switch (A->getOption().getID()) {3690    case OBJDUMP_x86_asm_syntax_att:3691      AsmSyntax = "--x86-asm-syntax=att";3692      continue;3693    case OBJDUMP_x86_asm_syntax_intel:3694      AsmSyntax = "--x86-asm-syntax=intel";3695      continue;3696    }3697 3698    SmallVector<StringRef, 2> Values;3699    llvm::SplitString(A->getValue(), Values, ",");3700    for (StringRef V : Values) {3701      if (V == "att")3702        AsmSyntax = "--x86-asm-syntax=att";3703      else if (V == "intel")3704        AsmSyntax = "--x86-asm-syntax=intel";3705      else3706        DisassemblerOptions.push_back(V.str());3707    }3708  }3709  SmallVector<const char *> Args = {"llvm-objdump"};3710  for (const opt::Arg *A : InputArgs.filtered(OBJDUMP_mllvm))3711    Args.push_back(A->getValue());3712  if (AsmSyntax)3713    Args.push_back(AsmSyntax);3714  if (Args.size() > 1)3715    llvm::cl::ParseCommandLineOptions(Args.size(), Args.data());3716 3717  // Look up any provided build IDs, then append them to the input filenames.3718  for (const opt::Arg *A : InputArgs.filtered(OBJDUMP_build_id)) {3719    object::BuildID BuildID = parseBuildIDArg(A);3720    std::optional<std::string> Path = BIDFetcher->fetch(BuildID);3721    if (!Path) {3722      reportCmdLineError(A->getSpelling() + ": could not find build ID '" +3723                         A->getValue() + "'");3724    }3725    InputFilenames.push_back(std::move(*Path));3726  }3727 3728  // objdump defaults to a.out if no filenames specified.3729  if (InputFilenames.empty())3730    InputFilenames.push_back("a.out");3731}3732 3733int llvm_objdump_main(int argc, char **argv, const llvm::ToolContext &) {3734  using namespace llvm;3735 3736  ToolName = argv[0];3737  std::unique_ptr<CommonOptTable> T;3738  OptSpecifier Unknown, HelpFlag, HelpHiddenFlag, VersionFlag;3739 3740  StringRef Stem = sys::path::stem(ToolName);3741  auto Is = [=](StringRef Tool) {3742    // We need to recognize the following filenames:3743    //3744    // llvm-objdump -> objdump3745    // llvm-otool-10.exe -> otool3746    // powerpc64-unknown-freebsd13-objdump -> objdump3747    auto I = Stem.rfind_insensitive(Tool);3748    return I != StringRef::npos &&3749           (I + Tool.size() == Stem.size() || !isAlnum(Stem[I + Tool.size()]));3750  };3751  if (Is("otool")) {3752    T = std::make_unique<OtoolOptTable>();3753    Unknown = OTOOL_UNKNOWN;3754    HelpFlag = OTOOL_help;3755    HelpHiddenFlag = OTOOL_help_hidden;3756    VersionFlag = OTOOL_version;3757  } else {3758    T = std::make_unique<ObjdumpOptTable>();3759    Unknown = OBJDUMP_UNKNOWN;3760    HelpFlag = OBJDUMP_help;3761    HelpHiddenFlag = OBJDUMP_help_hidden;3762    VersionFlag = OBJDUMP_version;3763  }3764 3765  BumpPtrAllocator A;3766  StringSaver Saver(A);3767  opt::InputArgList InputArgs =3768      T->parseArgs(argc, argv, Unknown, Saver,3769                   [&](StringRef Msg) { reportCmdLineError(Msg); });3770 3771  if (InputArgs.size() == 0 || InputArgs.hasArg(HelpFlag)) {3772    T->printHelp(ToolName);3773    return 0;3774  }3775  if (InputArgs.hasArg(HelpHiddenFlag)) {3776    T->printHelp(ToolName, /*ShowHidden=*/true);3777    return 0;3778  }3779 3780  // Initialize targets and assembly printers/parsers.3781  InitializeAllTargetInfos();3782  InitializeAllTargetMCs();3783  InitializeAllDisassemblers();3784 3785  if (InputArgs.hasArg(VersionFlag)) {3786    cl::PrintVersionMessage();3787    if (!Is("otool")) {3788      outs() << '\n';3789      TargetRegistry::printRegisteredTargetsForVersion(outs());3790    }3791    return 0;3792  }3793 3794  // Initialize debuginfod.3795  const bool ShouldUseDebuginfodByDefault =3796      InputArgs.hasArg(OBJDUMP_build_id) || canUseDebuginfod();3797  std::vector<std::string> DebugFileDirectories =3798      InputArgs.getAllArgValues(OBJDUMP_debug_file_directory);3799  if (InputArgs.hasFlag(OBJDUMP_debuginfod, OBJDUMP_no_debuginfod,3800                        ShouldUseDebuginfodByDefault)) {3801    HTTPClient::initialize();3802    BIDFetcher =3803        std::make_unique<DebuginfodFetcher>(std::move(DebugFileDirectories));3804  } else {3805    BIDFetcher =3806        std::make_unique<BuildIDFetcher>(std::move(DebugFileDirectories));3807  }3808 3809  if (Is("otool"))3810    parseOtoolOptions(InputArgs);3811  else3812    parseObjdumpOptions(InputArgs);3813 3814  if (StartAddress >= StopAddress)3815    reportCmdLineError("start address should be less than stop address");3816 3817  // Removes trailing separators from prefix.3818  while (!Prefix.empty() && sys::path::is_separator(Prefix.back()))3819    Prefix.pop_back();3820 3821  if (AllHeaders)3822    ArchiveHeaders = FileHeaders = PrivateHeaders = Relocations =3823        SectionHeaders = SymbolTable = true;3824 3825  if (DisassembleAll || PrintSource || PrintLines || TracebackTable ||3826      !DisassembleSymbols.empty())3827    Disassemble = true;3828 3829  if (!ArchiveHeaders && !Disassemble && DwarfDumpType == DIDT_Null &&3830      !DynamicRelocations && !FileHeaders && !PrivateHeaders && !RawClangAST &&3831      !Relocations && !SectionHeaders && !SectionContents && !SymbolTable &&3832      !DynamicSymbolTable && !UnwindInfo && !FaultMapSection && !Offloading &&3833      !(MachOOpt &&3834        (Bind || DataInCode || ChainedFixups || DyldInfo || DylibId ||3835         DylibsUsed || ExportsTrie || FirstPrivateHeader ||3836         FunctionStartsType != FunctionStartsMode::None || IndirectSymbols ||3837         InfoPlist || LazyBind || LinkOptHints || ObjcMetaData || Rebase ||3838         Rpaths || UniversalHeaders || WeakBind || !FilterSections.empty()))) {3839    T->printHelp(ToolName);3840    return 2;3841  }3842 3843  DisasmSymbolSet.insert_range(DisassembleSymbols);3844 3845  llvm::for_each(InputFilenames, dumpInput);3846 3847  warnOnNoMatchForSections();3848 3849  return EXIT_SUCCESS;3850}3851