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