Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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