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_ClearUnwoundToCall,
64   UOP_PACSignLR,
65   UOP_SaveAnyRegI,
66   UOP_SaveAnyRegIP,
67   UOP_SaveAnyRegD,
68   UOP_SaveAnyRegDP,
69   UOP_SaveAnyRegQ,
70   UOP_SaveAnyRegQP,
71   UOP_SaveAnyRegIX,
72   UOP_SaveAnyRegIPX,
73   UOP_SaveAnyRegDX,
74   UOP_SaveAnyRegDPX,
75   UOP_SaveAnyRegQX,
76   UOP_SaveAnyRegQPX,
77 
78   // The following set of unwind opcodes is for ARM.  They are documented at
79   // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
80 
81   // Stack allocations use UOP_AllocSmall, UOP_AllocLarge from above, plus
82   // the following. AllocSmall, AllocLarge and AllocHuge represent a 16 bit
83   // instruction, while the WideAlloc* opcodes represent a 32 bit instruction.
84   // Small can represent a stack offset of 0x7f*4 (252) bytes, Medium can
85   // represent up to 0x3ff*4 (4092) bytes, Large up to 0xffff*4 (262140) bytes,
86   // and Huge up to 0xffffff*4 (67108860) bytes.
87   UOP_AllocHuge,
88   UOP_WideAllocMedium,
89   UOP_WideAllocLarge,
90   UOP_WideAllocHuge,
91 
92   UOP_WideSaveRegMask,
93   UOP_SaveSP,
94   UOP_SaveRegsR4R7LR,
95   UOP_WideSaveRegsR4R11LR,
96   UOP_SaveFRegD8D15,
97   UOP_SaveRegMask,
98   UOP_SaveLR,
99   UOP_SaveFRegD0D15,
100   UOP_SaveFRegD16D31,
101   // Using UOP_Nop from above
102   UOP_WideNop,
103   // Using UOP_End from above
104   UOP_EndNop,
105   UOP_WideEndNop,
106   // A custom unspecified opcode, consisting of one or more bytes. This
107   // allows producing opcodes in the implementation defined/reserved range.
108   UOP_Custom,
109 };
110 
111 /// UnwindCode - This union describes a single operation in a function prolog,
112 /// or part thereof.
113 union UnwindCode {
114   struct {
115     uint8_t CodeOffset;
116     uint8_t UnwindOpAndOpInfo;
117   } u;
118   support::ulittle16_t FrameOffset;
119 
120   uint8_t getUnwindOp() const {
121     return u.UnwindOpAndOpInfo & 0x0F;
122   }
123   uint8_t getOpInfo() const {
124     return (u.UnwindOpAndOpInfo >> 4) & 0x0F;
125   }
126 };
127 
128 enum {
129   /// UNW_ExceptionHandler - Specifies that this function has an exception
130   /// handler.
131   UNW_ExceptionHandler = 0x01,
132   /// UNW_TerminateHandler - Specifies that this function has a termination
133   /// handler.
134   UNW_TerminateHandler = 0x02,
135   /// UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to
136   /// another one.
137   UNW_ChainInfo = 0x04
138 };
139 
140 /// RuntimeFunction - An entry in the table of functions with unwind info.
141 struct RuntimeFunction {
142   support::ulittle32_t StartAddress;
143   support::ulittle32_t EndAddress;
144   support::ulittle32_t UnwindInfoOffset;
145 };
146 
147 /// UnwindInfo - An entry in the exception table.
148 struct UnwindInfo {
149   uint8_t VersionAndFlags;
150   uint8_t PrologSize;
151   uint8_t NumCodes;
152   uint8_t FrameRegisterAndOffset;
153   UnwindCode UnwindCodes[1];
154 
155   uint8_t getVersion() const {
156     return VersionAndFlags & 0x07;
157   }
158   uint8_t getFlags() const {
159     return (VersionAndFlags >> 3) & 0x1f;
160   }
161   uint8_t getFrameRegister() const {
162     return FrameRegisterAndOffset & 0x0f;
163   }
164   uint8_t getFrameOffset() const {
165     return (FrameRegisterAndOffset >> 4) & 0x0f;
166   }
167 
168   // The data after unwindCodes depends on flags.
169   // If UNW_ExceptionHandler or UNW_TerminateHandler is set then follows
170   // the address of the language-specific exception handler.
171   // If UNW_ChainInfo is set then follows a RuntimeFunction which defines
172   // the chained unwind info.
173   // For more information please see MSDN at:
174   // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
175 
176   /// Return pointer to language specific data part of UnwindInfo.
177   void *getLanguageSpecificData() {
178     return reinterpret_cast<void *>(&UnwindCodes[(NumCodes+1) & ~1]);
179   }
180 
181   /// Return pointer to language specific data part of UnwindInfo.
182   const void *getLanguageSpecificData() const {
183     return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes + 1) & ~1]);
184   }
185 
186   /// Return image-relative offset of language-specific exception handler.
187   uint32_t getLanguageSpecificHandlerOffset() const {
188     return *reinterpret_cast<const support::ulittle32_t *>(
189                getLanguageSpecificData());
190   }
191 
192   /// Set image-relative offset of language-specific exception handler.
193   void setLanguageSpecificHandlerOffset(uint32_t offset) {
194     *reinterpret_cast<support::ulittle32_t *>(getLanguageSpecificData()) =
195         offset;
196   }
197 
198   /// Return pointer to exception-specific data.
199   void *getExceptionData() {
200     return reinterpret_cast<void *>(reinterpret_cast<uint32_t *>(
201                                                   getLanguageSpecificData())+1);
202   }
203 
204   /// Return pointer to chained unwind info.
205   RuntimeFunction *getChainedFunctionEntry() {
206     return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData());
207   }
208 
209   /// Return pointer to chained unwind info.
210   const RuntimeFunction *getChainedFunctionEntry() const {
211     return reinterpret_cast<const RuntimeFunction *>(getLanguageSpecificData());
212   }
213 };
214 
215 
216 } // End of namespace Win64EH
217 } // End of namespace llvm
218 
219 #endif
220