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