Home | History | Annotate | Line # | Download | only in Object
      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 XCOFFSectionHeader {
     55   // Least significant 3 bits are reserved.
     56   static constexpr unsigned SectionFlagsReservedMask = 0x7;
     57 
     58   // The low order 16 bits of section flags denotes the section type.
     59   static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
     60 
     61 public:
     62   StringRef getName() const;
     63   uint16_t getSectionType() const;
     64   bool isReservedSectionType() const;
     65 };
     66 
     67 // Explicit extern template declarations.
     68 struct XCOFFSectionHeader32;
     69 struct XCOFFSectionHeader64;
     70 extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
     71 extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
     72 
     73 struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> {
     74   char Name[XCOFF::NameSize];
     75   support::ubig32_t PhysicalAddress;
     76   support::ubig32_t VirtualAddress;
     77   support::ubig32_t SectionSize;
     78   support::ubig32_t FileOffsetToRawData;
     79   support::ubig32_t FileOffsetToRelocationInfo;
     80   support::ubig32_t FileOffsetToLineNumberInfo;
     81   support::ubig16_t NumberOfRelocations;
     82   support::ubig16_t NumberOfLineNumbers;
     83   support::big32_t Flags;
     84 };
     85 
     86 struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
     87   char Name[XCOFF::NameSize];
     88   support::ubig64_t PhysicalAddress;
     89   support::ubig64_t VirtualAddress;
     90   support::ubig64_t SectionSize;
     91   support::big64_t FileOffsetToRawData;
     92   support::big64_t FileOffsetToRelocationInfo;
     93   support::big64_t FileOffsetToLineNumberInfo;
     94   support::ubig32_t NumberOfRelocations;
     95   support::ubig32_t NumberOfLineNumbers;
     96   support::big32_t Flags;
     97   char Padding[4];
     98 };
     99 
    100 struct XCOFFSymbolEntry {
    101   enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
    102   typedef struct {
    103     support::big32_t Magic; // Zero indicates name in string table.
    104     support::ubig32_t Offset;
    105   } NameInStrTblType;
    106 
    107   typedef struct {
    108     uint8_t LanguageId;
    109     uint8_t CpuTypeId;
    110   } CFileLanguageIdAndTypeIdType;
    111 
    112   union {
    113     char SymbolName[XCOFF::NameSize];
    114     NameInStrTblType NameInStrTbl;
    115   };
    116 
    117   support::ubig32_t Value; // Symbol value; storage class-dependent.
    118   support::big16_t SectionNumber;
    119 
    120   union {
    121     support::ubig16_t SymbolType;
    122     CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
    123   };
    124 
    125   XCOFF::StorageClass StorageClass;
    126   uint8_t NumberOfAuxEntries;
    127 };
    128 
    129 struct XCOFFStringTable {
    130   uint32_t Size;
    131   const char *Data;
    132 };
    133 
    134 struct XCOFFCsectAuxEnt32 {
    135   static constexpr uint8_t SymbolTypeMask = 0x07;
    136   static constexpr uint8_t SymbolAlignmentMask = 0xF8;
    137   static constexpr size_t SymbolAlignmentBitOffset = 3;
    138 
    139   support::ubig32_t
    140       SectionOrLength; // If the symbol type is XTY_SD or XTY_CM, the csect
    141                        // length.
    142                        // If the symbol type is XTY_LD, the symbol table
    143                        // index of the containing csect.
    144                        // If the symbol type is XTY_ER, 0.
    145   support::ubig32_t ParameterHashIndex;
    146   support::ubig16_t TypeChkSectNum;
    147   uint8_t SymbolAlignmentAndType;
    148   XCOFF::StorageMappingClass StorageMappingClass;
    149   support::ubig32_t StabInfoIndex;
    150   support::ubig16_t StabSectNum;
    151 
    152   uint16_t getAlignmentLog2() const {
    153     return (SymbolAlignmentAndType & SymbolAlignmentMask) >>
    154            SymbolAlignmentBitOffset;
    155   }
    156 
    157   uint8_t getSymbolType() const {
    158     return SymbolAlignmentAndType & SymbolTypeMask;
    159   }
    160 
    161   bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; }
    162 };
    163 
    164 struct XCOFFFileAuxEnt {
    165   typedef struct {
    166     support::big32_t Magic; // Zero indicates name in string table.
    167     support::ubig32_t Offset;
    168     char NamePad[XCOFF::FileNamePadSize];
    169   } NameInStrTblType;
    170   union {
    171     char Name[XCOFF::NameSize + XCOFF::FileNamePadSize];
    172     NameInStrTblType NameInStrTbl;
    173   };
    174   XCOFF::CFileStringType Type;
    175   uint8_t ReservedZeros[2];
    176   uint8_t AuxType; // 64-bit XCOFF file only.
    177 };
    178 
    179 struct XCOFFSectAuxEntForStat {
    180   support::ubig32_t SectionLength;
    181   support::ubig16_t NumberOfRelocEnt;
    182   support::ubig16_t NumberOfLineNum;
    183   uint8_t Pad[10];
    184 };
    185 
    186 struct XCOFFRelocation32 {
    187   // Masks for packing/unpacking the r_rsize field of relocations.
    188 
    189   // The msb is used to indicate if the bits being relocated are signed or
    190   // unsigned.
    191   static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80;
    192 
    193   // The 2nd msb is used to indicate that the binder has replaced/modified the
    194   // original instruction.
    195   static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40;
    196 
    197   // The remaining bits specify the bit length of the relocatable reference
    198   // minus one.
    199   static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;
    200 
    201 public:
    202   support::ubig32_t VirtualAddress;
    203   support::ubig32_t SymbolIndex;
    204 
    205   // Packed field, see XR_* masks for details of packing.
    206   uint8_t Info;
    207 
    208   XCOFF::RelocationType Type;
    209 
    210 public:
    211   bool isRelocationSigned() const;
    212   bool isFixupIndicated() const;
    213 
    214   // Returns the number of bits being relocated.
    215   uint8_t getRelocatedLength() const;
    216 };
    217 
    218 class XCOFFObjectFile : public ObjectFile {
    219 private:
    220   const void *FileHeader = nullptr;
    221   const void *SectionHeaderTable = nullptr;
    222 
    223   const XCOFFSymbolEntry *SymbolTblPtr = nullptr;
    224   XCOFFStringTable StringTable = {0, nullptr};
    225 
    226   const XCOFFFileHeader32 *fileHeader32() const;
    227   const XCOFFFileHeader64 *fileHeader64() const;
    228 
    229   const XCOFFSectionHeader32 *sectionHeaderTable32() const;
    230   const XCOFFSectionHeader64 *sectionHeaderTable64() const;
    231 
    232   size_t getFileHeaderSize() const;
    233   size_t getSectionHeaderSize() const;
    234 
    235   const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
    236   const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
    237   uintptr_t getSectionHeaderTableAddress() const;
    238   uintptr_t getEndOfSymbolTableAddress() const;
    239 
    240   // This returns a pointer to the start of the storage for the name field of
    241   // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
    242   // null-terminated.
    243   const char *getSectionNameInternal(DataRefImpl Sec) const;
    244 
    245   // This function returns string table entry.
    246   Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
    247 
    248   static bool isReservedSectionNumber(int16_t SectionNumber);
    249 
    250   // Constructor and "create" factory function. The constructor is only a thin
    251   // wrapper around the base constructor. The "create" function fills out the
    252   // XCOFF-specific information and performs the error checking along the way.
    253   XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
    254   static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
    255                                                            MemoryBufferRef MBR);
    256 
    257   // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
    258   // and an XCOFFStringTable if parsing succeeded.
    259   static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
    260                                                      uint64_t Offset);
    261 
    262   // Make a friend so it can call the private 'create' function.
    263   friend Expected<std::unique_ptr<ObjectFile>>
    264   ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
    265 
    266   void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
    267 
    268 public:
    269   static constexpr uint64_t InvalidRelocOffset =
    270       std::numeric_limits<uint64_t>::max();
    271 
    272   // Interface inherited from base classes.
    273   void moveSymbolNext(DataRefImpl &Symb) const override;
    274   Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
    275   basic_symbol_iterator symbol_begin() const override;
    276   basic_symbol_iterator symbol_end() const override;
    277 
    278   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
    279   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
    280   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
    281   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
    282   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
    283   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
    284 
    285   void moveSectionNext(DataRefImpl &Sec) const override;
    286   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
    287   uint64_t getSectionAddress(DataRefImpl Sec) const override;
    288   uint64_t getSectionIndex(DataRefImpl Sec) const override;
    289   uint64_t getSectionSize(DataRefImpl Sec) const override;
    290   Expected<ArrayRef<uint8_t>>
    291   getSectionContents(DataRefImpl Sec) const override;
    292   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
    293   bool isSectionCompressed(DataRefImpl Sec) const override;
    294   bool isSectionText(DataRefImpl Sec) const override;
    295   bool isSectionData(DataRefImpl Sec) const override;
    296   bool isSectionBSS(DataRefImpl Sec) const override;
    297 
    298   bool isSectionVirtual(DataRefImpl Sec) const override;
    299   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
    300   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
    301 
    302   void moveRelocationNext(DataRefImpl &Rel) const override;
    303 
    304   /// \returns the relocation offset with the base address of the containing
    305   /// section as zero, or InvalidRelocOffset on errors (such as a relocation
    306   /// that does not refer to an address in any section).
    307   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
    308   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
    309   uint64_t getRelocationType(DataRefImpl Rel) const override;
    310   void getRelocationTypeName(DataRefImpl Rel,
    311                              SmallVectorImpl<char> &Result) const override;
    312 
    313   section_iterator section_begin() const override;
    314   section_iterator section_end() const override;
    315   uint8_t getBytesInAddress() const override;
    316   StringRef getFileFormatName() const override;
    317   Triple::ArchType getArch() const override;
    318   SubtargetFeatures getFeatures() const override;
    319   Expected<uint64_t> getStartAddress() const override;
    320   StringRef mapDebugSectionName(StringRef Name) const override;
    321   bool isRelocatableObject() const override;
    322 
    323   // Below here is the non-inherited interface.
    324   bool is64Bit() const;
    325 
    326   const XCOFFSymbolEntry *getPointerToSymbolTable() const {
    327     assert(!is64Bit() && "Symbol table handling not supported yet.");
    328     return SymbolTblPtr;
    329   }
    330 
    331   Expected<StringRef>
    332   getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const;
    333 
    334   const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const;
    335 
    336   // File header related interfaces.
    337   uint16_t getMagic() const;
    338   uint16_t getNumberOfSections() const;
    339   int32_t getTimeStamp() const;
    340 
    341   // Symbol table offset and entry count are handled differently between
    342   // XCOFF32 and XCOFF64.
    343   uint32_t getSymbolTableOffset32() const;
    344   uint64_t getSymbolTableOffset64() const;
    345 
    346   // Note that this value is signed and might return a negative value. Negative
    347   // values are reserved for future use.
    348   int32_t getRawNumberOfSymbolTableEntries32() const;
    349 
    350   // The sanitized value appropriate to use as an index into the symbol table.
    351   uint32_t getLogicalNumberOfSymbolTableEntries32() const;
    352 
    353   uint32_t getNumberOfSymbolTableEntries64() const;
    354   uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
    355   Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
    356 
    357   Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
    358   uint16_t getOptionalHeaderSize() const;
    359   uint16_t getFlags() const;
    360 
    361   // Section header table related interfaces.
    362   ArrayRef<XCOFFSectionHeader32> sections32() const;
    363   ArrayRef<XCOFFSectionHeader64> sections64() const;
    364 
    365   int32_t getSectionFlags(DataRefImpl Sec) const;
    366   Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
    367 
    368   void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
    369 
    370   // Relocation-related interfaces.
    371   Expected<uint32_t>
    372   getLogicalNumberOfRelocationEntries(const XCOFFSectionHeader32 &Sec) const;
    373 
    374   Expected<ArrayRef<XCOFFRelocation32>>
    375   relocations(const XCOFFSectionHeader32 &) const;
    376 
    377   static bool classof(const Binary *B) { return B->isXCOFF(); }
    378 }; // XCOFFObjectFile
    379 
    380 class XCOFFSymbolRef {
    381   const DataRefImpl SymEntDataRef;
    382   const XCOFFObjectFile *const OwningObjectPtr;
    383 
    384 public:
    385   XCOFFSymbolRef(DataRefImpl SymEntDataRef,
    386                  const XCOFFObjectFile *OwningObjectPtr)
    387       : SymEntDataRef(SymEntDataRef), OwningObjectPtr(OwningObjectPtr){};
    388 
    389   XCOFF::StorageClass getStorageClass() const;
    390   uint8_t getNumberOfAuxEntries() const;
    391   const XCOFFCsectAuxEnt32 *getXCOFFCsectAuxEnt32() const;
    392   uint16_t getType() const;
    393   int16_t getSectionNumber() const;
    394 
    395   bool hasCsectAuxEnt() const;
    396   bool isFunction() const;
    397 };
    398 
    399 class TBVectorExt {
    400   friend class XCOFFTracebackTable;
    401 
    402   uint16_t Data;
    403   uint32_t VecParmsInfo;
    404 
    405   TBVectorExt(StringRef TBvectorStrRef);
    406 
    407 public:
    408   uint8_t getNumberOfVRSaved() const;
    409   bool isVRSavedOnStack() const;
    410   bool hasVarArgs() const;
    411   uint8_t getNumberOfVectorParms() const;
    412   bool hasVMXInstruction() const;
    413   SmallString<32> getVectorParmsInfoString() const;
    414 };
    415 
    416 /// This class provides methods to extract traceback table data from a buffer.
    417 /// The various accessors may reference the buffer provided via the constructor.
    418 
    419 class XCOFFTracebackTable {
    420   const uint8_t *const TBPtr;
    421   Optional<SmallString<32>> ParmsType;
    422   Optional<uint32_t> TraceBackTableOffset;
    423   Optional<uint32_t> HandlerMask;
    424   Optional<uint32_t> NumOfCtlAnchors;
    425   Optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp;
    426   Optional<StringRef> FunctionName;
    427   Optional<uint8_t> AllocaRegister;
    428   Optional<TBVectorExt> VecExt;
    429   Optional<uint8_t> ExtensionTable;
    430 
    431   XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
    432 public:
    433   /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
    434   /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
    435   /// Error is returned.
    436   ///
    437   /// \param[in] Ptr
    438   ///   A pointer that points just past the initial 4 bytes of zeros at the
    439   ///   beginning of an XCOFF Traceback Table.
    440   ///
    441   /// \param[in, out] Size
    442   ///    A pointer that points to the length of the XCOFF Traceback Table.
    443   ///    If the XCOFF Traceback Table is not parsed successfully or there are
    444   ///    extra bytes that are not recognized, \a Size will be updated to be the
    445   ///    size up to the end of the last successfully parsed field of the table.
    446   static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr,
    447                                               uint64_t &Size);
    448   uint8_t getVersion() const;
    449   uint8_t getLanguageID() const;
    450 
    451   bool isGlobalLinkage() const;
    452   bool isOutOfLineEpilogOrPrologue() const;
    453   bool hasTraceBackTableOffset() const;
    454   bool isInternalProcedure() const;
    455   bool hasControlledStorage() const;
    456   bool isTOCless() const;
    457   bool isFloatingPointPresent() const;
    458   bool isFloatingPointOperationLogOrAbortEnabled() const;
    459 
    460   bool isInterruptHandler() const;
    461   bool isFuncNamePresent() const;
    462   bool isAllocaUsed() const;
    463   uint8_t getOnConditionDirective() const;
    464   bool isCRSaved() const;
    465   bool isLRSaved() const;
    466 
    467   bool isBackChainStored() const;
    468   bool isFixup() const;
    469   uint8_t getNumOfFPRsSaved() const;
    470 
    471   bool hasVectorInfo() const;
    472   bool hasExtensionTable() const;
    473   uint8_t getNumOfGPRsSaved() const;
    474 
    475   uint8_t getNumberOfFixedParms() const;
    476 
    477   uint8_t getNumberOfFPParms() const;
    478   bool hasParmsOnStack() const;
    479 
    480   const Optional<SmallString<32>> &getParmsType() const { return ParmsType; }
    481   const Optional<uint32_t> &getTraceBackTableOffset() const {
    482     return TraceBackTableOffset;
    483   }
    484   const Optional<uint32_t> &getHandlerMask() const { return HandlerMask; }
    485   const Optional<uint32_t> &getNumOfCtlAnchors() { return NumOfCtlAnchors; }
    486   const Optional<SmallVector<uint32_t, 8>> &getControlledStorageInfoDisp() {
    487     return ControlledStorageInfoDisp;
    488   }
    489   const Optional<StringRef> &getFunctionName() const { return FunctionName; }
    490   const Optional<uint8_t> &getAllocaRegister() const { return AllocaRegister; }
    491   const Optional<TBVectorExt> &getVectorExt() const { return VecExt; }
    492   const Optional<uint8_t> &getExtensionTable() const { return ExtensionTable; }
    493 };
    494 
    495 bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);
    496 } // namespace object
    497 } // namespace llvm
    498 
    499 #endif // LLVM_OBJECT_XCOFFOBJECTFILE_H
    500