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