libunwind.cxx revision 1.10 1 1.1 joerg //===--------------------------- libuwind.cpp -----------------------------===//
2 1.1 joerg //
3 1.1 joerg // The LLVM Compiler Infrastructure
4 1.1 joerg //
5 1.1 joerg // This file is dual licensed under the MIT and the University of Illinois Open
6 1.1 joerg // Source Licenses. See LICENSE.TXT for details.
7 1.1 joerg //
8 1.1 joerg //
9 1.1 joerg // Implements C++ ABI Exception Handling Level 1 as documented at:
10 1.1 joerg // http://mentorembedded.github.io/cxx-abi/abi-eh.html
11 1.1 joerg //
12 1.1 joerg //===----------------------------------------------------------------------===//
13 1.1 joerg
14 1.9 joerg #define _UNWIND_GCC_EXTENSIONS
15 1.9 joerg
16 1.1 joerg #include <unwind.h>
17 1.1 joerg
18 1.1 joerg #include "UnwindCursor.hpp"
19 1.1 joerg
20 1.1 joerg using namespace _Unwind;
21 1.1 joerg
22 1.8 joerg typedef CFI_Parser<LocalAddressSpace, NativeUnwindRegisters> MyCFIParser;
23 1.1 joerg
24 1.1 joerg // Internal object representing the address space of this process.
25 1.1 joerg static LocalAddressSpace sThisAddressSpace(MyCFIParser::findPCRange);
26 1.1 joerg
27 1.8 joerg typedef UnwindCursor<LocalAddressSpace, NativeUnwindRegisters> ThisUnwindCursor;
28 1.1 joerg
29 1.1 joerg static _Unwind_Reason_Code unwind_phase1(ThisUnwindCursor &cursor,
30 1.1 joerg struct _Unwind_Exception *exc) {
31 1.1 joerg cursor.setInfoBasedOnIPRegister();
32 1.1 joerg
33 1.1 joerg // Walk frames looking for a place to stop.
34 1.1 joerg for (;;) {
35 1.1 joerg // Get next frame.
36 1.1 joerg // First frame is _Unwind_RaiseException and skipped.
37 1.1 joerg switch (cursor.step()) {
38 1.1 joerg case UNW_STEP_END:
39 1.1 joerg return _URC_END_OF_STACK;
40 1.1 joerg case UNW_STEP_FAILED:
41 1.1 joerg return _URC_FATAL_PHASE1_ERROR;
42 1.1 joerg case UNW_STEP_SUCCESS:
43 1.1 joerg break;
44 1.1 joerg }
45 1.1 joerg
46 1.1 joerg // Check if there is a personality routine for this frame.
47 1.1 joerg unw_proc_info_t frameInfo;
48 1.1 joerg cursor.getInfo(&frameInfo);
49 1.1 joerg if (frameInfo.end_ip == 0)
50 1.1 joerg return _URC_FATAL_PHASE1_ERROR;
51 1.1 joerg
52 1.1 joerg if (frameInfo.handler == 0)
53 1.1 joerg continue; // No personality routine, so try next frame.
54 1.1 joerg
55 1.1 joerg __personality_routine p = (__personality_routine)(frameInfo.handler);
56 1.1 joerg _Unwind_Reason_Code result = (*p)(1, _UA_SEARCH_PHASE, exc->exception_class,
57 1.1 joerg exc, (struct _Unwind_Context *)(&cursor));
58 1.1 joerg
59 1.1 joerg switch (result) {
60 1.1 joerg case _URC_HANDLER_FOUND:
61 1.1 joerg // This is either a catch clause or a local variable
62 1.1 joerg // with destructor.
63 1.1 joerg // Stop search and remember the frame for phase 2.
64 1.1 joerg exc->private_2 = cursor.getSP();
65 1.1 joerg return _URC_NO_REASON;
66 1.1 joerg
67 1.1 joerg case _URC_CONTINUE_UNWIND:
68 1.1 joerg // Continue unwinding
69 1.1 joerg break;
70 1.1 joerg
71 1.1 joerg default:
72 1.1 joerg // Bad personality routine.
73 1.1 joerg return _URC_FATAL_PHASE1_ERROR;
74 1.1 joerg }
75 1.1 joerg }
76 1.1 joerg }
77 1.1 joerg
78 1.1 joerg static _Unwind_Reason_Code unwind_phase2(ThisUnwindCursor &cursor,
79 1.1 joerg struct _Unwind_Exception *exc) {
80 1.1 joerg cursor.setInfoBasedOnIPRegister();
81 1.1 joerg
82 1.1 joerg // Walk frames until the frame selected in phase 1 is reached.
83 1.1 joerg for (;;) {
84 1.1 joerg // Get next frame.
85 1.1 joerg // First frame is _Unwind_RaiseException and skipped.
86 1.1 joerg switch (cursor.step()) {
87 1.1 joerg case UNW_STEP_END:
88 1.1 joerg return _URC_END_OF_STACK;
89 1.1 joerg case UNW_STEP_FAILED:
90 1.1 joerg return _URC_FATAL_PHASE2_ERROR;
91 1.1 joerg case UNW_STEP_SUCCESS:
92 1.1 joerg break;
93 1.1 joerg }
94 1.1 joerg
95 1.1 joerg unw_proc_info_t frameInfo;
96 1.1 joerg cursor.getInfo(&frameInfo);
97 1.1 joerg if (frameInfo.end_ip == 0)
98 1.1 joerg return _URC_FATAL_PHASE2_ERROR;
99 1.1 joerg
100 1.1 joerg if (frameInfo.handler == 0)
101 1.1 joerg continue; // No personality routine, continue.
102 1.1 joerg
103 1.1 joerg uintptr_t sp = cursor.getSP();
104 1.1 joerg
105 1.1 joerg _Unwind_Action action = _UA_CLEANUP_PHASE;
106 1.1 joerg // If this frame was selected in phase 1,
107 1.1 joerg // inform the personality routine.
108 1.1 joerg if (sp == exc->private_2)
109 1.1 joerg action = (_Unwind_Action)(action | _UA_HANDLER_FRAME);
110 1.1 joerg __personality_routine p = (__personality_routine)(frameInfo.handler);
111 1.1 joerg _Unwind_Reason_Code result = (*p)(1, action, exc->exception_class, exc,
112 1.1 joerg (struct _Unwind_Context *)(&cursor));
113 1.1 joerg switch (result) {
114 1.1 joerg case _URC_CONTINUE_UNWIND:
115 1.1 joerg // Continue unwinding unless the selected frame passed.
116 1.1 joerg if (sp == exc->private_2)
117 1.1 joerg return _URC_FATAL_PHASE2_ERROR;
118 1.1 joerg break;
119 1.1 joerg case _URC_INSTALL_CONTEXT:
120 1.1 joerg // Transfer control to landing pad.
121 1.1 joerg cursor.jumpto();
122 1.1 joerg default:
123 1.1 joerg // Bad personality routine.
124 1.1 joerg return _URC_FATAL_PHASE2_ERROR;
125 1.1 joerg }
126 1.1 joerg }
127 1.1 joerg }
128 1.1 joerg
129 1.1 joerg static _Unwind_Reason_Code unwind_phase2_forced(ThisUnwindCursor &cursor,
130 1.1 joerg struct _Unwind_Exception *exc,
131 1.1 joerg _Unwind_Stop_Fn stop,
132 1.1 joerg void *stop_arg) {
133 1.1 joerg _Unwind_Action action;
134 1.1 joerg cursor.setInfoBasedOnIPRegister();
135 1.1 joerg
136 1.1 joerg // Walk frames until the frame selected in phase 1 is reached.
137 1.1 joerg for (;;) {
138 1.1 joerg // Get next frame.
139 1.1 joerg // First frame is _Unwind_RaiseException and skipped.
140 1.1 joerg switch (cursor.step()) {
141 1.1 joerg case UNW_STEP_END:
142 1.1 joerg case UNW_STEP_FAILED:
143 1.1 joerg // End of stack or error condition.
144 1.1 joerg // Call the stop function one last time.
145 1.1 joerg action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE |
146 1.1 joerg _UA_END_OF_STACK);
147 1.1 joerg (*stop)(1, action, exc->exception_class, exc,
148 1.1 joerg (struct _Unwind_Context *)(&cursor), stop_arg);
149 1.1 joerg
150 1.1 joerg // Didn't stop at the expected frame, so return error.
151 1.1 joerg return _URC_FATAL_PHASE2_ERROR;
152 1.1 joerg
153 1.1 joerg case UNW_STEP_SUCCESS:
154 1.1 joerg break;
155 1.1 joerg }
156 1.1 joerg
157 1.1 joerg unw_proc_info_t frameInfo;
158 1.1 joerg cursor.getInfo(&frameInfo);
159 1.1 joerg if (frameInfo.end_ip == 0)
160 1.1 joerg return _URC_FATAL_PHASE2_ERROR;
161 1.1 joerg
162 1.1 joerg // Call stop function for each frame
163 1.1 joerg action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
164 1.1 joerg _Unwind_Reason_Code result =
165 1.1 joerg (*stop)(1, action, exc->exception_class, exc,
166 1.1 joerg (struct _Unwind_Context *)(&cursor), stop_arg);
167 1.1 joerg if (result != _URC_NO_REASON)
168 1.1 joerg return _URC_FATAL_PHASE2_ERROR;
169 1.1 joerg
170 1.1 joerg if (frameInfo.handler == 0)
171 1.1 joerg continue; // No personality routine, continue.
172 1.1 joerg
173 1.1 joerg __personality_routine p = (__personality_routine)(frameInfo.handler);
174 1.1 joerg result = (*p)(1, action, exc->exception_class, exc,
175 1.1 joerg (struct _Unwind_Context *)(&cursor));
176 1.1 joerg
177 1.1 joerg switch (result) {
178 1.1 joerg case _URC_CONTINUE_UNWIND:
179 1.1 joerg // Destructors called, continue.
180 1.1 joerg break;
181 1.1 joerg case _URC_INSTALL_CONTEXT:
182 1.1 joerg // Transfer control to landing pad.
183 1.1 joerg cursor.jumpto();
184 1.1 joerg default:
185 1.1 joerg // Bad personality routine.
186 1.1 joerg return _URC_FATAL_PHASE2_ERROR;
187 1.1 joerg }
188 1.1 joerg }
189 1.1 joerg }
190 1.1 joerg
191 1.1 joerg _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) {
192 1.8 joerg NativeUnwindRegisters registers;
193 1.1 joerg ThisUnwindCursor cursor1(registers, sThisAddressSpace);
194 1.1 joerg ThisUnwindCursor cursor2(registers, sThisAddressSpace);
195 1.1 joerg
196 1.1 joerg // Mark this as a non-forced unwind for _Unwind_Resume().
197 1.1 joerg exc->private_1 = 0;
198 1.1 joerg exc->private_2 = 0;
199 1.1 joerg
200 1.1 joerg // Phase 1: searching.
201 1.1 joerg _Unwind_Reason_Code phase1 = unwind_phase1(cursor1, exc);
202 1.1 joerg if (phase1 != _URC_NO_REASON)
203 1.1 joerg return phase1;
204 1.1 joerg
205 1.1 joerg // Phase 2: cleaning up.
206 1.1 joerg return unwind_phase2(cursor2, exc);
207 1.1 joerg }
208 1.1 joerg
209 1.1 joerg _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exc,
210 1.1 joerg _Unwind_Stop_Fn stop, void *stop_arg) {
211 1.8 joerg NativeUnwindRegisters registers;
212 1.1 joerg ThisUnwindCursor cursor(registers, sThisAddressSpace);
213 1.1 joerg
214 1.1 joerg // Mark this as forced unwind for _Unwind_Resume().
215 1.1 joerg exc->private_1 = (uintptr_t)stop;
216 1.1 joerg exc->private_2 = (uintptr_t)stop_arg;
217 1.1 joerg
218 1.1 joerg return unwind_phase2_forced(cursor, exc, stop, stop_arg);
219 1.1 joerg }
220 1.1 joerg
221 1.1 joerg void _Unwind_Resume(struct _Unwind_Exception *exc) {
222 1.8 joerg NativeUnwindRegisters registers;
223 1.1 joerg ThisUnwindCursor cursor(registers, sThisAddressSpace);
224 1.1 joerg
225 1.1 joerg if (exc->private_1 != 0)
226 1.1 joerg unwind_phase2_forced(cursor, exc, (_Unwind_Stop_Fn)exc->private_1,
227 1.1 joerg (void *)exc->private_2);
228 1.1 joerg else
229 1.1 joerg unwind_phase2(cursor, exc);
230 1.1 joerg abort();
231 1.1 joerg }
232 1.1 joerg
233 1.1 joerg _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *exc) {
234 1.1 joerg // This is a re-throw, if this is a non-forced unwind
235 1.1 joerg // and the stopping place was found.
236 1.1 joerg // In that case, call _Unwind_RaiseException() as if
237 1.1 joerg // it was a new exception.
238 1.1 joerg
239 1.1 joerg if (exc->private_1 != 0)
240 1.1 joerg _Unwind_Resume(exc);
241 1.1 joerg
242 1.1 joerg // This can return if there is no catch clause.
243 1.1 joerg // In that case, __cxa_rethrow is expected to call std::terminate().
244 1.1 joerg return _Unwind_RaiseException(exc);
245 1.1 joerg }
246 1.1 joerg
247 1.1 joerg void _Unwind_DeleteException(struct _Unwind_Exception *exc) {
248 1.1 joerg if (exc->exception_cleanup != NULL)
249 1.1 joerg (*exc->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
250 1.1 joerg }
251 1.1 joerg
252 1.1 joerg uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) {
253 1.1 joerg ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
254 1.1 joerg return cursor->getReg(index);
255 1.1 joerg }
256 1.1 joerg
257 1.1 joerg void _Unwind_SetGR(struct _Unwind_Context *context, int index,
258 1.1 joerg uintptr_t new_value) {
259 1.1 joerg ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
260 1.1 joerg cursor->setReg(index, new_value);
261 1.1 joerg }
262 1.1 joerg
263 1.1 joerg uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
264 1.1 joerg ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
265 1.1 joerg return cursor->getIP();
266 1.1 joerg }
267 1.1 joerg
268 1.3 joerg uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *isSignalFrame) {
269 1.3 joerg ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
270 1.3 joerg *isSignalFrame = cursor->isSignalFrame() ? 1 : 0;
271 1.3 joerg return cursor->getIP();
272 1.3 joerg }
273 1.3 joerg
274 1.1 joerg void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t new_value) {
275 1.1 joerg ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
276 1.1 joerg cursor->setIP(new_value);
277 1.1 joerg unw_proc_info_t info;
278 1.1 joerg cursor->getInfo(&info);
279 1.1 joerg cursor->setInfoBasedOnIPRegister(false);
280 1.10 joerg if (info.extra_args)
281 1.10 joerg cursor->setSP(cursor->getSP() + info.extra_args);
282 1.1 joerg }
283 1.1 joerg
284 1.1 joerg uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) {
285 1.1 joerg ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
286 1.1 joerg unw_proc_info_t frameInfo;
287 1.1 joerg cursor->getInfo(&frameInfo);
288 1.1 joerg return frameInfo.end_ip ? frameInfo.start_ip : 0;
289 1.1 joerg }
290 1.1 joerg
291 1.1 joerg uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
292 1.1 joerg ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
293 1.1 joerg unw_proc_info_t frameInfo;
294 1.1 joerg cursor->getInfo(&frameInfo);
295 1.1 joerg return frameInfo.end_ip ? frameInfo.lsda : 0;
296 1.1 joerg }
297 1.1 joerg
298 1.1 joerg _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
299 1.8 joerg NativeUnwindRegisters registers;
300 1.1 joerg ThisUnwindCursor cursor(registers, sThisAddressSpace);
301 1.1 joerg cursor.setInfoBasedOnIPRegister();
302 1.1 joerg
303 1.1 joerg // Walk each frame.
304 1.1 joerg while (true) {
305 1.1 joerg
306 1.1 joerg // Ask libuwind to get next frame (skip over first frame which is
307 1.1 joerg // _Unwind_Backtrace()).
308 1.1 joerg if (cursor.step() != UNW_STEP_SUCCESS)
309 1.1 joerg return _URC_END_OF_STACK;
310 1.1 joerg
311 1.1 joerg // Call trace function with this frame.
312 1.1 joerg _Unwind_Reason_Code result =
313 1.1 joerg (*callback)((struct _Unwind_Context *)(&cursor), ref);
314 1.1 joerg if (result != _URC_NO_REASON)
315 1.1 joerg return result;
316 1.1 joerg }
317 1.1 joerg }
318 1.1 joerg
319 1.1 joerg uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
320 1.1 joerg ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
321 1.1 joerg return cursor->getSP();
322 1.1 joerg }
323 1.1 joerg
324 1.1 joerg void *_Unwind_FindEnclosingFunction(void *pc) {
325 1.8 joerg NativeUnwindRegisters registers;
326 1.1 joerg ThisUnwindCursor cursor(registers, sThisAddressSpace);
327 1.1 joerg
328 1.1 joerg unw_proc_info_t info;
329 1.1 joerg cursor.setIP((uintptr_t)pc);
330 1.1 joerg cursor.setInfoBasedOnIPRegister();
331 1.1 joerg
332 1.1 joerg cursor.getInfo(&info);
333 1.1 joerg return info.end_ip ? (void *)info.start_ip : NULL;
334 1.1 joerg }
335 1.1 joerg
336 1.9 joerg void *_Unwind_Find_FDE(void *pc, struct dwarf_eh_bases *bases) {
337 1.9 joerg NativeUnwindRegisters registers;
338 1.9 joerg ThisUnwindCursor cursor(registers, sThisAddressSpace);
339 1.9 joerg
340 1.9 joerg unw_proc_info_t info;
341 1.9 joerg cursor.setIP((uintptr_t)pc);
342 1.9 joerg cursor.setInfoBasedOnIPRegister();
343 1.9 joerg
344 1.9 joerg cursor.getInfo(&info);
345 1.9 joerg if (info.end_ip == 0)
346 1.9 joerg return NULL;
347 1.9 joerg bases->tbase = 0; /* Not supported */
348 1.9 joerg bases->dbase = (void *)info.data_base;
349 1.9 joerg bases->func = (void *)info.start_ip;
350 1.9 joerg return (void *)info.unwind_info;
351 1.9 joerg }
352 1.9 joerg
353 1.1 joerg uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) {
354 1.1 joerg ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
355 1.1 joerg unw_proc_info_t frameInfo;
356 1.1 joerg cursor->getInfo(&frameInfo);
357 1.1 joerg return frameInfo.data_base;
358 1.1 joerg }
359 1.1 joerg
360 1.1 joerg uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) { return 0; }
361 1.1 joerg
362 1.1 joerg void __register_frame(const void *fde) {
363 1.1 joerg MyCFIParser::pint_t pcStart, pcEnd;
364 1.1 joerg
365 1.1 joerg MyCFIParser::findPCRange(sThisAddressSpace, (uintptr_t)fde, pcStart, pcEnd);
366 1.1 joerg if (pcEnd == 0)
367 1.1 joerg return; // Bad FDE.
368 1.1 joerg
369 1.1 joerg sThisAddressSpace.addFDE(pcStart, pcEnd, (uintptr_t)fde);
370 1.1 joerg }
371 1.1 joerg
372 1.1 joerg void __register_frame_info(const void *ehframe, void *storage) {
373 1.1 joerg sThisAddressSpace.setLazyReload();
374 1.1 joerg }
375 1.1 joerg
376 1.1 joerg void __deregister_frame(const void *fde) {
377 1.1 joerg MyCFIParser::pint_t pcStart, pcEnd;
378 1.1 joerg
379 1.1 joerg MyCFIParser::findPCRange(sThisAddressSpace, (uintptr_t)fde, pcStart, pcEnd);
380 1.1 joerg if (pcEnd == 0)
381 1.1 joerg return; // Bad FDE.
382 1.1 joerg
383 1.1 joerg sThisAddressSpace.removeFDE(pcStart, pcEnd, (uintptr_t)fde);
384 1.1 joerg }
385 1.1 joerg
386 1.1 joerg void *__deregister_frame_info(const void *ehFrameStart) {
387 1.1 joerg sThisAddressSpace.removeDSO((LocalAddressSpace::pint_t)ehFrameStart);
388 1.1 joerg return NULL;
389 1.1 joerg }
390