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