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