1 //===-- llvm/Support/Win64EH.h ---Win64 EH Constants-------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains constants and structures used for implementing
10 // exception handling on Win64 platforms. For more information, see
11 // http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_SUPPORT_WIN64EH_H
16 #define LLVM_SUPPORT_WIN64EH_H
17 
18 #include "llvm/Support/DataTypes.h"
19 #include "llvm/Support/Endian.h"
20 
21 namespace llvm {
22 namespace Win64EH {
23 
24 /// UnwindOpcodes - Enumeration whose values specify a single operation in
25 /// the prolog of a function.
26 enum UnwindOpcodes {
27   // The following set of unwind opcodes is for x86_64.  They are documented at
28   // https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64.
29   // Some generic values from this set are used for other architectures too.
30   UOP_PushNonVol = 0,
31   UOP_AllocLarge,
32   UOP_AllocSmall,
33   UOP_SetFPReg,
34   UOP_SaveNonVol,
35   UOP_SaveNonVolBig,
36   UOP_Epilog,
37   UOP_SpareCode,
38   UOP_SaveXMM128,
39   UOP_SaveXMM128Big,
40   UOP_PushMachFrame,
41   // The following set of unwind opcodes is for ARM64.  They are documented at
42   // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
43   UOP_AllocMedium,
44   UOP_SaveR19R20X,
45   UOP_SaveFPLRX,
46   UOP_SaveFPLR,
47   UOP_SaveReg,
48   UOP_SaveRegX,
49   UOP_SaveRegP,
50   UOP_SaveRegPX,
51   UOP_SaveLRPair,
52   UOP_SaveFReg,
53   UOP_SaveFRegX,
54   UOP_SaveFRegP,
55   UOP_SaveFRegPX,
56   UOP_SetFP,
57   UOP_AddFP,
58   UOP_Nop,
59   UOP_End,
60   UOP_SaveNext,
61   UOP_TrapFrame,
62   UOP_Context,
63   UOP_ECContext,
64   UOP_ClearUnwoundToCall,
65   UOP_PACSignLR,
66   UOP_SaveAnyRegI,
67   UOP_SaveAnyRegIP,
68   UOP_SaveAnyRegD,
69   UOP_SaveAnyRegDP,
70   UOP_SaveAnyRegQ,
71   UOP_SaveAnyRegQP,
72   UOP_SaveAnyRegIX,
73   UOP_SaveAnyRegIPX,
74   UOP_SaveAnyRegDX,
75   UOP_SaveAnyRegDPX,
76   UOP_SaveAnyRegQX,
77   UOP_SaveAnyRegQPX,
78 
79   // The following set of unwind opcodes is for ARM.  They are documented at
80   // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
81 
82   // Stack allocations use UOP_AllocSmall, UOP_AllocLarge from above, plus
83   // the following. AllocSmall, AllocLarge and AllocHuge represent a 16 bit
84   // instruction, while the WideAlloc* opcodes represent a 32 bit instruction.
85   // Small can represent a stack offset of 0x7f*4 (252) bytes, Medium can
86   // represent up to 0x3ff*4 (4092) bytes, Large up to 0xffff*4 (262140) bytes,
87   // and Huge up to 0xffffff*4 (67108860) bytes.
88   UOP_AllocHuge,
89   UOP_WideAllocMedium,
90   UOP_WideAllocLarge,
91   UOP_WideAllocHuge,
92 
93   UOP_WideSaveRegMask,
94   UOP_SaveSP,
95   UOP_SaveRegsR4R7LR,
96   UOP_WideSaveRegsR4R11LR,
97   UOP_SaveFRegD8D15,
98   UOP_SaveRegMask,
99   UOP_SaveLR,
100   UOP_SaveFRegD0D15,
101   UOP_SaveFRegD16D31,
102   // Using UOP_Nop from above
103   UOP_WideNop,
104   // Using UOP_End from above
105   UOP_EndNop,
106   UOP_WideEndNop,
107   // A custom unspecified opcode, consisting of one or more bytes. This
108   // allows producing opcodes in the implementation defined/reserved range.
109   UOP_Custom,
110 };
111 
112 /// UnwindCode - This union describes a single operation in a function prolog,
113 /// or part thereof.
114 union UnwindCode {
115   struct {
116     uint8_t CodeOffset;
117     uint8_t UnwindOpAndOpInfo;
118   } u;
119   support::ulittle16_t FrameOffset;
120 
121   uint8_t getUnwindOp() const {
122     return u.UnwindOpAndOpInfo & 0x0F;
123   }
124   uint8_t getOpInfo() const {
125     return (u.UnwindOpAndOpInfo >> 4) & 0x0F;
126   }
127 };
128 
129 enum {
130   /// UNW_ExceptionHandler - Specifies that this function has an exception
131   /// handler.
132   UNW_ExceptionHandler = 0x01,
133   /// UNW_TerminateHandler - Specifies that this function has a termination
134   /// handler.
135   UNW_TerminateHandler = 0x02,
136   /// UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to
137   /// another one.
138   UNW_ChainInfo = 0x04
139 };
140 
141 /// RuntimeFunction - An entry in the table of functions with unwind info.
142 struct RuntimeFunction {
143   support::ulittle32_t StartAddress;
144   support::ulittle32_t EndAddress;
145   support::ulittle32_t UnwindInfoOffset;
146 };
147 
148 /// UnwindInfo - An entry in the exception table.
149 struct UnwindInfo {
150   uint8_t VersionAndFlags;
151   uint8_t PrologSize;
152   uint8_t NumCodes;
153   uint8_t FrameRegisterAndOffset;
154   UnwindCode UnwindCodes[1];
155 
156   uint8_t getVersion() const {
157     return VersionAndFlags & 0x07;
158   }
159   uint8_t getFlags() const {
160     return (VersionAndFlags >> 3) & 0x1f;
161   }
162   uint8_t getFrameRegister() const {
163     return FrameRegisterAndOffset & 0x0f;
164   }
165   uint8_t getFrameOffset() const {
166     return (FrameRegisterAndOffset >> 4) & 0x0f;
167   }
168 
169   // The data after unwindCodes depends on flags.
170   // If UNW_ExceptionHandler or UNW_TerminateHandler is set then follows
171   // the address of the language-specific exception handler.
172   // If UNW_ChainInfo is set then follows a RuntimeFunction which defines
173   // the chained unwind info.
174   // For more information please see MSDN at:
175   // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
176 
177   /// Return pointer to language specific data part of UnwindInfo.
178   void *getLanguageSpecificData() {
179     return reinterpret_cast<void *>(&UnwindCodes[(NumCodes+1) & ~1]);
180   }
181 
182   /// Return pointer to language specific data part of UnwindInfo.
183   const void *getLanguageSpecificData() const {
184     return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes + 1) & ~1]);
185   }
186 
187   /// Return image-relative offset of language-specific exception handler.
188   uint32_t getLanguageSpecificHandlerOffset() const {
189     return *reinterpret_cast<const support::ulittle32_t *>(
190                getLanguageSpecificData());
191   }
192 
193   /// Set image-relative offset of language-specific exception handler.
194   void setLanguageSpecificHandlerOffset(uint32_t offset) {
195     *reinterpret_cast<support::ulittle32_t *>(getLanguageSpecificData()) =
196         offset;
197   }
198 
199   /// Return pointer to exception-specific data.
200   void *getExceptionData() {
201     return reinterpret_cast<void *>(reinterpret_cast<uint32_t *>(
202                                                   getLanguageSpecificData())+1);
203   }
204 
205   /// Return pointer to chained unwind info.
206   RuntimeFunction *getChainedFunctionEntry() {
207     return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData());
208   }
209 
210   /// Return pointer to chained unwind info.
211   const RuntimeFunction *getChainedFunctionEntry() const {
212     return reinterpret_cast<const RuntimeFunction *>(getLanguageSpecificData());
213   }
214 };
215 
216 
217 } // End of namespace Win64EH
218 } // End of namespace llvm
219 
220 #endif
221