177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* ===-- gcc_personality_v0.c - Implement __gcc_personality_v0 -------------=== 277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * 377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * The LLVM Compiler Infrastructure 477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * 577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * This file is distributed under the University of Illinois Open Source 677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * License. See LICENSE.TXT for details. 777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * 877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * ===----------------------------------------------------------------------=== 977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * 1077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */ 1177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 1277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#include <stdint.h> 1377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#include <stdio.h> 1477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#include <stdlib.h> 1577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 1677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* 1777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * _Unwind_* stuff based on C++ ABI public documentation 1877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * http://refspecs.freestandards.org/abi-eh-1.21.html 1977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */ 2077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 2177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaotypedef enum { 2277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _URC_NO_REASON = 0, 2377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _URC_FOREIGN_EXCEPTION_CAUGHT = 1, 2477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _URC_FATAL_PHASE2_ERROR = 2, 2577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _URC_FATAL_PHASE1_ERROR = 3, 2677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _URC_NORMAL_STOP = 4, 2777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _URC_END_OF_STACK = 5, 2877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _URC_HANDLER_FOUND = 6, 2977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _URC_INSTALL_CONTEXT = 7, 3077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _URC_CONTINUE_UNWIND = 8 3177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao} _Unwind_Reason_Code; 3277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 3377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaotypedef enum { 3477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _UA_SEARCH_PHASE = 1, 3577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _UA_CLEANUP_PHASE = 2, 3677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _UA_HANDLER_FRAME = 4, 3777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _UA_FORCE_UNWIND = 8, 3877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _UA_END_OF_STACK = 16 3977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao} _Unwind_Action; 4077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 4177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaotypedef struct _Unwind_Context* _Unwind_Context_t; 4277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 4377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaostruct _Unwind_Exception { 4477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uint64_t exception_class; 4577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao void (*exception_cleanup)(_Unwind_Reason_Code reason, 4677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao struct _Unwind_Exception* exc); 4777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t private_1; 4877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t private_2; 4977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao}; 5077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 5177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaoextern const uint8_t* _Unwind_GetLanguageSpecificData(_Unwind_Context_t c); 5277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaoextern void _Unwind_SetGR(_Unwind_Context_t c, int i, uintptr_t n); 5377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaoextern void _Unwind_SetIP(_Unwind_Context_t, uintptr_t new_value); 5477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaoextern uintptr_t _Unwind_GetIP(_Unwind_Context_t context); 5577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaoextern uintptr_t _Unwind_GetRegionStart(_Unwind_Context_t context); 5677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 5777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 5877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* 5977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * Pointer encodings documented at: 6077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html 6177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */ 6277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 6377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_omit 0xff /* no data follows */ 6477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 6577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_absptr 0x00 6677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_uleb128 0x01 6777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_udata2 0x02 6877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_udata4 0x03 6977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_udata8 0x04 7077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_sleb128 0x09 7177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_sdata2 0x0A 7277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_sdata4 0x0B 7377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_sdata8 0x0C 7477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 7577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_pcrel 0x10 7677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_textrel 0x20 7777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_datarel 0x30 7877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_funcrel 0x40 7977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_aligned 0x50 8077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define DW_EH_PE_indirect 0x80 /* gcc extension */ 8177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 8277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 8377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 8477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* read a uleb128 encoded value and advance pointer */ 8577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaostatic uintptr_t readULEB128(const uint8_t** data) 8677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{ 8777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t result = 0; 8877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t shift = 0; 8977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao unsigned char byte; 9077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao const uint8_t* p = *data; 9177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao do { 9277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao byte = *p++; 9377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result |= (byte & 0x7f) << shift; 9477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao shift += 7; 9577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } while (byte & 0x80); 9677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *data = p; 9777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return result; 9877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao} 9977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 10077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* read a pointer encoded value and advance pointer */ 10177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaostatic uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) 10277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{ 10377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao const uint8_t* p = *data; 10477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t result = 0; 10577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 10677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if ( encoding == DW_EH_PE_omit ) 10777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return 0; 10877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 10977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* first get value */ 11077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao switch (encoding & 0x0F) { 11177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_absptr: 11277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result = *((uintptr_t*)p); 11377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao p += sizeof(uintptr_t); 11477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 11577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_uleb128: 11677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result = readULEB128(&p); 11777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 11877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_udata2: 11977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result = *((uint16_t*)p); 12077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao p += sizeof(uint16_t); 12177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 12277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_udata4: 12377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result = *((uint32_t*)p); 12477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao p += sizeof(uint32_t); 12577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 12677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_udata8: 12777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result = *((uint64_t*)p); 12877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao p += sizeof(uint64_t); 12977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 13077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_sdata2: 13177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result = *((int16_t*)p); 13277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao p += sizeof(int16_t); 13377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 13477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_sdata4: 13577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result = *((int32_t*)p); 13677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao p += sizeof(int32_t); 13777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 13877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_sdata8: 13977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result = *((int64_t*)p); 14077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao p += sizeof(int64_t); 14177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 14277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_sleb128: 14377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao default: 14477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* not supported */ 14577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao abort(); 14677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 14777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 14877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 14977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* then add relative offset */ 15077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao switch ( encoding & 0x70 ) { 15177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_absptr: 15277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* do nothing */ 15377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 15477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_pcrel: 15577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result += (uintptr_t)(*data); 15677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 15777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_textrel: 15877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_datarel: 15977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_funcrel: 16077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao case DW_EH_PE_aligned: 16177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao default: 16277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* not supported */ 16377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao abort(); 16477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao break; 16577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 16677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 16777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* then apply indirection */ 16877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if (encoding & DW_EH_PE_indirect) { 16977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao result = *((uintptr_t*)result); 17077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 17177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 17277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *data = p; 17377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return result; 17477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao} 17577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 17677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 17777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* 17877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * The C compiler makes references to __gcc_personality_v0 in 17977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * the dwarf unwind information for translation units that use 18077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * __attribute__((cleanup(xx))) on local variables. 18177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * This personality routine is called by the system unwinder 18277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * on each frame as the stack is unwound during a C++ exception 18377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * throw through a C function compiled with -fexceptions. 18477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */ 18577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 18677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao_Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions, 18777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject, 18877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _Unwind_Context_t context) 18977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{ 19077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* Since C does not have catch clauses, there is nothing to do during */ 19177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* phase 1 (the search phase). */ 19277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if ( actions & _UA_SEARCH_PHASE ) 19377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return _URC_CONTINUE_UNWIND; 19477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 19577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* There is nothing to do if there is no LSDA for this frame. */ 19677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao const uint8_t* lsda = _Unwind_GetLanguageSpecificData(context); 19777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if ( lsda == NULL ) 19877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return _URC_CONTINUE_UNWIND; 19977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 20077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t pc = _Unwind_GetIP(context)-1; 20177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t funcStart = _Unwind_GetRegionStart(context); 20277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t pcOffset = pc - funcStart; 20377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 20477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* Parse LSDA header. */ 20577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uint8_t lpStartEncoding = *lsda++; 20677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if (lpStartEncoding != DW_EH_PE_omit) { 20777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao readEncodedPointer(&lsda, lpStartEncoding); 20877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 20977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uint8_t ttypeEncoding = *lsda++; 21077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if (ttypeEncoding != DW_EH_PE_omit) { 21177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao readULEB128(&lsda); 21277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 21377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* Walk call-site table looking for range that includes current PC. */ 21477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uint8_t callSiteEncoding = *lsda++; 21577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uint32_t callSiteTableLength = readULEB128(&lsda); 21677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao const uint8_t* callSiteTableStart = lsda; 21777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; 21877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao const uint8_t* p=callSiteTableStart; 21977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao while (p < callSiteTableEnd) { 22077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t start = readEncodedPointer(&p, callSiteEncoding); 22177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t length = readEncodedPointer(&p, callSiteEncoding); 22277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao uintptr_t landingPad = readEncodedPointer(&p, callSiteEncoding); 22377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao readULEB128(&p); /* action value not used for C code */ 22477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if ( landingPad == 0 ) 22577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao continue; /* no landing pad for this entry */ 22677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao if ( (start <= pcOffset) && (pcOffset < (start+length)) ) { 22777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* Found landing pad for the PC. 22877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * Set Instruction Pointer to so we re-enter function 22977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * at landing pad. The landing pad is created by the compiler 23077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * to take two parameters in registers. 23177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */ 23277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), 23377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao (uintptr_t)exceptionObject); 23477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); 23577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao _Unwind_SetIP(context, funcStart+landingPad); 23677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return _URC_INSTALL_CONTEXT; 23777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 23877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao } 23977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 24077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao /* No landing pad found, continue unwinding. */ 24177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao return _URC_CONTINUE_UNWIND; 24277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao} 24377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao 244