brintos

brintos / llvm-project-archived public Read only

0
0
Text · 49.5 KiB · 03764e9 Raw
1252 lines · cpp
1//===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//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 file implements an XCOFF specific dumper for llvm-readobj.10//11//===----------------------------------------------------------------------===//12 13#include "ObjDumper.h"14#include "llvm-readobj.h"15#include "llvm/Demangle/Demangle.h"16#include "llvm/Object/XCOFFObjectFile.h"17#include "llvm/Support/FormattedStream.h"18#include "llvm/Support/ScopedPrinter.h"19 20#include <ctime>21 22using namespace llvm;23using namespace object;24 25namespace {26 27class XCOFFDumper : public ObjDumper {28 29public:30  XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)31      : ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {}32 33  void printFileHeaders() override;34  void printAuxiliaryHeader() override;35  void printSectionHeaders() override;36  void printRelocations() override;37  void printSymbols(bool ExtraSymInfo) override;38  void printDynamicSymbols() override;39  void printUnwindInfo() override;40  void printStackMap() const override;41  void printNeededLibraries() override;42  void printStringTable() override;43  void printExceptionSection() override;44  void printLoaderSection(bool PrintHeader, bool PrintSymbols,45                          bool PrintRelocations) override;46 47  ScopedPrinter &getScopedPrinter() const { return W; }48 49private:50  template <typename T> void printSectionHeaders(ArrayRef<T> Sections);51  template <typename T> void printGenericSectionHeader(T &Sec) const;52  template <typename T> void printOverflowSectionHeader(T &Sec) const;53  template <typename T>54  void printExceptionSectionEntry(const T &ExceptionSectEnt) const;55  template <typename T> void printExceptionSectionEntries() const;56  template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress);57  void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);58  void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);59  void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);60  void printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr);61  void printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr);62  void printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr);63  void printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr);64  void printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr);65  template <typename T> void printSectAuxEntForDWARF(const T *AuxEntPtr);66  void printSymbol(const SymbolRef &);67  template <typename RelTy> void printRelocation(RelTy Reloc);68  template <typename Shdr, typename RelTy>69  void printRelocations(ArrayRef<Shdr> Sections);70  void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);71  void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);72  void printLoaderSectionHeader(uintptr_t LoaderSectAddr);73  void printLoaderSectionSymbols(uintptr_t LoaderSectAddr);74  template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>75  void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr);76  template <typename LoadSectionRelocTy>77  void printLoaderSectionRelocationEntry(LoadSectionRelocTy *LoaderSecRelEntPtr,78                                         StringRef SymbolName);79  void printLoaderSectionRelocationEntries(uintptr_t LoaderSectAddr);80  template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,81            typename LoaderSectionRelocationEntry>82  void printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectAddr);83 84  const XCOFFObjectFile &Obj;85  const static int32_t FirstSymIdxOfLoaderSec = 3;86};87} // anonymous namespace88 89void XCOFFDumper::printFileHeaders() {90  DictScope DS(W, "FileHeader");91  W.printHex("Magic", Obj.getMagic());92  W.printNumber("NumberOfSections", Obj.getNumberOfSections());93 94  // Negative timestamp values are reserved for future use.95  int32_t TimeStamp = Obj.getTimeStamp();96  if (TimeStamp > 0) {97    // This handling of the time stamp assumes that the host system's time_t is98    // compatible with AIX time_t. If a platform is not compatible, the lit99    // tests will let us know.100    time_t TimeDate = TimeStamp;101 102    char FormattedTime[80] = {};103 104    size_t BytesFormatted =105      strftime(FormattedTime, sizeof(FormattedTime), "%F %T", gmtime(&TimeDate));106    if (BytesFormatted)107      W.printHex("TimeStamp", FormattedTime, TimeStamp);108    else109      W.printHex("Timestamp", TimeStamp);110  } else {111    W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",112               TimeStamp);113  }114 115  // The number of symbol table entries is an unsigned value in 64-bit objects116  // and a signed value (with negative values being 'reserved') in 32-bit117  // objects.118  if (Obj.is64Bit()) {119    W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());120    W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());121  } else {122    W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());123    int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();124    if (SymTabEntries >= 0)125      W.printNumber("SymbolTableEntries", SymTabEntries);126    else127      W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);128  }129 130  W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());131  W.printHex("Flags", Obj.getFlags());132 133  // TODO FIXME Add support for the auxiliary header (if any) once134  // XCOFFObjectFile has the necessary support.135}136 137void XCOFFDumper::printAuxiliaryHeader() {138  DictScope DS(W, "AuxiliaryHeader");139 140  if (Obj.is64Bit())141    printAuxiliaryHeader(Obj.auxiliaryHeader64());142  else143    printAuxiliaryHeader(Obj.auxiliaryHeader32());144}145 146void XCOFFDumper::printSectionHeaders() {147  if (Obj.is64Bit())148    printSectionHeaders(Obj.sections64());149  else150    printSectionHeaders(Obj.sections32());151}152 153void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbols,154                                     bool PrintRelocations) {155  DictScope DS(W, "Loader Section");156  Expected<uintptr_t> LoaderSectionAddrOrError =157      Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);158  if (!LoaderSectionAddrOrError) {159    reportUniqueWarning(LoaderSectionAddrOrError.takeError());160    return;161  }162  uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();163 164  if (LoaderSectionAddr == 0)165    return;166 167  W.indent();168  if (PrintHeader)169    printLoaderSectionHeader(LoaderSectionAddr);170 171  if (PrintSymbols)172    printLoaderSectionSymbols(LoaderSectionAddr);173 174  if (PrintRelocations)175    printLoaderSectionRelocationEntries(LoaderSectionAddr);176 177  W.unindent();178}179 180void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr) {181  DictScope DS(W, "Loader Section Header");182 183  auto PrintLoadSecHeaderCommon = [&](const auto *LDHeader) {184    W.printNumber("Version", LDHeader->Version);185    W.printNumber("NumberOfSymbolEntries", LDHeader->NumberOfSymTabEnt);186    W.printNumber("NumberOfRelocationEntries", LDHeader->NumberOfRelTabEnt);187    W.printNumber("LengthOfImportFileIDStringTable",188                  LDHeader->LengthOfImpidStrTbl);189    W.printNumber("NumberOfImportFileIDs", LDHeader->NumberOfImpid);190    W.printHex("OffsetToImportFileIDs", LDHeader->OffsetToImpid);191    W.printNumber("LengthOfStringTable", LDHeader->LengthOfStrTbl);192    W.printHex("OffsetToStringTable", LDHeader->OffsetToStrTbl);193  };194 195  if (Obj.is64Bit()) {196    const LoaderSectionHeader64 *LoaderSec64 =197        reinterpret_cast<const LoaderSectionHeader64 *>(LoaderSectionAddr);198    PrintLoadSecHeaderCommon(LoaderSec64);199    W.printHex("OffsetToSymbolTable", LoaderSec64->OffsetToSymTbl);200    W.printHex("OffsetToRelocationEntries", LoaderSec64->OffsetToRelEnt);201  } else {202    const LoaderSectionHeader32 *LoaderSec32 =203        reinterpret_cast<const LoaderSectionHeader32 *>(LoaderSectionAddr);204    PrintLoadSecHeaderCommon(LoaderSec32);205  }206}207 208const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {209#define ECase(X)                                                               \210  { #X, XCOFF::X }211    ECase(C_NULL),  ECase(C_AUTO),    ECase(C_EXT),     ECase(C_STAT),212    ECase(C_REG),   ECase(C_EXTDEF),  ECase(C_LABEL),   ECase(C_ULABEL),213    ECase(C_MOS),   ECase(C_ARG),     ECase(C_STRTAG),  ECase(C_MOU),214    ECase(C_UNTAG), ECase(C_TPDEF),   ECase(C_USTATIC), ECase(C_ENTAG),215    ECase(C_MOE),   ECase(C_REGPARM), ECase(C_FIELD),   ECase(C_BLOCK),216    ECase(C_FCN),   ECase(C_EOS),     ECase(C_FILE),    ECase(C_LINE),217    ECase(C_ALIAS), ECase(C_HIDDEN),  ECase(C_HIDEXT),  ECase(C_BINCL),218    ECase(C_EINCL), ECase(C_INFO),    ECase(C_WEAKEXT), ECase(C_DWARF),219    ECase(C_GSYM),  ECase(C_LSYM),    ECase(C_PSYM),    ECase(C_RSYM),220    ECase(C_RPSYM), ECase(C_STSYM),   ECase(C_TCSYM),   ECase(C_BCOMM),221    ECase(C_ECOML), ECase(C_ECOMM),   ECase(C_DECL),    ECase(C_ENTRY),222    ECase(C_FUN),   ECase(C_BSTAT),   ECase(C_ESTAT),   ECase(C_GTLS),223    ECase(C_STTLS), ECase(C_EFCN)224#undef ECase225};226 227template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>228void XCOFFDumper::printLoaderSectionSymbolsHelper(uintptr_t LoaderSectionAddr) {229  const LoaderSectionHeader *LoadSecHeader =230      reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);231  const LoaderSectionSymbolEntry *LoadSecSymEntPtr =232      reinterpret_cast<LoaderSectionSymbolEntry *>(233          LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()));234 235  for (uint32_t i = 0; i < LoadSecHeader->NumberOfSymTabEnt;236       ++i, ++LoadSecSymEntPtr) {237    if (Error E = Binary::checkOffset(238            Obj.getMemoryBufferRef(),239            LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()) +240                (i * sizeof(LoaderSectionSymbolEntry)),241            sizeof(LoaderSectionSymbolEntry))) {242      reportUniqueWarning(std::move(E));243      return;244    }245 246    Expected<StringRef> SymbolNameOrErr =247        LoadSecSymEntPtr->getSymbolName(LoadSecHeader);248    if (!SymbolNameOrErr) {249      reportUniqueWarning(SymbolNameOrErr.takeError());250      return;251    }252 253    DictScope DS(W, "Symbol");254    StringRef SymbolName = SymbolNameOrErr.get();255    W.printString("Name", opts::Demangle ? demangle(SymbolName) : SymbolName);256    W.printHex("Virtual Address", LoadSecSymEntPtr->Value);257    W.printNumber("SectionNum", LoadSecSymEntPtr->SectionNumber);258    W.printHex("SymbolType", LoadSecSymEntPtr->SymbolType);259    W.printEnum("StorageClass",260                static_cast<uint8_t>(LoadSecSymEntPtr->StorageClass),261                ArrayRef(SymStorageClass));262    W.printHex("ImportFileID", LoadSecSymEntPtr->ImportFileID);263    W.printNumber("ParameterTypeCheck", LoadSecSymEntPtr->ParameterTypeCheck);264  }265}266 267void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr) {268  DictScope DS(W, "Loader Section Symbols");269  if (Obj.is64Bit())270    printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry64,271                                    LoaderSectionHeader64>(LoaderSectionAddr);272  else273    printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry32,274                                    LoaderSectionHeader32>(LoaderSectionAddr);275}276 277const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {278#define ECase(X)                                                               \279  { #X, XCOFF::X }280    ECase(R_POS),    ECase(R_RL),     ECase(R_RLA),    ECase(R_NEG),281    ECase(R_REL),    ECase(R_TOC),    ECase(R_TRL),    ECase(R_TRLA),282    ECase(R_GL),     ECase(R_TCL),    ECase(R_REF),    ECase(R_BA),283    ECase(R_BR),     ECase(R_RBA),    ECase(R_RBR),    ECase(R_TLS),284    ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),285    ECase(R_TLSML),  ECase(R_TOCU),   ECase(R_TOCL)286#undef ECase287};288 289// From the XCOFF specification: there are five implicit external symbols, one290// each for the .text, .data, .bss, .tdata, and .tbss sections. These symbols291// are referenced from the relocation table entries using symbol table index292// values 0, 1, 2, -1, and -2, respectively.293static const char *getImplicitLoaderSectionSymName(int SymIndx) {294  switch (SymIndx) {295  default:296    return "Unkown Symbol Name";297  case -2:298    return ".tbss";299  case -1:300    return ".tdata";301  case 0:302    return ".text";303  case 1:304    return ".data";305  case 2:306    return ".bss";307  }308}309 310template <typename LoadSectionRelocTy>311void XCOFFDumper::printLoaderSectionRelocationEntry(312    LoadSectionRelocTy *LoaderSecRelEntPtr, StringRef SymbolName) {313  uint16_t Type = LoaderSecRelEntPtr->Type;314  if (opts::ExpandRelocs) {315    DictScope DS(W, "Relocation");316    auto IsRelocationSigned = [](uint8_t Info) {317      return Info & XCOFF::XR_SIGN_INDICATOR_MASK;318    };319    auto IsFixupIndicated = [](uint8_t Info) {320      return Info & XCOFF::XR_FIXUP_INDICATOR_MASK;321    };322    auto GetRelocatedLength = [](uint8_t Info) {323      // The relocation encodes the bit length being relocated minus 1. Add324      // back325      //   the 1 to get the actual length being relocated.326      return (Info & XCOFF::XR_BIASED_LENGTH_MASK) + 1;327    };328 329    uint8_t Info = Type >> 8;330    W.printHex("Virtual Address", LoaderSecRelEntPtr->VirtualAddr);331    W.printNumber("Symbol", opts::Demangle ? demangle(SymbolName) : SymbolName,332                  LoaderSecRelEntPtr->SymbolIndex);333    W.printString("IsSigned", IsRelocationSigned(Info) ? "Yes" : "No");334    W.printNumber("FixupBitValue", IsFixupIndicated(Info) ? 1 : 0);335    W.printNumber("Length", GetRelocatedLength(Info));336    W.printEnum("Type", static_cast<uint8_t>(Type),337                ArrayRef(RelocationTypeNameclass));338    W.printNumber("SectionNumber", LoaderSecRelEntPtr->SectionNum);339  } else {340    W.startLine() << format_hex(LoaderSecRelEntPtr->VirtualAddr,341                                Obj.is64Bit() ? 18 : 10)342                  << " " << format_hex(Type, 6) << " ("343                  << XCOFF::getRelocationTypeString(344                         static_cast<XCOFF::RelocationType>(Type))345                  << ")" << format_decimal(LoaderSecRelEntPtr->SectionNum, 8)346                  << "    "347                  << (opts::Demangle ? demangle(SymbolName) : SymbolName)348                  << " (" << LoaderSecRelEntPtr->SymbolIndex << ")\n";349  }350}351 352template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,353          typename LoaderSectionRelocationEntry>354void XCOFFDumper::printLoaderSectionRelocationEntriesHelper(355    uintptr_t LoaderSectionAddr) {356  const LoaderSectionHeader *LoaderSec =357      reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);358  const LoaderSectionRelocationEntry *LoaderSecRelEntPtr =359      reinterpret_cast<const LoaderSectionRelocationEntry *>(360          LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToRelEnt()));361 362  if (!opts::ExpandRelocs)363    W.startLine() << center_justify("Vaddr", Obj.is64Bit() ? 18 : 10)364                  << center_justify("Type", 15) << right_justify("SecNum", 8)365                  << center_justify("SymbolName (Index) ", 24) << "\n";366 367  for (uint32_t i = 0; i < LoaderSec->NumberOfRelTabEnt;368       ++i, ++LoaderSecRelEntPtr) {369    StringRef SymbolName;370    if (LoaderSecRelEntPtr->SymbolIndex >= FirstSymIdxOfLoaderSec) {371      // Because there are implicit symbol index values (-2, -1, 0, 1, 2),372      // LoaderSecRelEnt.SymbolIndex - FirstSymIdxOfLoaderSec will get the373      // real symbol from the symbol table.374      const uint64_t SymOffset =375          (LoaderSecRelEntPtr->SymbolIndex - FirstSymIdxOfLoaderSec) *376          sizeof(LoaderSectionSymbolEntry);377      const LoaderSectionSymbolEntry *LoaderSecRelSymEntPtr =378          reinterpret_cast<LoaderSectionSymbolEntry *>(379              LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToSymTbl()) +380              SymOffset);381 382      Expected<StringRef> SymbolNameOrErr =383          LoaderSecRelSymEntPtr->getSymbolName(LoaderSec);384      if (!SymbolNameOrErr) {385        reportUniqueWarning(SymbolNameOrErr.takeError());386        return;387      }388      SymbolName = SymbolNameOrErr.get();389    } else390      SymbolName =391          getImplicitLoaderSectionSymName(LoaderSecRelEntPtr->SymbolIndex);392 393    printLoaderSectionRelocationEntry(LoaderSecRelEntPtr, SymbolName);394  }395}396 397void XCOFFDumper::printLoaderSectionRelocationEntries(398    uintptr_t LoaderSectionAddr) {399  DictScope DS(W, "Loader Section Relocations");400 401  if (Obj.is64Bit())402    printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader64,403                                              LoaderSectionSymbolEntry64,404                                              LoaderSectionRelocationEntry64>(405        LoaderSectionAddr);406  else407    printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader32,408                                              LoaderSectionSymbolEntry32,409                                              LoaderSectionRelocationEntry32>(410        LoaderSectionAddr);411}412 413template <typename T>414void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const {415  if (ExceptionSectEnt.getReason())416    W.printHex("Trap Instr Addr", ExceptionSectEnt.getTrapInstAddr());417  else {418    uint32_t SymIdx = ExceptionSectEnt.getSymbolIndex();419    Expected<StringRef> ErrOrSymbolName = Obj.getSymbolNameByIndex(SymIdx);420    if (Error E = ErrOrSymbolName.takeError()) {421      reportUniqueWarning(std::move(E));422      return;423    }424    StringRef SymName = *ErrOrSymbolName;425 426    W.printNumber("Symbol", SymName, SymIdx);427  }428  W.printNumber("LangID", ExceptionSectEnt.getLangID());429  W.printNumber("Reason", ExceptionSectEnt.getReason());430}431 432template <typename T> void XCOFFDumper::printExceptionSectionEntries() const {433  Expected<ArrayRef<T>> ExceptSectEntsOrErr = Obj.getExceptionEntries<T>();434  if (Error E = ExceptSectEntsOrErr.takeError()) {435    reportUniqueWarning(std::move(E));436    return;437  }438  ArrayRef<T> ExceptSectEnts = *ExceptSectEntsOrErr;439 440  DictScope DS(W, "Exception section");441  if (ExceptSectEnts.empty())442    return;443  for (auto &Ent : ExceptSectEnts)444    printExceptionSectionEntry(Ent);445}446 447void XCOFFDumper::printExceptionSection() {448  if (Obj.is64Bit())449    printExceptionSectionEntries<ExceptionSectionEntry64>();450  else451    printExceptionSectionEntries<ExceptionSectionEntry32>();452}453 454void XCOFFDumper::printRelocations() {455  if (Obj.is64Bit())456    printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64());457  else458    printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32());459}460 461template <typename RelTy> void XCOFFDumper::printRelocation(RelTy Reloc) {462  Expected<StringRef> ErrOrSymbolName =463      Obj.getSymbolNameByIndex(Reloc.SymbolIndex);464  if (Error E = ErrOrSymbolName.takeError()) {465    reportUniqueWarning(std::move(E));466    return;467  }468  StringRef SymbolName = *ErrOrSymbolName;469  StringRef RelocName = XCOFF::getRelocationTypeString(Reloc.Type);470  if (opts::ExpandRelocs) {471    DictScope Group(W, "Relocation");472    W.printHex("Virtual Address", Reloc.VirtualAddress);473    W.printNumber("Symbol", opts::Demangle ? demangle(SymbolName) : SymbolName,474                  Reloc.SymbolIndex);475    W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");476    W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);477    W.printNumber("Length", Reloc.getRelocatedLength());478    W.printEnum("Type", (uint8_t)Reloc.Type, ArrayRef(RelocationTypeNameclass));479  } else {480    raw_ostream &OS = W.startLine();481    OS << W.hex(Reloc.VirtualAddress) << " " << RelocName << " "482       << (opts::Demangle ? demangle(SymbolName) : SymbolName) << "("483       << Reloc.SymbolIndex << ") " << W.hex(Reloc.Info) << "\n";484  }485}486 487template <typename Shdr, typename RelTy>488void XCOFFDumper::printRelocations(ArrayRef<Shdr> Sections) {489  ListScope LS(W, "Relocations");490  uint16_t Index = 0;491  for (const Shdr &Sec : Sections) {492    ++Index;493    // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.494    if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&495        Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)496      continue;497    Expected<ArrayRef<RelTy>> ErrOrRelocations = Obj.relocations<Shdr, RelTy>(Sec);498    if (Error E = ErrOrRelocations.takeError()) {499      reportUniqueWarning(std::move(E));500      continue;501    }502 503    const ArrayRef<RelTy> Relocations = *ErrOrRelocations;504    if (Relocations.empty())505      continue;506 507    W.startLine() << "Section (index: " << Index << ") " << Sec.getName()508                  << " {\n";509    W.indent();510 511    for (const RelTy Reloc : Relocations)512      printRelocation(Reloc);513 514    W.unindent();515    W.startLine() << "}\n";516  }517}518 519const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {520#define ECase(X)                                                               \521  { #X, XCOFF::X }522    ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)523#undef ECase524};525 526const EnumEntry<XCOFF::SymbolAuxType> SymAuxType[] = {527#define ECase(X)                                                               \528  { #X, XCOFF::X }529    ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE),530    ECase(AUX_CSECT),  ECase(AUX_SECT)531#undef ECase532};533 534void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {535  assert((!Obj.is64Bit() || AuxEntPtr->AuxType == XCOFF::AUX_FILE) &&536         "Mismatched auxiliary type!");537  StringRef FileName =538      unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));539  DictScope SymDs(W, "File Auxiliary Entry");540  W.printNumber("Index",541                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));542  W.printString("Name", FileName);543  W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),544              ArrayRef(FileStringType));545  if (Obj.is64Bit()) {546    W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),547                ArrayRef(SymAuxType));548  }549}550 551static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =552    {553#define ECase(X)                                                               \554  { #X, XCOFF::X }555        ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB),   ECase(XMC_GL),556        ECase(XMC_XO), ECase(XMC_SV), ECase(XMC_SV64), ECase(XMC_SV3264),557        ECase(XMC_TI), ECase(XMC_TB), ECase(XMC_RW),   ECase(XMC_TC0),558        ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS),   ECase(XMC_UA),559        ECase(XMC_BS), ECase(XMC_UC), ECase(XMC_TL),   ECase(XMC_UL),560        ECase(XMC_TE)561#undef ECase562};563 564const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {565#define ECase(X)                                                               \566  { #X, XCOFF::X }567    ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)568#undef ECase569};570 571void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) {572  assert((!Obj.is64Bit() || AuxEntRef.getAuxType64() == XCOFF::AUX_CSECT) &&573         "Mismatched auxiliary type!");574 575  DictScope SymDs(W, "CSECT Auxiliary Entry");576  W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getEntryAddress()));577  W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex"578                                    : "SectionLen",579                AuxEntRef.getSectionOrLength());580  W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex());581  W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum());582  // Print out symbol alignment and type.583  W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2());584  W.printEnum("SymbolType", AuxEntRef.getSymbolType(),585              ArrayRef(CsectSymbolTypeClass));586  W.printEnum("StorageMappingClass",587              static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()),588              ArrayRef(CsectStorageMappingClass));589 590  if (Obj.is64Bit()) {591    W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT),592                ArrayRef(SymAuxType));593  } else {594    W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32());595    W.printHex("StabSectNum", AuxEntRef.getStabSectNum32());596  }597}598 599void XCOFFDumper::printSectAuxEntForStat(600    const XCOFFSectAuxEntForStat *AuxEntPtr) {601  assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");602 603  DictScope SymDs(W, "Sect Auxiliary Entry For Stat");604  W.printNumber("Index",605                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));606  W.printNumber("SectionLength", AuxEntPtr->SectionLength);607 608  // Unlike the corresponding fields in the section header, NumberOfRelocEnt609  // and NumberOfLineNum do not handle values greater than 65535.610  W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);611  W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);612}613 614void XCOFFDumper::printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr) {615  assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");616 617  DictScope SymDs(W, "Exception Auxiliary Entry");618  W.printNumber("Index",619                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));620  W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);621  W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);622  W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);623  W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),624              ArrayRef(SymAuxType));625}626 627void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr) {628  assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");629 630  DictScope SymDs(W, "Function Auxiliary Entry");631  W.printNumber("Index",632                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));633  W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);634  W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);635  W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);636  W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);637}638 639void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr) {640  assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");641 642  DictScope SymDs(W, "Function Auxiliary Entry");643  W.printNumber("Index",644                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));645  W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);646  W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);647  W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);648  W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),649              ArrayRef(SymAuxType));650}651 652void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr) {653  assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");654 655  DictScope SymDs(W, "Block Auxiliary Entry");656  W.printNumber("Index",657                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));658  W.printHex("LineNumber (High 2 Bytes)", AuxEntPtr->LineNumHi);659  W.printHex("LineNumber (Low 2 Bytes)", AuxEntPtr->LineNumLo);660}661 662void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr) {663  assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");664 665  DictScope SymDs(W, "Block Auxiliary Entry");666  W.printNumber("Index",667                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));668  W.printHex("LineNumber", AuxEntPtr->LineNum);669  W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),670              ArrayRef(SymAuxType));671}672 673template <typename T>674void XCOFFDumper::printSectAuxEntForDWARF(const T *AuxEntPtr) {675  DictScope SymDs(W, "Sect Auxiliary Entry For DWARF");676  W.printNumber("Index",677                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));678  W.printHex("LengthOfSectionPortion", AuxEntPtr->LengthOfSectionPortion);679  W.printNumber("NumberOfRelocEntries", AuxEntPtr->NumberOfRelocEnt);680  if (Obj.is64Bit())681    W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_SECT),682                ArrayRef(SymAuxType));683}684 685static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {686  switch (SC) {687  case XCOFF::C_EXT:688  case XCOFF::C_WEAKEXT:689  case XCOFF::C_HIDEXT:690  case XCOFF::C_STAT:691  case XCOFF::C_FCN:692  case XCOFF::C_BLOCK:693    return "Value (RelocatableAddress)";694  case XCOFF::C_FILE:695  case XCOFF::C_BSTAT:696    return "Value (SymbolTableIndex)";697  case XCOFF::C_DWARF:698    return "Value (OffsetInDWARF)";699  case XCOFF::C_FUN:700  case XCOFF::C_STSYM:701    return "Value (OffsetInCSect)";702  case XCOFF::C_BINCL:703  case XCOFF::C_EINCL:704    return "Value (OffsetInFile)";705  case XCOFF::C_INFO:706    return "Value (OffsetInCommentSection)";707  case XCOFF::C_LSYM:708  case XCOFF::C_PSYM:709    return "Value (OffsetRelToStackFrame)";710  case XCOFF::C_RPSYM:711  case XCOFF::C_RSYM:712    return "Value (RegisterNumber)";713  case XCOFF::C_ECOML:714    return "Value (OffsetInCommBlock)";715  default:716    return "Value";717  }718}719 720const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {721#define ECase(X)                                                               \722  { #X, XCOFF::X }723    ECase(TB_C), ECase(TB_Fortran), ECase(TB_CPLUSPLUS)724#undef ECase725};726 727const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {728#define ECase(X)                                                               \729  { #X, XCOFF::X }730    ECase(TCPU_INVALID), ECase(TCPU_PPC),  ECase(TCPU_PPC64), ECase(TCPU_COM),731    ECase(TCPU_PWR),     ECase(TCPU_ANY),  ECase(TCPU_601),   ECase(TCPU_603),732    ECase(TCPU_604),     ECase(TCPU_620),  ECase(TCPU_A35),   ECase(TCPU_970),733    ECase(TCPU_PWR5),    ECase(TCPU_PWR6), ECase(TCPU_PWR5X), ECase(TCPU_PWR6E),734    ECase(TCPU_PWR7),    ECase(TCPU_PWR8), ECase(TCPU_PWR9),  ECase(TCPU_PWR10),735    ECase(TCPU_PWRX)736#undef ECase737};738 739template <typename T> const T *XCOFFDumper::getAuxEntPtr(uintptr_t AuxAddress) {740  const T *AuxEntPtr = reinterpret_cast<const T *>(AuxAddress);741  Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(AuxEntPtr));742  return AuxEntPtr;743}744 745static void printUnexpectedRawAuxEnt(ScopedPrinter &W, uintptr_t AuxAddress) {746  W.startLine() << "!Unexpected raw auxiliary entry data:\n";747  W.startLine() << format_bytes(748                       ArrayRef<uint8_t>(749                           reinterpret_cast<const uint8_t *>(AuxAddress),750                           XCOFF::SymbolTableEntrySize),751                       std::nullopt, XCOFF::SymbolTableEntrySize)752                << "\n";753}754 755void XCOFFDumper::printSymbol(const SymbolRef &S) {756  DataRefImpl SymbolDRI = S.getRawDataRefImpl();757  XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);758 759  uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();760 761  DictScope SymDs(W, "Symbol");762 763  StringRef SymbolName =764      unwrapOrError(Obj.getFileName(), SymbolEntRef.getName());765 766  uint32_t SymbolIdx = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());767  XCOFF::StorageClass SymbolClass = SymbolEntRef.getStorageClass();768 769  W.printNumber("Index", SymbolIdx);770  W.printString("Name", opts::Demangle ? demangle(SymbolName) : SymbolName);771  W.printHex(GetSymbolValueName(SymbolClass), SymbolEntRef.getValue());772 773  StringRef SectionName =774      unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef));775 776  W.printString("Section", SectionName);777  if (SymbolClass == XCOFF::C_FILE) {778    W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(),779                ArrayRef(CFileLangIdClass));780    W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(),781                ArrayRef(CFileCpuIdClass));782  } else783    W.printHex("Type", SymbolEntRef.getSymbolType());784 785  W.printEnum("StorageClass", static_cast<uint8_t>(SymbolClass),786              ArrayRef(SymStorageClass));787  W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries);788 789  if (NumberOfAuxEntries == 0)790    return;791 792  auto checkNumOfAux = [=] {793    if (NumberOfAuxEntries > 1)794      reportUniqueWarning("the " +795                          enumToString(static_cast<uint8_t>(SymbolClass),796                                       ArrayRef(SymStorageClass)) +797                          " symbol at index " + Twine(SymbolIdx) +798                          " should not have more than 1 "799                          "auxiliary entry");800  };801 802  switch (SymbolClass) {803  case XCOFF::C_FILE:804    // If the symbol is C_FILE and has auxiliary entries...805    for (int I = 1; I <= NumberOfAuxEntries; I++) {806      uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(807          SymbolEntRef.getEntryAddress(), I);808 809      if (Obj.is64Bit() &&810          *Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) {811        printUnexpectedRawAuxEnt(W, AuxAddress);812        continue;813      }814 815      const XCOFFFileAuxEnt *FileAuxEntPtr =816          getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress);817      printFileAuxEnt(FileAuxEntPtr);818    }819    break;820  case XCOFF::C_EXT:821  case XCOFF::C_WEAKEXT:822  case XCOFF::C_HIDEXT: {823    // For 32-bit objects, print the function auxiliary symbol table entry. The824    // last one must be a CSECT auxiliary entry.825    // For 64-bit objects, both a function auxiliary entry and an exception826    // auxiliary entry may appear, print them in the loop and skip printing the827    // CSECT auxiliary entry, which will be printed outside the loop.828    for (int I = 1; I <= NumberOfAuxEntries; I++) {829      if (I == NumberOfAuxEntries && !Obj.is64Bit())830        break;831 832      uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(833          SymbolEntRef.getEntryAddress(), I);834 835      if (Obj.is64Bit()) {836        XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress);837        if (Type == XCOFF::SymbolAuxType::AUX_CSECT)838          continue;839        if (Type == XCOFF::SymbolAuxType::AUX_FCN) {840          const XCOFFFunctionAuxEnt64 *AuxEntPtr =841              getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress);842          printFunctionAuxEnt(AuxEntPtr);843        } else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT) {844          const XCOFFExceptionAuxEnt *AuxEntPtr =845              getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress);846          printExceptionAuxEnt(AuxEntPtr);847        } else {848          printUnexpectedRawAuxEnt(W, AuxAddress);849        }850      } else {851        const XCOFFFunctionAuxEnt32 *AuxEntPtr =852            getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress);853        printFunctionAuxEnt(AuxEntPtr);854      }855    }856 857    // Print the CSECT auxiliary entry.858    auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();859    if (!ErrOrCsectAuxRef)860      reportUniqueWarning(ErrOrCsectAuxRef.takeError());861    else862      printCsectAuxEnt(*ErrOrCsectAuxRef);863 864    break;865  }866  case XCOFF::C_STAT: {867    checkNumOfAux();868 869    const XCOFFSectAuxEntForStat *StatAuxEntPtr =870        getAuxEntPtr<XCOFFSectAuxEntForStat>(871            XCOFFObjectFile::getAdvancedSymbolEntryAddress(872                SymbolEntRef.getEntryAddress(), 1));873    printSectAuxEntForStat(StatAuxEntPtr);874    break;875  }876  case XCOFF::C_DWARF: {877    checkNumOfAux();878 879    uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(880        SymbolEntRef.getEntryAddress(), 1);881 882    if (Obj.is64Bit()) {883      const XCOFFSectAuxEntForDWARF64 *AuxEntPtr =884          getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress);885      printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF64>(AuxEntPtr);886    } else {887      const XCOFFSectAuxEntForDWARF32 *AuxEntPtr =888          getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress);889      printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF32>(AuxEntPtr);890    }891    break;892  }893  case XCOFF::C_BLOCK:894  case XCOFF::C_FCN: {895    checkNumOfAux();896 897    uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(898        SymbolEntRef.getEntryAddress(), 1);899 900    if (Obj.is64Bit()) {901      const XCOFFBlockAuxEnt64 *AuxEntPtr =902          getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress);903      printBlockAuxEnt(AuxEntPtr);904    } else {905      const XCOFFBlockAuxEnt32 *AuxEntPtr =906          getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress);907      printBlockAuxEnt(AuxEntPtr);908    }909    break;910  }911  default:912    for (int i = 1; i <= NumberOfAuxEntries; i++) {913      printUnexpectedRawAuxEnt(W,914                               XCOFFObjectFile::getAdvancedSymbolEntryAddress(915                                   SymbolEntRef.getEntryAddress(), i));916    }917    break;918  }919}920 921void XCOFFDumper::printSymbols(bool /*ExtraSymInfo*/) {922  ListScope Group(W, "Symbols");923  for (const SymbolRef &S : Obj.symbols())924    printSymbol(S);925}926 927void XCOFFDumper::printStringTable() {928  DictScope DS(W, "StringTable");929  StringRef StrTable = Obj.getStringTable();930  uint32_t StrTabSize = StrTable.size();931  W.printNumber("Length", StrTabSize);932  // Print strings from the fifth byte, since the first four bytes contain the933  // length (in bytes) of the string table (including the length field).934  if (StrTabSize > 4)935    printAsStringList(StrTable, 4);936}937 938void XCOFFDumper::printDynamicSymbols() {939  llvm_unreachable("Unimplemented functionality for XCOFFDumper");940}941 942void XCOFFDumper::printUnwindInfo() {943  llvm_unreachable("Unimplemented functionality for XCOFFDumper");944}945 946void XCOFFDumper::printStackMap() const {947  llvm_unreachable("Unimplemented functionality for XCOFFDumper");948}949 950void XCOFFDumper::printNeededLibraries() {951  ListScope D(W, "NeededLibraries");952  auto ImportFilesOrError = Obj.getImportFileTable();953  if (!ImportFilesOrError) {954    reportUniqueWarning(ImportFilesOrError.takeError());955    return;956  }957 958  StringRef ImportFileTable = ImportFilesOrError.get();959  const char *CurrentStr = ImportFileTable.data();960  const char *TableEnd = ImportFileTable.end();961  // Default column width for names is 13 even if no names are that long.962  size_t BaseWidth = 13;963 964  // Get the max width of BASE columns.965  for (size_t StrIndex = 0; CurrentStr < TableEnd; ++StrIndex) {966    size_t CurrentLen = strlen(CurrentStr);967    CurrentStr += strlen(CurrentStr) + 1;968    if (StrIndex % 3 == 1)969      BaseWidth = std::max(BaseWidth, CurrentLen);970  }971 972  auto &OS = static_cast<formatted_raw_ostream &>(W.startLine());973  // Each entry consists of 3 strings: the path_name, base_name and974  // archive_member_name. The first entry is a default LIBPATH value and other975  // entries have no path_name. We just dump the base_name and976  // archive_member_name here.977  OS << left_justify("BASE", BaseWidth)  << " MEMBER\n";978  CurrentStr = ImportFileTable.data();979  for (size_t StrIndex = 0; CurrentStr < TableEnd;980       ++StrIndex, CurrentStr += strlen(CurrentStr) + 1) {981    if (StrIndex >= 3 && StrIndex % 3 != 0) {982      if (StrIndex % 3 == 1)983        OS << "  " << left_justify(CurrentStr, BaseWidth) << " ";984      else985        OS << CurrentStr << "\n";986    }987  }988}989 990const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {991#define ECase(X)                                                               \992  { #X, XCOFF::X }993    ECase(STYP_PAD),    ECase(STYP_DWARF), ECase(STYP_TEXT),994    ECase(STYP_DATA),   ECase(STYP_BSS),   ECase(STYP_EXCEPT),995    ECase(STYP_INFO),   ECase(STYP_TDATA), ECase(STYP_TBSS),996    ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),997    ECase(STYP_OVRFLO)998#undef ECase999};1000 1001const EnumEntry<XCOFF::DwarfSectionSubtypeFlags>1002    DWARFSectionSubtypeFlagsNames[] = {1003#define ECase(X)                                                               \1004  { #X, XCOFF::X }1005        ECase(SSUBTYP_DWINFO),  ECase(SSUBTYP_DWLINE),  ECase(SSUBTYP_DWPBNMS),1006        ECase(SSUBTYP_DWPBTYP), ECase(SSUBTYP_DWARNGE), ECase(SSUBTYP_DWABREV),1007        ECase(SSUBTYP_DWSTR),   ECase(SSUBTYP_DWRNGES), ECase(SSUBTYP_DWLOC),1008        ECase(SSUBTYP_DWFRAME), ECase(SSUBTYP_DWMAC)1009#undef ECase1010};1011 1012template <typename T>1013void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {1014  if (Obj.is64Bit()) {1015    reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "1016                                          "contain an overflow section header.",1017                                          object_error::parse_failed),1018                  Obj.getFileName());1019  }1020 1021  W.printString("Name", Sec.getName());1022  W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);1023  W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);1024  W.printHex("Size", Sec.SectionSize);1025  W.printHex("RawDataOffset", Sec.FileOffsetToRawData);1026  W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);1027  W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);1028  W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);1029  W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);1030}1031 1032template <typename T>1033void XCOFFDumper::printGenericSectionHeader(T &Sec) const {1034  W.printString("Name", Sec.getName());1035  W.printHex("PhysicalAddress", Sec.PhysicalAddress);1036  W.printHex("VirtualAddress", Sec.VirtualAddress);1037  W.printHex("Size", Sec.SectionSize);1038  W.printHex("RawDataOffset", Sec.FileOffsetToRawData);1039  W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);1040  W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);1041  W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);1042  W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);1043}1044 1045enum PrintStyle { Hex, Number };1046template <typename T, typename V>1047static void printAuxMemberHelper(PrintStyle Style, const char *MemberName,1048                                 const T &Member, const V *AuxHeader,1049                                 uint16_t AuxSize, uint16_t &PartialFieldOffset,1050                                 const char *&PartialFieldName,1051                                 ScopedPrinter &W) {1052  ptrdiff_t Offset = reinterpret_cast<const char *>(&Member) -1053                     reinterpret_cast<const char *>(AuxHeader);1054  if (Offset + sizeof(Member) <= AuxSize)1055    Style == Hex ? W.printHex(MemberName, Member)1056                 : W.printNumber(MemberName, Member);1057  else if (Offset < AuxSize) {1058    PartialFieldOffset = Offset;1059    PartialFieldName = MemberName;1060  }1061}1062 1063template <class T>1064void checkAndPrintAuxHeaderParseError(const char *PartialFieldName,1065                                      uint16_t PartialFieldOffset,1066                                      uint16_t AuxSize, T &AuxHeader,1067                                      XCOFFDumper *Dumper) {1068  if (PartialFieldOffset < AuxSize) {1069    Dumper->reportUniqueWarning(Twine("only partial field for ") +1070                                PartialFieldName + " at offset (" +1071                                Twine(PartialFieldOffset) + ")");1072    Dumper->getScopedPrinter().printBinary(1073        "Raw data", "",1074        ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +1075                              PartialFieldOffset,1076                          AuxSize - PartialFieldOffset));1077  } else if (sizeof(AuxHeader) < AuxSize)1078    Dumper->getScopedPrinter().printBinary(1079        "Extra raw data", "",1080        ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +1081                              sizeof(AuxHeader),1082                          AuxSize - sizeof(AuxHeader)));1083}1084 1085void XCOFFDumper::printAuxiliaryHeader(1086    const XCOFFAuxiliaryHeader32 *AuxHeader) {1087  if (AuxHeader == nullptr)1088    return;1089  uint16_t AuxSize = Obj.getOptionalHeaderSize();1090  uint16_t PartialFieldOffset = AuxSize;1091  const char *PartialFieldName = nullptr;1092 1093  auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,1094                            auto &Member) {1095    printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,1096                         PartialFieldOffset, PartialFieldName, W);1097  };1098 1099  PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);1100  PrintAuxMember(Hex, "Version", AuxHeader->Version);1101  PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);1102  PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);1103  PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);1104  PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);1105  PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);1106  PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);1107  PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);1108  PrintAuxMember(Number, "Section number of entryPoint",1109                 AuxHeader->SecNumOfEntryPoint);1110  PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);1111  PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);1112  PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);1113  PrintAuxMember(Number, "Section number of loader data",1114                 AuxHeader->SecNumOfLoader);1115  PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);1116  PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);1117  PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);1118  PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);1119  PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);1120  PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);1121  PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);1122  PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);1123  PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);1124  PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);1125  PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);1126  PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);1127  if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) +1128          sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <=1129      AuxSize) {1130    W.printHex("Flag", AuxHeader->getFlag());1131    W.printHex("Alignment of thread-local storage",1132               AuxHeader->getTDataAlignment());1133  }1134 1135  PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);1136  PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);1137 1138  checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,1139                                   AuxSize, *AuxHeader, this);1140}1141 1142void XCOFFDumper::printAuxiliaryHeader(1143    const XCOFFAuxiliaryHeader64 *AuxHeader) {1144  if (AuxHeader == nullptr)1145    return;1146  uint16_t AuxSize = Obj.getOptionalHeaderSize();1147  uint16_t PartialFieldOffset = AuxSize;1148  const char *PartialFieldName = nullptr;1149 1150  auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,1151                            auto &Member) {1152    printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,1153                         PartialFieldOffset, PartialFieldName, W);1154  };1155 1156  PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);1157  PrintAuxMember(Hex, "Version", AuxHeader->Version);1158  PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);1159  PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);1160  PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);1161  PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);1162  PrintAuxMember(Number, "Section number of entryPoint",1163                 AuxHeader->SecNumOfEntryPoint);1164  PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);1165  PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);1166  PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);1167  PrintAuxMember(Number, "Section number of loader data",1168                 AuxHeader->SecNumOfLoader);1169  PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);1170  PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);1171  PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);1172  PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);1173  PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);1174  PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);1175  PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);1176  PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);1177  PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);1178  if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) +1179          sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <=1180      AuxSize) {1181    W.printHex("Flag", AuxHeader->getFlag());1182    W.printHex("Alignment of thread-local storage",1183               AuxHeader->getTDataAlignment());1184  }1185  PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);1186  PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);1187  PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);1188  PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);1189  PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);1190  PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);1191  PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);1192  PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);1193  PrintAuxMember(Hex, "Additional flags 64-bit XCOFF", AuxHeader->XCOFF64Flag);1194 1195  checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,1196                                   AuxSize, *AuxHeader, this);1197}1198 1199template <typename T>1200void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {1201  ListScope Group(W, "Sections");1202 1203  uint16_t Index = 1;1204  for (const T &Sec : Sections) {1205    DictScope SecDS(W, "Section");1206 1207    W.printNumber("Index", Index++);1208    uint16_t SectionType = Sec.getSectionType();1209    int32_t SectionSubtype = Sec.getSectionSubtype();1210    switch (SectionType) {1211    case XCOFF::STYP_OVRFLO:1212      printOverflowSectionHeader(Sec);1213      break;1214    case XCOFF::STYP_LOADER:1215    case XCOFF::STYP_EXCEPT:1216    case XCOFF::STYP_TYPCHK:1217      // TODO The interpretation of loader, exception and type check section1218      // headers are different from that of generic section headers. We will1219      // implement them later. We interpret them as generic section headers for1220      // now.1221    default:1222      printGenericSectionHeader(Sec);1223      break;1224    }1225    if (Sec.isReservedSectionType())1226      W.printHex("Flags", "Reserved", SectionType);1227    else {1228      W.printEnum("Type", SectionType, ArrayRef(SectionTypeFlagsNames));1229      if (SectionType == XCOFF::STYP_DWARF) {1230        W.printEnum("DWARFSubType", SectionSubtype,1231                    ArrayRef(DWARFSectionSubtypeFlagsNames));1232      }1233    }1234  }1235 1236  if (opts::SectionRelocations)1237    report_fatal_error("Dumping section relocations is unimplemented");1238 1239  if (opts::SectionSymbols)1240    report_fatal_error("Dumping symbols is unimplemented");1241 1242  if (opts::SectionData)1243    report_fatal_error("Dumping section data is unimplemented");1244}1245 1246namespace llvm {1247std::unique_ptr<ObjDumper>1248createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) {1249  return std::make_unique<XCOFFDumper>(XObj, Writer);1250}1251} // namespace llvm1252