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