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