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