XCOFFObjectFile.h 31 KB

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