1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8// Implements C++ ABI Exception Handling Level 1 as documented at:
9//      https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
10// using libunwind
11//
12//===----------------------------------------------------------------------===//
13
14// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}().  Thus, we are
15// defining inline functions to delegate the function calls to
16// _Unwind_VRS_{Get,Set}().  However, some applications might declare the
17// function protetype directly (instead of including <unwind.h>), thus we need
18// to export these functions from libunwind.so as well.
19#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1
20
21#include <inttypes.h>
22#include <stdint.h>
23#include <stdbool.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27
28#include "cet_unwind.h"
29#include "config.h"
30#include "libunwind.h"
31#include "libunwind_ext.h"
32#include "unwind.h"
33
34#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)
35
36#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
37
38// When CET is enabled, each "call" instruction will push return address to
39// CET shadow stack, each "ret" instruction will pop current CET shadow stack
40// top and compare it with target address which program will return.
41// In exception handing, some stack frames will be skipped before jumping to
42// landing pad and we must adjust CET shadow stack accordingly.
43// _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we
44// directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using
45// a regular function call to avoid pushing to CET shadow stack again.
46#if !defined(_LIBUNWIND_USE_CET)
47#define __unw_phase2_resume(cursor, fn)                                        \
48  do {                                                                         \
49    (void)fn;                                                                  \
50    __unw_resume((cursor));                                                    \
51  } while (0)
52#elif defined(_LIBUNWIND_TARGET_I386)
53#define __cet_ss_step_size 4
54#define __unw_phase2_resume(cursor, fn)                                        \
55  do {                                                                         \
56    _LIBUNWIND_POP_CET_SSP((fn));                                              \
57    void *cetRegContext = __libunwind_cet_get_registers((cursor));             \
58    void *cetJumpAddress = __libunwind_cet_get_jump_target();                  \
59    __asm__ volatile("push %%edi\n\t"                                          \
60                     "sub $4, %%esp\n\t"                                       \
61                     "jmp *%%edx\n\t" :: "D"(cetRegContext),                   \
62                     "d"(cetJumpAddress));                                     \
63  } while (0)
64#elif defined(_LIBUNWIND_TARGET_X86_64)
65#define __cet_ss_step_size 8
66#define __unw_phase2_resume(cursor, fn)                                        \
67  do {                                                                         \
68    _LIBUNWIND_POP_CET_SSP((fn));                                              \
69    void *cetRegContext = __libunwind_cet_get_registers((cursor));             \
70    void *cetJumpAddress = __libunwind_cet_get_jump_target();                  \
71    __asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext),                  \
72                     "d"(cetJumpAddress));                                     \
73  } while (0)
74#endif
75
76static _Unwind_Reason_Code
77unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
78  __unw_init_local(cursor, uc);
79
80  // Walk each frame looking for a place to stop.
81  while (true) {
82    // Ask libunwind to get next frame (skip over first which is
83    // _Unwind_RaiseException).
84    int stepResult = __unw_step(cursor);
85    if (stepResult == 0) {
86      _LIBUNWIND_TRACE_UNWINDING(
87          "unwind_phase1(ex_obj=%p): __unw_step() reached "
88          "bottom => _URC_END_OF_STACK",
89          (void *)exception_object);
90      return _URC_END_OF_STACK;
91    } else if (stepResult < 0) {
92      _LIBUNWIND_TRACE_UNWINDING(
93          "unwind_phase1(ex_obj=%p): __unw_step failed => "
94          "_URC_FATAL_PHASE1_ERROR",
95          (void *)exception_object);
96      return _URC_FATAL_PHASE1_ERROR;
97    }
98
99    // See if frame has code to run (has personality routine).
100    unw_proc_info_t frameInfo;
101    unw_word_t sp;
102    if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
103      _LIBUNWIND_TRACE_UNWINDING(
104          "unwind_phase1(ex_obj=%p): __unw_get_proc_info "
105          "failed => _URC_FATAL_PHASE1_ERROR",
106          (void *)exception_object);
107      return _URC_FATAL_PHASE1_ERROR;
108    }
109
110#ifndef NDEBUG
111    // When tracing, print state information.
112    if (_LIBUNWIND_TRACING_UNWINDING) {
113      char functionBuf[512];
114      const char *functionName = functionBuf;
115      unw_word_t offset;
116      if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
117                               &offset) != UNW_ESUCCESS) ||
118          (frameInfo.start_ip + offset > frameInfo.end_ip))
119        functionName = ".anonymous.";
120      unw_word_t pc;
121      __unw_get_reg(cursor, UNW_REG_IP, &pc);
122      _LIBUNWIND_TRACE_UNWINDING(
123          "unwind_phase1(ex_obj=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR
124          ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",
125          (void *)exception_object, pc, frameInfo.start_ip, functionName,
126          frameInfo.lsda, frameInfo.handler);
127    }
128#endif
129
130    // If there is a personality routine, ask it if it will want to stop at
131    // this frame.
132    if (frameInfo.handler != 0) {
133      _Unwind_Personality_Fn p =
134          (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
135      _LIBUNWIND_TRACE_UNWINDING(
136          "unwind_phase1(ex_obj=%p): calling personality function %p",
137          (void *)exception_object, (void *)(uintptr_t)p);
138      _Unwind_Reason_Code personalityResult =
139          (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
140               exception_object, (struct _Unwind_Context *)(cursor));
141      switch (personalityResult) {
142      case _URC_HANDLER_FOUND:
143        // found a catch clause or locals that need destructing in this frame
144        // stop search and remember stack pointer at the frame
145        __unw_get_reg(cursor, UNW_REG_SP, &sp);
146        exception_object->private_2 = (uintptr_t)sp;
147        _LIBUNWIND_TRACE_UNWINDING(
148            "unwind_phase1(ex_obj=%p): _URC_HANDLER_FOUND",
149            (void *)exception_object);
150        return _URC_NO_REASON;
151
152      case _URC_CONTINUE_UNWIND:
153        _LIBUNWIND_TRACE_UNWINDING(
154            "unwind_phase1(ex_obj=%p): _URC_CONTINUE_UNWIND",
155            (void *)exception_object);
156        // continue unwinding
157        break;
158
159      default:
160        // something went wrong
161        _LIBUNWIND_TRACE_UNWINDING(
162            "unwind_phase1(ex_obj=%p): _URC_FATAL_PHASE1_ERROR",
163            (void *)exception_object);
164        return _URC_FATAL_PHASE1_ERROR;
165      }
166    }
167  }
168  return _URC_NO_REASON;
169}
170extern int __unw_step_stage2(unw_cursor_t *);
171
172static _Unwind_Reason_Code
173unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
174  __unw_init_local(cursor, uc);
175
176  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",
177                             (void *)exception_object);
178
179  // uc is initialized by __unw_getcontext in the parent frame. The first stack
180  // frame walked is unwind_phase2.
181  unsigned framesWalked = 1;
182#ifdef _LIBUNWIND_USE_CET
183  unsigned long shadowStackTop = _get_ssp();
184#endif
185  // Walk each frame until we reach where search phase said to stop.
186  while (true) {
187
188    // Ask libunwind to get next frame (skip over first which is
189    // _Unwind_RaiseException).
190    int stepResult = __unw_step_stage2(cursor);
191    if (stepResult == 0) {
192      _LIBUNWIND_TRACE_UNWINDING(
193          "unwind_phase2(ex_obj=%p): __unw_step_stage2() reached "
194          "bottom => _URC_END_OF_STACK",
195          (void *)exception_object);
196      return _URC_END_OF_STACK;
197    } else if (stepResult < 0) {
198      _LIBUNWIND_TRACE_UNWINDING(
199          "unwind_phase2(ex_obj=%p): __unw_step_stage2 failed => "
200          "_URC_FATAL_PHASE1_ERROR",
201          (void *)exception_object);
202      return _URC_FATAL_PHASE2_ERROR;
203    }
204
205    // Get info about this frame.
206    unw_word_t sp;
207    unw_proc_info_t frameInfo;
208    __unw_get_reg(cursor, UNW_REG_SP, &sp);
209    if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
210      _LIBUNWIND_TRACE_UNWINDING(
211          "unwind_phase2(ex_obj=%p): __unw_get_proc_info "
212          "failed => _URC_FATAL_PHASE1_ERROR",
213          (void *)exception_object);
214      return _URC_FATAL_PHASE2_ERROR;
215    }
216
217#ifndef NDEBUG
218    // When tracing, print state information.
219    if (_LIBUNWIND_TRACING_UNWINDING) {
220      char functionBuf[512];
221      const char *functionName = functionBuf;
222      unw_word_t offset;
223      if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
224                               &offset) != UNW_ESUCCESS) ||
225          (frameInfo.start_ip + offset > frameInfo.end_ip))
226        functionName = ".anonymous.";
227      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): start_ip=0x%" PRIxPTR
228                                 ", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR
229                                 ", personality=0x%" PRIxPTR,
230                                 (void *)exception_object, frameInfo.start_ip,
231                                 functionName, sp, frameInfo.lsda,
232                                 frameInfo.handler);
233    }
234#endif
235
236// In CET enabled environment, we check return address stored in normal stack
237// against return address stored in CET shadow stack, if the 2 addresses don't
238// match, it means return address in normal stack has been corrupted, we return
239// _URC_FATAL_PHASE2_ERROR.
240#ifdef _LIBUNWIND_USE_CET
241    if (shadowStackTop != 0) {
242      unw_word_t retInNormalStack;
243      __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack);
244      unsigned long retInShadowStack = *(
245          unsigned long *)(shadowStackTop + __cet_ss_step_size * framesWalked);
246      if (retInNormalStack != retInShadowStack)
247        return _URC_FATAL_PHASE2_ERROR;
248    }
249#endif
250    ++framesWalked;
251    // If there is a personality routine, tell it we are unwinding.
252    if (frameInfo.handler != 0) {
253      _Unwind_Personality_Fn p =
254          (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
255      _Unwind_Action action = _UA_CLEANUP_PHASE;
256      if (sp == exception_object->private_2) {
257        // Tell personality this was the frame it marked in phase 1.
258        action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
259      }
260       _Unwind_Reason_Code personalityResult =
261          (*p)(1, action, exception_object->exception_class, exception_object,
262               (struct _Unwind_Context *)(cursor));
263      switch (personalityResult) {
264      case _URC_CONTINUE_UNWIND:
265        // Continue unwinding
266        _LIBUNWIND_TRACE_UNWINDING(
267            "unwind_phase2(ex_obj=%p): _URC_CONTINUE_UNWIND",
268            (void *)exception_object);
269        if (sp == exception_object->private_2) {
270          // Phase 1 said we would stop at this frame, but we did not...
271          _LIBUNWIND_ABORT("during phase1 personality function said it would "
272                           "stop here, but now in phase2 it did not stop here");
273        }
274        break;
275      case _URC_INSTALL_CONTEXT:
276        _LIBUNWIND_TRACE_UNWINDING(
277            "unwind_phase2(ex_obj=%p): _URC_INSTALL_CONTEXT",
278            (void *)exception_object);
279        // Personality routine says to transfer control to landing pad.
280        // We may get control back if landing pad calls _Unwind_Resume().
281        if (_LIBUNWIND_TRACING_UNWINDING) {
282          unw_word_t pc;
283          __unw_get_reg(cursor, UNW_REG_IP, &pc);
284          __unw_get_reg(cursor, UNW_REG_SP, &sp);
285          _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): re-entering "
286                                     "user code with ip=0x%" PRIxPTR
287                                     ", sp=0x%" PRIxPTR,
288                                     (void *)exception_object, pc, sp);
289        }
290
291        __unw_phase2_resume(cursor, framesWalked);
292        // __unw_phase2_resume() only returns if there was an error.
293        return _URC_FATAL_PHASE2_ERROR;
294      default:
295        // Personality routine returned an unknown result code.
296        _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
297                             personalityResult);
298        return _URC_FATAL_PHASE2_ERROR;
299      }
300    }
301  }
302
303  // Clean up phase did not resume at the frame that the search phase
304  // said it would...
305  return _URC_FATAL_PHASE2_ERROR;
306}
307
308static _Unwind_Reason_Code
309unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
310                     _Unwind_Exception *exception_object,
311                     _Unwind_Stop_Fn stop, void *stop_parameter) {
312  __unw_init_local(cursor, uc);
313
314  // uc is initialized by __unw_getcontext in the parent frame. The first stack
315  // frame walked is unwind_phase2_forced.
316  unsigned framesWalked = 1;
317  // Walk each frame until we reach where search phase said to stop
318  while (__unw_step_stage2(cursor) > 0) {
319
320    // Update info about this frame.
321    unw_proc_info_t frameInfo;
322    if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
323      _LIBUNWIND_TRACE_UNWINDING(
324          "unwind_phase2_forced(ex_obj=%p): __unw_get_proc_info "
325          "failed => _URC_END_OF_STACK",
326          (void *)exception_object);
327      return _URC_FATAL_PHASE2_ERROR;
328    }
329
330#ifndef NDEBUG
331    // When tracing, print state information.
332    if (_LIBUNWIND_TRACING_UNWINDING) {
333      char functionBuf[512];
334      const char *functionName = functionBuf;
335      unw_word_t offset;
336      if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
337                               &offset) != UNW_ESUCCESS) ||
338          (frameInfo.start_ip + offset > frameInfo.end_ip))
339        functionName = ".anonymous.";
340      _LIBUNWIND_TRACE_UNWINDING(
341          "unwind_phase2_forced(ex_obj=%p): start_ip=0x%" PRIxPTR
342          ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
343          (void *)exception_object, frameInfo.start_ip, functionName,
344          frameInfo.lsda, frameInfo.handler);
345    }
346#endif
347
348    // Call stop function at each frame.
349    _Unwind_Action action =
350        (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
351    _Unwind_Reason_Code stopResult =
352        (*stop)(1, action, exception_object->exception_class, exception_object,
353                (struct _Unwind_Context *)(cursor), stop_parameter);
354    _LIBUNWIND_TRACE_UNWINDING(
355        "unwind_phase2_forced(ex_obj=%p): stop function returned %d",
356        (void *)exception_object, stopResult);
357    if (stopResult != _URC_NO_REASON) {
358      _LIBUNWIND_TRACE_UNWINDING(
359          "unwind_phase2_forced(ex_obj=%p): stopped by stop function",
360          (void *)exception_object);
361      return _URC_FATAL_PHASE2_ERROR;
362    }
363
364    ++framesWalked;
365    // If there is a personality routine, tell it we are unwinding.
366    if (frameInfo.handler != 0) {
367      _Unwind_Personality_Fn p =
368          (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);
369      _LIBUNWIND_TRACE_UNWINDING(
370          "unwind_phase2_forced(ex_obj=%p): calling personality function %p",
371          (void *)exception_object, (void *)(uintptr_t)p);
372      _Unwind_Reason_Code personalityResult =
373          (*p)(1, action, exception_object->exception_class, exception_object,
374               (struct _Unwind_Context *)(cursor));
375      switch (personalityResult) {
376      case _URC_CONTINUE_UNWIND:
377        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
378                                   "personality returned "
379                                   "_URC_CONTINUE_UNWIND",
380                                   (void *)exception_object);
381        // Destructors called, continue unwinding
382        break;
383      case _URC_INSTALL_CONTEXT:
384        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
385                                   "personality returned "
386                                   "_URC_INSTALL_CONTEXT",
387                                   (void *)exception_object);
388        // We may get control back if landing pad calls _Unwind_Resume().
389        __unw_phase2_resume(cursor, framesWalked);
390        break;
391      default:
392        // Personality routine returned an unknown result code.
393        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
394                                   "personality returned %d, "
395                                   "_URC_FATAL_PHASE2_ERROR",
396                                   (void *)exception_object, personalityResult);
397        return _URC_FATAL_PHASE2_ERROR;
398      }
399    }
400  }
401
402  // Call stop function one last time and tell it we've reached the end
403  // of the stack.
404  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): calling stop "
405                             "function with _UA_END_OF_STACK",
406                             (void *)exception_object);
407  _Unwind_Action lastAction =
408      (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
409  (*stop)(1, lastAction, exception_object->exception_class, exception_object,
410          (struct _Unwind_Context *)(cursor), stop_parameter);
411
412  // Clean up phase did not resume at the frame that the search phase said it
413  // would.
414  return _URC_FATAL_PHASE2_ERROR;
415}
416
417
418/// Called by __cxa_throw.  Only returns if there is a fatal error.
419_LIBUNWIND_EXPORT _Unwind_Reason_Code
420_Unwind_RaiseException(_Unwind_Exception *exception_object) {
421  _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
422                       (void *)exception_object);
423  unw_context_t uc;
424  unw_cursor_t cursor;
425  __unw_getcontext(&uc);
426
427  // Mark that this is a non-forced unwind, so _Unwind_Resume()
428  // can do the right thing.
429  exception_object->private_1 = 0;
430  exception_object->private_2 = 0;
431
432  // phase 1: the search phase
433  _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
434  if (phase1 != _URC_NO_REASON)
435    return phase1;
436
437  // phase 2: the clean up phase
438  return unwind_phase2(&uc, &cursor, exception_object);
439}
440
441
442
443/// When _Unwind_RaiseException() is in phase2, it hands control
444/// to the personality function at each frame.  The personality
445/// may force a jump to a landing pad in that function, the landing
446/// pad code may then call _Unwind_Resume() to continue with the
447/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
448/// generated user code.  All other _Unwind_* routines are called
449/// by the C++ runtime __cxa_* routines.
450///
451/// Note: re-throwing an exception (as opposed to continuing the unwind)
452/// is implemented by having the code call __cxa_rethrow() which
453/// in turn calls _Unwind_Resume_or_Rethrow().
454_LIBUNWIND_EXPORT void
455_Unwind_Resume(_Unwind_Exception *exception_object) {
456  _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);
457  unw_context_t uc;
458  unw_cursor_t cursor;
459  __unw_getcontext(&uc);
460
461  if (exception_object->private_1 != 0)
462    unwind_phase2_forced(&uc, &cursor, exception_object,
463                         (_Unwind_Stop_Fn) exception_object->private_1,
464                         (void *)exception_object->private_2);
465  else
466    unwind_phase2(&uc, &cursor, exception_object);
467
468  // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
469  _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
470}
471
472
473
474/// Not used by C++.
475/// Unwinds stack, calling "stop" function at each frame.
476/// Could be used to implement longjmp().
477_LIBUNWIND_EXPORT _Unwind_Reason_Code
478_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
479                     _Unwind_Stop_Fn stop, void *stop_parameter) {
480  _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
481                       (void *)exception_object, (void *)(uintptr_t)stop);
482  unw_context_t uc;
483  unw_cursor_t cursor;
484  __unw_getcontext(&uc);
485
486  // Mark that this is a forced unwind, so _Unwind_Resume() can do
487  // the right thing.
488  exception_object->private_1 = (uintptr_t) stop;
489  exception_object->private_2 = (uintptr_t) stop_parameter;
490
491  // do it
492  return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter);
493}
494
495
496/// Called by personality handler during phase 2 to get LSDA for current frame.
497_LIBUNWIND_EXPORT uintptr_t
498_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
499  unw_cursor_t *cursor = (unw_cursor_t *)context;
500  unw_proc_info_t frameInfo;
501  uintptr_t result = 0;
502  if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
503    result = (uintptr_t)frameInfo.lsda;
504  _LIBUNWIND_TRACE_API(
505      "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
506      (void *)context, result);
507#if !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
508  if (result != 0) {
509    if (*((uint8_t *)result) != 0xFF)
510      _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",
511                           result);
512  }
513#endif
514  return result;
515}
516
517
518/// Called by personality handler during phase 2 to find the start of the
519/// function.
520_LIBUNWIND_EXPORT uintptr_t
521_Unwind_GetRegionStart(struct _Unwind_Context *context) {
522  unw_cursor_t *cursor = (unw_cursor_t *)context;
523  unw_proc_info_t frameInfo;
524  uintptr_t result = 0;
525  if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
526    result = (uintptr_t)frameInfo.start_ip;
527  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,
528                       (void *)context, result);
529  return result;
530}
531
532#endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND
533
534/// Called by personality handler during phase 2 if a foreign exception
535// is caught.
536_LIBUNWIND_EXPORT void
537_Unwind_DeleteException(_Unwind_Exception *exception_object) {
538  _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
539                       (void *)exception_object);
540  if (exception_object->exception_cleanup != NULL)
541    (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
542                                           exception_object);
543}
544
545/// Called by personality handler during phase 2 to get register values.
546_LIBUNWIND_EXPORT uintptr_t
547_Unwind_GetGR(struct _Unwind_Context *context, int index) {
548  unw_cursor_t *cursor = (unw_cursor_t *)context;
549  unw_word_t result;
550  __unw_get_reg(cursor, index, &result);
551  _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIxPTR,
552                       (void *)context, index, result);
553  return (uintptr_t)result;
554}
555
556/// Called by personality handler during phase 2 to alter register values.
557_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
558                                     uintptr_t value) {
559  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIxPTR
560                       ")",
561                       (void *)context, index, value);
562  unw_cursor_t *cursor = (unw_cursor_t *)context;
563  __unw_set_reg(cursor, index, value);
564}
565
566/// Called by personality handler during phase 2 to get instruction pointer.
567_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
568  unw_cursor_t *cursor = (unw_cursor_t *)context;
569  unw_word_t result;
570  __unw_get_reg(cursor, UNW_REG_IP, &result);
571  _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
572                       (void *)context, result);
573  return (uintptr_t)result;
574}
575
576/// Called by personality handler during phase 2 to alter instruction pointer,
577/// such as setting where the landing pad is, so _Unwind_Resume() will
578/// start executing in the landing pad.
579_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
580                                     uintptr_t value) {
581  _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIxPTR ")",
582                       (void *)context, value);
583  unw_cursor_t *cursor = (unw_cursor_t *)context;
584  __unw_set_reg(cursor, UNW_REG_IP, value);
585}
586
587#endif // !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)
588