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/Object/XCOFFObjectFile.h" 16 #include "llvm/Support/ScopedPrinter.h" 17 18 using namespace llvm; 19 using namespace object; 20 21 namespace { 22 23 class XCOFFDumper : public ObjDumper { 24 25 public: 26 XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer) 27 : ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {} 28 29 void printFileHeaders() override; 30 void printSectionHeaders() override; 31 void printRelocations() override; 32 void printSymbols() override; 33 void printDynamicSymbols() override; 34 void printUnwindInfo() override; 35 void printStackMap() const override; 36 void printNeededLibraries() override; 37 void printStringTable() override; 38 39 private: 40 template <typename T> void printSectionHeaders(ArrayRef<T> Sections); 41 template <typename T> void printGenericSectionHeader(T &Sec) const; 42 template <typename T> void printOverflowSectionHeader(T &Sec) const; 43 void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr); 44 void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef); 45 void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr); 46 void printSymbol(const SymbolRef &); 47 void printRelocations(ArrayRef<XCOFFSectionHeader32> Sections); 48 const XCOFFObjectFile &Obj; 49 }; 50 } // anonymous namespace 51 52 void XCOFFDumper::printFileHeaders() { 53 DictScope DS(W, "FileHeader"); 54 W.printHex("Magic", Obj.getMagic()); 55 W.printNumber("NumberOfSections", Obj.getNumberOfSections()); 56 57 // Negative timestamp values are reserved for future use. 58 int32_t TimeStamp = Obj.getTimeStamp(); 59 if (TimeStamp > 0) { 60 // This handling of the time stamp assumes that the host system's time_t is 61 // compatible with AIX time_t. If a platform is not compatible, the lit 62 // tests will let us know. 63 time_t TimeDate = TimeStamp; 64 65 char FormattedTime[21] = {}; 66 size_t BytesWritten = 67 strftime(FormattedTime, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate)); 68 if (BytesWritten) 69 W.printHex("TimeStamp", FormattedTime, TimeStamp); 70 else 71 W.printHex("Timestamp", TimeStamp); 72 } else { 73 W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value", 74 TimeStamp); 75 } 76 77 // The number of symbol table entries is an unsigned value in 64-bit objects 78 // and a signed value (with negative values being 'reserved') in 32-bit 79 // objects. 80 if (Obj.is64Bit()) { 81 W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64()); 82 W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64()); 83 } else { 84 W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32()); 85 int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32(); 86 if (SymTabEntries >= 0) 87 W.printNumber("SymbolTableEntries", SymTabEntries); 88 else 89 W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries); 90 } 91 92 W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize()); 93 W.printHex("Flags", Obj.getFlags()); 94 95 // TODO FIXME Add support for the auxiliary header (if any) once 96 // XCOFFObjectFile has the necessary support. 97 } 98 99 void XCOFFDumper::printSectionHeaders() { 100 if (Obj.is64Bit()) 101 printSectionHeaders(Obj.sections64()); 102 else 103 printSectionHeaders(Obj.sections32()); 104 } 105 106 void XCOFFDumper::printRelocations() { 107 if (Obj.is64Bit()) 108 llvm_unreachable("64-bit relocation output not implemented!"); 109 else 110 printRelocations(Obj.sections32()); 111 } 112 113 static const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = { 114 #define ECase(X) \ 115 { #X, XCOFF::X } 116 ECase(R_POS), ECase(R_RL), ECase(R_RLA), ECase(R_NEG), 117 ECase(R_REL), ECase(R_TOC), ECase(R_TRL), ECase(R_TRLA), 118 ECase(R_GL), ECase(R_TCL), ECase(R_REF), ECase(R_BA), 119 ECase(R_BR), ECase(R_RBA), ECase(R_RBR), ECase(R_TLS), 120 ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM), 121 ECase(R_TLSML), ECase(R_TOCU), ECase(R_TOCL) 122 #undef ECase 123 }; 124 125 void XCOFFDumper::printRelocations(ArrayRef<XCOFFSectionHeader32> Sections) { 126 if (!opts::ExpandRelocs) 127 report_fatal_error("Unexpanded relocation output not implemented."); 128 129 ListScope LS(W, "Relocations"); 130 uint16_t Index = 0; 131 for (const auto &Sec : Sections) { 132 ++Index; 133 // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation. 134 if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA && 135 Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF) 136 continue; 137 auto Relocations = unwrapOrError(Obj.getFileName(), Obj.relocations(Sec)); 138 if (Relocations.empty()) 139 continue; 140 141 W.startLine() << "Section (index: " << Index << ") " << Sec.getName() 142 << " {\n"; 143 for (auto Reloc : Relocations) { 144 StringRef SymbolName = unwrapOrError( 145 Obj.getFileName(), Obj.getSymbolNameByIndex(Reloc.SymbolIndex)); 146 147 DictScope RelocScope(W, "Relocation"); 148 W.printHex("Virtual Address", Reloc.VirtualAddress); 149 W.printNumber("Symbol", SymbolName, Reloc.SymbolIndex); 150 W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No"); 151 W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0); 152 W.printNumber("Length", Reloc.getRelocatedLength()); 153 W.printEnum("Type", (uint8_t)Reloc.Type, 154 makeArrayRef(RelocationTypeNameclass)); 155 } 156 W.unindent(); 157 W.startLine() << "}\n"; 158 } 159 } 160 161 static const EnumEntry<XCOFF::CFileStringType> FileStringType[] = { 162 #define ECase(X) \ 163 { #X, XCOFF::X } 164 ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD) 165 #undef ECase 166 }; 167 168 static const EnumEntry<XCOFF::SymbolAuxType> SymAuxType[] = { 169 #define ECase(X) \ 170 { #X, XCOFF::X } 171 ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE), 172 ECase(AUX_CSECT), ECase(AUX_SECT) 173 #undef ECase 174 }; 175 176 void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) { 177 assert((!Obj.is64Bit() || AuxEntPtr->AuxType == XCOFF::AUX_FILE) && 178 "Mismatched auxiliary type!"); 179 StringRef FileName = 180 unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr)); 181 DictScope SymDs(W, "File Auxiliary Entry"); 182 W.printNumber("Index", 183 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr))); 184 W.printString("Name", FileName); 185 W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type), 186 makeArrayRef(FileStringType)); 187 if (Obj.is64Bit()) { 188 W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType), 189 makeArrayRef(SymAuxType)); 190 } 191 } 192 193 static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] = 194 { 195 #define ECase(X) \ 196 { #X, XCOFF::X } 197 ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB), ECase(XMC_GL), 198 ECase(XMC_XO), ECase(XMC_SV), ECase(XMC_SV64), ECase(XMC_SV3264), 199 ECase(XMC_TI), ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0), 200 ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS), ECase(XMC_UA), 201 ECase(XMC_BS), ECase(XMC_UC), ECase(XMC_TL), ECase(XMC_UL), 202 ECase(XMC_TE) 203 #undef ECase 204 }; 205 206 static const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = { 207 #define ECase(X) \ 208 { #X, XCOFF::X } 209 ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM) 210 #undef ECase 211 }; 212 213 void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) { 214 assert((!Obj.is64Bit() || AuxEntRef.getAuxType64() == XCOFF::AUX_CSECT) && 215 "Mismatched auxiliary type!"); 216 217 DictScope SymDs(W, "CSECT Auxiliary Entry"); 218 W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getEntryAddress())); 219 W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex" 220 : "SectionLen", 221 AuxEntRef.getSectionOrLength()); 222 W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex()); 223 W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum()); 224 // Print out symbol alignment and type. 225 W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2()); 226 W.printEnum("SymbolType", AuxEntRef.getSymbolType(), 227 makeArrayRef(CsectSymbolTypeClass)); 228 W.printEnum("StorageMappingClass", 229 static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()), 230 makeArrayRef(CsectStorageMappingClass)); 231 232 if (Obj.is64Bit()) { 233 W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT), 234 makeArrayRef(SymAuxType)); 235 } else { 236 W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32()); 237 W.printHex("StabSectNum", AuxEntRef.getStabSectNum32()); 238 } 239 } 240 241 void XCOFFDumper::printSectAuxEntForStat( 242 const XCOFFSectAuxEntForStat *AuxEntPtr) { 243 assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file."); 244 245 DictScope SymDs(W, "Sect Auxiliary Entry For Stat"); 246 W.printNumber("Index", 247 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr))); 248 W.printNumber("SectionLength", AuxEntPtr->SectionLength); 249 250 // Unlike the corresponding fields in the section header, NumberOfRelocEnt 251 // and NumberOfLineNum do not handle values greater than 65535. 252 W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt); 253 W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum); 254 } 255 256 static const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = { 257 #define ECase(X) \ 258 { #X, XCOFF::X } 259 ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT), 260 ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL), 261 ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU), 262 ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG), 263 ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK), 264 ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE), 265 ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL), 266 ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF), 267 ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM), 268 ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM), 269 ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY), 270 ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS), 271 ECase(C_STTLS), ECase(C_EFCN) 272 #undef ECase 273 }; 274 275 static StringRef GetSymbolValueName(XCOFF::StorageClass SC) { 276 switch (SC) { 277 case XCOFF::C_EXT: 278 case XCOFF::C_WEAKEXT: 279 case XCOFF::C_HIDEXT: 280 case XCOFF::C_STAT: 281 return "Value (RelocatableAddress)"; 282 case XCOFF::C_FILE: 283 return "Value (SymbolTableIndex)"; 284 case XCOFF::C_FCN: 285 case XCOFF::C_BLOCK: 286 case XCOFF::C_FUN: 287 case XCOFF::C_STSYM: 288 case XCOFF::C_BINCL: 289 case XCOFF::C_EINCL: 290 case XCOFF::C_INFO: 291 case XCOFF::C_BSTAT: 292 case XCOFF::C_LSYM: 293 case XCOFF::C_PSYM: 294 case XCOFF::C_RPSYM: 295 case XCOFF::C_RSYM: 296 case XCOFF::C_ECOML: 297 case XCOFF::C_DWARF: 298 assert(false && "This StorageClass for the symbol is not yet implemented."); 299 return ""; 300 default: 301 return "Value"; 302 } 303 } 304 305 static const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = { 306 #define ECase(X) \ 307 { #X, XCOFF::X } 308 ECase(TB_C), ECase(TB_CPLUSPLUS) 309 #undef ECase 310 }; 311 312 static const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = { 313 #define ECase(X) \ 314 { #X, XCOFF::X } 315 ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970) 316 #undef ECase 317 }; 318 319 void XCOFFDumper::printSymbol(const SymbolRef &S) { 320 DataRefImpl SymbolDRI = S.getRawDataRefImpl(); 321 XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI); 322 323 uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries(); 324 325 DictScope SymDs(W, "Symbol"); 326 327 StringRef SymbolName = 328 unwrapOrError(Obj.getFileName(), SymbolEntRef.getName()); 329 330 W.printNumber("Index", Obj.getSymbolIndex(SymbolEntRef.getEntryAddress())); 331 W.printString("Name", SymbolName); 332 W.printHex(GetSymbolValueName(SymbolEntRef.getStorageClass()), 333 SymbolEntRef.getValue()); 334 335 StringRef SectionName = 336 unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef)); 337 338 W.printString("Section", SectionName); 339 if (SymbolEntRef.getStorageClass() == XCOFF::C_FILE) { 340 W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(), 341 makeArrayRef(CFileLangIdClass)); 342 W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(), 343 makeArrayRef(CFileCpuIdClass)); 344 } else 345 W.printHex("Type", SymbolEntRef.getSymbolType()); 346 347 W.printEnum("StorageClass", 348 static_cast<uint8_t>(SymbolEntRef.getStorageClass()), 349 makeArrayRef(SymStorageClass)); 350 W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries); 351 352 if (NumberOfAuxEntries == 0) 353 return; 354 355 switch (SymbolEntRef.getStorageClass()) { 356 case XCOFF::C_FILE: 357 // If the symbol is C_FILE and has auxiliary entries... 358 for (int I = 1; I <= NumberOfAuxEntries; I++) { 359 uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 360 SymbolEntRef.getEntryAddress(), I); 361 362 if (Obj.is64Bit() && 363 *Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) { 364 W.startLine() << "!Unexpected raw auxiliary entry data:\n"; 365 W.startLine() << format_bytes( 366 ArrayRef<uint8_t>( 367 reinterpret_cast<const uint8_t *>(AuxAddress), 368 XCOFF::SymbolTableEntrySize), 369 0, XCOFF::SymbolTableEntrySize) 370 << "\n"; 371 continue; 372 } 373 374 const XCOFFFileAuxEnt *FileAuxEntPtr = 375 reinterpret_cast<const XCOFFFileAuxEnt *>(AuxAddress); 376 #ifndef NDEBUG 377 Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(FileAuxEntPtr)); 378 #endif 379 printFileAuxEnt(FileAuxEntPtr); 380 } 381 break; 382 case XCOFF::C_EXT: 383 case XCOFF::C_WEAKEXT: 384 case XCOFF::C_HIDEXT: { 385 // If the symbol is for a function, and it has more than 1 auxiliary entry, 386 // then one of them must be function auxiliary entry which we do not 387 // support yet. 388 if (SymbolEntRef.isFunction() && NumberOfAuxEntries >= 2) 389 report_fatal_error("Function auxiliary entry printing is unimplemented."); 390 391 // If there is more than 1 auxiliary entry, instead of printing out 392 // error information, print out the raw Auxiliary entry. 393 // For 32-bit object, print from first to the last - 1. The last one must be 394 // a CSECT Auxiliary Entry. 395 // For 64-bit object, print from first to last and skips if SymbolAuxType is 396 // AUX_CSECT. 397 for (int I = 1; I <= NumberOfAuxEntries; I++) { 398 if (I == NumberOfAuxEntries && !Obj.is64Bit()) 399 break; 400 401 uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 402 SymbolEntRef.getEntryAddress(), I); 403 if (Obj.is64Bit() && 404 *Obj.getSymbolAuxType(AuxAddress) == XCOFF::SymbolAuxType::AUX_CSECT) 405 continue; 406 407 W.startLine() << "!Unexpected raw auxiliary entry data:\n"; 408 W.startLine() << format_bytes( 409 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(AuxAddress), 410 XCOFF::SymbolTableEntrySize)); 411 } 412 413 auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef(); 414 if (!ErrOrCsectAuxRef) 415 reportUniqueWarning(ErrOrCsectAuxRef.takeError()); 416 else 417 printCsectAuxEnt(*ErrOrCsectAuxRef); 418 419 break; 420 } 421 case XCOFF::C_STAT: 422 if (NumberOfAuxEntries > 1) 423 report_fatal_error( 424 "C_STAT symbol should not have more than 1 auxiliary entry."); 425 426 const XCOFFSectAuxEntForStat *StatAuxEntPtr; 427 StatAuxEntPtr = reinterpret_cast<const XCOFFSectAuxEntForStat *>( 428 XCOFFObjectFile::getAdvancedSymbolEntryAddress( 429 SymbolEntRef.getEntryAddress(), 1)); 430 #ifndef NDEBUG 431 Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(StatAuxEntPtr)); 432 #endif 433 printSectAuxEntForStat(StatAuxEntPtr); 434 break; 435 case XCOFF::C_DWARF: 436 case XCOFF::C_BLOCK: 437 case XCOFF::C_FCN: 438 report_fatal_error("Symbol table entry printing for this storage class " 439 "type is unimplemented."); 440 break; 441 default: 442 for (int i = 1; i <= NumberOfAuxEntries; i++) { 443 W.startLine() << "!Unexpected raw auxiliary entry data:\n"; 444 W.startLine() << format_bytes( 445 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>( 446 XCOFFObjectFile::getAdvancedSymbolEntryAddress( 447 SymbolEntRef.getEntryAddress(), i)), 448 XCOFF::SymbolTableEntrySize)); 449 } 450 break; 451 } 452 } 453 454 void XCOFFDumper::printSymbols() { 455 ListScope Group(W, "Symbols"); 456 for (const SymbolRef &S : Obj.symbols()) 457 printSymbol(S); 458 } 459 460 void XCOFFDumper::printStringTable() { 461 DictScope DS(W, "StringTable"); 462 StringRef StrTable = Obj.getStringTable(); 463 printAsStringList(StrTable); 464 } 465 466 void XCOFFDumper::printDynamicSymbols() { 467 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 468 } 469 470 void XCOFFDumper::printUnwindInfo() { 471 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 472 } 473 474 void XCOFFDumper::printStackMap() const { 475 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 476 } 477 478 void XCOFFDumper::printNeededLibraries() { 479 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 480 } 481 482 static const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = { 483 #define ECase(X) \ 484 { #X, XCOFF::X } 485 ECase(STYP_PAD), ECase(STYP_DWARF), ECase(STYP_TEXT), 486 ECase(STYP_DATA), ECase(STYP_BSS), ECase(STYP_EXCEPT), 487 ECase(STYP_INFO), ECase(STYP_TDATA), ECase(STYP_TBSS), 488 ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK), 489 ECase(STYP_OVRFLO) 490 #undef ECase 491 }; 492 493 template <typename T> 494 void XCOFFDumper::printOverflowSectionHeader(T &Sec) const { 495 if (Obj.is64Bit()) { 496 reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not " 497 "contain an overflow section header.", 498 object_error::parse_failed), 499 Obj.getFileName()); 500 } 501 502 W.printString("Name", Sec.getName()); 503 W.printNumber("NumberOfRelocations", Sec.PhysicalAddress); 504 W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress); 505 W.printHex("Size", Sec.SectionSize); 506 W.printHex("RawDataOffset", Sec.FileOffsetToRawData); 507 W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo); 508 W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo); 509 W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations); 510 W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers); 511 } 512 513 template <typename T> 514 void XCOFFDumper::printGenericSectionHeader(T &Sec) const { 515 W.printString("Name", Sec.getName()); 516 W.printHex("PhysicalAddress", Sec.PhysicalAddress); 517 W.printHex("VirtualAddress", Sec.VirtualAddress); 518 W.printHex("Size", Sec.SectionSize); 519 W.printHex("RawDataOffset", Sec.FileOffsetToRawData); 520 W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo); 521 W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo); 522 W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations); 523 W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers); 524 } 525 526 template <typename T> 527 void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) { 528 ListScope Group(W, "Sections"); 529 530 uint16_t Index = 1; 531 for (const T &Sec : Sections) { 532 DictScope SecDS(W, "Section"); 533 534 W.printNumber("Index", Index++); 535 uint16_t SectionType = Sec.getSectionType(); 536 switch (SectionType) { 537 case XCOFF::STYP_OVRFLO: 538 printOverflowSectionHeader(Sec); 539 break; 540 case XCOFF::STYP_LOADER: 541 case XCOFF::STYP_EXCEPT: 542 case XCOFF::STYP_TYPCHK: 543 // TODO The interpretation of loader, exception and type check section 544 // headers are different from that of generic section headers. We will 545 // implement them later. We interpret them as generic section headers for 546 // now. 547 default: 548 printGenericSectionHeader(Sec); 549 break; 550 } 551 if (Sec.isReservedSectionType()) 552 W.printHex("Flags", "Reserved", SectionType); 553 else 554 W.printEnum("Type", SectionType, makeArrayRef(SectionTypeFlagsNames)); 555 } 556 557 if (opts::SectionRelocations) 558 report_fatal_error("Dumping section relocations is unimplemented"); 559 560 if (opts::SectionSymbols) 561 report_fatal_error("Dumping symbols is unimplemented"); 562 563 if (opts::SectionData) 564 report_fatal_error("Dumping section data is unimplemented"); 565 } 566 567 namespace llvm { 568 std::unique_ptr<ObjDumper> 569 createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) { 570 return std::make_unique<XCOFFDumper>(XObj, Writer); 571 } 572 } // namespace llvm 573