xref: /aosp_15_r20/external/libcxxabi/src/cxa_personality.cpp (revision c05d8e5dc3e10f6ce4317e8bc22cc4a25f55fa94)
1*c05d8e5dSAndroid Build Coastguard Worker //===------------------------- cxa_exception.cpp --------------------------===//
2*c05d8e5dSAndroid Build Coastguard Worker //
3*c05d8e5dSAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*c05d8e5dSAndroid Build Coastguard Worker //
5*c05d8e5dSAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*c05d8e5dSAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*c05d8e5dSAndroid Build Coastguard Worker //
8*c05d8e5dSAndroid Build Coastguard Worker //
9*c05d8e5dSAndroid Build Coastguard Worker //  This file implements the "Exception Handling APIs"
10*c05d8e5dSAndroid Build Coastguard Worker //  http://mentorembedded.github.io/cxx-abi/abi-eh.html
11*c05d8e5dSAndroid Build Coastguard Worker //  http://www.intel.com/design/itanium/downloads/245358.htm
12*c05d8e5dSAndroid Build Coastguard Worker //
13*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*c05d8e5dSAndroid Build Coastguard Worker 
15*c05d8e5dSAndroid Build Coastguard Worker #include <assert.h>
16*c05d8e5dSAndroid Build Coastguard Worker #include <stdlib.h>
17*c05d8e5dSAndroid Build Coastguard Worker #include <string.h>
18*c05d8e5dSAndroid Build Coastguard Worker #include <typeinfo>
19*c05d8e5dSAndroid Build Coastguard Worker 
20*c05d8e5dSAndroid Build Coastguard Worker #include "__cxxabi_config.h"
21*c05d8e5dSAndroid Build Coastguard Worker #include "cxa_exception.hpp"
22*c05d8e5dSAndroid Build Coastguard Worker #include "cxa_handlers.hpp"
23*c05d8e5dSAndroid Build Coastguard Worker #include "private_typeinfo.h"
24*c05d8e5dSAndroid Build Coastguard Worker #include "unwind.h"
25*c05d8e5dSAndroid Build Coastguard Worker 
26*c05d8e5dSAndroid Build Coastguard Worker #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
27*c05d8e5dSAndroid Build Coastguard Worker #include <windows.h>
28*c05d8e5dSAndroid Build Coastguard Worker #include <winnt.h>
29*c05d8e5dSAndroid Build Coastguard Worker 
30*c05d8e5dSAndroid Build Coastguard Worker extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
31*c05d8e5dSAndroid Build Coastguard Worker                                                        void *, PCONTEXT,
32*c05d8e5dSAndroid Build Coastguard Worker                                                        PDISPATCHER_CONTEXT,
33*c05d8e5dSAndroid Build Coastguard Worker                                                        _Unwind_Personality_Fn);
34*c05d8e5dSAndroid Build Coastguard Worker #endif
35*c05d8e5dSAndroid Build Coastguard Worker 
36*c05d8e5dSAndroid Build Coastguard Worker /*
37*c05d8e5dSAndroid Build Coastguard Worker     Exception Header Layout:
38*c05d8e5dSAndroid Build Coastguard Worker 
39*c05d8e5dSAndroid Build Coastguard Worker +---------------------------+-----------------------------+---------------+
40*c05d8e5dSAndroid Build Coastguard Worker | __cxa_exception           | _Unwind_Exception CLNGC++\0 | thrown object |
41*c05d8e5dSAndroid Build Coastguard Worker +---------------------------+-----------------------------+---------------+
42*c05d8e5dSAndroid Build Coastguard Worker                                                           ^
43*c05d8e5dSAndroid Build Coastguard Worker                                                           |
44*c05d8e5dSAndroid Build Coastguard Worker   +-------------------------------------------------------+
45*c05d8e5dSAndroid Build Coastguard Worker   |
46*c05d8e5dSAndroid Build Coastguard Worker +---------------------------+-----------------------------+
47*c05d8e5dSAndroid Build Coastguard Worker | __cxa_dependent_exception | _Unwind_Exception CLNGC++\1 |
48*c05d8e5dSAndroid Build Coastguard Worker +---------------------------+-----------------------------+
49*c05d8e5dSAndroid Build Coastguard Worker 
50*c05d8e5dSAndroid Build Coastguard Worker     Exception Handling Table Layout:
51*c05d8e5dSAndroid Build Coastguard Worker 
52*c05d8e5dSAndroid Build Coastguard Worker +-----------------+--------+
53*c05d8e5dSAndroid Build Coastguard Worker | lpStartEncoding | (char) |
54*c05d8e5dSAndroid Build Coastguard Worker +---------+-------+--------+---------------+-----------------------+
55*c05d8e5dSAndroid Build Coastguard Worker | lpStart | (encoded with lpStartEncoding) | defaults to funcStart |
56*c05d8e5dSAndroid Build Coastguard Worker +---------+-----+--------+-----------------+---------------+-------+
57*c05d8e5dSAndroid Build Coastguard Worker | ttypeEncoding | (char) | Encoding of the type_info table |
58*c05d8e5dSAndroid Build Coastguard Worker +---------------+-+------+----+----------------------------+----------------+
59*c05d8e5dSAndroid Build Coastguard Worker | classInfoOffset | (ULEB128) | Offset to type_info table, defaults to null |
60*c05d8e5dSAndroid Build Coastguard Worker +-----------------++--------+-+----------------------------+----------------+
61*c05d8e5dSAndroid Build Coastguard Worker | callSiteEncoding | (char) | Encoding for Call Site Table |
62*c05d8e5dSAndroid Build Coastguard Worker +------------------+--+-----+-----+------------------------+--------------------------+
63*c05d8e5dSAndroid Build Coastguard Worker | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |
64*c05d8e5dSAndroid Build Coastguard Worker +---------------------+-----------+---------------------------------------------------+
65*c05d8e5dSAndroid Build Coastguard Worker #ifndef __USING_SJLJ_EXCEPTIONS__
66*c05d8e5dSAndroid Build Coastguard Worker +---------------------+-----------+------------------------------------------------+
67*c05d8e5dSAndroid Build Coastguard Worker | Beginning of Call Site Table            The current ip lies within the           |
68*c05d8e5dSAndroid Build Coastguard Worker | ...                                     (start, length) range of one of these    |
69*c05d8e5dSAndroid Build Coastguard Worker |                                         call sites. There may be action needed.  |
70*c05d8e5dSAndroid Build Coastguard Worker | +-------------+---------------------------------+------------------------------+ |
71*c05d8e5dSAndroid Build Coastguard Worker | | start       | (encoded with callSiteEncoding) | offset relative to funcStart | |
72*c05d8e5dSAndroid Build Coastguard Worker | | length      | (encoded with callSiteEncoding) | length of code fragment      | |
73*c05d8e5dSAndroid Build Coastguard Worker | | landingPad  | (encoded with callSiteEncoding) | offset relative to lpStart   | |
74*c05d8e5dSAndroid Build Coastguard Worker | | actionEntry | (ULEB128)                       | Action Table Index 1-based   | |
75*c05d8e5dSAndroid Build Coastguard Worker | |             |                                 | actionEntry == 0 -> cleanup  | |
76*c05d8e5dSAndroid Build Coastguard Worker | +-------------+---------------------------------+------------------------------+ |
77*c05d8e5dSAndroid Build Coastguard Worker | ...                                                                              |
78*c05d8e5dSAndroid Build Coastguard Worker +----------------------------------------------------------------------------------+
79*c05d8e5dSAndroid Build Coastguard Worker #else  // __USING_SJLJ_EXCEPTIONS__
80*c05d8e5dSAndroid Build Coastguard Worker +---------------------+-----------+------------------------------------------------+
81*c05d8e5dSAndroid Build Coastguard Worker | Beginning of Call Site Table            The current ip is a 1-based index into   |
82*c05d8e5dSAndroid Build Coastguard Worker | ...                                     this table.  Or it is -1 meaning no      |
83*c05d8e5dSAndroid Build Coastguard Worker |                                         action is needed.  Or it is 0 meaning    |
84*c05d8e5dSAndroid Build Coastguard Worker |                                         terminate.                               |
85*c05d8e5dSAndroid Build Coastguard Worker | +-------------+---------------------------------+------------------------------+ |
86*c05d8e5dSAndroid Build Coastguard Worker | | landingPad  | (ULEB128)                       | offset relative to lpStart   | |
87*c05d8e5dSAndroid Build Coastguard Worker | | actionEntry | (ULEB128)                       | Action Table Index 1-based   | |
88*c05d8e5dSAndroid Build Coastguard Worker | |             |                                 | actionEntry == 0 -> cleanup  | |
89*c05d8e5dSAndroid Build Coastguard Worker | +-------------+---------------------------------+------------------------------+ |
90*c05d8e5dSAndroid Build Coastguard Worker | ...                                                                              |
91*c05d8e5dSAndroid Build Coastguard Worker +----------------------------------------------------------------------------------+
92*c05d8e5dSAndroid Build Coastguard Worker #endif  // __USING_SJLJ_EXCEPTIONS__
93*c05d8e5dSAndroid Build Coastguard Worker +---------------------------------------------------------------------+
94*c05d8e5dSAndroid Build Coastguard Worker | Beginning of Action Table       ttypeIndex == 0 : cleanup           |
95*c05d8e5dSAndroid Build Coastguard Worker | ...                             ttypeIndex  > 0 : catch             |
96*c05d8e5dSAndroid Build Coastguard Worker |                                 ttypeIndex  < 0 : exception spec    |
97*c05d8e5dSAndroid Build Coastguard Worker | +--------------+-----------+--------------------------------------+ |
98*c05d8e5dSAndroid Build Coastguard Worker | | ttypeIndex   | (SLEB128) | Index into type_info Table (1-based) | |
99*c05d8e5dSAndroid Build Coastguard Worker | | actionOffset | (SLEB128) | Offset into next Action Table entry  | |
100*c05d8e5dSAndroid Build Coastguard Worker | +--------------+-----------+--------------------------------------+ |
101*c05d8e5dSAndroid Build Coastguard Worker | ...                                                                 |
102*c05d8e5dSAndroid Build Coastguard Worker +---------------------------------------------------------------------+-----------------+
103*c05d8e5dSAndroid Build Coastguard Worker | type_info Table, but classInfoOffset does *not* point here!                           |
104*c05d8e5dSAndroid Build Coastguard Worker | +----------------+------------------------------------------------+-----------------+ |
105*c05d8e5dSAndroid Build Coastguard Worker | | Nth type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == N | |
106*c05d8e5dSAndroid Build Coastguard Worker | +----------------+------------------------------------------------+-----------------+ |
107*c05d8e5dSAndroid Build Coastguard Worker | ...                                                                                   |
108*c05d8e5dSAndroid Build Coastguard Worker | +----------------+------------------------------------------------+-----------------+ |
109*c05d8e5dSAndroid Build Coastguard Worker | | 1st type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == 1 | |
110*c05d8e5dSAndroid Build Coastguard Worker | +----------------+------------------------------------------------+-----------------+ |
111*c05d8e5dSAndroid Build Coastguard Worker | +---------------------------------------+-----------+------------------------------+  |
112*c05d8e5dSAndroid Build Coastguard Worker | | 1st ttypeIndex for 1st exception spec | (ULEB128) | classInfoOffset points here! |  |
113*c05d8e5dSAndroid Build Coastguard Worker | | ...                                   | (ULEB128) |                              |  |
114*c05d8e5dSAndroid Build Coastguard Worker | | Mth ttypeIndex for 1st exception spec | (ULEB128) |                              |  |
115*c05d8e5dSAndroid Build Coastguard Worker | | 0                                     | (ULEB128) |                              |  |
116*c05d8e5dSAndroid Build Coastguard Worker | +---------------------------------------+------------------------------------------+  |
117*c05d8e5dSAndroid Build Coastguard Worker | ...                                                                                   |
118*c05d8e5dSAndroid Build Coastguard Worker | +---------------------------------------+------------------------------------------+  |
119*c05d8e5dSAndroid Build Coastguard Worker | | 0                                     | (ULEB128) | throw()                      |  |
120*c05d8e5dSAndroid Build Coastguard Worker | +---------------------------------------+------------------------------------------+  |
121*c05d8e5dSAndroid Build Coastguard Worker | ...                                                                                   |
122*c05d8e5dSAndroid Build Coastguard Worker | +---------------------------------------+------------------------------------------+  |
123*c05d8e5dSAndroid Build Coastguard Worker | | 1st ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
124*c05d8e5dSAndroid Build Coastguard Worker | | ...                                   | (ULEB128) |                              |  |
125*c05d8e5dSAndroid Build Coastguard Worker | | Mth ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
126*c05d8e5dSAndroid Build Coastguard Worker | | 0                                     | (ULEB128) |                              |  |
127*c05d8e5dSAndroid Build Coastguard Worker | +---------------------------------------+------------------------------------------+  |
128*c05d8e5dSAndroid Build Coastguard Worker +---------------------------------------------------------------------------------------+
129*c05d8e5dSAndroid Build Coastguard Worker 
130*c05d8e5dSAndroid Build Coastguard Worker Notes:
131*c05d8e5dSAndroid Build Coastguard Worker 
132*c05d8e5dSAndroid Build Coastguard Worker *  ttypeIndex in the Action Table, and in the exception spec table, is an index,
133*c05d8e5dSAndroid Build Coastguard Worker      not a byte count, if positive.  It is a negative index offset of
134*c05d8e5dSAndroid Build Coastguard Worker      classInfoOffset and the sizeof entry depends on ttypeEncoding.
135*c05d8e5dSAndroid Build Coastguard Worker    But if ttypeIndex is negative, it is a positive 1-based byte offset into the
136*c05d8e5dSAndroid Build Coastguard Worker      type_info Table.
137*c05d8e5dSAndroid Build Coastguard Worker    And if ttypeIndex is zero, it refers to a catch (...).
138*c05d8e5dSAndroid Build Coastguard Worker 
139*c05d8e5dSAndroid Build Coastguard Worker *  landingPad can be 0, this implies there is nothing to be done.
140*c05d8e5dSAndroid Build Coastguard Worker 
141*c05d8e5dSAndroid Build Coastguard Worker *  landingPad != 0 and actionEntry == 0 implies a cleanup needs to be done
142*c05d8e5dSAndroid Build Coastguard Worker      @landingPad.
143*c05d8e5dSAndroid Build Coastguard Worker 
144*c05d8e5dSAndroid Build Coastguard Worker *  A cleanup can also be found under landingPad != 0 and actionEntry != 0 in
145*c05d8e5dSAndroid Build Coastguard Worker      the Action Table with ttypeIndex == 0.
146*c05d8e5dSAndroid Build Coastguard Worker */
147*c05d8e5dSAndroid Build Coastguard Worker 
148*c05d8e5dSAndroid Build Coastguard Worker namespace __cxxabiv1
149*c05d8e5dSAndroid Build Coastguard Worker {
150*c05d8e5dSAndroid Build Coastguard Worker 
151*c05d8e5dSAndroid Build Coastguard Worker namespace
152*c05d8e5dSAndroid Build Coastguard Worker {
153*c05d8e5dSAndroid Build Coastguard Worker 
154*c05d8e5dSAndroid Build Coastguard Worker template <class AsType>
readPointerHelper(const uint8_t * & p)155*c05d8e5dSAndroid Build Coastguard Worker uintptr_t readPointerHelper(const uint8_t*& p) {
156*c05d8e5dSAndroid Build Coastguard Worker     AsType value;
157*c05d8e5dSAndroid Build Coastguard Worker     memcpy(&value, p, sizeof(AsType));
158*c05d8e5dSAndroid Build Coastguard Worker     p += sizeof(AsType);
159*c05d8e5dSAndroid Build Coastguard Worker     return static_cast<uintptr_t>(value);
160*c05d8e5dSAndroid Build Coastguard Worker }
161*c05d8e5dSAndroid Build Coastguard Worker 
162*c05d8e5dSAndroid Build Coastguard Worker } // end namespace
163*c05d8e5dSAndroid Build Coastguard Worker 
164*c05d8e5dSAndroid Build Coastguard Worker extern "C"
165*c05d8e5dSAndroid Build Coastguard Worker {
166*c05d8e5dSAndroid Build Coastguard Worker 
167*c05d8e5dSAndroid Build Coastguard Worker // private API
168*c05d8e5dSAndroid Build Coastguard Worker 
169*c05d8e5dSAndroid Build Coastguard Worker // Heavily borrowed from llvm/examples/ExceptionDemo/ExceptionDemo.cpp
170*c05d8e5dSAndroid Build Coastguard Worker 
171*c05d8e5dSAndroid Build Coastguard Worker // DWARF Constants
172*c05d8e5dSAndroid Build Coastguard Worker enum
173*c05d8e5dSAndroid Build Coastguard Worker {
174*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_absptr   = 0x00,
175*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_uleb128  = 0x01,
176*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_udata2   = 0x02,
177*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_udata4   = 0x03,
178*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_udata8   = 0x04,
179*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_sleb128  = 0x09,
180*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_sdata2   = 0x0A,
181*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_sdata4   = 0x0B,
182*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_sdata8   = 0x0C,
183*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_pcrel    = 0x10,
184*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_textrel  = 0x20,
185*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_datarel  = 0x30,
186*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_funcrel  = 0x40,
187*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_aligned  = 0x50,
188*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_indirect = 0x80,
189*c05d8e5dSAndroid Build Coastguard Worker     DW_EH_PE_omit     = 0xFF
190*c05d8e5dSAndroid Build Coastguard Worker };
191*c05d8e5dSAndroid Build Coastguard Worker 
192*c05d8e5dSAndroid Build Coastguard Worker /// Read a uleb128 encoded value and advance pointer
193*c05d8e5dSAndroid Build Coastguard Worker /// See Variable Length Data Appendix C in:
194*c05d8e5dSAndroid Build Coastguard Worker /// @link http://dwarfstd.org/Dwarf4.pdf @unlink
195*c05d8e5dSAndroid Build Coastguard Worker /// @param data reference variable holding memory pointer to decode from
196*c05d8e5dSAndroid Build Coastguard Worker /// @returns decoded value
197*c05d8e5dSAndroid Build Coastguard Worker static
198*c05d8e5dSAndroid Build Coastguard Worker uintptr_t
readULEB128(const uint8_t ** data)199*c05d8e5dSAndroid Build Coastguard Worker readULEB128(const uint8_t** data)
200*c05d8e5dSAndroid Build Coastguard Worker {
201*c05d8e5dSAndroid Build Coastguard Worker     uintptr_t result = 0;
202*c05d8e5dSAndroid Build Coastguard Worker     uintptr_t shift = 0;
203*c05d8e5dSAndroid Build Coastguard Worker     unsigned char byte;
204*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t *p = *data;
205*c05d8e5dSAndroid Build Coastguard Worker     do
206*c05d8e5dSAndroid Build Coastguard Worker     {
207*c05d8e5dSAndroid Build Coastguard Worker         byte = *p++;
208*c05d8e5dSAndroid Build Coastguard Worker         result |= static_cast<uintptr_t>(byte & 0x7F) << shift;
209*c05d8e5dSAndroid Build Coastguard Worker         shift += 7;
210*c05d8e5dSAndroid Build Coastguard Worker     } while (byte & 0x80);
211*c05d8e5dSAndroid Build Coastguard Worker     *data = p;
212*c05d8e5dSAndroid Build Coastguard Worker     return result;
213*c05d8e5dSAndroid Build Coastguard Worker }
214*c05d8e5dSAndroid Build Coastguard Worker 
215*c05d8e5dSAndroid Build Coastguard Worker /// Read a sleb128 encoded value and advance pointer
216*c05d8e5dSAndroid Build Coastguard Worker /// See Variable Length Data Appendix C in:
217*c05d8e5dSAndroid Build Coastguard Worker /// @link http://dwarfstd.org/Dwarf4.pdf @unlink
218*c05d8e5dSAndroid Build Coastguard Worker /// @param data reference variable holding memory pointer to decode from
219*c05d8e5dSAndroid Build Coastguard Worker /// @returns decoded value
220*c05d8e5dSAndroid Build Coastguard Worker static
221*c05d8e5dSAndroid Build Coastguard Worker intptr_t
readSLEB128(const uint8_t ** data)222*c05d8e5dSAndroid Build Coastguard Worker readSLEB128(const uint8_t** data)
223*c05d8e5dSAndroid Build Coastguard Worker {
224*c05d8e5dSAndroid Build Coastguard Worker     uintptr_t result = 0;
225*c05d8e5dSAndroid Build Coastguard Worker     uintptr_t shift = 0;
226*c05d8e5dSAndroid Build Coastguard Worker     unsigned char byte;
227*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t *p = *data;
228*c05d8e5dSAndroid Build Coastguard Worker     do
229*c05d8e5dSAndroid Build Coastguard Worker     {
230*c05d8e5dSAndroid Build Coastguard Worker         byte = *p++;
231*c05d8e5dSAndroid Build Coastguard Worker         result |= static_cast<uintptr_t>(byte & 0x7F) << shift;
232*c05d8e5dSAndroid Build Coastguard Worker         shift += 7;
233*c05d8e5dSAndroid Build Coastguard Worker     } while (byte & 0x80);
234*c05d8e5dSAndroid Build Coastguard Worker     *data = p;
235*c05d8e5dSAndroid Build Coastguard Worker     if ((byte & 0x40) && (shift < (sizeof(result) << 3)))
236*c05d8e5dSAndroid Build Coastguard Worker         result |= static_cast<uintptr_t>(~0) << shift;
237*c05d8e5dSAndroid Build Coastguard Worker     return static_cast<intptr_t>(result);
238*c05d8e5dSAndroid Build Coastguard Worker }
239*c05d8e5dSAndroid Build Coastguard Worker 
240*c05d8e5dSAndroid Build Coastguard Worker /// Read a pointer encoded value and advance pointer
241*c05d8e5dSAndroid Build Coastguard Worker /// See Variable Length Data in:
242*c05d8e5dSAndroid Build Coastguard Worker /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
243*c05d8e5dSAndroid Build Coastguard Worker /// @param data reference variable holding memory pointer to decode from
244*c05d8e5dSAndroid Build Coastguard Worker /// @param encoding dwarf encoding type
245*c05d8e5dSAndroid Build Coastguard Worker /// @returns decoded value
246*c05d8e5dSAndroid Build Coastguard Worker static
247*c05d8e5dSAndroid Build Coastguard Worker uintptr_t
readEncodedPointer(const uint8_t ** data,uint8_t encoding)248*c05d8e5dSAndroid Build Coastguard Worker readEncodedPointer(const uint8_t** data, uint8_t encoding)
249*c05d8e5dSAndroid Build Coastguard Worker {
250*c05d8e5dSAndroid Build Coastguard Worker     uintptr_t result = 0;
251*c05d8e5dSAndroid Build Coastguard Worker     if (encoding == DW_EH_PE_omit)
252*c05d8e5dSAndroid Build Coastguard Worker         return result;
253*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* p = *data;
254*c05d8e5dSAndroid Build Coastguard Worker     // first get value
255*c05d8e5dSAndroid Build Coastguard Worker     switch (encoding & 0x0F)
256*c05d8e5dSAndroid Build Coastguard Worker     {
257*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_absptr:
258*c05d8e5dSAndroid Build Coastguard Worker         result = readPointerHelper<uintptr_t>(p);
259*c05d8e5dSAndroid Build Coastguard Worker         break;
260*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_uleb128:
261*c05d8e5dSAndroid Build Coastguard Worker         result = readULEB128(&p);
262*c05d8e5dSAndroid Build Coastguard Worker         break;
263*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_sleb128:
264*c05d8e5dSAndroid Build Coastguard Worker         result = static_cast<uintptr_t>(readSLEB128(&p));
265*c05d8e5dSAndroid Build Coastguard Worker         break;
266*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_udata2:
267*c05d8e5dSAndroid Build Coastguard Worker         result = readPointerHelper<uint16_t>(p);
268*c05d8e5dSAndroid Build Coastguard Worker         break;
269*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_udata4:
270*c05d8e5dSAndroid Build Coastguard Worker         result = readPointerHelper<uint32_t>(p);
271*c05d8e5dSAndroid Build Coastguard Worker         break;
272*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_udata8:
273*c05d8e5dSAndroid Build Coastguard Worker         result = readPointerHelper<uint64_t>(p);
274*c05d8e5dSAndroid Build Coastguard Worker         break;
275*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata2:
276*c05d8e5dSAndroid Build Coastguard Worker         result = readPointerHelper<int16_t>(p);
277*c05d8e5dSAndroid Build Coastguard Worker         break;
278*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata4:
279*c05d8e5dSAndroid Build Coastguard Worker         result = readPointerHelper<int32_t>(p);
280*c05d8e5dSAndroid Build Coastguard Worker         break;
281*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata8:
282*c05d8e5dSAndroid Build Coastguard Worker         result = readPointerHelper<int64_t>(p);
283*c05d8e5dSAndroid Build Coastguard Worker         break;
284*c05d8e5dSAndroid Build Coastguard Worker     default:
285*c05d8e5dSAndroid Build Coastguard Worker         // not supported
286*c05d8e5dSAndroid Build Coastguard Worker         abort();
287*c05d8e5dSAndroid Build Coastguard Worker         break;
288*c05d8e5dSAndroid Build Coastguard Worker     }
289*c05d8e5dSAndroid Build Coastguard Worker     // then add relative offset
290*c05d8e5dSAndroid Build Coastguard Worker     switch (encoding & 0x70)
291*c05d8e5dSAndroid Build Coastguard Worker     {
292*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_absptr:
293*c05d8e5dSAndroid Build Coastguard Worker         // do nothing
294*c05d8e5dSAndroid Build Coastguard Worker         break;
295*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_pcrel:
296*c05d8e5dSAndroid Build Coastguard Worker         if (result)
297*c05d8e5dSAndroid Build Coastguard Worker             result += (uintptr_t)(*data);
298*c05d8e5dSAndroid Build Coastguard Worker         break;
299*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_textrel:
300*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_datarel:
301*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_funcrel:
302*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_aligned:
303*c05d8e5dSAndroid Build Coastguard Worker     default:
304*c05d8e5dSAndroid Build Coastguard Worker         // not supported
305*c05d8e5dSAndroid Build Coastguard Worker         abort();
306*c05d8e5dSAndroid Build Coastguard Worker         break;
307*c05d8e5dSAndroid Build Coastguard Worker     }
308*c05d8e5dSAndroid Build Coastguard Worker     // then apply indirection
309*c05d8e5dSAndroid Build Coastguard Worker     if (result && (encoding & DW_EH_PE_indirect))
310*c05d8e5dSAndroid Build Coastguard Worker         result = *((uintptr_t*)result);
311*c05d8e5dSAndroid Build Coastguard Worker     *data = p;
312*c05d8e5dSAndroid Build Coastguard Worker     return result;
313*c05d8e5dSAndroid Build Coastguard Worker }
314*c05d8e5dSAndroid Build Coastguard Worker 
315*c05d8e5dSAndroid Build Coastguard Worker static
316*c05d8e5dSAndroid Build Coastguard Worker void
call_terminate(bool native_exception,_Unwind_Exception * unwind_exception)317*c05d8e5dSAndroid Build Coastguard Worker call_terminate(bool native_exception, _Unwind_Exception* unwind_exception)
318*c05d8e5dSAndroid Build Coastguard Worker {
319*c05d8e5dSAndroid Build Coastguard Worker     __cxa_begin_catch(unwind_exception);
320*c05d8e5dSAndroid Build Coastguard Worker     if (native_exception)
321*c05d8e5dSAndroid Build Coastguard Worker     {
322*c05d8e5dSAndroid Build Coastguard Worker         // Use the stored terminate_handler if possible
323*c05d8e5dSAndroid Build Coastguard Worker         __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
324*c05d8e5dSAndroid Build Coastguard Worker         std::__terminate(exception_header->terminateHandler);
325*c05d8e5dSAndroid Build Coastguard Worker     }
326*c05d8e5dSAndroid Build Coastguard Worker     std::terminate();
327*c05d8e5dSAndroid Build Coastguard Worker }
328*c05d8e5dSAndroid Build Coastguard Worker 
329*c05d8e5dSAndroid Build Coastguard Worker #if defined(_LIBCXXABI_ARM_EHABI)
read_target2_value(const void * ptr)330*c05d8e5dSAndroid Build Coastguard Worker static const void* read_target2_value(const void* ptr)
331*c05d8e5dSAndroid Build Coastguard Worker {
332*c05d8e5dSAndroid Build Coastguard Worker     uintptr_t offset = *reinterpret_cast<const uintptr_t*>(ptr);
333*c05d8e5dSAndroid Build Coastguard Worker     if (!offset)
334*c05d8e5dSAndroid Build Coastguard Worker         return 0;
335*c05d8e5dSAndroid Build Coastguard Worker     // "ARM EABI provides a TARGET2 relocation to describe these typeinfo
336*c05d8e5dSAndroid Build Coastguard Worker     // pointers. The reason being it allows their precise semantics to be
337*c05d8e5dSAndroid Build Coastguard Worker     // deferred to the linker. For bare-metal they turn into absolute
338*c05d8e5dSAndroid Build Coastguard Worker     // relocations. For linux they turn into GOT-REL relocations."
339*c05d8e5dSAndroid Build Coastguard Worker     // https://gcc.gnu.org/ml/gcc-patches/2009-08/msg00264.html
340*c05d8e5dSAndroid Build Coastguard Worker #if defined(LIBCXXABI_BAREMETAL)
341*c05d8e5dSAndroid Build Coastguard Worker     return reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(ptr) +
342*c05d8e5dSAndroid Build Coastguard Worker                                          offset);
343*c05d8e5dSAndroid Build Coastguard Worker #else
344*c05d8e5dSAndroid Build Coastguard Worker     return *reinterpret_cast<const void **>(reinterpret_cast<uintptr_t>(ptr) +
345*c05d8e5dSAndroid Build Coastguard Worker                                             offset);
346*c05d8e5dSAndroid Build Coastguard Worker #endif
347*c05d8e5dSAndroid Build Coastguard Worker }
348*c05d8e5dSAndroid Build Coastguard Worker 
349*c05d8e5dSAndroid Build Coastguard Worker static const __shim_type_info*
get_shim_type_info(uint64_t ttypeIndex,const uint8_t * classInfo,uint8_t ttypeEncoding,bool native_exception,_Unwind_Exception * unwind_exception)350*c05d8e5dSAndroid Build Coastguard Worker get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
351*c05d8e5dSAndroid Build Coastguard Worker                    uint8_t ttypeEncoding, bool native_exception,
352*c05d8e5dSAndroid Build Coastguard Worker                    _Unwind_Exception* unwind_exception)
353*c05d8e5dSAndroid Build Coastguard Worker {
354*c05d8e5dSAndroid Build Coastguard Worker     if (classInfo == 0)
355*c05d8e5dSAndroid Build Coastguard Worker     {
356*c05d8e5dSAndroid Build Coastguard Worker         // this should not happen.  Indicates corrupted eh_table.
357*c05d8e5dSAndroid Build Coastguard Worker         call_terminate(native_exception, unwind_exception);
358*c05d8e5dSAndroid Build Coastguard Worker     }
359*c05d8e5dSAndroid Build Coastguard Worker 
360*c05d8e5dSAndroid Build Coastguard Worker     assert(((ttypeEncoding == DW_EH_PE_absptr) ||  // LLVM or GCC 4.6
361*c05d8e5dSAndroid Build Coastguard Worker             (ttypeEncoding == DW_EH_PE_pcrel) ||  // GCC 4.7 baremetal
362*c05d8e5dSAndroid Build Coastguard Worker             (ttypeEncoding == (DW_EH_PE_pcrel | DW_EH_PE_indirect))) &&  // GCC 4.7 linux
363*c05d8e5dSAndroid Build Coastguard Worker            "Unexpected TTypeEncoding");
364*c05d8e5dSAndroid Build Coastguard Worker     (void)ttypeEncoding;
365*c05d8e5dSAndroid Build Coastguard Worker 
366*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* ttypePtr = classInfo - ttypeIndex * sizeof(uintptr_t);
367*c05d8e5dSAndroid Build Coastguard Worker     return reinterpret_cast<const __shim_type_info *>(
368*c05d8e5dSAndroid Build Coastguard Worker         read_target2_value(ttypePtr));
369*c05d8e5dSAndroid Build Coastguard Worker }
370*c05d8e5dSAndroid Build Coastguard Worker #else // !defined(_LIBCXXABI_ARM_EHABI)
371*c05d8e5dSAndroid Build Coastguard Worker static
372*c05d8e5dSAndroid Build Coastguard Worker const __shim_type_info*
get_shim_type_info(uint64_t ttypeIndex,const uint8_t * classInfo,uint8_t ttypeEncoding,bool native_exception,_Unwind_Exception * unwind_exception)373*c05d8e5dSAndroid Build Coastguard Worker get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
374*c05d8e5dSAndroid Build Coastguard Worker                    uint8_t ttypeEncoding, bool native_exception,
375*c05d8e5dSAndroid Build Coastguard Worker                    _Unwind_Exception* unwind_exception)
376*c05d8e5dSAndroid Build Coastguard Worker {
377*c05d8e5dSAndroid Build Coastguard Worker     if (classInfo == 0)
378*c05d8e5dSAndroid Build Coastguard Worker     {
379*c05d8e5dSAndroid Build Coastguard Worker         // this should not happen.  Indicates corrupted eh_table.
380*c05d8e5dSAndroid Build Coastguard Worker         call_terminate(native_exception, unwind_exception);
381*c05d8e5dSAndroid Build Coastguard Worker     }
382*c05d8e5dSAndroid Build Coastguard Worker     switch (ttypeEncoding & 0x0F)
383*c05d8e5dSAndroid Build Coastguard Worker     {
384*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_absptr:
385*c05d8e5dSAndroid Build Coastguard Worker         ttypeIndex *= sizeof(void*);
386*c05d8e5dSAndroid Build Coastguard Worker         break;
387*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_udata2:
388*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata2:
389*c05d8e5dSAndroid Build Coastguard Worker         ttypeIndex *= 2;
390*c05d8e5dSAndroid Build Coastguard Worker         break;
391*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_udata4:
392*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata4:
393*c05d8e5dSAndroid Build Coastguard Worker         ttypeIndex *= 4;
394*c05d8e5dSAndroid Build Coastguard Worker         break;
395*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_udata8:
396*c05d8e5dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata8:
397*c05d8e5dSAndroid Build Coastguard Worker         ttypeIndex *= 8;
398*c05d8e5dSAndroid Build Coastguard Worker         break;
399*c05d8e5dSAndroid Build Coastguard Worker     default:
400*c05d8e5dSAndroid Build Coastguard Worker         // this should not happen.   Indicates corrupted eh_table.
401*c05d8e5dSAndroid Build Coastguard Worker         call_terminate(native_exception, unwind_exception);
402*c05d8e5dSAndroid Build Coastguard Worker     }
403*c05d8e5dSAndroid Build Coastguard Worker     classInfo -= ttypeIndex;
404*c05d8e5dSAndroid Build Coastguard Worker     return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding);
405*c05d8e5dSAndroid Build Coastguard Worker }
406*c05d8e5dSAndroid Build Coastguard Worker #endif // !defined(_LIBCXXABI_ARM_EHABI)
407*c05d8e5dSAndroid Build Coastguard Worker 
408*c05d8e5dSAndroid Build Coastguard Worker /*
409*c05d8e5dSAndroid Build Coastguard Worker     This is checking a thrown exception type, excpType, against a possibly empty
410*c05d8e5dSAndroid Build Coastguard Worker     list of catchType's which make up an exception spec.
411*c05d8e5dSAndroid Build Coastguard Worker 
412*c05d8e5dSAndroid Build Coastguard Worker     An exception spec acts like a catch handler, but in reverse.  This "catch
413*c05d8e5dSAndroid Build Coastguard Worker     handler" will catch an excpType if and only if none of the catchType's in
414*c05d8e5dSAndroid Build Coastguard Worker     the list will catch a excpType.  If any catchType in the list can catch an
415*c05d8e5dSAndroid Build Coastguard Worker     excpType, then this exception spec does not catch the excpType.
416*c05d8e5dSAndroid Build Coastguard Worker */
417*c05d8e5dSAndroid Build Coastguard Worker #if defined(_LIBCXXABI_ARM_EHABI)
418*c05d8e5dSAndroid Build Coastguard Worker static
419*c05d8e5dSAndroid Build Coastguard Worker bool
exception_spec_can_catch(int64_t specIndex,const uint8_t * classInfo,uint8_t ttypeEncoding,const __shim_type_info * excpType,void * adjustedPtr,_Unwind_Exception * unwind_exception)420*c05d8e5dSAndroid Build Coastguard Worker exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
421*c05d8e5dSAndroid Build Coastguard Worker                          uint8_t ttypeEncoding, const __shim_type_info* excpType,
422*c05d8e5dSAndroid Build Coastguard Worker                          void* adjustedPtr, _Unwind_Exception* unwind_exception)
423*c05d8e5dSAndroid Build Coastguard Worker {
424*c05d8e5dSAndroid Build Coastguard Worker     if (classInfo == 0)
425*c05d8e5dSAndroid Build Coastguard Worker     {
426*c05d8e5dSAndroid Build Coastguard Worker         // this should not happen.   Indicates corrupted eh_table.
427*c05d8e5dSAndroid Build Coastguard Worker         call_terminate(false, unwind_exception);
428*c05d8e5dSAndroid Build Coastguard Worker     }
429*c05d8e5dSAndroid Build Coastguard Worker 
430*c05d8e5dSAndroid Build Coastguard Worker     assert(((ttypeEncoding == DW_EH_PE_absptr) ||  // LLVM or GCC 4.6
431*c05d8e5dSAndroid Build Coastguard Worker             (ttypeEncoding == DW_EH_PE_pcrel) ||  // GCC 4.7 baremetal
432*c05d8e5dSAndroid Build Coastguard Worker             (ttypeEncoding == (DW_EH_PE_pcrel | DW_EH_PE_indirect))) &&  // GCC 4.7 linux
433*c05d8e5dSAndroid Build Coastguard Worker            "Unexpected TTypeEncoding");
434*c05d8e5dSAndroid Build Coastguard Worker     (void)ttypeEncoding;
435*c05d8e5dSAndroid Build Coastguard Worker 
436*c05d8e5dSAndroid Build Coastguard Worker     // specIndex is negative of 1-based byte offset into classInfo;
437*c05d8e5dSAndroid Build Coastguard Worker     specIndex = -specIndex;
438*c05d8e5dSAndroid Build Coastguard Worker     --specIndex;
439*c05d8e5dSAndroid Build Coastguard Worker     const void** temp = reinterpret_cast<const void**>(
440*c05d8e5dSAndroid Build Coastguard Worker         reinterpret_cast<uintptr_t>(classInfo) +
441*c05d8e5dSAndroid Build Coastguard Worker         static_cast<uintptr_t>(specIndex) * sizeof(uintptr_t));
442*c05d8e5dSAndroid Build Coastguard Worker     // If any type in the spec list can catch excpType, return false, else return true
443*c05d8e5dSAndroid Build Coastguard Worker     //    adjustments to adjustedPtr are ignored.
444*c05d8e5dSAndroid Build Coastguard Worker     while (true)
445*c05d8e5dSAndroid Build Coastguard Worker     {
446*c05d8e5dSAndroid Build Coastguard Worker         // ARM EHABI exception specification table (filter table) consists of
447*c05d8e5dSAndroid Build Coastguard Worker         // several pointers which will directly point to the type info object
448*c05d8e5dSAndroid Build Coastguard Worker         // (instead of ttypeIndex).  The table will be terminated with 0.
449*c05d8e5dSAndroid Build Coastguard Worker         const void** ttypePtr = temp++;
450*c05d8e5dSAndroid Build Coastguard Worker         if (*ttypePtr == 0)
451*c05d8e5dSAndroid Build Coastguard Worker             break;
452*c05d8e5dSAndroid Build Coastguard Worker         // We can get the __shim_type_info simply by performing a
453*c05d8e5dSAndroid Build Coastguard Worker         // R_ARM_TARGET2 relocation, and cast the result to __shim_type_info.
454*c05d8e5dSAndroid Build Coastguard Worker         const __shim_type_info* catchType =
455*c05d8e5dSAndroid Build Coastguard Worker             static_cast<const __shim_type_info*>(read_target2_value(ttypePtr));
456*c05d8e5dSAndroid Build Coastguard Worker         void* tempPtr = adjustedPtr;
457*c05d8e5dSAndroid Build Coastguard Worker         if (catchType->can_catch(excpType, tempPtr))
458*c05d8e5dSAndroid Build Coastguard Worker             return false;
459*c05d8e5dSAndroid Build Coastguard Worker     }
460*c05d8e5dSAndroid Build Coastguard Worker     return true;
461*c05d8e5dSAndroid Build Coastguard Worker }
462*c05d8e5dSAndroid Build Coastguard Worker #else
463*c05d8e5dSAndroid Build Coastguard Worker static
464*c05d8e5dSAndroid Build Coastguard Worker bool
exception_spec_can_catch(int64_t specIndex,const uint8_t * classInfo,uint8_t ttypeEncoding,const __shim_type_info * excpType,void * adjustedPtr,_Unwind_Exception * unwind_exception)465*c05d8e5dSAndroid Build Coastguard Worker exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
466*c05d8e5dSAndroid Build Coastguard Worker                          uint8_t ttypeEncoding, const __shim_type_info* excpType,
467*c05d8e5dSAndroid Build Coastguard Worker                          void* adjustedPtr, _Unwind_Exception* unwind_exception)
468*c05d8e5dSAndroid Build Coastguard Worker {
469*c05d8e5dSAndroid Build Coastguard Worker     if (classInfo == 0)
470*c05d8e5dSAndroid Build Coastguard Worker     {
471*c05d8e5dSAndroid Build Coastguard Worker         // this should not happen.   Indicates corrupted eh_table.
472*c05d8e5dSAndroid Build Coastguard Worker         call_terminate(false, unwind_exception);
473*c05d8e5dSAndroid Build Coastguard Worker     }
474*c05d8e5dSAndroid Build Coastguard Worker     // specIndex is negative of 1-based byte offset into classInfo;
475*c05d8e5dSAndroid Build Coastguard Worker     specIndex = -specIndex;
476*c05d8e5dSAndroid Build Coastguard Worker     --specIndex;
477*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* temp = classInfo + specIndex;
478*c05d8e5dSAndroid Build Coastguard Worker     // If any type in the spec list can catch excpType, return false, else return true
479*c05d8e5dSAndroid Build Coastguard Worker     //    adjustments to adjustedPtr are ignored.
480*c05d8e5dSAndroid Build Coastguard Worker     while (true)
481*c05d8e5dSAndroid Build Coastguard Worker     {
482*c05d8e5dSAndroid Build Coastguard Worker         uint64_t ttypeIndex = readULEB128(&temp);
483*c05d8e5dSAndroid Build Coastguard Worker         if (ttypeIndex == 0)
484*c05d8e5dSAndroid Build Coastguard Worker             break;
485*c05d8e5dSAndroid Build Coastguard Worker         const __shim_type_info* catchType = get_shim_type_info(ttypeIndex,
486*c05d8e5dSAndroid Build Coastguard Worker                                                                classInfo,
487*c05d8e5dSAndroid Build Coastguard Worker                                                                ttypeEncoding,
488*c05d8e5dSAndroid Build Coastguard Worker                                                                true,
489*c05d8e5dSAndroid Build Coastguard Worker                                                                unwind_exception);
490*c05d8e5dSAndroid Build Coastguard Worker         void* tempPtr = adjustedPtr;
491*c05d8e5dSAndroid Build Coastguard Worker         if (catchType->can_catch(excpType, tempPtr))
492*c05d8e5dSAndroid Build Coastguard Worker             return false;
493*c05d8e5dSAndroid Build Coastguard Worker     }
494*c05d8e5dSAndroid Build Coastguard Worker     return true;
495*c05d8e5dSAndroid Build Coastguard Worker }
496*c05d8e5dSAndroid Build Coastguard Worker #endif
497*c05d8e5dSAndroid Build Coastguard Worker 
498*c05d8e5dSAndroid Build Coastguard Worker static
499*c05d8e5dSAndroid Build Coastguard Worker void*
get_thrown_object_ptr(_Unwind_Exception * unwind_exception)500*c05d8e5dSAndroid Build Coastguard Worker get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
501*c05d8e5dSAndroid Build Coastguard Worker {
502*c05d8e5dSAndroid Build Coastguard Worker     // Even for foreign exceptions, the exception object is *probably* at unwind_exception + 1
503*c05d8e5dSAndroid Build Coastguard Worker     //    Regardless, this library is prohibited from touching a foreign exception
504*c05d8e5dSAndroid Build Coastguard Worker     void* adjustedPtr = unwind_exception + 1;
505*c05d8e5dSAndroid Build Coastguard Worker     if (__getExceptionClass(unwind_exception) == kOurDependentExceptionClass)
506*c05d8e5dSAndroid Build Coastguard Worker         adjustedPtr = ((__cxa_dependent_exception*)adjustedPtr - 1)->primaryException;
507*c05d8e5dSAndroid Build Coastguard Worker     return adjustedPtr;
508*c05d8e5dSAndroid Build Coastguard Worker }
509*c05d8e5dSAndroid Build Coastguard Worker 
510*c05d8e5dSAndroid Build Coastguard Worker namespace
511*c05d8e5dSAndroid Build Coastguard Worker {
512*c05d8e5dSAndroid Build Coastguard Worker 
513*c05d8e5dSAndroid Build Coastguard Worker struct scan_results
514*c05d8e5dSAndroid Build Coastguard Worker {
515*c05d8e5dSAndroid Build Coastguard Worker     int64_t        ttypeIndex;   // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup
516*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* actionRecord;         // Currently unused.  Retained to ease future maintenance.
517*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* languageSpecificData;  // Needed only for __cxa_call_unexpected
518*c05d8e5dSAndroid Build Coastguard Worker     uintptr_t      landingPad;   // null -> nothing found, else something found
519*c05d8e5dSAndroid Build Coastguard Worker     void*          adjustedPtr;  // Used in cxa_exception.cpp
520*c05d8e5dSAndroid Build Coastguard Worker     _Unwind_Reason_Code reason;  // One of _URC_FATAL_PHASE1_ERROR,
521*c05d8e5dSAndroid Build Coastguard Worker                                  //        _URC_FATAL_PHASE2_ERROR,
522*c05d8e5dSAndroid Build Coastguard Worker                                  //        _URC_CONTINUE_UNWIND,
523*c05d8e5dSAndroid Build Coastguard Worker                                  //        _URC_HANDLER_FOUND
524*c05d8e5dSAndroid Build Coastguard Worker };
525*c05d8e5dSAndroid Build Coastguard Worker 
526*c05d8e5dSAndroid Build Coastguard Worker }  // unnamed namespace
527*c05d8e5dSAndroid Build Coastguard Worker 
528*c05d8e5dSAndroid Build Coastguard Worker static
529*c05d8e5dSAndroid Build Coastguard Worker void
set_registers(_Unwind_Exception * unwind_exception,_Unwind_Context * context,const scan_results & results)530*c05d8e5dSAndroid Build Coastguard Worker set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
531*c05d8e5dSAndroid Build Coastguard Worker               const scan_results& results)
532*c05d8e5dSAndroid Build Coastguard Worker {
533*c05d8e5dSAndroid Build Coastguard Worker #if defined(__USING_SJLJ_EXCEPTIONS__)
534*c05d8e5dSAndroid Build Coastguard Worker #define __builtin_eh_return_data_regno(regno) regno
535*c05d8e5dSAndroid Build Coastguard Worker #endif
536*c05d8e5dSAndroid Build Coastguard Worker   _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
537*c05d8e5dSAndroid Build Coastguard Worker                 reinterpret_cast<uintptr_t>(unwind_exception));
538*c05d8e5dSAndroid Build Coastguard Worker   _Unwind_SetGR(context, __builtin_eh_return_data_regno(1),
539*c05d8e5dSAndroid Build Coastguard Worker                 static_cast<uintptr_t>(results.ttypeIndex));
540*c05d8e5dSAndroid Build Coastguard Worker   _Unwind_SetIP(context, results.landingPad);
541*c05d8e5dSAndroid Build Coastguard Worker }
542*c05d8e5dSAndroid Build Coastguard Worker 
543*c05d8e5dSAndroid Build Coastguard Worker /*
544*c05d8e5dSAndroid Build Coastguard Worker     There are 3 types of scans needed:
545*c05d8e5dSAndroid Build Coastguard Worker 
546*c05d8e5dSAndroid Build Coastguard Worker     1.  Scan for handler with native or foreign exception.  If handler found,
547*c05d8e5dSAndroid Build Coastguard Worker         save state and return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND.
548*c05d8e5dSAndroid Build Coastguard Worker         May also report an error on invalid input.
549*c05d8e5dSAndroid Build Coastguard Worker         May terminate for invalid exception table.
550*c05d8e5dSAndroid Build Coastguard Worker         _UA_SEARCH_PHASE
551*c05d8e5dSAndroid Build Coastguard Worker 
552*c05d8e5dSAndroid Build Coastguard Worker     2.  Scan for handler with foreign exception.  Must return _URC_HANDLER_FOUND,
553*c05d8e5dSAndroid Build Coastguard Worker         or call terminate.
554*c05d8e5dSAndroid Build Coastguard Worker         _UA_CLEANUP_PHASE && _UA_HANDLER_FRAME && !native_exception
555*c05d8e5dSAndroid Build Coastguard Worker 
556*c05d8e5dSAndroid Build Coastguard Worker     3.  Scan for cleanups.  If a handler is found and this isn't forced unwind,
557*c05d8e5dSAndroid Build Coastguard Worker         then terminate, otherwise ignore the handler and keep looking for cleanup.
558*c05d8e5dSAndroid Build Coastguard Worker         If a cleanup is found, return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND.
559*c05d8e5dSAndroid Build Coastguard Worker         May also report an error on invalid input.
560*c05d8e5dSAndroid Build Coastguard Worker         May terminate for invalid exception table.
561*c05d8e5dSAndroid Build Coastguard Worker         _UA_CLEANUP_PHASE && !_UA_HANDLER_FRAME
562*c05d8e5dSAndroid Build Coastguard Worker */
563*c05d8e5dSAndroid Build Coastguard Worker 
scan_eh_tab(scan_results & results,_Unwind_Action actions,bool native_exception,_Unwind_Exception * unwind_exception,_Unwind_Context * context)564*c05d8e5dSAndroid Build Coastguard Worker static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
565*c05d8e5dSAndroid Build Coastguard Worker                         bool native_exception,
566*c05d8e5dSAndroid Build Coastguard Worker                         _Unwind_Exception *unwind_exception,
567*c05d8e5dSAndroid Build Coastguard Worker                         _Unwind_Context *context) {
568*c05d8e5dSAndroid Build Coastguard Worker     // Initialize results to found nothing but an error
569*c05d8e5dSAndroid Build Coastguard Worker     results.ttypeIndex = 0;
570*c05d8e5dSAndroid Build Coastguard Worker     results.actionRecord = 0;
571*c05d8e5dSAndroid Build Coastguard Worker     results.languageSpecificData = 0;
572*c05d8e5dSAndroid Build Coastguard Worker     results.landingPad = 0;
573*c05d8e5dSAndroid Build Coastguard Worker     results.adjustedPtr = 0;
574*c05d8e5dSAndroid Build Coastguard Worker     results.reason = _URC_FATAL_PHASE1_ERROR;
575*c05d8e5dSAndroid Build Coastguard Worker     // Check for consistent actions
576*c05d8e5dSAndroid Build Coastguard Worker     if (actions & _UA_SEARCH_PHASE)
577*c05d8e5dSAndroid Build Coastguard Worker     {
578*c05d8e5dSAndroid Build Coastguard Worker         // Do Phase 1
579*c05d8e5dSAndroid Build Coastguard Worker         if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND))
580*c05d8e5dSAndroid Build Coastguard Worker         {
581*c05d8e5dSAndroid Build Coastguard Worker             // None of these flags should be set during Phase 1
582*c05d8e5dSAndroid Build Coastguard Worker             //   Client error
583*c05d8e5dSAndroid Build Coastguard Worker             results.reason = _URC_FATAL_PHASE1_ERROR;
584*c05d8e5dSAndroid Build Coastguard Worker             return;
585*c05d8e5dSAndroid Build Coastguard Worker         }
586*c05d8e5dSAndroid Build Coastguard Worker     }
587*c05d8e5dSAndroid Build Coastguard Worker     else if (actions & _UA_CLEANUP_PHASE)
588*c05d8e5dSAndroid Build Coastguard Worker     {
589*c05d8e5dSAndroid Build Coastguard Worker         if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND))
590*c05d8e5dSAndroid Build Coastguard Worker         {
591*c05d8e5dSAndroid Build Coastguard Worker             // _UA_HANDLER_FRAME should only be set if phase 1 found a handler.
592*c05d8e5dSAndroid Build Coastguard Worker             // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened.
593*c05d8e5dSAndroid Build Coastguard Worker             //    Client error
594*c05d8e5dSAndroid Build Coastguard Worker             results.reason = _URC_FATAL_PHASE2_ERROR;
595*c05d8e5dSAndroid Build Coastguard Worker             return;
596*c05d8e5dSAndroid Build Coastguard Worker         }
597*c05d8e5dSAndroid Build Coastguard Worker     }
598*c05d8e5dSAndroid Build Coastguard Worker     else // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set
599*c05d8e5dSAndroid Build Coastguard Worker     {
600*c05d8e5dSAndroid Build Coastguard Worker         // One of these should be set.
601*c05d8e5dSAndroid Build Coastguard Worker         //   Client error
602*c05d8e5dSAndroid Build Coastguard Worker         results.reason = _URC_FATAL_PHASE1_ERROR;
603*c05d8e5dSAndroid Build Coastguard Worker         return;
604*c05d8e5dSAndroid Build Coastguard Worker     }
605*c05d8e5dSAndroid Build Coastguard Worker     // Start scan by getting exception table address
606*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t *lsda = (const uint8_t *)_Unwind_GetLanguageSpecificData(context);
607*c05d8e5dSAndroid Build Coastguard Worker     if (lsda == 0)
608*c05d8e5dSAndroid Build Coastguard Worker     {
609*c05d8e5dSAndroid Build Coastguard Worker         // There is no exception table
610*c05d8e5dSAndroid Build Coastguard Worker         results.reason = _URC_CONTINUE_UNWIND;
611*c05d8e5dSAndroid Build Coastguard Worker         return;
612*c05d8e5dSAndroid Build Coastguard Worker     }
613*c05d8e5dSAndroid Build Coastguard Worker     results.languageSpecificData = lsda;
614*c05d8e5dSAndroid Build Coastguard Worker     // Get the current instruction pointer and offset it before next
615*c05d8e5dSAndroid Build Coastguard Worker     // instruction in the current frame which threw the exception.
616*c05d8e5dSAndroid Build Coastguard Worker     uintptr_t ip = _Unwind_GetIP(context) - 1;
617*c05d8e5dSAndroid Build Coastguard Worker     // Get beginning current frame's code (as defined by the
618*c05d8e5dSAndroid Build Coastguard Worker     // emitted dwarf code)
619*c05d8e5dSAndroid Build Coastguard Worker     uintptr_t funcStart = _Unwind_GetRegionStart(context);
620*c05d8e5dSAndroid Build Coastguard Worker #ifdef __USING_SJLJ_EXCEPTIONS__
621*c05d8e5dSAndroid Build Coastguard Worker     if (ip == uintptr_t(-1))
622*c05d8e5dSAndroid Build Coastguard Worker     {
623*c05d8e5dSAndroid Build Coastguard Worker         // no action
624*c05d8e5dSAndroid Build Coastguard Worker         results.reason = _URC_CONTINUE_UNWIND;
625*c05d8e5dSAndroid Build Coastguard Worker         return;
626*c05d8e5dSAndroid Build Coastguard Worker     }
627*c05d8e5dSAndroid Build Coastguard Worker     else if (ip == 0)
628*c05d8e5dSAndroid Build Coastguard Worker         call_terminate(native_exception, unwind_exception);
629*c05d8e5dSAndroid Build Coastguard Worker     // ip is 1-based index into call site table
630*c05d8e5dSAndroid Build Coastguard Worker #else  // !__USING_SJLJ_EXCEPTIONS__
631*c05d8e5dSAndroid Build Coastguard Worker     uintptr_t ipOffset = ip - funcStart;
632*c05d8e5dSAndroid Build Coastguard Worker #endif  // !defined(_USING_SLJL_EXCEPTIONS__)
633*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* classInfo = NULL;
634*c05d8e5dSAndroid Build Coastguard Worker     // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
635*c05d8e5dSAndroid Build Coastguard Worker     //       dwarf emission
636*c05d8e5dSAndroid Build Coastguard Worker     // Parse LSDA header.
637*c05d8e5dSAndroid Build Coastguard Worker     uint8_t lpStartEncoding = *lsda++;
638*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
639*c05d8e5dSAndroid Build Coastguard Worker     if (lpStart == 0)
640*c05d8e5dSAndroid Build Coastguard Worker         lpStart = (const uint8_t*)funcStart;
641*c05d8e5dSAndroid Build Coastguard Worker     uint8_t ttypeEncoding = *lsda++;
642*c05d8e5dSAndroid Build Coastguard Worker     if (ttypeEncoding != DW_EH_PE_omit)
643*c05d8e5dSAndroid Build Coastguard Worker     {
644*c05d8e5dSAndroid Build Coastguard Worker         // Calculate type info locations in emitted dwarf code which
645*c05d8e5dSAndroid Build Coastguard Worker         // were flagged by type info arguments to llvm.eh.selector
646*c05d8e5dSAndroid Build Coastguard Worker         // intrinsic
647*c05d8e5dSAndroid Build Coastguard Worker         uintptr_t classInfoOffset = readULEB128(&lsda);
648*c05d8e5dSAndroid Build Coastguard Worker         classInfo = lsda + classInfoOffset;
649*c05d8e5dSAndroid Build Coastguard Worker     }
650*c05d8e5dSAndroid Build Coastguard Worker     // Walk call-site table looking for range that
651*c05d8e5dSAndroid Build Coastguard Worker     // includes current PC.
652*c05d8e5dSAndroid Build Coastguard Worker     uint8_t callSiteEncoding = *lsda++;
653*c05d8e5dSAndroid Build Coastguard Worker #ifdef __USING_SJLJ_EXCEPTIONS__
654*c05d8e5dSAndroid Build Coastguard Worker     (void)callSiteEncoding;  // When using SjLj exceptions, callSiteEncoding is never used
655*c05d8e5dSAndroid Build Coastguard Worker #endif
656*c05d8e5dSAndroid Build Coastguard Worker     uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
657*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* callSiteTableStart = lsda;
658*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength;
659*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* actionTableStart = callSiteTableEnd;
660*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* callSitePtr = callSiteTableStart;
661*c05d8e5dSAndroid Build Coastguard Worker     while (callSitePtr < callSiteTableEnd)
662*c05d8e5dSAndroid Build Coastguard Worker     {
663*c05d8e5dSAndroid Build Coastguard Worker         // There is one entry per call site.
664*c05d8e5dSAndroid Build Coastguard Worker #ifndef __USING_SJLJ_EXCEPTIONS__
665*c05d8e5dSAndroid Build Coastguard Worker         // The call sites are non-overlapping in [start, start+length)
666*c05d8e5dSAndroid Build Coastguard Worker         // The call sites are ordered in increasing value of start
667*c05d8e5dSAndroid Build Coastguard Worker         uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
668*c05d8e5dSAndroid Build Coastguard Worker         uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding);
669*c05d8e5dSAndroid Build Coastguard Worker         uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
670*c05d8e5dSAndroid Build Coastguard Worker         uintptr_t actionEntry = readULEB128(&callSitePtr);
671*c05d8e5dSAndroid Build Coastguard Worker         if ((start <= ipOffset) && (ipOffset < (start + length)))
672*c05d8e5dSAndroid Build Coastguard Worker #else  // __USING_SJLJ_EXCEPTIONS__
673*c05d8e5dSAndroid Build Coastguard Worker         // ip is 1-based index into this table
674*c05d8e5dSAndroid Build Coastguard Worker         uintptr_t landingPad = readULEB128(&callSitePtr);
675*c05d8e5dSAndroid Build Coastguard Worker         uintptr_t actionEntry = readULEB128(&callSitePtr);
676*c05d8e5dSAndroid Build Coastguard Worker         if (--ip == 0)
677*c05d8e5dSAndroid Build Coastguard Worker #endif  // __USING_SJLJ_EXCEPTIONS__
678*c05d8e5dSAndroid Build Coastguard Worker         {
679*c05d8e5dSAndroid Build Coastguard Worker             // Found the call site containing ip.
680*c05d8e5dSAndroid Build Coastguard Worker #ifndef __USING_SJLJ_EXCEPTIONS__
681*c05d8e5dSAndroid Build Coastguard Worker             if (landingPad == 0)
682*c05d8e5dSAndroid Build Coastguard Worker             {
683*c05d8e5dSAndroid Build Coastguard Worker                 // No handler here
684*c05d8e5dSAndroid Build Coastguard Worker                 results.reason = _URC_CONTINUE_UNWIND;
685*c05d8e5dSAndroid Build Coastguard Worker                 return;
686*c05d8e5dSAndroid Build Coastguard Worker             }
687*c05d8e5dSAndroid Build Coastguard Worker             landingPad = (uintptr_t)lpStart + landingPad;
688*c05d8e5dSAndroid Build Coastguard Worker #else  // __USING_SJLJ_EXCEPTIONS__
689*c05d8e5dSAndroid Build Coastguard Worker             ++landingPad;
690*c05d8e5dSAndroid Build Coastguard Worker #endif  // __USING_SJLJ_EXCEPTIONS__
691*c05d8e5dSAndroid Build Coastguard Worker             if (actionEntry == 0)
692*c05d8e5dSAndroid Build Coastguard Worker             {
693*c05d8e5dSAndroid Build Coastguard Worker                 // Found a cleanup
694*c05d8e5dSAndroid Build Coastguard Worker                 // If this is a type 1 or type 2 search, there are no handlers
695*c05d8e5dSAndroid Build Coastguard Worker                 // If this is a type 3 search, you want to install the cleanup.
696*c05d8e5dSAndroid Build Coastguard Worker                 if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
697*c05d8e5dSAndroid Build Coastguard Worker                 {
698*c05d8e5dSAndroid Build Coastguard Worker                     results.ttypeIndex = 0;  // Redundant but clarifying
699*c05d8e5dSAndroid Build Coastguard Worker                     results.landingPad = landingPad;
700*c05d8e5dSAndroid Build Coastguard Worker                     results.reason = _URC_HANDLER_FOUND;
701*c05d8e5dSAndroid Build Coastguard Worker                     return;
702*c05d8e5dSAndroid Build Coastguard Worker                 }
703*c05d8e5dSAndroid Build Coastguard Worker                 // No handler here
704*c05d8e5dSAndroid Build Coastguard Worker                 results.reason = _URC_CONTINUE_UNWIND;
705*c05d8e5dSAndroid Build Coastguard Worker                 return;
706*c05d8e5dSAndroid Build Coastguard Worker             }
707*c05d8e5dSAndroid Build Coastguard Worker             // Convert 1-based byte offset into
708*c05d8e5dSAndroid Build Coastguard Worker             const uint8_t* action = actionTableStart + (actionEntry - 1);
709*c05d8e5dSAndroid Build Coastguard Worker             // Scan action entries until you find a matching handler, cleanup, or the end of action list
710*c05d8e5dSAndroid Build Coastguard Worker             while (true)
711*c05d8e5dSAndroid Build Coastguard Worker             {
712*c05d8e5dSAndroid Build Coastguard Worker                 const uint8_t* actionRecord = action;
713*c05d8e5dSAndroid Build Coastguard Worker                 int64_t ttypeIndex = readSLEB128(&action);
714*c05d8e5dSAndroid Build Coastguard Worker                 if (ttypeIndex > 0)
715*c05d8e5dSAndroid Build Coastguard Worker                 {
716*c05d8e5dSAndroid Build Coastguard Worker                     // Found a catch, does it actually catch?
717*c05d8e5dSAndroid Build Coastguard Worker                     // First check for catch (...)
718*c05d8e5dSAndroid Build Coastguard Worker                     const __shim_type_info* catchType =
719*c05d8e5dSAndroid Build Coastguard Worker                         get_shim_type_info(static_cast<uint64_t>(ttypeIndex),
720*c05d8e5dSAndroid Build Coastguard Worker                                            classInfo, ttypeEncoding,
721*c05d8e5dSAndroid Build Coastguard Worker                                            native_exception, unwind_exception);
722*c05d8e5dSAndroid Build Coastguard Worker                     if (catchType == 0)
723*c05d8e5dSAndroid Build Coastguard Worker                     {
724*c05d8e5dSAndroid Build Coastguard Worker                         // Found catch (...) catches everything, including foreign exceptions
725*c05d8e5dSAndroid Build Coastguard Worker                         // If this is a type 1 search save state and return _URC_HANDLER_FOUND
726*c05d8e5dSAndroid Build Coastguard Worker                         // If this is a type 2 search save state and return _URC_HANDLER_FOUND
727*c05d8e5dSAndroid Build Coastguard Worker                         // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
728*c05d8e5dSAndroid Build Coastguard Worker                         // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
729*c05d8e5dSAndroid Build Coastguard Worker                         if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
730*c05d8e5dSAndroid Build Coastguard Worker                         {
731*c05d8e5dSAndroid Build Coastguard Worker                             // Save state and return _URC_HANDLER_FOUND
732*c05d8e5dSAndroid Build Coastguard Worker                             results.ttypeIndex = ttypeIndex;
733*c05d8e5dSAndroid Build Coastguard Worker                             results.actionRecord = actionRecord;
734*c05d8e5dSAndroid Build Coastguard Worker                             results.landingPad = landingPad;
735*c05d8e5dSAndroid Build Coastguard Worker                             results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
736*c05d8e5dSAndroid Build Coastguard Worker                             results.reason = _URC_HANDLER_FOUND;
737*c05d8e5dSAndroid Build Coastguard Worker                             return;
738*c05d8e5dSAndroid Build Coastguard Worker                         }
739*c05d8e5dSAndroid Build Coastguard Worker                         else if (!(actions & _UA_FORCE_UNWIND))
740*c05d8e5dSAndroid Build Coastguard Worker                         {
741*c05d8e5dSAndroid Build Coastguard Worker                             // It looks like the exception table has changed
742*c05d8e5dSAndroid Build Coastguard Worker                             //    on us.  Likely stack corruption!
743*c05d8e5dSAndroid Build Coastguard Worker                             call_terminate(native_exception, unwind_exception);
744*c05d8e5dSAndroid Build Coastguard Worker                         }
745*c05d8e5dSAndroid Build Coastguard Worker                     }
746*c05d8e5dSAndroid Build Coastguard Worker                     // Else this is a catch (T) clause and will never
747*c05d8e5dSAndroid Build Coastguard Worker                     //    catch a foreign exception
748*c05d8e5dSAndroid Build Coastguard Worker                     else if (native_exception)
749*c05d8e5dSAndroid Build Coastguard Worker                     {
750*c05d8e5dSAndroid Build Coastguard Worker                         __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
751*c05d8e5dSAndroid Build Coastguard Worker                         void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
752*c05d8e5dSAndroid Build Coastguard Worker                         const __shim_type_info* excpType =
753*c05d8e5dSAndroid Build Coastguard Worker                             static_cast<const __shim_type_info*>(exception_header->exceptionType);
754*c05d8e5dSAndroid Build Coastguard Worker                         if (adjustedPtr == 0 || excpType == 0)
755*c05d8e5dSAndroid Build Coastguard Worker                         {
756*c05d8e5dSAndroid Build Coastguard Worker                             // Something very bad happened
757*c05d8e5dSAndroid Build Coastguard Worker                             call_terminate(native_exception, unwind_exception);
758*c05d8e5dSAndroid Build Coastguard Worker                         }
759*c05d8e5dSAndroid Build Coastguard Worker                         if (catchType->can_catch(excpType, adjustedPtr))
760*c05d8e5dSAndroid Build Coastguard Worker                         {
761*c05d8e5dSAndroid Build Coastguard Worker                             // Found a matching handler
762*c05d8e5dSAndroid Build Coastguard Worker                             // If this is a type 1 search save state and return _URC_HANDLER_FOUND
763*c05d8e5dSAndroid Build Coastguard Worker                             // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1!
764*c05d8e5dSAndroid Build Coastguard Worker                             // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan
765*c05d8e5dSAndroid Build Coastguard Worker                             if (actions & _UA_SEARCH_PHASE)
766*c05d8e5dSAndroid Build Coastguard Worker                             {
767*c05d8e5dSAndroid Build Coastguard Worker                                 // Save state and return _URC_HANDLER_FOUND
768*c05d8e5dSAndroid Build Coastguard Worker                                 results.ttypeIndex = ttypeIndex;
769*c05d8e5dSAndroid Build Coastguard Worker                                 results.actionRecord = actionRecord;
770*c05d8e5dSAndroid Build Coastguard Worker                                 results.landingPad = landingPad;
771*c05d8e5dSAndroid Build Coastguard Worker                                 results.adjustedPtr = adjustedPtr;
772*c05d8e5dSAndroid Build Coastguard Worker                                 results.reason = _URC_HANDLER_FOUND;
773*c05d8e5dSAndroid Build Coastguard Worker                                 return;
774*c05d8e5dSAndroid Build Coastguard Worker                             }
775*c05d8e5dSAndroid Build Coastguard Worker                             else if (!(actions & _UA_FORCE_UNWIND))
776*c05d8e5dSAndroid Build Coastguard Worker                             {
777*c05d8e5dSAndroid Build Coastguard Worker                                 // It looks like the exception table has changed
778*c05d8e5dSAndroid Build Coastguard Worker                                 //    on us.  Likely stack corruption!
779*c05d8e5dSAndroid Build Coastguard Worker                                 call_terminate(native_exception, unwind_exception);
780*c05d8e5dSAndroid Build Coastguard Worker                             }
781*c05d8e5dSAndroid Build Coastguard Worker                         }
782*c05d8e5dSAndroid Build Coastguard Worker                     }
783*c05d8e5dSAndroid Build Coastguard Worker                     // Scan next action ...
784*c05d8e5dSAndroid Build Coastguard Worker                 }
785*c05d8e5dSAndroid Build Coastguard Worker                 else if (ttypeIndex < 0)
786*c05d8e5dSAndroid Build Coastguard Worker                 {
787*c05d8e5dSAndroid Build Coastguard Worker                     // Found an exception spec.  If this is a foreign exception,
788*c05d8e5dSAndroid Build Coastguard Worker                     //   it is always caught.
789*c05d8e5dSAndroid Build Coastguard Worker                     if (native_exception)
790*c05d8e5dSAndroid Build Coastguard Worker                     {
791*c05d8e5dSAndroid Build Coastguard Worker                         // Does the exception spec catch this native exception?
792*c05d8e5dSAndroid Build Coastguard Worker                         __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
793*c05d8e5dSAndroid Build Coastguard Worker                         void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
794*c05d8e5dSAndroid Build Coastguard Worker                         const __shim_type_info* excpType =
795*c05d8e5dSAndroid Build Coastguard Worker                             static_cast<const __shim_type_info*>(exception_header->exceptionType);
796*c05d8e5dSAndroid Build Coastguard Worker                         if (adjustedPtr == 0 || excpType == 0)
797*c05d8e5dSAndroid Build Coastguard Worker                         {
798*c05d8e5dSAndroid Build Coastguard Worker                             // Something very bad happened
799*c05d8e5dSAndroid Build Coastguard Worker                             call_terminate(native_exception, unwind_exception);
800*c05d8e5dSAndroid Build Coastguard Worker                         }
801*c05d8e5dSAndroid Build Coastguard Worker                         if (exception_spec_can_catch(ttypeIndex, classInfo,
802*c05d8e5dSAndroid Build Coastguard Worker                                                      ttypeEncoding, excpType,
803*c05d8e5dSAndroid Build Coastguard Worker                                                      adjustedPtr, unwind_exception))
804*c05d8e5dSAndroid Build Coastguard Worker                         {
805*c05d8e5dSAndroid Build Coastguard Worker                             // native exception caught by exception spec
806*c05d8e5dSAndroid Build Coastguard Worker                             // If this is a type 1 search, save state and return _URC_HANDLER_FOUND
807*c05d8e5dSAndroid Build Coastguard Worker                             // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
808*c05d8e5dSAndroid Build Coastguard Worker                             // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
809*c05d8e5dSAndroid Build Coastguard Worker                             if (actions & _UA_SEARCH_PHASE)
810*c05d8e5dSAndroid Build Coastguard Worker                             {
811*c05d8e5dSAndroid Build Coastguard Worker                                 // Save state and return _URC_HANDLER_FOUND
812*c05d8e5dSAndroid Build Coastguard Worker                                 results.ttypeIndex = ttypeIndex;
813*c05d8e5dSAndroid Build Coastguard Worker                                 results.actionRecord = actionRecord;
814*c05d8e5dSAndroid Build Coastguard Worker                                 results.landingPad = landingPad;
815*c05d8e5dSAndroid Build Coastguard Worker                                 results.adjustedPtr = adjustedPtr;
816*c05d8e5dSAndroid Build Coastguard Worker                                 results.reason = _URC_HANDLER_FOUND;
817*c05d8e5dSAndroid Build Coastguard Worker                                 return;
818*c05d8e5dSAndroid Build Coastguard Worker                             }
819*c05d8e5dSAndroid Build Coastguard Worker                             else if (!(actions & _UA_FORCE_UNWIND))
820*c05d8e5dSAndroid Build Coastguard Worker                             {
821*c05d8e5dSAndroid Build Coastguard Worker                                 // It looks like the exception table has changed
822*c05d8e5dSAndroid Build Coastguard Worker                                 //    on us.  Likely stack corruption!
823*c05d8e5dSAndroid Build Coastguard Worker                                 call_terminate(native_exception, unwind_exception);
824*c05d8e5dSAndroid Build Coastguard Worker                             }
825*c05d8e5dSAndroid Build Coastguard Worker                         }
826*c05d8e5dSAndroid Build Coastguard Worker                     }
827*c05d8e5dSAndroid Build Coastguard Worker                     else
828*c05d8e5dSAndroid Build Coastguard Worker                     {
829*c05d8e5dSAndroid Build Coastguard Worker                         // foreign exception caught by exception spec
830*c05d8e5dSAndroid Build Coastguard Worker                         // If this is a type 1 search, save state and return _URC_HANDLER_FOUND
831*c05d8e5dSAndroid Build Coastguard Worker                         // If this is a type 2 search, save state and return _URC_HANDLER_FOUND
832*c05d8e5dSAndroid Build Coastguard Worker                         // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
833*c05d8e5dSAndroid Build Coastguard Worker                         // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
834*c05d8e5dSAndroid Build Coastguard Worker                         if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
835*c05d8e5dSAndroid Build Coastguard Worker                         {
836*c05d8e5dSAndroid Build Coastguard Worker                             // Save state and return _URC_HANDLER_FOUND
837*c05d8e5dSAndroid Build Coastguard Worker                             results.ttypeIndex = ttypeIndex;
838*c05d8e5dSAndroid Build Coastguard Worker                             results.actionRecord = actionRecord;
839*c05d8e5dSAndroid Build Coastguard Worker                             results.landingPad = landingPad;
840*c05d8e5dSAndroid Build Coastguard Worker                             results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
841*c05d8e5dSAndroid Build Coastguard Worker                             results.reason = _URC_HANDLER_FOUND;
842*c05d8e5dSAndroid Build Coastguard Worker                             return;
843*c05d8e5dSAndroid Build Coastguard Worker                         }
844*c05d8e5dSAndroid Build Coastguard Worker                         else if (!(actions & _UA_FORCE_UNWIND))
845*c05d8e5dSAndroid Build Coastguard Worker                         {
846*c05d8e5dSAndroid Build Coastguard Worker                             // It looks like the exception table has changed
847*c05d8e5dSAndroid Build Coastguard Worker                             //    on us.  Likely stack corruption!
848*c05d8e5dSAndroid Build Coastguard Worker                             call_terminate(native_exception, unwind_exception);
849*c05d8e5dSAndroid Build Coastguard Worker                         }
850*c05d8e5dSAndroid Build Coastguard Worker                     }
851*c05d8e5dSAndroid Build Coastguard Worker                     // Scan next action ...
852*c05d8e5dSAndroid Build Coastguard Worker                 }
853*c05d8e5dSAndroid Build Coastguard Worker                 else  // ttypeIndex == 0
854*c05d8e5dSAndroid Build Coastguard Worker                 {
855*c05d8e5dSAndroid Build Coastguard Worker                     // Found a cleanup
856*c05d8e5dSAndroid Build Coastguard Worker                     // If this is a type 1 search, ignore it and continue scan
857*c05d8e5dSAndroid Build Coastguard Worker                     // If this is a type 2 search, ignore it and continue scan
858*c05d8e5dSAndroid Build Coastguard Worker                     // If this is a type 3 search, save state and return _URC_HANDLER_FOUND
859*c05d8e5dSAndroid Build Coastguard Worker                     if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
860*c05d8e5dSAndroid Build Coastguard Worker                     {
861*c05d8e5dSAndroid Build Coastguard Worker                         // Save state and return _URC_HANDLER_FOUND
862*c05d8e5dSAndroid Build Coastguard Worker                         results.ttypeIndex = ttypeIndex;
863*c05d8e5dSAndroid Build Coastguard Worker                         results.actionRecord = actionRecord;
864*c05d8e5dSAndroid Build Coastguard Worker                         results.landingPad = landingPad;
865*c05d8e5dSAndroid Build Coastguard Worker                         results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
866*c05d8e5dSAndroid Build Coastguard Worker                         results.reason = _URC_HANDLER_FOUND;
867*c05d8e5dSAndroid Build Coastguard Worker                         return;
868*c05d8e5dSAndroid Build Coastguard Worker                     }
869*c05d8e5dSAndroid Build Coastguard Worker                 }
870*c05d8e5dSAndroid Build Coastguard Worker                 const uint8_t* temp = action;
871*c05d8e5dSAndroid Build Coastguard Worker                 int64_t actionOffset = readSLEB128(&temp);
872*c05d8e5dSAndroid Build Coastguard Worker                 if (actionOffset == 0)
873*c05d8e5dSAndroid Build Coastguard Worker                 {
874*c05d8e5dSAndroid Build Coastguard Worker                     // End of action list, no matching handler or cleanup found
875*c05d8e5dSAndroid Build Coastguard Worker                     results.reason = _URC_CONTINUE_UNWIND;
876*c05d8e5dSAndroid Build Coastguard Worker                     return;
877*c05d8e5dSAndroid Build Coastguard Worker                 }
878*c05d8e5dSAndroid Build Coastguard Worker                 // Go to next action
879*c05d8e5dSAndroid Build Coastguard Worker                 action += actionOffset;
880*c05d8e5dSAndroid Build Coastguard Worker             }  // there is no break out of this loop, only return
881*c05d8e5dSAndroid Build Coastguard Worker         }
882*c05d8e5dSAndroid Build Coastguard Worker #ifndef __USING_SJLJ_EXCEPTIONS__
883*c05d8e5dSAndroid Build Coastguard Worker         else if (ipOffset < start)
884*c05d8e5dSAndroid Build Coastguard Worker         {
885*c05d8e5dSAndroid Build Coastguard Worker             // There is no call site for this ip
886*c05d8e5dSAndroid Build Coastguard Worker             // Something bad has happened.  We should never get here.
887*c05d8e5dSAndroid Build Coastguard Worker             // Possible stack corruption.
888*c05d8e5dSAndroid Build Coastguard Worker             call_terminate(native_exception, unwind_exception);
889*c05d8e5dSAndroid Build Coastguard Worker         }
890*c05d8e5dSAndroid Build Coastguard Worker #endif  // !__USING_SJLJ_EXCEPTIONS__
891*c05d8e5dSAndroid Build Coastguard Worker     }  // there might be some tricky cases which break out of this loop
892*c05d8e5dSAndroid Build Coastguard Worker 
893*c05d8e5dSAndroid Build Coastguard Worker     // It is possible that no eh table entry specify how to handle
894*c05d8e5dSAndroid Build Coastguard Worker     // this exception. By spec, terminate it immediately.
895*c05d8e5dSAndroid Build Coastguard Worker     call_terminate(native_exception, unwind_exception);
896*c05d8e5dSAndroid Build Coastguard Worker }
897*c05d8e5dSAndroid Build Coastguard Worker 
898*c05d8e5dSAndroid Build Coastguard Worker // public API
899*c05d8e5dSAndroid Build Coastguard Worker 
900*c05d8e5dSAndroid Build Coastguard Worker /*
901*c05d8e5dSAndroid Build Coastguard Worker The personality function branches on actions like so:
902*c05d8e5dSAndroid Build Coastguard Worker 
903*c05d8e5dSAndroid Build Coastguard Worker _UA_SEARCH_PHASE
904*c05d8e5dSAndroid Build Coastguard Worker 
905*c05d8e5dSAndroid Build Coastguard Worker     If _UA_CLEANUP_PHASE or _UA_HANDLER_FRAME or _UA_FORCE_UNWIND there's
906*c05d8e5dSAndroid Build Coastguard Worker       an error from above, return _URC_FATAL_PHASE1_ERROR.
907*c05d8e5dSAndroid Build Coastguard Worker 
908*c05d8e5dSAndroid Build Coastguard Worker     Scan for anything that could stop unwinding:
909*c05d8e5dSAndroid Build Coastguard Worker 
910*c05d8e5dSAndroid Build Coastguard Worker        1.  A catch clause that will catch this exception
911*c05d8e5dSAndroid Build Coastguard Worker            (will never catch foreign).
912*c05d8e5dSAndroid Build Coastguard Worker        2.  A catch (...) (will always catch foreign).
913*c05d8e5dSAndroid Build Coastguard Worker        3.  An exception spec that will catch this exception
914*c05d8e5dSAndroid Build Coastguard Worker            (will always catch foreign).
915*c05d8e5dSAndroid Build Coastguard Worker     If a handler is found
916*c05d8e5dSAndroid Build Coastguard Worker         If not foreign
917*c05d8e5dSAndroid Build Coastguard Worker             Save state in header
918*c05d8e5dSAndroid Build Coastguard Worker         return _URC_HANDLER_FOUND
919*c05d8e5dSAndroid Build Coastguard Worker     Else a handler not found
920*c05d8e5dSAndroid Build Coastguard Worker         return _URC_CONTINUE_UNWIND
921*c05d8e5dSAndroid Build Coastguard Worker 
922*c05d8e5dSAndroid Build Coastguard Worker _UA_CLEANUP_PHASE
923*c05d8e5dSAndroid Build Coastguard Worker 
924*c05d8e5dSAndroid Build Coastguard Worker     If _UA_HANDLER_FRAME
925*c05d8e5dSAndroid Build Coastguard Worker         If _UA_FORCE_UNWIND
926*c05d8e5dSAndroid Build Coastguard Worker             How did this happen?  return _URC_FATAL_PHASE2_ERROR
927*c05d8e5dSAndroid Build Coastguard Worker         If foreign
928*c05d8e5dSAndroid Build Coastguard Worker             Do _UA_SEARCH_PHASE to recover state
929*c05d8e5dSAndroid Build Coastguard Worker         else
930*c05d8e5dSAndroid Build Coastguard Worker             Recover state from header
931*c05d8e5dSAndroid Build Coastguard Worker         Transfer control to landing pad.  return _URC_INSTALL_CONTEXT
932*c05d8e5dSAndroid Build Coastguard Worker 
933*c05d8e5dSAndroid Build Coastguard Worker     Else
934*c05d8e5dSAndroid Build Coastguard Worker 
935*c05d8e5dSAndroid Build Coastguard Worker         This branch handles both normal C++ non-catching handlers (cleanups)
936*c05d8e5dSAndroid Build Coastguard Worker           and forced unwinding.
937*c05d8e5dSAndroid Build Coastguard Worker         Scan for anything that can not stop unwinding:
938*c05d8e5dSAndroid Build Coastguard Worker 
939*c05d8e5dSAndroid Build Coastguard Worker             1.  A cleanup.
940*c05d8e5dSAndroid Build Coastguard Worker 
941*c05d8e5dSAndroid Build Coastguard Worker         If a cleanup is found
942*c05d8e5dSAndroid Build Coastguard Worker             transfer control to it. return _URC_INSTALL_CONTEXT
943*c05d8e5dSAndroid Build Coastguard Worker         Else a cleanup is not found: return _URC_CONTINUE_UNWIND
944*c05d8e5dSAndroid Build Coastguard Worker */
945*c05d8e5dSAndroid Build Coastguard Worker 
946*c05d8e5dSAndroid Build Coastguard Worker #if !defined(_LIBCXXABI_ARM_EHABI)
947*c05d8e5dSAndroid Build Coastguard Worker #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
__gxx_personality_imp(int version,_Unwind_Action actions,uint64_t exceptionClass,_Unwind_Exception * unwind_exception,_Unwind_Context * context)948*c05d8e5dSAndroid Build Coastguard Worker static _Unwind_Reason_Code __gxx_personality_imp
949*c05d8e5dSAndroid Build Coastguard Worker #else
950*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
951*c05d8e5dSAndroid Build Coastguard Worker #ifdef __USING_SJLJ_EXCEPTIONS__
952*c05d8e5dSAndroid Build Coastguard Worker __gxx_personality_sj0
953*c05d8e5dSAndroid Build Coastguard Worker #else
954*c05d8e5dSAndroid Build Coastguard Worker __gxx_personality_v0
955*c05d8e5dSAndroid Build Coastguard Worker #endif
956*c05d8e5dSAndroid Build Coastguard Worker #endif
957*c05d8e5dSAndroid Build Coastguard Worker                     (int version, _Unwind_Action actions, uint64_t exceptionClass,
958*c05d8e5dSAndroid Build Coastguard Worker                      _Unwind_Exception* unwind_exception, _Unwind_Context* context)
959*c05d8e5dSAndroid Build Coastguard Worker {
960*c05d8e5dSAndroid Build Coastguard Worker     if (version != 1 || unwind_exception == 0 || context == 0)
961*c05d8e5dSAndroid Build Coastguard Worker         return _URC_FATAL_PHASE1_ERROR;
962*c05d8e5dSAndroid Build Coastguard Worker 
963*c05d8e5dSAndroid Build Coastguard Worker     bool native_exception = (exceptionClass     & get_vendor_and_language) ==
964*c05d8e5dSAndroid Build Coastguard Worker                             (kOurExceptionClass & get_vendor_and_language);
965*c05d8e5dSAndroid Build Coastguard Worker     scan_results results;
966*c05d8e5dSAndroid Build Coastguard Worker     if (actions & _UA_SEARCH_PHASE)
967*c05d8e5dSAndroid Build Coastguard Worker     {
968*c05d8e5dSAndroid Build Coastguard Worker         // Phase 1 search:  All we're looking for in phase 1 is a handler that
969*c05d8e5dSAndroid Build Coastguard Worker         //   halts unwinding
970*c05d8e5dSAndroid Build Coastguard Worker         scan_eh_tab(results, actions, native_exception, unwind_exception, context);
971*c05d8e5dSAndroid Build Coastguard Worker         if (results.reason == _URC_HANDLER_FOUND)
972*c05d8e5dSAndroid Build Coastguard Worker         {
973*c05d8e5dSAndroid Build Coastguard Worker             // Found one.  Can we cache the results somewhere to optimize phase 2?
974*c05d8e5dSAndroid Build Coastguard Worker             if (native_exception)
975*c05d8e5dSAndroid Build Coastguard Worker             {
976*c05d8e5dSAndroid Build Coastguard Worker                 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
977*c05d8e5dSAndroid Build Coastguard Worker                 exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
978*c05d8e5dSAndroid Build Coastguard Worker                 exception_header->actionRecord = results.actionRecord;
979*c05d8e5dSAndroid Build Coastguard Worker                 exception_header->languageSpecificData = results.languageSpecificData;
980*c05d8e5dSAndroid Build Coastguard Worker                 exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad);
981*c05d8e5dSAndroid Build Coastguard Worker                 exception_header->adjustedPtr = results.adjustedPtr;
982*c05d8e5dSAndroid Build Coastguard Worker             }
983*c05d8e5dSAndroid Build Coastguard Worker             return _URC_HANDLER_FOUND;
984*c05d8e5dSAndroid Build Coastguard Worker         }
985*c05d8e5dSAndroid Build Coastguard Worker         // Did not find a catching-handler.  Return the results of the scan
986*c05d8e5dSAndroid Build Coastguard Worker         //    (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR
987*c05d8e5dSAndroid Build Coastguard Worker         //     if we were called improperly).
988*c05d8e5dSAndroid Build Coastguard Worker         return results.reason;
989*c05d8e5dSAndroid Build Coastguard Worker     }
990*c05d8e5dSAndroid Build Coastguard Worker     if (actions & _UA_CLEANUP_PHASE)
991*c05d8e5dSAndroid Build Coastguard Worker     {
992*c05d8e5dSAndroid Build Coastguard Worker         // Phase 2 search:
993*c05d8e5dSAndroid Build Coastguard Worker         //  Did we find a catching handler in phase 1?
994*c05d8e5dSAndroid Build Coastguard Worker         if (actions & _UA_HANDLER_FRAME)
995*c05d8e5dSAndroid Build Coastguard Worker         {
996*c05d8e5dSAndroid Build Coastguard Worker             // Yes, phase 1 said we have a catching handler here.
997*c05d8e5dSAndroid Build Coastguard Worker             // Did we cache the results of the scan?
998*c05d8e5dSAndroid Build Coastguard Worker             if (native_exception)
999*c05d8e5dSAndroid Build Coastguard Worker             {
1000*c05d8e5dSAndroid Build Coastguard Worker                 // Yes, reload the results from the cache.
1001*c05d8e5dSAndroid Build Coastguard Worker                 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
1002*c05d8e5dSAndroid Build Coastguard Worker                 results.ttypeIndex = exception_header->handlerSwitchValue;
1003*c05d8e5dSAndroid Build Coastguard Worker                 results.actionRecord = exception_header->actionRecord;
1004*c05d8e5dSAndroid Build Coastguard Worker                 results.languageSpecificData = exception_header->languageSpecificData;
1005*c05d8e5dSAndroid Build Coastguard Worker                 results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp);
1006*c05d8e5dSAndroid Build Coastguard Worker                 results.adjustedPtr = exception_header->adjustedPtr;
1007*c05d8e5dSAndroid Build Coastguard Worker             }
1008*c05d8e5dSAndroid Build Coastguard Worker             else
1009*c05d8e5dSAndroid Build Coastguard Worker             {
1010*c05d8e5dSAndroid Build Coastguard Worker                 // No, do the scan again to reload the results.
1011*c05d8e5dSAndroid Build Coastguard Worker                 scan_eh_tab(results, actions, native_exception, unwind_exception, context);
1012*c05d8e5dSAndroid Build Coastguard Worker                 // Phase 1 told us we would find a handler.  Now in Phase 2 we
1013*c05d8e5dSAndroid Build Coastguard Worker                 //   didn't find a handler.  The eh table should not be changing!
1014*c05d8e5dSAndroid Build Coastguard Worker                 if (results.reason != _URC_HANDLER_FOUND)
1015*c05d8e5dSAndroid Build Coastguard Worker                     call_terminate(native_exception, unwind_exception);
1016*c05d8e5dSAndroid Build Coastguard Worker             }
1017*c05d8e5dSAndroid Build Coastguard Worker             // Jump to the handler
1018*c05d8e5dSAndroid Build Coastguard Worker             set_registers(unwind_exception, context, results);
1019*c05d8e5dSAndroid Build Coastguard Worker             return _URC_INSTALL_CONTEXT;
1020*c05d8e5dSAndroid Build Coastguard Worker         }
1021*c05d8e5dSAndroid Build Coastguard Worker         // Either we didn't do a phase 1 search (due to forced unwinding), or
1022*c05d8e5dSAndroid Build Coastguard Worker         //   phase 1 reported no catching-handlers.
1023*c05d8e5dSAndroid Build Coastguard Worker         // Search for a (non-catching) cleanup
1024*c05d8e5dSAndroid Build Coastguard Worker         scan_eh_tab(results, actions, native_exception, unwind_exception, context);
1025*c05d8e5dSAndroid Build Coastguard Worker         if (results.reason == _URC_HANDLER_FOUND)
1026*c05d8e5dSAndroid Build Coastguard Worker         {
1027*c05d8e5dSAndroid Build Coastguard Worker             // Found a non-catching handler.  Jump to it:
1028*c05d8e5dSAndroid Build Coastguard Worker             set_registers(unwind_exception, context, results);
1029*c05d8e5dSAndroid Build Coastguard Worker             return _URC_INSTALL_CONTEXT;
1030*c05d8e5dSAndroid Build Coastguard Worker         }
1031*c05d8e5dSAndroid Build Coastguard Worker         // Did not find a cleanup.  Return the results of the scan
1032*c05d8e5dSAndroid Build Coastguard Worker         //    (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR
1033*c05d8e5dSAndroid Build Coastguard Worker         //     if we were called improperly).
1034*c05d8e5dSAndroid Build Coastguard Worker         return results.reason;
1035*c05d8e5dSAndroid Build Coastguard Worker     }
1036*c05d8e5dSAndroid Build Coastguard Worker     // We were called improperly: neither a phase 1 or phase 2 search
1037*c05d8e5dSAndroid Build Coastguard Worker     return _URC_FATAL_PHASE1_ERROR;
1038*c05d8e5dSAndroid Build Coastguard Worker }
1039*c05d8e5dSAndroid Build Coastguard Worker 
1040*c05d8e5dSAndroid Build Coastguard Worker #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
1041*c05d8e5dSAndroid Build Coastguard Worker extern "C" _LIBCXXABI_FUNC_VIS EXCEPTION_DISPOSITION
__gxx_personality_seh0(PEXCEPTION_RECORD ms_exc,void * this_frame,PCONTEXT ms_orig_context,PDISPATCHER_CONTEXT ms_disp)1042*c05d8e5dSAndroid Build Coastguard Worker __gxx_personality_seh0(PEXCEPTION_RECORD ms_exc, void *this_frame,
1043*c05d8e5dSAndroid Build Coastguard Worker                        PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp)
1044*c05d8e5dSAndroid Build Coastguard Worker {
1045*c05d8e5dSAndroid Build Coastguard Worker   return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context, ms_disp,
1046*c05d8e5dSAndroid Build Coastguard Worker                                __gxx_personality_imp);
1047*c05d8e5dSAndroid Build Coastguard Worker }
1048*c05d8e5dSAndroid Build Coastguard Worker #endif
1049*c05d8e5dSAndroid Build Coastguard Worker 
1050*c05d8e5dSAndroid Build Coastguard Worker #else
1051*c05d8e5dSAndroid Build Coastguard Worker 
1052*c05d8e5dSAndroid Build Coastguard Worker extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*,
1053*c05d8e5dSAndroid Build Coastguard Worker                                                   _Unwind_Context*);
1054*c05d8e5dSAndroid Build Coastguard Worker 
1055*c05d8e5dSAndroid Build Coastguard Worker // Helper function to unwind one frame.
1056*c05d8e5dSAndroid Build Coastguard Worker // ARM EHABI 7.3 and 7.4: If the personality function returns _URC_CONTINUE_UNWIND, the
1057*c05d8e5dSAndroid Build Coastguard Worker // personality routine should update the virtual register set (VRS) according to the
1058*c05d8e5dSAndroid Build Coastguard Worker // corresponding frame unwinding instructions (ARM EHABI 9.3.)
continue_unwind(_Unwind_Exception * unwind_exception,_Unwind_Context * context)1059*c05d8e5dSAndroid Build Coastguard Worker static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception,
1060*c05d8e5dSAndroid Build Coastguard Worker                                            _Unwind_Context* context)
1061*c05d8e5dSAndroid Build Coastguard Worker {
1062*c05d8e5dSAndroid Build Coastguard Worker     if (__gnu_unwind_frame(unwind_exception, context) != _URC_OK)
1063*c05d8e5dSAndroid Build Coastguard Worker         return _URC_FAILURE;
1064*c05d8e5dSAndroid Build Coastguard Worker     return _URC_CONTINUE_UNWIND;
1065*c05d8e5dSAndroid Build Coastguard Worker }
1066*c05d8e5dSAndroid Build Coastguard Worker 
1067*c05d8e5dSAndroid Build Coastguard Worker // ARM register names
1068*c05d8e5dSAndroid Build Coastguard Worker #if !defined(LIBCXXABI_USE_LLVM_UNWINDER)
1069*c05d8e5dSAndroid Build Coastguard Worker static const uint32_t REG_UCB = 12;  // Register to save _Unwind_Control_Block
1070*c05d8e5dSAndroid Build Coastguard Worker #endif
1071*c05d8e5dSAndroid Build Coastguard Worker static const uint32_t REG_SP = 13;
1072*c05d8e5dSAndroid Build Coastguard Worker 
save_results_to_barrier_cache(_Unwind_Exception * unwind_exception,const scan_results & results)1073*c05d8e5dSAndroid Build Coastguard Worker static void save_results_to_barrier_cache(_Unwind_Exception* unwind_exception,
1074*c05d8e5dSAndroid Build Coastguard Worker                                           const scan_results& results)
1075*c05d8e5dSAndroid Build Coastguard Worker {
1076*c05d8e5dSAndroid Build Coastguard Worker     unwind_exception->barrier_cache.bitpattern[0] = (uint32_t)results.adjustedPtr;
1077*c05d8e5dSAndroid Build Coastguard Worker     unwind_exception->barrier_cache.bitpattern[1] = (uint32_t)results.actionRecord;
1078*c05d8e5dSAndroid Build Coastguard Worker     unwind_exception->barrier_cache.bitpattern[2] = (uint32_t)results.languageSpecificData;
1079*c05d8e5dSAndroid Build Coastguard Worker     unwind_exception->barrier_cache.bitpattern[3] = (uint32_t)results.landingPad;
1080*c05d8e5dSAndroid Build Coastguard Worker     unwind_exception->barrier_cache.bitpattern[4] = (uint32_t)results.ttypeIndex;
1081*c05d8e5dSAndroid Build Coastguard Worker }
1082*c05d8e5dSAndroid Build Coastguard Worker 
load_results_from_barrier_cache(scan_results & results,const _Unwind_Exception * unwind_exception)1083*c05d8e5dSAndroid Build Coastguard Worker static void load_results_from_barrier_cache(scan_results& results,
1084*c05d8e5dSAndroid Build Coastguard Worker                                             const _Unwind_Exception* unwind_exception)
1085*c05d8e5dSAndroid Build Coastguard Worker {
1086*c05d8e5dSAndroid Build Coastguard Worker     results.adjustedPtr = (void*)unwind_exception->barrier_cache.bitpattern[0];
1087*c05d8e5dSAndroid Build Coastguard Worker     results.actionRecord = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[1];
1088*c05d8e5dSAndroid Build Coastguard Worker     results.languageSpecificData = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[2];
1089*c05d8e5dSAndroid Build Coastguard Worker     results.landingPad = (uintptr_t)unwind_exception->barrier_cache.bitpattern[3];
1090*c05d8e5dSAndroid Build Coastguard Worker     results.ttypeIndex = (int64_t)(int32_t)unwind_exception->barrier_cache.bitpattern[4];
1091*c05d8e5dSAndroid Build Coastguard Worker }
1092*c05d8e5dSAndroid Build Coastguard Worker 
1093*c05d8e5dSAndroid Build Coastguard Worker extern "C" _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
__gxx_personality_v0(_Unwind_State state,_Unwind_Exception * unwind_exception,_Unwind_Context * context)1094*c05d8e5dSAndroid Build Coastguard Worker __gxx_personality_v0(_Unwind_State state,
1095*c05d8e5dSAndroid Build Coastguard Worker                      _Unwind_Exception* unwind_exception,
1096*c05d8e5dSAndroid Build Coastguard Worker                      _Unwind_Context* context)
1097*c05d8e5dSAndroid Build Coastguard Worker {
1098*c05d8e5dSAndroid Build Coastguard Worker     if (unwind_exception == 0 || context == 0)
1099*c05d8e5dSAndroid Build Coastguard Worker         return _URC_FATAL_PHASE1_ERROR;
1100*c05d8e5dSAndroid Build Coastguard Worker 
1101*c05d8e5dSAndroid Build Coastguard Worker     bool native_exception = __isOurExceptionClass(unwind_exception);
1102*c05d8e5dSAndroid Build Coastguard Worker 
1103*c05d8e5dSAndroid Build Coastguard Worker #if !defined(LIBCXXABI_USE_LLVM_UNWINDER)
1104*c05d8e5dSAndroid Build Coastguard Worker     // Copy the address of _Unwind_Control_Block to r12 so that
1105*c05d8e5dSAndroid Build Coastguard Worker     // _Unwind_GetLanguageSpecificData() and _Unwind_GetRegionStart() can
1106*c05d8e5dSAndroid Build Coastguard Worker     // return correct address.
1107*c05d8e5dSAndroid Build Coastguard Worker     _Unwind_SetGR(context, REG_UCB, reinterpret_cast<uint32_t>(unwind_exception));
1108*c05d8e5dSAndroid Build Coastguard Worker #endif
1109*c05d8e5dSAndroid Build Coastguard Worker 
1110*c05d8e5dSAndroid Build Coastguard Worker     // Check the undocumented force unwinding behavior
1111*c05d8e5dSAndroid Build Coastguard Worker     bool is_force_unwinding = state & _US_FORCE_UNWIND;
1112*c05d8e5dSAndroid Build Coastguard Worker     state &= ~_US_FORCE_UNWIND;
1113*c05d8e5dSAndroid Build Coastguard Worker 
1114*c05d8e5dSAndroid Build Coastguard Worker     scan_results results;
1115*c05d8e5dSAndroid Build Coastguard Worker     switch (state) {
1116*c05d8e5dSAndroid Build Coastguard Worker     case _US_VIRTUAL_UNWIND_FRAME:
1117*c05d8e5dSAndroid Build Coastguard Worker         if (is_force_unwinding)
1118*c05d8e5dSAndroid Build Coastguard Worker             return continue_unwind(unwind_exception, context);
1119*c05d8e5dSAndroid Build Coastguard Worker 
1120*c05d8e5dSAndroid Build Coastguard Worker         // Phase 1 search:  All we're looking for in phase 1 is a handler that halts unwinding
1121*c05d8e5dSAndroid Build Coastguard Worker         scan_eh_tab(results, _UA_SEARCH_PHASE, native_exception, unwind_exception, context);
1122*c05d8e5dSAndroid Build Coastguard Worker         if (results.reason == _URC_HANDLER_FOUND)
1123*c05d8e5dSAndroid Build Coastguard Worker         {
1124*c05d8e5dSAndroid Build Coastguard Worker             unwind_exception->barrier_cache.sp = _Unwind_GetGR(context, REG_SP);
1125*c05d8e5dSAndroid Build Coastguard Worker             if (native_exception)
1126*c05d8e5dSAndroid Build Coastguard Worker                 save_results_to_barrier_cache(unwind_exception, results);
1127*c05d8e5dSAndroid Build Coastguard Worker             return _URC_HANDLER_FOUND;
1128*c05d8e5dSAndroid Build Coastguard Worker         }
1129*c05d8e5dSAndroid Build Coastguard Worker         // Did not find the catch handler
1130*c05d8e5dSAndroid Build Coastguard Worker         if (results.reason == _URC_CONTINUE_UNWIND)
1131*c05d8e5dSAndroid Build Coastguard Worker             return continue_unwind(unwind_exception, context);
1132*c05d8e5dSAndroid Build Coastguard Worker         return results.reason;
1133*c05d8e5dSAndroid Build Coastguard Worker 
1134*c05d8e5dSAndroid Build Coastguard Worker     case _US_UNWIND_FRAME_STARTING:
1135*c05d8e5dSAndroid Build Coastguard Worker         // TODO: Support force unwinding in the phase 2 search.
1136*c05d8e5dSAndroid Build Coastguard Worker         // NOTE: In order to call the cleanup functions, _Unwind_ForcedUnwind()
1137*c05d8e5dSAndroid Build Coastguard Worker         // will call this personality function with (_US_FORCE_UNWIND |
1138*c05d8e5dSAndroid Build Coastguard Worker         // _US_UNWIND_FRAME_STARTING).
1139*c05d8e5dSAndroid Build Coastguard Worker 
1140*c05d8e5dSAndroid Build Coastguard Worker         // Phase 2 search
1141*c05d8e5dSAndroid Build Coastguard Worker         if (unwind_exception->barrier_cache.sp == _Unwind_GetGR(context, REG_SP))
1142*c05d8e5dSAndroid Build Coastguard Worker         {
1143*c05d8e5dSAndroid Build Coastguard Worker             // Found a catching handler in phase 1
1144*c05d8e5dSAndroid Build Coastguard Worker             if (native_exception)
1145*c05d8e5dSAndroid Build Coastguard Worker             {
1146*c05d8e5dSAndroid Build Coastguard Worker                 // Load the result from the native exception barrier cache.
1147*c05d8e5dSAndroid Build Coastguard Worker                 load_results_from_barrier_cache(results, unwind_exception);
1148*c05d8e5dSAndroid Build Coastguard Worker                 results.reason = _URC_HANDLER_FOUND;
1149*c05d8e5dSAndroid Build Coastguard Worker             }
1150*c05d8e5dSAndroid Build Coastguard Worker             else
1151*c05d8e5dSAndroid Build Coastguard Worker             {
1152*c05d8e5dSAndroid Build Coastguard Worker                 // Search for the catching handler again for the foreign exception.
1153*c05d8e5dSAndroid Build Coastguard Worker                 scan_eh_tab(results, static_cast<_Unwind_Action>(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME),
1154*c05d8e5dSAndroid Build Coastguard Worker                             native_exception, unwind_exception, context);
1155*c05d8e5dSAndroid Build Coastguard Worker                 if (results.reason != _URC_HANDLER_FOUND)  // phase1 search should guarantee to find one
1156*c05d8e5dSAndroid Build Coastguard Worker                     call_terminate(native_exception, unwind_exception);
1157*c05d8e5dSAndroid Build Coastguard Worker             }
1158*c05d8e5dSAndroid Build Coastguard Worker 
1159*c05d8e5dSAndroid Build Coastguard Worker             // Install the context for the catching handler
1160*c05d8e5dSAndroid Build Coastguard Worker             set_registers(unwind_exception, context, results);
1161*c05d8e5dSAndroid Build Coastguard Worker             return _URC_INSTALL_CONTEXT;
1162*c05d8e5dSAndroid Build Coastguard Worker         }
1163*c05d8e5dSAndroid Build Coastguard Worker 
1164*c05d8e5dSAndroid Build Coastguard Worker         // Either we didn't do a phase 1 search (due to forced unwinding), or
1165*c05d8e5dSAndroid Build Coastguard Worker         //  phase 1 reported no catching-handlers.
1166*c05d8e5dSAndroid Build Coastguard Worker         // Search for a (non-catching) cleanup
1167*c05d8e5dSAndroid Build Coastguard Worker         scan_eh_tab(results, _UA_CLEANUP_PHASE, native_exception, unwind_exception, context);
1168*c05d8e5dSAndroid Build Coastguard Worker         if (results.reason == _URC_HANDLER_FOUND)
1169*c05d8e5dSAndroid Build Coastguard Worker         {
1170*c05d8e5dSAndroid Build Coastguard Worker             // Found a non-catching handler
1171*c05d8e5dSAndroid Build Coastguard Worker 
1172*c05d8e5dSAndroid Build Coastguard Worker             // ARM EHABI 8.4.2: Before we can jump to the cleanup handler, we have to setup some
1173*c05d8e5dSAndroid Build Coastguard Worker             // internal data structures, so that __cxa_end_cleanup() can get unwind_exception from
1174*c05d8e5dSAndroid Build Coastguard Worker             // __cxa_get_globals().
1175*c05d8e5dSAndroid Build Coastguard Worker             __cxa_begin_cleanup(unwind_exception);
1176*c05d8e5dSAndroid Build Coastguard Worker 
1177*c05d8e5dSAndroid Build Coastguard Worker             // Install the context for the cleanup handler
1178*c05d8e5dSAndroid Build Coastguard Worker             set_registers(unwind_exception, context, results);
1179*c05d8e5dSAndroid Build Coastguard Worker             return _URC_INSTALL_CONTEXT;
1180*c05d8e5dSAndroid Build Coastguard Worker         }
1181*c05d8e5dSAndroid Build Coastguard Worker 
1182*c05d8e5dSAndroid Build Coastguard Worker         // Did not find any handler
1183*c05d8e5dSAndroid Build Coastguard Worker         if (results.reason == _URC_CONTINUE_UNWIND)
1184*c05d8e5dSAndroid Build Coastguard Worker             return continue_unwind(unwind_exception, context);
1185*c05d8e5dSAndroid Build Coastguard Worker         return results.reason;
1186*c05d8e5dSAndroid Build Coastguard Worker 
1187*c05d8e5dSAndroid Build Coastguard Worker     case _US_UNWIND_FRAME_RESUME:
1188*c05d8e5dSAndroid Build Coastguard Worker         return continue_unwind(unwind_exception, context);
1189*c05d8e5dSAndroid Build Coastguard Worker     }
1190*c05d8e5dSAndroid Build Coastguard Worker 
1191*c05d8e5dSAndroid Build Coastguard Worker     // We were called improperly: neither a phase 1 or phase 2 search
1192*c05d8e5dSAndroid Build Coastguard Worker     return _URC_FATAL_PHASE1_ERROR;
1193*c05d8e5dSAndroid Build Coastguard Worker }
1194*c05d8e5dSAndroid Build Coastguard Worker #endif
1195*c05d8e5dSAndroid Build Coastguard Worker 
1196*c05d8e5dSAndroid Build Coastguard Worker 
1197*c05d8e5dSAndroid Build Coastguard Worker __attribute__((noreturn))
1198*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void
__cxa_call_unexpected(void * arg)1199*c05d8e5dSAndroid Build Coastguard Worker __cxa_call_unexpected(void* arg)
1200*c05d8e5dSAndroid Build Coastguard Worker {
1201*c05d8e5dSAndroid Build Coastguard Worker     _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg);
1202*c05d8e5dSAndroid Build Coastguard Worker     if (unwind_exception == 0)
1203*c05d8e5dSAndroid Build Coastguard Worker         call_terminate(false, unwind_exception);
1204*c05d8e5dSAndroid Build Coastguard Worker     __cxa_begin_catch(unwind_exception);
1205*c05d8e5dSAndroid Build Coastguard Worker     bool native_old_exception = __isOurExceptionClass(unwind_exception);
1206*c05d8e5dSAndroid Build Coastguard Worker     std::unexpected_handler u_handler;
1207*c05d8e5dSAndroid Build Coastguard Worker     std::terminate_handler t_handler;
1208*c05d8e5dSAndroid Build Coastguard Worker     __cxa_exception* old_exception_header = 0;
1209*c05d8e5dSAndroid Build Coastguard Worker     int64_t ttypeIndex;
1210*c05d8e5dSAndroid Build Coastguard Worker     const uint8_t* lsda;
1211*c05d8e5dSAndroid Build Coastguard Worker     if (native_old_exception)
1212*c05d8e5dSAndroid Build Coastguard Worker     {
1213*c05d8e5dSAndroid Build Coastguard Worker         old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
1214*c05d8e5dSAndroid Build Coastguard Worker         t_handler = old_exception_header->terminateHandler;
1215*c05d8e5dSAndroid Build Coastguard Worker         u_handler = old_exception_header->unexpectedHandler;
1216*c05d8e5dSAndroid Build Coastguard Worker         // If std::__unexpected(u_handler) rethrows the same exception,
1217*c05d8e5dSAndroid Build Coastguard Worker         //   these values get overwritten by the rethrow.  So save them now:
1218*c05d8e5dSAndroid Build Coastguard Worker #if defined(_LIBCXXABI_ARM_EHABI)
1219*c05d8e5dSAndroid Build Coastguard Worker         ttypeIndex = (int64_t)(int32_t)unwind_exception->barrier_cache.bitpattern[4];
1220*c05d8e5dSAndroid Build Coastguard Worker         lsda = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[2];
1221*c05d8e5dSAndroid Build Coastguard Worker #else
1222*c05d8e5dSAndroid Build Coastguard Worker         ttypeIndex = old_exception_header->handlerSwitchValue;
1223*c05d8e5dSAndroid Build Coastguard Worker         lsda = old_exception_header->languageSpecificData;
1224*c05d8e5dSAndroid Build Coastguard Worker #endif
1225*c05d8e5dSAndroid Build Coastguard Worker     }
1226*c05d8e5dSAndroid Build Coastguard Worker     else
1227*c05d8e5dSAndroid Build Coastguard Worker     {
1228*c05d8e5dSAndroid Build Coastguard Worker         t_handler = std::get_terminate();
1229*c05d8e5dSAndroid Build Coastguard Worker         u_handler = std::get_unexpected();
1230*c05d8e5dSAndroid Build Coastguard Worker     }
1231*c05d8e5dSAndroid Build Coastguard Worker     try
1232*c05d8e5dSAndroid Build Coastguard Worker     {
1233*c05d8e5dSAndroid Build Coastguard Worker         std::__unexpected(u_handler);
1234*c05d8e5dSAndroid Build Coastguard Worker     }
1235*c05d8e5dSAndroid Build Coastguard Worker     catch (...)
1236*c05d8e5dSAndroid Build Coastguard Worker     {
1237*c05d8e5dSAndroid Build Coastguard Worker         // If the old exception is foreign, then all we can do is terminate.
1238*c05d8e5dSAndroid Build Coastguard Worker         //   We have no way to recover the needed old exception spec.  There's
1239*c05d8e5dSAndroid Build Coastguard Worker         //   no way to pass that information here.  And the personality routine
1240*c05d8e5dSAndroid Build Coastguard Worker         //   can't call us directly and do anything but terminate() if we throw
1241*c05d8e5dSAndroid Build Coastguard Worker         //   from here.
1242*c05d8e5dSAndroid Build Coastguard Worker         if (native_old_exception)
1243*c05d8e5dSAndroid Build Coastguard Worker         {
1244*c05d8e5dSAndroid Build Coastguard Worker             // Have:
1245*c05d8e5dSAndroid Build Coastguard Worker             //   old_exception_header->languageSpecificData
1246*c05d8e5dSAndroid Build Coastguard Worker             //   old_exception_header->actionRecord
1247*c05d8e5dSAndroid Build Coastguard Worker             // Need
1248*c05d8e5dSAndroid Build Coastguard Worker             //   const uint8_t* classInfo
1249*c05d8e5dSAndroid Build Coastguard Worker             //   uint8_t ttypeEncoding
1250*c05d8e5dSAndroid Build Coastguard Worker             uint8_t lpStartEncoding = *lsda++;
1251*c05d8e5dSAndroid Build Coastguard Worker             const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
1252*c05d8e5dSAndroid Build Coastguard Worker             (void)lpStart;  // purposefully unused.  Just needed to increment lsda.
1253*c05d8e5dSAndroid Build Coastguard Worker             uint8_t ttypeEncoding = *lsda++;
1254*c05d8e5dSAndroid Build Coastguard Worker             if (ttypeEncoding == DW_EH_PE_omit)
1255*c05d8e5dSAndroid Build Coastguard Worker                 std::__terminate(t_handler);
1256*c05d8e5dSAndroid Build Coastguard Worker             uintptr_t classInfoOffset = readULEB128(&lsda);
1257*c05d8e5dSAndroid Build Coastguard Worker             const uint8_t* classInfo = lsda + classInfoOffset;
1258*c05d8e5dSAndroid Build Coastguard Worker             // Is this new exception catchable by the exception spec at ttypeIndex?
1259*c05d8e5dSAndroid Build Coastguard Worker             // The answer is obviously yes if the new and old exceptions are the same exception
1260*c05d8e5dSAndroid Build Coastguard Worker             // If no
1261*c05d8e5dSAndroid Build Coastguard Worker             //    throw;
1262*c05d8e5dSAndroid Build Coastguard Worker             __cxa_eh_globals* globals = __cxa_get_globals_fast();
1263*c05d8e5dSAndroid Build Coastguard Worker             __cxa_exception* new_exception_header = globals->caughtExceptions;
1264*c05d8e5dSAndroid Build Coastguard Worker             if (new_exception_header == 0)
1265*c05d8e5dSAndroid Build Coastguard Worker                 // This shouldn't be able to happen!
1266*c05d8e5dSAndroid Build Coastguard Worker                 std::__terminate(t_handler);
1267*c05d8e5dSAndroid Build Coastguard Worker             bool native_new_exception = __isOurExceptionClass(&new_exception_header->unwindHeader);
1268*c05d8e5dSAndroid Build Coastguard Worker             void* adjustedPtr;
1269*c05d8e5dSAndroid Build Coastguard Worker             if (native_new_exception && (new_exception_header != old_exception_header))
1270*c05d8e5dSAndroid Build Coastguard Worker             {
1271*c05d8e5dSAndroid Build Coastguard Worker                 const __shim_type_info* excpType =
1272*c05d8e5dSAndroid Build Coastguard Worker                     static_cast<const __shim_type_info*>(new_exception_header->exceptionType);
1273*c05d8e5dSAndroid Build Coastguard Worker                 adjustedPtr =
1274*c05d8e5dSAndroid Build Coastguard Worker                     __getExceptionClass(&new_exception_header->unwindHeader) == kOurDependentExceptionClass ?
1275*c05d8e5dSAndroid Build Coastguard Worker                         ((__cxa_dependent_exception*)new_exception_header)->primaryException :
1276*c05d8e5dSAndroid Build Coastguard Worker                         new_exception_header + 1;
1277*c05d8e5dSAndroid Build Coastguard Worker                 if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
1278*c05d8e5dSAndroid Build Coastguard Worker                                               excpType, adjustedPtr, unwind_exception))
1279*c05d8e5dSAndroid Build Coastguard Worker                 {
1280*c05d8e5dSAndroid Build Coastguard Worker                     // We need to __cxa_end_catch, but for the old exception,
1281*c05d8e5dSAndroid Build Coastguard Worker                     //   not the new one.  This is a little tricky ...
1282*c05d8e5dSAndroid Build Coastguard Worker                     // Disguise new_exception_header as a rethrown exception, but
1283*c05d8e5dSAndroid Build Coastguard Worker                     //   don't actually rethrow it.  This means you can temporarily
1284*c05d8e5dSAndroid Build Coastguard Worker                     //   end the catch clause enclosing new_exception_header without
1285*c05d8e5dSAndroid Build Coastguard Worker                     //   __cxa_end_catch destroying new_exception_header.
1286*c05d8e5dSAndroid Build Coastguard Worker                     new_exception_header->handlerCount = -new_exception_header->handlerCount;
1287*c05d8e5dSAndroid Build Coastguard Worker                     globals->uncaughtExceptions += 1;
1288*c05d8e5dSAndroid Build Coastguard Worker                     // Call __cxa_end_catch for new_exception_header
1289*c05d8e5dSAndroid Build Coastguard Worker                     __cxa_end_catch();
1290*c05d8e5dSAndroid Build Coastguard Worker                     // Call __cxa_end_catch for old_exception_header
1291*c05d8e5dSAndroid Build Coastguard Worker                     __cxa_end_catch();
1292*c05d8e5dSAndroid Build Coastguard Worker                     // Renter this catch clause with new_exception_header
1293*c05d8e5dSAndroid Build Coastguard Worker                     __cxa_begin_catch(&new_exception_header->unwindHeader);
1294*c05d8e5dSAndroid Build Coastguard Worker                     // Rethrow new_exception_header
1295*c05d8e5dSAndroid Build Coastguard Worker                     throw;
1296*c05d8e5dSAndroid Build Coastguard Worker                 }
1297*c05d8e5dSAndroid Build Coastguard Worker             }
1298*c05d8e5dSAndroid Build Coastguard Worker             // Will a std::bad_exception be catchable by the exception spec at
1299*c05d8e5dSAndroid Build Coastguard Worker             //   ttypeIndex?
1300*c05d8e5dSAndroid Build Coastguard Worker             // If no
1301*c05d8e5dSAndroid Build Coastguard Worker             //    throw std::bad_exception();
1302*c05d8e5dSAndroid Build Coastguard Worker             const __shim_type_info* excpType =
1303*c05d8e5dSAndroid Build Coastguard Worker                 static_cast<const __shim_type_info*>(&typeid(std::bad_exception));
1304*c05d8e5dSAndroid Build Coastguard Worker             std::bad_exception be;
1305*c05d8e5dSAndroid Build Coastguard Worker             adjustedPtr = &be;
1306*c05d8e5dSAndroid Build Coastguard Worker             if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
1307*c05d8e5dSAndroid Build Coastguard Worker                                           excpType, adjustedPtr, unwind_exception))
1308*c05d8e5dSAndroid Build Coastguard Worker             {
1309*c05d8e5dSAndroid Build Coastguard Worker                 // We need to __cxa_end_catch for both the old exception and the
1310*c05d8e5dSAndroid Build Coastguard Worker                 //   new exception.  Technically we should do it in that order.
1311*c05d8e5dSAndroid Build Coastguard Worker                 //   But it is expedient to do it in the opposite order:
1312*c05d8e5dSAndroid Build Coastguard Worker                 // Call __cxa_end_catch for new_exception_header
1313*c05d8e5dSAndroid Build Coastguard Worker                 __cxa_end_catch();
1314*c05d8e5dSAndroid Build Coastguard Worker                 // Throw std::bad_exception will __cxa_end_catch for
1315*c05d8e5dSAndroid Build Coastguard Worker                 //   old_exception_header
1316*c05d8e5dSAndroid Build Coastguard Worker                 throw be;
1317*c05d8e5dSAndroid Build Coastguard Worker             }
1318*c05d8e5dSAndroid Build Coastguard Worker         }
1319*c05d8e5dSAndroid Build Coastguard Worker     }
1320*c05d8e5dSAndroid Build Coastguard Worker     std::__terminate(t_handler);
1321*c05d8e5dSAndroid Build Coastguard Worker }
1322*c05d8e5dSAndroid Build Coastguard Worker 
1323*c05d8e5dSAndroid Build Coastguard Worker }  // extern "C"
1324*c05d8e5dSAndroid Build Coastguard Worker 
1325*c05d8e5dSAndroid Build Coastguard Worker }  // __cxxabiv1
1326