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