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