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