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