1 // Exception handling and frame unwind runtime interface routines.
2 // Copyright (C) 2011-2021 Free Software Foundation, Inc.
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
_Unwind_GetGR(_Unwind_Context * context,int regno)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
_Unwind_SetGR(_Unwind_Context * context,int regno,_Unwind_Word val)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;
245