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