diff options
author | 2018-09-11 18:06:31 +0000 | |
---|---|---|
committer | 2018-09-11 18:06:31 +0000 | |
commit | 8a05a458f6e66ba4e39e97f266f4fbfbbdf85f5b (patch) | |
tree | daa979747ce9e345dc0680933d017c4bb0b5768c /lib/libcxxabi/src/cxa_exception.cpp | |
parent | merge libunwind 6.0.0; ok patrick@, kettenis@ (diff) | |
download | wireguard-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.cpp | 123 |
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 |