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