10b57cec5SDimitry Andric //===- XCOFFObjectFile.h - XCOFF object file implementation -----*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file declares the XCOFFObjectFile class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_OBJECT_XCOFFOBJECTFILE_H 140b57cec5SDimitry Andric #define LLVM_OBJECT_XCOFFOBJECTFILE_H 150b57cec5SDimitry Andric 16e8d8bef9SDimitry Andric #include "llvm/ADT/SmallString.h" 17e8d8bef9SDimitry Andric #include "llvm/ADT/SmallVector.h" 185f757f3fSDimitry Andric #include "llvm/ADT/iterator_range.h" 190b57cec5SDimitry Andric #include "llvm/BinaryFormat/XCOFF.h" 200b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 215ffd83dbSDimitry Andric #include "llvm/Support/Endian.h" 225ffd83dbSDimitry Andric #include <limits> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric namespace object { 260b57cec5SDimitry Andric 275f757f3fSDimitry Andric class xcoff_symbol_iterator; 285f757f3fSDimitry Andric 290b57cec5SDimitry Andric struct XCOFFFileHeader32 { 300b57cec5SDimitry Andric support::ubig16_t Magic; 310b57cec5SDimitry Andric support::ubig16_t NumberOfSections; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric // Unix time value, value of 0 indicates no timestamp. 340b57cec5SDimitry Andric // Negative values are reserved. 350b57cec5SDimitry Andric support::big32_t TimeStamp; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric support::ubig32_t SymbolTableOffset; // File offset to symbol table. 380b57cec5SDimitry Andric support::big32_t NumberOfSymTableEntries; 390b57cec5SDimitry Andric support::ubig16_t AuxHeaderSize; 400b57cec5SDimitry Andric support::ubig16_t Flags; 410b57cec5SDimitry Andric }; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric struct XCOFFFileHeader64 { 440b57cec5SDimitry Andric support::ubig16_t Magic; 450b57cec5SDimitry Andric support::ubig16_t NumberOfSections; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric // Unix time value, value of 0 indicates no timestamp. 480b57cec5SDimitry Andric // Negative values are reserved. 490b57cec5SDimitry Andric support::big32_t TimeStamp; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric support::ubig64_t SymbolTableOffset; // File offset to symbol table. 520b57cec5SDimitry Andric support::ubig16_t AuxHeaderSize; 530b57cec5SDimitry Andric support::ubig16_t Flags; 540b57cec5SDimitry Andric support::ubig32_t NumberOfSymTableEntries; 550b57cec5SDimitry Andric }; 560b57cec5SDimitry Andric 57349cc55cSDimitry Andric template <typename T> struct XCOFFAuxiliaryHeader { 58349cc55cSDimitry Andric static constexpr uint8_t AuxiHeaderFlagMask = 0xF0; 59349cc55cSDimitry Andric static constexpr uint8_t AuxiHeaderTDataAlignmentMask = 0x0F; 60349cc55cSDimitry Andric 61349cc55cSDimitry Andric public: 62349cc55cSDimitry Andric uint8_t getFlag() const { 63349cc55cSDimitry Andric return static_cast<const T *>(this)->FlagAndTDataAlignment & 64349cc55cSDimitry Andric AuxiHeaderFlagMask; 65349cc55cSDimitry Andric } 6681ad6265SDimitry Andric 67349cc55cSDimitry Andric uint8_t getTDataAlignment() const { 68349cc55cSDimitry Andric return static_cast<const T *>(this)->FlagAndTDataAlignment & 69349cc55cSDimitry Andric AuxiHeaderTDataAlignmentMask; 70349cc55cSDimitry Andric } 7181ad6265SDimitry Andric 7281ad6265SDimitry Andric uint16_t getVersion() const { return static_cast<const T *>(this)->Version; } 73*0fca6ea1SDimitry Andric uint64_t getEntryPointAddr() const { 74*0fca6ea1SDimitry Andric return static_cast<const T *>(this)->EntryPointAddr; 75*0fca6ea1SDimitry Andric } 76349cc55cSDimitry Andric }; 77349cc55cSDimitry Andric 78349cc55cSDimitry Andric struct XCOFFAuxiliaryHeader32 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader32> { 79349cc55cSDimitry Andric support::ubig16_t 80349cc55cSDimitry Andric AuxMagic; ///< If the value of the o_vstamp field is greater than 1, the 81349cc55cSDimitry Andric ///< o_mflags field is reserved for future use and it should 82349cc55cSDimitry Andric ///< contain 0. Otherwise, this field is not used. 83349cc55cSDimitry Andric support::ubig16_t 84349cc55cSDimitry Andric Version; ///< The valid values are 1 and 2. When the o_vstamp field is 2 85349cc55cSDimitry Andric ///< in an XCOFF32 file, the new interpretation of the n_type 86349cc55cSDimitry Andric ///< field in the symbol table entry is used. 87349cc55cSDimitry Andric support::ubig32_t TextSize; 88349cc55cSDimitry Andric support::ubig32_t InitDataSize; 89349cc55cSDimitry Andric support::ubig32_t BssDataSize; 90349cc55cSDimitry Andric support::ubig32_t EntryPointAddr; 91349cc55cSDimitry Andric support::ubig32_t TextStartAddr; 92349cc55cSDimitry Andric support::ubig32_t DataStartAddr; 93349cc55cSDimitry Andric support::ubig32_t TOCAnchorAddr; 94349cc55cSDimitry Andric support::ubig16_t SecNumOfEntryPoint; 95349cc55cSDimitry Andric support::ubig16_t SecNumOfText; 96349cc55cSDimitry Andric support::ubig16_t SecNumOfData; 97349cc55cSDimitry Andric support::ubig16_t SecNumOfTOC; 98349cc55cSDimitry Andric support::ubig16_t SecNumOfLoader; 99349cc55cSDimitry Andric support::ubig16_t SecNumOfBSS; 100349cc55cSDimitry Andric support::ubig16_t MaxAlignOfText; 101349cc55cSDimitry Andric support::ubig16_t MaxAlignOfData; 102349cc55cSDimitry Andric support::ubig16_t ModuleType; 103349cc55cSDimitry Andric uint8_t CpuFlag; 104349cc55cSDimitry Andric uint8_t CpuType; 105349cc55cSDimitry Andric support::ubig32_t MaxStackSize; ///< If the value is 0, the system default 106349cc55cSDimitry Andric ///< maximum stack size is used. 107349cc55cSDimitry Andric support::ubig32_t MaxDataSize; ///< If the value is 0, the system default 108349cc55cSDimitry Andric ///< maximum data size is used. 109349cc55cSDimitry Andric support::ubig32_t 110349cc55cSDimitry Andric ReservedForDebugger; ///< This field should contain 0. When a loaded 111349cc55cSDimitry Andric ///< program is being debugged, the memory image of 112349cc55cSDimitry Andric ///< this field may be modified by a debugger to 113349cc55cSDimitry Andric ///< insert a trap instruction. 114349cc55cSDimitry Andric uint8_t TextPageSize; ///< Specifies the size of pages for the exec text. The 115349cc55cSDimitry Andric ///< default value is 0 (system-selected page size). 116349cc55cSDimitry Andric uint8_t DataPageSize; ///< Specifies the size of pages for the exec data. The 117349cc55cSDimitry Andric ///< default value is 0 (system-selected page size). 118349cc55cSDimitry Andric uint8_t StackPageSize; ///< Specifies the size of pages for the stack. The 119349cc55cSDimitry Andric ///< default value is 0 (system-selected page size). 120349cc55cSDimitry Andric uint8_t FlagAndTDataAlignment; 121349cc55cSDimitry Andric support::ubig16_t SecNumOfTData; 122349cc55cSDimitry Andric support::ubig16_t SecNumOfTBSS; 123349cc55cSDimitry Andric }; 124349cc55cSDimitry Andric 12581ad6265SDimitry Andric struct XCOFFAuxiliaryHeader64 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader64> { 126349cc55cSDimitry Andric support::ubig16_t AuxMagic; 127349cc55cSDimitry Andric support::ubig16_t Version; 128349cc55cSDimitry Andric support::ubig32_t ReservedForDebugger; 129349cc55cSDimitry Andric support::ubig64_t TextStartAddr; 130349cc55cSDimitry Andric support::ubig64_t DataStartAddr; 131349cc55cSDimitry Andric support::ubig64_t TOCAnchorAddr; 132349cc55cSDimitry Andric support::ubig16_t SecNumOfEntryPoint; 133349cc55cSDimitry Andric support::ubig16_t SecNumOfText; 134349cc55cSDimitry Andric support::ubig16_t SecNumOfData; 135349cc55cSDimitry Andric support::ubig16_t SecNumOfTOC; 136349cc55cSDimitry Andric support::ubig16_t SecNumOfLoader; 137349cc55cSDimitry Andric support::ubig16_t SecNumOfBSS; 138349cc55cSDimitry Andric support::ubig16_t MaxAlignOfText; 139349cc55cSDimitry Andric support::ubig16_t MaxAlignOfData; 140349cc55cSDimitry Andric support::ubig16_t ModuleType; 141349cc55cSDimitry Andric uint8_t CpuFlag; 142349cc55cSDimitry Andric uint8_t CpuType; 143349cc55cSDimitry Andric uint8_t TextPageSize; 144349cc55cSDimitry Andric uint8_t DataPageSize; 145349cc55cSDimitry Andric uint8_t StackPageSize; 146349cc55cSDimitry Andric uint8_t FlagAndTDataAlignment; 147349cc55cSDimitry Andric support::ubig64_t TextSize; 148349cc55cSDimitry Andric support::ubig64_t InitDataSize; 149349cc55cSDimitry Andric support::ubig64_t BssDataSize; 150349cc55cSDimitry Andric support::ubig64_t EntryPointAddr; 151349cc55cSDimitry Andric support::ubig64_t MaxStackSize; 152349cc55cSDimitry Andric support::ubig64_t MaxDataSize; 153349cc55cSDimitry Andric support::ubig16_t SecNumOfTData; 154349cc55cSDimitry Andric support::ubig16_t SecNumOfTBSS; 155349cc55cSDimitry Andric support::ubig16_t XCOFF64Flag; 156349cc55cSDimitry Andric }; 157349cc55cSDimitry Andric 158480093f4SDimitry Andric template <typename T> struct XCOFFSectionHeader { 159*0fca6ea1SDimitry Andric // The section flags definitions are the same in both 32- and 64-bit objects. 160480093f4SDimitry Andric // Least significant 3 bits are reserved. 161480093f4SDimitry Andric static constexpr unsigned SectionFlagsReservedMask = 0x7; 162480093f4SDimitry Andric 163480093f4SDimitry Andric // The low order 16 bits of section flags denotes the section type. 164*0fca6ea1SDimitry Andric // The high order 16 bits of section flags denotes the section subtype. 165*0fca6ea1SDimitry Andric // For now, this is only used for DWARF sections. 166480093f4SDimitry Andric static constexpr unsigned SectionFlagsTypeMask = 0xffffu; 167480093f4SDimitry Andric 168480093f4SDimitry Andric public: 169480093f4SDimitry Andric StringRef getName() const; 170480093f4SDimitry Andric uint16_t getSectionType() const; 171*0fca6ea1SDimitry Andric uint32_t getSectionSubtype() const; 172480093f4SDimitry Andric bool isReservedSectionType() const; 173480093f4SDimitry Andric }; 174480093f4SDimitry Andric 175480093f4SDimitry Andric // Explicit extern template declarations. 176480093f4SDimitry Andric struct XCOFFSectionHeader32; 177480093f4SDimitry Andric struct XCOFFSectionHeader64; 178480093f4SDimitry Andric extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>; 179480093f4SDimitry Andric extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>; 180480093f4SDimitry Andric 181480093f4SDimitry Andric struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> { 1828bcb0991SDimitry Andric char Name[XCOFF::NameSize]; 1830b57cec5SDimitry Andric support::ubig32_t PhysicalAddress; 1840b57cec5SDimitry Andric support::ubig32_t VirtualAddress; 1850b57cec5SDimitry Andric support::ubig32_t SectionSize; 1860b57cec5SDimitry Andric support::ubig32_t FileOffsetToRawData; 1870b57cec5SDimitry Andric support::ubig32_t FileOffsetToRelocationInfo; 1880b57cec5SDimitry Andric support::ubig32_t FileOffsetToLineNumberInfo; 1890b57cec5SDimitry Andric support::ubig16_t NumberOfRelocations; 1900b57cec5SDimitry Andric support::ubig16_t NumberOfLineNumbers; 1910b57cec5SDimitry Andric support::big32_t Flags; 1920b57cec5SDimitry Andric }; 1930b57cec5SDimitry Andric 194480093f4SDimitry Andric struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> { 1958bcb0991SDimitry Andric char Name[XCOFF::NameSize]; 1960b57cec5SDimitry Andric support::ubig64_t PhysicalAddress; 1970b57cec5SDimitry Andric support::ubig64_t VirtualAddress; 1980b57cec5SDimitry Andric support::ubig64_t SectionSize; 1990b57cec5SDimitry Andric support::big64_t FileOffsetToRawData; 2000b57cec5SDimitry Andric support::big64_t FileOffsetToRelocationInfo; 2010b57cec5SDimitry Andric support::big64_t FileOffsetToLineNumberInfo; 2020b57cec5SDimitry Andric support::ubig32_t NumberOfRelocations; 2030b57cec5SDimitry Andric support::ubig32_t NumberOfLineNumbers; 2040b57cec5SDimitry Andric support::big32_t Flags; 2050b57cec5SDimitry Andric char Padding[4]; 2060b57cec5SDimitry Andric }; 2070b57cec5SDimitry Andric 208bdd1243dSDimitry Andric struct LoaderSectionHeader32; 209bdd1243dSDimitry Andric struct LoaderSectionHeader64; 210bdd1243dSDimitry Andric struct LoaderSectionSymbolEntry32 { 211bdd1243dSDimitry Andric struct NameOffsetInStrTbl { 212bdd1243dSDimitry Andric support::big32_t IsNameInStrTbl; // Zero indicates name in string table. 213bdd1243dSDimitry Andric support::ubig32_t Offset; 214bdd1243dSDimitry Andric }; 215bdd1243dSDimitry Andric 216bdd1243dSDimitry Andric char SymbolName[XCOFF::NameSize]; 217bdd1243dSDimitry Andric support::ubig32_t Value; // The virtual address of the symbol. 218bdd1243dSDimitry Andric support::big16_t SectionNumber; 219bdd1243dSDimitry Andric uint8_t SymbolType; 220bdd1243dSDimitry Andric XCOFF::StorageClass StorageClass; 221bdd1243dSDimitry Andric support::ubig32_t ImportFileID; 222bdd1243dSDimitry Andric support::ubig32_t ParameterTypeCheck; 223bdd1243dSDimitry Andric 224bdd1243dSDimitry Andric Expected<StringRef> 225bdd1243dSDimitry Andric getSymbolName(const LoaderSectionHeader32 *LoaderSecHeader) const; 226bdd1243dSDimitry Andric }; 227bdd1243dSDimitry Andric 228bdd1243dSDimitry Andric struct LoaderSectionSymbolEntry64 { 229bdd1243dSDimitry Andric support::ubig64_t Value; // The virtual address of the symbol. 230bdd1243dSDimitry Andric support::ubig32_t Offset; 231bdd1243dSDimitry Andric support::big16_t SectionNumber; 232bdd1243dSDimitry Andric uint8_t SymbolType; 233bdd1243dSDimitry Andric XCOFF::StorageClass StorageClass; 234bdd1243dSDimitry Andric support::ubig32_t ImportFileID; 235bdd1243dSDimitry Andric support::ubig32_t ParameterTypeCheck; 236bdd1243dSDimitry Andric 237bdd1243dSDimitry Andric Expected<StringRef> 238bdd1243dSDimitry Andric getSymbolName(const LoaderSectionHeader64 *LoaderSecHeader) const; 239bdd1243dSDimitry Andric }; 240bdd1243dSDimitry Andric 241bdd1243dSDimitry Andric struct LoaderSectionRelocationEntry32 { 242bdd1243dSDimitry Andric support::ubig32_t VirtualAddr; 243bdd1243dSDimitry Andric support::big32_t SymbolIndex; 244bdd1243dSDimitry Andric support::ubig16_t Type; 245bdd1243dSDimitry Andric support::big16_t SectionNum; 246bdd1243dSDimitry Andric }; 247bdd1243dSDimitry Andric 248bdd1243dSDimitry Andric struct LoaderSectionRelocationEntry64 { 249bdd1243dSDimitry Andric support::ubig64_t VirtualAddr; 250bdd1243dSDimitry Andric support::ubig16_t Type; 251bdd1243dSDimitry Andric support::big16_t SectionNum; 252bdd1243dSDimitry Andric support::big32_t SymbolIndex; 253bdd1243dSDimitry Andric }; 254bdd1243dSDimitry Andric 255349cc55cSDimitry Andric struct LoaderSectionHeader32 { 256349cc55cSDimitry Andric support::ubig32_t Version; 257349cc55cSDimitry Andric support::ubig32_t NumberOfSymTabEnt; 258349cc55cSDimitry Andric support::ubig32_t NumberOfRelTabEnt; 259349cc55cSDimitry Andric support::ubig32_t LengthOfImpidStrTbl; 260349cc55cSDimitry Andric support::ubig32_t NumberOfImpid; 261349cc55cSDimitry Andric support::big32_t OffsetToImpid; 262349cc55cSDimitry Andric support::ubig32_t LengthOfStrTbl; 263349cc55cSDimitry Andric support::big32_t OffsetToStrTbl; 264bdd1243dSDimitry Andric 265bdd1243dSDimitry Andric uint64_t getOffsetToSymTbl() const { 266bdd1243dSDimitry Andric return NumberOfSymTabEnt == 0 ? 0 : sizeof(LoaderSectionHeader32); 267bdd1243dSDimitry Andric } 268bdd1243dSDimitry Andric 269bdd1243dSDimitry Andric uint64_t getOffsetToRelEnt() const { 270bdd1243dSDimitry Andric // Relocation table is after Symbol table. 271bdd1243dSDimitry Andric return NumberOfRelTabEnt == 0 272bdd1243dSDimitry Andric ? 0 273bdd1243dSDimitry Andric : sizeof(LoaderSectionHeader32) + 274bdd1243dSDimitry Andric sizeof(LoaderSectionSymbolEntry32) * NumberOfSymTabEnt; 275bdd1243dSDimitry Andric } 276349cc55cSDimitry Andric }; 277349cc55cSDimitry Andric 278349cc55cSDimitry Andric struct LoaderSectionHeader64 { 279349cc55cSDimitry Andric support::ubig32_t Version; 280349cc55cSDimitry Andric support::ubig32_t NumberOfSymTabEnt; 281349cc55cSDimitry Andric support::ubig32_t NumberOfRelTabEnt; 282349cc55cSDimitry Andric support::ubig32_t LengthOfImpidStrTbl; 283349cc55cSDimitry Andric support::ubig32_t NumberOfImpid; 284349cc55cSDimitry Andric support::ubig32_t LengthOfStrTbl; 285349cc55cSDimitry Andric support::big64_t OffsetToImpid; 286349cc55cSDimitry Andric support::big64_t OffsetToStrTbl; 287349cc55cSDimitry Andric support::big64_t OffsetToSymTbl; 288bdd1243dSDimitry Andric support::big64_t OffsetToRelEnt; 289bdd1243dSDimitry Andric 290bdd1243dSDimitry Andric uint64_t getOffsetToSymTbl() const { return OffsetToSymTbl; } 291bdd1243dSDimitry Andric uint64_t getOffsetToRelEnt() const { return OffsetToRelEnt; } 292349cc55cSDimitry Andric }; 293349cc55cSDimitry Andric 294bdd1243dSDimitry Andric template <typename AddressType> struct ExceptionSectionEntry { 295bdd1243dSDimitry Andric union { 296bdd1243dSDimitry Andric support::ubig32_t SymbolIdx; 297bdd1243dSDimitry Andric AddressType TrapInstAddr; 298bdd1243dSDimitry Andric }; 299bdd1243dSDimitry Andric uint8_t LangId; 300bdd1243dSDimitry Andric uint8_t Reason; 301bdd1243dSDimitry Andric 302bdd1243dSDimitry Andric uint32_t getSymbolIndex() const { 303bdd1243dSDimitry Andric assert(Reason == 0 && "Get symbol table index of the function only when " 304bdd1243dSDimitry Andric "the e_reason field is 0."); 305bdd1243dSDimitry Andric return SymbolIdx; 306bdd1243dSDimitry Andric } 307bdd1243dSDimitry Andric 308bdd1243dSDimitry Andric uint64_t getTrapInstAddr() const { 309bdd1243dSDimitry Andric assert(Reason != 0 && "Zero is not a valid trap exception reason code."); 310bdd1243dSDimitry Andric return TrapInstAddr; 311bdd1243dSDimitry Andric } 312bdd1243dSDimitry Andric uint8_t getLangID() const { return LangId; } 313bdd1243dSDimitry Andric uint8_t getReason() const { return Reason; } 314bdd1243dSDimitry Andric }; 315bdd1243dSDimitry Andric 316bdd1243dSDimitry Andric typedef ExceptionSectionEntry<support::ubig32_t> ExceptionSectionEntry32; 317bdd1243dSDimitry Andric typedef ExceptionSectionEntry<support::ubig64_t> ExceptionSectionEntry64; 318bdd1243dSDimitry Andric 319bdd1243dSDimitry Andric // Explicit extern template declarations. 320bdd1243dSDimitry Andric extern template struct ExceptionSectionEntry<support::ubig32_t>; 321bdd1243dSDimitry Andric extern template struct ExceptionSectionEntry<support::ubig64_t>; 322bdd1243dSDimitry Andric 3230b57cec5SDimitry Andric struct XCOFFStringTable { 3240b57cec5SDimitry Andric uint32_t Size; 3250b57cec5SDimitry Andric const char *Data; 3260b57cec5SDimitry Andric }; 3270b57cec5SDimitry Andric 3288bcb0991SDimitry Andric struct XCOFFCsectAuxEnt32 { 329fe6060f1SDimitry Andric support::ubig32_t SectionOrLength; 3308bcb0991SDimitry Andric support::ubig32_t ParameterHashIndex; 3318bcb0991SDimitry Andric support::ubig16_t TypeChkSectNum; 3328bcb0991SDimitry Andric uint8_t SymbolAlignmentAndType; 3338bcb0991SDimitry Andric XCOFF::StorageMappingClass StorageMappingClass; 3348bcb0991SDimitry Andric support::ubig32_t StabInfoIndex; 3358bcb0991SDimitry Andric support::ubig16_t StabSectNum; 336fe6060f1SDimitry Andric }; 337fe6060f1SDimitry Andric 338fe6060f1SDimitry Andric struct XCOFFCsectAuxEnt64 { 339fe6060f1SDimitry Andric support::ubig32_t SectionOrLengthLowByte; 340fe6060f1SDimitry Andric support::ubig32_t ParameterHashIndex; 341fe6060f1SDimitry Andric support::ubig16_t TypeChkSectNum; 342fe6060f1SDimitry Andric uint8_t SymbolAlignmentAndType; 343fe6060f1SDimitry Andric XCOFF::StorageMappingClass StorageMappingClass; 344fe6060f1SDimitry Andric support::ubig32_t SectionOrLengthHighByte; 345fe6060f1SDimitry Andric uint8_t Pad; 346fe6060f1SDimitry Andric XCOFF::SymbolAuxType AuxType; 347fe6060f1SDimitry Andric }; 348fe6060f1SDimitry Andric 349fe6060f1SDimitry Andric class XCOFFCsectAuxRef { 350fe6060f1SDimitry Andric public: 351fe6060f1SDimitry Andric static constexpr uint8_t SymbolTypeMask = 0x07; 352fe6060f1SDimitry Andric static constexpr uint8_t SymbolAlignmentMask = 0xF8; 353fe6060f1SDimitry Andric static constexpr size_t SymbolAlignmentBitOffset = 3; 354fe6060f1SDimitry Andric 355fe6060f1SDimitry Andric XCOFFCsectAuxRef(const XCOFFCsectAuxEnt32 *Entry32) : Entry32(Entry32) {} 356fe6060f1SDimitry Andric XCOFFCsectAuxRef(const XCOFFCsectAuxEnt64 *Entry64) : Entry64(Entry64) {} 357fe6060f1SDimitry Andric 358fe6060f1SDimitry Andric // For getSectionOrLength(), 359fe6060f1SDimitry Andric // If the symbol type is XTY_SD or XTY_CM, the csect length. 360fe6060f1SDimitry Andric // If the symbol type is XTY_LD, the symbol table 361fe6060f1SDimitry Andric // index of the containing csect. 362fe6060f1SDimitry Andric // If the symbol type is XTY_ER, 0. 363fe6060f1SDimitry Andric uint64_t getSectionOrLength() const { 364fe6060f1SDimitry Andric return Entry32 ? getSectionOrLength32() : getSectionOrLength64(); 365fe6060f1SDimitry Andric } 366fe6060f1SDimitry Andric 367fe6060f1SDimitry Andric uint32_t getSectionOrLength32() const { 368fe6060f1SDimitry Andric assert(Entry32 && "32-bit interface called on 64-bit object file."); 369fe6060f1SDimitry Andric return Entry32->SectionOrLength; 370fe6060f1SDimitry Andric } 371fe6060f1SDimitry Andric 372fe6060f1SDimitry Andric uint64_t getSectionOrLength64() const { 373fe6060f1SDimitry Andric assert(Entry64 && "64-bit interface called on 32-bit object file."); 374fe6060f1SDimitry Andric return (static_cast<uint64_t>(Entry64->SectionOrLengthHighByte) << 32) | 375fe6060f1SDimitry Andric Entry64->SectionOrLengthLowByte; 376fe6060f1SDimitry Andric } 377fe6060f1SDimitry Andric 378fe6060f1SDimitry Andric #define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X 379fe6060f1SDimitry Andric 380fe6060f1SDimitry Andric uint32_t getParameterHashIndex() const { 381fe6060f1SDimitry Andric return GETVALUE(ParameterHashIndex); 382fe6060f1SDimitry Andric } 383fe6060f1SDimitry Andric 384fe6060f1SDimitry Andric uint16_t getTypeChkSectNum() const { return GETVALUE(TypeChkSectNum); } 385fe6060f1SDimitry Andric 386fe6060f1SDimitry Andric XCOFF::StorageMappingClass getStorageMappingClass() const { 387fe6060f1SDimitry Andric return GETVALUE(StorageMappingClass); 388fe6060f1SDimitry Andric } 389fe6060f1SDimitry Andric 390fe6060f1SDimitry Andric uintptr_t getEntryAddress() const { 391fe6060f1SDimitry Andric return Entry32 ? reinterpret_cast<uintptr_t>(Entry32) 392fe6060f1SDimitry Andric : reinterpret_cast<uintptr_t>(Entry64); 393fe6060f1SDimitry Andric } 3945ffd83dbSDimitry Andric 3955ffd83dbSDimitry Andric uint16_t getAlignmentLog2() const { 396fe6060f1SDimitry Andric return (getSymbolAlignmentAndType() & SymbolAlignmentMask) >> 3975ffd83dbSDimitry Andric SymbolAlignmentBitOffset; 3985ffd83dbSDimitry Andric } 3995ffd83dbSDimitry Andric 4005ffd83dbSDimitry Andric uint8_t getSymbolType() const { 401fe6060f1SDimitry Andric return getSymbolAlignmentAndType() & SymbolTypeMask; 4025ffd83dbSDimitry Andric } 4035ffd83dbSDimitry Andric 4045ffd83dbSDimitry Andric bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; } 405fe6060f1SDimitry Andric 406fe6060f1SDimitry Andric uint32_t getStabInfoIndex32() const { 407fe6060f1SDimitry Andric assert(Entry32 && "32-bit interface called on 64-bit object file."); 408fe6060f1SDimitry Andric return Entry32->StabInfoIndex; 409fe6060f1SDimitry Andric } 410fe6060f1SDimitry Andric 411fe6060f1SDimitry Andric uint16_t getStabSectNum32() const { 412fe6060f1SDimitry Andric assert(Entry32 && "32-bit interface called on 64-bit object file."); 413fe6060f1SDimitry Andric return Entry32->StabSectNum; 414fe6060f1SDimitry Andric } 415fe6060f1SDimitry Andric 416fe6060f1SDimitry Andric XCOFF::SymbolAuxType getAuxType64() const { 417fe6060f1SDimitry Andric assert(Entry64 && "64-bit interface called on 32-bit object file."); 418fe6060f1SDimitry Andric return Entry64->AuxType; 419fe6060f1SDimitry Andric } 420fe6060f1SDimitry Andric 421fe6060f1SDimitry Andric uint8_t getSymbolAlignmentAndType() const { 422fe6060f1SDimitry Andric return GETVALUE(SymbolAlignmentAndType); 423fe6060f1SDimitry Andric } 424fe6060f1SDimitry Andric 425fe6060f1SDimitry Andric #undef GETVALUE 426fe6060f1SDimitry Andric 4275f757f3fSDimitry Andric private: 428fe6060f1SDimitry Andric const XCOFFCsectAuxEnt32 *Entry32 = nullptr; 429fe6060f1SDimitry Andric const XCOFFCsectAuxEnt64 *Entry64 = nullptr; 4308bcb0991SDimitry Andric }; 4318bcb0991SDimitry Andric 4328bcb0991SDimitry Andric struct XCOFFFileAuxEnt { 4338bcb0991SDimitry Andric typedef struct { 4348bcb0991SDimitry Andric support::big32_t Magic; // Zero indicates name in string table. 4358bcb0991SDimitry Andric support::ubig32_t Offset; 4368bcb0991SDimitry Andric char NamePad[XCOFF::FileNamePadSize]; 4378bcb0991SDimitry Andric } NameInStrTblType; 4388bcb0991SDimitry Andric union { 4398bcb0991SDimitry Andric char Name[XCOFF::NameSize + XCOFF::FileNamePadSize]; 4408bcb0991SDimitry Andric NameInStrTblType NameInStrTbl; 4418bcb0991SDimitry Andric }; 4428bcb0991SDimitry Andric XCOFF::CFileStringType Type; 4438bcb0991SDimitry Andric uint8_t ReservedZeros[2]; 444fe6060f1SDimitry Andric XCOFF::SymbolAuxType AuxType; // 64-bit XCOFF file only. 4458bcb0991SDimitry Andric }; 4468bcb0991SDimitry Andric 4478bcb0991SDimitry Andric struct XCOFFSectAuxEntForStat { 4488bcb0991SDimitry Andric support::ubig32_t SectionLength; 4498bcb0991SDimitry Andric support::ubig16_t NumberOfRelocEnt; 4508bcb0991SDimitry Andric support::ubig16_t NumberOfLineNum; 4518bcb0991SDimitry Andric uint8_t Pad[10]; 452fe6060f1SDimitry Andric }; // 32-bit XCOFF file only. 4538bcb0991SDimitry Andric 45404eeddc0SDimitry Andric struct XCOFFFunctionAuxEnt32 { 45504eeddc0SDimitry Andric support::ubig32_t OffsetToExceptionTbl; 45604eeddc0SDimitry Andric support::ubig32_t SizeOfFunction; 45704eeddc0SDimitry Andric support::ubig32_t PtrToLineNum; 45804eeddc0SDimitry Andric support::big32_t SymIdxOfNextBeyond; 45904eeddc0SDimitry Andric uint8_t Pad[2]; 46004eeddc0SDimitry Andric }; 46104eeddc0SDimitry Andric 46204eeddc0SDimitry Andric struct XCOFFFunctionAuxEnt64 { 46304eeddc0SDimitry Andric support::ubig64_t PtrToLineNum; 46404eeddc0SDimitry Andric support::ubig32_t SizeOfFunction; 46504eeddc0SDimitry Andric support::big32_t SymIdxOfNextBeyond; 46604eeddc0SDimitry Andric uint8_t Pad; 46704eeddc0SDimitry Andric XCOFF::SymbolAuxType AuxType; // Contains _AUX_FCN; Type of auxiliary entry 46804eeddc0SDimitry Andric }; 46904eeddc0SDimitry Andric 47004eeddc0SDimitry Andric struct XCOFFExceptionAuxEnt { 47104eeddc0SDimitry Andric support::ubig64_t OffsetToExceptionTbl; 47204eeddc0SDimitry Andric support::ubig32_t SizeOfFunction; 47304eeddc0SDimitry Andric support::big32_t SymIdxOfNextBeyond; 47404eeddc0SDimitry Andric uint8_t Pad; 47504eeddc0SDimitry Andric XCOFF::SymbolAuxType AuxType; // Contains _AUX_EXCEPT; Type of auxiliary entry 47604eeddc0SDimitry Andric }; 47704eeddc0SDimitry Andric 47804eeddc0SDimitry Andric struct XCOFFBlockAuxEnt32 { 47904eeddc0SDimitry Andric uint8_t ReservedZeros1[2]; 48004eeddc0SDimitry Andric support::ubig16_t LineNumHi; 48104eeddc0SDimitry Andric support::ubig16_t LineNumLo; 48204eeddc0SDimitry Andric uint8_t ReservedZeros2[12]; 48304eeddc0SDimitry Andric }; 48404eeddc0SDimitry Andric 48504eeddc0SDimitry Andric struct XCOFFBlockAuxEnt64 { 48604eeddc0SDimitry Andric support::ubig32_t LineNum; 48704eeddc0SDimitry Andric uint8_t Pad[13]; 48804eeddc0SDimitry Andric XCOFF::SymbolAuxType AuxType; // Contains _AUX_SYM; Type of auxiliary entry 48904eeddc0SDimitry Andric }; 49004eeddc0SDimitry Andric 49104eeddc0SDimitry Andric struct XCOFFSectAuxEntForDWARF32 { 49204eeddc0SDimitry Andric support::ubig32_t LengthOfSectionPortion; 49304eeddc0SDimitry Andric uint8_t Pad1[4]; 49404eeddc0SDimitry Andric support::ubig32_t NumberOfRelocEnt; 49504eeddc0SDimitry Andric uint8_t Pad2[6]; 49604eeddc0SDimitry Andric }; 49704eeddc0SDimitry Andric 49804eeddc0SDimitry Andric struct XCOFFSectAuxEntForDWARF64 { 49904eeddc0SDimitry Andric support::ubig64_t LengthOfSectionPortion; 50004eeddc0SDimitry Andric support::ubig64_t NumberOfRelocEnt; 50104eeddc0SDimitry Andric uint8_t Pad; 50204eeddc0SDimitry Andric XCOFF::SymbolAuxType AuxType; // Contains _AUX_SECT; Type of Auxillary entry 50304eeddc0SDimitry Andric }; 50404eeddc0SDimitry Andric 505349cc55cSDimitry Andric template <typename AddressType> struct XCOFFRelocation { 5068bcb0991SDimitry Andric public: 507349cc55cSDimitry Andric AddressType VirtualAddress; 5088bcb0991SDimitry Andric support::ubig32_t SymbolIndex; 5098bcb0991SDimitry Andric 5108bcb0991SDimitry Andric // Packed field, see XR_* masks for details of packing. 5118bcb0991SDimitry Andric uint8_t Info; 5128bcb0991SDimitry Andric 5138bcb0991SDimitry Andric XCOFF::RelocationType Type; 5148bcb0991SDimitry Andric 5158bcb0991SDimitry Andric public: 5168bcb0991SDimitry Andric bool isRelocationSigned() const; 5178bcb0991SDimitry Andric bool isFixupIndicated() const; 5188bcb0991SDimitry Andric 5198bcb0991SDimitry Andric // Returns the number of bits being relocated. 5208bcb0991SDimitry Andric uint8_t getRelocatedLength() const; 5218bcb0991SDimitry Andric }; 5228bcb0991SDimitry Andric 523349cc55cSDimitry Andric extern template struct XCOFFRelocation<llvm::support::ubig32_t>; 524349cc55cSDimitry Andric extern template struct XCOFFRelocation<llvm::support::ubig64_t>; 525349cc55cSDimitry Andric 526349cc55cSDimitry Andric struct XCOFFRelocation32 : XCOFFRelocation<llvm::support::ubig32_t> {}; 527349cc55cSDimitry Andric struct XCOFFRelocation64 : XCOFFRelocation<llvm::support::ubig64_t> {}; 528349cc55cSDimitry Andric 529fe6060f1SDimitry Andric class XCOFFSymbolRef; 530fe6060f1SDimitry Andric 5310b57cec5SDimitry Andric class XCOFFObjectFile : public ObjectFile { 5320b57cec5SDimitry Andric private: 5330b57cec5SDimitry Andric const void *FileHeader = nullptr; 534349cc55cSDimitry Andric const void *AuxiliaryHeader = nullptr; 5350b57cec5SDimitry Andric const void *SectionHeaderTable = nullptr; 5360b57cec5SDimitry Andric 537fe6060f1SDimitry Andric const void *SymbolTblPtr = nullptr; 5380b57cec5SDimitry Andric XCOFFStringTable StringTable = {0, nullptr}; 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric const XCOFFSectionHeader32 *sectionHeaderTable32() const; 5410b57cec5SDimitry Andric const XCOFFSectionHeader64 *sectionHeaderTable64() const; 542349cc55cSDimitry Andric template <typename T> const T *sectionHeaderTable() const; 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric size_t getFileHeaderSize() const; 5450b57cec5SDimitry Andric size_t getSectionHeaderSize() const; 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const; 5480b57cec5SDimitry Andric const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const; 5490b57cec5SDimitry Andric uintptr_t getSectionHeaderTableAddress() const; 5508bcb0991SDimitry Andric uintptr_t getEndOfSymbolTableAddress() const; 551bdd1243dSDimitry Andric 552bdd1243dSDimitry Andric DataRefImpl getSectionByType(XCOFF::SectionTypeFlags SectType) const; 553bdd1243dSDimitry Andric uint64_t getSectionFileOffsetToRawData(DataRefImpl Sec) const; 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric // This returns a pointer to the start of the storage for the name field of 5560b57cec5SDimitry Andric // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily 5570b57cec5SDimitry Andric // null-terminated. 5580b57cec5SDimitry Andric const char *getSectionNameInternal(DataRefImpl Sec) const; 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric static bool isReservedSectionNumber(int16_t SectionNumber); 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric // Constructor and "create" factory function. The constructor is only a thin 5630b57cec5SDimitry Andric // wrapper around the base constructor. The "create" function fills out the 5640b57cec5SDimitry Andric // XCOFF-specific information and performs the error checking along the way. 5650b57cec5SDimitry Andric XCOFFObjectFile(unsigned Type, MemoryBufferRef Object); 5660b57cec5SDimitry Andric static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type, 5670b57cec5SDimitry Andric MemoryBufferRef MBR); 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric // Helper for parsing the StringTable. Returns an 'Error' if parsing failed 5700b57cec5SDimitry Andric // and an XCOFFStringTable if parsing succeeded. 5710b57cec5SDimitry Andric static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj, 5720b57cec5SDimitry Andric uint64_t Offset); 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric // Make a friend so it can call the private 'create' function. 5750b57cec5SDimitry Andric friend Expected<std::unique_ptr<ObjectFile>> 5760b57cec5SDimitry Andric ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); 5770b57cec5SDimitry Andric 5788bcb0991SDimitry Andric void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const; 5798bcb0991SDimitry Andric 5800b57cec5SDimitry Andric public: 5815ffd83dbSDimitry Andric static constexpr uint64_t InvalidRelocOffset = 5825ffd83dbSDimitry Andric std::numeric_limits<uint64_t>::max(); 5835ffd83dbSDimitry Andric 5840b57cec5SDimitry Andric // Interface inherited from base classes. 5850b57cec5SDimitry Andric void moveSymbolNext(DataRefImpl &Symb) const override; 5865ffd83dbSDimitry Andric Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; 5870b57cec5SDimitry Andric basic_symbol_iterator symbol_begin() const override; 5880b57cec5SDimitry Andric basic_symbol_iterator symbol_end() const override; 5895f757f3fSDimitry Andric 5905f757f3fSDimitry Andric using xcoff_symbol_iterator_range = iterator_range<xcoff_symbol_iterator>; 5915f757f3fSDimitry Andric xcoff_symbol_iterator_range symbols() const; 5925f757f3fSDimitry Andric 59306c3fb27SDimitry Andric bool is64Bit() const override; 5940b57cec5SDimitry Andric Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; 5950b57cec5SDimitry Andric Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; 5960b57cec5SDimitry Andric uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; 597349cc55cSDimitry Andric uint32_t getSymbolAlignment(DataRefImpl Symb) const override; 5980b57cec5SDimitry Andric uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; 5990b57cec5SDimitry Andric Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; 6000b57cec5SDimitry Andric Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric void moveSectionNext(DataRefImpl &Sec) const override; 6030b57cec5SDimitry Andric Expected<StringRef> getSectionName(DataRefImpl Sec) const override; 6040b57cec5SDimitry Andric uint64_t getSectionAddress(DataRefImpl Sec) const override; 6050b57cec5SDimitry Andric uint64_t getSectionIndex(DataRefImpl Sec) const override; 6060b57cec5SDimitry Andric uint64_t getSectionSize(DataRefImpl Sec) const override; 6070b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>> 6080b57cec5SDimitry Andric getSectionContents(DataRefImpl Sec) const override; 6090b57cec5SDimitry Andric uint64_t getSectionAlignment(DataRefImpl Sec) const override; 6100b57cec5SDimitry Andric bool isSectionCompressed(DataRefImpl Sec) const override; 6110b57cec5SDimitry Andric bool isSectionText(DataRefImpl Sec) const override; 6120b57cec5SDimitry Andric bool isSectionData(DataRefImpl Sec) const override; 6130b57cec5SDimitry Andric bool isSectionBSS(DataRefImpl Sec) const override; 614fe6060f1SDimitry Andric bool isDebugSection(DataRefImpl Sec) const override; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric bool isSectionVirtual(DataRefImpl Sec) const override; 6170b57cec5SDimitry Andric relocation_iterator section_rel_begin(DataRefImpl Sec) const override; 6180b57cec5SDimitry Andric relocation_iterator section_rel_end(DataRefImpl Sec) const override; 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric void moveRelocationNext(DataRefImpl &Rel) const override; 6215ffd83dbSDimitry Andric 6225ffd83dbSDimitry Andric /// \returns the relocation offset with the base address of the containing 6235ffd83dbSDimitry Andric /// section as zero, or InvalidRelocOffset on errors (such as a relocation 6245ffd83dbSDimitry Andric /// that does not refer to an address in any section). 6250b57cec5SDimitry Andric uint64_t getRelocationOffset(DataRefImpl Rel) const override; 6260b57cec5SDimitry Andric symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; 6270b57cec5SDimitry Andric uint64_t getRelocationType(DataRefImpl Rel) const override; 6280b57cec5SDimitry Andric void getRelocationTypeName(DataRefImpl Rel, 6290b57cec5SDimitry Andric SmallVectorImpl<char> &Result) const override; 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric section_iterator section_begin() const override; 6320b57cec5SDimitry Andric section_iterator section_end() const override; 6330b57cec5SDimitry Andric uint8_t getBytesInAddress() const override; 6340b57cec5SDimitry Andric StringRef getFileFormatName() const override; 6350b57cec5SDimitry Andric Triple::ArchType getArch() const override; 636bdd1243dSDimitry Andric Expected<SubtargetFeatures> getFeatures() const override; 6370b57cec5SDimitry Andric Expected<uint64_t> getStartAddress() const override; 638fe6060f1SDimitry Andric StringRef mapDebugSectionName(StringRef Name) const override; 6390b57cec5SDimitry Andric bool isRelocatableObject() const override; 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric // Below here is the non-inherited interface. 64206c3fb27SDimitry Andric 64381ad6265SDimitry Andric Expected<StringRef> getRawData(const char *Start, uint64_t Size, 64481ad6265SDimitry Andric StringRef Name) const; 6450b57cec5SDimitry Andric 646349cc55cSDimitry Andric const XCOFFAuxiliaryHeader32 *auxiliaryHeader32() const; 647349cc55cSDimitry Andric const XCOFFAuxiliaryHeader64 *auxiliaryHeader64() const; 648349cc55cSDimitry Andric 649fe6060f1SDimitry Andric const void *getPointerToSymbolTable() const { return SymbolTblPtr; } 6500b57cec5SDimitry Andric 651fe6060f1SDimitry Andric Expected<StringRef> getSymbolSectionName(XCOFFSymbolRef Ref) const; 652fe6060f1SDimitry Andric unsigned getSymbolSectionID(SymbolRef Sym) const; 653fe6060f1SDimitry Andric XCOFFSymbolRef toSymbolRef(DataRefImpl Ref) const; 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric // File header related interfaces. 65681ad6265SDimitry Andric const XCOFFFileHeader32 *fileHeader32() const; 65781ad6265SDimitry Andric const XCOFFFileHeader64 *fileHeader64() const; 6580b57cec5SDimitry Andric uint16_t getMagic() const; 6590b57cec5SDimitry Andric uint16_t getNumberOfSections() const; 6600b57cec5SDimitry Andric int32_t getTimeStamp() const; 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric // Symbol table offset and entry count are handled differently between 6630b57cec5SDimitry Andric // XCOFF32 and XCOFF64. 6640b57cec5SDimitry Andric uint32_t getSymbolTableOffset32() const; 6650b57cec5SDimitry Andric uint64_t getSymbolTableOffset64() const; 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric // Note that this value is signed and might return a negative value. Negative 6680b57cec5SDimitry Andric // values are reserved for future use. 6690b57cec5SDimitry Andric int32_t getRawNumberOfSymbolTableEntries32() const; 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric // The sanitized value appropriate to use as an index into the symbol table. 6720b57cec5SDimitry Andric uint32_t getLogicalNumberOfSymbolTableEntries32() const; 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric uint32_t getNumberOfSymbolTableEntries64() const; 675fe6060f1SDimitry Andric 676fe6060f1SDimitry Andric // Return getLogicalNumberOfSymbolTableEntries32 or 677fe6060f1SDimitry Andric // getNumberOfSymbolTableEntries64 depending on the object mode. 678fe6060f1SDimitry Andric uint32_t getNumberOfSymbolTableEntries() const; 679fe6060f1SDimitry Andric 6808bcb0991SDimitry Andric uint32_t getSymbolIndex(uintptr_t SymEntPtr) const; 681349cc55cSDimitry Andric uint64_t getSymbolSize(DataRefImpl Symb) const; 682349cc55cSDimitry Andric uintptr_t getSymbolByIndex(uint32_t Idx) const { 683349cc55cSDimitry Andric return reinterpret_cast<uintptr_t>(SymbolTblPtr) + 684349cc55cSDimitry Andric XCOFF::SymbolTableEntrySize * Idx; 685349cc55cSDimitry Andric } 686fe6060f1SDimitry Andric uintptr_t getSymbolEntryAddressByIndex(uint32_t SymbolTableIndex) const; 6878bcb0991SDimitry Andric Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const; 6880b57cec5SDimitry Andric 6898bcb0991SDimitry Andric Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const; 6900b57cec5SDimitry Andric uint16_t getOptionalHeaderSize() const; 6910b57cec5SDimitry Andric uint16_t getFlags() const; 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric // Section header table related interfaces. 6940b57cec5SDimitry Andric ArrayRef<XCOFFSectionHeader32> sections32() const; 6950b57cec5SDimitry Andric ArrayRef<XCOFFSectionHeader64> sections64() const; 6968bcb0991SDimitry Andric 6978bcb0991SDimitry Andric int32_t getSectionFlags(DataRefImpl Sec) const; 6988bcb0991SDimitry Andric Expected<DataRefImpl> getSectionByNum(int16_t Num) const; 6998bcb0991SDimitry Andric 700bdd1243dSDimitry Andric Expected<uintptr_t> 701bdd1243dSDimitry Andric getSectionFileOffsetToRawData(XCOFF::SectionTypeFlags SectType) const; 702bdd1243dSDimitry Andric 7038bcb0991SDimitry Andric void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const; 7048bcb0991SDimitry Andric 7058bcb0991SDimitry Andric // Relocation-related interfaces. 706349cc55cSDimitry Andric template <typename T> 7078bcb0991SDimitry Andric Expected<uint32_t> 708349cc55cSDimitry Andric getNumberOfRelocationEntries(const XCOFFSectionHeader<T> &Sec) const; 7098bcb0991SDimitry Andric 710349cc55cSDimitry Andric template <typename Shdr, typename Reloc> 711349cc55cSDimitry Andric Expected<ArrayRef<Reloc>> relocations(const Shdr &Sec) const; 712349cc55cSDimitry Andric 713349cc55cSDimitry Andric // Loader section related interfaces. 714349cc55cSDimitry Andric Expected<StringRef> getImportFileTable() const; 715e8d8bef9SDimitry Andric 716bdd1243dSDimitry Andric // Exception-related interface. 717bdd1243dSDimitry Andric template <typename ExceptEnt> 718bdd1243dSDimitry Andric Expected<ArrayRef<ExceptEnt>> getExceptionEntries() const; 719bdd1243dSDimitry Andric 720fe6060f1SDimitry Andric // This function returns string table entry. 721fe6060f1SDimitry Andric Expected<StringRef> getStringTableEntry(uint32_t Offset) const; 722fe6060f1SDimitry Andric 723fe6060f1SDimitry Andric // This function returns the string table. 724fe6060f1SDimitry Andric StringRef getStringTable() const; 725fe6060f1SDimitry Andric 726fe6060f1SDimitry Andric const XCOFF::SymbolAuxType *getSymbolAuxType(uintptr_t AuxEntryAddress) const; 727fe6060f1SDimitry Andric 728fe6060f1SDimitry Andric static uintptr_t getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, 729fe6060f1SDimitry Andric uint32_t Distance); 730fe6060f1SDimitry Andric 731e8d8bef9SDimitry Andric static bool classof(const Binary *B) { return B->isXCOFF(); } 73206c3fb27SDimitry Andric 73306c3fb27SDimitry Andric std::optional<StringRef> tryGetCPUName() const override; 7340b57cec5SDimitry Andric }; // XCOFFObjectFile 7350b57cec5SDimitry Andric 736fe6060f1SDimitry Andric typedef struct { 737fe6060f1SDimitry Andric uint8_t LanguageId; 738fe6060f1SDimitry Andric uint8_t CpuTypeId; 739fe6060f1SDimitry Andric } CFileLanguageIdAndTypeIdType; 7408bcb0991SDimitry Andric 741fe6060f1SDimitry Andric struct XCOFFSymbolEntry32 { 742fe6060f1SDimitry Andric typedef struct { 743fe6060f1SDimitry Andric support::big32_t Magic; // Zero indicates name in string table. 744fe6060f1SDimitry Andric support::ubig32_t Offset; 745fe6060f1SDimitry Andric } NameInStrTblType; 746fe6060f1SDimitry Andric 747fe6060f1SDimitry Andric union { 748fe6060f1SDimitry Andric char SymbolName[XCOFF::NameSize]; 749fe6060f1SDimitry Andric NameInStrTblType NameInStrTbl; 750fe6060f1SDimitry Andric }; 751fe6060f1SDimitry Andric 752fe6060f1SDimitry Andric support::ubig32_t Value; // Symbol value; storage class-dependent. 753fe6060f1SDimitry Andric support::big16_t SectionNumber; 754fe6060f1SDimitry Andric 755fe6060f1SDimitry Andric union { 756fe6060f1SDimitry Andric support::ubig16_t SymbolType; 757fe6060f1SDimitry Andric CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; 758fe6060f1SDimitry Andric }; 759fe6060f1SDimitry Andric 760fe6060f1SDimitry Andric XCOFF::StorageClass StorageClass; 761fe6060f1SDimitry Andric uint8_t NumberOfAuxEntries; 762fe6060f1SDimitry Andric }; 763fe6060f1SDimitry Andric 764fe6060f1SDimitry Andric struct XCOFFSymbolEntry64 { 765fe6060f1SDimitry Andric support::ubig64_t Value; // Symbol value; storage class-dependent. 766fe6060f1SDimitry Andric support::ubig32_t Offset; 767fe6060f1SDimitry Andric support::big16_t SectionNumber; 768fe6060f1SDimitry Andric 769fe6060f1SDimitry Andric union { 770fe6060f1SDimitry Andric support::ubig16_t SymbolType; 771fe6060f1SDimitry Andric CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; 772fe6060f1SDimitry Andric }; 773fe6060f1SDimitry Andric 774fe6060f1SDimitry Andric XCOFF::StorageClass StorageClass; 775fe6060f1SDimitry Andric uint8_t NumberOfAuxEntries; 776fe6060f1SDimitry Andric }; 777fe6060f1SDimitry Andric 7785f757f3fSDimitry Andric class XCOFFSymbolRef : public SymbolRef { 7798bcb0991SDimitry Andric public: 780fe6060f1SDimitry Andric enum { NAME_IN_STR_TBL_MAGIC = 0x0 }; 781fe6060f1SDimitry Andric 7828bcb0991SDimitry Andric XCOFFSymbolRef(DataRefImpl SymEntDataRef, 7838bcb0991SDimitry Andric const XCOFFObjectFile *OwningObjectPtr) 7845f757f3fSDimitry Andric : SymbolRef(SymEntDataRef, OwningObjectPtr) { 785fe6060f1SDimitry Andric assert(OwningObjectPtr && "OwningObjectPtr cannot be nullptr!"); 786fe6060f1SDimitry Andric assert(SymEntDataRef.p != 0 && 787fe6060f1SDimitry Andric "Symbol table entry pointer cannot be nullptr!"); 788fe6060f1SDimitry Andric } 7898bcb0991SDimitry Andric 7905f757f3fSDimitry Andric const XCOFFSymbolEntry32 *getSymbol32() const { 7915f757f3fSDimitry Andric return reinterpret_cast<const XCOFFSymbolEntry32 *>(getRawDataRefImpl().p); 7925f757f3fSDimitry Andric } 79381ad6265SDimitry Andric 7945f757f3fSDimitry Andric const XCOFFSymbolEntry64 *getSymbol64() const { 7955f757f3fSDimitry Andric return reinterpret_cast<const XCOFFSymbolEntry64 *>(getRawDataRefImpl().p); 7965f757f3fSDimitry Andric } 797fe6060f1SDimitry Andric 7985f757f3fSDimitry Andric uint64_t getValue() const { 7995f757f3fSDimitry Andric return getObject()->is64Bit() ? getValue64() : getValue32(); 8005f757f3fSDimitry Andric } 801fe6060f1SDimitry Andric 8025f757f3fSDimitry Andric uint32_t getValue32() const { 8035f757f3fSDimitry Andric return reinterpret_cast<const XCOFFSymbolEntry32 *>(getRawDataRefImpl().p) 8045f757f3fSDimitry Andric ->Value; 8055f757f3fSDimitry Andric } 806fe6060f1SDimitry Andric 8075f757f3fSDimitry Andric uint64_t getValue64() const { 8085f757f3fSDimitry Andric return reinterpret_cast<const XCOFFSymbolEntry64 *>(getRawDataRefImpl().p) 8095f757f3fSDimitry Andric ->Value; 8105f757f3fSDimitry Andric } 8115f757f3fSDimitry Andric 8125f757f3fSDimitry Andric uint64_t getSize() const { 8135f757f3fSDimitry Andric return getObject()->getSymbolSize(getRawDataRefImpl()); 8145f757f3fSDimitry Andric } 8155f757f3fSDimitry Andric 8165f757f3fSDimitry Andric #define GETVALUE(X) \ 8175f757f3fSDimitry Andric getObject()->is64Bit() \ 8185f757f3fSDimitry Andric ? reinterpret_cast<const XCOFFSymbolEntry64 *>(getRawDataRefImpl().p)->X \ 8195f757f3fSDimitry Andric : reinterpret_cast<const XCOFFSymbolEntry32 *>(getRawDataRefImpl().p)->X 820fe6060f1SDimitry Andric 821fe6060f1SDimitry Andric int16_t getSectionNumber() const { return GETVALUE(SectionNumber); } 822fe6060f1SDimitry Andric 823fe6060f1SDimitry Andric uint16_t getSymbolType() const { return GETVALUE(SymbolType); } 824fe6060f1SDimitry Andric 825fe6060f1SDimitry Andric uint8_t getLanguageIdForCFile() const { 826fe6060f1SDimitry Andric assert(getStorageClass() == XCOFF::C_FILE && 827fe6060f1SDimitry Andric "This interface is for C_FILE only."); 828fe6060f1SDimitry Andric return GETVALUE(CFileLanguageIdAndTypeId.LanguageId); 829fe6060f1SDimitry Andric } 830fe6060f1SDimitry Andric 831fe6060f1SDimitry Andric uint8_t getCPUTypeIddForCFile() const { 832fe6060f1SDimitry Andric assert(getStorageClass() == XCOFF::C_FILE && 833fe6060f1SDimitry Andric "This interface is for C_FILE only."); 834fe6060f1SDimitry Andric return GETVALUE(CFileLanguageIdAndTypeId.CpuTypeId); 835fe6060f1SDimitry Andric } 836fe6060f1SDimitry Andric 837fe6060f1SDimitry Andric XCOFF::StorageClass getStorageClass() const { return GETVALUE(StorageClass); } 838fe6060f1SDimitry Andric 839fe6060f1SDimitry Andric uint8_t getNumberOfAuxEntries() const { return GETVALUE(NumberOfAuxEntries); } 840fe6060f1SDimitry Andric 841fe6060f1SDimitry Andric #undef GETVALUE 842fe6060f1SDimitry Andric 843fe6060f1SDimitry Andric uintptr_t getEntryAddress() const { 8445f757f3fSDimitry Andric return getRawDataRefImpl().p; 845fe6060f1SDimitry Andric } 846fe6060f1SDimitry Andric 847fe6060f1SDimitry Andric Expected<StringRef> getName() const; 8485f757f3fSDimitry Andric Expected<bool> isFunction() const; 849fe6060f1SDimitry Andric bool isCsectSymbol() const; 850fe6060f1SDimitry Andric Expected<XCOFFCsectAuxRef> getXCOFFCsectAuxRef() const; 851fe6060f1SDimitry Andric 852fe6060f1SDimitry Andric private: 8535f757f3fSDimitry Andric const XCOFFObjectFile *getObject() const { 8545f757f3fSDimitry Andric return cast<XCOFFObjectFile>(BasicSymbolRef::getObject()); 8555f757f3fSDimitry Andric } 8565f757f3fSDimitry Andric }; 8575f757f3fSDimitry Andric 8585f757f3fSDimitry Andric class xcoff_symbol_iterator : public symbol_iterator { 8595f757f3fSDimitry Andric public: 8605f757f3fSDimitry Andric xcoff_symbol_iterator(const basic_symbol_iterator &B) 8615f757f3fSDimitry Andric : symbol_iterator(B) {} 8625f757f3fSDimitry Andric 8635f757f3fSDimitry Andric xcoff_symbol_iterator(const XCOFFSymbolRef *Symbol) 8645f757f3fSDimitry Andric : symbol_iterator(*Symbol) {} 8655f757f3fSDimitry Andric 8665f757f3fSDimitry Andric const XCOFFSymbolRef *operator->() const { 8675f757f3fSDimitry Andric return static_cast<const XCOFFSymbolRef *>(symbol_iterator::operator->()); 8685f757f3fSDimitry Andric } 8695f757f3fSDimitry Andric 8705f757f3fSDimitry Andric const XCOFFSymbolRef &operator*() const { 8715f757f3fSDimitry Andric return static_cast<const XCOFFSymbolRef &>(symbol_iterator::operator*()); 8725f757f3fSDimitry Andric } 8738bcb0991SDimitry Andric }; 8748bcb0991SDimitry Andric 875e8d8bef9SDimitry Andric class TBVectorExt { 876e8d8bef9SDimitry Andric uint16_t Data; 877fe6060f1SDimitry Andric SmallString<32> VecParmsInfo; 878e8d8bef9SDimitry Andric 879fe6060f1SDimitry Andric TBVectorExt(StringRef TBvectorStrRef, Error &Err); 880e8d8bef9SDimitry Andric 881e8d8bef9SDimitry Andric public: 882fe6060f1SDimitry Andric static Expected<TBVectorExt> create(StringRef TBvectorStrRef); 883e8d8bef9SDimitry Andric uint8_t getNumberOfVRSaved() const; 884e8d8bef9SDimitry Andric bool isVRSavedOnStack() const; 885e8d8bef9SDimitry Andric bool hasVarArgs() const; 886e8d8bef9SDimitry Andric uint8_t getNumberOfVectorParms() const; 887e8d8bef9SDimitry Andric bool hasVMXInstruction() const; 888fe6060f1SDimitry Andric SmallString<32> getVectorParmsInfo() const { return VecParmsInfo; }; 889e8d8bef9SDimitry Andric }; 890e8d8bef9SDimitry Andric 891e8d8bef9SDimitry Andric /// This class provides methods to extract traceback table data from a buffer. 892e8d8bef9SDimitry Andric /// The various accessors may reference the buffer provided via the constructor. 893e8d8bef9SDimitry Andric 894e8d8bef9SDimitry Andric class XCOFFTracebackTable { 895e8d8bef9SDimitry Andric const uint8_t *const TBPtr; 89606c3fb27SDimitry Andric bool Is64BitObj; 897bdd1243dSDimitry Andric std::optional<SmallString<32>> ParmsType; 898bdd1243dSDimitry Andric std::optional<uint32_t> TraceBackTableOffset; 899bdd1243dSDimitry Andric std::optional<uint32_t> HandlerMask; 900bdd1243dSDimitry Andric std::optional<uint32_t> NumOfCtlAnchors; 901bdd1243dSDimitry Andric std::optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp; 902bdd1243dSDimitry Andric std::optional<StringRef> FunctionName; 903bdd1243dSDimitry Andric std::optional<uint8_t> AllocaRegister; 904bdd1243dSDimitry Andric std::optional<TBVectorExt> VecExt; 905bdd1243dSDimitry Andric std::optional<uint8_t> ExtensionTable; 90606c3fb27SDimitry Andric std::optional<uint64_t> EhInfoDisp; 907e8d8bef9SDimitry Andric 90806c3fb27SDimitry Andric XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err, 90906c3fb27SDimitry Andric bool Is64Bit = false); 910349cc55cSDimitry Andric 911e8d8bef9SDimitry Andric public: 912e8d8bef9SDimitry Andric /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes. 913e8d8bef9SDimitry Andric /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an 914e8d8bef9SDimitry Andric /// Error is returned. 915e8d8bef9SDimitry Andric /// 916e8d8bef9SDimitry Andric /// \param[in] Ptr 917e8d8bef9SDimitry Andric /// A pointer that points just past the initial 4 bytes of zeros at the 918e8d8bef9SDimitry Andric /// beginning of an XCOFF Traceback Table. 919e8d8bef9SDimitry Andric /// 920e8d8bef9SDimitry Andric /// \param[in, out] Size 921e8d8bef9SDimitry Andric /// A pointer that points to the length of the XCOFF Traceback Table. 922e8d8bef9SDimitry Andric /// If the XCOFF Traceback Table is not parsed successfully or there are 923e8d8bef9SDimitry Andric /// extra bytes that are not recognized, \a Size will be updated to be the 924e8d8bef9SDimitry Andric /// size up to the end of the last successfully parsed field of the table. 92506c3fb27SDimitry Andric static Expected<XCOFFTracebackTable> 92606c3fb27SDimitry Andric create(const uint8_t *Ptr, uint64_t &Size, bool Is64Bits = false); 927e8d8bef9SDimitry Andric uint8_t getVersion() const; 928e8d8bef9SDimitry Andric uint8_t getLanguageID() const; 929e8d8bef9SDimitry Andric 930e8d8bef9SDimitry Andric bool isGlobalLinkage() const; 931e8d8bef9SDimitry Andric bool isOutOfLineEpilogOrPrologue() const; 932e8d8bef9SDimitry Andric bool hasTraceBackTableOffset() const; 933e8d8bef9SDimitry Andric bool isInternalProcedure() const; 934e8d8bef9SDimitry Andric bool hasControlledStorage() const; 935e8d8bef9SDimitry Andric bool isTOCless() const; 936e8d8bef9SDimitry Andric bool isFloatingPointPresent() const; 937e8d8bef9SDimitry Andric bool isFloatingPointOperationLogOrAbortEnabled() const; 938e8d8bef9SDimitry Andric 939e8d8bef9SDimitry Andric bool isInterruptHandler() const; 940e8d8bef9SDimitry Andric bool isFuncNamePresent() const; 941e8d8bef9SDimitry Andric bool isAllocaUsed() const; 942e8d8bef9SDimitry Andric uint8_t getOnConditionDirective() const; 943e8d8bef9SDimitry Andric bool isCRSaved() const; 944e8d8bef9SDimitry Andric bool isLRSaved() const; 945e8d8bef9SDimitry Andric 946e8d8bef9SDimitry Andric bool isBackChainStored() const; 947e8d8bef9SDimitry Andric bool isFixup() const; 948e8d8bef9SDimitry Andric uint8_t getNumOfFPRsSaved() const; 949e8d8bef9SDimitry Andric 950e8d8bef9SDimitry Andric bool hasVectorInfo() const; 951e8d8bef9SDimitry Andric bool hasExtensionTable() const; 952e8d8bef9SDimitry Andric uint8_t getNumOfGPRsSaved() const; 953e8d8bef9SDimitry Andric 954e8d8bef9SDimitry Andric uint8_t getNumberOfFixedParms() const; 955e8d8bef9SDimitry Andric 956e8d8bef9SDimitry Andric uint8_t getNumberOfFPParms() const; 957e8d8bef9SDimitry Andric bool hasParmsOnStack() const; 958e8d8bef9SDimitry Andric 959bdd1243dSDimitry Andric const std::optional<SmallString<32>> &getParmsType() const { 960bdd1243dSDimitry Andric return ParmsType; 961bdd1243dSDimitry Andric } 962bdd1243dSDimitry Andric const std::optional<uint32_t> &getTraceBackTableOffset() const { 963e8d8bef9SDimitry Andric return TraceBackTableOffset; 964e8d8bef9SDimitry Andric } 965bdd1243dSDimitry Andric const std::optional<uint32_t> &getHandlerMask() const { return HandlerMask; } 966bdd1243dSDimitry Andric const std::optional<uint32_t> &getNumOfCtlAnchors() { 967bdd1243dSDimitry Andric return NumOfCtlAnchors; 968bdd1243dSDimitry Andric } 969bdd1243dSDimitry Andric const std::optional<SmallVector<uint32_t, 8>> & 970bdd1243dSDimitry Andric getControlledStorageInfoDisp() { 971e8d8bef9SDimitry Andric return ControlledStorageInfoDisp; 972e8d8bef9SDimitry Andric } 973bdd1243dSDimitry Andric const std::optional<StringRef> &getFunctionName() const { 974bdd1243dSDimitry Andric return FunctionName; 975bdd1243dSDimitry Andric } 976bdd1243dSDimitry Andric const std::optional<uint8_t> &getAllocaRegister() const { 977bdd1243dSDimitry Andric return AllocaRegister; 978bdd1243dSDimitry Andric } 979bdd1243dSDimitry Andric const std::optional<TBVectorExt> &getVectorExt() const { return VecExt; } 980bdd1243dSDimitry Andric const std::optional<uint8_t> &getExtensionTable() const { 981bdd1243dSDimitry Andric return ExtensionTable; 982bdd1243dSDimitry Andric } 98306c3fb27SDimitry Andric const std::optional<uint64_t> &getEhInfoDisp() const { return EhInfoDisp; } 984e8d8bef9SDimitry Andric }; 985e8d8bef9SDimitry Andric 986e8d8bef9SDimitry Andric bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes); 9870b57cec5SDimitry Andric } // namespace object 9880b57cec5SDimitry Andric } // namespace llvm 9890b57cec5SDimitry Andric 9900b57cec5SDimitry Andric #endif // LLVM_OBJECT_XCOFFOBJECTFILE_H 991