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