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