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