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