ARMWinEH.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  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) + 1;
  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. bool Prologue = true);
  201. /// RuntimeFunctionARM64 - An entry in the table of procedure data (.pdata)
  202. ///
  203. /// 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
  204. /// 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
  205. /// +---------------------------------------------------------------+
  206. /// | Function Start RVA |
  207. /// +-----------------+---+-+-------+-----+---------------------+---+
  208. /// | Frame Size |CR |H| RegI |RegF | Function Length |Flg|
  209. /// +-----------------+---+-+-------+-----+---------------------+---+
  210. ///
  211. /// See https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
  212. /// for the full reference for this struct.
  213. class RuntimeFunctionARM64 {
  214. public:
  215. const support::ulittle32_t BeginAddress;
  216. const support::ulittle32_t UnwindData;
  217. RuntimeFunctionARM64(const support::ulittle32_t *Data)
  218. : BeginAddress(Data[0]), UnwindData(Data[1]) {}
  219. RuntimeFunctionARM64(const support::ulittle32_t BeginAddress,
  220. const support::ulittle32_t UnwindData)
  221. : BeginAddress(BeginAddress), UnwindData(UnwindData) {}
  222. RuntimeFunctionFlag Flag() const {
  223. return RuntimeFunctionFlag(UnwindData & 0x3);
  224. }
  225. uint32_t ExceptionInformationRVA() const {
  226. assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
  227. "unpacked form required for this operation");
  228. return (UnwindData & ~0x3);
  229. }
  230. uint32_t PackedUnwindData() const {
  231. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  232. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  233. "packed form required for this operation");
  234. return (UnwindData & ~0x3);
  235. }
  236. uint32_t FunctionLength() const {
  237. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  238. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  239. "packed form required for this operation");
  240. return (((UnwindData & 0x00001ffc) >> 2) << 2);
  241. }
  242. uint8_t RegF() const {
  243. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  244. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  245. "packed form required for this operation");
  246. return ((UnwindData & 0x0000e000) >> 13);
  247. }
  248. uint8_t RegI() const {
  249. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  250. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  251. "packed form required for this operation");
  252. return ((UnwindData & 0x000f0000) >> 16);
  253. }
  254. bool H() const {
  255. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  256. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  257. "packed form required for this operation");
  258. return ((UnwindData & 0x00100000) >> 20);
  259. }
  260. uint8_t CR() const {
  261. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  262. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  263. "packed form required for this operation");
  264. return ((UnwindData & 0x600000) >> 21);
  265. }
  266. uint16_t FrameSize() const {
  267. assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
  268. Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
  269. "packed form required for this operation");
  270. return ((UnwindData & 0xff800000) >> 23);
  271. }
  272. };
  273. /// ExceptionDataRecord - An entry in the table of exception data (.xdata)
  274. ///
  275. /// The format on ARM is:
  276. ///
  277. /// 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
  278. /// 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
  279. /// +-------+---------+-+-+-+---+-----------------------------------+
  280. /// | C Wrd | Epi Cnt |F|E|X|Ver| Function Length |
  281. /// +-------+--------+'-'-'-'---'---+-------------------------------+
  282. /// | Reserved |Ex. Code Words| (Extended Epilogue Count) |
  283. /// +-------+--------+--------------+-------------------------------+
  284. ///
  285. /// The format on ARM64 is:
  286. ///
  287. /// 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
  288. /// 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
  289. /// +---------+---------+-+-+---+-----------------------------------+
  290. /// | C Wrd | Epi Cnt |E|X|Ver| Function Length |
  291. /// +---------+------+--'-'-'---'---+-------------------------------+
  292. /// | Reserved |Ex. Code Words| (Extended Epilogue Count) |
  293. /// +-------+--------+--------------+-------------------------------+
  294. ///
  295. /// Function Length : 18-bit field indicating the total length of the function
  296. /// in bytes divided by 2. If a function is larger than
  297. /// 512KB, then multiple pdata and xdata records must be used.
  298. /// Vers : 2-bit field describing the version of the remaining structure. Only
  299. /// version 0 is currently defined (values 1-3 are not permitted).
  300. /// X : 1-bit field indicating the presence of exception data
  301. /// E : 1-bit field indicating that the single epilogue is packed into the
  302. /// header
  303. /// F : 1-bit field indicating that the record describes a function fragment
  304. /// (implies that no prologue is present, and prologue processing should be
  305. /// skipped) (ARM only)
  306. /// Epilogue Count : 5-bit field that differs in meaning based on the E field.
  307. ///
  308. /// If E is set, then this field specifies the index of the
  309. /// first unwind code describing the (only) epilogue.
  310. ///
  311. /// Otherwise, this field indicates the number of exception
  312. /// scopes. If more than 31 scopes exist, then this field and
  313. /// the Code Words field must both be set to 0 to indicate that
  314. /// an extension word is required.
  315. /// Code Words : 4-bit (5-bit on ARM64) field that specifies the number of
  316. /// 32-bit words needed to contain all the unwind codes. If more
  317. /// than 15 words (31 words on ARM64) are required, then this field
  318. /// and the Epilogue Count field must both be set to 0 to indicate
  319. /// that an extension word is required.
  320. /// Extended Epilogue Count, Extended Code Words :
  321. /// Valid only if Epilog Count and Code Words are both
  322. /// set to 0. Provides an 8-bit extended code word
  323. /// count and 16-bits for epilogue count
  324. ///
  325. /// The epilogue scope format on ARM is:
  326. ///
  327. /// 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
  328. /// 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
  329. /// +----------------+------+---+---+-------------------------------+
  330. /// | Ep Start Idx | Cond |Res| Epilogue Start Offset |
  331. /// +----------------+------+---+-----------------------------------+
  332. ///
  333. /// The epilogue scope format on ARM64 is:
  334. ///
  335. /// 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
  336. /// 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
  337. /// +-------------------+-------+---+-------------------------------+
  338. /// | Ep Start Idx | Res | Epilogue Start Offset |
  339. /// +-------------------+-------+-----------------------------------+
  340. ///
  341. /// If the E bit is unset in the header, the header is followed by a series of
  342. /// epilogue scopes, which are sorted by their offset.
  343. ///
  344. /// Epilogue Start Offset: 18-bit field encoding the offset of epilogue relative
  345. /// to the start of the function in bytes divided by two
  346. /// Res : 2-bit field reserved for future expansion (must be set to 0)
  347. /// Condition : (ARM only) 4-bit field providing the condition under which the
  348. /// epilogue is executed. Unconditional epilogues should set this
  349. /// field to 0xe. Epilogues must be entirely conditional or
  350. /// unconditional, and in Thumb-2 mode. The epilogue begins with
  351. /// the first instruction after the IT opcode.
  352. /// Epilogue Start Index : 8-bit field indicating the byte index of the first
  353. /// unwind code describing the epilogue
  354. ///
  355. /// 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
  356. /// 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
  357. /// +---------------+---------------+---------------+---------------+
  358. /// | Unwind Code 3 | Unwind Code 2 | Unwind Code 1 | Unwind Code 0 |
  359. /// +---------------+---------------+---------------+---------------+
  360. ///
  361. /// Following the epilogue scopes, the byte code describing the unwinding
  362. /// follows. This is padded to align up to word alignment. Bytes are stored in
  363. /// little endian.
  364. ///
  365. /// 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
  366. /// 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
  367. /// +---------------------------------------------------------------+
  368. /// | Exception Handler RVA (requires X = 1) |
  369. /// +---------------------------------------------------------------+
  370. /// | (possibly followed by data required for exception handler) |
  371. /// +---------------------------------------------------------------+
  372. ///
  373. /// If the X bit is set in the header, the unwind byte code is followed by the
  374. /// exception handler information. This constants of one Exception Handler RVA
  375. /// which is the address to the exception handler, followed immediately by the
  376. /// variable length data associated with the exception handler.
  377. ///
  378. struct EpilogueScope {
  379. const support::ulittle32_t ES;
  380. EpilogueScope(const support::ulittle32_t Data) : ES(Data) {}
  381. // Same for both ARM and AArch64.
  382. uint32_t EpilogueStartOffset() const {
  383. return (ES & 0x0003ffff);
  384. }
  385. // Different implementations for ARM and AArch64.
  386. uint8_t ResARM() const {
  387. return ((ES & 0x000c0000) >> 18);
  388. }
  389. uint8_t ResAArch64() const {
  390. return ((ES & 0x000f0000) >> 18);
  391. }
  392. // Condition is only applicable to ARM.
  393. uint8_t Condition() const {
  394. return ((ES & 0x00f00000) >> 20);
  395. }
  396. // Different implementations for ARM and AArch64.
  397. uint8_t EpilogueStartIndexARM() const {
  398. return ((ES & 0xff000000) >> 24);
  399. }
  400. uint16_t EpilogueStartIndexAArch64() const {
  401. return ((ES & 0xffc00000) >> 22);
  402. }
  403. };
  404. struct ExceptionDataRecord;
  405. inline size_t HeaderWords(const ExceptionDataRecord &XR);
  406. struct ExceptionDataRecord {
  407. const support::ulittle32_t *Data;
  408. bool isAArch64;
  409. ExceptionDataRecord(const support::ulittle32_t *Data, bool isAArch64) :
  410. Data(Data), isAArch64(isAArch64) {}
  411. uint32_t FunctionLength() const {
  412. return (Data[0] & 0x0003ffff);
  413. }
  414. uint32_t FunctionLengthInBytesARM() const {
  415. return FunctionLength() << 1;
  416. }
  417. uint32_t FunctionLengthInBytesAArch64() const {
  418. return FunctionLength() << 2;
  419. }
  420. uint8_t Vers() const {
  421. return (Data[0] & 0x000C0000) >> 18;
  422. }
  423. bool X() const {
  424. return ((Data[0] & 0x00100000) >> 20);
  425. }
  426. bool E() const {
  427. return ((Data[0] & 0x00200000) >> 21);
  428. }
  429. bool F() const {
  430. assert(!isAArch64 && "Fragments are only supported on ARMv7 WinEH");
  431. return ((Data[0] & 0x00400000) >> 22);
  432. }
  433. uint16_t EpilogueCount() const {
  434. if (HeaderWords(*this) == 1) {
  435. if (isAArch64)
  436. return (Data[0] & 0x07C00000) >> 22;
  437. return (Data[0] & 0x0f800000) >> 23;
  438. }
  439. return Data[1] & 0x0000ffff;
  440. }
  441. uint8_t CodeWords() const {
  442. if (HeaderWords(*this) == 1) {
  443. if (isAArch64)
  444. return (Data[0] & 0xf8000000) >> 27;
  445. return (Data[0] & 0xf0000000) >> 28;
  446. }
  447. return (Data[1] & 0x00ff0000) >> 16;
  448. }
  449. ArrayRef<support::ulittle32_t> EpilogueScopes() const {
  450. assert(E() == 0 && "epilogue scopes are only present when the E bit is 0");
  451. size_t Offset = HeaderWords(*this);
  452. return ArrayRef(&Data[Offset], EpilogueCount());
  453. }
  454. ArrayRef<uint8_t> UnwindByteCode() const {
  455. const size_t Offset = HeaderWords(*this)
  456. + (E() ? 0 : EpilogueCount());
  457. const uint8_t *ByteCode =
  458. reinterpret_cast<const uint8_t *>(&Data[Offset]);
  459. return ArrayRef(ByteCode, CodeWords() * sizeof(uint32_t));
  460. }
  461. uint32_t ExceptionHandlerRVA() const {
  462. assert(X() && "Exception Handler RVA is only valid if the X bit is set");
  463. return Data[HeaderWords(*this) + (E() ? 0 : EpilogueCount()) + CodeWords()];
  464. }
  465. uint32_t ExceptionHandlerParameter() const {
  466. assert(X() && "Exception Handler RVA is only valid if the X bit is set");
  467. return Data[HeaderWords(*this) + (E() ? 0 : EpilogueCount()) + CodeWords() +
  468. 1];
  469. }
  470. };
  471. inline size_t HeaderWords(const ExceptionDataRecord &XR) {
  472. if (XR.isAArch64)
  473. return (XR.Data[0] & 0xffc00000) ? 1 : 2;
  474. return (XR.Data[0] & 0xff800000) ? 1 : 2;
  475. }
  476. }
  477. }
  478. }
  479. #endif
  480. #ifdef __GNUC__
  481. #pragma GCC diagnostic pop
  482. #endif