]>
Commit | Line | Data |
---|---|---|
03385ed3 | 1 | // Exception handling and frame unwind runtime interface routines. |
fbd26352 | 2 | // Copyright (C) 2011-2019 Free Software Foundation, Inc. |
03385ed3 | 3 | |
4 | // GCC is free software; you can redistribute it and/or modify it under | |
5 | // the terms of the GNU General Public License as published by the Free | |
6 | // Software Foundation; either version 3, or (at your option) any later | |
7 | // version. | |
8 | ||
9 | // GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
10 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 | // for more details. | |
13 | ||
14 | // Under Section 7 of GPL version 3, you are granted additional | |
15 | // permissions described in the GCC Runtime Library Exception, version | |
16 | // 3.1, as published by the Free Software Foundation. | |
17 | ||
18 | // You should have received a copy of the GNU General Public License and | |
19 | // a copy of the GCC Runtime Library Exception along with this program; | |
20 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
21 | // <http://www.gnu.org/licenses/>. | |
22 | ||
23 | // extern(C) interface for the generic unwinder library. | |
24 | // This corresponds to unwind-generic.h | |
25 | ||
26 | module gcc.unwind.generic; | |
27 | ||
28 | import gcc.config; | |
29 | ||
30 | static if (!GNU_ARM_EABI_Unwinder): | |
31 | ||
32 | import gcc.builtins; | |
33 | ||
34 | // This is derived from the C++ ABI for IA-64. Where we diverge | |
35 | // for cross-architecture compatibility are noted with "@@@". | |
36 | ||
37 | extern (C): | |
38 | ||
39 | // Placed outside @nogc in order to not constrain what the callback does. | |
40 | // ??? Does this really need to be extern(C) alias? | |
41 | ||
42 | extern(C) alias _Unwind_Exception_Cleanup_Fn | |
43 | = void function(_Unwind_Reason_Code, _Unwind_Exception*); | |
44 | ||
45 | extern(C) alias _Unwind_Stop_Fn | |
46 | = _Unwind_Reason_Code function(int, _Unwind_Action, | |
47 | _Unwind_Exception_Class, | |
48 | _Unwind_Exception*, | |
49 | _Unwind_Context*, void*); | |
50 | ||
51 | extern(C) alias _Unwind_Trace_Fn | |
52 | = _Unwind_Reason_Code function(_Unwind_Context*, void*); | |
53 | ||
54 | // The personality routine is the function in the C++ (or other language) | |
55 | // runtime library which serves as an interface between the system unwind | |
56 | // library and language-specific exception handling semantics. It is | |
57 | // specific to the code fragment described by an unwind info block, and | |
58 | // it is always referenced via the pointer in the unwind info block, and | |
59 | // hence it has no ABI-specified name. | |
60 | ||
61 | // Note that this implies that two different C++ implementations can | |
62 | // use different names, and have different contents in the language | |
63 | // specific data area. Moreover, that the language specific data | |
64 | // area contains no version info because name of the function invoked | |
65 | // provides more effective versioning by detecting at link time the | |
66 | // lack of code to handle the different data format. | |
67 | ||
68 | extern(C) alias _Unwind_Personality_Fn | |
69 | = _Unwind_Reason_Code function(int, _Unwind_Action, | |
70 | _Unwind_Exception_Class, | |
71 | _Unwind_Exception*, | |
72 | _Unwind_Context*); | |
73 | ||
74 | @nogc: | |
75 | ||
76 | // Level 1: Base ABI | |
77 | ||
78 | // @@@ The IA-64 ABI uses uint64 throughout. | |
79 | // Most places this is inefficient for 32-bit and smaller machines. | |
80 | alias _Unwind_Word = __builtin_unwind_uint; | |
81 | alias _Unwind_Sword = __builtin_unwind_int; | |
82 | version (IA64) | |
83 | { | |
84 | version (HPUX) | |
85 | alias _Unwind_Ptr = __builtin_machine_uint; | |
86 | else | |
87 | alias _Unwind_Ptr = __builtin_pointer_uint; | |
88 | } | |
89 | else | |
90 | { | |
91 | alias _Unwind_Ptr = __builtin_pointer_uint; | |
92 | } | |
93 | alias _Unwind_Internal_Ptr = __builtin_pointer_uint; | |
94 | ||
95 | // @@@ The IA-64 ABI uses a 64-bit word to identify the producer and | |
96 | // consumer of an exception. We'll go along with this for now even on | |
97 | // 32-bit machines. We'll need to provide some other option for | |
98 | // 16-bit machines and for machines with > 8 bits per byte. | |
99 | alias _Unwind_Exception_Class = ulong; | |
100 | ||
101 | // The unwind interface uses reason codes in several contexts to | |
102 | // identify the reasons for failures or other actions. | |
103 | alias _Unwind_Reason_Code = uint; | |
104 | enum : _Unwind_Reason_Code | |
105 | { | |
106 | _URC_NO_REASON = 0, | |
107 | _URC_FOREIGN_EXCEPTION_CAUGHT = 1, | |
108 | _URC_FATAL_PHASE2_ERROR = 2, | |
109 | _URC_FATAL_PHASE1_ERROR = 3, | |
110 | _URC_NORMAL_STOP = 4, | |
111 | _URC_END_OF_STACK = 5, | |
112 | _URC_HANDLER_FOUND = 6, | |
113 | _URC_INSTALL_CONTEXT = 7, | |
114 | _URC_CONTINUE_UNWIND = 8 | |
115 | } | |
116 | ||
117 | // The unwind interface uses a pointer to an exception header object | |
118 | // as its representation of an exception being thrown. In general, the | |
119 | // full representation of an exception object is language- and | |
120 | // implementation-specific, but it will be prefixed by a header | |
121 | // understood by the unwind interface. | |
122 | ||
123 | // @@@ The IA-64 ABI says that this structure must be double-word aligned. | |
124 | // Taking that literally does not make much sense generically. Instead we | |
125 | // provide the maximum alignment required by any type for the machine. | |
126 | struct _Unwind_Exception | |
127 | { | |
128 | _Unwind_Exception_Class exception_class; | |
129 | _Unwind_Exception_Cleanup_Fn exception_cleanup; | |
130 | _Unwind_Word private_1; | |
131 | _Unwind_Word private_2; | |
132 | } | |
133 | ||
134 | // The ACTIONS argument to the personality routine is a bitwise OR of one | |
135 | // or more of the following constants. | |
136 | alias _Unwind_Action = int; | |
137 | enum : _Unwind_Action | |
138 | { | |
139 | _UA_SEARCH_PHASE = 1, | |
140 | _UA_CLEANUP_PHASE = 2, | |
141 | _UA_HANDLER_FRAME = 4, | |
142 | _UA_FORCE_UNWIND = 8, | |
143 | _UA_END_OF_STACK = 16 | |
144 | } | |
145 | ||
146 | // This is an opaque type used to refer to a system-specific data | |
147 | // structure used by the system unwinder. This context is created and | |
148 | // destroyed by the system, and passed to the personality routine | |
149 | // during unwinding. | |
150 | struct _Unwind_Context; | |
151 | ||
152 | // Raise an exception, passing along the given exception object. | |
153 | _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*); | |
154 | ||
155 | // Raise an exception for forced unwinding. | |
156 | _Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception*, _Unwind_Stop_Fn, void*); | |
157 | ||
158 | // Helper to invoke the exception_cleanup routine. | |
159 | void _Unwind_DeleteException(_Unwind_Exception*); | |
160 | ||
161 | // Resume propagation of an existing exception. This is used after | |
162 | // e.g. executing cleanup code, and not to implement rethrowing. | |
163 | void _Unwind_Resume(_Unwind_Exception*); | |
164 | ||
165 | // @@@ Resume propagation of an FORCE_UNWIND exception, or to rethrow | |
166 | // a normal exception that was handled. | |
167 | _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception*); | |
168 | ||
169 | // @@@ Use unwind data to perform a stack backtrace. The trace callback | |
170 | // is called for every stack frame in the call chain, but no cleanup | |
171 | // actions are performed. | |
172 | _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*); | |
173 | ||
174 | // These functions are used for communicating information about the unwind | |
175 | // context (i.e. the unwind descriptors and the user register state) between | |
176 | // the unwind library and the personality routine and landing pad. Only | |
177 | // selected registers may be manipulated. | |
178 | ||
179 | _Unwind_Word _Unwind_GetGR(_Unwind_Context*, int); | |
180 | void _Unwind_SetGR(_Unwind_Context*, int, _Unwind_Word); | |
181 | ||
182 | _Unwind_Ptr _Unwind_GetIP(_Unwind_Context*); | |
183 | _Unwind_Ptr _Unwind_GetIPInfo(_Unwind_Context*, int*); | |
184 | void _Unwind_SetIP(_Unwind_Context*, _Unwind_Ptr); | |
185 | ||
186 | // @@@ Retrieve the CFA of the given context. | |
187 | _Unwind_Word _Unwind_GetCFA(_Unwind_Context*); | |
188 | ||
189 | void* _Unwind_GetLanguageSpecificData(_Unwind_Context*); | |
190 | ||
191 | _Unwind_Ptr _Unwind_GetRegionStart(_Unwind_Context*); | |
192 | ||
193 | ||
194 | // @@@ The following alternate entry points are for setjmp/longjmp | |
195 | // based unwinding. | |
196 | ||
197 | struct SjLj_Function_Context; | |
198 | extern void _Unwind_SjLj_Register(SjLj_Function_Context*); | |
199 | extern void _Unwind_SjLj_Unregister(SjLj_Function_Context*); | |
200 | ||
201 | _Unwind_Reason_Code _Unwind_SjLj_RaiseException(_Unwind_Exception*); | |
202 | _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(_Unwind_Exception*, _Unwind_Stop_Fn, void*); | |
203 | void _Unwind_SjLj_Resume(_Unwind_Exception*); | |
204 | _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception*); | |
205 | ||
206 | // @@@ The following provide access to the base addresses for text | |
207 | // and data-relative addressing in the LDSA. In order to stay link | |
208 | // compatible with the standard ABI for IA-64, we inline these. | |
209 | ||
210 | version (IA64) | |
211 | { | |
212 | _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context* _C) | |
213 | { | |
214 | // The GP is stored in R1. | |
215 | return _Unwind_GetGR(_C, 1); | |
216 | } | |
217 | ||
218 | _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*) | |
219 | { | |
220 | __builtin_abort(); | |
221 | return 0; | |
222 | } | |
223 | ||
224 | // @@@ Retrieve the Backing Store Pointer of the given context. | |
225 | _Unwind_Word _Unwind_GetBSP(_Unwind_Context*); | |
226 | } | |
227 | else | |
228 | { | |
229 | _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context*); | |
230 | _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*); | |
231 | } | |
232 | ||
233 | // @@@ Given an address, return the entry point of the function that | |
234 | // contains it. | |
235 | extern void* _Unwind_FindEnclosingFunction(void* pc); | |
236 | ||
237 | ||
238 | // leb128 type numbers have a potentially unlimited size. | |
239 | // The target of the following definitions of _sleb128_t and _uleb128_t | |
240 | // is to have efficient data types large enough to hold the leb128 type | |
241 | // numbers used in the unwind code. | |
242 | // Mostly these types will simply be defined to long and unsigned long | |
243 | // except when a unsigned long data type on the target machine is not | |
244 | // capable of storing a pointer. | |
245 | ||
246 | static if (__builtin_clong.sizeof >= (void*).sizeof) | |
247 | { | |
248 | alias _sleb128_t = __builtin_clong; | |
249 | alias _uleb128_t = __builtin_culong; | |
250 | } | |
251 | else static if (long.sizeof >= (void*).sizeof) | |
252 | { | |
253 | alias _sleb128_t = long; | |
254 | alias _uleb128_t = ulong; | |
255 | } | |
256 | else | |
257 | { | |
258 | static assert(false, "What type shall we use for _sleb128_t?"); | |
259 | } | |
260 | ||
261 | version (GNU_SEH_Exceptions) | |
262 | { | |
263 | // We're lazy, exact definition in MinGW/winnt.h | |
264 | enum EXCEPTION_DISPOSITION | |
265 | { | |
266 | ExceptionContinueExecution, | |
267 | ExceptionContinueSearch, | |
268 | ExceptionNestedException, | |
269 | ExceptionCollidedUnwind | |
270 | } | |
271 | ||
272 | extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*, | |
273 | _Unwind_Personality_Fn); | |
274 | } |