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