summaryrefslogtreecommitdiffstats
path: root/lib/libcxxabi/src/cxa_exception.cpp
diff options
context:
space:
mode:
authorrobert <robert@openbsd.org>2018-09-11 18:06:31 +0000
committerrobert <robert@openbsd.org>2018-09-11 18:06:31 +0000
commit8a05a458f6e66ba4e39e97f266f4fbfbbdf85f5b (patch)
treedaa979747ce9e345dc0680933d017c4bb0b5768c /lib/libcxxabi/src/cxa_exception.cpp
parentmerge libunwind 6.0.0; ok patrick@, kettenis@ (diff)
downloadwireguard-openbsd-8a05a458f6e66ba4e39e97f266f4fbfbbdf85f5b.tar.xz
wireguard-openbsd-8a05a458f6e66ba4e39e97f266f4fbfbbdf85f5b.zip
import of libc++abi 6.0.0
Diffstat (limited to 'lib/libcxxabi/src/cxa_exception.cpp')
-rw-r--r--lib/libcxxabi/src/cxa_exception.cpp123
1 files changed, 73 insertions, 50 deletions
diff --git a/lib/libcxxabi/src/cxa_exception.cpp b/lib/libcxxabi/src/cxa_exception.cpp
index 50d1a468cea..d5230cdc7d9 100644
--- a/lib/libcxxabi/src/cxa_exception.cpp
+++ b/lib/libcxxabi/src/cxa_exception.cpp
@@ -11,17 +11,17 @@
//
//===----------------------------------------------------------------------===//
-#include "config.h"
#include "cxxabi.h"
#include <exception> // for std::terminate
-#include <cstdlib> // for malloc, free
#include <cstring> // for memset
-#if !LIBCXXABI_HAS_NO_THREADS
-# include <pthread.h> // for fallback_malloc.ipp's mutexes
-#endif
#include "cxa_exception.hpp"
#include "cxa_handlers.hpp"
+#include "fallback_malloc.h"
+
+#if __has_feature(address_sanitizer)
+extern "C" void __asan_handle_no_return(void);
+#endif
// +---------------------------+-----------------------------+---------------+
// | __cxa_exception | _Unwind_Exception CLNGC++\0 | thrown object |
@@ -36,8 +36,6 @@
namespace __cxxabiv1 {
-#pragma GCC visibility push(default)
-
// Utility routines
static
inline
@@ -68,12 +66,16 @@ cxa_exception_from_exception_unwind_exception(_Unwind_Exception* unwind_exceptio
return cxa_exception_from_thrown_object(unwind_exception + 1 );
}
-static
-inline
-size_t
-cxa_exception_size_from_exception_thrown_size(size_t size)
-{
- return size + sizeof (__cxa_exception);
+// Round s up to next multiple of a.
+static inline
+size_t aligned_allocation_size(size_t s, size_t a) {
+ return (s + a - 1) & ~(a - 1);
+}
+
+static inline
+size_t cxa_exception_size_from_exception_thrown_size(size_t size) {
+ return aligned_allocation_size(size + sizeof (__cxa_exception),
+ alignof(__cxa_exception));
}
static void setExceptionClass(_Unwind_Exception* unwind_exception) {
@@ -104,20 +106,6 @@ static inline int decrementHandlerCount(__cxa_exception *exception) {
return --exception->handlerCount;
}
-#include "fallback_malloc.ipp"
-
-// Allocate some memory from _somewhere_
-static void *do_malloc(size_t size) {
- void *ptr = std::malloc(size);
- if (NULL == ptr) // if malloc fails, fall back to emergency stash
- ptr = fallback_malloc(size);
- return ptr;
-}
-
-static void do_free(void *ptr) {
- is_fallback_ptr(ptr) ? fallback_free(ptr) : std::free(ptr);
-}
-
/*
If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
stored in exc is called. Otherwise the exceptionDestructor stored in
@@ -137,7 +125,7 @@ exception_cleanup_func(_Unwind_Reason_Code reason, _Unwind_Exception* unwind_exc
__cxa_decrement_exception_refcount(unwind_exception + 1);
}
-static LIBCXXABI_NORETURN void failed_throw(__cxa_exception* exception_header) {
+static _LIBCXXABI_NORETURN void failed_throw(__cxa_exception* exception_header) {
// Section 2.5.3 says:
// * For purposes of this ABI, several things are considered exception handlers:
// ** A terminate() call due to a throw.
@@ -149,6 +137,28 @@ static LIBCXXABI_NORETURN void failed_throw(__cxa_exception* exception_header) {
std::__terminate(exception_header->terminateHandler);
}
+// Return the offset of the __cxa_exception header from the start of the
+// allocated buffer. If __cxa_exception's alignment is smaller than the maximum
+// useful alignment for the target machine, padding has to be inserted before
+// the header to ensure the thrown object that follows the header is
+// sufficiently aligned. This happens if _Unwind_exception isn't double-word
+// aligned (on Darwin, for example).
+static size_t get_cxa_exception_offset() {
+ struct S {
+ } __attribute__((aligned));
+
+ // Compute the maximum alignment for the target machine.
+ constexpr size_t alignment = std::alignment_of<S>::value;
+ constexpr size_t excp_size = sizeof(__cxa_exception);
+ constexpr size_t aligned_size =
+ (excp_size + alignment - 1) / alignment * alignment;
+ constexpr size_t offset = aligned_size - excp_size;
+ static_assert((offset == 0 ||
+ std::alignment_of<_Unwind_Exception>::value < alignment),
+ "offset is non-zero only if _Unwind_Exception isn't aligned");
+ return offset;
+}
+
extern "C" {
// Allocate a __cxa_exception object, and zero-fill it.
@@ -156,19 +166,30 @@ extern "C" {
// object. Zero-fill the object. If memory can't be allocated, call
// std::terminate. Return a pointer to the memory to be used for the
// user's exception object.
-_LIBCXXABI_FUNC_VIS void *__cxa_allocate_exception(size_t thrown_size) throw() {
+void *__cxa_allocate_exception(size_t thrown_size) throw() {
size_t actual_size = cxa_exception_size_from_exception_thrown_size(thrown_size);
- __cxa_exception* exception_header = static_cast<__cxa_exception*>(do_malloc(actual_size));
- if (NULL == exception_header)
+
+ // Allocate extra space before the __cxa_exception header to ensure the
+ // start of the thrown object is sufficiently aligned.
+ size_t header_offset = get_cxa_exception_offset();
+ char *raw_buffer =
+ (char *)__aligned_malloc_with_fallback(header_offset + actual_size);
+ if (NULL == raw_buffer)
std::terminate();
+ __cxa_exception *exception_header =
+ static_cast<__cxa_exception *>((void *)(raw_buffer + header_offset));
std::memset(exception_header, 0, actual_size);
return thrown_object_from_cxa_exception(exception_header);
}
// Free a __cxa_exception object allocated with __cxa_allocate_exception.
-_LIBCXXABI_FUNC_VIS void __cxa_free_exception(void *thrown_object) throw() {
- do_free(cxa_exception_from_thrown_object(thrown_object));
+void __cxa_free_exception(void *thrown_object) throw() {
+ // Compute the size of the padding before the header.
+ size_t header_offset = get_cxa_exception_offset();
+ char *raw_buffer =
+ ((char *)cxa_exception_from_thrown_object(thrown_object)) - header_offset;
+ __aligned_free_with_fallback((void *)raw_buffer);
}
@@ -177,7 +198,7 @@ _LIBCXXABI_FUNC_VIS void __cxa_free_exception(void *thrown_object) throw() {
// Otherwise, it will work like __cxa_allocate_exception.
void * __cxa_allocate_dependent_exception () {
size_t actual_size = sizeof(__cxa_dependent_exception);
- void *ptr = do_malloc(actual_size);
+ void *ptr = __aligned_malloc_with_fallback(actual_size);
if (NULL == ptr)
std::terminate();
std::memset(ptr, 0, actual_size);
@@ -188,7 +209,7 @@ void * __cxa_allocate_dependent_exception () {
// This function shall free a dependent_exception.
// It does not affect the reference count of the primary exception.
void __cxa_free_dependent_exception (void * dependent_exception) {
- do_free(dependent_exception);
+ __aligned_free_with_fallback(dependent_exception);
}
@@ -218,7 +239,7 @@ handler, _Unwind_RaiseException may return. In that case, __cxa_throw
will call terminate, assuming that there was no handler for the
exception.
*/
-_LIBCXXABI_FUNC_VIS LIBCXXABI_NORETURN void
+void
__cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) {
__cxa_eh_globals *globals = __cxa_get_globals();
__cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
@@ -232,6 +253,12 @@ __cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) {
globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
exception_header->unwindHeader.exception_cleanup = exception_cleanup_func;
+
+#if __has_feature(address_sanitizer)
+ // Inform the ASan runtime that now might be a good time to clean stuff up.
+ __asan_handle_no_return();
+#endif
+
#ifdef __USING_SJLJ_EXCEPTIONS__
_Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
#else
@@ -251,9 +278,8 @@ The adjusted pointer is computed by the personality routine during phase 1
Requires: exception is native
*/
-_LIBCXXABI_FUNC_VIS
void *__cxa_get_exception_ptr(void *unwind_exception) throw() {
-#if LIBCXXABI_ARM_EHABI
+#if defined(_LIBCXXABI_ARM_EHABI)
return reinterpret_cast<void*>(
static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]);
#else
@@ -262,12 +288,11 @@ void *__cxa_get_exception_ptr(void *unwind_exception) throw() {
#endif
}
-#if LIBCXXABI_ARM_EHABI
+#if defined(_LIBCXXABI_ARM_EHABI)
/*
The routine to be called before the cleanup. This will save __cxa_exception in
__cxa_eh_globals, so that __cxa_end_cleanup() can recover later.
*/
-_LIBCXXABI_FUNC_VIS
bool __cxa_begin_cleanup(void *unwind_arg) throw() {
_Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
__cxa_eh_globals* globals = __cxa_get_globals();
@@ -345,7 +370,7 @@ asm (
" bl abort\n"
" .popsection"
);
-#endif // LIBCXXABI_ARM_EHABI
+#endif // defined(_LIBCXXABI_ARM_EHABI)
/*
This routine can catch foreign or native exceptions. If native, the exception
@@ -405,7 +430,7 @@ __cxa_begin_catch(void* unwind_arg) throw()
globals->caughtExceptions = exception_header;
}
globals->uncaughtExceptions -= 1; // Not atomically, since globals are thread-local
-#if LIBCXXABI_ARM_EHABI
+#if defined(_LIBCXXABI_ARM_EHABI)
return reinterpret_cast<void*>(exception_header->unwindHeader.barrier_cache.bitpattern[0]);
#else
return exception_header->adjustedPtr;
@@ -439,7 +464,7 @@ For a foreign exception:
* If it has been rethrown, there is nothing to do.
* Otherwise delete the exception and pop the catch stack to empty.
*/
-_LIBCXXABI_FUNC_VIS void __cxa_end_catch() {
+void __cxa_end_catch() {
static_assert(sizeof(__cxa_exception) == sizeof(__cxa_dependent_exception),
"sizeof(__cxa_exception) must be equal to "
"sizeof(__cxa_dependent_exception)");
@@ -516,7 +541,7 @@ _LIBCXXABI_FUNC_VIS void __cxa_end_catch() {
// Note: exception_header may be masquerading as a __cxa_dependent_exception
// and that's ok. exceptionType is there too.
// However watch out for foreign exceptions. Return null for them.
-_LIBCXXABI_FUNC_VIS std::type_info *__cxa_current_exception_type() {
+std::type_info *__cxa_current_exception_type() {
// get the current exception
__cxa_eh_globals *globals = __cxa_get_globals_fast();
if (NULL == globals)
@@ -541,7 +566,7 @@ If the exception is native:
Note: exception_header may be masquerading as a __cxa_dependent_exception
and that's ok.
*/
-_LIBCXXABI_FUNC_VIS LIBCXXABI_NORETURN void __cxa_rethrow() {
+void __cxa_rethrow() {
__cxa_eh_globals* globals = __cxa_get_globals();
__cxa_exception* exception_header = globals->caughtExceptions;
if (NULL == exception_header)
@@ -586,7 +611,7 @@ _LIBCXXABI_FUNC_VIS LIBCXXABI_NORETURN void __cxa_rethrow() {
Requires: If thrown_object is not NULL, it is a native exception.
*/
-_LIBCXXABI_FUNC_VIS void
+void
__cxa_increment_exception_refcount(void *thrown_object) throw() {
if (thrown_object != NULL )
{
@@ -603,7 +628,7 @@ __cxa_increment_exception_refcount(void *thrown_object) throw() {
Requires: If thrown_object is not NULL, it is a native exception.
*/
-_LIBCXXABI_FUNC_VIS void
+void
__cxa_decrement_exception_refcount(void *thrown_object) throw() {
if (thrown_object != NULL )
{
@@ -627,7 +652,7 @@ __cxa_decrement_exception_refcount(void *thrown_object) throw() {
been no exceptions thrown, ever, on this thread, we can return NULL without
the need to allocate the exception-handling globals.
*/
-_LIBCXXABI_FUNC_VIS void *__cxa_current_primary_exception() throw() {
+void *__cxa_current_primary_exception() throw() {
// get the current exception
__cxa_eh_globals* globals = __cxa_get_globals_fast();
if (NULL == globals)
@@ -713,6 +738,4 @@ __cxa_uncaught_exceptions() throw()
} // extern "C"
-#pragma GCC visibility pop
-
} // abi