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