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   UOP_PushNonVol = 0,
28   UOP_AllocLarge,
29   UOP_AllocSmall,
30   UOP_SetFPReg,
31   UOP_SaveNonVol,
32   UOP_SaveNonVolBig,
33   UOP_Epilog,
34   UOP_SpareCode,
35   UOP_SaveXMM128,
36   UOP_SaveXMM128Big,
37   UOP_PushMachFrame,
38   // The following set of unwind opcodes is for ARM64.  They are documented at
39   // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
40   UOP_AllocMedium,
41   UOP_SaveR19R20X,
42   UOP_SaveFPLRX,
43   UOP_SaveFPLR,
44   UOP_SaveReg,
45   UOP_SaveRegX,
46   UOP_SaveRegP,
47   UOP_SaveRegPX,
48   UOP_SaveLRPair,
49   UOP_SaveFReg,
50   UOP_SaveFRegX,
51   UOP_SaveFRegP,
52   UOP_SaveFRegPX,
53   UOP_SetFP,
54   UOP_AddFP,
55   UOP_Nop,
56   UOP_End,
57   UOP_SaveNext,
58   UOP_TrapFrame,
59   UOP_Context,
60   UOP_ClearUnwoundToCall
61 };
62 
63 /// UnwindCode - This union describes a single operation in a function prolog,
64 /// or part thereof.
65 union UnwindCode {
66   struct {
67     uint8_t CodeOffset;
68     uint8_t UnwindOpAndOpInfo;
69   } u;
70   support::ulittle16_t FrameOffset;
71 
getUnwindOp()72   uint8_t getUnwindOp() const {
73     return u.UnwindOpAndOpInfo & 0x0F;
74   }
getOpInfo()75   uint8_t getOpInfo() const {
76     return (u.UnwindOpAndOpInfo >> 4) & 0x0F;
77   }
78 };
79 
80 enum {
81   /// UNW_ExceptionHandler - Specifies that this function has an exception
82   /// handler.
83   UNW_ExceptionHandler = 0x01,
84   /// UNW_TerminateHandler - Specifies that this function has a termination
85   /// handler.
86   UNW_TerminateHandler = 0x02,
87   /// UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to
88   /// another one.
89   UNW_ChainInfo = 0x04
90 };
91 
92 /// RuntimeFunction - An entry in the table of functions with unwind info.
93 struct RuntimeFunction {
94   support::ulittle32_t StartAddress;
95   support::ulittle32_t EndAddress;
96   support::ulittle32_t UnwindInfoOffset;
97 };
98 
99 /// UnwindInfo - An entry in the exception table.
100 struct UnwindInfo {
101   uint8_t VersionAndFlags;
102   uint8_t PrologSize;
103   uint8_t NumCodes;
104   uint8_t FrameRegisterAndOffset;
105   UnwindCode UnwindCodes[1];
106 
getVersionUnwindInfo107   uint8_t getVersion() const {
108     return VersionAndFlags & 0x07;
109   }
getFlagsUnwindInfo110   uint8_t getFlags() const {
111     return (VersionAndFlags >> 3) & 0x1f;
112   }
getFrameRegisterUnwindInfo113   uint8_t getFrameRegister() const {
114     return FrameRegisterAndOffset & 0x0f;
115   }
getFrameOffsetUnwindInfo116   uint8_t getFrameOffset() const {
117     return (FrameRegisterAndOffset >> 4) & 0x0f;
118   }
119 
120   // The data after unwindCodes depends on flags.
121   // If UNW_ExceptionHandler or UNW_TerminateHandler is set then follows
122   // the address of the language-specific exception handler.
123   // If UNW_ChainInfo is set then follows a RuntimeFunction which defines
124   // the chained unwind info.
125   // For more information please see MSDN at:
126   // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
127 
128   /// Return pointer to language specific data part of UnwindInfo.
getLanguageSpecificDataUnwindInfo129   void *getLanguageSpecificData() {
130     return reinterpret_cast<void *>(&UnwindCodes[(NumCodes+1) & ~1]);
131   }
132 
133   /// Return pointer to language specific data part of UnwindInfo.
getLanguageSpecificDataUnwindInfo134   const void *getLanguageSpecificData() const {
135     return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes + 1) & ~1]);
136   }
137 
138   /// Return image-relative offset of language-specific exception handler.
getLanguageSpecificHandlerOffsetUnwindInfo139   uint32_t getLanguageSpecificHandlerOffset() const {
140     return *reinterpret_cast<const support::ulittle32_t *>(
141                getLanguageSpecificData());
142   }
143 
144   /// Set image-relative offset of language-specific exception handler.
setLanguageSpecificHandlerOffsetUnwindInfo145   void setLanguageSpecificHandlerOffset(uint32_t offset) {
146     *reinterpret_cast<support::ulittle32_t *>(getLanguageSpecificData()) =
147         offset;
148   }
149 
150   /// Return pointer to exception-specific data.
getExceptionDataUnwindInfo151   void *getExceptionData() {
152     return reinterpret_cast<void *>(reinterpret_cast<uint32_t *>(
153                                                   getLanguageSpecificData())+1);
154   }
155 
156   /// Return pointer to chained unwind info.
getChainedFunctionEntryUnwindInfo157   RuntimeFunction *getChainedFunctionEntry() {
158     return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData());
159   }
160 
161   /// Return pointer to chained unwind info.
getChainedFunctionEntryUnwindInfo162   const RuntimeFunction *getChainedFunctionEntry() const {
163     return reinterpret_cast<const RuntimeFunction *>(getLanguageSpecificData());
164   }
165 };
166 
167 
168 } // End of namespace Win64EH
169 } // End of namespace llvm
170 
171 #endif
172