1//===------------------------- UnwindLevel1.c -----------------------------===//
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// using libunwind
12//
13//===----------------------------------------------------------------------===//
14
15#include <stdint.h>
16#include <stdbool.h>
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20
21#include "libunwind.h"
22#include "unwind.h"
23#include "config.h"
24
25#if _LIBUNWIND_BUILD_ZERO_COST_APIS && !LIBCXXABI_ARM_EHABI
26
27static _Unwind_Reason_Code
28unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
29  unw_cursor_t cursor1;
30  unw_init_local(&cursor1, uc);
31
32  // Walk each frame looking for a place to stop.
33  for (bool handlerNotFound = true; handlerNotFound;) {
34
35    // Ask libuwind to get next frame (skip over first which is
36    // _Unwind_RaiseException).
37    int stepResult = unw_step(&cursor1);
38    if (stepResult == 0) {
39      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
40                            "bottom => _URC_END_OF_STACK\n",
41                            exception_object);
42      return _URC_END_OF_STACK;
43    } else if (stepResult < 0) {
44      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => "
45                            "_URC_FATAL_PHASE1_ERROR\n",
46                            exception_object);
47      return _URC_FATAL_PHASE1_ERROR;
48    }
49
50    // See if frame has code to run (has personality routine).
51    unw_proc_info_t frameInfo;
52    unw_word_t sp;
53    if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) {
54      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
55                            "failed => _URC_FATAL_PHASE1_ERROR\n",
56                            exception_object);
57      return _URC_FATAL_PHASE1_ERROR;
58    }
59
60    // When tracing, print state information.
61    if (_LIBUNWIND_TRACING_UNWINDING) {
62      char functionName[512];
63      unw_word_t offset;
64      if ((unw_get_proc_name(&cursor1, functionName, 512, &offset) !=
65           UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip))
66        strcpy(functionName, ".anonymous.");
67      unw_word_t pc;
68      unw_get_reg(&cursor1, UNW_REG_IP, &pc);
69      _LIBUNWIND_TRACE_UNWINDING(
70          "unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, "
71          "lsda=0x%llX, personality=0x%llX\n",
72          exception_object, pc, frameInfo.start_ip, functionName,
73          frameInfo.lsda, frameInfo.handler);
74    }
75
76    // If there is a personality routine, ask it if it will want to stop at
77    // this frame.
78    if (frameInfo.handler != 0) {
79      __personality_routine p =
80          (__personality_routine)(long)(frameInfo.handler);
81      _LIBUNWIND_TRACE_UNWINDING(
82          "unwind_phase1(ex_ojb=%p): calling personality function %p\n",
83          exception_object, p);
84      _Unwind_Reason_Code personalityResult =
85          (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
86               exception_object, (struct _Unwind_Context *)(&cursor1));
87      switch (personalityResult) {
88      case _URC_HANDLER_FOUND:
89        // found a catch clause or locals that need destructing in this frame
90        // stop search and remember stack pointer at the frame
91        handlerNotFound = false;
92        unw_get_reg(&cursor1, UNW_REG_SP, &sp);
93        exception_object->private_2 = (uintptr_t)sp;
94        _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
95                                   "_URC_HANDLER_FOUND \n",
96                                   exception_object);
97        return _URC_NO_REASON;
98
99      case _URC_CONTINUE_UNWIND:
100        _LIBUNWIND_TRACE_UNWINDING(
101            "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
102            exception_object);
103        // continue unwinding
104        break;
105
106      default:
107        // something went wrong
108        _LIBUNWIND_TRACE_UNWINDING(
109            "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
110            exception_object);
111        return _URC_FATAL_PHASE1_ERROR;
112      }
113    }
114  }
115  return _URC_NO_REASON;
116}
117
118
119static _Unwind_Reason_Code
120unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
121  unw_cursor_t cursor2;
122  unw_init_local(&cursor2, uc);
123
124  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object);
125
126  // Walk each frame until we reach where search phase said to stop.
127  while (true) {
128
129    // Ask libuwind to get next frame (skip over first which is
130    // _Unwind_RaiseException).
131    int stepResult = unw_step(&cursor2);
132    if (stepResult == 0) {
133      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
134                            "bottom => _URC_END_OF_STACK\n",
135                            exception_object);
136      return _URC_END_OF_STACK;
137    } else if (stepResult < 0) {
138      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => "
139                            "_URC_FATAL_PHASE1_ERROR\n",
140                            exception_object);
141      return _URC_FATAL_PHASE2_ERROR;
142    }
143
144    // Get info about this frame.
145    unw_word_t sp;
146    unw_proc_info_t frameInfo;
147    unw_get_reg(&cursor2, UNW_REG_SP, &sp);
148    if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
149      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
150                            "failed => _URC_FATAL_PHASE1_ERROR\n",
151                            exception_object);
152      return _URC_FATAL_PHASE2_ERROR;
153    }
154
155    // When tracing, print state information.
156    if (_LIBUNWIND_TRACING_UNWINDING) {
157      char functionName[512];
158      unw_word_t offset;
159      if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) !=
160           UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip))
161        strcpy(functionName, ".anonymous.");
162      _LIBUNWIND_TRACE_UNWINDING(
163          "unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, "
164          "lsda=0x%llX, personality=0x%llX\n",
165          exception_object, frameInfo.start_ip, functionName, sp,
166          frameInfo.lsda, frameInfo.handler);
167    }
168
169    // If there is a personality routine, tell it we are unwinding.
170    if (frameInfo.handler != 0) {
171      __personality_routine p =
172          (__personality_routine)(long)(frameInfo.handler);
173      _Unwind_Action action = _UA_CLEANUP_PHASE;
174      if (sp == exception_object->private_2) {
175        // Tell personality this was the frame it marked in phase 1.
176        action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
177      }
178       _Unwind_Reason_Code personalityResult =
179          (*p)(1, action, exception_object->exception_class, exception_object,
180               (struct _Unwind_Context *)(&cursor2));
181      switch (personalityResult) {
182      case _URC_CONTINUE_UNWIND:
183        // Continue unwinding
184        _LIBUNWIND_TRACE_UNWINDING(
185            "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
186            exception_object);
187        if (sp == exception_object->private_2) {
188          // Phase 1 said we would stop at this frame, but we did not...
189          _LIBUNWIND_ABORT("during phase1 personality function said it would "
190                           "stop here, but now in phase2 it did not stop here");
191        }
192        break;
193      case _URC_INSTALL_CONTEXT:
194        _LIBUNWIND_TRACE_UNWINDING(
195            "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n",
196            exception_object);
197        // Personality routine says to transfer control to landing pad.
198        // We may get control back if landing pad calls _Unwind_Resume().
199        if (_LIBUNWIND_TRACING_UNWINDING) {
200          unw_word_t pc;
201          unw_get_reg(&cursor2, UNW_REG_IP, &pc);
202          unw_get_reg(&cursor2, UNW_REG_SP, &sp);
203          _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering  "
204                                     "user code with ip=0x%llX, sp=0x%llX\n",
205                                     exception_object, pc, sp);
206        }
207        unw_resume(&cursor2);
208        // unw_resume() only returns if there was an error.
209        return _URC_FATAL_PHASE2_ERROR;
210      default:
211        // Personality routine returned an unknown result code.
212        _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
213                      personalityResult);
214        return _URC_FATAL_PHASE2_ERROR;
215      }
216    }
217  }
218
219  // Clean up phase did not resume at the frame that the search phase
220  // said it would...
221  return _URC_FATAL_PHASE2_ERROR;
222}
223
224static _Unwind_Reason_Code
225unwind_phase2_forced(unw_context_t *uc,
226                     _Unwind_Exception *exception_object,
227                     _Unwind_Stop_Fn stop, void *stop_parameter) {
228  unw_cursor_t cursor2;
229  unw_init_local(&cursor2, uc);
230
231  // Walk each frame until we reach where search phase said to stop
232  while (unw_step(&cursor2) > 0) {
233
234    // Update info about this frame.
235    unw_proc_info_t frameInfo;
236    if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
237      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
238                                 "failed => _URC_END_OF_STACK\n",
239                                 exception_object);
240      return _URC_FATAL_PHASE2_ERROR;
241    }
242
243    // When tracing, print state information.
244    if (_LIBUNWIND_TRACING_UNWINDING) {
245      char functionName[512];
246      unw_word_t offset;
247      if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) !=
248           UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip))
249        strcpy(functionName, ".anonymous.");
250      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p):  "
251                                 "start_ip=0x%llX, func=%s, lsda=0x%llX, "
252                                 " personality=0x%llX\n",
253                                 exception_object, frameInfo.start_ip,
254                                 functionName, frameInfo.lsda,
255                                 frameInfo.handler);
256    }
257
258    // Call stop function at each frame.
259    _Unwind_Action action =
260        (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
261    _Unwind_Reason_Code stopResult =
262        (*stop)(1, action, exception_object->exception_class, exception_object,
263                (struct _Unwind_Context *)(&cursor2), stop_parameter);
264    _LIBUNWIND_TRACE_UNWINDING(
265        "unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n",
266        exception_object, stopResult);
267    if (stopResult != _URC_NO_REASON) {
268      _LIBUNWIND_TRACE_UNWINDING(
269          "unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n",
270          exception_object);
271      return _URC_FATAL_PHASE2_ERROR;
272    }
273
274    // If there is a personality routine, tell it we are unwinding.
275    if (frameInfo.handler != 0) {
276      __personality_routine p =
277          (__personality_routine)(long)(frameInfo.handler);
278      _LIBUNWIND_TRACE_UNWINDING(
279          "unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n",
280          exception_object, p);
281      _Unwind_Reason_Code personalityResult =
282          (*p)(1, action, exception_object->exception_class, exception_object,
283               (struct _Unwind_Context *)(&cursor2));
284      switch (personalityResult) {
285      case _URC_CONTINUE_UNWIND:
286        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
287                                "personality  returned _URC_CONTINUE_UNWIND\n",
288                                 exception_object);
289        // Destructors called, continue unwinding
290        break;
291      case _URC_INSTALL_CONTEXT:
292        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
293                                  "personality returned _URC_INSTALL_CONTEXT\n",
294                                   exception_object);
295        // We may get control back if landing pad calls _Unwind_Resume().
296        unw_resume(&cursor2);
297        break;
298      default:
299        // Personality routine returned an unknown result code.
300        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
301                                   "personality returned %d, "
302                                   "_URC_FATAL_PHASE2_ERROR\n",
303                                   exception_object, personalityResult);
304        return _URC_FATAL_PHASE2_ERROR;
305      }
306    }
307  }
308
309  // Call stop function one last time and tell it we've reached the end
310  // of the stack.
311  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
312                        "function with _UA_END_OF_STACK\n",
313                        exception_object);
314  _Unwind_Action lastAction =
315      (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
316  (*stop)(1, lastAction, exception_object->exception_class, exception_object,
317          (struct _Unwind_Context *)(&cursor2), stop_parameter);
318
319  // Clean up phase did not resume at the frame that the search phase said it
320  // would.
321  return _URC_FATAL_PHASE2_ERROR;
322}
323
324
325/// Called by __cxa_throw.  Only returns if there is a fatal error.
326_LIBUNWIND_EXPORT _Unwind_Reason_Code
327_Unwind_RaiseException(_Unwind_Exception *exception_object) {
328  _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n",
329                             exception_object);
330  unw_context_t uc;
331  unw_getcontext(&uc);
332
333  // Mark that this is a non-forced unwind, so _Unwind_Resume()
334  // can do the right thing.
335  exception_object->private_1 = 0;
336  exception_object->private_2 = 0;
337
338  // phase 1: the search phase
339  _Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object);
340  if (phase1 != _URC_NO_REASON)
341    return phase1;
342
343  // phase 2: the clean up phase
344  return unwind_phase2(&uc, exception_object);
345}
346
347
348
349/// When _Unwind_RaiseException() is in phase2, it hands control
350/// to the personality function at each frame.  The personality
351/// may force a jump to a landing pad in that function, the landing
352/// pad code may then call _Unwind_Resume() to continue with the
353/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
354/// geneated user code.  All other _Unwind_* routines are called
355/// by the C++ runtime __cxa_* routines.
356///
357/// Note: re-throwing an exception (as opposed to continuing the unwind)
358/// is implemented by having the code call __cxa_rethrow() which
359/// in turn calls _Unwind_Resume_or_Rethrow().
360_LIBUNWIND_EXPORT void
361_Unwind_Resume(_Unwind_Exception *exception_object) {
362  _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", exception_object);
363  unw_context_t uc;
364  unw_getcontext(&uc);
365
366  if (exception_object->private_1 != 0)
367    unwind_phase2_forced(&uc, exception_object,
368                         (_Unwind_Stop_Fn) exception_object->private_1,
369                         (void *)exception_object->private_2);
370  else
371    unwind_phase2(&uc, exception_object);
372
373  // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
374  _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
375}
376
377
378
379/// Not used by C++.
380/// Unwinds stack, calling "stop" function at each frame.
381/// Could be used to implement longjmp().
382_LIBUNWIND_EXPORT _Unwind_Reason_Code
383_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
384                     _Unwind_Stop_Fn stop, void *stop_parameter) {
385  _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n",
386                  exception_object, stop);
387  unw_context_t uc;
388  unw_getcontext(&uc);
389
390  // Mark that this is a forced unwind, so _Unwind_Resume() can do
391  // the right thing.
392  exception_object->private_1 = (uintptr_t) stop;
393  exception_object->private_2 = (uintptr_t) stop_parameter;
394
395  // do it
396  return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
397}
398
399
400/// Called by personality handler during phase 2 to get LSDA for current frame.
401_LIBUNWIND_EXPORT uintptr_t
402_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
403  unw_cursor_t *cursor = (unw_cursor_t *)context;
404  unw_proc_info_t frameInfo;
405  uintptr_t result = 0;
406  if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
407    result = (uintptr_t)frameInfo.lsda;
408  _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p)"
409                             "=> 0x%lX\n", context, result);
410  if (result != 0) {
411    if (*((uint8_t *)result) != 0xFF)
412      _LIBUNWIND_DEBUG_LOG("lsda at 0x%lX does not start with 0xFF\n", result);
413  }
414  return result;
415}
416
417
418
419/// Called by personality handler during phase 2 to get register values.
420_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
421                                          int index) {
422  unw_cursor_t *cursor = (unw_cursor_t *)context;
423  unw_word_t result;
424  unw_get_reg(cursor, index, &result);
425  _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%llX\n",
426    context,
427                  index, (uint64_t) result);
428  return (uintptr_t)result;
429}
430
431
432
433/// Called by personality handler during phase 2 to alter register values.
434_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
435                                     uintptr_t new_value) {
436  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, "
437                             "value=0x%0llX)\n", context,
438                             index, (uint64_t) new_value);
439  unw_cursor_t *cursor = (unw_cursor_t *)context;
440  unw_set_reg(cursor, index, new_value);
441}
442
443
444
445/// Called by personality handler during phase 2 to get instruction pointer.
446_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
447  unw_cursor_t *cursor = (unw_cursor_t *)context;
448  unw_word_t result;
449  unw_get_reg(cursor, UNW_REG_IP, &result);
450  _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%llX\n", context,
451                             (uint64_t) result);
452  return (uintptr_t)result;
453}
454
455
456
457/// Called by personality handler during phase 2 to alter instruction pointer,
458/// such as setting where the landing pad is, so _Unwind_Resume() will
459/// start executing in the landing pad.
460_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
461                                     uintptr_t new_value) {
462  _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0llX)\n",
463                             context, (uint64_t) new_value);
464  unw_cursor_t *cursor = (unw_cursor_t *)context;
465  unw_set_reg(cursor, UNW_REG_IP, new_value);
466}
467
468
469/// Called by personality handler during phase 2 to find the start of the
470/// function.
471_LIBUNWIND_EXPORT uintptr_t
472_Unwind_GetRegionStart(struct _Unwind_Context *context) {
473  unw_cursor_t *cursor = (unw_cursor_t *)context;
474  unw_proc_info_t frameInfo;
475  uintptr_t result = 0;
476  if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
477    result = (uintptr_t)frameInfo.start_ip;
478  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%lX\n",
479                             context, result);
480  return result;
481}
482
483
484/// Called by personality handler during phase 2 if a foreign exception
485// is caught.
486_LIBUNWIND_EXPORT void
487_Unwind_DeleteException(_Unwind_Exception *exception_object) {
488  _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n",
489                              exception_object);
490  if (exception_object->exception_cleanup != NULL)
491    (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
492                                           exception_object);
493}
494
495#endif // _LIBUNWIND_BUILD_ZERO_COST_APIS && !LIBCXXABI_ARM_EHABI
496