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