ARMWinEH.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- llvm/Support/ARMWinEH.h - Windows on ARM EH Constants ---*- 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. #ifndef LLVM_SUPPORT_ARMWINEH_H
  14. #define LLVM_SUPPORT_ARMWINEH_H
  15. #include "llvm/ADT/ArrayRef.h"
  16. #include "llvm/Support/Endian.h"
  17. namespace llvm {
  18. namespace ARM {
  19. namespace WinEH {
  20. enum class RuntimeFunctionFlag {
  21. RFF_Unpacked, /// unpacked entry
  22. RFF_Packed, /// packed entry
  23. RFF_PackedFragment, /// packed entry representing a fragment
  24. RFF_Reserved, /// reserved
  25. };
  26. enum class ReturnType {
  27. RT_POP, /// return via pop {pc} (L flag must be set)
  28. RT_B, /// 16-bit branch
  29. RT_BW, /// 32-bit branch
  30. RT_NoEpilogue, /// no epilogue (fragment)
  31. };
  32. /// RuntimeFunction - An entry in the table of procedure data (.pdata)
  33. ///
  34. /// This is ARM specific, but the Function Start RVA, Flag and
  35. /// ExceptionInformationRVA fields work identically for ARM64.
  36. ///
  37. /// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  38. /// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  39. /// +---------------------------------------------------------------+
  40. /// | Function Start RVA |
  41. /// +-------------------+-+-+-+-----+-+---+---------------------+---+
  42. /// | Stack Adjust |C|L|R| Reg |H|Ret| Function Length |Flg|
  43. /// +-------------------+-+-+-+-----+-+---+---------------------+---+
  44. ///
  45. /// Flag : 2-bit field with the following meanings:
  46. /// - 00 = packed unwind data not used; reamining bits point to .xdata record
  47. /// - 01 = packed unwind data
  48. /// - 10 = packed unwind data, function assumed to have no prologue; useful
  49. /// for function fragments that are discontiguous with the start of the
  50. /// function
  51. /// - 11 = reserved
  52. /// Function Length : 11-bit field providing the length of the entire function
  53. /// in bytes, divided by 2; if the function is greater than
  54. /// 4KB, a full .xdata record must be used instead
  55. /// Ret : 2-bit field indicating how the function returns
  56. /// - 00 = return via pop {pc} (the L bit must be set)
  57. /// - 01 = return via 16-bit branch
  58. /// - 10 = return via 32-bit branch
  59. /// - 11 = no epilogue; useful for function fragments that may only contain a
  60. /// prologue but the epilogue is elsewhere
  61. /// H : 1-bit flag indicating whether the function "homes" the integer parameter
  62. /// registers (r0-r3), allocating 16-bytes on the stack
  63. /// Reg : 3-bit field indicating the index of the last saved non-volatile
  64. /// register. If the R bit is set to 0, then only integer registers are
  65. /// saved (r4-rN, where N is 4 + Reg). If the R bit is set to 1, then
  66. /// only floating-point registers are being saved (d8-dN, where N is
  67. /// 8 + Reg). The special case of the R bit being set to 1 and Reg equal
  68. /// to 7 indicates that no registers are saved.
  69. /// R : 1-bit flag indicating whether the non-volatile registers are integer or
  70. /// floating-point. 0 indicates integer, 1 indicates floating-point. The
  71. /// special case of the R-flag being set and Reg being set to 7 indicates
  72. /// that no non-volatile registers are saved.
  73. /// L : 1-bit flag indicating whether the function saves/restores the link
  74. /// register (LR)
  75. /// C : 1-bit flag indicating whether the function includes extra instructions
  76. /// to setup a frame chain for fast walking. If this flag is set, r11 is
  77. /// implicitly added to the list of saved non-volatile integer registers.
  78. /// Stack Adjust : 10-bit field indicating the number of bytes of stack that are
  79. /// allocated for this function. Only values between 0x000 and
  80. /// 0x3f3 can be directly encoded. If the value is 0x3f4 or
  81. /// greater, then the low 4 bits have special meaning as follows:
  82. /// - Bit 0-1
  83. /// indicate the number of words' of adjustment (1-4), minus 1
  84. /// - Bit 2
  85. /// indicates if the prologue combined adjustment into push
  86. /// - Bit 3
  87. /// indicates if the epilogue combined adjustment into pop
  88. ///
  89. /// RESTRICTIONS:
  90. /// - IF C is SET:
  91. /// + L flag must be set since frame chaining requires r11 and lr
  92. /// + r11 must NOT be included in the set of registers described by Reg
  93. /// - IF Ret is 0:
  94. /// + L flag must be set
  95. // NOTE: RuntimeFunction is meant to be a simple class that provides raw access
  96. // to all fields in the structure. The accessor methods reflect the names of
  97. // the bitfields that they correspond to. Although some obvious simplifications
  98. // are possible via merging of methods, it would prevent the use of this class
  99. // to fully inspect the contents of the data structure which is particularly
  100. // useful for scenarios such as llvm-readobj to aid in testing.
  101. class RuntimeFunction {
  102. public:
  103. const support::ulittle32_t BeginAddress;
  104. const support::ulittle32_t UnwindData;
  105. RuntimeFunction(const support::ulittle32_t *Data)
  106. : BeginAddress(Data[0]), UnwindData(Data[1]) {}
  107. RuntimeFunction(const support::ulittle32_t BeginAddress,
  108. const support::ulittle32_t UnwindData)
  109. : BeginAddress(BeginAddress), UnwindData(UnwindData) {}
  110. RuntimeFunctionFlag Flag() const {
  111. return RuntimeFunctionFlag(UnwindData & 0x3);
  112. }
  113. uint32_t ExceptionInformationRVA() const {
  114. assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
  115. "unpacked form required for this operation");
  116. return (UnwindData & ~0x3);
  117. }
  118. uint32_t PackedUnwindData() const {
  119. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  120. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  121. "packed form required for this operation");
  122. return (UnwindData & ~0x3);
  123. }
  124. uint32_t FunctionLength() const {
  125. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  126. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  127. "packed form required for this operation");
  128. return (((UnwindData & 0x00001ffc) >> 2) << 1);
  129. }
  130. ReturnType Ret() const {
  131. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  132. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  133. "packed form required for this operation");
  134. assert(((UnwindData & 0x00006000) || L()) && "L must be set to 1");
  135. return ReturnType((UnwindData & 0x00006000) >> 13);
  136. }
  137. bool H() const {
  138. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  139. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  140. "packed form required for this operation");
  141. return ((UnwindData & 0x00008000) >> 15);
  142. }
  143. uint8_t Reg() const {
  144. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  145. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  146. "packed form required for this operation");
  147. return ((UnwindData & 0x00070000) >> 16);
  148. }
  149. bool R() const {
  150. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  151. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  152. "packed form required for this operation");
  153. return ((UnwindData & 0x00080000) >> 19);
  154. }
  155. bool L() const {
  156. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  157. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  158. "packed form required for this operation");
  159. return ((UnwindData & 0x00100000) >> 20);
  160. }
  161. bool C() const {
  162. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  163. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  164. "packed form required for this operation");
  165. assert(((~UnwindData & 0x00200000) || L()) &&
  166. "L flag must be set, chaining requires r11 and LR");
  167. assert(((~UnwindData & 0x00200000) || (Reg() < 7) || R()) &&
  168. "r11 must not be included in Reg; C implies r11");
  169. return ((UnwindData & 0x00200000) >> 21);
  170. }
  171. uint16_t StackAdjust() const {
  172. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  173. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  174. "packed form required for this operation");
  175. return ((UnwindData & 0xffc00000) >> 22);
  176. }
  177. };
  178. /// PrologueFolding - pseudo-flag derived from Stack Adjust indicating that the
  179. /// prologue has stack adjustment combined into the push
  180. inline bool PrologueFolding(const RuntimeFunction &RF) {
  181. return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x4);
  182. }
  183. /// Epilogue - pseudo-flag derived from Stack Adjust indicating that the
  184. /// epilogue has stack adjustment combined into the pop
  185. inline bool EpilogueFolding(const RuntimeFunction &RF) {
  186. return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x8);
  187. }
  188. /// StackAdjustment - calculated stack adjustment in words. The stack
  189. /// adjustment should be determined via this function to account for the special
  190. /// handling the special encoding when the value is >= 0x3f4.
  191. inline uint16_t StackAdjustment(const RuntimeFunction &RF) {
  192. uint16_t Adjustment = RF.StackAdjust();
  193. if (Adjustment >= 0x3f4)
  194. return (Adjustment & 0x3) ? ((Adjustment & 0x3) << 2) - 1 : 0;
  195. return Adjustment;
  196. }
  197. /// SavedRegisterMask - Utility function to calculate the set of saved general
  198. /// purpose (r0-r15) and VFP (d0-d31) registers.
  199. std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF);
  200. /// RuntimeFunctionARM64 - An entry in the table of procedure data (.pdata)
  201. ///
  202. /// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  203. /// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  204. /// +---------------------------------------------------------------+
  205. /// | Function Start RVA |
  206. /// +-----------------+---+-+-------+-----+---------------------+---+
  207. /// | Frame Size |CR |H| RegI |RegF | Function Length |Flg|
  208. /// +-----------------+---+-+-------+-----+---------------------+---+
  209. ///
  210. /// See https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
  211. /// for the full reference for this struct.
  212. class RuntimeFunctionARM64 {
  213. public:
  214. const support::ulittle32_t BeginAddress;
  215. const support::ulittle32_t UnwindData;
  216. RuntimeFunctionARM64(const support::ulittle32_t *Data)
  217. : BeginAddress(Data[0]), UnwindData(Data[1]) {}
  218. RuntimeFunctionARM64(const support::ulittle32_t BeginAddress,
  219. const support::ulittle32_t UnwindData)
  220. : BeginAddress(BeginAddress), UnwindData(UnwindData) {}
  221. RuntimeFunctionFlag Flag() const {
  222. return RuntimeFunctionFlag(UnwindData & 0x3);
  223. }
  224. uint32_t ExceptionInformationRVA() const {
  225. assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
  226. "unpacked form required for this operation");
  227. return (UnwindData & ~0x3);
  228. }
  229. uint32_t PackedUnwindData() const {
  230. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  231. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  232. "packed form required for this operation");
  233. return (UnwindData & ~0x3);
  234. }
  235. uint32_t FunctionLength() const {
  236. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  237. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  238. "packed form required for this operation");
  239. return (((UnwindData & 0x00001ffc) >> 2) << 2);
  240. }
  241. uint8_t RegF() const {
  242. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  243. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  244. "packed form required for this operation");
  245. return ((UnwindData & 0x0000e000) >> 13);
  246. }
  247. uint8_t RegI() const {
  248. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  249. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  250. "packed form required for this operation");
  251. return ((UnwindData & 0x000f0000) >> 16);
  252. }
  253. bool H() const {
  254. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  255. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  256. "packed form required for this operation");
  257. return ((UnwindData & 0x00100000) >> 20);
  258. }
  259. uint8_t CR() const {
  260. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  261. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  262. "packed form required for this operation");
  263. return ((UnwindData & 0x600000) >> 21);
  264. }
  265. uint16_t FrameSize() const {
  266. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  267. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  268. "packed form required for this operation");
  269. return ((UnwindData & 0xff800000) >> 23);
  270. }
  271. };
  272. /// ExceptionDataRecord - An entry in the table of exception data (.xdata)
  273. ///
  274. /// The format on ARM is:
  275. ///
  276. /// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  277. /// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  278. /// +-------+---------+-+-+-+---+-----------------------------------+
  279. /// | C Wrd | Epi Cnt |F|E|X|Ver| Function Length |
  280. /// +-------+--------+'-'-'-'---'---+-------------------------------+
  281. /// | Reserved |Ex. Code Words| (Extended Epilogue Count) |
  282. /// +-------+--------+--------------+-------------------------------+
  283. ///
  284. /// The format on ARM64 is:
  285. ///
  286. /// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  287. /// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  288. /// +---------+---------+-+-+---+-----------------------------------+
  289. /// | C Wrd | Epi Cnt |E|X|Ver| Function Length |
  290. /// +---------+------+--'-'-'---'---+-------------------------------+
  291. /// | Reserved |Ex. Code Words| (Extended Epilogue Count) |
  292. /// +-------+--------+--------------+-------------------------------+
  293. ///
  294. /// Function Length : 18-bit field indicating the total length of the function
  295. /// in bytes divided by 2. If a function is larger than
  296. /// 512KB, then multiple pdata and xdata records must be used.
  297. /// Vers : 2-bit field describing the version of the remaining structure. Only
  298. /// version 0 is currently defined (values 1-3 are not permitted).
  299. /// X : 1-bit field indicating the presence of exception data
  300. /// E : 1-bit field indicating that the single epilogue is packed into the
  301. /// header
  302. /// F : 1-bit field indicating that the record describes a function fragment
  303. /// (implies that no prologue is present, and prologue processing should be
  304. /// skipped) (ARM only)
  305. /// Epilogue Count : 5-bit field that differs in meaning based on the E field.
  306. ///
  307. /// If E is set, then this field specifies the index of the
  308. /// first unwind code describing the (only) epilogue.
  309. ///
  310. /// Otherwise, this field indicates the number of exception
  311. /// scopes. If more than 31 scopes exist, then this field and
  312. /// the Code Words field must both be set to 0 to indicate that
  313. /// an extension word is required.
  314. /// Code Words : 4-bit (5-bit on ARM64) field that specifies the number of
  315. /// 32-bit words needed to contain all the unwind codes. If more
  316. /// than 15 words (31 words on ARM64) are required, then this field
  317. /// and the Epilogue Count field must both be set to 0 to indicate
  318. /// that an extension word is required.
  319. /// Extended Epilogue Count, Extended Code Words :
  320. /// Valid only if Epilog Count and Code Words are both
  321. /// set to 0. Provides an 8-bit extended code word
  322. /// count and 16-bits for epilogue count
  323. ///
  324. /// The epilogue scope format on ARM is:
  325. ///
  326. /// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  327. /// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  328. /// +----------------+------+---+---+-------------------------------+
  329. /// | Ep Start Idx | Cond |Res| Epilogue Start Offset |
  330. /// +----------------+------+---+-----------------------------------+
  331. ///
  332. /// The epilogue scope format on ARM64 is:
  333. ///
  334. /// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  335. /// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  336. /// +-------------------+-------+---+-------------------------------+
  337. /// | Ep Start Idx | Res | Epilogue Start Offset |
  338. /// +-------------------+-------+-----------------------------------+
  339. ///
  340. /// If the E bit is unset in the header, the header is followed by a series of
  341. /// epilogue scopes, which are sorted by their offset.
  342. ///
  343. /// Epilogue Start Offset: 18-bit field encoding the offset of epilogue relative
  344. /// to the start of the function in bytes divided by two
  345. /// Res : 2-bit field reserved for future expansion (must be set to 0)
  346. /// Condition : (ARM only) 4-bit field providing the condition under which the
  347. /// epilogue is executed. Unconditional epilogues should set this
  348. /// field to 0xe. Epilogues must be entirely conditional or
  349. /// unconditional, and in Thumb-2 mode. The epilogue begins with
  350. /// the first instruction after the IT opcode.
  351. /// Epilogue Start Index : 8-bit field indicating the byte index of the first
  352. /// unwind code describing the epilogue
  353. ///
  354. /// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  355. /// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  356. /// +---------------+---------------+---------------+---------------+
  357. /// | Unwind Code 3 | Unwind Code 2 | Unwind Code 1 | Unwind Code 0 |
  358. /// +---------------+---------------+---------------+---------------+
  359. ///
  360. /// Following the epilogue scopes, the byte code describing the unwinding
  361. /// follows. This is padded to align up to word alignment. Bytes are stored in
  362. /// little endian.
  363. ///
  364. /// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  365. /// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  366. /// +---------------------------------------------------------------+
  367. /// | Exception Handler RVA (requires X = 1) |
  368. /// +---------------------------------------------------------------+
  369. /// | (possibly followed by data required for exception handler) |
  370. /// +---------------------------------------------------------------+
  371. ///
  372. /// If the X bit is set in the header, the unwind byte code is followed by the
  373. /// exception handler information. This constants of one Exception Handler RVA
  374. /// which is the address to the exception handler, followed immediately by the
  375. /// variable length data associated with the exception handler.
  376. ///
  377. struct EpilogueScope {
  378. const support::ulittle32_t ES;
  379. EpilogueScope(const support::ulittle32_t Data) : ES(Data) {}
  380. // Same for both ARM and AArch64.
  381. uint32_t EpilogueStartOffset() const {
  382. return (ES & 0x0003ffff);
  383. }
  384. // Different implementations for ARM and AArch64.
  385. uint8_t ResARM() const {
  386. return ((ES & 0x000c0000) >> 18);
  387. }
  388. uint8_t ResAArch64() const {
  389. return ((ES & 0x000f0000) >> 18);
  390. }
  391. // Condition is only applicable to ARM.
  392. uint8_t Condition() const {
  393. return ((ES & 0x00f00000) >> 20);
  394. }
  395. // Different implementations for ARM and AArch64.
  396. uint8_t EpilogueStartIndexARM() const {
  397. return ((ES & 0xff000000) >> 24);
  398. }
  399. uint16_t EpilogueStartIndexAArch64() const {
  400. return ((ES & 0xffc00000) >> 22);
  401. }
  402. };
  403. struct ExceptionDataRecord;
  404. inline size_t HeaderWords(const ExceptionDataRecord &XR);
  405. struct ExceptionDataRecord {
  406. const support::ulittle32_t *Data;
  407. bool isAArch64;
  408. ExceptionDataRecord(const support::ulittle32_t *Data, bool isAArch64) :
  409. Data(Data), isAArch64(isAArch64) {}
  410. uint32_t FunctionLength() const {
  411. return (Data[0] & 0x0003ffff);
  412. }
  413. uint32_t FunctionLengthInBytesARM() const {
  414. return FunctionLength() << 1;
  415. }
  416. uint32_t FunctionLengthInBytesAArch64() const {
  417. return FunctionLength() << 2;
  418. }
  419. uint8_t Vers() const {
  420. return (Data[0] & 0x000C0000) >> 18;
  421. }
  422. bool X() const {
  423. return ((Data[0] & 0x00100000) >> 20);
  424. }
  425. bool E() const {
  426. return ((Data[0] & 0x00200000) >> 21);
  427. }
  428. bool F() const {
  429. assert(!isAArch64 && "Fragments are only supported on ARMv7 WinEH");
  430. return ((Data[0] & 0x00400000) >> 22);
  431. }
  432. uint16_t EpilogueCount() const {
  433. if (HeaderWords(*this) == 1) {
  434. if (isAArch64)
  435. return (Data[0] & 0x07C00000) >> 22;
  436. return (Data[0] & 0x0f800000) >> 23;
  437. }
  438. return Data[1] & 0x0000ffff;
  439. }
  440. uint8_t CodeWords() const {
  441. if (HeaderWords(*this) == 1) {
  442. if (isAArch64)
  443. return (Data[0] & 0xf8000000) >> 27;
  444. return (Data[0] & 0xf0000000) >> 28;
  445. }
  446. return (Data[1] & 0x00ff0000) >> 16;
  447. }
  448. ArrayRef<support::ulittle32_t> EpilogueScopes() const {
  449. assert(E() == 0 && "epilogue scopes are only present when the E bit is 0");
  450. size_t Offset = HeaderWords(*this);
  451. return makeArrayRef(&Data[Offset], EpilogueCount());
  452. }
  453. ArrayRef<uint8_t> UnwindByteCode() const {
  454. const size_t Offset = HeaderWords(*this)
  455. + (E() ? 0 : EpilogueCount());
  456. const uint8_t *ByteCode =
  457. reinterpret_cast<const uint8_t *>(&Data[Offset]);
  458. return makeArrayRef(ByteCode, CodeWords() * sizeof(uint32_t));
  459. }
  460. uint32_t ExceptionHandlerRVA() const {
  461. assert(X() && "Exception Handler RVA is only valid if the X bit is set");
  462. return Data[HeaderWords(*this) + (E() ? 0 : EpilogueCount()) + CodeWords()];
  463. }
  464. uint32_t ExceptionHandlerParameter() const {
  465. assert(X() && "Exception Handler RVA is only valid if the X bit is set");
  466. return Data[HeaderWords(*this) + (E() ? 0 : EpilogueCount()) + CodeWords() +
  467. 1];
  468. }
  469. };
  470. inline size_t HeaderWords(const ExceptionDataRecord &XR) {
  471. if (XR.isAArch64)
  472. return (XR.Data[0] & 0xffc00000) ? 1 : 2;
  473. return (XR.Data[0] & 0xff800000) ? 1 : 2;
  474. }
  475. }
  476. }
  477. }
  478. #endif
  479. #ifdef __GNUC__
  480. #pragma GCC diagnostic pop
  481. #endif