12bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan/* ===-- gcc_personality_v0.c - Implement __gcc_personality_v0 -------------=== 22bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * 32bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * The LLVM Compiler Infrastructure 42bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * 59ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * This file is dual licensed under the MIT and the University of Illinois Open 69ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * Source Licenses. See LICENSE.TXT for details. 72bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * 82bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * ===----------------------------------------------------------------------=== 92bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * 102bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan */ 11b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 12d0d9913a7456c5fad3f4b09e0c94ab893077d1ddNick Kledzik#include "int_lib.h" 13d0d9913a7456c5fad3f4b09e0c94ab893077d1ddNick Kledzik 142bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan/* 152bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * _Unwind_* stuff based on C++ ABI public documentation 162bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * http://refspecs.freestandards.org/abi-eh-1.21.html 172bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan */ 182bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan 19b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbartypedef enum { 20b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _URC_NO_REASON = 0, 21b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _URC_FOREIGN_EXCEPTION_CAUGHT = 1, 22b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _URC_FATAL_PHASE2_ERROR = 2, 23b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _URC_FATAL_PHASE1_ERROR = 3, 24b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _URC_NORMAL_STOP = 4, 25b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _URC_END_OF_STACK = 5, 26b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _URC_HANDLER_FOUND = 6, 27b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _URC_INSTALL_CONTEXT = 7, 28b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _URC_CONTINUE_UNWIND = 8 29b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar} _Unwind_Reason_Code; 30b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 31b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbartypedef enum { 32b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _UA_SEARCH_PHASE = 1, 33b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _UA_CLEANUP_PHASE = 2, 34b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _UA_HANDLER_FRAME = 4, 35b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _UA_FORCE_UNWIND = 8, 36b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _UA_END_OF_STACK = 16 37b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar} _Unwind_Action; 38b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 39b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbartypedef struct _Unwind_Context* _Unwind_Context_t; 40b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 41b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbarstruct _Unwind_Exception { 42b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uint64_t exception_class; 43b04c2c4ddd4e51075ea377e7c4d603f8bb9bf617Nick Kledzik void (*exception_cleanup)(_Unwind_Reason_Code reason, 44b04c2c4ddd4e51075ea377e7c4d603f8bb9bf617Nick Kledzik struct _Unwind_Exception* exc); 45b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t private_1; 46b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t private_2; 47b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar}; 48b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesCOMPILER_RT_ABI const uint8_t* _Unwind_GetLanguageSpecificData(_Unwind_Context_t c); 502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesCOMPILER_RT_ABI void _Unwind_SetGR(_Unwind_Context_t c, int i, uintptr_t n); 512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesCOMPILER_RT_ABI void _Unwind_SetIP(_Unwind_Context_t, uintptr_t new_value); 522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesCOMPILER_RT_ABI uintptr_t _Unwind_GetIP(_Unwind_Context_t context); 532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesCOMPILER_RT_ABI uintptr_t _Unwind_GetRegionStart(_Unwind_Context_t context); 54b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 55b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 562bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan/* 572bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * Pointer encodings documented at: 582bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html 592bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan */ 602bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan 612bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan#define DW_EH_PE_omit 0xff /* no data follows */ 62b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 63b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_absptr 0x00 64b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_uleb128 0x01 65b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_udata2 0x02 66b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_udata4 0x03 67b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_udata8 0x04 68b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_sleb128 0x09 69b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_sdata2 0x0A 70b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_sdata4 0x0B 71b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_sdata8 0x0C 72b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 73b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_pcrel 0x10 74b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_textrel 0x20 75b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_datarel 0x30 76b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_funcrel 0x40 77b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#define DW_EH_PE_aligned 0x50 782bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan#define DW_EH_PE_indirect 0x80 /* gcc extension */ 79b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 80b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 81b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 822bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan/* read a uleb128 encoded value and advance pointer */ 83b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbarstatic uintptr_t readULEB128(const uint8_t** data) 84b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar{ 85b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t result = 0; 86b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t shift = 0; 87b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar unsigned char byte; 88b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const uint8_t* p = *data; 89b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar do { 90b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar byte = *p++; 91b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar result |= (byte & 0x7f) << shift; 92b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar shift += 7; 93b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } while (byte & 0x80); 94b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar *data = p; 95b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return result; 96b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar} 97b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 982bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan/* read a pointer encoded value and advance pointer */ 99b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbarstatic uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) 100b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar{ 101b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const uint8_t* p = *data; 102b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t result = 0; 103b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 104b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if ( encoding == DW_EH_PE_omit ) 105b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return 0; 106b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 1072bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* first get value */ 108b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar switch (encoding & 0x0F) { 109b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_absptr: 1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines result = *((const uintptr_t*)p); 111b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar p += sizeof(uintptr_t); 112b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 113b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_uleb128: 114b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar result = readULEB128(&p); 115b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 116b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_udata2: 1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines result = *((const uint16_t*)p); 118b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar p += sizeof(uint16_t); 119b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 120b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_udata4: 1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines result = *((const uint32_t*)p); 122b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar p += sizeof(uint32_t); 123b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 124b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_udata8: 1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines result = *((const uint64_t*)p); 126b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar p += sizeof(uint64_t); 127b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 128b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_sdata2: 1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines result = *((const int16_t*)p); 130b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar p += sizeof(int16_t); 131b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 132b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_sdata4: 1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines result = *((const int32_t*)p); 134b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar p += sizeof(int32_t); 135b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 136b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_sdata8: 1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines result = *((const int64_t*)p); 138b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar p += sizeof(int64_t); 139b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 140b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_sleb128: 141b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar default: 1422bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* not supported */ 14348f46ac1d9a82210f6e469567cb60aa7e7cd2f3bDaniel Dunbar compilerrt_abort(); 144b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 145b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 146b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 1472bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* then add relative offset */ 148b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar switch ( encoding & 0x70 ) { 149b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_absptr: 1502bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* do nothing */ 151b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 152b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_pcrel: 153b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar result += (uintptr_t)(*data); 154b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 155b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_textrel: 156b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_datarel: 157b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_funcrel: 158b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar case DW_EH_PE_aligned: 159b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar default: 1602bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* not supported */ 16148f46ac1d9a82210f6e469567cb60aa7e7cd2f3bDaniel Dunbar compilerrt_abort(); 162b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar break; 163b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 164b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 1652bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* then apply indirection */ 166b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (encoding & DW_EH_PE_indirect) { 1672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines result = *((const uintptr_t*)result); 168b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 169b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 170b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar *data = p; 171b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return result; 172b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar} 173b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 174b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 1752bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan/* 1762bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * The C compiler makes references to __gcc_personality_v0 in 1772bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * the dwarf unwind information for translation units that use 1782bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * __attribute__((cleanup(xx))) on local variables. 1792bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * This personality routine is called by the system unwinder 1802bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * on each frame as the stack is unwound during a C++ exception 1812bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * throw through a C function compiled with -fexceptions. 1822bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan */ 1832579d72d1a7d462a2344b38cb1125cf15e26d5fbNick Kledzik#if __arm__ 1842579d72d1a7d462a2344b38cb1125cf15e26d5fbNick Kledzik// the setjump-longjump based exceptions personality routine has a different name 1852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesCOMPILER_RT_ABI _Unwind_Reason_Code 1862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines__gcc_personality_sj0(int version, _Unwind_Action actions, 1872579d72d1a7d462a2344b38cb1125cf15e26d5fbNick Kledzik uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject, 1882579d72d1a7d462a2344b38cb1125cf15e26d5fbNick Kledzik _Unwind_Context_t context) 1892579d72d1a7d462a2344b38cb1125cf15e26d5fbNick Kledzik#else 1902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesCOMPILER_RT_ABI _Unwind_Reason_Code 1912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines__gcc_personality_v0(int version, _Unwind_Action actions, 192b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject, 193b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _Unwind_Context_t context) 1942579d72d1a7d462a2344b38cb1125cf15e26d5fbNick Kledzik#endif 195b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar{ 1962bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* Since C does not have catch clauses, there is nothing to do during */ 1972bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* phase 1 (the search phase). */ 198b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if ( actions & _UA_SEARCH_PHASE ) 199b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return _URC_CONTINUE_UNWIND; 200b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 2012bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* There is nothing to do if there is no LSDA for this frame. */ 202b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const uint8_t* lsda = _Unwind_GetLanguageSpecificData(context); 2036b682e41f005d0a452ab45fa31192bc43431240eDaniel Dunbar if ( lsda == (uint8_t*) 0 ) 204b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return _URC_CONTINUE_UNWIND; 205b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 206b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t pc = _Unwind_GetIP(context)-1; 207b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t funcStart = _Unwind_GetRegionStart(context); 208b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t pcOffset = pc - funcStart; 209b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 2102bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* Parse LSDA header. */ 211b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uint8_t lpStartEncoding = *lsda++; 212b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (lpStartEncoding != DW_EH_PE_omit) { 213b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar readEncodedPointer(&lsda, lpStartEncoding); 214b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 215b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uint8_t ttypeEncoding = *lsda++; 216b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (ttypeEncoding != DW_EH_PE_omit) { 217b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar readULEB128(&lsda); 218b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 2192bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* Walk call-site table looking for range that includes current PC. */ 220b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uint8_t callSiteEncoding = *lsda++; 221b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uint32_t callSiteTableLength = readULEB128(&lsda); 222b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const uint8_t* callSiteTableStart = lsda; 223b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; 224b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const uint8_t* p=callSiteTableStart; 225b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar while (p < callSiteTableEnd) { 226b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t start = readEncodedPointer(&p, callSiteEncoding); 227b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t length = readEncodedPointer(&p, callSiteEncoding); 228b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar uintptr_t landingPad = readEncodedPointer(&p, callSiteEncoding); 2292bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan readULEB128(&p); /* action value not used for C code */ 230b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if ( landingPad == 0 ) 2312bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan continue; /* no landing pad for this entry */ 232b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if ( (start <= pcOffset) && (pcOffset < (start+length)) ) { 2332bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* Found landing pad for the PC. 2342bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * Set Instruction Pointer to so we re-enter function 2352bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * at landing pad. The landing pad is created by the compiler 2362bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan * to take two parameters in registers. 2372bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan */ 238b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), 239b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar (uintptr_t)exceptionObject); 240b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); 241b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar _Unwind_SetIP(context, funcStart+landingPad); 242b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return _URC_INSTALL_CONTEXT; 243b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 244b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 245b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 2462bf62728b8ce00e295c7bf0fb328427496cc85aaEdward O'Callaghan /* No landing pad found, continue unwinding. */ 247b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return _URC_CONTINUE_UNWIND; 248b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar} 249b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 250