123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===-- llvm/Support/ARMWinEH.h - Windows on ARM EH Constants ---*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_SUPPORT_ARMWINEH_H
- #define LLVM_SUPPORT_ARMWINEH_H
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/Support/Endian.h"
- namespace llvm {
- namespace ARM {
- namespace WinEH {
- enum class RuntimeFunctionFlag {
- RFF_Unpacked, /// unpacked entry
- RFF_Packed, /// packed entry
- RFF_PackedFragment, /// packed entry representing a fragment
- RFF_Reserved, /// reserved
- };
- enum class ReturnType {
- RT_POP, /// return via pop {pc} (L flag must be set)
- RT_B, /// 16-bit branch
- RT_BW, /// 32-bit branch
- RT_NoEpilogue, /// no epilogue (fragment)
- };
- /// RuntimeFunction - An entry in the table of procedure data (.pdata)
- ///
- /// This is ARM specific, but the Function Start RVA, Flag and
- /// ExceptionInformationRVA fields work identically for ARM64.
- ///
- /// 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
- /// 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
- /// +---------------------------------------------------------------+
- /// | Function Start RVA |
- /// +-------------------+-+-+-+-----+-+---+---------------------+---+
- /// | Stack Adjust |C|L|R| Reg |H|Ret| Function Length |Flg|
- /// +-------------------+-+-+-+-----+-+---+---------------------+---+
- ///
- /// Flag : 2-bit field with the following meanings:
- /// - 00 = packed unwind data not used; reamining bits point to .xdata record
- /// - 01 = packed unwind data
- /// - 10 = packed unwind data, function assumed to have no prologue; useful
- /// for function fragments that are discontiguous with the start of the
- /// function
- /// - 11 = reserved
- /// Function Length : 11-bit field providing the length of the entire function
- /// in bytes, divided by 2; if the function is greater than
- /// 4KB, a full .xdata record must be used instead
- /// Ret : 2-bit field indicating how the function returns
- /// - 00 = return via pop {pc} (the L bit must be set)
- /// - 01 = return via 16-bit branch
- /// - 10 = return via 32-bit branch
- /// - 11 = no epilogue; useful for function fragments that may only contain a
- /// prologue but the epilogue is elsewhere
- /// H : 1-bit flag indicating whether the function "homes" the integer parameter
- /// registers (r0-r3), allocating 16-bytes on the stack
- /// Reg : 3-bit field indicating the index of the last saved non-volatile
- /// register. If the R bit is set to 0, then only integer registers are
- /// saved (r4-rN, where N is 4 + Reg). If the R bit is set to 1, then
- /// only floating-point registers are being saved (d8-dN, where N is
- /// 8 + Reg). The special case of the R bit being set to 1 and Reg equal
- /// to 7 indicates that no registers are saved.
- /// R : 1-bit flag indicating whether the non-volatile registers are integer or
- /// floating-point. 0 indicates integer, 1 indicates floating-point. The
- /// special case of the R-flag being set and Reg being set to 7 indicates
- /// that no non-volatile registers are saved.
- /// L : 1-bit flag indicating whether the function saves/restores the link
- /// register (LR)
- /// C : 1-bit flag indicating whether the function includes extra instructions
- /// to setup a frame chain for fast walking. If this flag is set, r11 is
- /// implicitly added to the list of saved non-volatile integer registers.
- /// Stack Adjust : 10-bit field indicating the number of bytes of stack that are
- /// allocated for this function. Only values between 0x000 and
- /// 0x3f3 can be directly encoded. If the value is 0x3f4 or
- /// greater, then the low 4 bits have special meaning as follows:
- /// - Bit 0-1
- /// indicate the number of words' of adjustment (1-4), minus 1
- /// - Bit 2
- /// indicates if the prologue combined adjustment into push
- /// - Bit 3
- /// indicates if the epilogue combined adjustment into pop
- ///
- /// RESTRICTIONS:
- /// - IF C is SET:
- /// + L flag must be set since frame chaining requires r11 and lr
- /// + r11 must NOT be included in the set of registers described by Reg
- /// - IF Ret is 0:
- /// + L flag must be set
- // NOTE: RuntimeFunction is meant to be a simple class that provides raw access
- // to all fields in the structure. The accessor methods reflect the names of
- // the bitfields that they correspond to. Although some obvious simplifications
- // are possible via merging of methods, it would prevent the use of this class
- // to fully inspect the contents of the data structure which is particularly
- // useful for scenarios such as llvm-readobj to aid in testing.
- class RuntimeFunction {
- public:
- const support::ulittle32_t BeginAddress;
- const support::ulittle32_t UnwindData;
- RuntimeFunction(const support::ulittle32_t *Data)
- : BeginAddress(Data[0]), UnwindData(Data[1]) {}
- RuntimeFunction(const support::ulittle32_t BeginAddress,
- const support::ulittle32_t UnwindData)
- : BeginAddress(BeginAddress), UnwindData(UnwindData) {}
- RuntimeFunctionFlag Flag() const {
- return RuntimeFunctionFlag(UnwindData & 0x3);
- }
- uint32_t ExceptionInformationRVA() const {
- assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
- "unpacked form required for this operation");
- return (UnwindData & ~0x3);
- }
- uint32_t PackedUnwindData() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return (UnwindData & ~0x3);
- }
- uint32_t FunctionLength() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return (((UnwindData & 0x00001ffc) >> 2) << 1);
- }
- ReturnType Ret() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- assert(((UnwindData & 0x00006000) || L()) && "L must be set to 1");
- return ReturnType((UnwindData & 0x00006000) >> 13);
- }
- bool H() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return ((UnwindData & 0x00008000) >> 15);
- }
- uint8_t Reg() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return ((UnwindData & 0x00070000) >> 16);
- }
- bool R() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return ((UnwindData & 0x00080000) >> 19);
- }
- bool L() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return ((UnwindData & 0x00100000) >> 20);
- }
- bool C() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- assert(((~UnwindData & 0x00200000) || L()) &&
- "L flag must be set, chaining requires r11 and LR");
- assert(((~UnwindData & 0x00200000) || (Reg() < 7) || R()) &&
- "r11 must not be included in Reg; C implies r11");
- return ((UnwindData & 0x00200000) >> 21);
- }
- uint16_t StackAdjust() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return ((UnwindData & 0xffc00000) >> 22);
- }
- };
- /// PrologueFolding - pseudo-flag derived from Stack Adjust indicating that the
- /// prologue has stack adjustment combined into the push
- inline bool PrologueFolding(const RuntimeFunction &RF) {
- return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x4);
- }
- /// Epilogue - pseudo-flag derived from Stack Adjust indicating that the
- /// epilogue has stack adjustment combined into the pop
- inline bool EpilogueFolding(const RuntimeFunction &RF) {
- return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x8);
- }
- /// StackAdjustment - calculated stack adjustment in words. The stack
- /// adjustment should be determined via this function to account for the special
- /// handling the special encoding when the value is >= 0x3f4.
- inline uint16_t StackAdjustment(const RuntimeFunction &RF) {
- uint16_t Adjustment = RF.StackAdjust();
- if (Adjustment >= 0x3f4)
- return (Adjustment & 0x3) ? ((Adjustment & 0x3) << 2) - 1 : 0;
- return Adjustment;
- }
- /// SavedRegisterMask - Utility function to calculate the set of saved general
- /// purpose (r0-r15) and VFP (d0-d31) registers.
- std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF);
- /// RuntimeFunctionARM64 - An entry in the table of procedure data (.pdata)
- ///
- /// 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
- /// 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
- /// +---------------------------------------------------------------+
- /// | Function Start RVA |
- /// +-----------------+---+-+-------+-----+---------------------+---+
- /// | Frame Size |CR |H| RegI |RegF | Function Length |Flg|
- /// +-----------------+---+-+-------+-----+---------------------+---+
- ///
- /// See https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
- /// for the full reference for this struct.
- class RuntimeFunctionARM64 {
- public:
- const support::ulittle32_t BeginAddress;
- const support::ulittle32_t UnwindData;
- RuntimeFunctionARM64(const support::ulittle32_t *Data)
- : BeginAddress(Data[0]), UnwindData(Data[1]) {}
- RuntimeFunctionARM64(const support::ulittle32_t BeginAddress,
- const support::ulittle32_t UnwindData)
- : BeginAddress(BeginAddress), UnwindData(UnwindData) {}
- RuntimeFunctionFlag Flag() const {
- return RuntimeFunctionFlag(UnwindData & 0x3);
- }
- uint32_t ExceptionInformationRVA() const {
- assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
- "unpacked form required for this operation");
- return (UnwindData & ~0x3);
- }
- uint32_t PackedUnwindData() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return (UnwindData & ~0x3);
- }
- uint32_t FunctionLength() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return (((UnwindData & 0x00001ffc) >> 2) << 2);
- }
- uint8_t RegF() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return ((UnwindData & 0x0000e000) >> 13);
- }
- uint8_t RegI() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return ((UnwindData & 0x000f0000) >> 16);
- }
- bool H() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return ((UnwindData & 0x00100000) >> 20);
- }
- uint8_t CR() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return ((UnwindData & 0x600000) >> 21);
- }
- uint16_t FrameSize() const {
- assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
- Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
- "packed form required for this operation");
- return ((UnwindData & 0xff800000) >> 23);
- }
- };
- /// ExceptionDataRecord - An entry in the table of exception data (.xdata)
- ///
- /// The format on ARM is:
- ///
- /// 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
- /// 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
- /// +-------+---------+-+-+-+---+-----------------------------------+
- /// | C Wrd | Epi Cnt |F|E|X|Ver| Function Length |
- /// +-------+--------+'-'-'-'---'---+-------------------------------+
- /// | Reserved |Ex. Code Words| (Extended Epilogue Count) |
- /// +-------+--------+--------------+-------------------------------+
- ///
- /// The format on ARM64 is:
- ///
- /// 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
- /// 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
- /// +---------+---------+-+-+---+-----------------------------------+
- /// | C Wrd | Epi Cnt |E|X|Ver| Function Length |
- /// +---------+------+--'-'-'---'---+-------------------------------+
- /// | Reserved |Ex. Code Words| (Extended Epilogue Count) |
- /// +-------+--------+--------------+-------------------------------+
- ///
- /// Function Length : 18-bit field indicating the total length of the function
- /// in bytes divided by 2. If a function is larger than
- /// 512KB, then multiple pdata and xdata records must be used.
- /// Vers : 2-bit field describing the version of the remaining structure. Only
- /// version 0 is currently defined (values 1-3 are not permitted).
- /// X : 1-bit field indicating the presence of exception data
- /// E : 1-bit field indicating that the single epilogue is packed into the
- /// header
- /// F : 1-bit field indicating that the record describes a function fragment
- /// (implies that no prologue is present, and prologue processing should be
- /// skipped) (ARM only)
- /// Epilogue Count : 5-bit field that differs in meaning based on the E field.
- ///
- /// If E is set, then this field specifies the index of the
- /// first unwind code describing the (only) epilogue.
- ///
- /// Otherwise, this field indicates the number of exception
- /// scopes. If more than 31 scopes exist, then this field and
- /// the Code Words field must both be set to 0 to indicate that
- /// an extension word is required.
- /// Code Words : 4-bit (5-bit on ARM64) field that specifies the number of
- /// 32-bit words needed to contain all the unwind codes. If more
- /// than 15 words (31 words on ARM64) are required, then this field
- /// and the Epilogue Count field must both be set to 0 to indicate
- /// that an extension word is required.
- /// Extended Epilogue Count, Extended Code Words :
- /// Valid only if Epilog Count and Code Words are both
- /// set to 0. Provides an 8-bit extended code word
- /// count and 16-bits for epilogue count
- ///
- /// The epilogue scope format on ARM is:
- ///
- /// 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
- /// 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
- /// +----------------+------+---+---+-------------------------------+
- /// | Ep Start Idx | Cond |Res| Epilogue Start Offset |
- /// +----------------+------+---+-----------------------------------+
- ///
- /// The epilogue scope format on ARM64 is:
- ///
- /// 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
- /// 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
- /// +-------------------+-------+---+-------------------------------+
- /// | Ep Start Idx | Res | Epilogue Start Offset |
- /// +-------------------+-------+-----------------------------------+
- ///
- /// If the E bit is unset in the header, the header is followed by a series of
- /// epilogue scopes, which are sorted by their offset.
- ///
- /// Epilogue Start Offset: 18-bit field encoding the offset of epilogue relative
- /// to the start of the function in bytes divided by two
- /// Res : 2-bit field reserved for future expansion (must be set to 0)
- /// Condition : (ARM only) 4-bit field providing the condition under which the
- /// epilogue is executed. Unconditional epilogues should set this
- /// field to 0xe. Epilogues must be entirely conditional or
- /// unconditional, and in Thumb-2 mode. The epilogue begins with
- /// the first instruction after the IT opcode.
- /// Epilogue Start Index : 8-bit field indicating the byte index of the first
- /// unwind code describing the epilogue
- ///
- /// 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
- /// 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
- /// +---------------+---------------+---------------+---------------+
- /// | Unwind Code 3 | Unwind Code 2 | Unwind Code 1 | Unwind Code 0 |
- /// +---------------+---------------+---------------+---------------+
- ///
- /// Following the epilogue scopes, the byte code describing the unwinding
- /// follows. This is padded to align up to word alignment. Bytes are stored in
- /// little endian.
- ///
- /// 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
- /// 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
- /// +---------------------------------------------------------------+
- /// | Exception Handler RVA (requires X = 1) |
- /// +---------------------------------------------------------------+
- /// | (possibly followed by data required for exception handler) |
- /// +---------------------------------------------------------------+
- ///
- /// If the X bit is set in the header, the unwind byte code is followed by the
- /// exception handler information. This constants of one Exception Handler RVA
- /// which is the address to the exception handler, followed immediately by the
- /// variable length data associated with the exception handler.
- ///
- struct EpilogueScope {
- const support::ulittle32_t ES;
- EpilogueScope(const support::ulittle32_t Data) : ES(Data) {}
- // Same for both ARM and AArch64.
- uint32_t EpilogueStartOffset() const {
- return (ES & 0x0003ffff);
- }
- // Different implementations for ARM and AArch64.
- uint8_t ResARM() const {
- return ((ES & 0x000c0000) >> 18);
- }
- uint8_t ResAArch64() const {
- return ((ES & 0x000f0000) >> 18);
- }
- // Condition is only applicable to ARM.
- uint8_t Condition() const {
- return ((ES & 0x00f00000) >> 20);
- }
- // Different implementations for ARM and AArch64.
- uint8_t EpilogueStartIndexARM() const {
- return ((ES & 0xff000000) >> 24);
- }
- uint16_t EpilogueStartIndexAArch64() const {
- return ((ES & 0xffc00000) >> 22);
- }
- };
- struct ExceptionDataRecord;
- inline size_t HeaderWords(const ExceptionDataRecord &XR);
- struct ExceptionDataRecord {
- const support::ulittle32_t *Data;
- bool isAArch64;
- ExceptionDataRecord(const support::ulittle32_t *Data, bool isAArch64) :
- Data(Data), isAArch64(isAArch64) {}
- uint32_t FunctionLength() const {
- return (Data[0] & 0x0003ffff);
- }
- uint32_t FunctionLengthInBytesARM() const {
- return FunctionLength() << 1;
- }
- uint32_t FunctionLengthInBytesAArch64() const {
- return FunctionLength() << 2;
- }
- uint8_t Vers() const {
- return (Data[0] & 0x000C0000) >> 18;
- }
- bool X() const {
- return ((Data[0] & 0x00100000) >> 20);
- }
- bool E() const {
- return ((Data[0] & 0x00200000) >> 21);
- }
- bool F() const {
- assert(!isAArch64 && "Fragments are only supported on ARMv7 WinEH");
- return ((Data[0] & 0x00400000) >> 22);
- }
- uint16_t EpilogueCount() const {
- if (HeaderWords(*this) == 1) {
- if (isAArch64)
- return (Data[0] & 0x07C00000) >> 22;
- return (Data[0] & 0x0f800000) >> 23;
- }
- return Data[1] & 0x0000ffff;
- }
- uint8_t CodeWords() const {
- if (HeaderWords(*this) == 1) {
- if (isAArch64)
- return (Data[0] & 0xf8000000) >> 27;
- return (Data[0] & 0xf0000000) >> 28;
- }
- return (Data[1] & 0x00ff0000) >> 16;
- }
- ArrayRef<support::ulittle32_t> EpilogueScopes() const {
- assert(E() == 0 && "epilogue scopes are only present when the E bit is 0");
- size_t Offset = HeaderWords(*this);
- return makeArrayRef(&Data[Offset], EpilogueCount());
- }
- ArrayRef<uint8_t> UnwindByteCode() const {
- const size_t Offset = HeaderWords(*this)
- + (E() ? 0 : EpilogueCount());
- const uint8_t *ByteCode =
- reinterpret_cast<const uint8_t *>(&Data[Offset]);
- return makeArrayRef(ByteCode, CodeWords() * sizeof(uint32_t));
- }
- uint32_t ExceptionHandlerRVA() const {
- assert(X() && "Exception Handler RVA is only valid if the X bit is set");
- return Data[HeaderWords(*this) + (E() ? 0 : EpilogueCount()) + CodeWords()];
- }
- uint32_t ExceptionHandlerParameter() const {
- assert(X() && "Exception Handler RVA is only valid if the X bit is set");
- return Data[HeaderWords(*this) + (E() ? 0 : EpilogueCount()) + CodeWords() +
- 1];
- }
- };
- inline size_t HeaderWords(const ExceptionDataRecord &XR) {
- if (XR.isAArch64)
- return (XR.Data[0] & 0xffc00000) ? 1 : 2;
- return (XR.Data[0] & 0xff800000) ? 1 : 2;
- }
- }
- }
- }
- #endif
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|