Path: blob/main/contrib/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
35231 views
//===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements an XCOFF specific dumper for llvm-readobj.9//10//===----------------------------------------------------------------------===//1112#include "ObjDumper.h"13#include "llvm-readobj.h"14#include "llvm/Demangle/Demangle.h"15#include "llvm/Object/XCOFFObjectFile.h"16#include "llvm/Support/FormattedStream.h"17#include "llvm/Support/ScopedPrinter.h"1819#include <ctime>2021using namespace llvm;22using namespace object;2324namespace {2526class XCOFFDumper : public ObjDumper {2728public:29XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)30: ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {}3132void printFileHeaders() override;33void printAuxiliaryHeader() override;34void printSectionHeaders() override;35void printRelocations() override;36void printSymbols(bool ExtraSymInfo) override;37void printDynamicSymbols() override;38void printUnwindInfo() override;39void printStackMap() const override;40void printNeededLibraries() override;41void printStringTable() override;42void printExceptionSection() override;43void printLoaderSection(bool PrintHeader, bool PrintSymbols,44bool PrintRelocations) override;4546ScopedPrinter &getScopedPrinter() const { return W; }4748private:49template <typename T> void printSectionHeaders(ArrayRef<T> Sections);50template <typename T> void printGenericSectionHeader(T &Sec) const;51template <typename T> void printOverflowSectionHeader(T &Sec) const;52template <typename T>53void printExceptionSectionEntry(const T &ExceptionSectEnt) const;54template <typename T> void printExceptionSectionEntries() const;55template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress);56void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);57void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);58void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);59void printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr);60void printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr);61void printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr);62void printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr);63void printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr);64template <typename T> void printSectAuxEntForDWARF(const T *AuxEntPtr);65void printSymbol(const SymbolRef &);66template <typename RelTy> void printRelocation(RelTy Reloc);67template <typename Shdr, typename RelTy>68void printRelocations(ArrayRef<Shdr> Sections);69void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);70void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);71void printLoaderSectionHeader(uintptr_t LoaderSectAddr);72void printLoaderSectionSymbols(uintptr_t LoaderSectAddr);73template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>74void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr);75template <typename LoadSectionRelocTy>76void printLoaderSectionRelocationEntry(LoadSectionRelocTy *LoaderSecRelEntPtr,77StringRef SymbolName);78void printLoaderSectionRelocationEntries(uintptr_t LoaderSectAddr);79template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,80typename LoaderSectionRelocationEntry>81void printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectAddr);8283const XCOFFObjectFile &Obj;84const static int32_t FirstSymIdxOfLoaderSec = 3;85};86} // anonymous namespace8788void XCOFFDumper::printFileHeaders() {89DictScope DS(W, "FileHeader");90W.printHex("Magic", Obj.getMagic());91W.printNumber("NumberOfSections", Obj.getNumberOfSections());9293// Negative timestamp values are reserved for future use.94int32_t TimeStamp = Obj.getTimeStamp();95if (TimeStamp > 0) {96// This handling of the time stamp assumes that the host system's time_t is97// compatible with AIX time_t. If a platform is not compatible, the lit98// tests will let us know.99time_t TimeDate = TimeStamp;100101char FormattedTime[80] = {};102103size_t BytesFormatted =104strftime(FormattedTime, sizeof(FormattedTime), "%F %T", gmtime(&TimeDate));105if (BytesFormatted)106W.printHex("TimeStamp", FormattedTime, TimeStamp);107else108W.printHex("Timestamp", TimeStamp);109} else {110W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",111TimeStamp);112}113114// The number of symbol table entries is an unsigned value in 64-bit objects115// and a signed value (with negative values being 'reserved') in 32-bit116// objects.117if (Obj.is64Bit()) {118W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());119W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());120} else {121W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());122int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();123if (SymTabEntries >= 0)124W.printNumber("SymbolTableEntries", SymTabEntries);125else126W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);127}128129W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());130W.printHex("Flags", Obj.getFlags());131132// TODO FIXME Add support for the auxiliary header (if any) once133// XCOFFObjectFile has the necessary support.134}135136void XCOFFDumper::printAuxiliaryHeader() {137DictScope DS(W, "AuxiliaryHeader");138139if (Obj.is64Bit())140printAuxiliaryHeader(Obj.auxiliaryHeader64());141else142printAuxiliaryHeader(Obj.auxiliaryHeader32());143}144145void XCOFFDumper::printSectionHeaders() {146if (Obj.is64Bit())147printSectionHeaders(Obj.sections64());148else149printSectionHeaders(Obj.sections32());150}151152void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbols,153bool PrintRelocations) {154DictScope DS(W, "Loader Section");155Expected<uintptr_t> LoaderSectionAddrOrError =156Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);157if (!LoaderSectionAddrOrError) {158reportUniqueWarning(LoaderSectionAddrOrError.takeError());159return;160}161uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();162163if (LoaderSectionAddr == 0)164return;165166W.indent();167if (PrintHeader)168printLoaderSectionHeader(LoaderSectionAddr);169170if (PrintSymbols)171printLoaderSectionSymbols(LoaderSectionAddr);172173if (PrintRelocations)174printLoaderSectionRelocationEntries(LoaderSectionAddr);175176W.unindent();177}178179void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr) {180DictScope DS(W, "Loader Section Header");181182auto PrintLoadSecHeaderCommon = [&](const auto *LDHeader) {183W.printNumber("Version", LDHeader->Version);184W.printNumber("NumberOfSymbolEntries", LDHeader->NumberOfSymTabEnt);185W.printNumber("NumberOfRelocationEntries", LDHeader->NumberOfRelTabEnt);186W.printNumber("LengthOfImportFileIDStringTable",187LDHeader->LengthOfImpidStrTbl);188W.printNumber("NumberOfImportFileIDs", LDHeader->NumberOfImpid);189W.printHex("OffsetToImportFileIDs", LDHeader->OffsetToImpid);190W.printNumber("LengthOfStringTable", LDHeader->LengthOfStrTbl);191W.printHex("OffsetToStringTable", LDHeader->OffsetToStrTbl);192};193194if (Obj.is64Bit()) {195const LoaderSectionHeader64 *LoaderSec64 =196reinterpret_cast<const LoaderSectionHeader64 *>(LoaderSectionAddr);197PrintLoadSecHeaderCommon(LoaderSec64);198W.printHex("OffsetToSymbolTable", LoaderSec64->OffsetToSymTbl);199W.printHex("OffsetToRelocationEntries", LoaderSec64->OffsetToRelEnt);200} else {201const LoaderSectionHeader32 *LoaderSec32 =202reinterpret_cast<const LoaderSectionHeader32 *>(LoaderSectionAddr);203PrintLoadSecHeaderCommon(LoaderSec32);204}205}206207const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {208#define ECase(X) \209{ #X, XCOFF::X }210ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT),211ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL),212ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU),213ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG),214ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK),215ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE),216ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL),217ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF),218ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM),219ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM),220ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY),221ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS),222ECase(C_STTLS), ECase(C_EFCN)223#undef ECase224};225226template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>227void XCOFFDumper::printLoaderSectionSymbolsHelper(uintptr_t LoaderSectionAddr) {228const LoaderSectionHeader *LoadSecHeader =229reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);230const LoaderSectionSymbolEntry *LoadSecSymEntPtr =231reinterpret_cast<LoaderSectionSymbolEntry *>(232LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()));233234for (uint32_t i = 0; i < LoadSecHeader->NumberOfSymTabEnt;235++i, ++LoadSecSymEntPtr) {236if (Error E = Binary::checkOffset(237Obj.getMemoryBufferRef(),238LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()) +239(i * sizeof(LoaderSectionSymbolEntry)),240sizeof(LoaderSectionSymbolEntry))) {241reportUniqueWarning(std::move(E));242return;243}244245Expected<StringRef> SymbolNameOrErr =246LoadSecSymEntPtr->getSymbolName(LoadSecHeader);247if (!SymbolNameOrErr) {248reportUniqueWarning(SymbolNameOrErr.takeError());249return;250}251252DictScope DS(W, "Symbol");253StringRef SymbolName = SymbolNameOrErr.get();254W.printString("Name", opts::Demangle ? demangle(SymbolName) : SymbolName);255W.printHex("Virtual Address", LoadSecSymEntPtr->Value);256W.printNumber("SectionNum", LoadSecSymEntPtr->SectionNumber);257W.printHex("SymbolType", LoadSecSymEntPtr->SymbolType);258W.printEnum("StorageClass",259static_cast<uint8_t>(LoadSecSymEntPtr->StorageClass),260ArrayRef(SymStorageClass));261W.printHex("ImportFileID", LoadSecSymEntPtr->ImportFileID);262W.printNumber("ParameterTypeCheck", LoadSecSymEntPtr->ParameterTypeCheck);263}264}265266void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr) {267DictScope DS(W, "Loader Section Symbols");268if (Obj.is64Bit())269printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry64,270LoaderSectionHeader64>(LoaderSectionAddr);271else272printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry32,273LoaderSectionHeader32>(LoaderSectionAddr);274}275276const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {277#define ECase(X) \278{ #X, XCOFF::X }279ECase(R_POS), ECase(R_RL), ECase(R_RLA), ECase(R_NEG),280ECase(R_REL), ECase(R_TOC), ECase(R_TRL), ECase(R_TRLA),281ECase(R_GL), ECase(R_TCL), ECase(R_REF), ECase(R_BA),282ECase(R_BR), ECase(R_RBA), ECase(R_RBR), ECase(R_TLS),283ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),284ECase(R_TLSML), ECase(R_TOCU), ECase(R_TOCL)285#undef ECase286};287288// From the XCOFF specification: there are five implicit external symbols, one289// each for the .text, .data, .bss, .tdata, and .tbss sections. These symbols290// are referenced from the relocation table entries using symbol table index291// values 0, 1, 2, -1, and -2, respectively.292static const char *getImplicitLoaderSectionSymName(int SymIndx) {293switch (SymIndx) {294default:295return "Unkown Symbol Name";296case -2:297return ".tbss";298case -1:299return ".tdata";300case 0:301return ".text";302case 1:303return ".data";304case 2:305return ".bss";306}307}308309template <typename LoadSectionRelocTy>310void XCOFFDumper::printLoaderSectionRelocationEntry(311LoadSectionRelocTy *LoaderSecRelEntPtr, StringRef SymbolName) {312uint16_t Type = LoaderSecRelEntPtr->Type;313if (opts::ExpandRelocs) {314DictScope DS(W, "Relocation");315auto IsRelocationSigned = [](uint8_t Info) {316return Info & XCOFF::XR_SIGN_INDICATOR_MASK;317};318auto IsFixupIndicated = [](uint8_t Info) {319return Info & XCOFF::XR_FIXUP_INDICATOR_MASK;320};321auto GetRelocatedLength = [](uint8_t Info) {322// The relocation encodes the bit length being relocated minus 1. Add323// back324// the 1 to get the actual length being relocated.325return (Info & XCOFF::XR_BIASED_LENGTH_MASK) + 1;326};327328uint8_t Info = Type >> 8;329W.printHex("Virtual Address", LoaderSecRelEntPtr->VirtualAddr);330W.printNumber("Symbol", opts::Demangle ? demangle(SymbolName) : SymbolName,331LoaderSecRelEntPtr->SymbolIndex);332W.printString("IsSigned", IsRelocationSigned(Info) ? "Yes" : "No");333W.printNumber("FixupBitValue", IsFixupIndicated(Info) ? 1 : 0);334W.printNumber("Length", GetRelocatedLength(Info));335W.printEnum("Type", static_cast<uint8_t>(Type),336ArrayRef(RelocationTypeNameclass));337W.printNumber("SectionNumber", LoaderSecRelEntPtr->SectionNum);338} else {339W.startLine() << format_hex(LoaderSecRelEntPtr->VirtualAddr,340Obj.is64Bit() ? 18 : 10)341<< " " << format_hex(Type, 6) << " ("342<< XCOFF::getRelocationTypeString(343static_cast<XCOFF::RelocationType>(Type))344<< ")" << format_decimal(LoaderSecRelEntPtr->SectionNum, 8)345<< " "346<< (opts::Demangle ? demangle(SymbolName) : SymbolName)347<< " (" << LoaderSecRelEntPtr->SymbolIndex << ")\n";348}349}350351template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,352typename LoaderSectionRelocationEntry>353void XCOFFDumper::printLoaderSectionRelocationEntriesHelper(354uintptr_t LoaderSectionAddr) {355const LoaderSectionHeader *LoaderSec =356reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);357const LoaderSectionRelocationEntry *LoaderSecRelEntPtr =358reinterpret_cast<const LoaderSectionRelocationEntry *>(359LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToRelEnt()));360361if (!opts::ExpandRelocs)362W.startLine() << center_justify("Vaddr", Obj.is64Bit() ? 18 : 10)363<< center_justify("Type", 15) << right_justify("SecNum", 8)364<< center_justify("SymbolName (Index) ", 24) << "\n";365366for (uint32_t i = 0; i < LoaderSec->NumberOfRelTabEnt;367++i, ++LoaderSecRelEntPtr) {368StringRef SymbolName;369if (LoaderSecRelEntPtr->SymbolIndex >= FirstSymIdxOfLoaderSec) {370// Because there are implicit symbol index values (-2, -1, 0, 1, 2),371// LoaderSecRelEnt.SymbolIndex - FirstSymIdxOfLoaderSec will get the372// real symbol from the symbol table.373const uint64_t SymOffset =374(LoaderSecRelEntPtr->SymbolIndex - FirstSymIdxOfLoaderSec) *375sizeof(LoaderSectionSymbolEntry);376const LoaderSectionSymbolEntry *LoaderSecRelSymEntPtr =377reinterpret_cast<LoaderSectionSymbolEntry *>(378LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToSymTbl()) +379SymOffset);380381Expected<StringRef> SymbolNameOrErr =382LoaderSecRelSymEntPtr->getSymbolName(LoaderSec);383if (!SymbolNameOrErr) {384reportUniqueWarning(SymbolNameOrErr.takeError());385return;386}387SymbolName = SymbolNameOrErr.get();388} else389SymbolName =390getImplicitLoaderSectionSymName(LoaderSecRelEntPtr->SymbolIndex);391392printLoaderSectionRelocationEntry(LoaderSecRelEntPtr, SymbolName);393}394}395396void XCOFFDumper::printLoaderSectionRelocationEntries(397uintptr_t LoaderSectionAddr) {398DictScope DS(W, "Loader Section Relocations");399400if (Obj.is64Bit())401printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader64,402LoaderSectionSymbolEntry64,403LoaderSectionRelocationEntry64>(404LoaderSectionAddr);405else406printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader32,407LoaderSectionSymbolEntry32,408LoaderSectionRelocationEntry32>(409LoaderSectionAddr);410}411412template <typename T>413void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const {414if (ExceptionSectEnt.getReason())415W.printHex("Trap Instr Addr", ExceptionSectEnt.getTrapInstAddr());416else {417uint32_t SymIdx = ExceptionSectEnt.getSymbolIndex();418Expected<StringRef> ErrOrSymbolName = Obj.getSymbolNameByIndex(SymIdx);419if (Error E = ErrOrSymbolName.takeError()) {420reportUniqueWarning(std::move(E));421return;422}423StringRef SymName = *ErrOrSymbolName;424425W.printNumber("Symbol", SymName, SymIdx);426}427W.printNumber("LangID", ExceptionSectEnt.getLangID());428W.printNumber("Reason", ExceptionSectEnt.getReason());429}430431template <typename T> void XCOFFDumper::printExceptionSectionEntries() const {432Expected<ArrayRef<T>> ExceptSectEntsOrErr = Obj.getExceptionEntries<T>();433if (Error E = ExceptSectEntsOrErr.takeError()) {434reportUniqueWarning(std::move(E));435return;436}437ArrayRef<T> ExceptSectEnts = *ExceptSectEntsOrErr;438439DictScope DS(W, "Exception section");440if (ExceptSectEnts.empty())441return;442for (auto &Ent : ExceptSectEnts)443printExceptionSectionEntry(Ent);444}445446void XCOFFDumper::printExceptionSection() {447if (Obj.is64Bit())448printExceptionSectionEntries<ExceptionSectionEntry64>();449else450printExceptionSectionEntries<ExceptionSectionEntry32>();451}452453void XCOFFDumper::printRelocations() {454if (Obj.is64Bit())455printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64());456else457printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32());458}459460template <typename RelTy> void XCOFFDumper::printRelocation(RelTy Reloc) {461Expected<StringRef> ErrOrSymbolName =462Obj.getSymbolNameByIndex(Reloc.SymbolIndex);463if (Error E = ErrOrSymbolName.takeError()) {464reportUniqueWarning(std::move(E));465return;466}467StringRef SymbolName = *ErrOrSymbolName;468StringRef RelocName = XCOFF::getRelocationTypeString(Reloc.Type);469if (opts::ExpandRelocs) {470DictScope Group(W, "Relocation");471W.printHex("Virtual Address", Reloc.VirtualAddress);472W.printNumber("Symbol", opts::Demangle ? demangle(SymbolName) : SymbolName,473Reloc.SymbolIndex);474W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");475W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);476W.printNumber("Length", Reloc.getRelocatedLength());477W.printEnum("Type", (uint8_t)Reloc.Type, ArrayRef(RelocationTypeNameclass));478} else {479raw_ostream &OS = W.startLine();480OS << W.hex(Reloc.VirtualAddress) << " " << RelocName << " "481<< (opts::Demangle ? demangle(SymbolName) : SymbolName) << "("482<< Reloc.SymbolIndex << ") " << W.hex(Reloc.Info) << "\n";483}484}485486template <typename Shdr, typename RelTy>487void XCOFFDumper::printRelocations(ArrayRef<Shdr> Sections) {488ListScope LS(W, "Relocations");489uint16_t Index = 0;490for (const Shdr &Sec : Sections) {491++Index;492// Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.493if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&494Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)495continue;496Expected<ArrayRef<RelTy>> ErrOrRelocations = Obj.relocations<Shdr, RelTy>(Sec);497if (Error E = ErrOrRelocations.takeError()) {498reportUniqueWarning(std::move(E));499continue;500}501502const ArrayRef<RelTy> Relocations = *ErrOrRelocations;503if (Relocations.empty())504continue;505506W.startLine() << "Section (index: " << Index << ") " << Sec.getName()507<< " {\n";508W.indent();509510for (const RelTy Reloc : Relocations)511printRelocation(Reloc);512513W.unindent();514W.startLine() << "}\n";515}516}517518const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {519#define ECase(X) \520{ #X, XCOFF::X }521ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)522#undef ECase523};524525const EnumEntry<XCOFF::SymbolAuxType> SymAuxType[] = {526#define ECase(X) \527{ #X, XCOFF::X }528ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE),529ECase(AUX_CSECT), ECase(AUX_SECT)530#undef ECase531};532533void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {534assert((!Obj.is64Bit() || AuxEntPtr->AuxType == XCOFF::AUX_FILE) &&535"Mismatched auxiliary type!");536StringRef FileName =537unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));538DictScope SymDs(W, "File Auxiliary Entry");539W.printNumber("Index",540Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));541W.printString("Name", FileName);542W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),543ArrayRef(FileStringType));544if (Obj.is64Bit()) {545W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),546ArrayRef(SymAuxType));547}548}549550static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =551{552#define ECase(X) \553{ #X, XCOFF::X }554ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB), ECase(XMC_GL),555ECase(XMC_XO), ECase(XMC_SV), ECase(XMC_SV64), ECase(XMC_SV3264),556ECase(XMC_TI), ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0),557ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS), ECase(XMC_UA),558ECase(XMC_BS), ECase(XMC_UC), ECase(XMC_TL), ECase(XMC_UL),559ECase(XMC_TE)560#undef ECase561};562563const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {564#define ECase(X) \565{ #X, XCOFF::X }566ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)567#undef ECase568};569570void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) {571assert((!Obj.is64Bit() || AuxEntRef.getAuxType64() == XCOFF::AUX_CSECT) &&572"Mismatched auxiliary type!");573574DictScope SymDs(W, "CSECT Auxiliary Entry");575W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getEntryAddress()));576W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex"577: "SectionLen",578AuxEntRef.getSectionOrLength());579W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex());580W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum());581// Print out symbol alignment and type.582W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2());583W.printEnum("SymbolType", AuxEntRef.getSymbolType(),584ArrayRef(CsectSymbolTypeClass));585W.printEnum("StorageMappingClass",586static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()),587ArrayRef(CsectStorageMappingClass));588589if (Obj.is64Bit()) {590W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT),591ArrayRef(SymAuxType));592} else {593W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32());594W.printHex("StabSectNum", AuxEntRef.getStabSectNum32());595}596}597598void XCOFFDumper::printSectAuxEntForStat(599const XCOFFSectAuxEntForStat *AuxEntPtr) {600assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");601602DictScope SymDs(W, "Sect Auxiliary Entry For Stat");603W.printNumber("Index",604Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));605W.printNumber("SectionLength", AuxEntPtr->SectionLength);606607// Unlike the corresponding fields in the section header, NumberOfRelocEnt608// and NumberOfLineNum do not handle values greater than 65535.609W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);610W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);611}612613void XCOFFDumper::printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr) {614assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");615616DictScope SymDs(W, "Exception Auxiliary Entry");617W.printNumber("Index",618Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));619W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);620W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);621W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);622W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),623ArrayRef(SymAuxType));624}625626void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr) {627assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");628629DictScope SymDs(W, "Function Auxiliary Entry");630W.printNumber("Index",631Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));632W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);633W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);634W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);635W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);636}637638void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr) {639assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");640641DictScope SymDs(W, "Function Auxiliary Entry");642W.printNumber("Index",643Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));644W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);645W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);646W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);647W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),648ArrayRef(SymAuxType));649}650651void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr) {652assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");653654DictScope SymDs(W, "Block Auxiliary Entry");655W.printNumber("Index",656Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));657W.printHex("LineNumber (High 2 Bytes)", AuxEntPtr->LineNumHi);658W.printHex("LineNumber (Low 2 Bytes)", AuxEntPtr->LineNumLo);659}660661void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr) {662assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");663664DictScope SymDs(W, "Block Auxiliary Entry");665W.printNumber("Index",666Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));667W.printHex("LineNumber", AuxEntPtr->LineNum);668W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),669ArrayRef(SymAuxType));670}671672template <typename T>673void XCOFFDumper::printSectAuxEntForDWARF(const T *AuxEntPtr) {674DictScope SymDs(W, "Sect Auxiliary Entry For DWARF");675W.printNumber("Index",676Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));677W.printHex("LengthOfSectionPortion", AuxEntPtr->LengthOfSectionPortion);678W.printNumber("NumberOfRelocEntries", AuxEntPtr->NumberOfRelocEnt);679if (Obj.is64Bit())680W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_SECT),681ArrayRef(SymAuxType));682}683684static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {685switch (SC) {686case XCOFF::C_EXT:687case XCOFF::C_WEAKEXT:688case XCOFF::C_HIDEXT:689case XCOFF::C_STAT:690case XCOFF::C_FCN:691case XCOFF::C_BLOCK:692return "Value (RelocatableAddress)";693case XCOFF::C_FILE:694return "Value (SymbolTableIndex)";695case XCOFF::C_DWARF:696return "Value (OffsetInDWARF)";697case XCOFF::C_FUN:698case XCOFF::C_STSYM:699case XCOFF::C_BINCL:700case XCOFF::C_EINCL:701case XCOFF::C_INFO:702case XCOFF::C_BSTAT:703case XCOFF::C_LSYM:704case XCOFF::C_PSYM:705case XCOFF::C_RPSYM:706case XCOFF::C_RSYM:707case XCOFF::C_ECOML:708assert(false && "This StorageClass for the symbol is not yet implemented.");709return "";710default:711return "Value";712}713}714715const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {716#define ECase(X) \717{ #X, XCOFF::X }718ECase(TB_C), ECase(TB_Fortran), ECase(TB_CPLUSPLUS)719#undef ECase720};721722const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {723#define ECase(X) \724{ #X, XCOFF::X }725ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)726#undef ECase727};728729template <typename T> const T *XCOFFDumper::getAuxEntPtr(uintptr_t AuxAddress) {730const T *AuxEntPtr = reinterpret_cast<const T *>(AuxAddress);731Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(AuxEntPtr));732return AuxEntPtr;733}734735static void printUnexpectedRawAuxEnt(ScopedPrinter &W, uintptr_t AuxAddress) {736W.startLine() << "!Unexpected raw auxiliary entry data:\n";737W.startLine() << format_bytes(738ArrayRef<uint8_t>(739reinterpret_cast<const uint8_t *>(AuxAddress),740XCOFF::SymbolTableEntrySize),741std::nullopt, XCOFF::SymbolTableEntrySize)742<< "\n";743}744745void XCOFFDumper::printSymbol(const SymbolRef &S) {746DataRefImpl SymbolDRI = S.getRawDataRefImpl();747XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);748749uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();750751DictScope SymDs(W, "Symbol");752753StringRef SymbolName =754unwrapOrError(Obj.getFileName(), SymbolEntRef.getName());755756uint32_t SymbolIdx = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());757XCOFF::StorageClass SymbolClass = SymbolEntRef.getStorageClass();758759W.printNumber("Index", SymbolIdx);760W.printString("Name", opts::Demangle ? demangle(SymbolName) : SymbolName);761W.printHex(GetSymbolValueName(SymbolClass), SymbolEntRef.getValue());762763StringRef SectionName =764unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef));765766W.printString("Section", SectionName);767if (SymbolClass == XCOFF::C_FILE) {768W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(),769ArrayRef(CFileLangIdClass));770W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(),771ArrayRef(CFileCpuIdClass));772} else773W.printHex("Type", SymbolEntRef.getSymbolType());774775W.printEnum("StorageClass", static_cast<uint8_t>(SymbolClass),776ArrayRef(SymStorageClass));777W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries);778779if (NumberOfAuxEntries == 0)780return;781782auto checkNumOfAux = [=] {783if (NumberOfAuxEntries > 1)784reportUniqueWarning("the " +785enumToString(static_cast<uint8_t>(SymbolClass),786ArrayRef(SymStorageClass)) +787" symbol at index " + Twine(SymbolIdx) +788" should not have more than 1 "789"auxiliary entry");790};791792switch (SymbolClass) {793case XCOFF::C_FILE:794// If the symbol is C_FILE and has auxiliary entries...795for (int I = 1; I <= NumberOfAuxEntries; I++) {796uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(797SymbolEntRef.getEntryAddress(), I);798799if (Obj.is64Bit() &&800*Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) {801printUnexpectedRawAuxEnt(W, AuxAddress);802continue;803}804805const XCOFFFileAuxEnt *FileAuxEntPtr =806getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress);807printFileAuxEnt(FileAuxEntPtr);808}809break;810case XCOFF::C_EXT:811case XCOFF::C_WEAKEXT:812case XCOFF::C_HIDEXT: {813// For 32-bit objects, print the function auxiliary symbol table entry. The814// last one must be a CSECT auxiliary entry.815// For 64-bit objects, both a function auxiliary entry and an exception816// auxiliary entry may appear, print them in the loop and skip printing the817// CSECT auxiliary entry, which will be printed outside the loop.818for (int I = 1; I <= NumberOfAuxEntries; I++) {819if (I == NumberOfAuxEntries && !Obj.is64Bit())820break;821822uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(823SymbolEntRef.getEntryAddress(), I);824825if (Obj.is64Bit()) {826XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress);827if (Type == XCOFF::SymbolAuxType::AUX_CSECT)828continue;829if (Type == XCOFF::SymbolAuxType::AUX_FCN) {830const XCOFFFunctionAuxEnt64 *AuxEntPtr =831getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress);832printFunctionAuxEnt(AuxEntPtr);833} else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT) {834const XCOFFExceptionAuxEnt *AuxEntPtr =835getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress);836printExceptionAuxEnt(AuxEntPtr);837} else {838printUnexpectedRawAuxEnt(W, AuxAddress);839}840} else {841const XCOFFFunctionAuxEnt32 *AuxEntPtr =842getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress);843printFunctionAuxEnt(AuxEntPtr);844}845}846847// Print the CSECT auxiliary entry.848auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();849if (!ErrOrCsectAuxRef)850reportUniqueWarning(ErrOrCsectAuxRef.takeError());851else852printCsectAuxEnt(*ErrOrCsectAuxRef);853854break;855}856case XCOFF::C_STAT: {857checkNumOfAux();858859const XCOFFSectAuxEntForStat *StatAuxEntPtr =860getAuxEntPtr<XCOFFSectAuxEntForStat>(861XCOFFObjectFile::getAdvancedSymbolEntryAddress(862SymbolEntRef.getEntryAddress(), 1));863printSectAuxEntForStat(StatAuxEntPtr);864break;865}866case XCOFF::C_DWARF: {867checkNumOfAux();868869uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(870SymbolEntRef.getEntryAddress(), 1);871872if (Obj.is64Bit()) {873const XCOFFSectAuxEntForDWARF64 *AuxEntPtr =874getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress);875printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF64>(AuxEntPtr);876} else {877const XCOFFSectAuxEntForDWARF32 *AuxEntPtr =878getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress);879printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF32>(AuxEntPtr);880}881break;882}883case XCOFF::C_BLOCK:884case XCOFF::C_FCN: {885checkNumOfAux();886887uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(888SymbolEntRef.getEntryAddress(), 1);889890if (Obj.is64Bit()) {891const XCOFFBlockAuxEnt64 *AuxEntPtr =892getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress);893printBlockAuxEnt(AuxEntPtr);894} else {895const XCOFFBlockAuxEnt32 *AuxEntPtr =896getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress);897printBlockAuxEnt(AuxEntPtr);898}899break;900}901default:902for (int i = 1; i <= NumberOfAuxEntries; i++) {903printUnexpectedRawAuxEnt(W,904XCOFFObjectFile::getAdvancedSymbolEntryAddress(905SymbolEntRef.getEntryAddress(), i));906}907break;908}909}910911void XCOFFDumper::printSymbols(bool /*ExtraSymInfo*/) {912ListScope Group(W, "Symbols");913for (const SymbolRef &S : Obj.symbols())914printSymbol(S);915}916917void XCOFFDumper::printStringTable() {918DictScope DS(W, "StringTable");919StringRef StrTable = Obj.getStringTable();920uint32_t StrTabSize = StrTable.size();921W.printNumber("Length", StrTabSize);922// Print strings from the fifth byte, since the first four bytes contain the923// length (in bytes) of the string table (including the length field).924if (StrTabSize > 4)925printAsStringList(StrTable, 4);926}927928void XCOFFDumper::printDynamicSymbols() {929llvm_unreachable("Unimplemented functionality for XCOFFDumper");930}931932void XCOFFDumper::printUnwindInfo() {933llvm_unreachable("Unimplemented functionality for XCOFFDumper");934}935936void XCOFFDumper::printStackMap() const {937llvm_unreachable("Unimplemented functionality for XCOFFDumper");938}939940void XCOFFDumper::printNeededLibraries() {941ListScope D(W, "NeededLibraries");942auto ImportFilesOrError = Obj.getImportFileTable();943if (!ImportFilesOrError) {944reportUniqueWarning(ImportFilesOrError.takeError());945return;946}947948StringRef ImportFileTable = ImportFilesOrError.get();949const char *CurrentStr = ImportFileTable.data();950const char *TableEnd = ImportFileTable.end();951// Default column width for names is 13 even if no names are that long.952size_t BaseWidth = 13;953954// Get the max width of BASE columns.955for (size_t StrIndex = 0; CurrentStr < TableEnd; ++StrIndex) {956size_t CurrentLen = strlen(CurrentStr);957CurrentStr += strlen(CurrentStr) + 1;958if (StrIndex % 3 == 1)959BaseWidth = std::max(BaseWidth, CurrentLen);960}961962auto &OS = static_cast<formatted_raw_ostream &>(W.startLine());963// Each entry consists of 3 strings: the path_name, base_name and964// archive_member_name. The first entry is a default LIBPATH value and other965// entries have no path_name. We just dump the base_name and966// archive_member_name here.967OS << left_justify("BASE", BaseWidth) << " MEMBER\n";968CurrentStr = ImportFileTable.data();969for (size_t StrIndex = 0; CurrentStr < TableEnd;970++StrIndex, CurrentStr += strlen(CurrentStr) + 1) {971if (StrIndex >= 3 && StrIndex % 3 != 0) {972if (StrIndex % 3 == 1)973OS << " " << left_justify(CurrentStr, BaseWidth) << " ";974else975OS << CurrentStr << "\n";976}977}978}979980const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {981#define ECase(X) \982{ #X, XCOFF::X }983ECase(STYP_PAD), ECase(STYP_DWARF), ECase(STYP_TEXT),984ECase(STYP_DATA), ECase(STYP_BSS), ECase(STYP_EXCEPT),985ECase(STYP_INFO), ECase(STYP_TDATA), ECase(STYP_TBSS),986ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),987ECase(STYP_OVRFLO)988#undef ECase989};990991const EnumEntry<XCOFF::DwarfSectionSubtypeFlags>992DWARFSectionSubtypeFlagsNames[] = {993#define ECase(X) \994{ #X, XCOFF::X }995ECase(SSUBTYP_DWINFO), ECase(SSUBTYP_DWLINE), ECase(SSUBTYP_DWPBNMS),996ECase(SSUBTYP_DWPBTYP), ECase(SSUBTYP_DWARNGE), ECase(SSUBTYP_DWABREV),997ECase(SSUBTYP_DWSTR), ECase(SSUBTYP_DWRNGES), ECase(SSUBTYP_DWLOC),998ECase(SSUBTYP_DWFRAME), ECase(SSUBTYP_DWMAC)999#undef ECase1000};10011002template <typename T>1003void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {1004if (Obj.is64Bit()) {1005reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "1006"contain an overflow section header.",1007object_error::parse_failed),1008Obj.getFileName());1009}10101011W.printString("Name", Sec.getName());1012W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);1013W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);1014W.printHex("Size", Sec.SectionSize);1015W.printHex("RawDataOffset", Sec.FileOffsetToRawData);1016W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);1017W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);1018W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);1019W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);1020}10211022template <typename T>1023void XCOFFDumper::printGenericSectionHeader(T &Sec) const {1024W.printString("Name", Sec.getName());1025W.printHex("PhysicalAddress", Sec.PhysicalAddress);1026W.printHex("VirtualAddress", Sec.VirtualAddress);1027W.printHex("Size", Sec.SectionSize);1028W.printHex("RawDataOffset", Sec.FileOffsetToRawData);1029W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);1030W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);1031W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);1032W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);1033}10341035enum PrintStyle { Hex, Number };1036template <typename T, typename V>1037static void printAuxMemberHelper(PrintStyle Style, const char *MemberName,1038const T &Member, const V *AuxHeader,1039uint16_t AuxSize, uint16_t &PartialFieldOffset,1040const char *&PartialFieldName,1041ScopedPrinter &W) {1042ptrdiff_t Offset = reinterpret_cast<const char *>(&Member) -1043reinterpret_cast<const char *>(AuxHeader);1044if (Offset + sizeof(Member) <= AuxSize)1045Style == Hex ? W.printHex(MemberName, Member)1046: W.printNumber(MemberName, Member);1047else if (Offset < AuxSize) {1048PartialFieldOffset = Offset;1049PartialFieldName = MemberName;1050}1051}10521053template <class T>1054void checkAndPrintAuxHeaderParseError(const char *PartialFieldName,1055uint16_t PartialFieldOffset,1056uint16_t AuxSize, T &AuxHeader,1057XCOFFDumper *Dumper) {1058if (PartialFieldOffset < AuxSize) {1059Dumper->reportUniqueWarning(Twine("only partial field for ") +1060PartialFieldName + " at offset (" +1061Twine(PartialFieldOffset) + ")");1062Dumper->getScopedPrinter().printBinary(1063"Raw data", "",1064ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +1065PartialFieldOffset,1066AuxSize - PartialFieldOffset));1067} else if (sizeof(AuxHeader) < AuxSize)1068Dumper->getScopedPrinter().printBinary(1069"Extra raw data", "",1070ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +1071sizeof(AuxHeader),1072AuxSize - sizeof(AuxHeader)));1073}10741075void XCOFFDumper::printAuxiliaryHeader(1076const XCOFFAuxiliaryHeader32 *AuxHeader) {1077if (AuxHeader == nullptr)1078return;1079uint16_t AuxSize = Obj.getOptionalHeaderSize();1080uint16_t PartialFieldOffset = AuxSize;1081const char *PartialFieldName = nullptr;10821083auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,1084auto &Member) {1085printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,1086PartialFieldOffset, PartialFieldName, W);1087};10881089PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);1090PrintAuxMember(Hex, "Version", AuxHeader->Version);1091PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);1092PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);1093PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);1094PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);1095PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);1096PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);1097PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);1098PrintAuxMember(Number, "Section number of entryPoint",1099AuxHeader->SecNumOfEntryPoint);1100PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);1101PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);1102PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);1103PrintAuxMember(Number, "Section number of loader data",1104AuxHeader->SecNumOfLoader);1105PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);1106PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);1107PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);1108PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);1109PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);1110PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);1111PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);1112PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);1113PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);1114PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);1115PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);1116PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);1117if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) +1118sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <=1119AuxSize) {1120W.printHex("Flag", AuxHeader->getFlag());1121W.printHex("Alignment of thread-local storage",1122AuxHeader->getTDataAlignment());1123}11241125PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);1126PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);11271128checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,1129AuxSize, *AuxHeader, this);1130}11311132void XCOFFDumper::printAuxiliaryHeader(1133const XCOFFAuxiliaryHeader64 *AuxHeader) {1134if (AuxHeader == nullptr)1135return;1136uint16_t AuxSize = Obj.getOptionalHeaderSize();1137uint16_t PartialFieldOffset = AuxSize;1138const char *PartialFieldName = nullptr;11391140auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,1141auto &Member) {1142printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,1143PartialFieldOffset, PartialFieldName, W);1144};11451146PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);1147PrintAuxMember(Hex, "Version", AuxHeader->Version);1148PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);1149PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);1150PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);1151PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);1152PrintAuxMember(Number, "Section number of entryPoint",1153AuxHeader->SecNumOfEntryPoint);1154PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);1155PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);1156PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);1157PrintAuxMember(Number, "Section number of loader data",1158AuxHeader->SecNumOfLoader);1159PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);1160PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);1161PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);1162PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);1163PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);1164PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);1165PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);1166PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);1167PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);1168if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) +1169sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <=1170AuxSize) {1171W.printHex("Flag", AuxHeader->getFlag());1172W.printHex("Alignment of thread-local storage",1173AuxHeader->getTDataAlignment());1174}1175PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);1176PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);1177PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);1178PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);1179PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);1180PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);1181PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);1182PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);1183PrintAuxMember(Hex, "Additional flags 64-bit XCOFF", AuxHeader->XCOFF64Flag);11841185checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,1186AuxSize, *AuxHeader, this);1187}11881189template <typename T>1190void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {1191ListScope Group(W, "Sections");11921193uint16_t Index = 1;1194for (const T &Sec : Sections) {1195DictScope SecDS(W, "Section");11961197W.printNumber("Index", Index++);1198uint16_t SectionType = Sec.getSectionType();1199int32_t SectionSubtype = Sec.getSectionSubtype();1200switch (SectionType) {1201case XCOFF::STYP_OVRFLO:1202printOverflowSectionHeader(Sec);1203break;1204case XCOFF::STYP_LOADER:1205case XCOFF::STYP_EXCEPT:1206case XCOFF::STYP_TYPCHK:1207// TODO The interpretation of loader, exception and type check section1208// headers are different from that of generic section headers. We will1209// implement them later. We interpret them as generic section headers for1210// now.1211default:1212printGenericSectionHeader(Sec);1213break;1214}1215if (Sec.isReservedSectionType())1216W.printHex("Flags", "Reserved", SectionType);1217else {1218W.printEnum("Type", SectionType, ArrayRef(SectionTypeFlagsNames));1219if (SectionType == XCOFF::STYP_DWARF) {1220W.printEnum("DWARFSubType", SectionSubtype,1221ArrayRef(DWARFSectionSubtypeFlagsNames));1222}1223}1224}12251226if (opts::SectionRelocations)1227report_fatal_error("Dumping section relocations is unimplemented");12281229if (opts::SectionSymbols)1230report_fatal_error("Dumping symbols is unimplemented");12311232if (opts::SectionData)1233report_fatal_error("Dumping section data is unimplemented");1234}12351236namespace llvm {1237std::unique_ptr<ObjDumper>1238createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) {1239return std::make_unique<XCOFFDumper>(XObj, Writer);1240}1241} // namespace llvm124212431244