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