~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to system/lib/libcxxabi/src/cxa_personality.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===------------------------- cxa_exception.cpp --------------------------===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is dual licensed under the MIT and the University of Illinois Open
 
6
// Source Licenses. See LICENSE.TXT for details.
 
7
//
 
8
//  
 
9
//  This file implements the "Exception Handling APIs"
 
10
//  http://www.codesourcery.com/public/cxx-abi/abi-eh.html
 
11
//  http://www.intel.com/design/itanium/downloads/245358.htm
 
12
//  
 
13
//===----------------------------------------------------------------------===//
 
14
 
 
15
#include "unwind.h"
 
16
#include "cxa_exception.hpp"
 
17
#include "cxa_handlers.hpp"
 
18
#include "private_typeinfo.h"
 
19
#include <typeinfo>
 
20
#include <stdlib.h>
 
21
#include <assert.h>
 
22
 
 
23
/*
 
24
    Exception Header Layout:
 
25
 
 
26
+---------------------------+-----------------------------+---------------+
 
27
| __cxa_exception           | _Unwind_Exception CLNGC++\0 | thrown object |
 
28
+---------------------------+-----------------------------+---------------+
 
29
                                                          ^
 
30
                                                          |
 
31
  +-------------------------------------------------------+
 
32
  |
 
33
+---------------------------+-----------------------------+
 
34
| __cxa_dependent_exception | _Unwind_Exception CLNGC++\1 |
 
35
+---------------------------+-----------------------------+
 
36
 
 
37
    Exception Handling Table Layout:
 
38
 
 
39
+-----------------+--------+
 
40
| lpStartEncoding | (char) |
 
41
+---------+-------+--------+---------------+-----------------------+
 
42
| lpStart | (encoded with lpStartEncoding) | defaults to funcStart |
 
43
+---------+-----+--------+-----------------+---------------+-------+
 
44
| ttypeEncoding | (char) | Encoding of the type_info table |
 
45
+---------------+-+------+----+----------------------------+----------------+
 
46
| classInfoOffset | (ULEB128) | Offset to type_info table, defaults to null |
 
47
+-----------------++--------+-+----------------------------+----------------+
 
48
| callSiteEncoding | (char) | Encoding for Call Site Table |
 
49
+------------------+--+-----+-----+------------------------+--------------------------+
 
50
| callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |
 
51
+---------------------+-----------+---------------------------------------------------+
 
52
#if !__arm__
 
53
+---------------------+-----------+------------------------------------------------+
 
54
| Beginning of Call Site Table            The current ip lies within the           |
 
55
| ...                                     (start, length) range of one of these    |
 
56
|                                         call sites. There may be action needed.  |
 
57
| +-------------+---------------------------------+------------------------------+ |
 
58
| | start       | (encoded with callSiteEncoding) | offset relative to funcStart | |
 
59
| | length      | (encoded with callSiteEncoding) | length of code fragment      | |
 
60
| | landingPad  | (encoded with callSiteEncoding) | offset relative to lpStart   | |
 
61
| | actionEntry | (ULEB128)                       | Action Table Index 1-based   | |
 
62
| |             |                                 | actionEntry == 0 -> cleanup  | |
 
63
| +-------------+---------------------------------+------------------------------+ |
 
64
| ...                                                                              |
 
65
+----------------------------------------------------------------------------------+
 
66
#else  // __arm_
 
67
+---------------------+-----------+------------------------------------------------+
 
68
| Beginning of Call Site Table            The current ip is a 1-based index into   |
 
69
| ...                                     this table.  Or it is -1 meaning no      |
 
70
|                                         action is needed.  Or it is 0 meaning    |
 
71
|                                         terminate.                               |
 
72
| +-------------+---------------------------------+------------------------------+ |
 
73
| | landingPad  | (ULEB128)                       | offset relative to lpStart   | |
 
74
| | actionEntry | (ULEB128)                       | Action Table Index 1-based   | |
 
75
| |             |                                 | actionEntry == 0 -> cleanup  | |
 
76
| +-------------+---------------------------------+------------------------------+ |
 
77
| ...                                                                              |
 
78
+----------------------------------------------------------------------------------+
 
79
#endif  // __arm_
 
80
+---------------------------------------------------------------------+
 
81
| Beginning of Action Table       ttypeIndex == 0 : cleanup           |
 
82
| ...                             ttypeIndex  > 0 : catch             |
 
83
|                                 ttypeIndex  < 0 : exception spec    |
 
84
| +--------------+-----------+--------------------------------------+ |
 
85
| | ttypeIndex   | (SLEB128) | Index into type_info Table (1-based) | |
 
86
| | actionOffset | (SLEB128) | Offset into next Action Table entry  | |
 
87
| +--------------+-----------+--------------------------------------+ |
 
88
| ...                                                                 |
 
89
+---------------------------------------------------------------------+-----------------+
 
90
| type_info Table, but classInfoOffset does *not* point here!                           |
 
91
| +----------------+------------------------------------------------+-----------------+ |
 
92
| | Nth type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == N | |
 
93
| +----------------+------------------------------------------------+-----------------+ |
 
94
| ...                                                                                   |
 
95
| +----------------+------------------------------------------------+-----------------+ |
 
96
| | 1st type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == 1 | |
 
97
| +----------------+------------------------------------------------+-----------------+ |
 
98
| +---------------------------------------+-----------+------------------------------+  |
 
99
| | 1st ttypeIndex for 1st exception spec | (ULEB128) | classInfoOffset points here! |  |
 
100
| | ...                                   | (ULEB128) |                              |  |
 
101
| | Mth ttypeIndex for 1st exception spec | (ULEB128) |                              |  |
 
102
| | 0                                     | (ULEB128) |                              |  |
 
103
| +---------------------------------------+------------------------------------------+  |
 
104
| ...                                                                                   |
 
105
| +---------------------------------------+------------------------------------------+  |
 
106
| | 0                                     | (ULEB128) | throw()                      |  |
 
107
| +---------------------------------------+------------------------------------------+  |
 
108
| ...                                                                                   |
 
109
| +---------------------------------------+------------------------------------------+  |
 
110
| | 1st ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
 
111
| | ...                                   | (ULEB128) |                              |  |
 
112
| | Mth ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
 
113
| | 0                                     | (ULEB128) |                              |  |
 
114
| +---------------------------------------+------------------------------------------+  |
 
115
+---------------------------------------------------------------------------------------+
 
116
 
 
117
Notes:
 
118
 
 
119
*  ttypeIndex in the Action Table, and in the exception spec table, is an index,
 
120
     not a byte count, if positive.  It is a negative index offset of
 
121
     classInfoOffset and the sizeof entry depends on ttypeEncoding.
 
122
   But if ttypeIndex is negative, it is a positive 1-based byte offset into the
 
123
     type_info Table.
 
124
   And if ttypeIndex is zero, it refers to a catch (...).
 
125
 
 
126
*  landingPad can be 0, this implies there is nothing to be done.
 
127
 
 
128
*  landingPad != 0 and actionEntry == 0 implies a cleanup needs to be done
 
129
     @landingPad.
 
130
 
 
131
*  A cleanup can also be found under landingPad != 0 and actionEntry != 0 in
 
132
     the Action Table with ttypeIndex == 0.
 
133
*/
 
134
 
 
135
namespace __cxxabiv1
 
136
{
 
137
 
 
138
extern "C"
 
139
{
 
140
 
 
141
// private API
 
142
 
 
143
// Heavily borrowed from llvm/examples/ExceptionDemo/ExceptionDemo.cpp
 
144
 
 
145
// DWARF Constants
 
146
enum
 
147
{
 
148
    DW_EH_PE_absptr   = 0x00,
 
149
    DW_EH_PE_uleb128  = 0x01,
 
150
    DW_EH_PE_udata2   = 0x02,
 
151
    DW_EH_PE_udata4   = 0x03,
 
152
    DW_EH_PE_udata8   = 0x04,
 
153
    DW_EH_PE_sleb128  = 0x09,
 
154
    DW_EH_PE_sdata2   = 0x0A,
 
155
    DW_EH_PE_sdata4   = 0x0B,
 
156
    DW_EH_PE_sdata8   = 0x0C,
 
157
    DW_EH_PE_pcrel    = 0x10,
 
158
    DW_EH_PE_textrel  = 0x20,
 
159
    DW_EH_PE_datarel  = 0x30,
 
160
    DW_EH_PE_funcrel  = 0x40,
 
161
    DW_EH_PE_aligned  = 0x50,
 
162
    DW_EH_PE_indirect = 0x80,
 
163
    DW_EH_PE_omit     = 0xFF
 
164
};
 
165
 
 
166
/// Read a uleb128 encoded value and advance pointer 
 
167
/// See Variable Length Data Appendix C in: 
 
168
/// @link http://dwarfstd.org/Dwarf4.pdf @unlink
 
169
/// @param data reference variable holding memory pointer to decode from
 
170
/// @returns decoded value
 
171
static
 
172
uintptr_t
 
173
readULEB128(const uint8_t** data)
 
174
{
 
175
    uintptr_t result = 0;
 
176
    uintptr_t shift = 0;
 
177
    unsigned char byte;
 
178
    const uint8_t *p = *data;
 
179
    do
 
180
    {
 
181
        byte = *p++;
 
182
        result |= static_cast<uintptr_t>(byte & 0x7F) << shift;
 
183
        shift += 7;
 
184
    } while (byte & 0x80);
 
185
    *data = p;
 
186
    return result;
 
187
}
 
188
 
 
189
/// Read a sleb128 encoded value and advance pointer 
 
190
/// See Variable Length Data Appendix C in: 
 
191
/// @link http://dwarfstd.org/Dwarf4.pdf @unlink
 
192
/// @param data reference variable holding memory pointer to decode from
 
193
/// @returns decoded value
 
194
static
 
195
intptr_t
 
196
readSLEB128(const uint8_t** data)
 
197
{
 
198
    uintptr_t result = 0;
 
199
    uintptr_t shift = 0;
 
200
    unsigned char byte;
 
201
    const uint8_t *p = *data;
 
202
    do
 
203
    {
 
204
        byte = *p++;
 
205
        result |= static_cast<uintptr_t>(byte & 0x7F) << shift;
 
206
        shift += 7;
 
207
    } while (byte & 0x80);
 
208
    *data = p;
 
209
    if ((byte & 0x40) && (shift < (sizeof(result) << 3)))
 
210
        result |= static_cast<uintptr_t>(~0) << shift;
 
211
    return static_cast<intptr_t>(result);
 
212
}
 
213
 
 
214
/// Read a pointer encoded value and advance pointer 
 
215
/// See Variable Length Data in: 
 
216
/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
 
217
/// @param data reference variable holding memory pointer to decode from
 
218
/// @param encoding dwarf encoding type
 
219
/// @returns decoded value
 
220
static
 
221
uintptr_t
 
222
readEncodedPointer(const uint8_t** data, uint8_t encoding)
 
223
{
 
224
    uintptr_t result = 0;
 
225
    if (encoding == DW_EH_PE_omit) 
 
226
        return result;
 
227
    const uint8_t* p = *data;
 
228
    // first get value 
 
229
    switch (encoding & 0x0F)
 
230
    {
 
231
    case DW_EH_PE_absptr:
 
232
        result = *((uintptr_t*)p);
 
233
        p += sizeof(uintptr_t);
 
234
        break;
 
235
    case DW_EH_PE_uleb128:
 
236
        result = readULEB128(&p);
 
237
        break;
 
238
    case DW_EH_PE_sleb128:
 
239
        result = static_cast<uintptr_t>(readSLEB128(&p));
 
240
        break;
 
241
    case DW_EH_PE_udata2:
 
242
        result = *((uint16_t*)p);
 
243
        p += sizeof(uint16_t);
 
244
        break;
 
245
    case DW_EH_PE_udata4:
 
246
        result = *((uint32_t*)p);
 
247
        p += sizeof(uint32_t);
 
248
        break;
 
249
    case DW_EH_PE_udata8:
 
250
        result = static_cast<uintptr_t>(*((uint64_t*)p));
 
251
        p += sizeof(uint64_t);
 
252
        break;
 
253
    case DW_EH_PE_sdata2:
 
254
        result = static_cast<uintptr_t>(*((int16_t*)p));
 
255
        p += sizeof(int16_t);
 
256
        break;
 
257
    case DW_EH_PE_sdata4:
 
258
        result = static_cast<uintptr_t>(*((int32_t*)p));
 
259
        p += sizeof(int32_t);
 
260
        break;
 
261
    case DW_EH_PE_sdata8:
 
262
        result = static_cast<uintptr_t>(*((int64_t*)p));
 
263
        p += sizeof(int64_t);
 
264
        break;
 
265
    default:
 
266
        // not supported 
 
267
        abort();
 
268
        break;
 
269
    }
 
270
    // then add relative offset 
 
271
    switch (encoding & 0x70)
 
272
    {
 
273
    case DW_EH_PE_absptr:
 
274
        // do nothing 
 
275
        break;
 
276
    case DW_EH_PE_pcrel:
 
277
        if (result)
 
278
            result += (uintptr_t)(*data);
 
279
        break;
 
280
    case DW_EH_PE_textrel:
 
281
    case DW_EH_PE_datarel:
 
282
    case DW_EH_PE_funcrel:
 
283
    case DW_EH_PE_aligned:
 
284
    default:
 
285
        // not supported 
 
286
        abort();
 
287
        break;
 
288
    }
 
289
    // then apply indirection 
 
290
    if (result && (encoding & DW_EH_PE_indirect))
 
291
        result = *((uintptr_t*)result);
 
292
    *data = p;
 
293
    return result;
 
294
}
 
295
 
 
296
static
 
297
void
 
298
call_terminate(bool native_exception, _Unwind_Exception* unwind_exception)
 
299
{
 
300
    __cxa_begin_catch(unwind_exception);
 
301
    if (native_exception)
 
302
    {
 
303
        // Use the stored terminate_handler if possible
 
304
        __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
 
305
        std::__terminate(exception_header->terminateHandler);
 
306
    }
 
307
    std::terminate();
 
308
}
 
309
 
 
310
static
 
311
const __shim_type_info*
 
312
get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
 
313
                   uint8_t ttypeEncoding, bool native_exception,
 
314
                   _Unwind_Exception* unwind_exception)
 
315
{
 
316
    if (classInfo == 0)
 
317
    {
 
318
        // this should not happen.  Indicates corrupted eh_table.
 
319
        call_terminate(native_exception, unwind_exception);
 
320
    }
 
321
    switch (ttypeEncoding & 0x0F)
 
322
    {
 
323
    case DW_EH_PE_absptr:
 
324
        ttypeIndex *= sizeof(void*);
 
325
        break;
 
326
    case DW_EH_PE_udata2:
 
327
    case DW_EH_PE_sdata2:
 
328
        ttypeIndex *= 2;
 
329
        break;
 
330
    case DW_EH_PE_udata4:
 
331
    case DW_EH_PE_sdata4:
 
332
        ttypeIndex *= 4;
 
333
        break;
 
334
    case DW_EH_PE_udata8:
 
335
    case DW_EH_PE_sdata8:
 
336
        ttypeIndex *= 8;
 
337
        break;
 
338
    default:
 
339
        // this should not happen.   Indicates corrupted eh_table.
 
340
        call_terminate(native_exception, unwind_exception);
 
341
    }
 
342
    classInfo -= ttypeIndex;
 
343
    return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding);
 
344
}
 
345
 
 
346
/*
 
347
    This is checking a thrown exception type, excpType, against a possibly empty
 
348
    list of catchType's which make up an exception spec.
 
349
 
 
350
    An exception spec acts like a catch handler, but in reverse.  This "catch
 
351
    handler" will catch an excpType if and only if none of the catchType's in
 
352
    the list will catch a excpType.  If any catchType in the list can catch an
 
353
    excpType, then this exception spec does not catch the excpType.
 
354
*/
 
355
static
 
356
bool
 
357
exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
 
358
                         uint8_t ttypeEncoding, const __shim_type_info* excpType,
 
359
                         void* adjustedPtr, _Unwind_Exception* unwind_exception)
 
360
{
 
361
    if (classInfo == 0)
 
362
    {
 
363
        // this should not happen.   Indicates corrupted eh_table.
 
364
        call_terminate(false, unwind_exception);
 
365
    }
 
366
    // specIndex is negative of 1-based byte offset into classInfo;
 
367
    specIndex = -specIndex;
 
368
    --specIndex;
 
369
    const uint8_t* temp = classInfo + specIndex;
 
370
    // If any type in the spec list can catch excpType, return false, else return true
 
371
    //    adjustments to adjustedPtr are ignored.
 
372
    while (true)
 
373
    {
 
374
        uint64_t ttypeIndex = readULEB128(&temp);
 
375
        if (ttypeIndex == 0)
 
376
            break;
 
377
        const __shim_type_info* catchType = get_shim_type_info(ttypeIndex,
 
378
                                                               classInfo,
 
379
                                                               ttypeEncoding,
 
380
                                                               true,
 
381
                                                               unwind_exception);
 
382
        void* tempPtr = adjustedPtr;
 
383
        if (catchType->can_catch(excpType, tempPtr))
 
384
            return false;
 
385
    }
 
386
    return true;
 
387
}
 
388
 
 
389
static
 
390
void*
 
391
get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
 
392
{
 
393
    // Even for foreign exceptions, the exception object is *probably* at unwind_exception + 1
 
394
    //    Regardless, this library is prohibited from touching a foreign exception
 
395
    void* adjustedPtr = unwind_exception + 1;
 
396
    if (unwind_exception->exception_class == kOurDependentExceptionClass)
 
397
        adjustedPtr = ((__cxa_dependent_exception*)adjustedPtr - 1)->primaryException;
 
398
    return adjustedPtr;
 
399
}
 
400
 
 
401
namespace
 
402
{
 
403
 
 
404
struct scan_results
 
405
{
 
406
    int64_t        ttypeIndex;   // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup
 
407
    const uint8_t* actionRecord;         // Currently unused.  Retained to ease future maintenance.
 
408
    const uint8_t* languageSpecificData;  // Needed only for __cxa_call_unexpected
 
409
    uintptr_t      landingPad;   // null -> nothing found, else something found
 
410
    void*          adjustedPtr;  // Used in cxa_exception.cpp
 
411
    _Unwind_Reason_Code reason;  // One of _URC_FATAL_PHASE1_ERROR,
 
412
                                 //        _URC_FATAL_PHASE2_ERROR,
 
413
                                 //        _URC_CONTINUE_UNWIND,
 
414
                                 //        _URC_HANDLER_FOUND
 
415
};
 
416
 
 
417
}  // unnamed namespace
 
418
 
 
419
static
 
420
void
 
421
set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
 
422
              const scan_results& results)
 
423
{
 
424
#if __arm__
 
425
    _Unwind_SetGR(context, 0, reinterpret_cast<uintptr_t>(unwind_exception));
 
426
    _Unwind_SetGR(context, 1, static_cast<uintptr_t>(results.ttypeIndex));
 
427
#else
 
428
    _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
 
429
                                 reinterpret_cast<uintptr_t>(unwind_exception));
 
430
    _Unwind_SetGR(context, __builtin_eh_return_data_regno(1),
 
431
                                    static_cast<uintptr_t>(results.ttypeIndex));
 
432
#endif
 
433
    _Unwind_SetIP(context, results.landingPad);
 
434
}
 
435
 
 
436
/*
 
437
    There are 3 types of scans needed:
 
438
 
 
439
    1.  Scan for handler with native or foreign exception.  If handler found,
 
440
        save state and return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND.
 
441
        May also report an error on invalid input.
 
442
        May terminate for invalid exception table.
 
443
        _UA_SEARCH_PHASE
 
444
 
 
445
    2.  Scan for handler with foreign exception.  Must return _URC_HANDLER_FOUND,
 
446
        or call terminate.
 
447
        _UA_CLEANUP_PHASE && _UA_HANDLER_FRAME && !native_exception
 
448
 
 
449
    3.  Scan for cleanups.  If a handler is found and this isn't forced unwind,
 
450
        then terminate, otherwise ignore the handler and keep looking for cleanup.
 
451
        If a cleanup is found, return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND.
 
452
        May also report an error on invalid input.
 
453
        May terminate for invalid exception table.
 
454
        _UA_CLEANUP_PHASE && !_UA_HANDLER_FRAME
 
455
*/
 
456
 
 
457
static
 
458
void
 
459
scan_eh_tab(scan_results& results, _Unwind_Action actions, bool native_exception,
 
460
            _Unwind_Exception* unwind_exception, _Unwind_Context* context)
 
461
{
 
462
    // Initialize results to found nothing but an error
 
463
    results.ttypeIndex = 0;
 
464
    results.actionRecord = 0;
 
465
    results.languageSpecificData = 0;
 
466
    results.landingPad = 0;
 
467
    results.adjustedPtr = 0;
 
468
    results.reason = _URC_FATAL_PHASE1_ERROR;
 
469
    // Check for consistent actions
 
470
    if (actions & _UA_SEARCH_PHASE)
 
471
    {
 
472
        // Do Phase 1
 
473
        if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND))
 
474
        {
 
475
            // None of these flags should be set during Phase 1
 
476
            //   Client error
 
477
            results.reason = _URC_FATAL_PHASE1_ERROR;
 
478
            return;
 
479
        }
 
480
    }
 
481
    else if (actions & _UA_CLEANUP_PHASE)
 
482
    {
 
483
        if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND))
 
484
        {
 
485
            // _UA_HANDLER_FRAME should only be set if phase 1 found a handler.
 
486
            // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened.
 
487
            //    Client error
 
488
            results.reason = _URC_FATAL_PHASE2_ERROR;
 
489
            return;
 
490
        }
 
491
    }
 
492
    else // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set
 
493
    {
 
494
        // One of these should be set.
 
495
        //   Client error
 
496
        results.reason = _URC_FATAL_PHASE1_ERROR;
 
497
        return;
 
498
    }
 
499
    // Start scan by getting exception table address
 
500
    const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context);
 
501
    if (lsda == 0)
 
502
    {
 
503
        // There is no exception table
 
504
        results.reason = _URC_CONTINUE_UNWIND;
 
505
        return;
 
506
    }
 
507
    results.languageSpecificData = lsda;
 
508
    // Get the current instruction pointer and offset it before next
 
509
    // instruction in the current frame which threw the exception.
 
510
    uintptr_t ip = _Unwind_GetIP(context) - 1;
 
511
    // Get beginning current frame's code (as defined by the 
 
512
    // emitted dwarf code)
 
513
    uintptr_t funcStart = _Unwind_GetRegionStart(context);
 
514
#if __arm__
 
515
    if (ip == uintptr_t(-1))
 
516
    {
 
517
        // no action
 
518
        results.reason = _URC_CONTINUE_UNWIND;
 
519
        return;
 
520
    }
 
521
    else if (ip == 0)
 
522
        call_terminate(native_exception, unwind_exception);
 
523
    // ip is 1-based index into call site table
 
524
#else  // __arm__
 
525
    uintptr_t ipOffset = ip - funcStart;
 
526
#endif  // __arm__
 
527
    const uint8_t* classInfo = NULL;
 
528
    // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
 
529
    //       dwarf emission
 
530
    // Parse LSDA header.
 
531
    uint8_t lpStartEncoding = *lsda++;
 
532
    const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
 
533
    if (lpStart == 0)
 
534
        lpStart = (const uint8_t*)funcStart;
 
535
    uint8_t ttypeEncoding = *lsda++;
 
536
    if (ttypeEncoding != DW_EH_PE_omit)
 
537
    {
 
538
        // Calculate type info locations in emitted dwarf code which
 
539
        // were flagged by type info arguments to llvm.eh.selector
 
540
        // intrinsic
 
541
        uintptr_t classInfoOffset = readULEB128(&lsda);
 
542
        classInfo = lsda + classInfoOffset;
 
543
    }
 
544
    // Walk call-site table looking for range that 
 
545
    // includes current PC. 
 
546
    uint8_t callSiteEncoding = *lsda++;
 
547
#if __arm__
 
548
    (void)callSiteEncoding;  // On arm callSiteEncoding is never used
 
549
#endif
 
550
    uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
 
551
    const uint8_t* callSiteTableStart = lsda;
 
552
    const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength;
 
553
    const uint8_t* actionTableStart = callSiteTableEnd;
 
554
    const uint8_t* callSitePtr = callSiteTableStart;
 
555
    while (callSitePtr < callSiteTableEnd)
 
556
    {
 
557
        // There is one entry per call site.
 
558
#if !__arm__
 
559
        // The call sites are non-overlapping in [start, start+length)
 
560
        // The call sites are ordered in increasing value of start
 
561
        uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
 
562
        uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding);
 
563
        uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
 
564
        uintptr_t actionEntry = readULEB128(&callSitePtr);
 
565
        if ((start <= ipOffset) && (ipOffset < (start + length)))
 
566
#else  // __arm__
 
567
        // ip is 1-based index into this table
 
568
        uintptr_t landingPad = readULEB128(&callSitePtr);
 
569
        uintptr_t actionEntry = readULEB128(&callSitePtr);
 
570
        if (--ip == 0)
 
571
#endif  // __arm__
 
572
        {
 
573
            // Found the call site containing ip.
 
574
#if !__arm__
 
575
            if (landingPad == 0)
 
576
            {
 
577
                // No handler here
 
578
                results.reason = _URC_CONTINUE_UNWIND;
 
579
                return;
 
580
            }
 
581
            landingPad = (uintptr_t)lpStart + landingPad;
 
582
#else  // __arm__
 
583
            ++landingPad;
 
584
#endif  // __arm__
 
585
            if (actionEntry == 0)
 
586
            {
 
587
                // Found a cleanup
 
588
                // If this is a type 1 or type 2 search, there are no handlers
 
589
                // If this is a type 3 search, you want to install the cleanup.
 
590
                if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
 
591
                {
 
592
                    results.ttypeIndex = 0;  // Redundant but clarifying
 
593
                    results.landingPad = landingPad;
 
594
                    results.reason = _URC_HANDLER_FOUND;
 
595
                    return;
 
596
                }
 
597
                // No handler here
 
598
                results.reason = _URC_CONTINUE_UNWIND;
 
599
                return;
 
600
            }
 
601
            // Convert 1-based byte offset into
 
602
            const uint8_t* action = actionTableStart + (actionEntry - 1);
 
603
            // Scan action entries until you find a matching handler, cleanup, or the end of action list
 
604
            while (true)
 
605
            {
 
606
                const uint8_t* actionRecord = action;
 
607
                int64_t ttypeIndex = readSLEB128(&action);
 
608
                if (ttypeIndex > 0)
 
609
                {
 
610
                    // Found a catch, does it actually catch?
 
611
                    // First check for catch (...)
 
612
                    const __shim_type_info* catchType =
 
613
                        get_shim_type_info(static_cast<uint64_t>(ttypeIndex),
 
614
                                           classInfo, ttypeEncoding,
 
615
                                           native_exception, unwind_exception);
 
616
                    if (catchType == 0)
 
617
                    {
 
618
                        // Found catch (...) catches everything, including foreign exceptions
 
619
                        // If this is a type 1 search save state and return _URC_HANDLER_FOUND
 
620
                        // If this is a type 2 search save state and return _URC_HANDLER_FOUND
 
621
                        // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
 
622
                        // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
 
623
                        if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
 
624
                        {
 
625
                            // Save state and return _URC_HANDLER_FOUND
 
626
                            results.ttypeIndex = ttypeIndex;
 
627
                            results.actionRecord = actionRecord;
 
628
                            results.landingPad = landingPad;
 
629
                            results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
 
630
                            results.reason = _URC_HANDLER_FOUND;
 
631
                            return;
 
632
                        }
 
633
                        else if (!(actions & _UA_FORCE_UNWIND))
 
634
                        {
 
635
                            // It looks like the exception table has changed
 
636
                            //    on us.  Likely stack corruption!
 
637
                            call_terminate(native_exception, unwind_exception);
 
638
                        }
 
639
                    }
 
640
                    // Else this is a catch (T) clause and will never
 
641
                    //    catch a foreign exception
 
642
                    else if (native_exception)
 
643
                    {
 
644
                        __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
 
645
                        void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
 
646
                        const __shim_type_info* excpType =
 
647
                            static_cast<const __shim_type_info*>(exception_header->exceptionType);
 
648
                        if (adjustedPtr == 0 || excpType == 0)
 
649
                        {
 
650
                            // Something very bad happened
 
651
                            call_terminate(native_exception, unwind_exception);
 
652
                        }
 
653
                        if (catchType->can_catch(excpType, adjustedPtr))
 
654
                        {
 
655
                            // Found a matching handler
 
656
                            // If this is a type 1 search save state and return _URC_HANDLER_FOUND
 
657
                            // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1!
 
658
                            // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan
 
659
                            if (actions & _UA_SEARCH_PHASE)
 
660
                            {
 
661
                                // Save state and return _URC_HANDLER_FOUND
 
662
                                results.ttypeIndex = ttypeIndex;
 
663
                                results.actionRecord = actionRecord;
 
664
                                results.landingPad = landingPad;
 
665
                                results.adjustedPtr = adjustedPtr;
 
666
                                results.reason = _URC_HANDLER_FOUND;
 
667
                                return;
 
668
                            }
 
669
                            else if (!(actions & _UA_FORCE_UNWIND))
 
670
                            {
 
671
                                // It looks like the exception table has changed
 
672
                                //    on us.  Likely stack corruption!
 
673
                                call_terminate(native_exception, unwind_exception);
 
674
                            }
 
675
                        }
 
676
                    }
 
677
                    // Scan next action ...
 
678
                }
 
679
                else if (ttypeIndex < 0)
 
680
                {
 
681
                    // Found an exception spec.  If this is a foreign exception,
 
682
                    //   it is always caught.
 
683
                    if (native_exception)
 
684
                    {
 
685
                        // Does the exception spec catch this native exception?
 
686
                        __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
 
687
                        void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
 
688
                        const __shim_type_info* excpType =
 
689
                            static_cast<const __shim_type_info*>(exception_header->exceptionType);
 
690
                        if (adjustedPtr == 0 || excpType == 0)
 
691
                        {
 
692
                            // Something very bad happened
 
693
                            call_terminate(native_exception, unwind_exception);
 
694
                        }
 
695
                        if (exception_spec_can_catch(ttypeIndex, classInfo,
 
696
                                                     ttypeEncoding, excpType,
 
697
                                                     adjustedPtr, unwind_exception))
 
698
                        {
 
699
                            // native exception caught by exception spec
 
700
                            // If this is a type 1 search, save state and return _URC_HANDLER_FOUND
 
701
                            // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
 
702
                            // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
 
703
                            if (actions & _UA_SEARCH_PHASE)
 
704
                            {
 
705
                                // Save state and return _URC_HANDLER_FOUND
 
706
                                results.ttypeIndex = ttypeIndex;
 
707
                                results.actionRecord = actionRecord;
 
708
                                results.landingPad = landingPad;
 
709
                                results.adjustedPtr = adjustedPtr;
 
710
                                results.reason = _URC_HANDLER_FOUND;
 
711
                                return;
 
712
                            }
 
713
                            else if (!(actions & _UA_FORCE_UNWIND))
 
714
                            {
 
715
                                // It looks like the exception table has changed
 
716
                                //    on us.  Likely stack corruption!
 
717
                                call_terminate(native_exception, unwind_exception);
 
718
                            }
 
719
                        }
 
720
                    }
 
721
                    else
 
722
                    {
 
723
                        // foreign exception caught by exception spec
 
724
                        // If this is a type 1 search, save state and return _URC_HANDLER_FOUND
 
725
                        // If this is a type 2 search, save state and return _URC_HANDLER_FOUND
 
726
                        // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
 
727
                        // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
 
728
                        if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
 
729
                        {
 
730
                            // Save state and return _URC_HANDLER_FOUND
 
731
                            results.ttypeIndex = ttypeIndex;
 
732
                            results.actionRecord = actionRecord;
 
733
                            results.landingPad = landingPad;
 
734
                            results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
 
735
                            results.reason = _URC_HANDLER_FOUND;
 
736
                            return;
 
737
                        }
 
738
                        else if (!(actions & _UA_FORCE_UNWIND))
 
739
                        {
 
740
                            // It looks like the exception table has changed
 
741
                            //    on us.  Likely stack corruption!
 
742
                            call_terminate(native_exception, unwind_exception);
 
743
                        }
 
744
                    }
 
745
                    // Scan next action ...
 
746
                }
 
747
                else  // ttypeIndex == 0
 
748
                {
 
749
                    // Found a cleanup
 
750
                    // If this is a type 1 search, ignore it and continue scan
 
751
                    // If this is a type 2 search, ignore it and continue scan
 
752
                    // If this is a type 3 search, save state and return _URC_HANDLER_FOUND
 
753
                    if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
 
754
                    {
 
755
                        // Save state and return _URC_HANDLER_FOUND
 
756
                        results.ttypeIndex = ttypeIndex;
 
757
                        results.actionRecord = actionRecord;
 
758
                        results.landingPad = landingPad;
 
759
                        results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
 
760
                        results.reason = _URC_HANDLER_FOUND;
 
761
                        return;
 
762
                    }
 
763
                }
 
764
                const uint8_t* temp = action;
 
765
                int64_t actionOffset = readSLEB128(&temp);
 
766
                if (actionOffset == 0)
 
767
                {
 
768
                    // End of action list, no matching handler or cleanup found
 
769
                    results.reason = _URC_CONTINUE_UNWIND;
 
770
                    return;
 
771
                }
 
772
                // Go to next action
 
773
                action += actionOffset;
 
774
            }  // there is no break out of this loop, only return
 
775
        }
 
776
#if !__arm__
 
777
        else if (ipOffset < start)
 
778
        {
 
779
            // There is no call site for this ip
 
780
            // Something bad has happened.  We should never get here.
 
781
            // Possible stack corruption.
 
782
            call_terminate(native_exception, unwind_exception);
 
783
        }
 
784
#endif  // !__arm__
 
785
    }  // there might be some tricky cases which break out of this loop
 
786
 
 
787
    // It is possible that no eh table entry specify how to handle
 
788
    // this exception. By spec, terminate it immediately.
 
789
    call_terminate(native_exception, unwind_exception);
 
790
}
 
791
 
 
792
// public API
 
793
 
 
794
/*
 
795
The personality function branches on actions like so:
 
796
 
 
797
_UA_SEARCH_PHASE
 
798
 
 
799
    If _UA_CLEANUP_PHASE or _UA_HANDLER_FRAME or _UA_FORCE_UNWIND there's
 
800
      an error from above, return _URC_FATAL_PHASE1_ERROR.
 
801
 
 
802
    Scan for anything that could stop unwinding:
 
803
 
 
804
       1.  A catch clause that will catch this exception
 
805
           (will never catch foreign).
 
806
       2.  A catch (...) (will always catch foreign).
 
807
       3.  An exception spec that will catch this exception
 
808
           (will always catch foreign).
 
809
    If a handler is found
 
810
        If not foreign
 
811
            Save state in header
 
812
        return _URC_HANDLER_FOUND
 
813
    Else a handler not found
 
814
        return _URC_CONTINUE_UNWIND
 
815
 
 
816
_UA_CLEANUP_PHASE
 
817
 
 
818
    If _UA_HANDLER_FRAME
 
819
        If _UA_FORCE_UNWIND
 
820
            How did this happen?  return _URC_FATAL_PHASE2_ERROR
 
821
        If foreign
 
822
            Do _UA_SEARCH_PHASE to recover state
 
823
        else
 
824
            Recover state from header
 
825
        Transfer control to landing pad.  return _URC_INSTALL_CONTEXT
 
826
    
 
827
    Else
 
828
 
 
829
        This branch handles both normal C++ non-catching handlers (cleanups)
 
830
          and forced unwinding.    
 
831
        Scan for anything that can not stop unwinding:
 
832
    
 
833
            1.  A cleanup.
 
834
 
 
835
        If a cleanup is found
 
836
            transfer control to it. return _URC_INSTALL_CONTEXT
 
837
        Else a cleanup is not found: return _URC_CONTINUE_UNWIND
 
838
*/
 
839
 
 
840
_Unwind_Reason_Code
 
841
#if __arm__
 
842
__gxx_personality_sj0
 
843
#else
 
844
__gxx_personality_v0
 
845
#endif
 
846
                    (int version, _Unwind_Action actions, uint64_t exceptionClass,
 
847
                     _Unwind_Exception* unwind_exception, _Unwind_Context* context)
 
848
{
 
849
    if (version != 1 || unwind_exception == 0 || context == 0)
 
850
        return _URC_FATAL_PHASE1_ERROR;
 
851
    bool native_exception = (exceptionClass     & get_vendor_and_language) ==
 
852
                            (kOurExceptionClass & get_vendor_and_language);
 
853
    scan_results results;
 
854
    if (actions & _UA_SEARCH_PHASE)
 
855
    {
 
856
        // Phase 1 search:  All we're looking for in phase 1 is a handler that
 
857
        //   halts unwinding
 
858
        scan_eh_tab(results, actions, native_exception, unwind_exception, context);
 
859
        if (results.reason == _URC_HANDLER_FOUND)
 
860
        {
 
861
            // Found one.  Can we cache the results somewhere to optimize phase 2?
 
862
            if (native_exception)
 
863
            {
 
864
                __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
 
865
                exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
 
866
                exception_header->actionRecord = results.actionRecord;
 
867
                exception_header->languageSpecificData = results.languageSpecificData;
 
868
                exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad);
 
869
                exception_header->adjustedPtr = results.adjustedPtr;
 
870
            }
 
871
            return _URC_HANDLER_FOUND;
 
872
        }
 
873
        // Did not find a catching-handler.  Return the results of the scan
 
874
        //    (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR
 
875
        //     if we were called improperly).
 
876
        return results.reason;
 
877
    }
 
878
    if (actions & _UA_CLEANUP_PHASE)
 
879
    {
 
880
        // Phase 2 search:
 
881
        //  Did we find a catching handler in phase 1?
 
882
        if (actions & _UA_HANDLER_FRAME)
 
883
        {
 
884
            // Yes, phase 1 said we have a catching handler here.
 
885
            // Did we cache the results of the scan?
 
886
            if (native_exception)
 
887
            {
 
888
                // Yes, reload the results from the cache.
 
889
                __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
 
890
                results.ttypeIndex = exception_header->handlerSwitchValue;
 
891
                results.actionRecord = exception_header->actionRecord;
 
892
                results.languageSpecificData = exception_header->languageSpecificData;
 
893
                results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp);
 
894
                results.adjustedPtr = exception_header->adjustedPtr;
 
895
            }
 
896
            else
 
897
            {
 
898
                // No, do the scan again to reload the results.
 
899
                scan_eh_tab(results, actions, native_exception, unwind_exception, context);
 
900
                // Phase 1 told us we would find a handler.  Now in Phase 2 we
 
901
                //   didn't find a handler.  The eh table should not be changing!
 
902
                if (results.reason != _URC_HANDLER_FOUND)
 
903
                    call_terminate(native_exception, unwind_exception);
 
904
            }
 
905
            // Jump to the handler
 
906
            set_registers(unwind_exception, context, results);
 
907
            return _URC_INSTALL_CONTEXT;
 
908
        }
 
909
        // Either we didn't do a phase 1 search (due to forced unwinding), or
 
910
        //   phase 1 reported no catching-handlers.
 
911
        // Search for a (non-catching) cleanup
 
912
        scan_eh_tab(results, actions, native_exception, unwind_exception, context);
 
913
        if (results.reason == _URC_HANDLER_FOUND)
 
914
        {
 
915
            // Found a non-catching handler.  Jump to it:
 
916
            set_registers(unwind_exception, context, results);
 
917
            return _URC_INSTALL_CONTEXT;
 
918
        }
 
919
        // Did not find a cleanup.  Return the results of the scan
 
920
        //    (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR
 
921
        //     if we were called improperly).
 
922
        return results.reason;
 
923
    }
 
924
    // We were called improperly: neither a phase 1 or phase 2 search
 
925
    return _URC_FATAL_PHASE1_ERROR;
 
926
}
 
927
 
 
928
__attribute__((noreturn))
 
929
void
 
930
__cxa_call_unexpected(void* arg)
 
931
{
 
932
    _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg);
 
933
    if (unwind_exception == 0)
 
934
        call_terminate(false, unwind_exception);
 
935
    __cxa_begin_catch(unwind_exception);
 
936
    bool native_old_exception =
 
937
        (unwind_exception->exception_class & get_vendor_and_language) ==
 
938
        (kOurExceptionClass                & get_vendor_and_language);
 
939
    std::unexpected_handler u_handler;
 
940
    std::terminate_handler t_handler;
 
941
    __cxa_exception* old_exception_header = 0;
 
942
    int64_t ttypeIndex;
 
943
    const uint8_t* lsda;
 
944
    if (native_old_exception)
 
945
    {
 
946
        old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
 
947
        t_handler = old_exception_header->terminateHandler;
 
948
        u_handler = old_exception_header->unexpectedHandler;
 
949
        // If std::__unexpected(u_handler) rethrows the same exception,
 
950
        //   these values get overwritten by the rethrow.  So save them now:
 
951
        ttypeIndex = old_exception_header->handlerSwitchValue;
 
952
        lsda = old_exception_header->languageSpecificData;
 
953
    }
 
954
    else
 
955
    {
 
956
        t_handler = std::get_terminate();
 
957
        u_handler = std::get_unexpected();
 
958
    }
 
959
    try
 
960
    {
 
961
        std::__unexpected(u_handler);
 
962
    }
 
963
    catch (...)
 
964
    {
 
965
        // If the old exception is foreign, then all we can do is terminate.
 
966
        //   We have no way to recover the needed old exception spec.  There's
 
967
        //   no way to pass that information here.  And the personality routine
 
968
        //   can't call us directly and do anything but terminate() if we throw
 
969
        //   from here.
 
970
        if (native_old_exception)
 
971
        {
 
972
            // Have:
 
973
            //   old_exception_header->languageSpecificData
 
974
            //   old_exception_header->actionRecord
 
975
            // Need
 
976
            //   const uint8_t* classInfo
 
977
            //   uint8_t ttypeEncoding
 
978
            uint8_t lpStartEncoding = *lsda++;
 
979
            const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
 
980
            (void)lpStart;  // purposefully unused.  Just needed to increment lsda.
 
981
            uint8_t ttypeEncoding = *lsda++;
 
982
            if (ttypeEncoding == DW_EH_PE_omit)
 
983
                std::__terminate(t_handler);
 
984
            uintptr_t classInfoOffset = readULEB128(&lsda);
 
985
            const uint8_t* classInfo = lsda + classInfoOffset;
 
986
            // Is this new exception catchable by the exception spec at ttypeIndex?
 
987
            // The answer is obviously yes if the new and old exceptions are the same exception
 
988
            // If no
 
989
            //    throw;
 
990
            __cxa_eh_globals* globals = __cxa_get_globals_fast();
 
991
            __cxa_exception* new_exception_header = globals->caughtExceptions;
 
992
            if (new_exception_header == 0)
 
993
                // This shouldn't be able to happen!
 
994
                std::__terminate(t_handler);
 
995
            bool native_new_exception =
 
996
                (new_exception_header->unwindHeader.exception_class & get_vendor_and_language) ==
 
997
                                                (kOurExceptionClass & get_vendor_and_language);
 
998
            void* adjustedPtr;
 
999
            if (native_new_exception && (new_exception_header != old_exception_header))
 
1000
            {
 
1001
                const __shim_type_info* excpType =
 
1002
                    static_cast<const __shim_type_info*>(new_exception_header->exceptionType);
 
1003
                adjustedPtr =
 
1004
                    new_exception_header->unwindHeader.exception_class == kOurDependentExceptionClass ?
 
1005
                        ((__cxa_dependent_exception*)new_exception_header)->primaryException :
 
1006
                        new_exception_header + 1;
 
1007
                if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
 
1008
                                              excpType, adjustedPtr, unwind_exception))
 
1009
                {
 
1010
                    // We need to __cxa_end_catch, but for the old exception,
 
1011
                    //   not the new one.  This is a little tricky ...
 
1012
                    // Disguise new_exception_header as a rethrown exception, but
 
1013
                    //   don't actually rethrow it.  This means you can temporarily
 
1014
                    //   end the catch clause enclosing new_exception_header without
 
1015
                    //   __cxa_end_catch destroying new_exception_header.
 
1016
                    new_exception_header->handlerCount = -new_exception_header->handlerCount;
 
1017
                    globals->uncaughtExceptions += 1;
 
1018
                    // Call __cxa_end_catch for new_exception_header
 
1019
                    __cxa_end_catch();
 
1020
                    // Call __cxa_end_catch for old_exception_header
 
1021
                    __cxa_end_catch();
 
1022
                    // Renter this catch clause with new_exception_header
 
1023
                    __cxa_begin_catch(&new_exception_header->unwindHeader);
 
1024
                    // Rethrow new_exception_header
 
1025
                    throw;
 
1026
                }
 
1027
            }
 
1028
            // Will a std::bad_exception be catchable by the exception spec at
 
1029
            //   ttypeIndex?
 
1030
            // If no
 
1031
            //    throw std::bad_exception();
 
1032
            const __shim_type_info* excpType =
 
1033
                static_cast<const __shim_type_info*>(&typeid(std::bad_exception));
 
1034
            std::bad_exception be;
 
1035
            adjustedPtr = &be;
 
1036
            if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
 
1037
                                          excpType, adjustedPtr, unwind_exception))
 
1038
            {
 
1039
                // We need to __cxa_end_catch for both the old exception and the
 
1040
                //   new exception.  Technically we should do it in that order.
 
1041
                //   But it is expedient to do it in the opposite order:
 
1042
                // Call __cxa_end_catch for new_exception_header
 
1043
                __cxa_end_catch();
 
1044
                // Throw std::bad_exception will __cxa_end_catch for
 
1045
                //   old_exception_header
 
1046
                throw be;
 
1047
            }
 
1048
        }
 
1049
    }
 
1050
    std::__terminate(t_handler);
 
1051
}
 
1052
 
 
1053
}  // extern "C"
 
1054
 
 
1055
}  // __cxxabiv1