xref: /llvm-project/llvm/include/llvm/Support/Win64EH.h (revision 2201164477982c2bd20fa2e925f567585c390805)
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   /// Gets the offset for an UOP_Epilog unwind code.
128   uint32_t getEpilogOffset() const {
129     assert(getUnwindOp() == UOP_Epilog);
130     return (getOpInfo() << 8) | static_cast<uint32_t>(u.CodeOffset);
131   }
132 };
133 
134 enum {
135   /// UNW_ExceptionHandler - Specifies that this function has an exception
136   /// handler.
137   UNW_ExceptionHandler = 0x01,
138   /// UNW_TerminateHandler - Specifies that this function has a termination
139   /// handler.
140   UNW_TerminateHandler = 0x02,
141   /// UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to
142   /// another one.
143   UNW_ChainInfo = 0x04
144 };
145 
146 /// RuntimeFunction - An entry in the table of functions with unwind info.
147 struct RuntimeFunction {
148   support::ulittle32_t StartAddress;
149   support::ulittle32_t EndAddress;
150   support::ulittle32_t UnwindInfoOffset;
151 };
152 
153 /// UnwindInfo - An entry in the exception table.
154 struct UnwindInfo {
155   uint8_t VersionAndFlags;
156   uint8_t PrologSize;
157   uint8_t NumCodes;
158   uint8_t FrameRegisterAndOffset;
159   UnwindCode UnwindCodes[1];
160 
161   uint8_t getVersion() const {
162     return VersionAndFlags & 0x07;
163   }
164   uint8_t getFlags() const {
165     return (VersionAndFlags >> 3) & 0x1f;
166   }
167   uint8_t getFrameRegister() const {
168     return FrameRegisterAndOffset & 0x0f;
169   }
170   uint8_t getFrameOffset() const {
171     return (FrameRegisterAndOffset >> 4) & 0x0f;
172   }
173 
174   // The data after unwindCodes depends on flags.
175   // If UNW_ExceptionHandler or UNW_TerminateHandler is set then follows
176   // the address of the language-specific exception handler.
177   // If UNW_ChainInfo is set then follows a RuntimeFunction which defines
178   // the chained unwind info.
179   // For more information please see MSDN at:
180   // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
181 
182   /// Return pointer to language specific data part of UnwindInfo.
183   void *getLanguageSpecificData() {
184     return reinterpret_cast<void *>(&UnwindCodes[(NumCodes+1) & ~1]);
185   }
186 
187   /// Return pointer to language specific data part of UnwindInfo.
188   const void *getLanguageSpecificData() const {
189     return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes + 1) & ~1]);
190   }
191 
192   /// Return image-relative offset of language-specific exception handler.
193   uint32_t getLanguageSpecificHandlerOffset() const {
194     return *reinterpret_cast<const support::ulittle32_t *>(
195                getLanguageSpecificData());
196   }
197 
198   /// Set image-relative offset of language-specific exception handler.
199   void setLanguageSpecificHandlerOffset(uint32_t offset) {
200     *reinterpret_cast<support::ulittle32_t *>(getLanguageSpecificData()) =
201         offset;
202   }
203 
204   /// Return pointer to exception-specific data.
205   void *getExceptionData() {
206     return reinterpret_cast<void *>(reinterpret_cast<uint32_t *>(
207                                                   getLanguageSpecificData())+1);
208   }
209 
210   /// Return pointer to chained unwind info.
211   RuntimeFunction *getChainedFunctionEntry() {
212     return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData());
213   }
214 
215   /// Return pointer to chained unwind info.
216   const RuntimeFunction *getChainedFunctionEntry() const {
217     return reinterpret_cast<const RuntimeFunction *>(getLanguageSpecificData());
218   }
219 };
220 
221 
222 } // End of namespace Win64EH
223 } // End of namespace llvm
224 
225 #endif
226