XCOFFObjectFile.h 17 KB

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