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 printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr); 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 void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) { 168 if (Obj.is64Bit()) 169 report_fatal_error( 170 "Printing for File Auxiliary Entry in 64-bit is unimplemented."); 171 StringRef FileName = 172 unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr)); 173 DictScope SymDs(W, "File Auxiliary Entry"); 174 W.printNumber("Index", 175 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr))); 176 W.printString("Name", FileName); 177 W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type), 178 makeArrayRef(FileStringType)); 179 } 180 181 static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] = 182 { 183 #define ECase(X) \ 184 { #X, XCOFF::X } 185 ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB), 186 ECase(XMC_GL), ECase(XMC_XO), ECase(XMC_SV), 187 ECase(XMC_SV64), ECase(XMC_SV3264), ECase(XMC_TI), 188 ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0), 189 ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS), 190 ECase(XMC_UA), ECase(XMC_BS), ECase(XMC_UC), 191 ECase(XMC_TL), ECase(XMC_TE) 192 #undef ECase 193 }; 194 195 static const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = { 196 #define ECase(X) \ 197 { #X, XCOFF::X } 198 ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM) 199 #undef ECase 200 }; 201 202 void XCOFFDumper::printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr) { 203 assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file."); 204 205 DictScope SymDs(W, "CSECT Auxiliary Entry"); 206 W.printNumber("Index", 207 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr))); 208 if (AuxEntPtr->isLabel()) 209 W.printNumber("ContainingCsectSymbolIndex", AuxEntPtr->SectionOrLength); 210 else 211 W.printNumber("SectionLen", AuxEntPtr->SectionOrLength); 212 W.printHex("ParameterHashIndex", AuxEntPtr->ParameterHashIndex); 213 W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum); 214 // Print out symbol alignment and type. 215 W.printNumber("SymbolAlignmentLog2", AuxEntPtr->getAlignmentLog2()); 216 W.printEnum("SymbolType", AuxEntPtr->getSymbolType(), 217 makeArrayRef(CsectSymbolTypeClass)); 218 W.printEnum("StorageMappingClass", 219 static_cast<uint8_t>(AuxEntPtr->StorageMappingClass), 220 makeArrayRef(CsectStorageMappingClass)); 221 W.printHex("StabInfoIndex", AuxEntPtr->StabInfoIndex); 222 W.printHex("StabSectNum", AuxEntPtr->StabSectNum); 223 } 224 225 void XCOFFDumper::printSectAuxEntForStat( 226 const XCOFFSectAuxEntForStat *AuxEntPtr) { 227 assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file."); 228 229 DictScope SymDs(W, "Sect Auxiliary Entry For Stat"); 230 W.printNumber("Index", 231 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr))); 232 W.printNumber("SectionLength", AuxEntPtr->SectionLength); 233 234 // Unlike the corresponding fields in the section header, NumberOfRelocEnt 235 // and NumberOfLineNum do not handle values greater than 65535. 236 W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt); 237 W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum); 238 } 239 240 static const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = { 241 #define ECase(X) \ 242 { #X, XCOFF::X } 243 ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT), 244 ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL), 245 ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU), 246 ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG), 247 ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK), 248 ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE), 249 ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL), 250 ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF), 251 ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM), 252 ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM), 253 ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY), 254 ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS), 255 ECase(C_STTLS), ECase(C_EFCN) 256 #undef ECase 257 }; 258 259 static StringRef GetSymbolValueName(XCOFF::StorageClass SC) { 260 switch (SC) { 261 case XCOFF::C_EXT: 262 case XCOFF::C_WEAKEXT: 263 case XCOFF::C_HIDEXT: 264 case XCOFF::C_STAT: 265 return "Value (RelocatableAddress)"; 266 case XCOFF::C_FILE: 267 return "Value (SymbolTableIndex)"; 268 case XCOFF::C_FCN: 269 case XCOFF::C_BLOCK: 270 case XCOFF::C_FUN: 271 case XCOFF::C_STSYM: 272 case XCOFF::C_BINCL: 273 case XCOFF::C_EINCL: 274 case XCOFF::C_INFO: 275 case XCOFF::C_BSTAT: 276 case XCOFF::C_LSYM: 277 case XCOFF::C_PSYM: 278 case XCOFF::C_RPSYM: 279 case XCOFF::C_RSYM: 280 case XCOFF::C_ECOML: 281 case XCOFF::C_DWARF: 282 assert(false && "This StorageClass for the symbol is not yet implemented."); 283 return ""; 284 default: 285 return "Value"; 286 } 287 } 288 289 static const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = { 290 #define ECase(X) \ 291 { #X, XCOFF::X } 292 ECase(TB_C), ECase(TB_CPLUSPLUS) 293 #undef ECase 294 }; 295 296 static const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = { 297 #define ECase(X) \ 298 { #X, XCOFF::X } 299 ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970) 300 #undef ECase 301 }; 302 303 void XCOFFDumper::printSymbol(const SymbolRef &S) { 304 if (Obj.is64Bit()) 305 report_fatal_error("64-bit support is unimplemented."); 306 307 DataRefImpl SymbolDRI = S.getRawDataRefImpl(); 308 const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI); 309 310 XCOFFSymbolRef XCOFFSymRef(SymbolDRI, &Obj); 311 uint8_t NumberOfAuxEntries = XCOFFSymRef.getNumberOfAuxEntries(); 312 313 DictScope SymDs(W, "Symbol"); 314 315 StringRef SymbolName = 316 unwrapOrError(Obj.getFileName(), Obj.getSymbolName(SymbolDRI)); 317 318 W.printNumber("Index", 319 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(SymbolEntPtr))); 320 W.printString("Name", SymbolName); 321 W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass), 322 SymbolEntPtr->Value); 323 324 StringRef SectionName = 325 unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntPtr)); 326 327 W.printString("Section", SectionName); 328 if (XCOFFSymRef.getStorageClass() == XCOFF::C_FILE) { 329 W.printEnum("Source Language ID", 330 SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId, 331 makeArrayRef(CFileLangIdClass)); 332 W.printEnum("CPU Version ID", 333 SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId, 334 makeArrayRef(CFileCpuIdClass)); 335 } else 336 W.printHex("Type", SymbolEntPtr->SymbolType); 337 338 W.printEnum("StorageClass", static_cast<uint8_t>(SymbolEntPtr->StorageClass), 339 makeArrayRef(SymStorageClass)); 340 W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries); 341 342 if (NumberOfAuxEntries == 0) 343 return; 344 345 switch (XCOFFSymRef.getStorageClass()) { 346 case XCOFF::C_FILE: 347 // If the symbol is C_FILE and has auxiliary entries... 348 for (int i = 1; i <= NumberOfAuxEntries; i++) { 349 const XCOFFFileAuxEnt *FileAuxEntPtr = 350 reinterpret_cast<const XCOFFFileAuxEnt *>(SymbolEntPtr + i); 351 #ifndef NDEBUG 352 Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(FileAuxEntPtr)); 353 #endif 354 printFileAuxEnt(FileAuxEntPtr); 355 } 356 break; 357 case XCOFF::C_EXT: 358 case XCOFF::C_WEAKEXT: 359 case XCOFF::C_HIDEXT: 360 // If the symbol is for a function, and it has more than 1 auxiliary entry, 361 // then one of them must be function auxiliary entry which we do not 362 // support yet. 363 if (XCOFFSymRef.isFunction() && NumberOfAuxEntries >= 2) 364 report_fatal_error("Function auxiliary entry printing is unimplemented."); 365 366 // If there is more than 1 auxiliary entry, instead of printing out 367 // error information, print out the raw Auxiliary entry from 1st till 368 // the last - 1. The last one must be a CSECT Auxiliary Entry. 369 for (int i = 1; i < NumberOfAuxEntries; i++) { 370 W.startLine() << "!Unexpected raw auxiliary entry data:\n"; 371 W.startLine() << format_bytes( 372 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i), 373 XCOFF::SymbolTableEntrySize)); 374 } 375 376 // The symbol's last auxiliary entry is a CSECT Auxiliary Entry. 377 printCsectAuxEnt32(XCOFFSymRef.getXCOFFCsectAuxEnt32()); 378 break; 379 case XCOFF::C_STAT: 380 if (NumberOfAuxEntries > 1) 381 report_fatal_error( 382 "C_STAT symbol should not have more than 1 auxiliary entry."); 383 384 const XCOFFSectAuxEntForStat *StatAuxEntPtr; 385 StatAuxEntPtr = 386 reinterpret_cast<const XCOFFSectAuxEntForStat *>(SymbolEntPtr + 1); 387 #ifndef NDEBUG 388 Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(StatAuxEntPtr)); 389 #endif 390 printSectAuxEntForStat(StatAuxEntPtr); 391 break; 392 case XCOFF::C_DWARF: 393 case XCOFF::C_BLOCK: 394 case XCOFF::C_FCN: 395 report_fatal_error("Symbol table entry printing for this storage class " 396 "type is unimplemented."); 397 break; 398 default: 399 for (int i = 1; i <= NumberOfAuxEntries; i++) { 400 W.startLine() << "!Unexpected raw auxiliary entry data:\n"; 401 W.startLine() << format_bytes( 402 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i), 403 XCOFF::SymbolTableEntrySize)); 404 } 405 break; 406 } 407 } 408 409 void XCOFFDumper::printSymbols() { 410 ListScope Group(W, "Symbols"); 411 for (const SymbolRef &S : Obj.symbols()) 412 printSymbol(S); 413 } 414 415 void XCOFFDumper::printDynamicSymbols() { 416 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 417 } 418 419 void XCOFFDumper::printUnwindInfo() { 420 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 421 } 422 423 void XCOFFDumper::printStackMap() const { 424 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 425 } 426 427 void XCOFFDumper::printNeededLibraries() { 428 llvm_unreachable("Unimplemented functionality for XCOFFDumper"); 429 } 430 431 static const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = { 432 #define ECase(X) \ 433 { #X, XCOFF::X } 434 ECase(STYP_PAD), ECase(STYP_DWARF), ECase(STYP_TEXT), 435 ECase(STYP_DATA), ECase(STYP_BSS), ECase(STYP_EXCEPT), 436 ECase(STYP_INFO), ECase(STYP_TDATA), ECase(STYP_TBSS), 437 ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK), 438 ECase(STYP_OVRFLO) 439 #undef ECase 440 }; 441 442 template <typename T> 443 void XCOFFDumper::printOverflowSectionHeader(T &Sec) const { 444 if (Obj.is64Bit()) { 445 reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not " 446 "contain an overflow section header.", 447 object_error::parse_failed), 448 Obj.getFileName()); 449 } 450 451 W.printString("Name", Sec.getName()); 452 W.printNumber("NumberOfRelocations", Sec.PhysicalAddress); 453 W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress); 454 W.printHex("Size", Sec.SectionSize); 455 W.printHex("RawDataOffset", Sec.FileOffsetToRawData); 456 W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo); 457 W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo); 458 W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations); 459 W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers); 460 } 461 462 template <typename T> 463 void XCOFFDumper::printGenericSectionHeader(T &Sec) const { 464 W.printString("Name", Sec.getName()); 465 W.printHex("PhysicalAddress", Sec.PhysicalAddress); 466 W.printHex("VirtualAddress", Sec.VirtualAddress); 467 W.printHex("Size", Sec.SectionSize); 468 W.printHex("RawDataOffset", Sec.FileOffsetToRawData); 469 W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo); 470 W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo); 471 W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations); 472 W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers); 473 } 474 475 template <typename T> 476 void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) { 477 ListScope Group(W, "Sections"); 478 479 uint16_t Index = 1; 480 for (const T &Sec : Sections) { 481 DictScope SecDS(W, "Section"); 482 483 W.printNumber("Index", Index++); 484 uint16_t SectionType = Sec.getSectionType(); 485 switch (SectionType) { 486 case XCOFF::STYP_OVRFLO: 487 printOverflowSectionHeader(Sec); 488 break; 489 case XCOFF::STYP_LOADER: 490 case XCOFF::STYP_EXCEPT: 491 case XCOFF::STYP_TYPCHK: 492 // TODO The interpretation of loader, exception and type check section 493 // headers are different from that of generic section headers. We will 494 // implement them later. We interpret them as generic section headers for 495 // now. 496 default: 497 printGenericSectionHeader(Sec); 498 break; 499 } 500 if (Sec.isReservedSectionType()) 501 W.printHex("Flags", "Reserved", SectionType); 502 else 503 W.printEnum("Type", SectionType, makeArrayRef(SectionTypeFlagsNames)); 504 } 505 506 if (opts::SectionRelocations) 507 report_fatal_error("Dumping section relocations is unimplemented"); 508 509 if (opts::SectionSymbols) 510 report_fatal_error("Dumping symbols is unimplemented"); 511 512 if (opts::SectionData) 513 report_fatal_error("Dumping section data is unimplemented"); 514 } 515 516 namespace llvm { 517 std::unique_ptr<ObjDumper> 518 createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) { 519 return std::make_unique<XCOFFDumper>(XObj, Writer); 520 } 521 } // namespace llvm 522