Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libcxxrt/exception.cc
39476 views
1
/*
2
* Copyright 2010-2011 PathScale, Inc. All rights reserved.
3
* Copyright 2021 David Chisnall. All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
7
*
8
* 1. Redistributions of source code must retain the above copyright notice,
9
* this list of conditions and the following disclaimer.
10
*
11
* 2. Redistributions in binary form must reproduce the above copyright notice,
12
* this list of conditions and the following disclaimer in the documentation
13
* and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
16
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*/
27
28
#include <stdlib.h>
29
#include <dlfcn.h>
30
#include <stdio.h>
31
#include <string.h>
32
#include <stdint.h>
33
#include <pthread.h>
34
#include "typeinfo.h"
35
#include "dwarf_eh.h"
36
#include "atomic.h"
37
#include "cxxabi.h"
38
39
#pragma weak pthread_key_create
40
#pragma weak pthread_setspecific
41
#pragma weak pthread_getspecific
42
#pragma weak pthread_once
43
#ifdef LIBCXXRT_WEAK_LOCKS
44
#pragma weak pthread_mutex_lock
45
#define pthread_mutex_lock(mtx) do {\
46
if (pthread_mutex_lock) pthread_mutex_lock(mtx);\
47
} while(0)
48
#pragma weak pthread_mutex_unlock
49
#define pthread_mutex_unlock(mtx) do {\
50
if (pthread_mutex_unlock) pthread_mutex_unlock(mtx);\
51
} while(0)
52
#pragma weak pthread_cond_signal
53
#define pthread_cond_signal(cv) do {\
54
if (pthread_cond_signal) pthread_cond_signal(cv);\
55
} while(0)
56
#pragma weak pthread_cond_wait
57
#define pthread_cond_wait(cv, mtx) do {\
58
if (pthread_cond_wait) pthread_cond_wait(cv, mtx);\
59
} while(0)
60
#endif
61
62
using namespace ABI_NAMESPACE;
63
64
/**
65
* Saves the result of the landing pad that we have found. For ARM, this is
66
* stored in the generic unwind structure, while on other platforms it is
67
* stored in the C++ exception.
68
*/
69
static void saveLandingPad(struct _Unwind_Context *context,
70
struct _Unwind_Exception *ucb,
71
struct __cxa_exception *ex,
72
int selector,
73
dw_eh_ptr_t landingPad)
74
{
75
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
76
// On ARM, we store the saved exception in the generic part of the structure
77
ucb->barrier_cache.sp = _Unwind_GetGR(context, 13);
78
ucb->barrier_cache.bitpattern[1] = static_cast<uint32_t>(selector);
79
ucb->barrier_cache.bitpattern[3] = reinterpret_cast<uint32_t>(landingPad);
80
#endif
81
// Cache the results for the phase 2 unwind, if we found a handler
82
// and this is not a foreign exception.
83
if (ex)
84
{
85
ex->handlerSwitchValue = selector;
86
ex->catchTemp = landingPad;
87
}
88
}
89
90
/**
91
* Loads the saved landing pad. Returns 1 on success, 0 on failure.
92
*/
93
static int loadLandingPad(struct _Unwind_Context *context,
94
struct _Unwind_Exception *ucb,
95
struct __cxa_exception *ex,
96
unsigned long *selector,
97
dw_eh_ptr_t *landingPad)
98
{
99
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
100
*selector = ucb->barrier_cache.bitpattern[1];
101
*landingPad = reinterpret_cast<dw_eh_ptr_t>(ucb->barrier_cache.bitpattern[3]);
102
return 1;
103
#else
104
if (ex)
105
{
106
*selector = ex->handlerSwitchValue;
107
*landingPad = reinterpret_cast<dw_eh_ptr_t>(ex->catchTemp);
108
return 0;
109
}
110
return 0;
111
#endif
112
}
113
114
static inline _Unwind_Reason_Code continueUnwinding(struct _Unwind_Exception *ex,
115
struct _Unwind_Context *context)
116
{
117
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
118
if (__gnu_unwind_frame(ex, context) != _URC_OK) { return _URC_FAILURE; }
119
#endif
120
return _URC_CONTINUE_UNWIND;
121
}
122
123
124
extern "C" void __cxa_free_exception(void *thrown_exception) _LIBCXXRT_NOEXCEPT;
125
extern "C" void __cxa_free_dependent_exception(void *thrown_exception);
126
extern "C" void* __dynamic_cast(const void *sub,
127
const __class_type_info *src,
128
const __class_type_info *dst,
129
ptrdiff_t src2dst_offset);
130
131
/**
132
* The type of a handler that has been found.
133
*/
134
typedef enum
135
{
136
/** No handler. */
137
handler_none,
138
/**
139
* A cleanup - the exception will propagate through this frame, but code
140
* must be run when this happens.
141
*/
142
handler_cleanup,
143
/**
144
* A catch statement. The exception will not propagate past this frame
145
* (without an explicit rethrow).
146
*/
147
handler_catch
148
} handler_type;
149
150
/**
151
* Per-thread info required by the runtime. We store a single structure
152
* pointer in thread-local storage, because this tends to be a scarce resource
153
* and it's impolite to steal all of it and not leave any for the rest of the
154
* program.
155
*
156
* Instances of this structure are allocated lazily - at most one per thread -
157
* and are destroyed on thread termination.
158
*/
159
struct __cxa_thread_info
160
{
161
/** The termination handler for this thread. */
162
terminate_handler terminateHandler;
163
/** The unexpected exception handler for this thread. */
164
unexpected_handler unexpectedHandler;
165
#ifndef LIBCXXRT_NO_EMERGENCY_MALLOC
166
/**
167
* The number of emergency buffers held by this thread. This is 0 in
168
* normal operation - the emergency buffers are only used when malloc()
169
* fails to return memory for allocating an exception. Threads are not
170
* permitted to hold more than 4 emergency buffers (as per recommendation
171
* in ABI spec [3.3.1]).
172
*/
173
int emergencyBuffersHeld;
174
#endif
175
/**
176
* The exception currently running in a cleanup.
177
*/
178
_Unwind_Exception *currentCleanup;
179
/**
180
* Our state with respect to foreign exceptions. Usually none, set to
181
* caught if we have just caught an exception and rethrown if we are
182
* rethrowing it.
183
*/
184
enum
185
{
186
none,
187
caught,
188
rethrown
189
} foreign_exception_state;
190
/**
191
* The public part of this structure, accessible from outside of this
192
* module.
193
*/
194
__cxa_eh_globals globals;
195
};
196
/**
197
* Dependent exception. This
198
*/
199
struct __cxa_dependent_exception
200
{
201
#ifdef __LP64__
202
void *reserve;
203
void *primaryException;
204
#endif
205
std::type_info *exceptionType;
206
void (*exceptionDestructor) (void *);
207
unexpected_handler unexpectedHandler;
208
terminate_handler terminateHandler;
209
__cxa_exception *nextException;
210
int handlerCount;
211
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
212
_Unwind_Exception *nextCleanup;
213
int cleanupCount;
214
#endif
215
int handlerSwitchValue;
216
const char *actionRecord;
217
const char *languageSpecificData;
218
void *catchTemp;
219
void *adjustedPtr;
220
#ifndef __LP64__
221
void *primaryException;
222
#endif
223
_Unwind_Exception unwindHeader;
224
};
225
static_assert(sizeof(__cxa_exception) == sizeof(__cxa_dependent_exception),
226
"__cxa_exception and __cxa_dependent_exception should have the same size");
227
static_assert(offsetof(__cxa_exception, referenceCount) ==
228
offsetof(__cxa_dependent_exception, primaryException),
229
"referenceCount and primaryException should have the same offset");
230
static_assert(offsetof(__cxa_exception, unwindHeader) ==
231
offsetof(__cxa_dependent_exception, unwindHeader),
232
"unwindHeader fields should have the same offset");
233
static_assert(offsetof(__cxa_dependent_exception, unwindHeader) ==
234
offsetof(__cxa_dependent_exception, adjustedPtr) + 8,
235
"there should be no padding before unwindHeader");
236
237
238
namespace std
239
{
240
[[noreturn]] void unexpected();
241
class exception
242
{
243
public:
244
virtual ~exception() _LIBCXXRT_NOEXCEPT;
245
virtual const char* what() const _LIBCXXRT_NOEXCEPT;
246
};
247
248
}
249
250
/**
251
* Class of exceptions to distinguish between this and other exception types.
252
*
253
* The first four characters are the vendor ID. Currently, we use GNUC,
254
* because we aim for ABI-compatibility with the GNU implementation, and
255
* various checks may test for equality of the class, which is incorrect.
256
*/
257
static const uint64_t exception_class =
258
EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\0');
259
/**
260
* Class used for dependent exceptions.
261
*/
262
static const uint64_t dependent_exception_class =
263
EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\x01');
264
/**
265
* The low four bytes of the exception class, indicating that we conform to the
266
* Itanium C++ ABI. This is currently unused, but should be used in the future
267
* if we change our exception class, to allow this library and libsupc++ to be
268
* linked to the same executable and both to interoperate.
269
*/
270
static const uint32_t abi_exception_class =
271
GENERIC_EXCEPTION_CLASS('C', '+', '+', '\0');
272
273
static bool isCXXException(uint64_t cls)
274
{
275
return (cls == exception_class) || (cls == dependent_exception_class);
276
}
277
278
static bool isDependentException(uint64_t cls)
279
{
280
return cls == dependent_exception_class;
281
}
282
283
static __cxa_exception *exceptionFromPointer(void *ex)
284
{
285
return reinterpret_cast<__cxa_exception*>(static_cast<char*>(ex) -
286
offsetof(struct __cxa_exception, unwindHeader));
287
}
288
static __cxa_exception *realExceptionFromException(__cxa_exception *ex)
289
{
290
if (!isDependentException(ex->unwindHeader.exception_class)) { return ex; }
291
return reinterpret_cast<__cxa_exception*>((reinterpret_cast<__cxa_dependent_exception*>(ex))->primaryException)-1;
292
}
293
294
295
namespace std
296
{
297
// Forward declaration of standard library terminate() function used to
298
// abort execution.
299
[[noreturn]] void terminate(void) _LIBCXXRT_NOEXCEPT;
300
}
301
302
using namespace ABI_NAMESPACE;
303
304
#ifdef LIBCXXRT_NO_DEFAULT_TERMINATE_DIAGNOSTICS
305
/** The global termination handler. */
306
static atomic<terminate_handler> terminateHandler = abort;
307
#else
308
/**
309
* Callback function used with _Unwind_Backtrace().
310
*
311
* Prints a stack trace. Used only for debugging help.
312
*
313
* Note: As of FreeBSD 8.1, dladdr() still doesn't work properly, so this only
314
* correctly prints function names from public, relocatable, symbols.
315
*/
316
static _Unwind_Reason_Code trace(struct _Unwind_Context *context, void *c)
317
{
318
Dl_info myinfo;
319
int mylookup =
320
dladdr(reinterpret_cast<void *>(__cxa_current_exception_type), &myinfo);
321
void *ip = reinterpret_cast<void*>(_Unwind_GetIP(context));
322
Dl_info info;
323
if (dladdr(ip, &info) != 0)
324
{
325
if (mylookup == 0 || strcmp(info.dli_fname, myinfo.dli_fname) != 0)
326
{
327
printf("%p:%s() in %s\n", ip, info.dli_sname, info.dli_fname);
328
}
329
}
330
return _URC_CONTINUE_UNWIND;
331
}
332
333
static void terminate_with_diagnostics() {
334
__cxa_eh_globals *globals = __cxa_get_globals();
335
__cxa_exception *ex = globals->caughtExceptions;
336
337
if (ex != nullptr) {
338
fprintf(stderr, "Terminating due to uncaught exception %p", static_cast<void*>(ex));
339
ex = realExceptionFromException(ex);
340
static const __class_type_info *e_ti =
341
static_cast<const __class_type_info*>(&typeid(std::exception));
342
const __class_type_info *throw_ti =
343
dynamic_cast<const __class_type_info*>(ex->exceptionType);
344
if (throw_ti)
345
{
346
std::exception *e =
347
static_cast<std::exception*>(e_ti->cast_to(static_cast<void*>(ex+1), throw_ti));
348
if (e)
349
{
350
fprintf(stderr, " '%s'", e->what());
351
}
352
}
353
354
size_t bufferSize = 128;
355
char *demangled = static_cast<char*>(malloc(bufferSize));
356
const char *mangled = ex->exceptionType->name();
357
int status;
358
demangled = __cxa_demangle(mangled, demangled, &bufferSize, &status);
359
fprintf(stderr, " of type %s\n",
360
status == 0 ? demangled : mangled);
361
if (status == 0) { free(demangled); }
362
363
_Unwind_Backtrace(trace, 0);
364
}
365
366
abort();
367
}
368
369
/** The global termination handler. */
370
static atomic<terminate_handler> terminateHandler = terminate_with_diagnostics;
371
#endif
372
373
/** The global unexpected exception handler. */
374
static atomic<unexpected_handler> unexpectedHandler = std::terminate;
375
376
/** Key used for thread-local data. */
377
static pthread_key_t eh_key;
378
379
380
/**
381
* Cleanup function, allowing foreign exception handlers to correctly destroy
382
* this exception if they catch it.
383
*/
384
static void exception_cleanup(_Unwind_Reason_Code reason,
385
struct _Unwind_Exception *ex)
386
{
387
// Exception layout:
388
// [__cxa_exception [_Unwind_Exception]] [exception object]
389
//
390
// __cxa_free_exception expects a pointer to the exception object
391
__cxa_free_exception(static_cast<void*>(ex + 1));
392
}
393
static void dependent_exception_cleanup(_Unwind_Reason_Code reason,
394
struct _Unwind_Exception *ex)
395
{
396
397
__cxa_free_dependent_exception(static_cast<void*>(ex + 1));
398
}
399
400
/**
401
* Recursively walk a list of exceptions and delete them all in post-order.
402
*/
403
static void free_exception_list(__cxa_exception *ex)
404
{
405
if (0 != ex->nextException)
406
{
407
free_exception_list(ex->nextException);
408
}
409
// __cxa_free_exception() expects to be passed the thrown object, which
410
// immediately follows the exception, not the exception itself
411
__cxa_free_exception(ex+1);
412
}
413
414
/**
415
* Cleanup function called when a thread exists to make certain that all of the
416
* per-thread data is deleted.
417
*/
418
static void thread_cleanup(void* thread_info)
419
{
420
__cxa_thread_info *info = static_cast<__cxa_thread_info*>(thread_info);
421
if (info->globals.caughtExceptions)
422
{
423
// If this is a foreign exception, ask it to clean itself up.
424
if (info->foreign_exception_state != __cxa_thread_info::none)
425
{
426
_Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(info->globals.caughtExceptions);
427
if (e->exception_cleanup)
428
e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e);
429
}
430
else
431
{
432
free_exception_list(info->globals.caughtExceptions);
433
}
434
}
435
free(thread_info);
436
}
437
438
439
/**
440
* Once control used to protect the key creation.
441
*/
442
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
443
444
/**
445
* We may not be linked against a full pthread implementation. If we're not,
446
* then we need to fake the thread-local storage by storing 'thread-local'
447
* things in a global.
448
*/
449
static bool fakeTLS;
450
/**
451
* Thread-local storage for a single-threaded program.
452
*/
453
static __cxa_thread_info singleThreadInfo;
454
/**
455
* Initialise eh_key.
456
*/
457
static void init_key(void)
458
{
459
if ((0 == pthread_key_create) ||
460
(0 == pthread_setspecific) ||
461
(0 == pthread_getspecific))
462
{
463
fakeTLS = true;
464
return;
465
}
466
pthread_key_create(&eh_key, thread_cleanup);
467
pthread_setspecific(eh_key, reinterpret_cast<void *>(0x42));
468
fakeTLS = (pthread_getspecific(eh_key) != reinterpret_cast<void *>(0x42));
469
pthread_setspecific(eh_key, 0);
470
}
471
472
/**
473
* Returns the thread info structure, creating it if it is not already created.
474
*/
475
static __cxa_thread_info *thread_info()
476
{
477
if ((0 == pthread_once) || pthread_once(&once_control, init_key))
478
{
479
fakeTLS = true;
480
}
481
if (fakeTLS) { return &singleThreadInfo; }
482
__cxa_thread_info *info = static_cast<__cxa_thread_info*>(pthread_getspecific(eh_key));
483
if (0 == info)
484
{
485
info = static_cast<__cxa_thread_info*>(calloc(1, sizeof(__cxa_thread_info)));
486
pthread_setspecific(eh_key, info);
487
}
488
return info;
489
}
490
/**
491
* Fast version of thread_info(). May fail if thread_info() is not called on
492
* this thread at least once already.
493
*/
494
static __cxa_thread_info *thread_info_fast()
495
{
496
if (fakeTLS) { return &singleThreadInfo; }
497
return static_cast<__cxa_thread_info*>(pthread_getspecific(eh_key));
498
}
499
/**
500
* ABI function returning the __cxa_eh_globals structure.
501
*/
502
extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals(void)
503
{
504
return &(thread_info()->globals);
505
}
506
/**
507
* Version of __cxa_get_globals() assuming that __cxa_get_globals() has already
508
* been called at least once by this thread.
509
*/
510
extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals_fast(void)
511
{
512
return &(thread_info_fast()->globals);
513
}
514
515
#ifdef LIBCXXRT_NO_EMERGENCY_MALLOC
516
static char *alloc_or_die(size_t size)
517
{
518
char *buffer = static_cast<char*>(calloc(1, size));
519
520
if (buffer == nullptr)
521
{
522
fputs("Out of memory attempting to allocate exception\n", stderr);
523
std::terminate();
524
}
525
return buffer;
526
}
527
static void free_exception(char *e)
528
{
529
free(e);
530
}
531
#else
532
/**
533
* An emergency allocation reserved for when malloc fails. This is treated as
534
* 16 buffers of 1KB each.
535
*/
536
static char emergency_buffer[16384];
537
/**
538
* Flag indicating whether each buffer is allocated.
539
*/
540
static bool buffer_allocated[16];
541
/**
542
* Lock used to protect emergency allocation.
543
*/
544
static pthread_mutex_t emergency_malloc_lock = PTHREAD_MUTEX_INITIALIZER;
545
/**
546
* Condition variable used to wait when two threads are both trying to use the
547
* emergency malloc() buffer at once.
548
*/
549
static pthread_cond_t emergency_malloc_wait = PTHREAD_COND_INITIALIZER;
550
551
/**
552
* Allocates size bytes from the emergency allocation mechanism, if possible.
553
* This function will fail if size is over 1KB or if this thread already has 4
554
* emergency buffers. If all emergency buffers are allocated, it will sleep
555
* until one becomes available.
556
*/
557
static char *emergency_malloc(size_t size)
558
{
559
if (size > 1024) { return 0; }
560
561
__cxa_thread_info *info = thread_info();
562
// Only 4 emergency buffers allowed per thread!
563
if (info->emergencyBuffersHeld > 3) { return 0; }
564
565
pthread_mutex_lock(&emergency_malloc_lock);
566
int buffer = -1;
567
while (buffer < 0)
568
{
569
// While we were sleeping on the lock, another thread might have free'd
570
// enough memory for us to use, so try the allocation again - no point
571
// using the emergency buffer if there is some real memory that we can
572
// use...
573
void *m = calloc(1, size);
574
if (0 != m)
575
{
576
pthread_mutex_unlock(&emergency_malloc_lock);
577
return static_cast<char*>(m);
578
}
579
for (int i=0 ; i<16 ; i++)
580
{
581
if (!buffer_allocated[i])
582
{
583
buffer = i;
584
buffer_allocated[i] = true;
585
break;
586
}
587
}
588
// If there still isn't a buffer available, then sleep on the condition
589
// variable. This will be signalled when another thread releases one
590
// of the emergency buffers.
591
if (buffer < 0)
592
{
593
pthread_cond_wait(&emergency_malloc_wait, &emergency_malloc_lock);
594
}
595
}
596
pthread_mutex_unlock(&emergency_malloc_lock);
597
info->emergencyBuffersHeld++;
598
return emergency_buffer + (1024 * buffer);
599
}
600
601
/**
602
* Frees a buffer returned by emergency_malloc().
603
*
604
* Note: Neither this nor emergency_malloc() is particularly efficient. This
605
* should not matter, because neither will be called in normal operation - they
606
* are only used when the program runs out of memory, which should not happen
607
* often.
608
*/
609
static void emergency_malloc_free(char *ptr)
610
{
611
int buffer = -1;
612
// Find the buffer corresponding to this pointer.
613
for (int i=0 ; i<16 ; i++)
614
{
615
if (ptr == static_cast<void*>(emergency_buffer + (1024 * i)))
616
{
617
buffer = i;
618
break;
619
}
620
}
621
assert(buffer >= 0 &&
622
"Trying to free something that is not an emergency buffer!");
623
// emergency_malloc() is expected to return 0-initialized data. We don't
624
// zero the buffer when allocating it, because the static buffers will
625
// begin life containing 0 values.
626
memset(ptr, 0, 1024);
627
// Signal the condition variable to wake up any threads that are blocking
628
// waiting for some space in the emergency buffer
629
pthread_mutex_lock(&emergency_malloc_lock);
630
// In theory, we don't need to do this with the lock held. In practice,
631
// our array of bools will probably be updated using 32-bit or 64-bit
632
// memory operations, so this update may clobber adjacent values.
633
buffer_allocated[buffer] = false;
634
pthread_cond_signal(&emergency_malloc_wait);
635
pthread_mutex_unlock(&emergency_malloc_lock);
636
}
637
638
static char *alloc_or_die(size_t size)
639
{
640
char *buffer = static_cast<char*>(calloc(1, size));
641
642
// If calloc() doesn't want to give us any memory, try using an emergency
643
// buffer.
644
if (0 == buffer)
645
{
646
buffer = emergency_malloc(size);
647
// This is only reached if the allocation is greater than 1KB, and
648
// anyone throwing objects that big really should know better.
649
if (0 == buffer)
650
{
651
fprintf(stderr, "Out of memory attempting to allocate exception\n");
652
std::terminate();
653
}
654
}
655
return buffer;
656
}
657
static void free_exception(char *e)
658
{
659
// If this allocation is within the address range of the emergency buffer,
660
// don't call free() because it was not allocated with malloc()
661
if ((e >= emergency_buffer) &&
662
(e < (emergency_buffer + sizeof(emergency_buffer))))
663
{
664
emergency_malloc_free(e);
665
}
666
else
667
{
668
free(e);
669
}
670
}
671
#endif
672
673
/**
674
* Allocates an exception structure. Returns a pointer to the space that can
675
* be used to store an object of thrown_size bytes. This function will use an
676
* emergency buffer if malloc() fails, and may block if there are no such
677
* buffers available.
678
*/
679
extern "C" void *__cxa_allocate_exception(size_t thrown_size) _LIBCXXRT_NOEXCEPT
680
{
681
size_t size = thrown_size + sizeof(__cxa_exception);
682
char *buffer = alloc_or_die(size);
683
return buffer+sizeof(__cxa_exception);
684
}
685
686
extern "C" void *__cxa_allocate_dependent_exception(void)
687
{
688
size_t size = sizeof(__cxa_dependent_exception);
689
char *buffer = alloc_or_die(size);
690
return buffer+sizeof(__cxa_dependent_exception);
691
}
692
693
/**
694
* __cxa_free_exception() is called when an exception was thrown in between
695
* calling __cxa_allocate_exception() and actually throwing the exception.
696
* This happens when the object's copy constructor throws an exception.
697
*
698
* In this implementation, it is also called by __cxa_end_catch() and during
699
* thread cleanup.
700
*/
701
extern "C" void __cxa_free_exception(void *thrown_exception) _LIBCXXRT_NOEXCEPT
702
{
703
__cxa_exception *ex = reinterpret_cast<__cxa_exception*>(thrown_exception) - 1;
704
// Free the object that was thrown, calling its destructor
705
if (0 != ex->exceptionDestructor)
706
{
707
try
708
{
709
ex->exceptionDestructor(thrown_exception);
710
}
711
catch(...)
712
{
713
// FIXME: Check that this is really what the spec says to do.
714
std::terminate();
715
}
716
}
717
718
free_exception(reinterpret_cast<char*>(ex));
719
}
720
721
static void releaseException(__cxa_exception *exception)
722
{
723
if (isDependentException(exception->unwindHeader.exception_class))
724
{
725
__cxa_free_dependent_exception(exception+1);
726
return;
727
}
728
if (__sync_sub_and_fetch(&exception->referenceCount, 1) == 0)
729
{
730
// __cxa_free_exception() expects to be passed the thrown object,
731
// which immediately follows the exception, not the exception
732
// itself
733
__cxa_free_exception(exception+1);
734
}
735
}
736
737
void __cxa_free_dependent_exception(void *thrown_exception)
738
{
739
__cxa_dependent_exception *ex = reinterpret_cast<__cxa_dependent_exception*>(thrown_exception) - 1;
740
assert(isDependentException(ex->unwindHeader.exception_class));
741
if (ex->primaryException)
742
{
743
releaseException(realExceptionFromException(reinterpret_cast<__cxa_exception*>(ex)));
744
}
745
free_exception(reinterpret_cast<char*>(ex));
746
}
747
748
/**
749
* Report a failure that occurred when attempting to throw an exception.
750
*
751
* If the failure happened by falling off the end of the stack without finding
752
* a handler, catch the exception before calling terminate. The default
753
* terminate handler will print a backtrace before aborting.
754
*/
755
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
756
extern "C" void *__cxa_begin_catch(void *e) _LIBCXXRT_NOEXCEPT;
757
#else
758
extern "C" void *__cxa_begin_catch(void *e);
759
#endif
760
static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exception)
761
{
762
switch (err)
763
{
764
default: break;
765
case _URC_FATAL_PHASE1_ERROR:
766
fprintf(stderr, "Fatal error during phase 1 unwinding\n");
767
break;
768
#if !defined(__arm__) || defined(__ARM_DWARF_EH__)
769
case _URC_FATAL_PHASE2_ERROR:
770
fprintf(stderr, "Fatal error during phase 2 unwinding\n");
771
break;
772
#endif
773
case _URC_END_OF_STACK:
774
__cxa_begin_catch (&(thrown_exception->unwindHeader));
775
break;
776
}
777
std::terminate();
778
}
779
780
static void throw_exception(__cxa_exception *ex)
781
{
782
__cxa_thread_info *info = thread_info();
783
ex->unexpectedHandler = info->unexpectedHandler;
784
if (0 == ex->unexpectedHandler)
785
{
786
ex->unexpectedHandler = unexpectedHandler.load();
787
}
788
ex->terminateHandler = info->terminateHandler;
789
if (0 == ex->terminateHandler)
790
{
791
ex->terminateHandler = terminateHandler.load();
792
}
793
info->globals.uncaughtExceptions++;
794
795
_Unwind_Reason_Code err = _Unwind_RaiseException(&ex->unwindHeader);
796
// The _Unwind_RaiseException() function should not return, it should
797
// unwind the stack past this function. If it does return, then something
798
// has gone wrong.
799
report_failure(err, ex);
800
}
801
802
extern "C" __cxa_exception *__cxa_init_primary_exception(
803
void *object, std::type_info* tinfo, void (*dest)(void *)) _LIBCXXRT_NOEXCEPT {
804
__cxa_exception *ex = reinterpret_cast<__cxa_exception*>(object) - 1;
805
806
ex->referenceCount = 0;
807
ex->exceptionType = tinfo;
808
809
ex->exceptionDestructor = dest;
810
811
ex->unwindHeader.exception_class = exception_class;
812
ex->unwindHeader.exception_cleanup = exception_cleanup;
813
814
return ex;
815
}
816
817
818
/**
819
* ABI function for throwing an exception. Takes the object to be thrown (the
820
* pointer returned by __cxa_allocate_exception()), the type info for the
821
* pointee, and the destructor (if there is one) as arguments.
822
*/
823
extern "C" void __cxa_throw(void *thrown_exception,
824
std::type_info *tinfo,
825
void(*dest)(void*))
826
{
827
__cxa_exception *ex = __cxa_init_primary_exception(thrown_exception, tinfo, dest);
828
ex->referenceCount = 1;
829
830
throw_exception(ex);
831
}
832
833
extern "C" void __cxa_rethrow_primary_exception(void* thrown_exception)
834
{
835
if (NULL == thrown_exception) { return; }
836
837
__cxa_exception *original = exceptionFromPointer(thrown_exception);
838
__cxa_dependent_exception *ex = reinterpret_cast<__cxa_dependent_exception*>(__cxa_allocate_dependent_exception())-1;
839
840
ex->primaryException = thrown_exception;
841
__cxa_increment_exception_refcount(thrown_exception);
842
843
ex->exceptionType = original->exceptionType;
844
ex->unwindHeader.exception_class = dependent_exception_class;
845
ex->unwindHeader.exception_cleanup = dependent_exception_cleanup;
846
847
throw_exception(reinterpret_cast<__cxa_exception*>(ex));
848
}
849
850
extern "C" void *__cxa_current_primary_exception(void)
851
{
852
__cxa_eh_globals* globals = __cxa_get_globals();
853
__cxa_exception *ex = globals->caughtExceptions;
854
855
if (0 == ex) { return NULL; }
856
ex = realExceptionFromException(ex);
857
__sync_fetch_and_add(&ex->referenceCount, 1);
858
return ex + 1;
859
}
860
861
extern "C" void __cxa_increment_exception_refcount(void* thrown_exception)
862
{
863
if (NULL == thrown_exception) { return; }
864
__cxa_exception *ex = static_cast<__cxa_exception*>(thrown_exception) - 1;
865
if (isDependentException(ex->unwindHeader.exception_class)) { return; }
866
__sync_fetch_and_add(&ex->referenceCount, 1);
867
}
868
extern "C" void __cxa_decrement_exception_refcount(void* thrown_exception)
869
{
870
if (NULL == thrown_exception) { return; }
871
__cxa_exception *ex = static_cast<__cxa_exception*>(thrown_exception) - 1;
872
releaseException(ex);
873
}
874
875
/**
876
* ABI function. Rethrows the current exception. Does not remove the
877
* exception from the stack or decrement its handler count - the compiler is
878
* expected to set the landing pad for this function to the end of the catch
879
* block, and then call _Unwind_Resume() to continue unwinding once
880
* __cxa_end_catch() has been called and any cleanup code has been run.
881
*/
882
extern "C" void __cxa_rethrow()
883
{
884
__cxa_thread_info *ti = thread_info();
885
__cxa_eh_globals *globals = &ti->globals;
886
// Note: We don't remove this from the caught list here, because
887
// __cxa_end_catch will be called when we unwind out of the try block. We
888
// could probably make this faster by providing an alternative rethrow
889
// function and ensuring that all cleanup code is run before calling it, so
890
// we can skip the top stack frame when unwinding.
891
__cxa_exception *ex = globals->caughtExceptions;
892
893
if (0 == ex)
894
{
895
fprintf(stderr,
896
"Attempting to rethrow an exception that doesn't exist!\n");
897
std::terminate();
898
}
899
900
if (ti->foreign_exception_state != __cxa_thread_info::none)
901
{
902
ti->foreign_exception_state = __cxa_thread_info::rethrown;
903
_Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(ex);
904
_Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(e);
905
report_failure(err, ex);
906
return;
907
}
908
909
assert(ex->handlerCount > 0 && "Rethrowing uncaught exception!");
910
911
// `globals->uncaughtExceptions` was decremented by `__cxa_begin_catch`.
912
// It's normally incremented by `throw_exception`, but this path invokes
913
// `_Unwind_Resume_or_Rethrow` directly to rethrow the exception.
914
// This path is only reachable if we're rethrowing a C++ exception -
915
// foreign exceptions don't adjust any of this state.
916
globals->uncaughtExceptions++;
917
918
// ex->handlerCount will be decremented in __cxa_end_catch in enclosing
919
// catch block
920
921
// Make handler count negative. This will tell __cxa_end_catch that
922
// exception was rethrown and exception object should not be destroyed
923
// when handler count become zero
924
ex->handlerCount = -ex->handlerCount;
925
926
// Continue unwinding the stack with this exception. This should unwind to
927
// the place in the caller where __cxa_end_catch() is called. The caller
928
// will then run cleanup code and bounce the exception back with
929
// _Unwind_Resume().
930
_Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(&ex->unwindHeader);
931
report_failure(err, ex);
932
}
933
934
/**
935
* Returns the type_info object corresponding to the filter.
936
*/
937
static std::type_info *get_type_info_entry(_Unwind_Context *context,
938
dwarf_eh_lsda *lsda,
939
int filter)
940
{
941
// Get the address of the record in the table.
942
dw_eh_ptr_t record = lsda->type_table -
943
dwarf_size_of_fixed_size_field(lsda->type_table_encoding)*filter;
944
//record -= 4;
945
dw_eh_ptr_t start = record;
946
// Read the value, but it's probably an indirect reference...
947
int64_t offset = read_value(lsda->type_table_encoding, &record);
948
949
// (If the entry is 0, don't try to dereference it. That would be bad.)
950
if (offset == 0) { return 0; }
951
952
// ...so we need to resolve it
953
return reinterpret_cast<std::type_info*>(resolve_indirect_value(context,
954
lsda->type_table_encoding, offset, start));
955
}
956
957
958
959
/**
960
* Checks the type signature found in a handler against the type of the thrown
961
* object. If ex is 0 then it is assumed to be a foreign exception and only
962
* matches cleanups.
963
*/
964
static bool check_type_signature(__cxa_exception *ex,
965
const std::type_info *type,
966
void *&adjustedPtr)
967
{
968
void *exception_ptr = static_cast<void*>(ex+1);
969
const std::type_info *ex_type = ex ? ex->exceptionType : 0;
970
971
bool is_ptr = ex ? ex_type->__is_pointer_p() : false;
972
if (is_ptr)
973
{
974
exception_ptr = *static_cast<void**>(exception_ptr);
975
}
976
// Always match a catchall, even with a foreign exception
977
//
978
// Note: A 0 here is a catchall, not a cleanup, so we return true to
979
// indicate that we found a catch.
980
if (0 == type)
981
{
982
if (ex)
983
{
984
adjustedPtr = exception_ptr;
985
}
986
return true;
987
}
988
989
if (0 == ex) { return false; }
990
991
// If the types are the same, no casting is needed.
992
if (*type == *ex_type)
993
{
994
adjustedPtr = exception_ptr;
995
return true;
996
}
997
998
999
if (type->__do_catch(ex_type, &exception_ptr, 1))
1000
{
1001
adjustedPtr = exception_ptr;
1002
return true;
1003
}
1004
1005
return false;
1006
}
1007
/**
1008
* Checks whether the exception matches the type specifiers in this action
1009
* record. If the exception only matches cleanups, then this returns false.
1010
* If it matches a catch (including a catchall) then it returns true.
1011
*
1012
* The selector argument is used to return the selector that is passed in the
1013
* second exception register when installing the context.
1014
*/
1015
static handler_type check_action_record(_Unwind_Context *context,
1016
dwarf_eh_lsda *lsda,
1017
dw_eh_ptr_t action_record,
1018
__cxa_exception *ex,
1019
unsigned long *selector,
1020
void *&adjustedPtr)
1021
{
1022
if (!action_record) { return handler_cleanup; }
1023
handler_type found = handler_none;
1024
while (action_record)
1025
{
1026
int filter = read_sleb128(&action_record);
1027
dw_eh_ptr_t action_record_offset_base = action_record;
1028
int displacement = read_sleb128(&action_record);
1029
action_record = displacement ?
1030
action_record_offset_base + displacement : 0;
1031
// We only check handler types for C++ exceptions - foreign exceptions
1032
// are only allowed for cleanups and catchalls.
1033
if (filter > 0)
1034
{
1035
std::type_info *handler_type = get_type_info_entry(context, lsda, filter);
1036
if (check_type_signature(ex, handler_type, adjustedPtr))
1037
{
1038
*selector = filter;
1039
return handler_catch;
1040
}
1041
}
1042
else if (filter < 0 && 0 != ex)
1043
{
1044
bool matched = false;
1045
*selector = filter;
1046
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
1047
filter++;
1048
std::type_info *handler_type = get_type_info_entry(context, lsda, filter--);
1049
while (handler_type)
1050
{
1051
if (check_type_signature(ex, handler_type, adjustedPtr))
1052
{
1053
matched = true;
1054
break;
1055
}
1056
handler_type = get_type_info_entry(context, lsda, filter--);
1057
}
1058
#else
1059
unsigned char *type_index = reinterpret_cast<unsigned char*>(lsda->type_table) - filter - 1;
1060
while (*type_index)
1061
{
1062
std::type_info *handler_type = get_type_info_entry(context, lsda, *(type_index++));
1063
// If the exception spec matches a permitted throw type for
1064
// this function, don't report a handler - we are allowed to
1065
// propagate this exception out.
1066
if (check_type_signature(ex, handler_type, adjustedPtr))
1067
{
1068
matched = true;
1069
break;
1070
}
1071
}
1072
#endif
1073
if (matched) { continue; }
1074
// If we don't find an allowed exception spec, we need to install
1075
// the context for this action. The landing pad will then call the
1076
// unexpected exception function. Treat this as a catch
1077
return handler_catch;
1078
}
1079
else if (filter == 0)
1080
{
1081
*selector = filter;
1082
found = handler_cleanup;
1083
}
1084
}
1085
return found;
1086
}
1087
1088
static void pushCleanupException(_Unwind_Exception *exceptionObject,
1089
__cxa_exception *ex)
1090
{
1091
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
1092
__cxa_thread_info *info = thread_info_fast();
1093
if (ex)
1094
{
1095
ex->cleanupCount++;
1096
if (ex->cleanupCount > 1)
1097
{
1098
assert(exceptionObject == info->currentCleanup);
1099
return;
1100
}
1101
ex->nextCleanup = info->currentCleanup;
1102
}
1103
info->currentCleanup = exceptionObject;
1104
#endif
1105
}
1106
1107
/**
1108
* The exception personality function. This is referenced in the unwinding
1109
* DWARF metadata and is called by the unwind library for each C++ stack frame
1110
* containing catch or cleanup code.
1111
*/
1112
extern "C"
1113
BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0)
1114
// This personality function is for version 1 of the ABI. If you use it
1115
// with a future version of the ABI, it won't know what to do, so it
1116
// reports a fatal error and give up before it breaks anything.
1117
if (1 != version)
1118
{
1119
return _URC_FATAL_PHASE1_ERROR;
1120
}
1121
__cxa_exception *ex = 0;
1122
__cxa_exception *realEx = 0;
1123
1124
// If this exception is throw by something else then we can't make any
1125
// assumptions about its layout beyond the fields declared in
1126
// _Unwind_Exception.
1127
bool foreignException = !isCXXException(exceptionClass);
1128
1129
// If this isn't a foreign exception, then we have a C++ exception structure
1130
if (!foreignException)
1131
{
1132
ex = exceptionFromPointer(exceptionObject);
1133
realEx = realExceptionFromException(ex);
1134
}
1135
1136
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
1137
unsigned char *lsda_addr =
1138
static_cast<unsigned char*>(_Unwind_GetLanguageSpecificData(context));
1139
#else
1140
unsigned char *lsda_addr =
1141
reinterpret_cast<unsigned char*>(static_cast<uintptr_t>(_Unwind_GetLanguageSpecificData(context)));
1142
#endif
1143
1144
// No LSDA implies no landing pads - try the next frame
1145
if (0 == lsda_addr) { return continueUnwinding(exceptionObject, context); }
1146
1147
// These two variables define how the exception will be handled.
1148
dwarf_eh_action action = {0};
1149
unsigned long selector = 0;
1150
1151
// During the search phase, we do a complete lookup. If we return
1152
// _URC_HANDLER_FOUND, then the phase 2 unwind will call this function with
1153
// a _UA_HANDLER_FRAME action, telling us to install the handler frame. If
1154
// we return _URC_CONTINUE_UNWIND, we may be called again later with a
1155
// _UA_CLEANUP_PHASE action for this frame.
1156
//
1157
// The point of the two-stage unwind allows us to entirely avoid any stack
1158
// unwinding if there is no handler. If there are just cleanups found,
1159
// then we can just panic call an abort function.
1160
//
1161
// Matching a handler is much more expensive than matching a cleanup,
1162
// because we don't need to bother doing type comparisons (or looking at
1163
// the type table at all) for a cleanup. This means that there is no need
1164
// to cache the result of finding a cleanup, because it's (quite) quick to
1165
// look it up again from the action table.
1166
if (actions & _UA_SEARCH_PHASE)
1167
{
1168
struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);
1169
1170
if (!dwarf_eh_find_callsite(context, &lsda, &action))
1171
{
1172
// EH range not found. This happens if exception is thrown and not
1173
// caught inside a cleanup (destructor). We should call
1174
// terminate() in this case. The catchTemp (landing pad) field of
1175
// exception object will contain null when personality function is
1176
// called with _UA_HANDLER_FRAME action for phase 2 unwinding.
1177
return _URC_HANDLER_FOUND;
1178
}
1179
1180
handler_type found_handler = check_action_record(context, &lsda,
1181
action.action_record, realEx, &selector, ex->adjustedPtr);
1182
// If there's no action record, we've only found a cleanup, so keep
1183
// searching for something real
1184
if (found_handler == handler_catch)
1185
{
1186
// Cache the results for the phase 2 unwind, if we found a handler
1187
// and this is not a foreign exception.
1188
if (ex)
1189
{
1190
saveLandingPad(context, exceptionObject, ex, selector, action.landing_pad);
1191
ex->languageSpecificData = reinterpret_cast<const char*>(lsda_addr);
1192
ex->actionRecord = reinterpret_cast<const char*>(action.action_record);
1193
// ex->adjustedPtr is set when finding the action record.
1194
}
1195
return _URC_HANDLER_FOUND;
1196
}
1197
return continueUnwinding(exceptionObject, context);
1198
}
1199
1200
1201
// If this is a foreign exception, we didn't have anywhere to cache the
1202
// lookup stuff, so we need to do it again. If this is either a forced
1203
// unwind, a foreign exception, or a cleanup, then we just install the
1204
// context for a cleanup.
1205
if (!(actions & _UA_HANDLER_FRAME))
1206
{
1207
// cleanup
1208
struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);
1209
dwarf_eh_find_callsite(context, &lsda, &action);
1210
if (0 == action.landing_pad) { return continueUnwinding(exceptionObject, context); }
1211
handler_type found_handler = check_action_record(context, &lsda,
1212
action.action_record, realEx, &selector, ex->adjustedPtr);
1213
// Ignore handlers this time.
1214
if (found_handler != handler_cleanup) { return continueUnwinding(exceptionObject, context); }
1215
pushCleanupException(exceptionObject, ex);
1216
}
1217
else if (foreignException)
1218
{
1219
struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);
1220
dwarf_eh_find_callsite(context, &lsda, &action);
1221
check_action_record(context, &lsda, action.action_record, realEx,
1222
&selector, ex->adjustedPtr);
1223
}
1224
else if (ex->catchTemp == 0)
1225
{
1226
// Uncaught exception in cleanup, calling terminate
1227
std::terminate();
1228
}
1229
else
1230
{
1231
// Restore the saved info if we saved some last time.
1232
loadLandingPad(context, exceptionObject, ex, &selector, &action.landing_pad);
1233
ex->catchTemp = 0;
1234
ex->handlerSwitchValue = 0;
1235
}
1236
1237
1238
_Unwind_SetIP(context, reinterpret_cast<unsigned long>(action.landing_pad));
1239
_Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
1240
reinterpret_cast<unsigned long>(exceptionObject));
1241
_Unwind_SetGR(context, __builtin_eh_return_data_regno(1), selector);
1242
1243
return _URC_INSTALL_CONTEXT;
1244
}
1245
1246
/**
1247
* ABI function called when entering a catch statement. The argument is the
1248
* pointer passed out of the personality function. This is always the start of
1249
* the _Unwind_Exception object. The return value for this function is the
1250
* pointer to the caught exception, which is either the adjusted pointer (for
1251
* C++ exceptions) of the unadjusted pointer (for foreign exceptions).
1252
*/
1253
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
1254
extern "C" void *__cxa_begin_catch(void *e) _LIBCXXRT_NOEXCEPT
1255
#else
1256
extern "C" void *__cxa_begin_catch(void *e)
1257
#endif
1258
{
1259
// We can't call the fast version here, because if the first exception that
1260
// we see is a foreign exception then we won't have called it yet.
1261
__cxa_thread_info *ti = thread_info();
1262
__cxa_eh_globals *globals = &ti->globals;
1263
_Unwind_Exception *exceptionObject = static_cast<_Unwind_Exception*>(e);
1264
1265
if (isCXXException(exceptionObject->exception_class))
1266
{
1267
// Only exceptions thrown with a C++ exception throwing function will
1268
// increment this, so don't decrement it here.
1269
globals->uncaughtExceptions--;
1270
__cxa_exception *ex = exceptionFromPointer(exceptionObject);
1271
1272
if (ex->handlerCount == 0)
1273
{
1274
// Add this to the front of the list of exceptions being handled
1275
// and increment its handler count so that it won't be deleted
1276
// prematurely.
1277
ex->nextException = globals->caughtExceptions;
1278
globals->caughtExceptions = ex;
1279
}
1280
1281
if (ex->handlerCount < 0)
1282
{
1283
// Rethrown exception is catched before end of catch block.
1284
// Clear the rethrow flag (make value positive) - we are allowed
1285
// to delete this exception at the end of the catch block, as long
1286
// as it isn't thrown again later.
1287
1288
// Code pattern:
1289
//
1290
// try {
1291
// throw x;
1292
// }
1293
// catch() {
1294
// try {
1295
// throw;
1296
// }
1297
// catch() {
1298
// __cxa_begin_catch() <- we are here
1299
// }
1300
// }
1301
ex->handlerCount = -ex->handlerCount + 1;
1302
}
1303
else
1304
{
1305
ex->handlerCount++;
1306
}
1307
ti->foreign_exception_state = __cxa_thread_info::none;
1308
1309
return ex->adjustedPtr;
1310
}
1311
else
1312
{
1313
// If this is a foreign exception, then we need to be able to
1314
// store it. We can't chain foreign exceptions, so we give up
1315
// if there are already some outstanding ones.
1316
if (globals->caughtExceptions != 0)
1317
{
1318
std::terminate();
1319
}
1320
globals->caughtExceptions = reinterpret_cast<__cxa_exception*>(exceptionObject);
1321
ti->foreign_exception_state = __cxa_thread_info::caught;
1322
}
1323
// exceptionObject is the pointer to the _Unwind_Exception within the
1324
// __cxa_exception. The throw object is after this
1325
return (reinterpret_cast<char*>(exceptionObject) + sizeof(_Unwind_Exception));
1326
}
1327
1328
1329
1330
/**
1331
* ABI function called when exiting a catch block. This will free the current
1332
* exception if it is no longer referenced in other catch blocks.
1333
*/
1334
extern "C" void __cxa_end_catch()
1335
{
1336
// We can call the fast version here because the slow version is called in
1337
// __cxa_throw(), which must have been called before we end a catch block
1338
__cxa_thread_info *ti = thread_info_fast();
1339
__cxa_eh_globals *globals = &ti->globals;
1340
__cxa_exception *ex = globals->caughtExceptions;
1341
1342
assert(0 != ex && "Ending catch when no exception is on the stack!");
1343
1344
if (ti->foreign_exception_state != __cxa_thread_info::none)
1345
{
1346
if (ti->foreign_exception_state != __cxa_thread_info::rethrown)
1347
{
1348
_Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(ti->globals.caughtExceptions);
1349
if (e->exception_cleanup)
1350
e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e);
1351
}
1352
globals->caughtExceptions = 0;
1353
ti->foreign_exception_state = __cxa_thread_info::none;
1354
return;
1355
}
1356
1357
bool deleteException = true;
1358
1359
if (ex->handlerCount < 0)
1360
{
1361
// exception was rethrown. Exception should not be deleted even if
1362
// handlerCount become zero.
1363
// Code pattern:
1364
// try {
1365
// throw x;
1366
// }
1367
// catch() {
1368
// {
1369
// throw;
1370
// }
1371
// cleanup {
1372
// __cxa_end_catch(); <- we are here
1373
// }
1374
// }
1375
//
1376
1377
ex->handlerCount++;
1378
deleteException = false;
1379
}
1380
else
1381
{
1382
ex->handlerCount--;
1383
}
1384
1385
if (ex->handlerCount == 0)
1386
{
1387
globals->caughtExceptions = ex->nextException;
1388
if (deleteException)
1389
{
1390
releaseException(ex);
1391
}
1392
}
1393
}
1394
1395
/**
1396
* ABI function. Returns the type of the current exception.
1397
*/
1398
extern "C" std::type_info *__cxa_current_exception_type()
1399
{
1400
__cxa_eh_globals *globals = __cxa_get_globals();
1401
__cxa_exception *ex = globals->caughtExceptions;
1402
return ex ? ex->exceptionType : 0;
1403
}
1404
1405
/**
1406
* Cleanup, ensures that `__cxa_end_catch` is called to balance an explicit
1407
* `__cxa_begin_catch` call.
1408
*/
1409
static void end_catch(char *)
1410
{
1411
__cxa_end_catch();
1412
}
1413
/**
1414
* ABI function, called when an exception specification is violated.
1415
*
1416
* This function does not return.
1417
*/
1418
extern "C" void __cxa_call_unexpected(void*exception)
1419
{
1420
_Unwind_Exception *exceptionObject = static_cast<_Unwind_Exception*>(exception);
1421
// Wrap the call to the unexpected handler in calls to `__cxa_begin_catch`
1422
// and `__cxa_end_catch` so that we correctly update exception counts if
1423
// the unexpected handler throws an exception.
1424
__cxa_begin_catch(exceptionObject);
1425
__attribute__((cleanup(end_catch)))
1426
char unused;
1427
if (exceptionObject->exception_class == exception_class)
1428
{
1429
__cxa_exception *ex = exceptionFromPointer(exceptionObject);
1430
if (ex->unexpectedHandler)
1431
{
1432
ex->unexpectedHandler();
1433
// Should not be reached.
1434
abort();
1435
}
1436
}
1437
std::unexpected();
1438
// Should not be reached.
1439
abort();
1440
}
1441
1442
/**
1443
* ABI function, called when an object destructor exits due to an
1444
* exception during stack unwinding.
1445
*
1446
* This function does not return.
1447
*/
1448
extern "C" void __cxa_call_terminate(void*exception) _LIBCXXRT_NOEXCEPT
1449
{
1450
std::terminate();
1451
// Should not be reached.
1452
abort();
1453
}
1454
1455
/**
1456
* ABI function, returns the adjusted pointer to the exception object.
1457
*/
1458
extern "C" void *__cxa_get_exception_ptr(void *exceptionObject)
1459
{
1460
return exceptionFromPointer(exceptionObject)->adjustedPtr;
1461
}
1462
1463
/**
1464
* As an extension, we provide the ability for the unexpected and terminate
1465
* handlers to be thread-local. We default to the standards-compliant
1466
* behaviour where they are global.
1467
*/
1468
static bool thread_local_handlers = false;
1469
1470
1471
namespace pathscale
1472
{
1473
/**
1474
* Sets whether unexpected and terminate handlers should be thread-local.
1475
*/
1476
void set_use_thread_local_handlers(bool flag) _LIBCXXRT_NOEXCEPT
1477
{
1478
thread_local_handlers = flag;
1479
}
1480
/**
1481
* Sets a thread-local unexpected handler.
1482
*/
1483
unexpected_handler set_unexpected(unexpected_handler f) _LIBCXXRT_NOEXCEPT
1484
{
1485
static __cxa_thread_info *info = thread_info();
1486
unexpected_handler old = info->unexpectedHandler;
1487
info->unexpectedHandler = f;
1488
return old;
1489
}
1490
/**
1491
* Sets a thread-local terminate handler.
1492
*/
1493
terminate_handler set_terminate(terminate_handler f) _LIBCXXRT_NOEXCEPT
1494
{
1495
static __cxa_thread_info *info = thread_info();
1496
terminate_handler old = info->terminateHandler;
1497
info->terminateHandler = f;
1498
return old;
1499
}
1500
}
1501
1502
namespace std
1503
{
1504
/**
1505
* Sets the function that will be called when an exception specification is
1506
* violated.
1507
*/
1508
unexpected_handler set_unexpected(unexpected_handler f) _LIBCXXRT_NOEXCEPT
1509
{
1510
if (thread_local_handlers) { return pathscale::set_unexpected(f); }
1511
1512
return unexpectedHandler.exchange(f);
1513
}
1514
/**
1515
* Sets the function that is called to terminate the program.
1516
*/
1517
terminate_handler set_terminate(terminate_handler f) _LIBCXXRT_NOEXCEPT
1518
{
1519
if (thread_local_handlers) { return pathscale::set_terminate(f); }
1520
1521
return terminateHandler.exchange(f);
1522
}
1523
/**
1524
* Terminates the program, calling a custom terminate implementation if
1525
* required.
1526
*/
1527
[[noreturn]] void terminate() _LIBCXXRT_NOEXCEPT
1528
{
1529
static __cxa_thread_info *info = thread_info();
1530
if (0 != info && 0 != info->terminateHandler)
1531
{
1532
info->terminateHandler();
1533
}
1534
else
1535
{
1536
terminateHandler.load()();
1537
}
1538
// Should not be reached - a terminate handler is not expected
1539
// to return.
1540
abort();
1541
}
1542
/**
1543
* Called when an unexpected exception is encountered (i.e. an exception
1544
* violates an exception specification). This calls abort() unless a
1545
* custom handler has been set..
1546
*/
1547
[[noreturn]] void unexpected()
1548
{
1549
static __cxa_thread_info *info = thread_info();
1550
if (0 != info && 0 != info->unexpectedHandler)
1551
{
1552
info->unexpectedHandler();
1553
}
1554
else
1555
{
1556
unexpectedHandler.load()();
1557
}
1558
// Should not be reached - a unexpected handler is not expected
1559
// to return.
1560
abort();
1561
}
1562
/**
1563
* Returns whether there are any exceptions currently being thrown that
1564
* have not been caught. This can occur inside a nested catch statement.
1565
*/
1566
bool uncaught_exception() _LIBCXXRT_NOEXCEPT
1567
{
1568
__cxa_thread_info *info = thread_info();
1569
return info->globals.uncaughtExceptions != 0;
1570
}
1571
/**
1572
* Returns the number of exceptions currently being thrown that have not
1573
* been caught. This can occur inside a nested catch statement.
1574
*/
1575
int uncaught_exceptions() _LIBCXXRT_NOEXCEPT
1576
{
1577
__cxa_thread_info *info = thread_info();
1578
return info->globals.uncaughtExceptions;
1579
}
1580
/**
1581
* Returns the current unexpected handler.
1582
*/
1583
unexpected_handler get_unexpected() _LIBCXXRT_NOEXCEPT
1584
{
1585
__cxa_thread_info *info = thread_info();
1586
if (info->unexpectedHandler)
1587
{
1588
return info->unexpectedHandler;
1589
}
1590
return unexpectedHandler.load();
1591
}
1592
/**
1593
* Returns the current terminate handler.
1594
*/
1595
terminate_handler get_terminate() _LIBCXXRT_NOEXCEPT
1596
{
1597
__cxa_thread_info *info = thread_info();
1598
if (info->terminateHandler)
1599
{
1600
return info->terminateHandler;
1601
}
1602
return terminateHandler.load();
1603
}
1604
}
1605
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
1606
extern "C" _Unwind_Exception *__cxa_get_cleanup(void)
1607
{
1608
__cxa_thread_info *info = thread_info_fast();
1609
_Unwind_Exception *exceptionObject = info->currentCleanup;
1610
if (isCXXException(exceptionObject->exception_class))
1611
{
1612
__cxa_exception *ex = exceptionFromPointer(exceptionObject);
1613
ex->cleanupCount--;
1614
if (ex->cleanupCount == 0)
1615
{
1616
info->currentCleanup = ex->nextCleanup;
1617
ex->nextCleanup = 0;
1618
}
1619
}
1620
else
1621
{
1622
info->currentCleanup = 0;
1623
}
1624
return exceptionObject;
1625
}
1626
1627
asm (
1628
".pushsection .text.__cxa_end_cleanup \n"
1629
".global __cxa_end_cleanup \n"
1630
".type __cxa_end_cleanup, \"function\" \n"
1631
"__cxa_end_cleanup: \n"
1632
" push {r1, r2, r3, r4} \n"
1633
" mov r4, lr \n"
1634
" bl __cxa_get_cleanup \n"
1635
" mov lr, r4 \n"
1636
" pop {r1, r2, r3, r4} \n"
1637
" b _Unwind_Resume \n"
1638
" bl abort \n"
1639
".popsection \n"
1640
);
1641
#endif
1642
1643