XCOFFObjectFile.h 17 KB

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