summaryrefslogtreecommitdiffstats
path: root/contrib/libs/cxxsupp/libcxxrt/exception.cc
diff options
context:
space:
mode:
authorAlexander Smirnov <[email protected]>2024-01-31 17:22:33 +0300
committerAlexander Smirnov <[email protected]>2024-01-31 17:22:33 +0300
commit52be5dbdd420165c68e7e90ba8f1d2f00da041f6 (patch)
tree5d47f5b2ff4e6a7c8e75d33931a1e683949b7229 /contrib/libs/cxxsupp/libcxxrt/exception.cc
parentea57c8867ceca391357c3c5ffcc5ba6738b49adc (diff)
parent809f0cf2fdfddfbeacc2256ffdbaaf5808ce5ed4 (diff)
Merge branch 'mergelibs12' into main
Diffstat (limited to 'contrib/libs/cxxsupp/libcxxrt/exception.cc')
-rw-r--r--contrib/libs/cxxsupp/libcxxrt/exception.cc117
1 files changed, 80 insertions, 37 deletions
diff --git a/contrib/libs/cxxsupp/libcxxrt/exception.cc b/contrib/libs/cxxsupp/libcxxrt/exception.cc
index 9bb47c8e9e7..0a26befee6a 100644
--- a/contrib/libs/cxxsupp/libcxxrt/exception.cc
+++ b/contrib/libs/cxxsupp/libcxxrt/exception.cc
@@ -1,5 +1,6 @@
/*
* Copyright 2010-2011 PathScale, Inc. All rights reserved.
+ * Copyright 2021 David Chisnall. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -139,6 +140,7 @@ struct __cxa_thread_info
terminate_handler terminateHandler;
/** The unexpected exception handler for this thread. */
unexpected_handler unexpectedHandler;
+#ifndef LIBCXXRT_NO_EMERGENCY_MALLOC
/**
* The number of emergency buffers held by this thread. This is 0 in
* normal operation - the emergency buffers are only used when malloc()
@@ -147,6 +149,7 @@ struct __cxa_thread_info
* in ABI spec [3.3.1]).
*/
int emergencyBuffersHeld;
+#endif
/**
* The exception currently running in a cleanup.
*/
@@ -174,6 +177,7 @@ struct __cxa_thread_info
struct __cxa_dependent_exception
{
#if __LP64__
+ void *reserve;
void *primaryException;
#endif
std::type_info *exceptionType;
@@ -196,8 +200,18 @@ struct __cxa_dependent_exception
#endif
_Unwind_Exception unwindHeader;
};
+static_assert(sizeof(__cxa_exception) == sizeof(__cxa_dependent_exception),
+ "__cxa_exception and __cxa_dependent_exception should have the same size");
+static_assert(offsetof(__cxa_exception, referenceCount) ==
+ offsetof(__cxa_dependent_exception, primaryException),
+ "referenceCount and primaryException should have the same offset");
+static_assert(offsetof(__cxa_exception, unwindHeader) ==
+ offsetof(__cxa_dependent_exception, unwindHeader),
+ "unwindHeader fields should have the same offset");
+static_assert(offsetof(__cxa_dependent_exception, unwindHeader) ==
+ offsetof(__cxa_dependent_exception, adjustedPtr) + 8,
+ "there should be no padding before unwindHeader");
-static_assert(sizeof(__cxa_dependent_exception) == sizeof(__cxa_exception));
namespace std
{
@@ -283,19 +297,19 @@ using namespace ABI_NAMESPACE;
*/
static _Unwind_Reason_Code trace(struct _Unwind_Context *context, void *c)
{
- Dl_info myinfo;
- int mylookup =
- dladdr(reinterpret_cast<void *>(__cxa_current_exception_type), &myinfo);
- void *ip = reinterpret_cast<void*>(_Unwind_GetIP(context));
- Dl_info info;
- if (dladdr(ip, &info) != 0)
- {
- if (mylookup == 0 || strcmp(info.dli_fname, myinfo.dli_fname) != 0)
- {
- printf("%p:%s() in %s\n", ip, info.dli_sname, info.dli_fname);
- }
- }
- return _URC_CONTINUE_UNWIND;
+ Dl_info myinfo;
+ int mylookup =
+ dladdr(reinterpret_cast<void *>(__cxa_current_exception_type), &myinfo);
+ void *ip = reinterpret_cast<void*>(_Unwind_GetIP(context));
+ Dl_info info;
+ if (dladdr(ip, &info) != 0)
+ {
+ if (mylookup == 0 || strcmp(info.dli_fname, myinfo.dli_fname) != 0)
+ {
+ printf("%p:%s() in %s\n", ip, info.dli_sname, info.dli_fname);
+ }
+ }
+ return _URC_CONTINUE_UNWIND;
}
static void bt_terminate_handler() {
@@ -335,9 +349,9 @@ static void bt_terminate_handler() {
}
/** The global termination handler. */
-static terminate_handler terminateHandler = bt_terminate_handler;
+static atomic<terminate_handler> terminateHandler = bt_terminate_handler;
/** The global unexpected exception handler. */
-static unexpected_handler unexpectedHandler = std::terminate;
+static atomic<unexpected_handler> unexpectedHandler = std::terminate;
/** Key used for thread-local data. */
static pthread_key_t eh_key;
@@ -512,6 +526,23 @@ extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals_fast(void)
return &(thread_info_fast()->globals);
}
+#ifdef LIBCXXRT_NO_EMERGENCY_MALLOC
+static char *alloc_or_die(size_t size)
+{
+ char *buffer = static_cast<char*>(calloc(1, size));
+
+ if (buffer == nullptr)
+ {
+ fputs("Out of memory attempting to allocate exception\n", stderr);
+ std::terminate();
+ }
+ return buffer;
+}
+static void free_exception(char *e)
+{
+ free(e);
+}
+#else
/**
* An emergency allocation reserved for when malloc fails. This is treated as
* 16 buffers of 1KB each.
@@ -651,6 +682,7 @@ static void free_exception(char *e)
free(e);
}
}
+#endif
static constexpr size_t align_to(size_t size, size_t alignment) noexcept {
return (size + alignment - 1) / alignment * alignment;
@@ -672,6 +704,7 @@ static_assert(
static constexpr size_t backtrace_buffer_size = 0;
#endif
+
/**
* Allocates an exception structure. Returns a pointer to the space that can
* be used to store an object of thrown_size bytes. This function will use an
@@ -821,12 +854,12 @@ static void throw_exception(__cxa_exception *ex)
ex->unexpectedHandler = info->unexpectedHandler;
if (0 == ex->unexpectedHandler)
{
- ex->unexpectedHandler = unexpectedHandler;
+ ex->unexpectedHandler = unexpectedHandler.load();
}
ex->terminateHandler = info->terminateHandler;
if (0 == ex->terminateHandler)
{
- ex->terminateHandler = terminateHandler;
+ ex->terminateHandler = terminateHandler.load();
}
info->globals.uncaughtExceptions++;
@@ -837,6 +870,21 @@ static void throw_exception(__cxa_exception *ex)
report_failure(err, ex);
}
+extern "C" __cxa_exception *__cxa_init_primary_exception(
+ void *object, std::type_info* tinfo, void (*dest)(void *)) {
+ __cxa_exception *ex = reinterpret_cast<__cxa_exception*>(object) - 1;
+
+ ex->referenceCount = 0;
+ ex->exceptionType = tinfo;
+
+ ex->exceptionDestructor = dest;
+
+ ex->unwindHeader.exception_class = exception_class;
+ ex->unwindHeader.exception_cleanup = exception_cleanup;
+
+ return ex;
+}
+
typedef void (*cxa_throw_hook_t)(void*, std::type_info*, void(*)(void*)) noexcept;
__attribute__((weak)) cxa_throw_hook_t cxa_throw_hook = nullptr;
@@ -850,20 +898,13 @@ extern "C" void __cxa_throw(void *thrown_exception,
std::type_info *tinfo,
void(*dest)(void*))
{
- if (cxa_throw_hook)
- {
- cxa_throw_hook(thrown_exception, tinfo, dest);
- }
-
- __cxa_exception *ex = reinterpret_cast<__cxa_exception*>(thrown_exception) - 1;
+ if (cxa_throw_hook)
+ {
+ cxa_throw_hook(thrown_exception, tinfo, dest);
+ }
+ __cxa_exception *ex = __cxa_init_primary_exception(thrown_exception, tinfo, dest);
ex->referenceCount = 1;
- ex->exceptionType = tinfo;
-
- ex->exceptionDestructor = dest;
-
- ex->unwindHeader.exception_class = exception_class;
- ex->unwindHeader.exception_cleanup = exception_cleanup;
throw_exception(ex);
}
@@ -1567,7 +1608,7 @@ namespace std
{
if (thread_local_handlers) { return pathscale::set_unexpected(f); }
- return ATOMIC_SWAP(&unexpectedHandler, f);
+ return unexpectedHandler.exchange(f);
}
/**
* Sets the function that is called to terminate the program.
@@ -1576,7 +1617,7 @@ namespace std
{
if (thread_local_handlers) { return pathscale::set_terminate(f); }
- return ATOMIC_SWAP(&terminateHandler, f);
+ return terminateHandler.exchange(f);
}
/**
* Terminates the program, calling a custom terminate implementation if
@@ -1592,7 +1633,7 @@ namespace std
// return.
abort();
}
- terminateHandler();
+ terminateHandler.load()();
}
/**
* Called when an unexpected exception is encountered (i.e. an exception
@@ -1609,7 +1650,7 @@ namespace std
// return.
abort();
}
- unexpectedHandler();
+ unexpectedHandler.load()();
}
/**
* Returns whether there are any exceptions currently being thrown that
@@ -1639,7 +1680,7 @@ namespace std
{
return info->unexpectedHandler;
}
- return ATOMIC_LOAD(&unexpectedHandler);
+ return unexpectedHandler.load();
}
/**
* Returns the current terminate handler.
@@ -1651,7 +1692,7 @@ namespace std
{
return info->terminateHandler;
}
- return ATOMIC_LOAD(&terminateHandler);
+ return terminateHandler.load();
}
}
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
@@ -1682,8 +1723,10 @@ asm (
".type __cxa_end_cleanup, \"function\" \n"
"__cxa_end_cleanup: \n"
" push {r1, r2, r3, r4} \n"
+" mov r4, lr \n"
" bl __cxa_get_cleanup \n"
-" push {r1, r2, r3, r4} \n"
+" mov lr, r4 \n"
+" pop {r1, r2, r3, r4} \n"
" b _Unwind_Resume \n"
" bl abort \n"
".popsection \n"