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