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-exception 6 // 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 22 using namespace llvm; 23 using namespace object; 24 25 namespace { 26 27 class XCOFFDumper : public ObjDumper { 28 29 public: 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 49 private: 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 namespace 88 89 void 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 is 98 // compatible with AIX time_t. If a platform is not compatible, the lit 99 // 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 else 109 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 objects 116 // and a signed value (with negative values being 'reserved') in 32-bit 117 // 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 else 127 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) once 134 // XCOFFObjectFile has the necessary support. 135 } 136 137 void XCOFFDumper::printAuxiliaryHeader() { 138 DictScope DS(W, "AuxiliaryHeader"); 139 140 if (Obj.is64Bit()) 141 printAuxiliaryHeader(Obj.auxiliaryHeader64()); 142 else 143 printAuxiliaryHeader(Obj.auxiliaryHeader32()); 144 } 145 146 void XCOFFDumper::printSectionHeaders() { 147 if (Obj.is64Bit()) 148 printSectionHeaders(Obj.sections64()); 149 else 150 printSectionHeaders(Obj.sections32()); 151 } 152 153 void 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 180 void 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 208 const 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 ECase 225 }; 226 227 template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader> 228 void 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 267 void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr) { 268 DictScope DS(W, "Loader Section Symbols"); 269 if (Obj.is64Bit()) 270 printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry64, 271 LoaderSectionHeader64>(LoaderSectionAddr); 272 else 273 printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry32, 274 LoaderSectionHeader32>(LoaderSectionAddr); 275 } 276 277 const 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 ECase 287 }; 288 289 // From the XCOFF specification: there are five implicit external symbols, one 290 // each for the .text, .data, .bss, .tdata, and .tbss sections. These symbols 291 // are referenced from the relocation table entries using symbol table index 292 // values 0, 1, 2, -1, and -2, respectively. 293 static 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 310 template <typename LoadSectionRelocTy> 311 void 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. Add 324 // back 325 // 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 352 template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry, 353 typename LoaderSectionRelocationEntry> 354 void 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 the 373 // 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 } else 390 SymbolName = 391 getImplicitLoaderSectionSymName(LoaderSecRelEntPtr->SymbolIndex); 392 393 printLoaderSectionRelocationEntry(LoaderSecRelEntPtr, SymbolName); 394 } 395 } 396 397 void 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 else 407 printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader32, 408 LoaderSectionSymbolEntry32, 409 LoaderSectionRelocationEntry32>( 410 LoaderSectionAddr); 411 } 412 413 template <typename T> 414 void 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 432 template <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 447 void XCOFFDumper::printExceptionSection() { 448 if (Obj.is64Bit()) 449 printExceptionSectionEntries<ExceptionSectionEntry64>(); 450 else 451 printExceptionSectionEntries<ExceptionSectionEntry32>(); 452 } 453 454 void XCOFFDumper::printRelocations() { 455 if (Obj.is64Bit()) 456 printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64()); 457 else 458 printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32()); 459 } 460 461 template <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 487 template <typename Shdr, typename RelTy> 488 void 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 519 const 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 ECase 524 }; 525 526 const 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 ECase 532 }; 533 534 void 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 551 static 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 ECase 562 }; 563 564 const 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 ECase 569 }; 570 571 void 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 599 void 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, NumberOfRelocEnt 609 // and NumberOfLineNum do not handle values greater than 65535. 610 W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt); 611 W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum); 612 } 613 614 void 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 627 void 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 639 void 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 652 void 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 662 void 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 673 template <typename T> 674 void 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 685 static 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 return "Value (SymbolTableIndex)"; 696 case XCOFF::C_DWARF: 697 return "Value (OffsetInDWARF)"; 698 case XCOFF::C_FUN: 699 case XCOFF::C_STSYM: 700 case XCOFF::C_BINCL: 701 case XCOFF::C_EINCL: 702 case XCOFF::C_INFO: 703 case XCOFF::C_BSTAT: 704 case XCOFF::C_LSYM: 705 case XCOFF::C_PSYM: 706 case XCOFF::C_RPSYM: 707 case XCOFF::C_RSYM: 708 case XCOFF::C_ECOML: 709 assert(false && "This StorageClass for the symbol is not yet implemented."); 710 return ""; 711 default: 712 return "Value"; 713 } 714 } 715 716 const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = { 717 #define ECase(X) \ 718 { #X, XCOFF::X } 719 ECase(TB_C), ECase(TB_Fortran), ECase(TB_CPLUSPLUS) 720 #undef ECase 721 }; 722 723 const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = { 724 #define ECase(X) \ 725 { #X, XCOFF::X } 726 ECase(TCPU_INVALID), ECase(TCPU_PPC), ECase(TCPU_PPC64), ECase(TCPU_COM), 727 ECase(TCPU_PWR), ECase(TCPU_ANY), ECase(TCPU_601), ECase(TCPU_603), 728 ECase(TCPU_604), ECase(TCPU_620), ECase(TCPU_A35), ECase(TCPU_970), 729 ECase(TCPU_PWR5), ECase(TCPU_PWR6), ECase(TCPU_PWR5X), ECase(TCPU_PWR6E), 730 ECase(TCPU_PWR7), ECase(TCPU_PWR8), ECase(TCPU_PWR9), ECase(TCPU_PWR10), 731 ECase(TCPU_PWRX) 732 #undef ECase 733 }; 734 735 template <typename T> const T *XCOFFDumper::getAuxEntPtr(uintptr_t AuxAddress) { 736 const T *AuxEntPtr = reinterpret_cast<const T *>(AuxAddress); 737 Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(AuxEntPtr)); 738 return AuxEntPtr; 739 } 740 741 static void printUnexpectedRawAuxEnt(ScopedPrinter &W, uintptr_t AuxAddress) { 742 W.startLine() << "!Unexpected raw auxiliary entry data:\n"; 743 W.startLine() << format_bytes( 744 ArrayRef<uint8_t>( 745 reinterpret_cast<const uint8_t *>(AuxAddress), 746 XCOFF::SymbolTableEntrySize), 747 std::nullopt, XCOFF::SymbolTableEntrySize) 748 << "\n"; 749 } 750 751 void XCOFFDumper::printSymbol(const SymbolRef &S) { 752 DataRefImpl SymbolDRI = S.getRawDataRefImpl(); 753 XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI); 754 755 uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries(); 756 757 DictScope SymDs(W, "Symbol"); 758 759 StringRef SymbolName = 760 unwrapOrError(Obj.getFileName(), SymbolEntRef.getName()); 761 762 uint32_t SymbolIdx = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress()); 763 XCOFF::StorageClass SymbolClass = SymbolEntRef.getStorageClass(); 764 765 W.printNumber("Index", SymbolIdx); 766 W.printString("Name", opts::Demangle ? demangle(SymbolName) : SymbolName); 767 W.printHex(GetSymbolValueName(SymbolClass), SymbolEntRef.getValue()); 768 769 StringRef SectionName = 770 unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef)); 771 772 W.printString("Section", SectionName); 773 if (SymbolClass == XCOFF::C_FILE) { 774 W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(), 775 ArrayRef(CFileLangIdClass)); 776 W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(), 777 ArrayRef(CFileCpuIdClass)); 778 } else 779 W.printHex("Type", SymbolEntRef.getSymbolType()); 780 781 W.printEnum("StorageClass", static_cast<uint8_t>(SymbolClass), 782 ArrayRef(SymStorageClass)); 783 W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries); 784 785 if (NumberOfAuxEntries == 0) 786 return; 787 788 auto checkNumOfAux = [=] { 789 if (NumberOfAuxEntries > 1) 790 reportUniqueWarning("the " + 791 enumToString(static_cast<uint8_t>(SymbolClass), 792 ArrayRef(SymStorageClass)) + 793 " symbol at index " + Twine(SymbolIdx) + 794 " should not have more than 1 " 795 "auxiliary entry"); 796 }; 797 798 switch (SymbolClass) { 799 case XCOFF::C_FILE: 800 // If the symbol is C_FILE and has auxiliary entries... 801 for (int I = 1; I <= NumberOfAuxEntries; I++) { 802 uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 803 SymbolEntRef.getEntryAddress(), I); 804 805 if (Obj.is64Bit() && 806 *Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) { 807 printUnexpectedRawAuxEnt(W, AuxAddress); 808 continue; 809 } 810 811 const XCOFFFileAuxEnt *FileAuxEntPtr = 812 getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress); 813 printFileAuxEnt(FileAuxEntPtr); 814 } 815 break; 816 case XCOFF::C_EXT: 817 case XCOFF::C_WEAKEXT: 818 case XCOFF::C_HIDEXT: { 819 // For 32-bit objects, print the function auxiliary symbol table entry. The 820 // last one must be a CSECT auxiliary entry. 821 // For 64-bit objects, both a function auxiliary entry and an exception 822 // auxiliary entry may appear, print them in the loop and skip printing the 823 // CSECT auxiliary entry, which will be printed outside the loop. 824 for (int I = 1; I <= NumberOfAuxEntries; I++) { 825 if (I == NumberOfAuxEntries && !Obj.is64Bit()) 826 break; 827 828 uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 829 SymbolEntRef.getEntryAddress(), I); 830 831 if (Obj.is64Bit()) { 832 XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress); 833 if (Type == XCOFF::SymbolAuxType::AUX_CSECT) 834 continue; 835 if (Type == XCOFF::SymbolAuxType::AUX_FCN) { 836 const XCOFFFunctionAuxEnt64 *AuxEntPtr = 837 getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress); 838 printFunctionAuxEnt(AuxEntPtr); 839 } else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT) { 840 const XCOFFExceptionAuxEnt *AuxEntPtr = 841 getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress); 842 printExceptionAuxEnt(AuxEntPtr); 843 } else { 844 printUnexpectedRawAuxEnt(W, AuxAddress); 845 } 846 } else { 847 const XCOFFFunctionAuxEnt32 *AuxEntPtr = 848 getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress); 849 printFunctionAuxEnt(AuxEntPtr); 850 } 851 } 852 853 // Print the CSECT auxiliary entry. 854 auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef(); 855 if (!ErrOrCsectAuxRef) 856 reportUniqueWarning(ErrOrCsectAuxRef.takeError()); 857 else 858 printCsectAuxEnt(*ErrOrCsectAuxRef); 859 860 break; 861 } 862 case XCOFF::C_STAT: { 863 checkNumOfAux(); 864 865 const XCOFFSectAuxEntForStat *StatAuxEntPtr = 866 getAuxEntPtr<XCOFFSectAuxEntForStat>( 867 XCOFFObjectFile::getAdvancedSymbolEntryAddress( 868 SymbolEntRef.getEntryAddress(), 1)); 869 printSectAuxEntForStat(StatAuxEntPtr); 870 break; 871 } 872 case XCOFF::C_DWARF: { 873 checkNumOfAux(); 874 875 uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 876 SymbolEntRef.getEntryAddress(), 1); 877 878 if (Obj.is64Bit()) { 879 const XCOFFSectAuxEntForDWARF64 *AuxEntPtr = 880 getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress); 881 printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF64>(AuxEntPtr); 882 } else { 883 const XCOFFSectAuxEntForDWARF32 *AuxEntPtr = 884 getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress); 885 printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF32>(AuxEntPtr); 886 } 887 break; 888 } 889 case XCOFF::C_BLOCK: 890 case XCOFF::C_FCN: { 891 checkNumOfAux(); 892 893 uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 894 SymbolEntRef.getEntryAddress(), 1); 895 896 if (Obj.is64Bit()) { 897 const XCOFFBlockAuxEnt64 *AuxEntPtr = 898 getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress); 899 printBlockAuxEnt(AuxEntPtr); 900 } else { 901 const XCOFFBlockAuxEnt32 *AuxEntPtr = 902 getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress); 903 printBlockAuxEnt(AuxEntPtr); 904 } 905 break; 906 } 907 default: 908 for (int i = 1; i <= NumberOfAuxEntries; i++) { 909 printUnexpectedRawAuxEnt(W, 910 XCOFFObjectFile::getAdvancedSymbolEntryAddress( 911 SymbolEntRef.getEntryAddress(), i)); 912 } 913 break; 914 } 915 } 916 917 void XCOFFDumper::printSymbols(bool /*ExtraSymInfo*/) { 918 ListScope Group(W, "Symbols"); 919 for (const SymbolRef &S : Obj.symbols()) 920 printSymbol(S); 921 } 922 923 void XCOFFDumper::printStringTable() { 924 DictScope DS(W, "StringTable"); 925 StringRef StrTable = Obj.getStringTable(); 926 uint32_t StrTabSize = StrTable.size(); 927 W.printNumber("Length", StrTabSize); 928 // Print strings from the fifth byte, since the first four bytes contain the 929 // length (in bytes) of the string table (including the length field). 930 if (StrTabSize > 4) 931 printAsStringList(StrTable, 4); 932 } 933 934 void XCOFFDumper::printDynamicSymbols() { 935 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 936 } 937 938 void XCOFFDumper::printUnwindInfo() { 939 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 940 } 941 942 void XCOFFDumper::printStackMap() const { 943 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 944 } 945 946 void XCOFFDumper::printNeededLibraries() { 947 ListScope D(W, "NeededLibraries"); 948 auto ImportFilesOrError = Obj.getImportFileTable(); 949 if (!ImportFilesOrError) { 950 reportUniqueWarning(ImportFilesOrError.takeError()); 951 return; 952 } 953 954 StringRef ImportFileTable = ImportFilesOrError.get(); 955 const char *CurrentStr = ImportFileTable.data(); 956 const char *TableEnd = ImportFileTable.end(); 957 // Default column width for names is 13 even if no names are that long. 958 size_t BaseWidth = 13; 959 960 // Get the max width of BASE columns. 961 for (size_t StrIndex = 0; CurrentStr < TableEnd; ++StrIndex) { 962 size_t CurrentLen = strlen(CurrentStr); 963 CurrentStr += strlen(CurrentStr) + 1; 964 if (StrIndex % 3 == 1) 965 BaseWidth = std::max(BaseWidth, CurrentLen); 966 } 967 968 auto &OS = static_cast<formatted_raw_ostream &>(W.startLine()); 969 // Each entry consists of 3 strings: the path_name, base_name and 970 // archive_member_name. The first entry is a default LIBPATH value and other 971 // entries have no path_name. We just dump the base_name and 972 // archive_member_name here. 973 OS << left_justify("BASE", BaseWidth) << " MEMBER\n"; 974 CurrentStr = ImportFileTable.data(); 975 for (size_t StrIndex = 0; CurrentStr < TableEnd; 976 ++StrIndex, CurrentStr += strlen(CurrentStr) + 1) { 977 if (StrIndex >= 3 && StrIndex % 3 != 0) { 978 if (StrIndex % 3 == 1) 979 OS << " " << left_justify(CurrentStr, BaseWidth) << " "; 980 else 981 OS << CurrentStr << "\n"; 982 } 983 } 984 } 985 986 const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = { 987 #define ECase(X) \ 988 { #X, XCOFF::X } 989 ECase(STYP_PAD), ECase(STYP_DWARF), ECase(STYP_TEXT), 990 ECase(STYP_DATA), ECase(STYP_BSS), ECase(STYP_EXCEPT), 991 ECase(STYP_INFO), ECase(STYP_TDATA), ECase(STYP_TBSS), 992 ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK), 993 ECase(STYP_OVRFLO) 994 #undef ECase 995 }; 996 997 const EnumEntry<XCOFF::DwarfSectionSubtypeFlags> 998 DWARFSectionSubtypeFlagsNames[] = { 999 #define ECase(X) \ 1000 { #X, XCOFF::X } 1001 ECase(SSUBTYP_DWINFO), ECase(SSUBTYP_DWLINE), ECase(SSUBTYP_DWPBNMS), 1002 ECase(SSUBTYP_DWPBTYP), ECase(SSUBTYP_DWARNGE), ECase(SSUBTYP_DWABREV), 1003 ECase(SSUBTYP_DWSTR), ECase(SSUBTYP_DWRNGES), ECase(SSUBTYP_DWLOC), 1004 ECase(SSUBTYP_DWFRAME), ECase(SSUBTYP_DWMAC) 1005 #undef ECase 1006 }; 1007 1008 template <typename T> 1009 void XCOFFDumper::printOverflowSectionHeader(T &Sec) const { 1010 if (Obj.is64Bit()) { 1011 reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not " 1012 "contain an overflow section header.", 1013 object_error::parse_failed), 1014 Obj.getFileName()); 1015 } 1016 1017 W.printString("Name", Sec.getName()); 1018 W.printNumber("NumberOfRelocations", Sec.PhysicalAddress); 1019 W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress); 1020 W.printHex("Size", Sec.SectionSize); 1021 W.printHex("RawDataOffset", Sec.FileOffsetToRawData); 1022 W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo); 1023 W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo); 1024 W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations); 1025 W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers); 1026 } 1027 1028 template <typename T> 1029 void XCOFFDumper::printGenericSectionHeader(T &Sec) const { 1030 W.printString("Name", Sec.getName()); 1031 W.printHex("PhysicalAddress", Sec.PhysicalAddress); 1032 W.printHex("VirtualAddress", Sec.VirtualAddress); 1033 W.printHex("Size", Sec.SectionSize); 1034 W.printHex("RawDataOffset", Sec.FileOffsetToRawData); 1035 W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo); 1036 W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo); 1037 W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations); 1038 W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers); 1039 } 1040 1041 enum PrintStyle { Hex, Number }; 1042 template <typename T, typename V> 1043 static void printAuxMemberHelper(PrintStyle Style, const char *MemberName, 1044 const T &Member, const V *AuxHeader, 1045 uint16_t AuxSize, uint16_t &PartialFieldOffset, 1046 const char *&PartialFieldName, 1047 ScopedPrinter &W) { 1048 ptrdiff_t Offset = reinterpret_cast<const char *>(&Member) - 1049 reinterpret_cast<const char *>(AuxHeader); 1050 if (Offset + sizeof(Member) <= AuxSize) 1051 Style == Hex ? W.printHex(MemberName, Member) 1052 : W.printNumber(MemberName, Member); 1053 else if (Offset < AuxSize) { 1054 PartialFieldOffset = Offset; 1055 PartialFieldName = MemberName; 1056 } 1057 } 1058 1059 template <class T> 1060 void checkAndPrintAuxHeaderParseError(const char *PartialFieldName, 1061 uint16_t PartialFieldOffset, 1062 uint16_t AuxSize, T &AuxHeader, 1063 XCOFFDumper *Dumper) { 1064 if (PartialFieldOffset < AuxSize) { 1065 Dumper->reportUniqueWarning(Twine("only partial field for ") + 1066 PartialFieldName + " at offset (" + 1067 Twine(PartialFieldOffset) + ")"); 1068 Dumper->getScopedPrinter().printBinary( 1069 "Raw data", "", 1070 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) + 1071 PartialFieldOffset, 1072 AuxSize - PartialFieldOffset)); 1073 } else if (sizeof(AuxHeader) < AuxSize) 1074 Dumper->getScopedPrinter().printBinary( 1075 "Extra raw data", "", 1076 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) + 1077 sizeof(AuxHeader), 1078 AuxSize - sizeof(AuxHeader))); 1079 } 1080 1081 void XCOFFDumper::printAuxiliaryHeader( 1082 const XCOFFAuxiliaryHeader32 *AuxHeader) { 1083 if (AuxHeader == nullptr) 1084 return; 1085 uint16_t AuxSize = Obj.getOptionalHeaderSize(); 1086 uint16_t PartialFieldOffset = AuxSize; 1087 const char *PartialFieldName = nullptr; 1088 1089 auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName, 1090 auto &Member) { 1091 printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize, 1092 PartialFieldOffset, PartialFieldName, W); 1093 }; 1094 1095 PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic); 1096 PrintAuxMember(Hex, "Version", AuxHeader->Version); 1097 PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize); 1098 PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize); 1099 PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize); 1100 PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr); 1101 PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr); 1102 PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr); 1103 PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr); 1104 PrintAuxMember(Number, "Section number of entryPoint", 1105 AuxHeader->SecNumOfEntryPoint); 1106 PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText); 1107 PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData); 1108 PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC); 1109 PrintAuxMember(Number, "Section number of loader data", 1110 AuxHeader->SecNumOfLoader); 1111 PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS); 1112 PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText); 1113 PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData); 1114 PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType); 1115 PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag); 1116 PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType); 1117 PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize); 1118 PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize); 1119 PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger); 1120 PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize); 1121 PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize); 1122 PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize); 1123 if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) + 1124 sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <= 1125 AuxSize) { 1126 W.printHex("Flag", AuxHeader->getFlag()); 1127 W.printHex("Alignment of thread-local storage", 1128 AuxHeader->getTDataAlignment()); 1129 } 1130 1131 PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData); 1132 PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS); 1133 1134 checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset, 1135 AuxSize, *AuxHeader, this); 1136 } 1137 1138 void XCOFFDumper::printAuxiliaryHeader( 1139 const XCOFFAuxiliaryHeader64 *AuxHeader) { 1140 if (AuxHeader == nullptr) 1141 return; 1142 uint16_t AuxSize = Obj.getOptionalHeaderSize(); 1143 uint16_t PartialFieldOffset = AuxSize; 1144 const char *PartialFieldName = nullptr; 1145 1146 auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName, 1147 auto &Member) { 1148 printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize, 1149 PartialFieldOffset, PartialFieldName, W); 1150 }; 1151 1152 PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic); 1153 PrintAuxMember(Hex, "Version", AuxHeader->Version); 1154 PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger); 1155 PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr); 1156 PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr); 1157 PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr); 1158 PrintAuxMember(Number, "Section number of entryPoint", 1159 AuxHeader->SecNumOfEntryPoint); 1160 PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText); 1161 PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData); 1162 PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC); 1163 PrintAuxMember(Number, "Section number of loader data", 1164 AuxHeader->SecNumOfLoader); 1165 PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS); 1166 PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText); 1167 PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData); 1168 PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType); 1169 PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag); 1170 PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType); 1171 PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize); 1172 PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize); 1173 PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize); 1174 if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) + 1175 sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <= 1176 AuxSize) { 1177 W.printHex("Flag", AuxHeader->getFlag()); 1178 W.printHex("Alignment of thread-local storage", 1179 AuxHeader->getTDataAlignment()); 1180 } 1181 PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize); 1182 PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize); 1183 PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize); 1184 PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr); 1185 PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize); 1186 PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize); 1187 PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData); 1188 PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS); 1189 PrintAuxMember(Hex, "Additional flags 64-bit XCOFF", AuxHeader->XCOFF64Flag); 1190 1191 checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset, 1192 AuxSize, *AuxHeader, this); 1193 } 1194 1195 template <typename T> 1196 void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) { 1197 ListScope Group(W, "Sections"); 1198 1199 uint16_t Index = 1; 1200 for (const T &Sec : Sections) { 1201 DictScope SecDS(W, "Section"); 1202 1203 W.printNumber("Index", Index++); 1204 uint16_t SectionType = Sec.getSectionType(); 1205 int32_t SectionSubtype = Sec.getSectionSubtype(); 1206 switch (SectionType) { 1207 case XCOFF::STYP_OVRFLO: 1208 printOverflowSectionHeader(Sec); 1209 break; 1210 case XCOFF::STYP_LOADER: 1211 case XCOFF::STYP_EXCEPT: 1212 case XCOFF::STYP_TYPCHK: 1213 // TODO The interpretation of loader, exception and type check section 1214 // headers are different from that of generic section headers. We will 1215 // implement them later. We interpret them as generic section headers for 1216 // now. 1217 default: 1218 printGenericSectionHeader(Sec); 1219 break; 1220 } 1221 if (Sec.isReservedSectionType()) 1222 W.printHex("Flags", "Reserved", SectionType); 1223 else { 1224 W.printEnum("Type", SectionType, ArrayRef(SectionTypeFlagsNames)); 1225 if (SectionType == XCOFF::STYP_DWARF) { 1226 W.printEnum("DWARFSubType", SectionSubtype, 1227 ArrayRef(DWARFSectionSubtypeFlagsNames)); 1228 } 1229 } 1230 } 1231 1232 if (opts::SectionRelocations) 1233 report_fatal_error("Dumping section relocations is unimplemented"); 1234 1235 if (opts::SectionSymbols) 1236 report_fatal_error("Dumping symbols is unimplemented"); 1237 1238 if (opts::SectionData) 1239 report_fatal_error("Dumping section data is unimplemented"); 1240 } 1241 1242 namespace llvm { 1243 std::unique_ptr<ObjDumper> 1244 createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) { 1245 return std::make_unique<XCOFFDumper>(XObj, Writer); 1246 } 1247 } // namespace llvm 1248