1 //===- XCOFFObjectFile.h - XCOFF object file implementation -----*- 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 declares the XCOFFObjectFile class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_OBJECT_XCOFFOBJECTFILE_H 14 #define LLVM_OBJECT_XCOFFOBJECTFILE_H 15 16 #include "llvm/ADT/SmallString.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/iterator_range.h" 19 #include "llvm/BinaryFormat/XCOFF.h" 20 #include "llvm/Object/ObjectFile.h" 21 #include "llvm/Support/Compiler.h" 22 #include "llvm/Support/Endian.h" 23 #include <limits> 24 25 namespace llvm { 26 namespace object { 27 28 class xcoff_symbol_iterator; 29 30 struct XCOFFFileHeader32 { 31 support::ubig16_t Magic; 32 support::ubig16_t NumberOfSections; 33 34 // Unix time value, value of 0 indicates no timestamp. 35 // Negative values are reserved. 36 support::big32_t TimeStamp; 37 38 support::ubig32_t SymbolTableOffset; // File offset to symbol table. 39 support::big32_t NumberOfSymTableEntries; 40 support::ubig16_t AuxHeaderSize; 41 support::ubig16_t Flags; 42 }; 43 44 struct XCOFFFileHeader64 { 45 support::ubig16_t Magic; 46 support::ubig16_t NumberOfSections; 47 48 // Unix time value, value of 0 indicates no timestamp. 49 // Negative values are reserved. 50 support::big32_t TimeStamp; 51 52 support::ubig64_t SymbolTableOffset; // File offset to symbol table. 53 support::ubig16_t AuxHeaderSize; 54 support::ubig16_t Flags; 55 support::ubig32_t NumberOfSymTableEntries; 56 }; 57 58 template <typename T> struct XCOFFAuxiliaryHeader { 59 static constexpr uint8_t AuxiHeaderFlagMask = 0xF0; 60 static constexpr uint8_t AuxiHeaderTDataAlignmentMask = 0x0F; 61 62 public: getFlagXCOFFAuxiliaryHeader63 uint8_t getFlag() const { 64 return static_cast<const T *>(this)->FlagAndTDataAlignment & 65 AuxiHeaderFlagMask; 66 } 67 getTDataAlignmentXCOFFAuxiliaryHeader68 uint8_t getTDataAlignment() const { 69 return static_cast<const T *>(this)->FlagAndTDataAlignment & 70 AuxiHeaderTDataAlignmentMask; 71 } 72 getVersionXCOFFAuxiliaryHeader73 uint16_t getVersion() const { return static_cast<const T *>(this)->Version; } getEntryPointAddrXCOFFAuxiliaryHeader74 uint64_t getEntryPointAddr() const { 75 return static_cast<const T *>(this)->EntryPointAddr; 76 } 77 }; 78 79 struct XCOFFAuxiliaryHeader32 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader32> { 80 support::ubig16_t 81 AuxMagic; ///< If the value of the o_vstamp field is greater than 1, the 82 ///< o_mflags field is reserved for future use and it should 83 ///< contain 0. Otherwise, this field is not used. 84 support::ubig16_t 85 Version; ///< The valid values are 1 and 2. When the o_vstamp field is 2 86 ///< in an XCOFF32 file, the new interpretation of the n_type 87 ///< field in the symbol table entry is used. 88 support::ubig32_t TextSize; 89 support::ubig32_t InitDataSize; 90 support::ubig32_t BssDataSize; 91 support::ubig32_t EntryPointAddr; 92 support::ubig32_t TextStartAddr; 93 support::ubig32_t DataStartAddr; 94 support::ubig32_t TOCAnchorAddr; 95 support::ubig16_t SecNumOfEntryPoint; 96 support::ubig16_t SecNumOfText; 97 support::ubig16_t SecNumOfData; 98 support::ubig16_t SecNumOfTOC; 99 support::ubig16_t SecNumOfLoader; 100 support::ubig16_t SecNumOfBSS; 101 support::ubig16_t MaxAlignOfText; 102 support::ubig16_t MaxAlignOfData; 103 support::ubig16_t ModuleType; 104 uint8_t CpuFlag; 105 uint8_t CpuType; 106 support::ubig32_t MaxStackSize; ///< If the value is 0, the system default 107 ///< maximum stack size is used. 108 support::ubig32_t MaxDataSize; ///< If the value is 0, the system default 109 ///< maximum data size is used. 110 support::ubig32_t 111 ReservedForDebugger; ///< This field should contain 0. When a loaded 112 ///< program is being debugged, the memory image of 113 ///< this field may be modified by a debugger to 114 ///< insert a trap instruction. 115 uint8_t TextPageSize; ///< Specifies the size of pages for the exec text. The 116 ///< default value is 0 (system-selected page size). 117 uint8_t DataPageSize; ///< Specifies the size of pages for the exec data. The 118 ///< default value is 0 (system-selected page size). 119 uint8_t StackPageSize; ///< Specifies the size of pages for the stack. The 120 ///< default value is 0 (system-selected page size). 121 uint8_t FlagAndTDataAlignment; 122 support::ubig16_t SecNumOfTData; 123 support::ubig16_t SecNumOfTBSS; 124 }; 125 126 struct XCOFFAuxiliaryHeader64 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader64> { 127 support::ubig16_t AuxMagic; 128 support::ubig16_t Version; 129 support::ubig32_t ReservedForDebugger; 130 support::ubig64_t TextStartAddr; 131 support::ubig64_t DataStartAddr; 132 support::ubig64_t TOCAnchorAddr; 133 support::ubig16_t SecNumOfEntryPoint; 134 support::ubig16_t SecNumOfText; 135 support::ubig16_t SecNumOfData; 136 support::ubig16_t SecNumOfTOC; 137 support::ubig16_t SecNumOfLoader; 138 support::ubig16_t SecNumOfBSS; 139 support::ubig16_t MaxAlignOfText; 140 support::ubig16_t MaxAlignOfData; 141 support::ubig16_t ModuleType; 142 uint8_t CpuFlag; 143 uint8_t CpuType; 144 uint8_t TextPageSize; 145 uint8_t DataPageSize; 146 uint8_t StackPageSize; 147 uint8_t FlagAndTDataAlignment; 148 support::ubig64_t TextSize; 149 support::ubig64_t InitDataSize; 150 support::ubig64_t BssDataSize; 151 support::ubig64_t EntryPointAddr; 152 support::ubig64_t MaxStackSize; 153 support::ubig64_t MaxDataSize; 154 support::ubig16_t SecNumOfTData; 155 support::ubig16_t SecNumOfTBSS; 156 support::ubig16_t XCOFF64Flag; 157 }; 158 159 template <typename T> struct XCOFFSectionHeader { 160 // The section flags definitions are the same in both 32- and 64-bit objects. 161 // Least significant 3 bits are reserved. 162 static constexpr unsigned SectionFlagsReservedMask = 0x7; 163 164 // The low order 16 bits of section flags denotes the section type. 165 // The high order 16 bits of section flags denotes the section subtype. 166 // For now, this is only used for DWARF sections. 167 static constexpr unsigned SectionFlagsTypeMask = 0xffffu; 168 169 public: 170 StringRef getName() const; 171 uint16_t getSectionType() const; 172 uint32_t getSectionSubtype() const; 173 bool isReservedSectionType() const; 174 }; 175 176 // Explicit extern template declarations. 177 struct XCOFFSectionHeader32; 178 struct XCOFFSectionHeader64; 179 extern template struct LLVM_TEMPLATE_ABI 180 XCOFFSectionHeader<XCOFFSectionHeader32>; 181 extern template struct LLVM_TEMPLATE_ABI 182 XCOFFSectionHeader<XCOFFSectionHeader64>; 183 184 struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> { 185 char Name[XCOFF::NameSize]; 186 support::ubig32_t PhysicalAddress; 187 support::ubig32_t VirtualAddress; 188 support::ubig32_t SectionSize; 189 support::ubig32_t FileOffsetToRawData; 190 support::ubig32_t FileOffsetToRelocationInfo; 191 support::ubig32_t FileOffsetToLineNumberInfo; 192 support::ubig16_t NumberOfRelocations; 193 support::ubig16_t NumberOfLineNumbers; 194 support::big32_t Flags; 195 }; 196 197 struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> { 198 char Name[XCOFF::NameSize]; 199 support::ubig64_t PhysicalAddress; 200 support::ubig64_t VirtualAddress; 201 support::ubig64_t SectionSize; 202 support::big64_t FileOffsetToRawData; 203 support::big64_t FileOffsetToRelocationInfo; 204 support::big64_t FileOffsetToLineNumberInfo; 205 support::ubig32_t NumberOfRelocations; 206 support::ubig32_t NumberOfLineNumbers; 207 support::big32_t Flags; 208 char Padding[4]; 209 }; 210 211 struct LoaderSectionHeader32; 212 struct LoaderSectionHeader64; 213 struct LoaderSectionSymbolEntry32 { 214 struct NameOffsetInStrTbl { 215 support::big32_t IsNameInStrTbl; // Zero indicates name in string table. 216 support::ubig32_t Offset; 217 }; 218 219 char SymbolName[XCOFF::NameSize]; 220 support::ubig32_t Value; // The virtual address of the symbol. 221 support::big16_t SectionNumber; 222 uint8_t SymbolType; 223 XCOFF::StorageClass StorageClass; 224 support::ubig32_t ImportFileID; 225 support::ubig32_t ParameterTypeCheck; 226 227 LLVM_ABI Expected<StringRef> 228 getSymbolName(const LoaderSectionHeader32 *LoaderSecHeader) const; 229 }; 230 231 struct LoaderSectionSymbolEntry64 { 232 support::ubig64_t Value; // The virtual address of the symbol. 233 support::ubig32_t Offset; 234 support::big16_t SectionNumber; 235 uint8_t SymbolType; 236 XCOFF::StorageClass StorageClass; 237 support::ubig32_t ImportFileID; 238 support::ubig32_t ParameterTypeCheck; 239 240 LLVM_ABI Expected<StringRef> 241 getSymbolName(const LoaderSectionHeader64 *LoaderSecHeader) const; 242 }; 243 244 struct LoaderSectionRelocationEntry32 { 245 support::ubig32_t VirtualAddr; 246 support::big32_t SymbolIndex; 247 support::ubig16_t Type; 248 support::big16_t SectionNum; 249 }; 250 251 struct LoaderSectionRelocationEntry64 { 252 support::ubig64_t VirtualAddr; 253 support::ubig16_t Type; 254 support::big16_t SectionNum; 255 support::big32_t SymbolIndex; 256 }; 257 258 struct LoaderSectionHeader32 { 259 support::ubig32_t Version; 260 support::ubig32_t NumberOfSymTabEnt; 261 support::ubig32_t NumberOfRelTabEnt; 262 support::ubig32_t LengthOfImpidStrTbl; 263 support::ubig32_t NumberOfImpid; 264 support::big32_t OffsetToImpid; 265 support::ubig32_t LengthOfStrTbl; 266 support::big32_t OffsetToStrTbl; 267 268 uint64_t getOffsetToSymTbl() const { 269 return NumberOfSymTabEnt == 0 ? 0 : sizeof(LoaderSectionHeader32); 270 } 271 272 uint64_t getOffsetToRelEnt() const { 273 // Relocation table is after Symbol table. 274 return NumberOfRelTabEnt == 0 275 ? 0 276 : sizeof(LoaderSectionHeader32) + 277 sizeof(LoaderSectionSymbolEntry32) * NumberOfSymTabEnt; 278 } 279 }; 280 281 struct LoaderSectionHeader64 { 282 support::ubig32_t Version; 283 support::ubig32_t NumberOfSymTabEnt; 284 support::ubig32_t NumberOfRelTabEnt; 285 support::ubig32_t LengthOfImpidStrTbl; 286 support::ubig32_t NumberOfImpid; 287 support::ubig32_t LengthOfStrTbl; 288 support::big64_t OffsetToImpid; 289 support::big64_t OffsetToStrTbl; 290 support::big64_t OffsetToSymTbl; 291 support::big64_t OffsetToRelEnt; 292 293 uint64_t getOffsetToSymTbl() const { return OffsetToSymTbl; } 294 uint64_t getOffsetToRelEnt() const { return OffsetToRelEnt; } 295 }; 296 297 template <typename AddressType> struct ExceptionSectionEntry { 298 union { 299 support::ubig32_t SymbolIdx; 300 AddressType TrapInstAddr; 301 }; 302 uint8_t LangId; 303 uint8_t Reason; 304 305 uint32_t getSymbolIndex() const { 306 assert(Reason == 0 && "Get symbol table index of the function only when " 307 "the e_reason field is 0."); 308 return SymbolIdx; 309 } 310 311 uint64_t getTrapInstAddr() const { 312 assert(Reason != 0 && "Zero is not a valid trap exception reason code."); 313 return TrapInstAddr; 314 } 315 uint8_t getLangID() const { return LangId; } 316 uint8_t getReason() const { return Reason; } 317 }; 318 319 typedef ExceptionSectionEntry<support::ubig32_t> ExceptionSectionEntry32; 320 typedef ExceptionSectionEntry<support::ubig64_t> ExceptionSectionEntry64; 321 322 // Explicit extern template declarations. 323 extern template struct LLVM_TEMPLATE_ABI 324 ExceptionSectionEntry<support::ubig32_t>; 325 extern template struct LLVM_TEMPLATE_ABI 326 ExceptionSectionEntry<support::ubig64_t>; 327 328 struct XCOFFStringTable { 329 uint32_t Size; 330 const char *Data; 331 }; 332 333 struct XCOFFCsectAuxEnt32 { 334 support::ubig32_t SectionOrLength; 335 support::ubig32_t ParameterHashIndex; 336 support::ubig16_t TypeChkSectNum; 337 uint8_t SymbolAlignmentAndType; 338 XCOFF::StorageMappingClass StorageMappingClass; 339 support::ubig32_t StabInfoIndex; 340 support::ubig16_t StabSectNum; 341 }; 342 343 struct XCOFFCsectAuxEnt64 { 344 support::ubig32_t SectionOrLengthLowByte; 345 support::ubig32_t ParameterHashIndex; 346 support::ubig16_t TypeChkSectNum; 347 uint8_t SymbolAlignmentAndType; 348 XCOFF::StorageMappingClass StorageMappingClass; 349 support::ubig32_t SectionOrLengthHighByte; 350 uint8_t Pad; 351 XCOFF::SymbolAuxType AuxType; 352 }; 353 354 class XCOFFCsectAuxRef { 355 public: 356 static constexpr uint8_t SymbolTypeMask = 0x07; 357 static constexpr uint8_t SymbolAlignmentMask = 0xF8; 358 static constexpr size_t SymbolAlignmentBitOffset = 3; 359 360 XCOFFCsectAuxRef(const XCOFFCsectAuxEnt32 *Entry32) : Entry32(Entry32) {} 361 XCOFFCsectAuxRef(const XCOFFCsectAuxEnt64 *Entry64) : Entry64(Entry64) {} 362 363 // For getSectionOrLength(), 364 // If the symbol type is XTY_SD or XTY_CM, the csect length. 365 // If the symbol type is XTY_LD, the symbol table 366 // index of the containing csect. 367 // If the symbol type is XTY_ER, 0. 368 uint64_t getSectionOrLength() const { 369 return Entry32 ? getSectionOrLength32() : getSectionOrLength64(); 370 } 371 372 uint32_t getSectionOrLength32() const { 373 assert(Entry32 && "32-bit interface called on 64-bit object file."); 374 return Entry32->SectionOrLength; 375 } 376 377 uint64_t getSectionOrLength64() const { 378 assert(Entry64 && "64-bit interface called on 32-bit object file."); 379 return (static_cast<uint64_t>(Entry64->SectionOrLengthHighByte) << 32) | 380 Entry64->SectionOrLengthLowByte; 381 } 382 383 #define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X 384 385 uint32_t getParameterHashIndex() const { 386 return GETVALUE(ParameterHashIndex); 387 } 388 389 uint16_t getTypeChkSectNum() const { return GETVALUE(TypeChkSectNum); } 390 391 XCOFF::StorageMappingClass getStorageMappingClass() const { 392 return GETVALUE(StorageMappingClass); 393 } 394 395 uintptr_t getEntryAddress() const { 396 return Entry32 ? reinterpret_cast<uintptr_t>(Entry32) 397 : reinterpret_cast<uintptr_t>(Entry64); 398 } 399 400 uint16_t getAlignmentLog2() const { 401 return (getSymbolAlignmentAndType() & SymbolAlignmentMask) >> 402 SymbolAlignmentBitOffset; 403 } 404 405 uint8_t getSymbolType() const { 406 return getSymbolAlignmentAndType() & SymbolTypeMask; 407 } 408 409 bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; } 410 411 uint32_t getStabInfoIndex32() const { 412 assert(Entry32 && "32-bit interface called on 64-bit object file."); 413 return Entry32->StabInfoIndex; 414 } 415 416 uint16_t getStabSectNum32() const { 417 assert(Entry32 && "32-bit interface called on 64-bit object file."); 418 return Entry32->StabSectNum; 419 } 420 421 XCOFF::SymbolAuxType getAuxType64() const { 422 assert(Entry64 && "64-bit interface called on 32-bit object file."); 423 return Entry64->AuxType; 424 } 425 426 uint8_t getSymbolAlignmentAndType() const { 427 return GETVALUE(SymbolAlignmentAndType); 428 } 429 430 #undef GETVALUE 431 432 private: 433 const XCOFFCsectAuxEnt32 *Entry32 = nullptr; 434 const XCOFFCsectAuxEnt64 *Entry64 = nullptr; 435 }; 436 437 struct XCOFFFileAuxEnt { 438 typedef struct { 439 support::big32_t Magic; // Zero indicates name in string table. 440 support::ubig32_t Offset; 441 char NamePad[XCOFF::FileNamePadSize]; 442 } NameInStrTblType; 443 union { 444 char Name[XCOFF::NameSize + XCOFF::FileNamePadSize]; 445 NameInStrTblType NameInStrTbl; 446 }; 447 XCOFF::CFileStringType Type; 448 uint8_t ReservedZeros[2]; 449 XCOFF::SymbolAuxType AuxType; // 64-bit XCOFF file only. 450 }; 451 452 struct XCOFFSectAuxEntForStat { 453 support::ubig32_t SectionLength; 454 support::ubig16_t NumberOfRelocEnt; 455 support::ubig16_t NumberOfLineNum; 456 uint8_t Pad[10]; 457 }; // 32-bit XCOFF file only. 458 459 struct XCOFFFunctionAuxEnt32 { 460 support::ubig32_t OffsetToExceptionTbl; 461 support::ubig32_t SizeOfFunction; 462 support::ubig32_t PtrToLineNum; 463 support::big32_t SymIdxOfNextBeyond; 464 uint8_t Pad[2]; 465 }; 466 467 struct XCOFFFunctionAuxEnt64 { 468 support::ubig64_t PtrToLineNum; 469 support::ubig32_t SizeOfFunction; 470 support::big32_t SymIdxOfNextBeyond; 471 uint8_t Pad; 472 XCOFF::SymbolAuxType AuxType; // Contains _AUX_FCN; Type of auxiliary entry 473 }; 474 475 struct XCOFFExceptionAuxEnt { 476 support::ubig64_t OffsetToExceptionTbl; 477 support::ubig32_t SizeOfFunction; 478 support::big32_t SymIdxOfNextBeyond; 479 uint8_t Pad; 480 XCOFF::SymbolAuxType AuxType; // Contains _AUX_EXCEPT; Type of auxiliary entry 481 }; 482 483 struct XCOFFBlockAuxEnt32 { 484 uint8_t ReservedZeros1[2]; 485 support::ubig16_t LineNumHi; 486 support::ubig16_t LineNumLo; 487 uint8_t ReservedZeros2[12]; 488 }; 489 490 struct XCOFFBlockAuxEnt64 { 491 support::ubig32_t LineNum; 492 uint8_t Pad[13]; 493 XCOFF::SymbolAuxType AuxType; // Contains _AUX_SYM; Type of auxiliary entry 494 }; 495 496 struct XCOFFSectAuxEntForDWARF32 { 497 support::ubig32_t LengthOfSectionPortion; 498 uint8_t Pad1[4]; 499 support::ubig32_t NumberOfRelocEnt; 500 uint8_t Pad2[6]; 501 }; 502 503 struct XCOFFSectAuxEntForDWARF64 { 504 support::ubig64_t LengthOfSectionPortion; 505 support::ubig64_t NumberOfRelocEnt; 506 uint8_t Pad; 507 XCOFF::SymbolAuxType AuxType; // Contains _AUX_SECT; Type of Auxillary entry 508 }; 509 510 template <typename AddressType> struct XCOFFRelocation { 511 public: 512 AddressType VirtualAddress; 513 support::ubig32_t SymbolIndex; 514 515 // Packed field, see XR_* masks for details of packing. 516 uint8_t Info; 517 518 XCOFF::RelocationType Type; 519 520 public: 521 bool isRelocationSigned() const; 522 bool isFixupIndicated() const; 523 524 // Returns the number of bits being relocated. 525 uint8_t getRelocatedLength() const; 526 }; 527 528 extern template struct LLVM_TEMPLATE_ABI 529 XCOFFRelocation<llvm::support::ubig32_t>; 530 extern template struct LLVM_TEMPLATE_ABI 531 XCOFFRelocation<llvm::support::ubig64_t>; 532 533 struct XCOFFRelocation32 : XCOFFRelocation<llvm::support::ubig32_t> {}; 534 struct XCOFFRelocation64 : XCOFFRelocation<llvm::support::ubig64_t> {}; 535 536 class XCOFFSymbolRef; 537 538 class LLVM_ABI XCOFFObjectFile : public ObjectFile { 539 private: 540 const void *FileHeader = nullptr; 541 const void *AuxiliaryHeader = nullptr; 542 const void *SectionHeaderTable = nullptr; 543 544 const void *SymbolTblPtr = nullptr; 545 XCOFFStringTable StringTable = {0, nullptr}; 546 547 const XCOFFSectionHeader32 *sectionHeaderTable32() const; 548 const XCOFFSectionHeader64 *sectionHeaderTable64() const; 549 template <typename T> const T *sectionHeaderTable() const; 550 551 size_t getFileHeaderSize() const; 552 size_t getSectionHeaderSize() const; 553 554 const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const; 555 const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const; 556 uintptr_t getSectionHeaderTableAddress() const; 557 uintptr_t getEndOfSymbolTableAddress() const; 558 559 DataRefImpl getSectionByType(XCOFF::SectionTypeFlags SectType) const; 560 uint64_t getSectionFileOffsetToRawData(DataRefImpl Sec) const; 561 562 // This returns a pointer to the start of the storage for the name field of 563 // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily 564 // null-terminated. 565 const char *getSectionNameInternal(DataRefImpl Sec) const; 566 567 static bool isReservedSectionNumber(int16_t SectionNumber); 568 569 // Constructor and "create" factory function. The constructor is only a thin 570 // wrapper around the base constructor. The "create" function fills out the 571 // XCOFF-specific information and performs the error checking along the way. 572 XCOFFObjectFile(unsigned Type, MemoryBufferRef Object); 573 static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type, 574 MemoryBufferRef MBR); 575 576 // Helper for parsing the StringTable. Returns an 'Error' if parsing failed 577 // and an XCOFFStringTable if parsing succeeded. 578 static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj, 579 uint64_t Offset); 580 581 // Make a friend so it can call the private 'create' function. 582 friend Expected<std::unique_ptr<ObjectFile>> 583 ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); 584 585 void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const; 586 587 public: 588 static constexpr uint64_t InvalidRelocOffset = 589 std::numeric_limits<uint64_t>::max(); 590 591 // Interface inherited from base classes. 592 void moveSymbolNext(DataRefImpl &Symb) const override; 593 Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; 594 basic_symbol_iterator symbol_begin() const override; 595 basic_symbol_iterator symbol_end() const override; 596 597 using xcoff_symbol_iterator_range = iterator_range<xcoff_symbol_iterator>; 598 xcoff_symbol_iterator_range symbols() const; 599 600 bool is64Bit() const override; 601 Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; 602 Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; 603 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; 604 uint32_t getSymbolAlignment(DataRefImpl Symb) const override; 605 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; 606 Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; 607 Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; 608 609 void moveSectionNext(DataRefImpl &Sec) const override; 610 Expected<StringRef> getSectionName(DataRefImpl Sec) const override; 611 uint64_t getSectionAddress(DataRefImpl Sec) const override; 612 uint64_t getSectionIndex(DataRefImpl Sec) const override; 613 uint64_t getSectionSize(DataRefImpl Sec) const override; 614 Expected<ArrayRef<uint8_t>> 615 getSectionContents(DataRefImpl Sec) const override; 616 uint64_t getSectionAlignment(DataRefImpl Sec) const override; 617 bool isSectionCompressed(DataRefImpl Sec) const override; 618 bool isSectionText(DataRefImpl Sec) const override; 619 bool isSectionData(DataRefImpl Sec) const override; 620 bool isSectionBSS(DataRefImpl Sec) const override; 621 bool isDebugSection(DataRefImpl Sec) const override; 622 623 bool isSectionVirtual(DataRefImpl Sec) const override; 624 relocation_iterator section_rel_begin(DataRefImpl Sec) const override; 625 relocation_iterator section_rel_end(DataRefImpl Sec) const override; 626 627 void moveRelocationNext(DataRefImpl &Rel) const override; 628 629 /// \returns the relocation offset with the base address of the containing 630 /// section as zero, or InvalidRelocOffset on errors (such as a relocation 631 /// that does not refer to an address in any section). 632 uint64_t getRelocationOffset(DataRefImpl Rel) const override; 633 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; 634 uint64_t getRelocationType(DataRefImpl Rel) const override; 635 void getRelocationTypeName(DataRefImpl Rel, 636 SmallVectorImpl<char> &Result) const override; 637 638 section_iterator section_begin() const override; 639 section_iterator section_end() const override; 640 uint8_t getBytesInAddress() const override; 641 StringRef getFileFormatName() const override; 642 Triple::ArchType getArch() const override; 643 Expected<SubtargetFeatures> getFeatures() const override; 644 Expected<uint64_t> getStartAddress() const override; 645 StringRef mapDebugSectionName(StringRef Name) const override; 646 bool isRelocatableObject() const override; 647 648 // Below here is the non-inherited interface. 649 650 Expected<StringRef> getRawData(const char *Start, uint64_t Size, 651 StringRef Name) const; 652 653 const XCOFFAuxiliaryHeader32 *auxiliaryHeader32() const; 654 const XCOFFAuxiliaryHeader64 *auxiliaryHeader64() const; 655 656 const void *getPointerToSymbolTable() const { return SymbolTblPtr; } 657 658 Expected<StringRef> getSymbolSectionName(XCOFFSymbolRef Ref) const; 659 unsigned getSymbolSectionID(SymbolRef Sym) const; 660 XCOFFSymbolRef toSymbolRef(DataRefImpl Ref) const; 661 662 // File header related interfaces. 663 const XCOFFFileHeader32 *fileHeader32() const; 664 const XCOFFFileHeader64 *fileHeader64() const; 665 uint16_t getMagic() const; 666 uint16_t getNumberOfSections() const; 667 int32_t getTimeStamp() const; 668 669 // Symbol table offset and entry count are handled differently between 670 // XCOFF32 and XCOFF64. 671 uint32_t getSymbolTableOffset32() const; 672 uint64_t getSymbolTableOffset64() const; 673 674 // Note that this value is signed and might return a negative value. Negative 675 // values are reserved for future use. 676 int32_t getRawNumberOfSymbolTableEntries32() const; 677 678 // The sanitized value appropriate to use as an index into the symbol table. 679 uint32_t getLogicalNumberOfSymbolTableEntries32() const; 680 681 uint32_t getNumberOfSymbolTableEntries64() const; 682 683 // Return getLogicalNumberOfSymbolTableEntries32 or 684 // getNumberOfSymbolTableEntries64 depending on the object mode. 685 uint32_t getNumberOfSymbolTableEntries() const; 686 687 uint32_t getSymbolIndex(uintptr_t SymEntPtr) const; 688 uint64_t getSymbolSize(DataRefImpl Symb) const; 689 uintptr_t getSymbolByIndex(uint32_t Idx) const { 690 return reinterpret_cast<uintptr_t>(SymbolTblPtr) + 691 XCOFF::SymbolTableEntrySize * Idx; 692 } 693 uintptr_t getSymbolEntryAddressByIndex(uint32_t SymbolTableIndex) const; 694 Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const; 695 696 Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const; 697 uint16_t getOptionalHeaderSize() const; 698 uint16_t getFlags() const; 699 700 // Section header table related interfaces. 701 ArrayRef<XCOFFSectionHeader32> sections32() const; 702 ArrayRef<XCOFFSectionHeader64> sections64() const; 703 704 int32_t getSectionFlags(DataRefImpl Sec) const; 705 Expected<DataRefImpl> getSectionByNum(int16_t Num) const; 706 707 Expected<uintptr_t> 708 getSectionFileOffsetToRawData(XCOFF::SectionTypeFlags SectType) const; 709 710 void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const; 711 712 // Relocation-related interfaces. 713 template <typename T> 714 Expected<uint32_t> 715 getNumberOfRelocationEntries(const XCOFFSectionHeader<T> &Sec) const; 716 717 template <typename Shdr, typename Reloc> 718 Expected<ArrayRef<Reloc>> relocations(const Shdr &Sec) const; 719 720 // Loader section related interfaces. 721 Expected<StringRef> getImportFileTable() const; 722 723 // Exception-related interface. 724 template <typename ExceptEnt> 725 Expected<ArrayRef<ExceptEnt>> getExceptionEntries() const; 726 727 // This function returns string table entry. 728 Expected<StringRef> getStringTableEntry(uint32_t Offset) const; 729 730 // This function returns the string table. 731 StringRef getStringTable() const; 732 733 const XCOFF::SymbolAuxType *getSymbolAuxType(uintptr_t AuxEntryAddress) const; 734 735 static uintptr_t getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, 736 uint32_t Distance); 737 738 static bool classof(const Binary *B) { return B->isXCOFF(); } 739 740 std::optional<StringRef> tryGetCPUName() const override; 741 }; // XCOFFObjectFile 742 743 typedef struct { 744 uint8_t LanguageId; 745 uint8_t CpuTypeId; 746 } CFileLanguageIdAndTypeIdType; 747 748 struct XCOFFSymbolEntry32 { 749 typedef struct { 750 support::big32_t Magic; // Zero indicates name in string table. 751 support::ubig32_t Offset; 752 } NameInStrTblType; 753 754 union { 755 char SymbolName[XCOFF::NameSize]; 756 NameInStrTblType NameInStrTbl; 757 }; 758 759 support::ubig32_t Value; // Symbol value; storage class-dependent. 760 support::big16_t SectionNumber; 761 762 union { 763 support::ubig16_t SymbolType; 764 CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; 765 }; 766 767 XCOFF::StorageClass StorageClass; 768 uint8_t NumberOfAuxEntries; 769 }; 770 771 struct XCOFFSymbolEntry64 { 772 support::ubig64_t Value; // Symbol value; storage class-dependent. 773 support::ubig32_t Offset; 774 support::big16_t SectionNumber; 775 776 union { 777 support::ubig16_t SymbolType; 778 CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; 779 }; 780 781 XCOFF::StorageClass StorageClass; 782 uint8_t NumberOfAuxEntries; 783 }; 784 785 extern template LLVM_TEMPLATE_ABI Expected<ArrayRef<XCOFFRelocation32>> 786 XCOFFObjectFile::relocations<XCOFFSectionHeader32, XCOFFRelocation32>( 787 const XCOFFSectionHeader32 &Sec) const; 788 extern template LLVM_TEMPLATE_ABI Expected<ArrayRef<XCOFFRelocation64>> 789 XCOFFObjectFile::relocations<XCOFFSectionHeader64, XCOFFRelocation64>( 790 const XCOFFSectionHeader64 &Sec) const; 791 792 class XCOFFSymbolRef : public SymbolRef { 793 public: 794 enum { NAME_IN_STR_TBL_MAGIC = 0x0 }; 795 796 XCOFFSymbolRef(DataRefImpl SymEntDataRef, 797 const XCOFFObjectFile *OwningObjectPtr) 798 : SymbolRef(SymEntDataRef, OwningObjectPtr) { 799 assert(OwningObjectPtr && "OwningObjectPtr cannot be nullptr!"); 800 assert(SymEntDataRef.p != 0 && 801 "Symbol table entry pointer cannot be nullptr!"); 802 } 803 804 const XCOFFSymbolEntry32 *getSymbol32() const { 805 return reinterpret_cast<const XCOFFSymbolEntry32 *>(getRawDataRefImpl().p); 806 } 807 808 const XCOFFSymbolEntry64 *getSymbol64() const { 809 return reinterpret_cast<const XCOFFSymbolEntry64 *>(getRawDataRefImpl().p); 810 } 811 812 uint64_t getValue() const { 813 return getObject()->is64Bit() ? getValue64() : getValue32(); 814 } 815 816 uint32_t getValue32() const { 817 return reinterpret_cast<const XCOFFSymbolEntry32 *>(getRawDataRefImpl().p) 818 ->Value; 819 } 820 821 uint64_t getValue64() const { 822 return reinterpret_cast<const XCOFFSymbolEntry64 *>(getRawDataRefImpl().p) 823 ->Value; 824 } 825 826 uint64_t getSize() const { 827 return getObject()->getSymbolSize(getRawDataRefImpl()); 828 } 829 830 #define GETVALUE(X) \ 831 getObject()->is64Bit() \ 832 ? reinterpret_cast<const XCOFFSymbolEntry64 *>(getRawDataRefImpl().p)->X \ 833 : reinterpret_cast<const XCOFFSymbolEntry32 *>(getRawDataRefImpl().p)->X 834 835 int16_t getSectionNumber() const { return GETVALUE(SectionNumber); } 836 837 uint16_t getSymbolType() const { return GETVALUE(SymbolType); } 838 839 uint8_t getLanguageIdForCFile() const { 840 assert(getStorageClass() == XCOFF::C_FILE && 841 "This interface is for C_FILE only."); 842 return GETVALUE(CFileLanguageIdAndTypeId.LanguageId); 843 } 844 845 uint8_t getCPUTypeIddForCFile() const { 846 assert(getStorageClass() == XCOFF::C_FILE && 847 "This interface is for C_FILE only."); 848 return GETVALUE(CFileLanguageIdAndTypeId.CpuTypeId); 849 } 850 851 XCOFF::StorageClass getStorageClass() const { return GETVALUE(StorageClass); } 852 853 uint8_t getNumberOfAuxEntries() const { return GETVALUE(NumberOfAuxEntries); } 854 855 #undef GETVALUE 856 857 uintptr_t getEntryAddress() const { 858 return getRawDataRefImpl().p; 859 } 860 861 LLVM_ABI Expected<StringRef> getName() const; 862 LLVM_ABI Expected<bool> isFunction() const; 863 LLVM_ABI bool isCsectSymbol() const; 864 LLVM_ABI Expected<XCOFFCsectAuxRef> getXCOFFCsectAuxRef() const; 865 866 private: 867 const XCOFFObjectFile *getObject() const { 868 return cast<XCOFFObjectFile>(BasicSymbolRef::getObject()); 869 } 870 }; 871 872 class xcoff_symbol_iterator : public symbol_iterator { 873 public: 874 xcoff_symbol_iterator(const basic_symbol_iterator &B) 875 : symbol_iterator(B) {} 876 877 xcoff_symbol_iterator(const XCOFFSymbolRef *Symbol) 878 : symbol_iterator(*Symbol) {} 879 880 const XCOFFSymbolRef *operator->() const { 881 return static_cast<const XCOFFSymbolRef *>(symbol_iterator::operator->()); 882 } 883 884 const XCOFFSymbolRef &operator*() const { 885 return static_cast<const XCOFFSymbolRef &>(symbol_iterator::operator*()); 886 } 887 }; 888 889 class TBVectorExt { 890 uint16_t Data; 891 SmallString<32> VecParmsInfo; 892 893 TBVectorExt(StringRef TBvectorStrRef, Error &Err); 894 895 public: 896 LLVM_ABI static Expected<TBVectorExt> create(StringRef TBvectorStrRef); 897 LLVM_ABI uint8_t getNumberOfVRSaved() const; 898 LLVM_ABI bool isVRSavedOnStack() const; 899 LLVM_ABI bool hasVarArgs() const; 900 LLVM_ABI uint8_t getNumberOfVectorParms() const; 901 LLVM_ABI bool hasVMXInstruction() const; 902 SmallString<32> getVectorParmsInfo() const { return VecParmsInfo; }; 903 }; 904 905 /// This class provides methods to extract traceback table data from a buffer. 906 /// The various accessors may reference the buffer provided via the constructor. 907 908 class XCOFFTracebackTable { 909 const uint8_t *const TBPtr; 910 bool Is64BitObj; 911 std::optional<SmallString<32>> ParmsType; 912 std::optional<uint32_t> TraceBackTableOffset; 913 std::optional<uint32_t> HandlerMask; 914 std::optional<uint32_t> NumOfCtlAnchors; 915 std::optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp; 916 std::optional<StringRef> FunctionName; 917 std::optional<uint8_t> AllocaRegister; 918 std::optional<TBVectorExt> VecExt; 919 std::optional<uint8_t> ExtensionTable; 920 std::optional<uint64_t> EhInfoDisp; 921 922 XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err, 923 bool Is64Bit = false); 924 925 public: 926 /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes. 927 /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an 928 /// Error is returned. 929 /// 930 /// \param[in] Ptr 931 /// A pointer that points just past the initial 4 bytes of zeros at the 932 /// beginning of an XCOFF Traceback Table. 933 /// 934 /// \param[in, out] Size 935 /// A pointer that points to the length of the XCOFF Traceback Table. 936 /// If the XCOFF Traceback Table is not parsed successfully or there are 937 /// extra bytes that are not recognized, \a Size will be updated to be the 938 /// size up to the end of the last successfully parsed field of the table. 939 LLVM_ABI static Expected<XCOFFTracebackTable> 940 create(const uint8_t *Ptr, uint64_t &Size, bool Is64Bits = false); 941 LLVM_ABI uint8_t getVersion() const; 942 LLVM_ABI uint8_t getLanguageID() const; 943 944 LLVM_ABI bool isGlobalLinkage() const; 945 LLVM_ABI bool isOutOfLineEpilogOrPrologue() const; 946 LLVM_ABI bool hasTraceBackTableOffset() const; 947 LLVM_ABI bool isInternalProcedure() const; 948 LLVM_ABI bool hasControlledStorage() const; 949 LLVM_ABI bool isTOCless() const; 950 LLVM_ABI bool isFloatingPointPresent() const; 951 LLVM_ABI bool isFloatingPointOperationLogOrAbortEnabled() const; 952 953 LLVM_ABI bool isInterruptHandler() const; 954 LLVM_ABI bool isFuncNamePresent() const; 955 LLVM_ABI bool isAllocaUsed() const; 956 LLVM_ABI uint8_t getOnConditionDirective() const; 957 LLVM_ABI bool isCRSaved() const; 958 LLVM_ABI bool isLRSaved() const; 959 960 LLVM_ABI bool isBackChainStored() const; 961 LLVM_ABI bool isFixup() const; 962 LLVM_ABI uint8_t getNumOfFPRsSaved() const; 963 964 LLVM_ABI bool hasVectorInfo() const; 965 LLVM_ABI bool hasExtensionTable() const; 966 LLVM_ABI uint8_t getNumOfGPRsSaved() const; 967 968 LLVM_ABI uint8_t getNumberOfFixedParms() const; 969 970 LLVM_ABI uint8_t getNumberOfFPParms() const; 971 LLVM_ABI bool hasParmsOnStack() const; 972 973 const std::optional<SmallString<32>> &getParmsType() const { 974 return ParmsType; 975 } 976 const std::optional<uint32_t> &getTraceBackTableOffset() const { 977 return TraceBackTableOffset; 978 } 979 const std::optional<uint32_t> &getHandlerMask() const { return HandlerMask; } 980 const std::optional<uint32_t> &getNumOfCtlAnchors() { 981 return NumOfCtlAnchors; 982 } 983 const std::optional<SmallVector<uint32_t, 8>> & 984 getControlledStorageInfoDisp() { 985 return ControlledStorageInfoDisp; 986 } 987 const std::optional<StringRef> &getFunctionName() const { 988 return FunctionName; 989 } 990 const std::optional<uint8_t> &getAllocaRegister() const { 991 return AllocaRegister; 992 } 993 const std::optional<TBVectorExt> &getVectorExt() const { return VecExt; } 994 const std::optional<uint8_t> &getExtensionTable() const { 995 return ExtensionTable; 996 } 997 const std::optional<uint64_t> &getEhInfoDisp() const { return EhInfoDisp; } 998 }; 999 1000 LLVM_ABI bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes); 1001 } // namespace object 1002 } // namespace llvm 1003 1004 #endif // LLVM_OBJECT_XCOFFOBJECTFILE_H 1005