1b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//===--------------------------- Unwind-sjlj.c ----------------------------===//
2b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
3b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//                     The LLVM Compiler Infrastructure
4b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
5b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// This file is dual licensed under the MIT and the University of Illinois Open
6b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// Source Licenses. See LICENSE.TXT for details.
7b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
8b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
9b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//  Implements setjump-longjump based C++ exceptions
10b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
11b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//===----------------------------------------------------------------------===//
12b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
13b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <unwind.h>
14b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
15b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <stdint.h>
16b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <stdbool.h>
17b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <stdlib.h>
18b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
19b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "config.h"
20b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "unwind_ext.h"
21b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
22b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
23b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// 32-bit iOS uses setjump/longjump based C++ exceptions.
24b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// Other architectures use "zero cost" exceptions.
25b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
26b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// With SJLJ based exceptions, any function that has a catch clause or needs to
27b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// do any clean up when an exception propagates through it, needs to call
28b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// _Unwind_SjLj_Register() at the start of the function and
29b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// _Unwind_SjLj_Unregister() at the end.  The register function is called with
30b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// the address of a block of memory in the function's stack frame.  The runtime
31b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// keeps a linked list (stack) of these blocks - one per thread.  The calling
32b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// function also sets the personality and lsda fields of the block.
33b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
34b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
35b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_BUILD_SJLJ_APIS
36b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
37b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikstruct _Unwind_FunctionContext {
38b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // next function in stack of handlers
39b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  struct _Unwind_FunctionContext *prev;
40b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
41b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // set by calling function before registering to be the landing pad
42b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uintptr_t                       resumeLocation;
43b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
44b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // set by personality handler to be parameters passed to landing pad function
45b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uintptr_t                       resumeParameters[4];
46b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
47b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // set by calling function before registering
48b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  __personality_routine           personality; // arm offset=24
49b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uintptr_t                       lsda;        // arm offset=28
50b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
51b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // variable length array, contains registers to restore
52b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // 0 = r7, 1 = pc, 2 = sp
53b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  void                           *jbuf[];
54b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
55b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
56b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
57b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called at start of each function that catches exceptions
58b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT void
59b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) {
60b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  fc->prev = __Unwind_SjLj_GetTopOfFunctionStack();
61b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  __Unwind_SjLj_SetTopOfFunctionStack(fc);
62b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
63b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
64b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
65b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called at end of each function that catches exceptions
66b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT void
67b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) {
68b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  __Unwind_SjLj_SetTopOfFunctionStack(fc->prev);
69b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
70b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
71b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
72b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikstatic _Unwind_Reason_Code
73b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikunwind_phase1(struct _Unwind_Exception *exception_object) {
74b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
75b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p\n", c);
76b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
77b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // walk each frame looking for a place to stop
78b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {
79b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
80b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // check for no more frames
81b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (c == NULL) {
82b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached "
83b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                 "bottom => _URC_END_OF_STACK\n",
84b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                  exception_object);
85b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return _URC_END_OF_STACK;
86b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
87b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
88b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p\n", c);
89b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // if there is a personality routine, ask it if it will want to stop at this
90b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // frame
91b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (c->personality != NULL) {
92b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling "
93b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                "personality function %p\n",
94b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                 exception_object, c->personality);
95b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _Unwind_Reason_Code personalityResult = (*c->personality)(
96b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          1, _UA_SEARCH_PHASE, exception_object->exception_class,
97b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          exception_object, (struct _Unwind_Context *)c);
98b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      switch (personalityResult) {
99b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      case _URC_HANDLER_FOUND:
100b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // found a catch clause or locals that need destructing in this frame
101b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // stop search and remember function context
102b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        handlerNotFound = false;
103b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        exception_object->private_2 = (uintptr_t) c;
104b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
105b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                   "_URC_HANDLER_FOUND\n", exception_object);
106b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        return _URC_NO_REASON;
107b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
108b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      case _URC_CONTINUE_UNWIND:
109b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
110b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                   "_URC_CONTINUE_UNWIND\n", exception_object);
111b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // continue unwinding
112b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
113b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
114b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      default:
115b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // something went wrong
116b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _LIBUNWIND_TRACE_UNWINDING(
117b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
118b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            exception_object);
119b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        return _URC_FATAL_PHASE1_ERROR;
120b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
121b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
122b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
123b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return _URC_NO_REASON;
124b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
125b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
126b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
127b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikstatic _Unwind_Reason_Code
128b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikunwind_phase2(struct _Unwind_Exception *exception_object) {
129b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object);
130b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
131b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // walk each frame until we reach where search phase said to stop
132b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
133b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  while (true) {
134b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p\n",
135b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              exception_object, c);
136b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
137b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // check for no more frames
138b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (c == NULL) {
139b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
140b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                "bottom => _URC_END_OF_STACK\n",
141b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                 exception_object);
142b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return _URC_END_OF_STACK;
143b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
144b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
145b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // if there is a personality routine, tell it we are unwinding
146b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (c->personality != NULL) {
147b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _Unwind_Action action = _UA_CLEANUP_PHASE;
148b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if ((uintptr_t) c == exception_object->private_2)
149b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        action = (_Unwind_Action)(
150b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            _UA_CLEANUP_PHASE |
151b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            _UA_HANDLER_FRAME); // tell personality this was the frame it marked
152b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                // in phase 1
153b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _Unwind_Reason_Code personalityResult =
154b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          (*c->personality)(1, action, exception_object->exception_class,
155b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                            exception_object, (struct _Unwind_Context *)c);
156b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      switch (personalityResult) {
157b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      case _URC_CONTINUE_UNWIND:
158b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // continue unwinding
159b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _LIBUNWIND_TRACE_UNWINDING(
160b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
161b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            exception_object);
162b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        if ((uintptr_t) c == exception_object->private_2) {
163b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          // phase 1 said we would stop at this frame, but we did not...
164b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _LIBUNWIND_ABORT("during phase1 personality function said it would "
165b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                           "stop here, but now if phase2 it did not stop here");
166b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        }
167b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
168b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      case _URC_INSTALL_CONTEXT:
169b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): "
170b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                  "_URC_INSTALL_CONTEXT, will resume at "
171b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                  "landing pad %p\n",
172b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                  exception_object, c->jbuf[1]);
173b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // personality routine says to transfer control to landing pad
174b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // we may get control back if landing pad calls _Unwind_Resume()
175b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        __Unwind_SjLj_SetTopOfFunctionStack(c);
176b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        __builtin_longjmp(c->jbuf, 1);
177b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // unw_resume() only returns if there was an error
178b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        return _URC_FATAL_PHASE2_ERROR;
179b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      default:
180b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // something went wrong
181b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
182b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                      personalityResult);
183b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        return _URC_FATAL_PHASE2_ERROR;
184b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
185b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
186b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    c = c->prev;
187b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
188b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
189b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // clean up phase did not resume at the frame that the search phase said it
190b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // would
191b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return _URC_FATAL_PHASE2_ERROR;
192b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
193b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
194b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
195b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikstatic _Unwind_Reason_Code
196b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikunwind_phase2_forced(struct _Unwind_Exception *exception_object,
197b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                     _Unwind_Stop_Fn stop, void *stop_parameter) {
198b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // walk each frame until we reach where search phase said to stop
199b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
200b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  while (true) {
201b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
202b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // get next frame (skip over first which is _Unwind_RaiseException)
203b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (c == NULL) {
204b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
205b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                 "bottom => _URC_END_OF_STACK\n",
206b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                 exception_object);
207b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return _URC_END_OF_STACK;
208b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
209b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
210b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // call stop function at each frame
211b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _Unwind_Action action =
212b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
213b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _Unwind_Reason_Code stopResult =
214b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        (*stop)(1, action, exception_object->exception_class, exception_object,
215b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                (struct _Unwind_Context *)c, stop_parameter);
216b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
217b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                               "stop function returned %d\n",
218b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                exception_object, stopResult);
219b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (stopResult != _URC_NO_REASON) {
220b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
221b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                 "stopped by stop function\n",
222b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                  exception_object);
223b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return _URC_FATAL_PHASE2_ERROR;
224b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
225b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
226b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // if there is a personality routine, tell it we are unwinding
227b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (c->personality != NULL) {
228b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      __personality_routine p = (__personality_routine) c->personality;
229b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
230b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                 "calling personality function %p\n",
231b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                  exception_object, p);
232b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _Unwind_Reason_Code personalityResult =
233b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          (*p)(1, action, exception_object->exception_class, exception_object,
234b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik               (struct _Unwind_Context *)c);
235b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      switch (personalityResult) {
236b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      case _URC_CONTINUE_UNWIND:
237b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p):  "
238b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                   "personality returned _URC_CONTINUE_UNWIND\n",
239b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                    exception_object);
240b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // destructors called, continue unwinding
241b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
242b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      case _URC_INSTALL_CONTEXT:
243b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
244b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                   "personality returned _URC_INSTALL_CONTEXT\n",
245b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                    exception_object);
246b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // we may get control back if landing pad calls _Unwind_Resume()
247b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        __Unwind_SjLj_SetTopOfFunctionStack(c);
248b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        __builtin_longjmp(c->jbuf, 1);
249b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
250b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      default:
251b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // something went wrong
252b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
253b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                   "personality returned %d, "
254b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                   "_URC_FATAL_PHASE2_ERROR\n",
255b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                    exception_object, personalityResult);
256b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        return _URC_FATAL_PHASE2_ERROR;
257b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
258b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
259b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    c = c->prev;
260b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
261b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
262b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // call stop function one last time and tell it we've reached the end of the
263b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // stack
264b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
265b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                        "function with _UA_END_OF_STACK\n",
266b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                        exception_object);
267b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_Action lastAction =
268b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
269b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  (*stop)(1, lastAction, exception_object->exception_class, exception_object,
270b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          (struct _Unwind_Context *)c, stop_parameter);
271b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
272b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // clean up phase did not resume at the frame that the search phase said it
273b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // would
274b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return _URC_FATAL_PHASE2_ERROR;
275b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
276b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
277b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
278b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by __cxa_throw.  Only returns if there is a fatal error
279b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT _Unwind_Reason_Code
280b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) {
281b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)\n", exception_object);
282b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
283b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // mark that this is a non-forced unwind, so _Unwind_Resume() can do the right
284b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // thing
285b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  exception_object->private_1 = 0;
286b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  exception_object->private_2 = 0;
287b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
288b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // phase 1: the search phase
289b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_Reason_Code phase1 = unwind_phase1(exception_object);
290b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (phase1 != _URC_NO_REASON)
291b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return phase1;
292b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
293b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // phase 2: the clean up phase
294b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return unwind_phase2(exception_object);
295b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
296b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
297b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
298b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
299b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// When _Unwind_RaiseException() is in phase2, it hands control
300b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// to the personality function at each frame.  The personality
301b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// may force a jump to a landing pad in that function, the landing
302b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// pad code may then call _Unwind_Resume() to continue with the
303b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
304b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// geneated user code.  All other _Unwind_* routines are called
305b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// by the C++ runtime __cxa_* routines.
306b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik///
307b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Re-throwing an exception is implemented by having the code call
308b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
309b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT void
310b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) {
311b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)\n", exception_object);
312b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
313b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (exception_object->private_1 != 0)
314b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    unwind_phase2_forced(exception_object,
315b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                         (_Unwind_Stop_Fn) exception_object->private_1,
316b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                         (void *)exception_object->private_2);
317b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  else
318b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    unwind_phase2(exception_object);
319b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
320b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // clients assume _Unwind_Resume() does not return, so all we can do is abort.
321b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_ABORT("_Unwind_SjLj_Resume() can't return");
322b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
323b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
324b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
325b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik///  Called by __cxa_rethrow().
326b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT _Unwind_Reason_Code
327b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) {
328b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), "
329b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                             "private_1=%ld\n",
330b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              exception_object, exception_object->private_1);
331b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // If this is non-forced and a stopping place was found, then this is a
332b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // re-throw.
333b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // Call _Unwind_RaiseException() as if this was a new exception.
334b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (exception_object->private_1 == 0) {
335b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _Unwind_SjLj_RaiseException(exception_object);
336b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // should return if there is no catch clause, so that __cxa_rethrow can call
337b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // std::terminate()
338b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
339b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
340b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // Call through to _Unwind_Resume() which distiguishes between forced and
341b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // regular exceptions.
342b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_SjLj_Resume(exception_object);
343b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called "
344b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                    "_Unwind_SjLj_Resume() which unexpectedly returned");
345b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
346b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
347b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
348b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler during phase 2 to get LSDA for current frame.
349b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT uintptr_t
350b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
351b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
352b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) "
353b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                             "=> 0x%0lX\n",  context, ufc->lsda);
354b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return ufc->lsda;
355b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
356b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
357b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
358b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler during phase 2 to get register values.
359b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
360b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                          int index) {
361b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)\n",
362b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                             context, index);
363b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
364b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return ufc->resumeParameters[index];
365b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
366b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
367b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
368b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler during phase 2 to alter register values.
369b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
370b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                     uintptr_t new_value) {
371b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)\n"
372b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                            , context, index, new_value);
373b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
374b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  ufc->resumeParameters[index] = new_value;
375b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
376b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
377b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
378b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler during phase 2 to get instruction pointer.
379b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
380b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
381b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX\n", context,
382b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                  ufc->resumeLocation + 1);
383b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return ufc->resumeLocation + 1;
384b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
385b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
386b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
387b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler during phase 2 to get instruction pointer.
388b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// ipBefore is a boolean that says if IP is already adjusted to be the call
389b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// site address.  Normally IP is the return address.
390b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
391b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                              int *ipBefore) {
392b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
393b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  *ipBefore = 0;
394b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX\n",
395b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                             context, ipBefore, ufc->resumeLocation + 1);
396b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return ufc->resumeLocation + 1;
397b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
398b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
399b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
400b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler during phase 2 to alter instruction pointer.
401b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
402b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                     uintptr_t new_value) {
403b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)\n",
404b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                             context, new_value);
405b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
406b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  ufc->resumeLocation = new_value - 1;
407b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
408b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
409b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
410b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler during phase 2 to find the start of the
411b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// function.
412b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT uintptr_t
413b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_Unwind_GetRegionStart(struct _Unwind_Context *context) {
414b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // Not supported or needed for sjlj based unwinding
415b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  (void)context;
416b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)\n", context);
417b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return 0;
418b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
419b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
420b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
421b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler during phase 2 if a foreign exception
422b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// is caught.
423b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT void
424b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_Unwind_DeleteException(struct _Unwind_Exception *exception_object) {
425b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n",
426b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              exception_object);
427b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (exception_object->exception_cleanup != NULL)
428b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
429b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                           exception_object);
430b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
431b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
432b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
433b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
434b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler during phase 2 to get base address for data
435b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// relative encodings.
436b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT uintptr_t
437b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
438b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // Not supported or needed for sjlj based unwinding
439b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  (void)context;
440b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)\n", context);
441b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
442b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
443b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
444b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
445b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler during phase 2 to get base address for text
446b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// relative encodings.
447b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT uintptr_t
448b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
449b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // Not supported or needed for sjlj based unwinding
450b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  (void)context;
451b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)\n", context);
452b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
453b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
454b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
455b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
456b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Called by personality handler to get "Call Frame Area" for current frame.
457b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
458b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)\n", context);
459b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (context != NULL) {
460b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
461b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // Setjmp/longjmp based exceptions don't have a true CFA.
462b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // Instead, the SP in the jmpbuf is the closest approximation.
463b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return (uintptr_t) ufc->jbuf[2];
464b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
465b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return 0;
466b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
467b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
468b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif // _LIBUNWIND_BUILD_SJLJ_APIS
469