]>
Commit | Line | Data |
---|---|---|
b4c522fa | 1 | // Exception handling and frame unwind runtime interface routines. |
99dee823 | 2 | // Copyright (C) 2011-2021 Free Software Foundation, Inc. |
b4c522fa IB |
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 ARM EABI and C6X unwinders. | |
24 | // This corresponds to unwind-arm-common.h | |
25 | ||
26 | module gcc.unwind.arm_common; | |
27 | ||
28 | import gcc.config; | |
29 | ||
30 | static if (GNU_ARM_EABI_Unwinder): | |
31 | ||
32 | import gcc.builtins; | |
33 | ||
34 | extern (C): | |
35 | ||
36 | // Placed outside @nogc in order to not constrain what the callback does. | |
37 | // ??? Does this really need to be extern(C) alias? | |
38 | extern(C) alias _Unwind_Exception_Cleanup_Fn | |
39 | = void function(_Unwind_Reason_Code, _Unwind_Exception*); | |
40 | ||
41 | extern(C) alias personality_routine | |
42 | = _Unwind_Reason_Code function(_Unwind_State, | |
43 | _Unwind_Control_Block*, | |
44 | _Unwind_Context*); | |
45 | ||
46 | extern(C) alias _Unwind_Stop_Fn | |
47 | =_Unwind_Reason_Code function(int, _Unwind_Action, | |
48 | _Unwind_Exception_Class, | |
49 | _Unwind_Control_Block*, | |
50 | _Unwind_Context*, void*); | |
51 | ||
52 | extern(C) alias _Unwind_Trace_Fn | |
53 | = _Unwind_Reason_Code function(_Unwind_Context*, void*); | |
54 | ||
55 | @nogc: | |
56 | ||
57 | alias _Unwind_Word = __builtin_machine_uint; | |
58 | alias _Unwind_Sword = __builtin_machine_int; | |
59 | alias _Unwind_Ptr = __builtin_pointer_uint; | |
60 | alias _Unwind_Internal_Ptr =__builtin_pointer_uint; | |
61 | alias _uw = _Unwind_Word; | |
62 | alias _uw64 = ulong; | |
63 | alias _uw16 = ushort; | |
64 | alias _uw8 = ubyte; | |
65 | ||
66 | alias _Unwind_Reason_Code = uint; | |
67 | enum : _Unwind_Reason_Code | |
68 | { | |
69 | _URC_OK = 0, // operation completed successfully | |
70 | _URC_FOREIGN_EXCEPTION_CAUGHT = 1, | |
71 | _URC_END_OF_STACK = 5, | |
72 | _URC_HANDLER_FOUND = 6, | |
73 | _URC_INSTALL_CONTEXT = 7, | |
74 | _URC_CONTINUE_UNWIND = 8, | |
75 | _URC_FAILURE = 9 // unspecified failure of some kind | |
76 | } | |
77 | ||
78 | alias _Unwind_State = int; | |
79 | enum : _Unwind_State | |
80 | { | |
81 | _US_VIRTUAL_UNWIND_FRAME = 0, | |
82 | _US_UNWIND_FRAME_STARTING = 1, | |
83 | _US_UNWIND_FRAME_RESUME = 2, | |
84 | _US_ACTION_MASK = 3, | |
85 | _US_FORCE_UNWIND = 8, | |
86 | _US_END_OF_STACK = 16 | |
87 | } | |
88 | ||
89 | // Provided only for for compatibility with existing code. | |
90 | alias _Unwind_Action = int; | |
91 | enum : _Unwind_Action | |
92 | { | |
93 | _UA_SEARCH_PHASE = 1, | |
94 | _UA_CLEANUP_PHASE = 2, | |
95 | _UA_HANDLER_FRAME = 4, | |
96 | _UA_FORCE_UNWIND = 8, | |
97 | _UA_END_OF_STACK = 16, | |
98 | _URC_NO_REASON = _URC_OK | |
99 | } | |
100 | ||
101 | struct _Unwind_Context; | |
102 | alias _Unwind_EHT_Header = _uw; | |
103 | ||
104 | struct _Unwind_Control_Block | |
105 | { | |
106 | _Unwind_Exception_Class exception_class = '\0'; | |
107 | _Unwind_Exception_Cleanup_Fn exception_cleanup; | |
108 | // Unwinder cache, private fields for the unwinder's use | |
109 | struct _unwinder_cache | |
110 | { | |
111 | _uw reserved1; // Forced unwind stop fn, 0 if not forced | |
112 | _uw reserved2; // Personality routine address | |
113 | _uw reserved3; // Saved callsite address | |
114 | _uw reserved4; // Forced unwind stop arg | |
115 | _uw reserved5; | |
116 | } | |
117 | _unwinder_cache unwinder_cache; | |
118 | // Propagation barrier cache (valid after phase 1): | |
119 | struct _barrier_cache | |
120 | { | |
121 | _uw sp; | |
122 | _uw[5] bitpattern; | |
123 | } | |
124 | _barrier_cache barrier_cache; | |
125 | // Cleanup cache (preserved over cleanup): | |
126 | struct _cleanup_cache | |
127 | { | |
128 | _uw[4] bitpattern; | |
129 | } | |
130 | _cleanup_cache cleanup_cache; | |
131 | // Pr cache (for pr's benefit): | |
132 | struct _pr_cache | |
133 | { | |
134 | _uw fnstart; // function start address */ | |
135 | _Unwind_EHT_Header* ehtp; // pointer to EHT entry header word | |
136 | _uw additional; // additional data | |
137 | _uw reserved1; | |
138 | } | |
139 | _pr_cache pr_cache; | |
140 | long[0] _force_alignment; // Force alignment to 8-byte boundary | |
141 | } | |
142 | ||
143 | // Virtual Register Set | |
144 | alias _Unwind_VRS_RegClass = int; | |
145 | enum : _Unwind_VRS_RegClass | |
146 | { | |
147 | _UVRSC_CORE = 0, // integer register | |
148 | _UVRSC_VFP = 1, // vfp | |
149 | _UVRSC_FPA = 2, // fpa | |
150 | _UVRSC_WMMXD = 3, // Intel WMMX data register | |
151 | _UVRSC_WMMXC = 4 // Intel WMMX control register | |
152 | } | |
153 | ||
154 | alias _Unwind_VRS_DataRepresentation = int; | |
155 | enum : _Unwind_VRS_DataRepresentation | |
156 | { | |
157 | _UVRSD_UINT32 = 0, | |
158 | _UVRSD_VFPX = 1, | |
159 | _UVRSD_FPAX = 2, | |
160 | _UVRSD_UINT64 = 3, | |
161 | _UVRSD_FLOAT = 4, | |
162 | _UVRSD_DOUBLE = 5 | |
163 | } | |
164 | ||
165 | alias _Unwind_VRS_Result = int; | |
166 | enum : _Unwind_VRS_Result | |
167 | { | |
168 | _UVRSR_OK = 0, | |
169 | _UVRSR_NOT_IMPLEMENTED = 1, | |
170 | _UVRSR_FAILED = 2 | |
171 | } | |
172 | ||
173 | // Frame unwinding state. | |
174 | struct __gnu_unwind_state | |
175 | { | |
176 | _uw data; // The current word (bytes packed msb first). | |
177 | _uw* next; // Pointer to the next word of data. | |
178 | _uw8 bytes_left; // The number of bytes left in this word. | |
179 | _uw8 words_left; // The number of words pointed to by ptr. | |
180 | } | |
181 | ||
182 | _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context*, _Unwind_VRS_RegClass, | |
183 | _uw, _Unwind_VRS_DataRepresentation, | |
184 | void*); | |
185 | ||
186 | _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context*, _Unwind_VRS_RegClass, | |
187 | _uw, _Unwind_VRS_DataRepresentation, | |
188 | void*); | |
189 | ||
190 | _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context*, _Unwind_VRS_RegClass, | |
191 | _uw, _Unwind_VRS_DataRepresentation); | |
192 | ||
193 | ||
194 | // Support functions for the PR. | |
195 | alias _Unwind_Exception = _Unwind_Control_Block; | |
196 | alias _Unwind_Exception_Class = char[8]; | |
197 | ||
198 | void* _Unwind_GetLanguageSpecificData(_Unwind_Context*); | |
199 | _Unwind_Ptr _Unwind_GetRegionStart(_Unwind_Context*); | |
200 | ||
201 | _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context*); | |
202 | // This should never be used. | |
203 | _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*); | |
204 | ||
205 | // Interface functions: | |
206 | _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block*); | |
207 | void _Unwind_Resume(_Unwind_Control_Block*); | |
208 | _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Control_Block*); | |
209 | ||
210 | _Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Control_Block*, | |
211 | _Unwind_Stop_Fn, void*); | |
212 | ||
213 | // @@@ Use unwind data to perform a stack backtrace. The trace callback | |
214 | // is called for every stack frame in the call chain, but no cleanup | |
215 | // actions are performed. | |
216 | _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*); | |
217 | ||
218 | _Unwind_Word _Unwind_GetCFA(_Unwind_Context*); | |
219 | void _Unwind_Complete(_Unwind_Control_Block*); | |
220 | void _Unwind_DeleteException(_Unwind_Exception*); | |
221 | ||
222 | _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Control_Block*, | |
223 | _Unwind_Context*); | |
224 | _Unwind_Reason_Code __gnu_unwind_execute(_Unwind_Context*, | |
225 | __gnu_unwind_state*); | |
226 | ||
227 | _Unwind_Word _Unwind_GetGR(_Unwind_Context* context, int regno) | |
228 | { | |
229 | _uw val; | |
230 | _Unwind_VRS_Get(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); | |
231 | return val; | |
232 | } | |
233 | ||
234 | void _Unwind_SetGR(_Unwind_Context* context, int regno, _Unwind_Word val) | |
235 | { | |
236 | _Unwind_VRS_Set(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); | |
237 | } | |
238 | ||
239 | // leb128 type numbers have a potentially unlimited size. | |
240 | // The target of the following definitions of _sleb128_t and _uleb128_t | |
241 | // is to have efficient data types large enough to hold the leb128 type | |
242 | // numbers used in the unwind code. | |
243 | alias _sleb128_t = __builtin_clong; | |
244 | alias _uleb128_t = __builtin_culong; |