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