diff options
author | neksard <neksard@yandex-team.ru> | 2022-02-10 16:45:23 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:23 +0300 |
commit | 8f7cf138264e0caa318144bf8a2c950e0b0a8593 (patch) | |
tree | 83bf5c8c8047c42d8475e6095df90ccdc3d1b57f /contrib/libs/cxxsupp | |
parent | d3a398281c6fd1d3672036cb2d63f842d2cb28c5 (diff) | |
download | ydb-8f7cf138264e0caa318144bf8a2c950e0b0a8593.tar.gz |
Restoring authorship annotation for <neksard@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/cxxsupp')
20 files changed, 3322 insertions, 3322 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/include/cstdio b/contrib/libs/cxxsupp/libcxx/include/cstdio index 6a88bee6e8..0a8b2cde3e 100644 --- a/contrib/libs/cxxsupp/libcxx/include/cstdio +++ b/contrib/libs/cxxsupp/libcxx/include/cstdio @@ -137,7 +137,7 @@ using ::fgetpos _LIBCPP_USING_IF_EXISTS; using ::fseek _LIBCPP_USING_IF_EXISTS; #ifndef _LIBCPP_HAS_NO_FGETPOS_FSETPOS using ::fsetpos _LIBCPP_USING_IF_EXISTS; -#endif +#endif using ::ftell _LIBCPP_USING_IF_EXISTS; using ::rewind _LIBCPP_USING_IF_EXISTS; using ::clearerr _LIBCPP_USING_IF_EXISTS; diff --git a/contrib/libs/cxxsupp/libcxxrt/AUTHORS b/contrib/libs/cxxsupp/libcxxrt/AUTHORS index 2d70ee83a4..5a8dc9f675 100644 --- a/contrib/libs/cxxsupp/libcxxrt/AUTHORS +++ b/contrib/libs/cxxsupp/libcxxrt/AUTHORS @@ -1,2 +1,2 @@ -David Chisnall -PathScale engineers +David Chisnall +PathScale engineers diff --git a/contrib/libs/cxxsupp/libcxxrt/COPYRIGHT b/contrib/libs/cxxsupp/libcxxrt/COPYRIGHT index c432d61a1d..5970606f54 100644 --- a/contrib/libs/cxxsupp/libcxxrt/COPYRIGHT +++ b/contrib/libs/cxxsupp/libcxxrt/COPYRIGHT @@ -1,3 +1,3 @@ -PathScale Inc -NetBSD Foundation -FreeBSD Foundation +PathScale Inc +NetBSD Foundation +FreeBSD Foundation diff --git a/contrib/libs/cxxsupp/libcxxrt/LICENSE b/contrib/libs/cxxsupp/libcxxrt/LICENSE index cda1ea2f7b..8e9218b4a1 100644 --- a/contrib/libs/cxxsupp/libcxxrt/LICENSE +++ b/contrib/libs/cxxsupp/libcxxrt/LICENSE @@ -1,14 +1,14 @@ -The BSD License - -Copyright 2010-2011 PathScale, Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of PathScale, Inc. +The BSD License + +Copyright 2010-2011 PathScale, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of PathScale, Inc. diff --git a/contrib/libs/cxxsupp/libcxxrt/README b/contrib/libs/cxxsupp/libcxxrt/README index c784c11693..abb9b3971a 100644 --- a/contrib/libs/cxxsupp/libcxxrt/README +++ b/contrib/libs/cxxsupp/libcxxrt/README @@ -1,50 +1,50 @@ -libcxxabi -========= - -This library implements the Code Sourcery C++ ABI, as documented here: - -http://www.codesourcery.com/public/cxx-abi/abi.html - -It is intended to sit below an STL implementation, and provide features required by the compiler for implementation of the C++ language. - -Current Status --------------- - -At present, the library implements the following parts of the ABI specification: - -- RTTI classes and support for the dynamic_cast<> operator. -- Exception handling. -- Thread-safe initializers. - -Exception handling requires the assistance of a stack-unwinding library -implementing the low-level parts of the ABI. Either libgcc_s or libunwind -should work for this purpose. - -The library depends on various libc features, but does not depend on any C++ -features not implemented purely in the compiler or in the library itself. - -Supported Platforms -------------------- - -This code was initially developed on FreeBSD/x86, and has also been tested on FreeBSD/x86-64. It should work on other platforms that use the Code Sourcery ABI, for example Itanium, however this is untested. - -This library also supports the ARM EH ABI. - -Installation ------------- - -The default build system does not perform any installation. It is expected that this will be done by at a higher level. The exact installation steps depend on how you plan on deploying libcxxrt. - -There are three files that you may consider installing: - -- cxxabi.h (and unwind.h and either unwind-arm.h or unwind-itanium.h) -- libcxxrt.a -- libcxxrt.so - -The first describes the contract between this library and the compiler / STL implementation (lib[std]{cxx,c++}). Its contents should be considered semi-private, as it is probably not a good idea to encourage any code above the STL implementation to depend on it. Doing so will introduce portability issues. You may install this file but I recommend simply copying or linking it into your STL implementation's build directory. - -In general, I recommend against installing both the .a and the .so file. For static linking, the .a file should be linked against the static and dynamic versions of your STL implementation. Statically linking libcxxrt into your STL implementation means that users who dynamically link against the STL implementation can have libcxxrt upgraded automatically when you ship a new version of your STL implementation. - -The other option, installing the .so, is recommended for situations where you have two or more STL implementations and wish to be able to link against both (e.g. where an application links one library using libstdc++ and another using libc++). To support this case, you should link both STL implementations against libcxxrt.so. - -Supporting all of these options in the CMake build system is not practical - the amount of effort required to select the one that you want would be more than the effort required to perform the installation from an external script or build system. +libcxxabi +========= + +This library implements the Code Sourcery C++ ABI, as documented here: + +http://www.codesourcery.com/public/cxx-abi/abi.html + +It is intended to sit below an STL implementation, and provide features required by the compiler for implementation of the C++ language. + +Current Status +-------------- + +At present, the library implements the following parts of the ABI specification: + +- RTTI classes and support for the dynamic_cast<> operator. +- Exception handling. +- Thread-safe initializers. + +Exception handling requires the assistance of a stack-unwinding library +implementing the low-level parts of the ABI. Either libgcc_s or libunwind +should work for this purpose. + +The library depends on various libc features, but does not depend on any C++ +features not implemented purely in the compiler or in the library itself. + +Supported Platforms +------------------- + +This code was initially developed on FreeBSD/x86, and has also been tested on FreeBSD/x86-64. It should work on other platforms that use the Code Sourcery ABI, for example Itanium, however this is untested. + +This library also supports the ARM EH ABI. + +Installation +------------ + +The default build system does not perform any installation. It is expected that this will be done by at a higher level. The exact installation steps depend on how you plan on deploying libcxxrt. + +There are three files that you may consider installing: + +- cxxabi.h (and unwind.h and either unwind-arm.h or unwind-itanium.h) +- libcxxrt.a +- libcxxrt.so + +The first describes the contract between this library and the compiler / STL implementation (lib[std]{cxx,c++}). Its contents should be considered semi-private, as it is probably not a good idea to encourage any code above the STL implementation to depend on it. Doing so will introduce portability issues. You may install this file but I recommend simply copying or linking it into your STL implementation's build directory. + +In general, I recommend against installing both the .a and the .so file. For static linking, the .a file should be linked against the static and dynamic versions of your STL implementation. Statically linking libcxxrt into your STL implementation means that users who dynamically link against the STL implementation can have libcxxrt upgraded automatically when you ship a new version of your STL implementation. + +The other option, installing the .so, is recommended for situations where you have two or more STL implementations and wish to be able to link against both (e.g. where an application links one library using libstdc++ and another using libc++). To support this case, you should link both STL implementations against libcxxrt.so. + +Supporting all of these options in the CMake build system is not practical - the amount of effort required to select the one that you want would be more than the effort required to perform the installation from an external script or build system. diff --git a/contrib/libs/cxxsupp/libcxxrt/abi_namespace.h b/contrib/libs/cxxsupp/libcxxrt/abi_namespace.h index dda788da19..24edefdc53 100644 --- a/contrib/libs/cxxsupp/libcxxrt/abi_namespace.h +++ b/contrib/libs/cxxsupp/libcxxrt/abi_namespace.h @@ -1,5 +1,5 @@ -/** - * The namespace used for the ABI declarations. This is currently defined to - * be the same as GNU libsupc++, however this may change in the future. - */ -#define ABI_NAMESPACE __cxxabiv1 +/** + * The namespace used for the ABI declarations. This is currently defined to + * be the same as GNU libsupc++, however this may change in the future. + */ +#define ABI_NAMESPACE __cxxabiv1 diff --git a/contrib/libs/cxxsupp/libcxxrt/atomic.h b/contrib/libs/cxxsupp/libcxxrt/atomic.h index afdbdd04d5..fae0e89655 100644 --- a/contrib/libs/cxxsupp/libcxxrt/atomic.h +++ b/contrib/libs/cxxsupp/libcxxrt/atomic.h @@ -1,28 +1,28 @@ -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif -#ifndef __has_feature -#define __has_feature(x) 0 -#endif -/** - * Swap macro that enforces a happens-before relationship with a corresponding - * ATOMIC_LOAD. - */ -#if __has_builtin(__c11_atomic_exchange) -#define ATOMIC_SWAP(addr, val)\ - __c11_atomic_exchange(reinterpret_cast<_Atomic(__typeof__(val))*>(addr), val, __ATOMIC_ACQ_REL) -#elif __has_builtin(__sync_swap) -#define ATOMIC_SWAP(addr, val)\ - __sync_swap(addr, val) -#else -#define ATOMIC_SWAP(addr, val)\ - __sync_lock_test_and_set(addr, val) -#endif - -#if __has_builtin(__c11_atomic_load) -#define ATOMIC_LOAD(addr)\ - __c11_atomic_load(reinterpret_cast<_Atomic(__typeof__(*addr))*>(addr), __ATOMIC_ACQUIRE) -#else -#define ATOMIC_LOAD(addr)\ - (__sync_synchronize(), *addr) -#endif +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif +#ifndef __has_feature +#define __has_feature(x) 0 +#endif +/** + * Swap macro that enforces a happens-before relationship with a corresponding + * ATOMIC_LOAD. + */ +#if __has_builtin(__c11_atomic_exchange) +#define ATOMIC_SWAP(addr, val)\ + __c11_atomic_exchange(reinterpret_cast<_Atomic(__typeof__(val))*>(addr), val, __ATOMIC_ACQ_REL) +#elif __has_builtin(__sync_swap) +#define ATOMIC_SWAP(addr, val)\ + __sync_swap(addr, val) +#else +#define ATOMIC_SWAP(addr, val)\ + __sync_lock_test_and_set(addr, val) +#endif + +#if __has_builtin(__c11_atomic_load) +#define ATOMIC_LOAD(addr)\ + __c11_atomic_load(reinterpret_cast<_Atomic(__typeof__(*addr))*>(addr), __ATOMIC_ACQUIRE) +#else +#define ATOMIC_LOAD(addr)\ + (__sync_synchronize(), *addr) +#endif diff --git a/contrib/libs/cxxsupp/libcxxrt/auxhelper.cc b/contrib/libs/cxxsupp/libcxxrt/auxhelper.cc index 74b998eef2..8acf45341b 100644 --- a/contrib/libs/cxxsupp/libcxxrt/auxhelper.cc +++ b/contrib/libs/cxxsupp/libcxxrt/auxhelper.cc @@ -1,39 +1,39 @@ -/* - * Copyright 2010-2011 PathScale, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* + * Copyright 2010-2011 PathScale, Inc. All rights reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * aux.cc - Compiler helper functions. - * - * The functions declared in this file are intended to be called only by code - * that is automatically generated by C++ compilers for some common cases. - */ - -#include <stdlib.h> -#include "stdexcept.h" - + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * aux.cc - Compiler helper functions. + * + * The functions declared in this file are intended to be called only by code + * that is automatically generated by C++ compilers for some common cases. + */ + +#include <stdlib.h> +#include "stdexcept.h" + namespace { /** * Throw an exception if we're compiling with exceptions, otherwise abort. @@ -49,49 +49,49 @@ namespace { } } -/** - * Called to generate a bad cast exception. This function is intended to allow - * compilers to insert code generating this exception without needing to - * duplicate the code for throwing the exception in every call site. - */ -extern "C" void __cxa_bad_cast() -{ +/** + * Called to generate a bad cast exception. This function is intended to allow + * compilers to insert code generating this exception without needing to + * duplicate the code for throwing the exception in every call site. + */ +extern "C" void __cxa_bad_cast() +{ throw_exception<std::bad_cast>(); -} - -/** - * Called to generate a bad typeid exception. This function is intended to - * allow compilers to insert code generating this exception without needing to - * duplicate the code for throwing the exception in every call site. - */ -extern "C" void __cxa_bad_typeid() -{ +} + +/** + * Called to generate a bad typeid exception. This function is intended to + * allow compilers to insert code generating this exception without needing to + * duplicate the code for throwing the exception in every call site. + */ +extern "C" void __cxa_bad_typeid() +{ throw_exception<std::bad_typeid>(); -} - -/** - * Compilers may (but are not required to) set any pure-virtual function's - * vtable entry to this function. This makes debugging slightly easier, as - * users can add a breakpoint on this function to tell if they've accidentally - * called a pure-virtual function. - */ -extern "C" void __cxa_pure_virtual() -{ +} + +/** + * Compilers may (but are not required to) set any pure-virtual function's + * vtable entry to this function. This makes debugging slightly easier, as + * users can add a breakpoint on this function to tell if they've accidentally + * called a pure-virtual function. + */ +extern "C" void __cxa_pure_virtual() +{ abort(); -} - -/** - * Compilers may (but are not required to) set any deleted-virtual function's - * vtable entry to this function. This makes debugging slightly easier, as - * users can add a breakpoint on this function to tell if they've accidentally - * called a deleted-virtual function. - */ -extern "C" void __cxa_deleted_virtual() -{ +} + +/** + * Compilers may (but are not required to) set any deleted-virtual function's + * vtable entry to this function. This makes debugging slightly easier, as + * users can add a breakpoint on this function to tell if they've accidentally + * called a deleted-virtual function. + */ +extern "C" void __cxa_deleted_virtual() +{ abort(); -} - -extern "C" void __cxa_throw_bad_array_new_length() -{ +} + +extern "C" void __cxa_throw_bad_array_new_length() +{ throw_exception<std::bad_array_new_length>(); -} +} diff --git a/contrib/libs/cxxsupp/libcxxrt/cxxabi.h b/contrib/libs/cxxsupp/libcxxrt/cxxabi.h index 7a8cb6745f..6d61434d7c 100644 --- a/contrib/libs/cxxsupp/libcxxrt/cxxabi.h +++ b/contrib/libs/cxxsupp/libcxxrt/cxxabi.h @@ -1,250 +1,250 @@ +/* + * Copyright 2012 David Chisnall. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CXXABI_H_ +#define __CXXABI_H_ +#include <stdint.h> +#include "unwind.h" +namespace std +{ + class type_info; +} /* - * Copyright 2012 David Chisnall. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * The cxxabi.h header provides a set of public definitions for types and + * functions defined by the Itanium C++ ABI specification. For reference, see + * the ABI specification here: * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * http://sourcery.mentor.com/public/cxx-abi/abi.html + * + * All deviations from this specification, unless otherwise noted, are + * accidental. */ - -#ifndef __CXXABI_H_ -#define __CXXABI_H_ -#include <stdint.h> -#include "unwind.h" -namespace std -{ - class type_info; -} -/* - * The cxxabi.h header provides a set of public definitions for types and - * functions defined by the Itanium C++ ABI specification. For reference, see - * the ABI specification here: - * - * http://sourcery.mentor.com/public/cxx-abi/abi.html - * - * All deviations from this specification, unless otherwise noted, are - * accidental. - */ - -#ifdef __cplusplus -namespace __cxxabiv1 { -extern "C" { -#endif -/** - * Function type to call when an unexpected exception is encountered. - */ -typedef void (*unexpected_handler)(); -/** - * Function type to call when an unrecoverable condition is encountered. - */ -typedef void (*terminate_handler)(); - - -/** - * Structure used as a header on thrown exceptions. This is the same layout as - * defined by the Itanium ABI spec, so should be interoperable with any other - * implementation of this spec, such as GNU libsupc++. - * - * This structure is allocated when an exception is thrown. Unwinding happens - * in two phases, the first looks for a handler and the second installs the - * context. This structure stores a cache of the handler location between - * phase 1 and phase 2. Unfortunately, cleanup information is not cached, so - * must be looked up in both phases. This happens for two reasons. The first - * is that we don't know how many frames containing cleanups there will be, and - * we should avoid dynamic allocation during unwinding (the exception may be - * reporting that we've run out of memory). The second is that finding - * cleanups is much cheaper than finding handlers, because we don't have to - * look at the type table at all. - * - * Note: Several fields of this structure have not-very-informative names. - * These are taken from the ABI spec and have not been changed to make it - * easier for people referring to to the spec while reading this code. - */ -struct __cxa_exception -{ -#if __LP64__ - /** - * Reference count. Used to support the C++11 exception_ptr class. This - * is prepended to the structure in 64-bit mode and squeezed in to the - * padding left before the 64-bit aligned _Unwind_Exception at the end in - * 32-bit mode. - * - * Note that it is safe to extend this structure at the beginning, rather - * than the end, because the public API for creating it returns the address - * of the end (where the exception object can be stored). - */ - uintptr_t referenceCount; -#endif - /** Type info for the thrown object. */ - std::type_info *exceptionType; - /** Destructor for the object, if one exists. */ - void (*exceptionDestructor) (void *); - /** Handler called when an exception specification is violated. */ - unexpected_handler unexpectedHandler; - /** Hander called to terminate. */ - terminate_handler terminateHandler; - /** - * Next exception in the list. If an exception is thrown inside a catch - * block and caught in a nested catch, this points to the exception that - * will be handled after the inner catch block completes. - */ - __cxa_exception *nextException; - /** - * The number of handlers that currently have references to this - * exception. The top (non-sign) bit of this is used as a flag to indicate - * that the exception is being rethrown, so should not be deleted when its - * handler count reaches 0 (which it doesn't with the top bit set). - */ - int handlerCount; -#if defined(__arm__) && !defined(__ARM_DWARF_EH__) - /** - * The ARM EH ABI requires the unwind library to keep track of exceptions - * during cleanups. These support nesting, so we need to keep a list of - * them. - */ - _Unwind_Exception *nextCleanup; - /** - * The number of cleanups that are currently being run on this exception. - */ - int cleanupCount; -#endif - /** - * The selector value to be returned when installing the catch handler. - * Used at the call site to determine which catch() block should execute. - * This is found in phase 1 of unwinding then installed in phase 2. - */ - int handlerSwitchValue; - /** - * The action record for the catch. This is cached during phase 1 - * unwinding. - */ - const char *actionRecord; - /** - * Pointer to the language-specific data area (LSDA) for the handler - * frame. This is unused in this implementation, but set for ABI - * compatibility in case we want to mix code in very weird ways. - */ - const char *languageSpecificData; - /** The cached landing pad for the catch handler.*/ - void *catchTemp; - /** - * The pointer that will be returned as the pointer to the object. When - * throwing a class and catching a virtual superclass (for example), we - * need to adjust the thrown pointer to make it all work correctly. - */ - void *adjustedPtr; -#if !__LP64__ - /** - * Reference count. Used to support the C++11 exception_ptr class. This - * is prepended to the structure in 64-bit mode and squeezed in to the - * padding left before the 64-bit aligned _Unwind_Exception at the end in - * 32-bit mode. - * - * Note that it is safe to extend this structure at the beginning, rather - * than the end, because the public API for creating it returns the address - * of the end (where the exception object can be stored) - */ - uintptr_t referenceCount; -#endif - /** The language-agnostic part of the exception header. */ - _Unwind_Exception unwindHeader; -}; - -/** - * ABI-specified globals structure. Returned by the __cxa_get_globals() - * function and its fast variant. This is a per-thread structure - every - * thread will have one lazily allocated. - * - * This structure is defined by the ABI, so may be used outside of this - * library. - */ -struct __cxa_eh_globals -{ - /** - * A linked list of exceptions that are currently caught. There may be - * several of these in nested catch() blocks. - */ - __cxa_exception *caughtExceptions; - /** - * The number of uncaught exceptions. - */ - unsigned int uncaughtExceptions; -}; + +#ifdef __cplusplus +namespace __cxxabiv1 { +extern "C" { +#endif +/** + * Function type to call when an unexpected exception is encountered. + */ +typedef void (*unexpected_handler)(); +/** + * Function type to call when an unrecoverable condition is encountered. + */ +typedef void (*terminate_handler)(); + + +/** + * Structure used as a header on thrown exceptions. This is the same layout as + * defined by the Itanium ABI spec, so should be interoperable with any other + * implementation of this spec, such as GNU libsupc++. + * + * This structure is allocated when an exception is thrown. Unwinding happens + * in two phases, the first looks for a handler and the second installs the + * context. This structure stores a cache of the handler location between + * phase 1 and phase 2. Unfortunately, cleanup information is not cached, so + * must be looked up in both phases. This happens for two reasons. The first + * is that we don't know how many frames containing cleanups there will be, and + * we should avoid dynamic allocation during unwinding (the exception may be + * reporting that we've run out of memory). The second is that finding + * cleanups is much cheaper than finding handlers, because we don't have to + * look at the type table at all. + * + * Note: Several fields of this structure have not-very-informative names. + * These are taken from the ABI spec and have not been changed to make it + * easier for people referring to to the spec while reading this code. + */ +struct __cxa_exception +{ +#if __LP64__ + /** + * Reference count. Used to support the C++11 exception_ptr class. This + * is prepended to the structure in 64-bit mode and squeezed in to the + * padding left before the 64-bit aligned _Unwind_Exception at the end in + * 32-bit mode. + * + * Note that it is safe to extend this structure at the beginning, rather + * than the end, because the public API for creating it returns the address + * of the end (where the exception object can be stored). + */ + uintptr_t referenceCount; +#endif + /** Type info for the thrown object. */ + std::type_info *exceptionType; + /** Destructor for the object, if one exists. */ + void (*exceptionDestructor) (void *); + /** Handler called when an exception specification is violated. */ + unexpected_handler unexpectedHandler; + /** Hander called to terminate. */ + terminate_handler terminateHandler; + /** + * Next exception in the list. If an exception is thrown inside a catch + * block and caught in a nested catch, this points to the exception that + * will be handled after the inner catch block completes. + */ + __cxa_exception *nextException; + /** + * The number of handlers that currently have references to this + * exception. The top (non-sign) bit of this is used as a flag to indicate + * that the exception is being rethrown, so should not be deleted when its + * handler count reaches 0 (which it doesn't with the top bit set). + */ + int handlerCount; +#if defined(__arm__) && !defined(__ARM_DWARF_EH__) + /** + * The ARM EH ABI requires the unwind library to keep track of exceptions + * during cleanups. These support nesting, so we need to keep a list of + * them. + */ + _Unwind_Exception *nextCleanup; + /** + * The number of cleanups that are currently being run on this exception. + */ + int cleanupCount; +#endif + /** + * The selector value to be returned when installing the catch handler. + * Used at the call site to determine which catch() block should execute. + * This is found in phase 1 of unwinding then installed in phase 2. + */ + int handlerSwitchValue; + /** + * The action record for the catch. This is cached during phase 1 + * unwinding. + */ + const char *actionRecord; + /** + * Pointer to the language-specific data area (LSDA) for the handler + * frame. This is unused in this implementation, but set for ABI + * compatibility in case we want to mix code in very weird ways. + */ + const char *languageSpecificData; + /** The cached landing pad for the catch handler.*/ + void *catchTemp; + /** + * The pointer that will be returned as the pointer to the object. When + * throwing a class and catching a virtual superclass (for example), we + * need to adjust the thrown pointer to make it all work correctly. + */ + void *adjustedPtr; +#if !__LP64__ + /** + * Reference count. Used to support the C++11 exception_ptr class. This + * is prepended to the structure in 64-bit mode and squeezed in to the + * padding left before the 64-bit aligned _Unwind_Exception at the end in + * 32-bit mode. + * + * Note that it is safe to extend this structure at the beginning, rather + * than the end, because the public API for creating it returns the address + * of the end (where the exception object can be stored) + */ + uintptr_t referenceCount; +#endif + /** The language-agnostic part of the exception header. */ + _Unwind_Exception unwindHeader; +}; + +/** + * ABI-specified globals structure. Returned by the __cxa_get_globals() + * function and its fast variant. This is a per-thread structure - every + * thread will have one lazily allocated. + * + * This structure is defined by the ABI, so may be used outside of this + * library. + */ +struct __cxa_eh_globals +{ + /** + * A linked list of exceptions that are currently caught. There may be + * several of these in nested catch() blocks. + */ + __cxa_exception *caughtExceptions; + /** + * The number of uncaught exceptions. + */ + unsigned int uncaughtExceptions; +}; #define Y_CXA_EH_GLOBALS_COMPLETE -/** - * ABI function returning the __cxa_eh_globals structure. - */ -__cxa_eh_globals *__cxa_get_globals(void); -/** - * Version of __cxa_get_globals() assuming that __cxa_get_globals() has already - * been called at least once by this thread. - */ -__cxa_eh_globals *__cxa_get_globals_fast(void); - -std::type_info * __cxa_current_exception_type(); - -/** - * Throws an exception returned by __cxa_current_primary_exception(). This - * exception may have been caught in another thread. - */ -void __cxa_rethrow_primary_exception(void* thrown_exception); -/** - * Returns the current exception in a form that can be stored in an - * exception_ptr object and then rethrown by a call to - * __cxa_rethrow_primary_exception(). - */ -void *__cxa_current_primary_exception(void); -/** - * Increments the reference count of an exception. Called when an - * exception_ptr is copied. - */ -void __cxa_increment_exception_refcount(void* thrown_exception); -/** - * Decrements the reference count of an exception. Called when an - * exception_ptr is deleted. - */ -void __cxa_decrement_exception_refcount(void* thrown_exception); -/** - * Demangles a C++ symbol or type name. The buffer, if non-NULL, must be - * allocated with malloc() and must be *n bytes or more long. This function - * may call realloc() on the value pointed to by buf, and will return the - * length of the string via *n. - * - * The value pointed to by status is set to one of the following: - * - * 0: success - * -1: memory allocation failure - * -2: invalid mangled name - * -3: invalid arguments - */ -char* __cxa_demangle(const char* mangled_name, - char* buf, - size_t* n, - int* status); +/** + * ABI function returning the __cxa_eh_globals structure. + */ +__cxa_eh_globals *__cxa_get_globals(void); +/** + * Version of __cxa_get_globals() assuming that __cxa_get_globals() has already + * been called at least once by this thread. + */ +__cxa_eh_globals *__cxa_get_globals_fast(void); + +std::type_info * __cxa_current_exception_type(); + +/** + * Throws an exception returned by __cxa_current_primary_exception(). This + * exception may have been caught in another thread. + */ +void __cxa_rethrow_primary_exception(void* thrown_exception); +/** + * Returns the current exception in a form that can be stored in an + * exception_ptr object and then rethrown by a call to + * __cxa_rethrow_primary_exception(). + */ +void *__cxa_current_primary_exception(void); +/** + * Increments the reference count of an exception. Called when an + * exception_ptr is copied. + */ +void __cxa_increment_exception_refcount(void* thrown_exception); +/** + * Decrements the reference count of an exception. Called when an + * exception_ptr is deleted. + */ +void __cxa_decrement_exception_refcount(void* thrown_exception); +/** + * Demangles a C++ symbol or type name. The buffer, if non-NULL, must be + * allocated with malloc() and must be *n bytes or more long. This function + * may call realloc() on the value pointed to by buf, and will return the + * length of the string via *n. + * + * The value pointed to by status is set to one of the following: + * + * 0: success + * -1: memory allocation failure + * -2: invalid mangled name + * -3: invalid arguments + */ +char* __cxa_demangle(const char* mangled_name, + char* buf, + size_t* n, + int* status); #ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE size_t __cxa_collect_current_exception_backtrace(void** dest, size_t size); #endif -#ifdef __cplusplus -} // extern "C" -} // namespace - -namespace abi = __cxxabiv1; - -#endif /* __cplusplus */ -#endif /* __CXXABI_H_ */ +#ifdef __cplusplus +} // extern "C" +} // namespace + +namespace abi = __cxxabiv1; + +#endif /* __cplusplus */ +#endif /* __CXXABI_H_ */ diff --git a/contrib/libs/cxxsupp/libcxxrt/dwarf_eh.h b/contrib/libs/cxxsupp/libcxxrt/dwarf_eh.h index da86846abf..b7e221c01a 100644 --- a/contrib/libs/cxxsupp/libcxxrt/dwarf_eh.h +++ b/contrib/libs/cxxsupp/libcxxrt/dwarf_eh.h @@ -1,477 +1,477 @@ -/* - * Copyright 2010-2011 PathScale, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* + * Copyright 2010-2011 PathScale, Inc. All rights reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * dwarf_eh.h - Defines some helper functions for parsing DWARF exception - * handling tables. - * - * This file contains various helper functions that are independent of the - * language-specific code. It can be used in any personality function for the - * Itanium ABI. - */ -#include <assert.h> - -// TODO: Factor out Itanium / ARM differences. We probably want an itanium.h -// and arm.h that can be included by this file depending on the target ABI. - -// _GNU_SOURCE must be defined for unwind.h to expose some of the functions -// that we want. If it isn't, then we define it and undefine it to make sure -// that it doesn't impact the rest of the program. -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -# include "unwind.h" -# undef _GNU_SOURCE -#else -# include "unwind.h" -#endif - -#include <stdint.h> - -/// Type used for pointers into DWARF data -typedef unsigned char *dw_eh_ptr_t; - -// Flag indicating a signed quantity -#define DW_EH_PE_signed 0x08 -/// DWARF data encoding types. -enum dwarf_data_encoding -{ - /// Absolute pointer value - DW_EH_PE_absptr = 0x00, - /// Unsigned, little-endian, base 128-encoded (variable length). - DW_EH_PE_uleb128 = 0x01, - /// Unsigned 16-bit integer. - DW_EH_PE_udata2 = 0x02, - /// Unsigned 32-bit integer. - DW_EH_PE_udata4 = 0x03, - /// Unsigned 64-bit integer. - DW_EH_PE_udata8 = 0x04, - /// Signed, little-endian, base 128-encoded (variable length) - DW_EH_PE_sleb128 = DW_EH_PE_uleb128 | DW_EH_PE_signed, - /// Signed 16-bit integer. - DW_EH_PE_sdata2 = DW_EH_PE_udata2 | DW_EH_PE_signed, - /// Signed 32-bit integer. - DW_EH_PE_sdata4 = DW_EH_PE_udata4 | DW_EH_PE_signed, - /// Signed 32-bit integer. - DW_EH_PE_sdata8 = DW_EH_PE_udata8 | DW_EH_PE_signed -}; - -/** - * Returns the encoding for a DWARF EH table entry. The encoding is stored in - * the low four of an octet. The high four bits store the addressing mode. - */ -static inline enum dwarf_data_encoding get_encoding(unsigned char x) -{ - return static_cast<enum dwarf_data_encoding>(x & 0xf); -} - -/** - * DWARF addressing mode constants. When reading a pointer value from a DWARF - * exception table, you must know how it is stored and what the addressing mode - * is. The low four bits tell you the encoding, allowing you to decode a - * number. The high four bits tell you the addressing mode, allowing you to - * turn that number into an address in memory. - */ -enum dwarf_data_relative -{ - /// Value is omitted - DW_EH_PE_omit = 0xff, - /// Value relative to program counter - DW_EH_PE_pcrel = 0x10, - /// Value relative to the text segment - DW_EH_PE_textrel = 0x20, - /// Value relative to the data segment - DW_EH_PE_datarel = 0x30, - /// Value relative to the start of the function - DW_EH_PE_funcrel = 0x40, - /// Aligned pointer (Not supported yet - are they actually used?) - DW_EH_PE_aligned = 0x50, - /// Pointer points to address of real value - DW_EH_PE_indirect = 0x80 -}; -/** - * Returns the addressing mode component of this encoding. - */ -static inline enum dwarf_data_relative get_base(unsigned char x) -{ - return static_cast<enum dwarf_data_relative>(x & 0x70); -} -/** - * Returns whether an encoding represents an indirect address. - */ -static int is_indirect(unsigned char x) -{ - return ((x & DW_EH_PE_indirect) == DW_EH_PE_indirect); -} - -/** - * Returns the size of a fixed-size encoding. This function will abort if - * called with a value that is not a fixed-size encoding. - */ -static inline int dwarf_size_of_fixed_size_field(unsigned char type) -{ - switch (get_encoding(type)) - { - default: abort(); - case DW_EH_PE_sdata2: - case DW_EH_PE_udata2: return 2; - case DW_EH_PE_sdata4: - case DW_EH_PE_udata4: return 4; - case DW_EH_PE_sdata8: - case DW_EH_PE_udata8: return 8; - case DW_EH_PE_absptr: return sizeof(void*); - } -} - + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * dwarf_eh.h - Defines some helper functions for parsing DWARF exception + * handling tables. + * + * This file contains various helper functions that are independent of the + * language-specific code. It can be used in any personality function for the + * Itanium ABI. + */ +#include <assert.h> + +// TODO: Factor out Itanium / ARM differences. We probably want an itanium.h +// and arm.h that can be included by this file depending on the target ABI. + +// _GNU_SOURCE must be defined for unwind.h to expose some of the functions +// that we want. If it isn't, then we define it and undefine it to make sure +// that it doesn't impact the rest of the program. +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +# include "unwind.h" +# undef _GNU_SOURCE +#else +# include "unwind.h" +#endif + +#include <stdint.h> + +/// Type used for pointers into DWARF data +typedef unsigned char *dw_eh_ptr_t; + +// Flag indicating a signed quantity +#define DW_EH_PE_signed 0x08 +/// DWARF data encoding types. +enum dwarf_data_encoding +{ + /// Absolute pointer value + DW_EH_PE_absptr = 0x00, + /// Unsigned, little-endian, base 128-encoded (variable length). + DW_EH_PE_uleb128 = 0x01, + /// Unsigned 16-bit integer. + DW_EH_PE_udata2 = 0x02, + /// Unsigned 32-bit integer. + DW_EH_PE_udata4 = 0x03, + /// Unsigned 64-bit integer. + DW_EH_PE_udata8 = 0x04, + /// Signed, little-endian, base 128-encoded (variable length) + DW_EH_PE_sleb128 = DW_EH_PE_uleb128 | DW_EH_PE_signed, + /// Signed 16-bit integer. + DW_EH_PE_sdata2 = DW_EH_PE_udata2 | DW_EH_PE_signed, + /// Signed 32-bit integer. + DW_EH_PE_sdata4 = DW_EH_PE_udata4 | DW_EH_PE_signed, + /// Signed 32-bit integer. + DW_EH_PE_sdata8 = DW_EH_PE_udata8 | DW_EH_PE_signed +}; + +/** + * Returns the encoding for a DWARF EH table entry. The encoding is stored in + * the low four of an octet. The high four bits store the addressing mode. + */ +static inline enum dwarf_data_encoding get_encoding(unsigned char x) +{ + return static_cast<enum dwarf_data_encoding>(x & 0xf); +} + +/** + * DWARF addressing mode constants. When reading a pointer value from a DWARF + * exception table, you must know how it is stored and what the addressing mode + * is. The low four bits tell you the encoding, allowing you to decode a + * number. The high four bits tell you the addressing mode, allowing you to + * turn that number into an address in memory. + */ +enum dwarf_data_relative +{ + /// Value is omitted + DW_EH_PE_omit = 0xff, + /// Value relative to program counter + DW_EH_PE_pcrel = 0x10, + /// Value relative to the text segment + DW_EH_PE_textrel = 0x20, + /// Value relative to the data segment + DW_EH_PE_datarel = 0x30, + /// Value relative to the start of the function + DW_EH_PE_funcrel = 0x40, + /// Aligned pointer (Not supported yet - are they actually used?) + DW_EH_PE_aligned = 0x50, + /// Pointer points to address of real value + DW_EH_PE_indirect = 0x80 +}; +/** + * Returns the addressing mode component of this encoding. + */ +static inline enum dwarf_data_relative get_base(unsigned char x) +{ + return static_cast<enum dwarf_data_relative>(x & 0x70); +} +/** + * Returns whether an encoding represents an indirect address. + */ +static int is_indirect(unsigned char x) +{ + return ((x & DW_EH_PE_indirect) == DW_EH_PE_indirect); +} + +/** + * Returns the size of a fixed-size encoding. This function will abort if + * called with a value that is not a fixed-size encoding. + */ +static inline int dwarf_size_of_fixed_size_field(unsigned char type) +{ + switch (get_encoding(type)) + { + default: abort(); + case DW_EH_PE_sdata2: + case DW_EH_PE_udata2: return 2; + case DW_EH_PE_sdata4: + case DW_EH_PE_udata4: return 4; + case DW_EH_PE_sdata8: + case DW_EH_PE_udata8: return 8; + case DW_EH_PE_absptr: return sizeof(void*); + } +} + +/** + * Read an unsigned, little-endian, base-128, DWARF value. Updates *data to + * point to the end of the value. Stores the number of bits read in the value + * pointed to by b, allowing you to determine the value of the highest bit, and + * therefore the sign of a signed value. + * + * This function is not intended to be called directly. Use read_sleb128() or + * read_uleb128() for reading signed and unsigned versions, respectively. + */ +static uint64_t read_leb128(dw_eh_ptr_t *data, int *b) +{ + uint64_t uleb = 0; + unsigned int bit = 0; + unsigned char digit = 0; + // We have to read at least one octet, and keep reading until we get to one + // with the high bit unset + do + { + // This check is a bit too strict - we should also check the highest + // bit of the digit. + assert(bit < sizeof(uint64_t) * 8); + // Get the base 128 digit + digit = (**data) & 0x7f; + // Add it to the current value + uleb += digit << bit; + // Increase the shift value + bit += 7; + // Proceed to the next octet + (*data)++; + // Terminate when we reach a value that does not have the high bit set + // (i.e. which was not modified when we mask it with 0x7f) + } while ((*(*data - 1)) != digit); + *b = bit; + + return uleb; +} + +/** + * Reads an unsigned little-endian base-128 value starting at the address + * pointed to by *data. Updates *data to point to the next byte after the end + * of the variable-length value. + */ +static int64_t read_uleb128(dw_eh_ptr_t *data) +{ + int b; + return read_leb128(data, &b); +} + /** - * Read an unsigned, little-endian, base-128, DWARF value. Updates *data to - * point to the end of the value. Stores the number of bits read in the value - * pointed to by b, allowing you to determine the value of the highest bit, and - * therefore the sign of a signed value. - * - * This function is not intended to be called directly. Use read_sleb128() or - * read_uleb128() for reading signed and unsigned versions, respectively. - */ -static uint64_t read_leb128(dw_eh_ptr_t *data, int *b) -{ - uint64_t uleb = 0; - unsigned int bit = 0; - unsigned char digit = 0; - // We have to read at least one octet, and keep reading until we get to one - // with the high bit unset - do - { - // This check is a bit too strict - we should also check the highest - // bit of the digit. - assert(bit < sizeof(uint64_t) * 8); - // Get the base 128 digit - digit = (**data) & 0x7f; - // Add it to the current value - uleb += digit << bit; - // Increase the shift value - bit += 7; - // Proceed to the next octet - (*data)++; - // Terminate when we reach a value that does not have the high bit set - // (i.e. which was not modified when we mask it with 0x7f) - } while ((*(*data - 1)) != digit); - *b = bit; - - return uleb; -} - -/** - * Reads an unsigned little-endian base-128 value starting at the address - * pointed to by *data. Updates *data to point to the next byte after the end - * of the variable-length value. - */ -static int64_t read_uleb128(dw_eh_ptr_t *data) -{ - int b; - return read_leb128(data, &b); -} - -/** - * Reads a signed little-endian base-128 value starting at the address pointed - * to by *data. Updates *data to point to the next byte after the end of the - * variable-length value. - */ -static int64_t read_sleb128(dw_eh_ptr_t *data) -{ - int bits; - // Read as if it's signed - uint64_t uleb = read_leb128(data, &bits); - // If the most significant bit read is 1, then we need to sign extend it - if ((uleb >> (bits-1)) == 1) - { - // Sign extend by setting all bits in front of it to 1 - uleb |= static_cast<int64_t>(-1) << bits; - } - return static_cast<int64_t>(uleb); -} -/** - * Reads a value using the specified encoding from the address pointed to by - * *data. Updates the value of *data to point to the next byte after the end - * of the data. - */ -static uint64_t read_value(char encoding, dw_eh_ptr_t *data) -{ - enum dwarf_data_encoding type = get_encoding(encoding); - switch (type) - { - // Read fixed-length types -#define READ(dwarf, type) \ - case dwarf:\ - {\ - type t;\ - memcpy(&t, *data, sizeof t);\ - *data += sizeof t;\ - return static_cast<uint64_t>(t);\ - } - READ(DW_EH_PE_udata2, uint16_t) - READ(DW_EH_PE_udata4, uint32_t) - READ(DW_EH_PE_udata8, uint64_t) - READ(DW_EH_PE_sdata2, int16_t) - READ(DW_EH_PE_sdata4, int32_t) - READ(DW_EH_PE_sdata8, int64_t) - READ(DW_EH_PE_absptr, intptr_t) -#undef READ - // Read variable-length types - case DW_EH_PE_sleb128: - return read_sleb128(data); - case DW_EH_PE_uleb128: - return read_uleb128(data); - default: abort(); - } -} - -/** - * Resolves an indirect value. This expects an unwind context, an encoding, a - * decoded value, and the start of the region as arguments. The returned value - * is a pointer to the address identified by the encoded value. - * - * If the encoding does not specify an indirect value, then this returns v. - */ -static uint64_t resolve_indirect_value(_Unwind_Context *c, - unsigned char encoding, - int64_t v, - dw_eh_ptr_t start) -{ - switch (get_base(encoding)) - { - case DW_EH_PE_pcrel: - v += reinterpret_cast<uint64_t>(start); - break; - case DW_EH_PE_textrel: - v += static_cast<uint64_t>(static_cast<uintptr_t>(_Unwind_GetTextRelBase(c))); - break; - case DW_EH_PE_datarel: - v += static_cast<uint64_t>(static_cast<uintptr_t>(_Unwind_GetDataRelBase(c))); - break; - case DW_EH_PE_funcrel: - v += static_cast<uint64_t>(static_cast<uintptr_t>(_Unwind_GetRegionStart(c))); - default: - break; - } - // If this is an indirect value, then it is really the address of the real - // value - // TODO: Check whether this should really always be a pointer - it seems to - // be a GCC extensions, so not properly documented... - if (is_indirect(encoding)) - { - v = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(*reinterpret_cast<void**>(v))); - } - return v; -} - - -/** - * Reads an encoding and a value, updating *data to point to the next byte. - */ -static inline void read_value_with_encoding(_Unwind_Context *context, - dw_eh_ptr_t *data, - uint64_t *out) -{ - dw_eh_ptr_t start = *data; - unsigned char encoding = *((*data)++); - // If this value is omitted, skip it and don't touch the output value - if (encoding == DW_EH_PE_omit) { return; } - - *out = read_value(encoding, data); - *out = resolve_indirect_value(context, encoding, *out, start); -} - -/** - * Structure storing a decoded language-specific data area. Use parse_lsda() - * to generate an instance of this structure from the address returned by the - * generic unwind library. - * - * You should not need to inspect the fields of this structure directly if you - * are just using this header. The structure stores the locations of the - * various tables used for unwinding exceptions and is used by the functions - * for reading values from these tables. - */ -struct dwarf_eh_lsda -{ - /// The start of the region. This is a cache of the value returned by - /// _Unwind_GetRegionStart(). - dw_eh_ptr_t region_start; - /// The start of the landing pads table. - dw_eh_ptr_t landing_pads; - /// The start of the type table. - dw_eh_ptr_t type_table; - /// The encoding used for entries in the type tables. - unsigned char type_table_encoding; - /// The location of the call-site table. - dw_eh_ptr_t call_site_table; - /// The location of the action table. - dw_eh_ptr_t action_table; - /// The encoding used for entries in the call-site table. - unsigned char callsite_encoding; -}; - -/** - * Parse the header on the language-specific data area and return a structure - * containing the addresses and encodings of the various tables. - */ -static inline struct dwarf_eh_lsda parse_lsda(_Unwind_Context *context, - unsigned char *data) -{ - struct dwarf_eh_lsda lsda; - - lsda.region_start = reinterpret_cast<dw_eh_ptr_t>(_Unwind_GetRegionStart(context)); - - // If the landing pads are relative to anything other than the start of - // this region, find out where. This is @LPStart in the spec, although the - // encoding that GCC uses does not quite match the spec. - uint64_t v = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(lsda.region_start)); - read_value_with_encoding(context, &data, &v); - lsda.landing_pads = reinterpret_cast<dw_eh_ptr_t>(static_cast<uintptr_t>(v)); - - // If there is a type table, find out where it is. This is @TTBase in the - // spec. Note: we find whether there is a type table pointer by checking - // whether the leading byte is DW_EH_PE_omit (0xff), which is not what the - // spec says, but does seem to be how G++ indicates this. - lsda.type_table = 0; - lsda.type_table_encoding = *data++; - if (lsda.type_table_encoding != DW_EH_PE_omit) - { - v = read_uleb128(&data); - dw_eh_ptr_t type_table = data; - type_table += v; - lsda.type_table = type_table; - //lsda.type_table = (uintptr_t*)(data + v); - } -#if defined(__arm__) && !defined(__ARM_DWARF_EH__) - lsda.type_table_encoding = (DW_EH_PE_pcrel | DW_EH_PE_indirect); -#endif - - lsda.callsite_encoding = static_cast<enum dwarf_data_encoding>(*(data++)); - - // Action table is immediately after the call site table - lsda.action_table = data; - uintptr_t callsite_size = static_cast<uintptr_t>(read_uleb128(&data)); - lsda.action_table = data + callsite_size; - // Call site table is immediately after the header - lsda.call_site_table = static_cast<dw_eh_ptr_t>(data); - - - return lsda; -} - -/** - * Structure representing an action to be performed while unwinding. This - * contains the address that should be unwound to and the action record that - * provoked this action. - */ -struct dwarf_eh_action -{ - /** - * The address that this action directs should be the new program counter - * value after unwinding. - */ - dw_eh_ptr_t landing_pad; - /// The address of the action record. - dw_eh_ptr_t action_record; -}; - -/** - * Look up the landing pad that corresponds to the current invoke. - * Returns true if record exists. The context is provided by the generic - * unwind library and the lsda should be the result of a call to parse_lsda(). - * - * The action record is returned via the result parameter. - */ -static bool dwarf_eh_find_callsite(struct _Unwind_Context *context, - struct dwarf_eh_lsda *lsda, - struct dwarf_eh_action *result) -{ - result->action_record = 0; - result->landing_pad = 0; - // The current instruction pointer offset within the region - uint64_t ip = _Unwind_GetIP(context) - _Unwind_GetRegionStart(context); - unsigned char *callsite_table = static_cast<unsigned char*>(lsda->call_site_table); - - while (callsite_table <= lsda->action_table) - { - // Once again, the layout deviates from the spec. - uint64_t call_site_start, call_site_size, landing_pad, action; - call_site_start = read_value(lsda->callsite_encoding, &callsite_table); - call_site_size = read_value(lsda->callsite_encoding, &callsite_table); - - // Call site entries are sorted, so if we find a call site that's after - // the current instruction pointer then there is no action associated - // with this call and we should unwind straight through this frame - // without doing anything. - if (call_site_start > ip) { break; } - - // Read the address of the landing pad and the action from the call - // site table. - landing_pad = read_value(lsda->callsite_encoding, &callsite_table); - action = read_uleb128(&callsite_table); - - // We should not include the call_site_start (beginning of the region) - // address in the ip range. For each call site: - // - // address1: call proc - // address2: next instruction - // - // The call stack contains address2 and not address1, address1 can be - // at the end of another EH region. - if (call_site_start < ip && ip <= call_site_start + call_site_size) - { - if (action) - { - // Action records are 1-biased so both no-record and zeroth - // record can be stored. - result->action_record = lsda->action_table + action - 1; - } - // No landing pad means keep unwinding. - if (landing_pad) - { - // Landing pad is the offset from the value in the header - result->landing_pad = lsda->landing_pads + landing_pad; - } - return true; - } - } - return false; -} - -/// Defines an exception class from 8 bytes (endian independent) -#define EXCEPTION_CLASS(a,b,c,d,e,f,g,h) \ - ((static_cast<uint64_t>(a) << 56) +\ - (static_cast<uint64_t>(b) << 48) +\ - (static_cast<uint64_t>(c) << 40) +\ - (static_cast<uint64_t>(d) << 32) +\ - (static_cast<uint64_t>(e) << 24) +\ - (static_cast<uint64_t>(f) << 16) +\ - (static_cast<uint64_t>(g) << 8) +\ - (static_cast<uint64_t>(h))) - -#define GENERIC_EXCEPTION_CLASS(e,f,g,h) \ - (static_cast<uint32_t>(e) << 24) +\ - (static_cast<uint32_t>(f) << 16) +\ - (static_cast<uint32_t>(g) << 8) +\ - (static_cast<uint32_t>(h)) + * Reads a signed little-endian base-128 value starting at the address pointed + * to by *data. Updates *data to point to the next byte after the end of the + * variable-length value. + */ +static int64_t read_sleb128(dw_eh_ptr_t *data) +{ + int bits; + // Read as if it's signed + uint64_t uleb = read_leb128(data, &bits); + // If the most significant bit read is 1, then we need to sign extend it + if ((uleb >> (bits-1)) == 1) + { + // Sign extend by setting all bits in front of it to 1 + uleb |= static_cast<int64_t>(-1) << bits; + } + return static_cast<int64_t>(uleb); +} +/** + * Reads a value using the specified encoding from the address pointed to by + * *data. Updates the value of *data to point to the next byte after the end + * of the data. + */ +static uint64_t read_value(char encoding, dw_eh_ptr_t *data) +{ + enum dwarf_data_encoding type = get_encoding(encoding); + switch (type) + { + // Read fixed-length types +#define READ(dwarf, type) \ + case dwarf:\ + {\ + type t;\ + memcpy(&t, *data, sizeof t);\ + *data += sizeof t;\ + return static_cast<uint64_t>(t);\ + } + READ(DW_EH_PE_udata2, uint16_t) + READ(DW_EH_PE_udata4, uint32_t) + READ(DW_EH_PE_udata8, uint64_t) + READ(DW_EH_PE_sdata2, int16_t) + READ(DW_EH_PE_sdata4, int32_t) + READ(DW_EH_PE_sdata8, int64_t) + READ(DW_EH_PE_absptr, intptr_t) +#undef READ + // Read variable-length types + case DW_EH_PE_sleb128: + return read_sleb128(data); + case DW_EH_PE_uleb128: + return read_uleb128(data); + default: abort(); + } +} + +/** + * Resolves an indirect value. This expects an unwind context, an encoding, a + * decoded value, and the start of the region as arguments. The returned value + * is a pointer to the address identified by the encoded value. + * + * If the encoding does not specify an indirect value, then this returns v. + */ +static uint64_t resolve_indirect_value(_Unwind_Context *c, + unsigned char encoding, + int64_t v, + dw_eh_ptr_t start) +{ + switch (get_base(encoding)) + { + case DW_EH_PE_pcrel: + v += reinterpret_cast<uint64_t>(start); + break; + case DW_EH_PE_textrel: + v += static_cast<uint64_t>(static_cast<uintptr_t>(_Unwind_GetTextRelBase(c))); + break; + case DW_EH_PE_datarel: + v += static_cast<uint64_t>(static_cast<uintptr_t>(_Unwind_GetDataRelBase(c))); + break; + case DW_EH_PE_funcrel: + v += static_cast<uint64_t>(static_cast<uintptr_t>(_Unwind_GetRegionStart(c))); + default: + break; + } + // If this is an indirect value, then it is really the address of the real + // value + // TODO: Check whether this should really always be a pointer - it seems to + // be a GCC extensions, so not properly documented... + if (is_indirect(encoding)) + { + v = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(*reinterpret_cast<void**>(v))); + } + return v; +} + + +/** + * Reads an encoding and a value, updating *data to point to the next byte. + */ +static inline void read_value_with_encoding(_Unwind_Context *context, + dw_eh_ptr_t *data, + uint64_t *out) +{ + dw_eh_ptr_t start = *data; + unsigned char encoding = *((*data)++); + // If this value is omitted, skip it and don't touch the output value + if (encoding == DW_EH_PE_omit) { return; } + + *out = read_value(encoding, data); + *out = resolve_indirect_value(context, encoding, *out, start); +} + +/** + * Structure storing a decoded language-specific data area. Use parse_lsda() + * to generate an instance of this structure from the address returned by the + * generic unwind library. + * + * You should not need to inspect the fields of this structure directly if you + * are just using this header. The structure stores the locations of the + * various tables used for unwinding exceptions and is used by the functions + * for reading values from these tables. + */ +struct dwarf_eh_lsda +{ + /// The start of the region. This is a cache of the value returned by + /// _Unwind_GetRegionStart(). + dw_eh_ptr_t region_start; + /// The start of the landing pads table. + dw_eh_ptr_t landing_pads; + /// The start of the type table. + dw_eh_ptr_t type_table; + /// The encoding used for entries in the type tables. + unsigned char type_table_encoding; + /// The location of the call-site table. + dw_eh_ptr_t call_site_table; + /// The location of the action table. + dw_eh_ptr_t action_table; + /// The encoding used for entries in the call-site table. + unsigned char callsite_encoding; +}; + +/** + * Parse the header on the language-specific data area and return a structure + * containing the addresses and encodings of the various tables. + */ +static inline struct dwarf_eh_lsda parse_lsda(_Unwind_Context *context, + unsigned char *data) +{ + struct dwarf_eh_lsda lsda; + + lsda.region_start = reinterpret_cast<dw_eh_ptr_t>(_Unwind_GetRegionStart(context)); + + // If the landing pads are relative to anything other than the start of + // this region, find out where. This is @LPStart in the spec, although the + // encoding that GCC uses does not quite match the spec. + uint64_t v = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(lsda.region_start)); + read_value_with_encoding(context, &data, &v); + lsda.landing_pads = reinterpret_cast<dw_eh_ptr_t>(static_cast<uintptr_t>(v)); + + // If there is a type table, find out where it is. This is @TTBase in the + // spec. Note: we find whether there is a type table pointer by checking + // whether the leading byte is DW_EH_PE_omit (0xff), which is not what the + // spec says, but does seem to be how G++ indicates this. + lsda.type_table = 0; + lsda.type_table_encoding = *data++; + if (lsda.type_table_encoding != DW_EH_PE_omit) + { + v = read_uleb128(&data); + dw_eh_ptr_t type_table = data; + type_table += v; + lsda.type_table = type_table; + //lsda.type_table = (uintptr_t*)(data + v); + } +#if defined(__arm__) && !defined(__ARM_DWARF_EH__) + lsda.type_table_encoding = (DW_EH_PE_pcrel | DW_EH_PE_indirect); +#endif + + lsda.callsite_encoding = static_cast<enum dwarf_data_encoding>(*(data++)); + + // Action table is immediately after the call site table + lsda.action_table = data; + uintptr_t callsite_size = static_cast<uintptr_t>(read_uleb128(&data)); + lsda.action_table = data + callsite_size; + // Call site table is immediately after the header + lsda.call_site_table = static_cast<dw_eh_ptr_t>(data); + + + return lsda; +} + +/** + * Structure representing an action to be performed while unwinding. This + * contains the address that should be unwound to and the action record that + * provoked this action. + */ +struct dwarf_eh_action +{ + /** + * The address that this action directs should be the new program counter + * value after unwinding. + */ + dw_eh_ptr_t landing_pad; + /// The address of the action record. + dw_eh_ptr_t action_record; +}; + +/** + * Look up the landing pad that corresponds to the current invoke. + * Returns true if record exists. The context is provided by the generic + * unwind library and the lsda should be the result of a call to parse_lsda(). + * + * The action record is returned via the result parameter. + */ +static bool dwarf_eh_find_callsite(struct _Unwind_Context *context, + struct dwarf_eh_lsda *lsda, + struct dwarf_eh_action *result) +{ + result->action_record = 0; + result->landing_pad = 0; + // The current instruction pointer offset within the region + uint64_t ip = _Unwind_GetIP(context) - _Unwind_GetRegionStart(context); + unsigned char *callsite_table = static_cast<unsigned char*>(lsda->call_site_table); + + while (callsite_table <= lsda->action_table) + { + // Once again, the layout deviates from the spec. + uint64_t call_site_start, call_site_size, landing_pad, action; + call_site_start = read_value(lsda->callsite_encoding, &callsite_table); + call_site_size = read_value(lsda->callsite_encoding, &callsite_table); + + // Call site entries are sorted, so if we find a call site that's after + // the current instruction pointer then there is no action associated + // with this call and we should unwind straight through this frame + // without doing anything. + if (call_site_start > ip) { break; } + + // Read the address of the landing pad and the action from the call + // site table. + landing_pad = read_value(lsda->callsite_encoding, &callsite_table); + action = read_uleb128(&callsite_table); + + // We should not include the call_site_start (beginning of the region) + // address in the ip range. For each call site: + // + // address1: call proc + // address2: next instruction + // + // The call stack contains address2 and not address1, address1 can be + // at the end of another EH region. + if (call_site_start < ip && ip <= call_site_start + call_site_size) + { + if (action) + { + // Action records are 1-biased so both no-record and zeroth + // record can be stored. + result->action_record = lsda->action_table + action - 1; + } + // No landing pad means keep unwinding. + if (landing_pad) + { + // Landing pad is the offset from the value in the header + result->landing_pad = lsda->landing_pads + landing_pad; + } + return true; + } + } + return false; +} + +/// Defines an exception class from 8 bytes (endian independent) +#define EXCEPTION_CLASS(a,b,c,d,e,f,g,h) \ + ((static_cast<uint64_t>(a) << 56) +\ + (static_cast<uint64_t>(b) << 48) +\ + (static_cast<uint64_t>(c) << 40) +\ + (static_cast<uint64_t>(d) << 32) +\ + (static_cast<uint64_t>(e) << 24) +\ + (static_cast<uint64_t>(f) << 16) +\ + (static_cast<uint64_t>(g) << 8) +\ + (static_cast<uint64_t>(h))) + +#define GENERIC_EXCEPTION_CLASS(e,f,g,h) \ + (static_cast<uint32_t>(e) << 24) +\ + (static_cast<uint32_t>(f) << 16) +\ + (static_cast<uint32_t>(g) << 8) +\ + (static_cast<uint32_t>(h)) diff --git a/contrib/libs/cxxsupp/libcxxrt/dynamic_cast.cc b/contrib/libs/cxxsupp/libcxxrt/dynamic_cast.cc index 6ae3a40355..2a98a2c164 100644 --- a/contrib/libs/cxxsupp/libcxxrt/dynamic_cast.cc +++ b/contrib/libs/cxxsupp/libcxxrt/dynamic_cast.cc @@ -1,210 +1,210 @@ -/* - * Copyright 2010-2011 PathScale, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* + * Copyright 2010-2011 PathScale, Inc. All rights reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "typeinfo.h" -#include <stdio.h> - -using namespace ABI_NAMESPACE; - -/** - * Vtable header. - */ -struct vtable_header -{ - /** Offset of the leaf object. */ - ptrdiff_t leaf_offset; - /** Type of the object. */ - const __class_type_info *type; -}; - -/** - * Simple macro that does pointer arithmetic in bytes but returns a value of - * the same type as the original. - */ -#define ADD_TO_PTR(x, off) reinterpret_cast<__typeof__(x)>(reinterpret_cast<char*>(x) + off) - -bool std::type_info::__do_catch(std::type_info const *ex_type, - void **exception_object, - unsigned int outer) const -{ - const type_info *type = this; - - if (type == ex_type) - { - return true; - } - if (const __class_type_info *cti = dynamic_cast<const __class_type_info *>(type)) - { - return ex_type->__do_upcast(cti, exception_object); - } - return false; -} - -bool __pbase_type_info::__do_catch(std::type_info const *ex_type, - void **exception_object, - unsigned int outer) const -{ - if (ex_type == this) - { - return true; - } - if (!ex_type->__is_pointer_p()) - { - // Can't catch a non-pointer type in a pointer catch - return false; - } - - if (!(outer & 1)) - { - // If the low bit is cleared on this means that we've gone - // through a pointer that is not const qualified. - return false; - } - // Clear the low bit on outer if we're not const qualified. - if (!(__flags & __const_mask)) - { - outer &= ~1; - } - - const __pbase_type_info *ptr_type = - static_cast<const __pbase_type_info*>(ex_type); - - if (ptr_type->__flags & ~__flags) - { - // Handler pointer is less qualified - return false; - } - - // Special case for void* handler. - if(*__pointee == typeid(void)) - { - return true; - } - - return __pointee->__do_catch(ptr_type->__pointee, exception_object, outer); -} - -void *__class_type_info::cast_to(void *obj, const struct __class_type_info *other) const -{ - if (this == other) - { - return obj; - } - return 0; -} - -void *__si_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const -{ - if (this == other) - { - return obj; - } - return __base_type->cast_to(obj, other); -} -bool __si_class_type_info::__do_upcast(const __class_type_info *target, - void **thrown_object) const -{ - if (this == target) - { - return true; - } - return __base_type->__do_upcast(target, thrown_object); -} - -void *__vmi_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const -{ - if (__do_upcast(other, &obj)) - { - return obj; - } - return 0; -} - -bool __vmi_class_type_info::__do_upcast(const __class_type_info *target, - void **thrown_object) const -{ - if (this == target) - { - return true; - } - for (unsigned int i=0 ; i<__base_count ; i++) - { - const __base_class_type_info *info = &__base_info[i]; - ptrdiff_t offset = info->offset(); - // If this is a virtual superclass, the offset is stored in the - // object's vtable at the offset requested; 2.9.5.6.c: - // - // 'For a non-virtual base, this is the offset in the object of the - // base subobject. For a virtual base, this is the offset in the - // virtual table of the virtual base offset for the virtual base - // referenced (negative).' - - void *obj = *thrown_object; - if (info->isVirtual()) - { - // Object's vtable - ptrdiff_t *off = *static_cast<ptrdiff_t**>(obj); - // Offset location in vtable - off = ADD_TO_PTR(off, offset); - offset = *off; - } - void *cast = ADD_TO_PTR(obj, offset); - - if (info->__base_type == target || - (info->__base_type->__do_upcast(target, &cast))) - { - *thrown_object = cast; - return true; - } - } - return 0; -} - - -/** - * ABI function used to implement the dynamic_cast<> operator. Some cases of - * this operator are implemented entirely in the compiler (e.g. to void*). - * This function implements the dynamic casts of the form dynamic_cast<T>(v). - * This will be translated to a call to this function with the value v as the - * first argument. The type id of the static type of v is the second argument - * and the type id of the destination type (T) is the third argument. - * - * The third argument is a hint about the compiler's guess at the correct - * pointer offset. If this value is negative, then -1 indicates no hint, -2 - * that src is not a public base of dst, and -3 that src is a multiple public - * base type but never a virtual base type - */ -extern "C" void* __dynamic_cast(const void *sub, - const __class_type_info *src, - const __class_type_info *dst, - ptrdiff_t src2dst_offset) -{ - const char *vtable_location = *static_cast<const char * const *>(sub); - const vtable_header *header = - reinterpret_cast<const vtable_header*>(vtable_location - sizeof(vtable_header)); - void *leaf = ADD_TO_PTR(const_cast<void *>(sub), header->leaf_offset); - return header->type->cast_to(leaf, dst); -} + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "typeinfo.h" +#include <stdio.h> + +using namespace ABI_NAMESPACE; + +/** + * Vtable header. + */ +struct vtable_header +{ + /** Offset of the leaf object. */ + ptrdiff_t leaf_offset; + /** Type of the object. */ + const __class_type_info *type; +}; + +/** + * Simple macro that does pointer arithmetic in bytes but returns a value of + * the same type as the original. + */ +#define ADD_TO_PTR(x, off) reinterpret_cast<__typeof__(x)>(reinterpret_cast<char*>(x) + off) + +bool std::type_info::__do_catch(std::type_info const *ex_type, + void **exception_object, + unsigned int outer) const +{ + const type_info *type = this; + + if (type == ex_type) + { + return true; + } + if (const __class_type_info *cti = dynamic_cast<const __class_type_info *>(type)) + { + return ex_type->__do_upcast(cti, exception_object); + } + return false; +} + +bool __pbase_type_info::__do_catch(std::type_info const *ex_type, + void **exception_object, + unsigned int outer) const +{ + if (ex_type == this) + { + return true; + } + if (!ex_type->__is_pointer_p()) + { + // Can't catch a non-pointer type in a pointer catch + return false; + } + + if (!(outer & 1)) + { + // If the low bit is cleared on this means that we've gone + // through a pointer that is not const qualified. + return false; + } + // Clear the low bit on outer if we're not const qualified. + if (!(__flags & __const_mask)) + { + outer &= ~1; + } + + const __pbase_type_info *ptr_type = + static_cast<const __pbase_type_info*>(ex_type); + + if (ptr_type->__flags & ~__flags) + { + // Handler pointer is less qualified + return false; + } + + // Special case for void* handler. + if(*__pointee == typeid(void)) + { + return true; + } + + return __pointee->__do_catch(ptr_type->__pointee, exception_object, outer); +} + +void *__class_type_info::cast_to(void *obj, const struct __class_type_info *other) const +{ + if (this == other) + { + return obj; + } + return 0; +} + +void *__si_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const +{ + if (this == other) + { + return obj; + } + return __base_type->cast_to(obj, other); +} +bool __si_class_type_info::__do_upcast(const __class_type_info *target, + void **thrown_object) const +{ + if (this == target) + { + return true; + } + return __base_type->__do_upcast(target, thrown_object); +} + +void *__vmi_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const +{ + if (__do_upcast(other, &obj)) + { + return obj; + } + return 0; +} + +bool __vmi_class_type_info::__do_upcast(const __class_type_info *target, + void **thrown_object) const +{ + if (this == target) + { + return true; + } + for (unsigned int i=0 ; i<__base_count ; i++) + { + const __base_class_type_info *info = &__base_info[i]; + ptrdiff_t offset = info->offset(); + // If this is a virtual superclass, the offset is stored in the + // object's vtable at the offset requested; 2.9.5.6.c: + // + // 'For a non-virtual base, this is the offset in the object of the + // base subobject. For a virtual base, this is the offset in the + // virtual table of the virtual base offset for the virtual base + // referenced (negative).' + + void *obj = *thrown_object; + if (info->isVirtual()) + { + // Object's vtable + ptrdiff_t *off = *static_cast<ptrdiff_t**>(obj); + // Offset location in vtable + off = ADD_TO_PTR(off, offset); + offset = *off; + } + void *cast = ADD_TO_PTR(obj, offset); + + if (info->__base_type == target || + (info->__base_type->__do_upcast(target, &cast))) + { + *thrown_object = cast; + return true; + } + } + return 0; +} + + +/** + * ABI function used to implement the dynamic_cast<> operator. Some cases of + * this operator are implemented entirely in the compiler (e.g. to void*). + * This function implements the dynamic casts of the form dynamic_cast<T>(v). + * This will be translated to a call to this function with the value v as the + * first argument. The type id of the static type of v is the second argument + * and the type id of the destination type (T) is the third argument. + * + * The third argument is a hint about the compiler's guess at the correct + * pointer offset. If this value is negative, then -1 indicates no hint, -2 + * that src is not a public base of dst, and -3 that src is a multiple public + * base type but never a virtual base type + */ +extern "C" void* __dynamic_cast(const void *sub, + const __class_type_info *src, + const __class_type_info *dst, + ptrdiff_t src2dst_offset) +{ + const char *vtable_location = *static_cast<const char * const *>(sub); + const vtable_header *header = + reinterpret_cast<const vtable_header*>(vtable_location - sizeof(vtable_header)); + void *leaf = ADD_TO_PTR(const_cast<void *>(sub), header->leaf_offset); + return header->type->cast_to(leaf, dst); +} diff --git a/contrib/libs/cxxsupp/libcxxrt/exception.cc b/contrib/libs/cxxsupp/libcxxrt/exception.cc index 6baf428ead..be7d1b0897 100644 --- a/contrib/libs/cxxsupp/libcxxrt/exception.cc +++ b/contrib/libs/cxxsupp/libcxxrt/exception.cc @@ -1,278 +1,278 @@ /* - * Copyright 2010-2011 PathScale, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * Copyright 2010-2011 PathScale, Inc. All rights reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> -#include <dlfcn.h> -#include <stdio.h> -#include <string.h> -#include <stdint.h> -#include <pthread.h> -#include "typeinfo.h" -#include "dwarf_eh.h" -#include "atomic.h" -#include "cxxabi.h" + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <dlfcn.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <pthread.h> +#include "typeinfo.h" +#include "dwarf_eh.h" +#include "atomic.h" +#include "cxxabi.h" #include "msan.h" - -using namespace ABI_NAMESPACE; - -/** - * Saves the result of the landing pad that we have found. For ARM, this is - * stored in the generic unwind structure, while on other platforms it is - * stored in the C++ exception. - */ -static void saveLandingPad(struct _Unwind_Context *context, - struct _Unwind_Exception *ucb, - struct __cxa_exception *ex, - int selector, - dw_eh_ptr_t landingPad) -{ -#if defined(__arm__) && !defined(__ARM_DWARF_EH__) - // On ARM, we store the saved exception in the generic part of the structure - ucb->barrier_cache.sp = _Unwind_GetGR(context, 13); - ucb->barrier_cache.bitpattern[1] = static_cast<uint32_t>(selector); - ucb->barrier_cache.bitpattern[3] = reinterpret_cast<uint32_t>(landingPad); -#endif - // Cache the results for the phase 2 unwind, if we found a handler + +using namespace ABI_NAMESPACE; + +/** + * Saves the result of the landing pad that we have found. For ARM, this is + * stored in the generic unwind structure, while on other platforms it is + * stored in the C++ exception. + */ +static void saveLandingPad(struct _Unwind_Context *context, + struct _Unwind_Exception *ucb, + struct __cxa_exception *ex, + int selector, + dw_eh_ptr_t landingPad) +{ +#if defined(__arm__) && !defined(__ARM_DWARF_EH__) + // On ARM, we store the saved exception in the generic part of the structure + ucb->barrier_cache.sp = _Unwind_GetGR(context, 13); + ucb->barrier_cache.bitpattern[1] = static_cast<uint32_t>(selector); + ucb->barrier_cache.bitpattern[3] = reinterpret_cast<uint32_t>(landingPad); +#endif + // Cache the results for the phase 2 unwind, if we found a handler // and this is not a foreign exception. - if (ex) - { - ex->handlerSwitchValue = selector; - ex->catchTemp = landingPad; - } -} - -/** - * Loads the saved landing pad. Returns 1 on success, 0 on failure. - */ -static int loadLandingPad(struct _Unwind_Context *context, - struct _Unwind_Exception *ucb, - struct __cxa_exception *ex, - unsigned long *selector, - dw_eh_ptr_t *landingPad) -{ -#if defined(__arm__) && !defined(__ARM_DWARF_EH__) - *selector = ucb->barrier_cache.bitpattern[1]; - *landingPad = reinterpret_cast<dw_eh_ptr_t>(ucb->barrier_cache.bitpattern[3]); - return 1; -#else - if (ex) - { - *selector = ex->handlerSwitchValue; - *landingPad = reinterpret_cast<dw_eh_ptr_t>(ex->catchTemp); - return 0; - } - return 0; -#endif -} - -static inline _Unwind_Reason_Code continueUnwinding(struct _Unwind_Exception *ex, - struct _Unwind_Context *context) -{ -#if defined(__arm__) && !defined(__ARM_DWARF_EH__) - if (__gnu_unwind_frame(ex, context) != _URC_OK) { return _URC_FAILURE; } -#endif - return _URC_CONTINUE_UNWIND; -} - - -extern "C" void __cxa_free_exception(void *thrown_exception); -extern "C" void __cxa_free_dependent_exception(void *thrown_exception); -extern "C" void* __dynamic_cast(const void *sub, - const __class_type_info *src, - const __class_type_info *dst, - ptrdiff_t src2dst_offset); - -/** - * The type of a handler that has been found. - */ -typedef enum -{ - /** No handler. */ - handler_none, - /** - * A cleanup - the exception will propagate through this frame, but code - * must be run when this happens. - */ - handler_cleanup, - /** - * A catch statement. The exception will not propagate past this frame - * (without an explicit rethrow). - */ - handler_catch -} handler_type; - -/** - * Per-thread info required by the runtime. We store a single structure - * pointer in thread-local storage, because this tends to be a scarce resource - * and it's impolite to steal all of it and not leave any for the rest of the - * program. - * - * Instances of this structure are allocated lazily - at most one per thread - - * and are destroyed on thread termination. - */ -struct __cxa_thread_info -{ - /** The termination handler for this thread. */ - terminate_handler terminateHandler; - /** The unexpected exception handler for this thread. */ - unexpected_handler unexpectedHandler; - /** - * The number of emergency buffers held by this thread. This is 0 in - * normal operation - the emergency buffers are only used when malloc() - * fails to return memory for allocating an exception. Threads are not - * permitted to hold more than 4 emergency buffers (as per recommendation - * in ABI spec [3.3.1]). - */ - int emergencyBuffersHeld; - /** - * The exception currently running in a cleanup. - */ - _Unwind_Exception *currentCleanup; - /** - * Our state with respect to foreign exceptions. Usually none, set to - * caught if we have just caught an exception and rethrown if we are - * rethrowing it. - */ + if (ex) + { + ex->handlerSwitchValue = selector; + ex->catchTemp = landingPad; + } +} + +/** + * Loads the saved landing pad. Returns 1 on success, 0 on failure. + */ +static int loadLandingPad(struct _Unwind_Context *context, + struct _Unwind_Exception *ucb, + struct __cxa_exception *ex, + unsigned long *selector, + dw_eh_ptr_t *landingPad) +{ +#if defined(__arm__) && !defined(__ARM_DWARF_EH__) + *selector = ucb->barrier_cache.bitpattern[1]; + *landingPad = reinterpret_cast<dw_eh_ptr_t>(ucb->barrier_cache.bitpattern[3]); + return 1; +#else + if (ex) + { + *selector = ex->handlerSwitchValue; + *landingPad = reinterpret_cast<dw_eh_ptr_t>(ex->catchTemp); + return 0; + } + return 0; +#endif +} + +static inline _Unwind_Reason_Code continueUnwinding(struct _Unwind_Exception *ex, + struct _Unwind_Context *context) +{ +#if defined(__arm__) && !defined(__ARM_DWARF_EH__) + if (__gnu_unwind_frame(ex, context) != _URC_OK) { return _URC_FAILURE; } +#endif + return _URC_CONTINUE_UNWIND; +} + + +extern "C" void __cxa_free_exception(void *thrown_exception); +extern "C" void __cxa_free_dependent_exception(void *thrown_exception); +extern "C" void* __dynamic_cast(const void *sub, + const __class_type_info *src, + const __class_type_info *dst, + ptrdiff_t src2dst_offset); + +/** + * The type of a handler that has been found. + */ +typedef enum +{ + /** No handler. */ + handler_none, + /** + * A cleanup - the exception will propagate through this frame, but code + * must be run when this happens. + */ + handler_cleanup, + /** + * A catch statement. The exception will not propagate past this frame + * (without an explicit rethrow). + */ + handler_catch +} handler_type; + +/** + * Per-thread info required by the runtime. We store a single structure + * pointer in thread-local storage, because this tends to be a scarce resource + * and it's impolite to steal all of it and not leave any for the rest of the + * program. + * + * Instances of this structure are allocated lazily - at most one per thread - + * and are destroyed on thread termination. + */ +struct __cxa_thread_info +{ + /** The termination handler for this thread. */ + terminate_handler terminateHandler; + /** The unexpected exception handler for this thread. */ + unexpected_handler unexpectedHandler; + /** + * The number of emergency buffers held by this thread. This is 0 in + * normal operation - the emergency buffers are only used when malloc() + * fails to return memory for allocating an exception. Threads are not + * permitted to hold more than 4 emergency buffers (as per recommendation + * in ABI spec [3.3.1]). + */ + int emergencyBuffersHeld; + /** + * The exception currently running in a cleanup. + */ + _Unwind_Exception *currentCleanup; + /** + * Our state with respect to foreign exceptions. Usually none, set to + * caught if we have just caught an exception and rethrown if we are + * rethrowing it. + */ enum - { - none, - caught, - rethrown - } foreign_exception_state; - /** - * The public part of this structure, accessible from outside of this - * module. - */ - __cxa_eh_globals globals; -}; -/** + { + none, + caught, + rethrown + } foreign_exception_state; + /** + * The public part of this structure, accessible from outside of this + * module. + */ + __cxa_eh_globals globals; +}; +/** * Dependent exception. This - */ -struct __cxa_dependent_exception -{ -#if __LP64__ - void *primaryException; -#endif - std::type_info *exceptionType; + */ +struct __cxa_dependent_exception +{ +#if __LP64__ + void *primaryException; +#endif + std::type_info *exceptionType; void (*exceptionDestructor) (void *); - unexpected_handler unexpectedHandler; - terminate_handler terminateHandler; - __cxa_exception *nextException; - int handlerCount; -#if defined(__arm__) && !defined(__ARM_DWARF_EH__) - _Unwind_Exception *nextCleanup; - int cleanupCount; -#endif - int handlerSwitchValue; - const char *actionRecord; - const char *languageSpecificData; - void *catchTemp; - void *adjustedPtr; -#if !__LP64__ - void *primaryException; -#endif - _Unwind_Exception unwindHeader; -}; - + unexpected_handler unexpectedHandler; + terminate_handler terminateHandler; + __cxa_exception *nextException; + int handlerCount; +#if defined(__arm__) && !defined(__ARM_DWARF_EH__) + _Unwind_Exception *nextCleanup; + int cleanupCount; +#endif + int handlerSwitchValue; + const char *actionRecord; + const char *languageSpecificData; + void *catchTemp; + void *adjustedPtr; +#if !__LP64__ + void *primaryException; +#endif + _Unwind_Exception unwindHeader; +}; + static_assert(sizeof(__cxa_dependent_exception) == sizeof(__cxa_exception)); - -namespace std -{ - void unexpected(); - class exception - { - public: + +namespace std +{ + void unexpected(); + class exception + { + public: virtual ~exception(); virtual const char* what() const noexcept; - }; - -} + }; -/** - * Class of exceptions to distinguish between this and other exception types. - * - * The first four characters are the vendor ID. Currently, we use GNUC, - * because we aim for ABI-compatibility with the GNU implementation, and - * various checks may test for equality of the class, which is incorrect. - */ -static const uint64_t exception_class = +} + +/** + * Class of exceptions to distinguish between this and other exception types. + * + * The first four characters are the vendor ID. Currently, we use GNUC, + * because we aim for ABI-compatibility with the GNU implementation, and + * various checks may test for equality of the class, which is incorrect. + */ +static const uint64_t exception_class = #ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_PRIMARY_CLASS; #else EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\0'); #endif -/** +/** * Class used for dependent exceptions. - */ -static const uint64_t dependent_exception_class = + */ +static const uint64_t dependent_exception_class = #ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_DEPENDENT_CLASS; #else - EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\x01'); + EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\x01'); #endif -/** - * The low four bytes of the exception class, indicating that we conform to the - * Itanium C++ ABI. This is currently unused, but should be used in the future - * if we change our exception class, to allow this library and libsupc++ to be - * linked to the same executable and both to interoperate. - */ +/** + * The low four bytes of the exception class, indicating that we conform to the + * Itanium C++ ABI. This is currently unused, but should be used in the future + * if we change our exception class, to allow this library and libsupc++ to be + * linked to the same executable and both to interoperate. + */ static const uint32_t abi_exception_class = - GENERIC_EXCEPTION_CLASS('C', '+', '+', '\0'); - -static bool isCXXException(uint64_t cls) -{ - return (cls == exception_class) || (cls == dependent_exception_class); -} - -static bool isDependentException(uint64_t cls) -{ - return cls == dependent_exception_class; -} - -static __cxa_exception *exceptionFromPointer(void *ex) -{ - return reinterpret_cast<__cxa_exception*>(static_cast<char*>(ex) - - offsetof(struct __cxa_exception, unwindHeader)); -} -static __cxa_exception *realExceptionFromException(__cxa_exception *ex) -{ - if (!isDependentException(ex->unwindHeader.exception_class)) { return ex; } - return reinterpret_cast<__cxa_exception*>((reinterpret_cast<__cxa_dependent_exception*>(ex))->primaryException)-1; -} - - -namespace std -{ - // Forward declaration of standard library terminate() function used to - // abort execution. + GENERIC_EXCEPTION_CLASS('C', '+', '+', '\0'); + +static bool isCXXException(uint64_t cls) +{ + return (cls == exception_class) || (cls == dependent_exception_class); +} + +static bool isDependentException(uint64_t cls) +{ + return cls == dependent_exception_class; +} + +static __cxa_exception *exceptionFromPointer(void *ex) +{ + return reinterpret_cast<__cxa_exception*>(static_cast<char*>(ex) - + offsetof(struct __cxa_exception, unwindHeader)); +} +static __cxa_exception *realExceptionFromException(__cxa_exception *ex) +{ + if (!isDependentException(ex->unwindHeader.exception_class)) { return ex; } + return reinterpret_cast<__cxa_exception*>((reinterpret_cast<__cxa_dependent_exception*>(ex))->primaryException)-1; +} + + +namespace std +{ + // Forward declaration of standard library terminate() function used to + // abort execution. void terminate(void) noexcept; -} - -using namespace ABI_NAMESPACE; - +} + +using namespace ABI_NAMESPACE; + /** * Callback function used with _Unwind_Backtrace(). * @@ -297,11 +297,11 @@ static _Unwind_Reason_Code trace(struct _Unwind_Context *context, void *c) } return _URC_CONTINUE_UNWIND; } - + static void bt_terminate_handler() { __cxa_eh_globals* globals = __cxa_get_globals(); __cxa_exception* thrown_exception = globals->caughtExceptions; - + if (!thrown_exception) { abort(); } @@ -334,49 +334,49 @@ static void bt_terminate_handler() { abort(); } -/** The global termination handler. */ +/** The global termination handler. */ static terminate_handler terminateHandler = bt_terminate_handler; -/** The global unexpected exception handler. */ -static unexpected_handler unexpectedHandler = std::terminate; - -/** Key used for thread-local data. */ -static pthread_key_t eh_key; - - -/** - * Cleanup function, allowing foreign exception handlers to correctly destroy - * this exception if they catch it. - */ +/** The global unexpected exception handler. */ +static unexpected_handler unexpectedHandler = std::terminate; + +/** Key used for thread-local data. */ +static pthread_key_t eh_key; + + +/** + * Cleanup function, allowing foreign exception handlers to correctly destroy + * this exception if they catch it. + */ static void exception_cleanup(_Unwind_Reason_Code reason, - struct _Unwind_Exception *ex) -{ + struct _Unwind_Exception *ex) +{ // Exception layout: // [__cxa_exception [_Unwind_Exception]] [exception object] // // __cxa_free_exception expects a pointer to the exception object __cxa_free_exception(static_cast<void*>(ex + 1)); -} +} static void dependent_exception_cleanup(_Unwind_Reason_Code reason, - struct _Unwind_Exception *ex) -{ - + struct _Unwind_Exception *ex) +{ + __cxa_free_dependent_exception(static_cast<void*>(ex + 1)); -} - -/** - * Recursively walk a list of exceptions and delete them all in post-order. - */ -static void free_exception_list(__cxa_exception *ex) -{ - if (0 != ex->nextException) - { - free_exception_list(ex->nextException); - } - // __cxa_free_exception() expects to be passed the thrown object, which - // immediately follows the exception, not the exception itself - __cxa_free_exception(ex+1); -} - +} + +/** + * Recursively walk a list of exceptions and delete them all in post-order. + */ +static void free_exception_list(__cxa_exception *ex) +{ + if (0 != ex->nextException) + { + free_exception_list(ex->nextException); + } + // __cxa_free_exception() expects to be passed the thrown object, which + // immediately follows the exception, not the exception itself + __cxa_free_exception(ex+1); +} + #define fast_ti_size 100 static long fast_ti_index; @@ -415,68 +415,68 @@ static inline void free_thread_info(__cxa_thread_info* ti) { } } -/** - * Cleanup function called when a thread exists to make certain that all of the - * per-thread data is deleted. - */ -static void thread_cleanup(void* thread_info) -{ - __cxa_thread_info *info = static_cast<__cxa_thread_info*>(thread_info); - if (info->globals.caughtExceptions) - { - // If this is a foreign exception, ask it to clean itself up. - if (info->foreign_exception_state != __cxa_thread_info::none) - { - _Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(info->globals.caughtExceptions); +/** + * Cleanup function called when a thread exists to make certain that all of the + * per-thread data is deleted. + */ +static void thread_cleanup(void* thread_info) +{ + __cxa_thread_info *info = static_cast<__cxa_thread_info*>(thread_info); + if (info->globals.caughtExceptions) + { + // If this is a foreign exception, ask it to clean itself up. + if (info->foreign_exception_state != __cxa_thread_info::none) + { + _Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(info->globals.caughtExceptions); if (e->exception_cleanup) e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e); - } - else - { - free_exception_list(info->globals.caughtExceptions); - } - } + } + else + { + free_exception_list(info->globals.caughtExceptions); + } + } free_thread_info(info); -} - -/** - * Once control used to protect the key creation. - */ -static pthread_once_t once_control = PTHREAD_ONCE_INIT; - -/** - * Initialise eh_key. - */ -static void init_key(void) -{ - pthread_key_create(&eh_key, thread_cleanup); - pthread_setspecific(eh_key, reinterpret_cast<void *>(0x42)); +} + +/** + * Once control used to protect the key creation. + */ +static pthread_once_t once_control = PTHREAD_ONCE_INIT; + +/** + * Initialise eh_key. + */ +static void init_key(void) +{ + pthread_key_create(&eh_key, thread_cleanup); + pthread_setspecific(eh_key, reinterpret_cast<void *>(0x42)); if (pthread_getspecific(eh_key) != reinterpret_cast<void *>(0x42)) { abort(); } - pthread_setspecific(eh_key, 0); -} - + pthread_setspecific(eh_key, 0); +} + static __thread __cxa_thread_info* THR_INFO = nullptr; -/** - * Returns the thread info structure, creating it if it is not already created. - */ -static __cxa_thread_info *thread_info() -{ +/** + * Returns the thread info structure, creating it if it is not already created. + */ +static __cxa_thread_info *thread_info() +{ if (THR_INFO) { return THR_INFO; } pthread_once(&once_control, init_key); - __cxa_thread_info *info = static_cast<__cxa_thread_info*>(pthread_getspecific(eh_key)); + __cxa_thread_info *info = static_cast<__cxa_thread_info*>(pthread_getspecific(eh_key)); if (0 == info) { info = alloc_thread_info(); - pthread_setspecific(eh_key, info); - } + pthread_setspecific(eh_key, info); + } THR_INFO = info; - return info; -} + return info; +} // ensure main thread will allocate preallocated tls static struct InitMainTls { @@ -485,173 +485,173 @@ static struct InitMainTls { } } init_main_tls; -/** - * Fast version of thread_info(). May fail if thread_info() is not called on - * this thread at least once already. - */ -static __cxa_thread_info *thread_info_fast() -{ +/** + * Fast version of thread_info(). May fail if thread_info() is not called on + * this thread at least once already. + */ +static __cxa_thread_info *thread_info_fast() +{ if (THR_INFO) { return THR_INFO; } - return static_cast<__cxa_thread_info*>(pthread_getspecific(eh_key)); -} -/** - * ABI function returning the __cxa_eh_globals structure. - */ -extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals(void) -{ - return &(thread_info()->globals); -} -/** - * Version of __cxa_get_globals() assuming that __cxa_get_globals() has already - * been called at least once by this thread. - */ -extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals_fast(void) -{ - return &(thread_info_fast()->globals); -} - -/** - * An emergency allocation reserved for when malloc fails. This is treated as - * 16 buffers of 1KB each. - */ -static char emergency_buffer[16384]; -/** - * Flag indicating whether each buffer is allocated. - */ -static bool buffer_allocated[16]; -/** - * Lock used to protect emergency allocation. - */ -static pthread_mutex_t emergency_malloc_lock = PTHREAD_MUTEX_INITIALIZER; -/** - * Condition variable used to wait when two threads are both trying to use the - * emergency malloc() buffer at once. - */ -static pthread_cond_t emergency_malloc_wait = PTHREAD_COND_INITIALIZER; - -/** - * Allocates size bytes from the emergency allocation mechanism, if possible. - * This function will fail if size is over 1KB or if this thread already has 4 - * emergency buffers. If all emergency buffers are allocated, it will sleep - * until one becomes available. - */ -static char *emergency_malloc(size_t size) -{ - if (size > 1024) { return 0; } - - __cxa_thread_info *info = thread_info(); - // Only 4 emergency buffers allowed per thread! - if (info->emergencyBuffersHeld > 3) { return 0; } - - pthread_mutex_lock(&emergency_malloc_lock); - int buffer = -1; - while (buffer < 0) - { - // While we were sleeping on the lock, another thread might have free'd - // enough memory for us to use, so try the allocation again - no point - // using the emergency buffer if there is some real memory that we can - // use... - void *m = calloc(1, size); - if (0 != m) - { - pthread_mutex_unlock(&emergency_malloc_lock); - return static_cast<char*>(m); - } - for (int i=0 ; i<16 ; i++) - { - if (!buffer_allocated[i]) - { - buffer = i; - buffer_allocated[i] = true; - break; - } - } - // If there still isn't a buffer available, then sleep on the condition - // variable. This will be signalled when another thread releases one - // of the emergency buffers. - if (buffer < 0) - { - pthread_cond_wait(&emergency_malloc_wait, &emergency_malloc_lock); - } - } - pthread_mutex_unlock(&emergency_malloc_lock); - info->emergencyBuffersHeld++; - return emergency_buffer + (1024 * buffer); -} - -/** - * Frees a buffer returned by emergency_malloc(). - * - * Note: Neither this nor emergency_malloc() is particularly efficient. This - * should not matter, because neither will be called in normal operation - they - * are only used when the program runs out of memory, which should not happen - * often. - */ -static void emergency_malloc_free(char *ptr) -{ - int buffer = -1; - // Find the buffer corresponding to this pointer. - for (int i=0 ; i<16 ; i++) - { - if (ptr == static_cast<void*>(emergency_buffer + (1024 * i))) - { - buffer = i; - break; - } - } + return static_cast<__cxa_thread_info*>(pthread_getspecific(eh_key)); +} +/** + * ABI function returning the __cxa_eh_globals structure. + */ +extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals(void) +{ + return &(thread_info()->globals); +} +/** + * Version of __cxa_get_globals() assuming that __cxa_get_globals() has already + * been called at least once by this thread. + */ +extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals_fast(void) +{ + return &(thread_info_fast()->globals); +} + +/** + * An emergency allocation reserved for when malloc fails. This is treated as + * 16 buffers of 1KB each. + */ +static char emergency_buffer[16384]; +/** + * Flag indicating whether each buffer is allocated. + */ +static bool buffer_allocated[16]; +/** + * Lock used to protect emergency allocation. + */ +static pthread_mutex_t emergency_malloc_lock = PTHREAD_MUTEX_INITIALIZER; +/** + * Condition variable used to wait when two threads are both trying to use the + * emergency malloc() buffer at once. + */ +static pthread_cond_t emergency_malloc_wait = PTHREAD_COND_INITIALIZER; + +/** + * Allocates size bytes from the emergency allocation mechanism, if possible. + * This function will fail if size is over 1KB or if this thread already has 4 + * emergency buffers. If all emergency buffers are allocated, it will sleep + * until one becomes available. + */ +static char *emergency_malloc(size_t size) +{ + if (size > 1024) { return 0; } + + __cxa_thread_info *info = thread_info(); + // Only 4 emergency buffers allowed per thread! + if (info->emergencyBuffersHeld > 3) { return 0; } + + pthread_mutex_lock(&emergency_malloc_lock); + int buffer = -1; + while (buffer < 0) + { + // While we were sleeping on the lock, another thread might have free'd + // enough memory for us to use, so try the allocation again - no point + // using the emergency buffer if there is some real memory that we can + // use... + void *m = calloc(1, size); + if (0 != m) + { + pthread_mutex_unlock(&emergency_malloc_lock); + return static_cast<char*>(m); + } + for (int i=0 ; i<16 ; i++) + { + if (!buffer_allocated[i]) + { + buffer = i; + buffer_allocated[i] = true; + break; + } + } + // If there still isn't a buffer available, then sleep on the condition + // variable. This will be signalled when another thread releases one + // of the emergency buffers. + if (buffer < 0) + { + pthread_cond_wait(&emergency_malloc_wait, &emergency_malloc_lock); + } + } + pthread_mutex_unlock(&emergency_malloc_lock); + info->emergencyBuffersHeld++; + return emergency_buffer + (1024 * buffer); +} + +/** + * Frees a buffer returned by emergency_malloc(). + * + * Note: Neither this nor emergency_malloc() is particularly efficient. This + * should not matter, because neither will be called in normal operation - they + * are only used when the program runs out of memory, which should not happen + * often. + */ +static void emergency_malloc_free(char *ptr) +{ + int buffer = -1; + // Find the buffer corresponding to this pointer. + for (int i=0 ; i<16 ; i++) + { + if (ptr == static_cast<void*>(emergency_buffer + (1024 * i))) + { + buffer = i; + break; + } + } assert(buffer >= 0 && - "Trying to free something that is not an emergency buffer!"); - // emergency_malloc() is expected to return 0-initialized data. We don't - // zero the buffer when allocating it, because the static buffers will - // begin life containing 0 values. - memset(ptr, 0, 1024); - // Signal the condition variable to wake up any threads that are blocking - // waiting for some space in the emergency buffer - pthread_mutex_lock(&emergency_malloc_lock); - // In theory, we don't need to do this with the lock held. In practice, - // our array of bools will probably be updated using 32-bit or 64-bit - // memory operations, so this update may clobber adjacent values. - buffer_allocated[buffer] = false; - pthread_cond_signal(&emergency_malloc_wait); - pthread_mutex_unlock(&emergency_malloc_lock); -} - -static char *alloc_or_die(size_t size) -{ - char *buffer = static_cast<char*>(calloc(1, size)); - - // If calloc() doesn't want to give us any memory, try using an emergency - // buffer. - if (0 == buffer) - { - buffer = emergency_malloc(size); - // This is only reached if the allocation is greater than 1KB, and + "Trying to free something that is not an emergency buffer!"); + // emergency_malloc() is expected to return 0-initialized data. We don't + // zero the buffer when allocating it, because the static buffers will + // begin life containing 0 values. + memset(ptr, 0, 1024); + // Signal the condition variable to wake up any threads that are blocking + // waiting for some space in the emergency buffer + pthread_mutex_lock(&emergency_malloc_lock); + // In theory, we don't need to do this with the lock held. In practice, + // our array of bools will probably be updated using 32-bit or 64-bit + // memory operations, so this update may clobber adjacent values. + buffer_allocated[buffer] = false; + pthread_cond_signal(&emergency_malloc_wait); + pthread_mutex_unlock(&emergency_malloc_lock); +} + +static char *alloc_or_die(size_t size) +{ + char *buffer = static_cast<char*>(calloc(1, size)); + + // If calloc() doesn't want to give us any memory, try using an emergency + // buffer. + if (0 == buffer) + { + buffer = emergency_malloc(size); + // This is only reached if the allocation is greater than 1KB, and // anyone throwing objects that big really should know better. - if (0 == buffer) - { - fprintf(stderr, "Out of memory attempting to allocate exception\n"); - std::terminate(); - } - } - return buffer; -} -static void free_exception(char *e) -{ - // If this allocation is within the address range of the emergency buffer, - // don't call free() because it was not allocated with malloc() + if (0 == buffer) + { + fprintf(stderr, "Out of memory attempting to allocate exception\n"); + std::terminate(); + } + } + return buffer; +} +static void free_exception(char *e) +{ + // If this allocation is within the address range of the emergency buffer, + // don't call free() because it was not allocated with malloc() if ((e >= emergency_buffer) && - (e < (emergency_buffer + sizeof(emergency_buffer)))) - { - emergency_malloc_free(e); - } - else - { - free(e); - } -} - + (e < (emergency_buffer + sizeof(emergency_buffer)))) + { + emergency_malloc_free(e); + } + else + { + free(e); + } +} + static constexpr size_t align_to(size_t size, size_t alignment) noexcept { return (size + alignment - 1) / alignment * alignment; } @@ -672,112 +672,112 @@ 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 - * emergency buffer if malloc() fails, and may block if there are no such - * buffers available. - */ -extern "C" void *__cxa_allocate_exception(size_t thrown_size) -{ +/** + * 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 + * emergency buffer if malloc() fails, and may block if there are no such + * buffers available. + */ +extern "C" void *__cxa_allocate_exception(size_t thrown_size) +{ size_t size = thrown_size + exception_size + backtrace_buffer_size; - char *buffer = alloc_or_die(size); + char *buffer = alloc_or_die(size); #ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE ((_Unwind_Backtrace_Buffer *)buffer)->size = 0; #endif return buffer + exception_size + backtrace_buffer_size; -} - -extern "C" void *__cxa_allocate_dependent_exception(void) -{ +} + +extern "C" void *__cxa_allocate_dependent_exception(void) +{ size_t size = dependent_exception_size + backtrace_buffer_size; - char *buffer = alloc_or_die(size); + char *buffer = alloc_or_die(size); return buffer + dependent_exception_size + backtrace_buffer_size; -} - -/** - * __cxa_free_exception() is called when an exception was thrown in between - * calling __cxa_allocate_exception() and actually throwing the exception. - * This happens when the object's copy constructor throws an exception. - * - * In this implementation, it is also called by __cxa_end_catch() and during - * thread cleanup. - */ -extern "C" void __cxa_free_exception(void *thrown_exception) -{ - __cxa_exception *ex = reinterpret_cast<__cxa_exception*>(thrown_exception) - 1; - // Free the object that was thrown, calling its destructor - if (0 != ex->exceptionDestructor) - { - try - { - ex->exceptionDestructor(thrown_exception); - } - catch(...) - { - // FIXME: Check that this is really what the spec says to do. - std::terminate(); - } - } - +} + +/** + * __cxa_free_exception() is called when an exception was thrown in between + * calling __cxa_allocate_exception() and actually throwing the exception. + * This happens when the object's copy constructor throws an exception. + * + * In this implementation, it is also called by __cxa_end_catch() and during + * thread cleanup. + */ +extern "C" void __cxa_free_exception(void *thrown_exception) +{ + __cxa_exception *ex = reinterpret_cast<__cxa_exception*>(thrown_exception) - 1; + // Free the object that was thrown, calling its destructor + if (0 != ex->exceptionDestructor) + { + try + { + ex->exceptionDestructor(thrown_exception); + } + catch(...) + { + // FIXME: Check that this is really what the spec says to do. + std::terminate(); + } + } + free_exception( reinterpret_cast<char*>(thrown_exception) - exception_size - backtrace_buffer_size); -} - -static void releaseException(__cxa_exception *exception) -{ - if (isDependentException(exception->unwindHeader.exception_class)) - { - __cxa_free_dependent_exception(exception+1); - return; - } - if (__sync_sub_and_fetch(&exception->referenceCount, 1) == 0) - { - // __cxa_free_exception() expects to be passed the thrown object, - // which immediately follows the exception, not the exception - // itself - __cxa_free_exception(exception+1); - } -} - -void __cxa_free_dependent_exception(void *thrown_exception) -{ - __cxa_dependent_exception *ex = reinterpret_cast<__cxa_dependent_exception*>(thrown_exception) - 1; - assert(isDependentException(ex->unwindHeader.exception_class)); - if (ex->primaryException) - { - releaseException(realExceptionFromException(reinterpret_cast<__cxa_exception*>(ex))); - } +} + +static void releaseException(__cxa_exception *exception) +{ + if (isDependentException(exception->unwindHeader.exception_class)) + { + __cxa_free_dependent_exception(exception+1); + return; + } + if (__sync_sub_and_fetch(&exception->referenceCount, 1) == 0) + { + // __cxa_free_exception() expects to be passed the thrown object, + // which immediately follows the exception, not the exception + // itself + __cxa_free_exception(exception+1); + } +} + +void __cxa_free_dependent_exception(void *thrown_exception) +{ + __cxa_dependent_exception *ex = reinterpret_cast<__cxa_dependent_exception*>(thrown_exception) - 1; + assert(isDependentException(ex->unwindHeader.exception_class)); + if (ex->primaryException) + { + releaseException(realExceptionFromException(reinterpret_cast<__cxa_exception*>(ex))); + } free_exception(reinterpret_cast<char*>(thrown_exception) - dependent_exception_size - backtrace_buffer_size); -} - -/** - * Report a failure that occurred when attempting to throw an exception. - * - * If the failure happened by falling off the end of the stack without finding - * a handler, prints a back trace before aborting. - */ -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +} + +/** + * Report a failure that occurred when attempting to throw an exception. + * + * If the failure happened by falling off the end of the stack without finding + * a handler, prints a back trace before aborting. + */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) extern "C" void *__cxa_begin_catch(void *e) noexcept; -#else -extern "C" void *__cxa_begin_catch(void *e); -#endif -static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exception) -{ - switch (err) - { - default: break; - case _URC_FATAL_PHASE1_ERROR: - fprintf(stderr, "Fatal error during phase 1 unwinding\n"); - break; -#if !defined(__arm__) || defined(__ARM_DWARF_EH__) - case _URC_FATAL_PHASE2_ERROR: - fprintf(stderr, "Fatal error during phase 2 unwinding\n"); - break; -#endif - case _URC_END_OF_STACK: - __cxa_begin_catch (&(thrown_exception->unwindHeader)); - std::terminate(); +#else +extern "C" void *__cxa_begin_catch(void *e); +#endif +static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exception) +{ + switch (err) + { + default: break; + case _URC_FATAL_PHASE1_ERROR: + fprintf(stderr, "Fatal error during phase 1 unwinding\n"); + break; +#if !defined(__arm__) || defined(__ARM_DWARF_EH__) + case _URC_FATAL_PHASE2_ERROR: + fprintf(stderr, "Fatal error during phase 2 unwinding\n"); + break; +#endif + case _URC_END_OF_STACK: + __cxa_begin_catch (&(thrown_exception->unwindHeader)); + std::terminate(); fprintf(stderr, "uncaught exception:\n address -> %p\n", static_cast<void*>(thrown_exception)); thrown_exception = realExceptionFromException(thrown_exception); @@ -808,108 +808,108 @@ static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exce // TODO: Make this optional _Unwind_Backtrace(trace, 0); - // Just abort. No need to call std::terminate for the second time - abort(); - break; - } - std::terminate(); -} - -static void throw_exception(__cxa_exception *ex) -{ - __cxa_thread_info *info = thread_info(); - ex->unexpectedHandler = info->unexpectedHandler; - if (0 == ex->unexpectedHandler) - { - ex->unexpectedHandler = unexpectedHandler; - } - ex->terminateHandler = info->terminateHandler; - if (0 == ex->terminateHandler) - { - ex->terminateHandler = terminateHandler; - } - info->globals.uncaughtExceptions++; - - _Unwind_Reason_Code err = _Unwind_RaiseException(&ex->unwindHeader); - // The _Unwind_RaiseException() function should not return, it should - // unwind the stack past this function. If it does return, then something - // has gone wrong. - report_failure(err, ex); -} - + // Just abort. No need to call std::terminate for the second time + abort(); + break; + } + std::terminate(); +} + +static void throw_exception(__cxa_exception *ex) +{ + __cxa_thread_info *info = thread_info(); + ex->unexpectedHandler = info->unexpectedHandler; + if (0 == ex->unexpectedHandler) + { + ex->unexpectedHandler = unexpectedHandler; + } + ex->terminateHandler = info->terminateHandler; + if (0 == ex->terminateHandler) + { + ex->terminateHandler = terminateHandler; + } + info->globals.uncaughtExceptions++; + + _Unwind_Reason_Code err = _Unwind_RaiseException(&ex->unwindHeader); + // The _Unwind_RaiseException() function should not return, it should + // unwind the stack past this function. If it does return, then something + // has gone wrong. + report_failure(err, ex); +} + typedef void (*cxa_throw_hook_t)(void*, std::type_info*, void(*)(void*)) noexcept; - + __attribute__((weak)) cxa_throw_hook_t cxa_throw_hook = nullptr; -/** - * ABI function for throwing an exception. Takes the object to be thrown (the - * pointer returned by __cxa_allocate_exception()), the type info for the - * pointee, and the destructor (if there is one) as arguments. - */ -extern "C" void __cxa_throw(void *thrown_exception, - std::type_info *tinfo, - void(*dest)(void*)) -{ +/** + * ABI function for throwing an exception. Takes the object to be thrown (the + * pointer returned by __cxa_allocate_exception()), the type info for the + * pointee, and the destructor (if there is one) as arguments. + */ +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; - - ex->referenceCount = 1; - ex->exceptionType = tinfo; + __cxa_exception *ex = reinterpret_cast<__cxa_exception*>(thrown_exception) - 1; + + ex->referenceCount = 1; + ex->exceptionType = tinfo; - ex->exceptionDestructor = dest; + ex->exceptionDestructor = dest; - ex->unwindHeader.exception_class = exception_class; - ex->unwindHeader.exception_cleanup = exception_cleanup; - - throw_exception(ex); -} - -extern "C" void __cxa_rethrow_primary_exception(void* thrown_exception) -{ - if (NULL == thrown_exception) { return; } - - __cxa_exception *original = exceptionFromPointer(thrown_exception); - __cxa_dependent_exception *ex = reinterpret_cast<__cxa_dependent_exception*>(__cxa_allocate_dependent_exception())-1; - - ex->primaryException = thrown_exception; - __cxa_increment_exception_refcount(thrown_exception); - - ex->exceptionType = original->exceptionType; - ex->unwindHeader.exception_class = dependent_exception_class; - ex->unwindHeader.exception_cleanup = dependent_exception_cleanup; - - throw_exception(reinterpret_cast<__cxa_exception*>(ex)); -} - -extern "C" void *__cxa_current_primary_exception(void) -{ - __cxa_eh_globals* globals = __cxa_get_globals(); - __cxa_exception *ex = globals->caughtExceptions; - - if (0 == ex) { return NULL; } - ex = realExceptionFromException(ex); - __sync_fetch_and_add(&ex->referenceCount, 1); - return ex + 1; -} - -extern "C" void __cxa_increment_exception_refcount(void* thrown_exception) -{ - if (NULL == thrown_exception) { return; } - __cxa_exception *ex = static_cast<__cxa_exception*>(thrown_exception) - 1; - if (isDependentException(ex->unwindHeader.exception_class)) { return; } - __sync_fetch_and_add(&ex->referenceCount, 1); -} -extern "C" void __cxa_decrement_exception_refcount(void* thrown_exception) -{ - if (NULL == thrown_exception) { return; } - __cxa_exception *ex = static_cast<__cxa_exception*>(thrown_exception) - 1; - releaseException(ex); -} - + ex->unwindHeader.exception_class = exception_class; + ex->unwindHeader.exception_cleanup = exception_cleanup; + + throw_exception(ex); +} + +extern "C" void __cxa_rethrow_primary_exception(void* thrown_exception) +{ + if (NULL == thrown_exception) { return; } + + __cxa_exception *original = exceptionFromPointer(thrown_exception); + __cxa_dependent_exception *ex = reinterpret_cast<__cxa_dependent_exception*>(__cxa_allocate_dependent_exception())-1; + + ex->primaryException = thrown_exception; + __cxa_increment_exception_refcount(thrown_exception); + + ex->exceptionType = original->exceptionType; + ex->unwindHeader.exception_class = dependent_exception_class; + ex->unwindHeader.exception_cleanup = dependent_exception_cleanup; + + throw_exception(reinterpret_cast<__cxa_exception*>(ex)); +} + +extern "C" void *__cxa_current_primary_exception(void) +{ + __cxa_eh_globals* globals = __cxa_get_globals(); + __cxa_exception *ex = globals->caughtExceptions; + + if (0 == ex) { return NULL; } + ex = realExceptionFromException(ex); + __sync_fetch_and_add(&ex->referenceCount, 1); + return ex + 1; +} + +extern "C" void __cxa_increment_exception_refcount(void* thrown_exception) +{ + if (NULL == thrown_exception) { return; } + __cxa_exception *ex = static_cast<__cxa_exception*>(thrown_exception) - 1; + if (isDependentException(ex->unwindHeader.exception_class)) { return; } + __sync_fetch_and_add(&ex->referenceCount, 1); +} +extern "C" void __cxa_decrement_exception_refcount(void* thrown_exception) +{ + if (NULL == thrown_exception) { return; } + __cxa_exception *ex = static_cast<__cxa_exception*>(thrown_exception) - 1; + releaseException(ex); +} + #ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE static size_t __cxa_collect_backtrace(__cxa_exception* ex, void** dest, size_t size) { if (!ex) { @@ -936,42 +936,42 @@ extern "C" size_t __cxa_collect_current_exception_backtrace(void** dest, size_t } #endif -/** - * ABI function. Rethrows the current exception. Does not remove the - * exception from the stack or decrement its handler count - the compiler is - * expected to set the landing pad for this function to the end of the catch - * block, and then call _Unwind_Resume() to continue unwinding once - * __cxa_end_catch() has been called and any cleanup code has been run. - */ -extern "C" void __cxa_rethrow() -{ - __cxa_thread_info *ti = thread_info(); - __cxa_eh_globals *globals = &ti->globals; - // Note: We don't remove this from the caught list here, because - // __cxa_end_catch will be called when we unwind out of the try block. We - // could probably make this faster by providing an alternative rethrow - // function and ensuring that all cleanup code is run before calling it, so - // we can skip the top stack frame when unwinding. - __cxa_exception *ex = globals->caughtExceptions; - - if (0 == ex) - { - fprintf(stderr, - "Attempting to rethrow an exception that doesn't exist!\n"); - std::terminate(); - } - - if (ti->foreign_exception_state != __cxa_thread_info::none) - { - ti->foreign_exception_state = __cxa_thread_info::rethrown; - _Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(ex); - _Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(e); - report_failure(err, ex); - return; - } - - assert(ex->handlerCount > 0 && "Rethrowing uncaught exception!"); - +/** + * ABI function. Rethrows the current exception. Does not remove the + * exception from the stack or decrement its handler count - the compiler is + * expected to set the landing pad for this function to the end of the catch + * block, and then call _Unwind_Resume() to continue unwinding once + * __cxa_end_catch() has been called and any cleanup code has been run. + */ +extern "C" void __cxa_rethrow() +{ + __cxa_thread_info *ti = thread_info(); + __cxa_eh_globals *globals = &ti->globals; + // Note: We don't remove this from the caught list here, because + // __cxa_end_catch will be called when we unwind out of the try block. We + // could probably make this faster by providing an alternative rethrow + // function and ensuring that all cleanup code is run before calling it, so + // we can skip the top stack frame when unwinding. + __cxa_exception *ex = globals->caughtExceptions; + + if (0 == ex) + { + fprintf(stderr, + "Attempting to rethrow an exception that doesn't exist!\n"); + std::terminate(); + } + + if (ti->foreign_exception_state != __cxa_thread_info::none) + { + ti->foreign_exception_state = __cxa_thread_info::rethrown; + _Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(ex); + _Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(e); + report_failure(err, ex); + return; + } + + assert(ex->handlerCount > 0 && "Rethrowing uncaught exception!"); + // `globals->uncaughtExceptions` was decremented by `__cxa_begin_catch`. // It's normally incremented by `throw_exception`, but this path invokes // `_Unwind_Resume_or_Rethrow` directly to rethrow the exception. @@ -979,202 +979,202 @@ extern "C" void __cxa_rethrow() // foreign exceptions don't adjust any of this state. globals->uncaughtExceptions++; - // ex->handlerCount will be decremented in __cxa_end_catch in enclosing - // catch block + // ex->handlerCount will be decremented in __cxa_end_catch in enclosing + // catch block - // Make handler count negative. This will tell __cxa_end_catch that - // exception was rethrown and exception object should not be destroyed - // when handler count become zero - ex->handlerCount = -ex->handlerCount; - - // Continue unwinding the stack with this exception. This should unwind to - // the place in the caller where __cxa_end_catch() is called. The caller - // will then run cleanup code and bounce the exception back with - // _Unwind_Resume(). - _Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(&ex->unwindHeader); - report_failure(err, ex); -} - -/** - * Returns the type_info object corresponding to the filter. - */ -static std::type_info *get_type_info_entry(_Unwind_Context *context, - dwarf_eh_lsda *lsda, - int filter) -{ - // Get the address of the record in the table. + // Make handler count negative. This will tell __cxa_end_catch that + // exception was rethrown and exception object should not be destroyed + // when handler count become zero + ex->handlerCount = -ex->handlerCount; + + // Continue unwinding the stack with this exception. This should unwind to + // the place in the caller where __cxa_end_catch() is called. The caller + // will then run cleanup code and bounce the exception back with + // _Unwind_Resume(). + _Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(&ex->unwindHeader); + report_failure(err, ex); +} + +/** + * Returns the type_info object corresponding to the filter. + */ +static std::type_info *get_type_info_entry(_Unwind_Context *context, + dwarf_eh_lsda *lsda, + int filter) +{ + // Get the address of the record in the table. dw_eh_ptr_t record = lsda->type_table - - dwarf_size_of_fixed_size_field(lsda->type_table_encoding)*filter; - //record -= 4; - dw_eh_ptr_t start = record; - // Read the value, but it's probably an indirect reference... - int64_t offset = read_value(lsda->type_table_encoding, &record); - - // (If the entry is 0, don't try to dereference it. That would be bad.) - if (offset == 0) { return 0; } - - // ...so we need to resolve it - return reinterpret_cast<std::type_info*>(resolve_indirect_value(context, - lsda->type_table_encoding, offset, start)); -} - - - -/** - * Checks the type signature found in a handler against the type of the thrown - * object. If ex is 0 then it is assumed to be a foreign exception and only - * matches cleanups. - */ -static bool check_type_signature(__cxa_exception *ex, - const std::type_info *type, - void *&adjustedPtr) -{ - void *exception_ptr = static_cast<void*>(ex+1); - const std::type_info *ex_type = ex ? ex->exceptionType : 0; - - bool is_ptr = ex ? ex_type->__is_pointer_p() : false; - if (is_ptr) - { - exception_ptr = *static_cast<void**>(exception_ptr); - } - // Always match a catchall, even with a foreign exception - // - // Note: A 0 here is a catchall, not a cleanup, so we return true to - // indicate that we found a catch. - if (0 == type) - { - if (ex) - { - adjustedPtr = exception_ptr; - } - return true; - } - - if (0 == ex) { return false; } - - // If the types are the same, no casting is needed. - if (*type == *ex_type) - { - adjustedPtr = exception_ptr; - return true; - } - - - if (type->__do_catch(ex_type, &exception_ptr, 1)) - { - adjustedPtr = exception_ptr; - return true; - } - - return false; -} -/** - * Checks whether the exception matches the type specifiers in this action - * record. If the exception only matches cleanups, then this returns false. - * If it matches a catch (including a catchall) then it returns true. - * - * The selector argument is used to return the selector that is passed in the - * second exception register when installing the context. - */ -static handler_type check_action_record(_Unwind_Context *context, - dwarf_eh_lsda *lsda, - dw_eh_ptr_t action_record, - __cxa_exception *ex, - unsigned long *selector, - void *&adjustedPtr) -{ - if (!action_record) { return handler_cleanup; } - handler_type found = handler_none; - while (action_record) - { - int filter = read_sleb128(&action_record); - dw_eh_ptr_t action_record_offset_base = action_record; - int displacement = read_sleb128(&action_record); + dwarf_size_of_fixed_size_field(lsda->type_table_encoding)*filter; + //record -= 4; + dw_eh_ptr_t start = record; + // Read the value, but it's probably an indirect reference... + int64_t offset = read_value(lsda->type_table_encoding, &record); + + // (If the entry is 0, don't try to dereference it. That would be bad.) + if (offset == 0) { return 0; } + + // ...so we need to resolve it + return reinterpret_cast<std::type_info*>(resolve_indirect_value(context, + lsda->type_table_encoding, offset, start)); +} + + + +/** + * Checks the type signature found in a handler against the type of the thrown + * object. If ex is 0 then it is assumed to be a foreign exception and only + * matches cleanups. + */ +static bool check_type_signature(__cxa_exception *ex, + const std::type_info *type, + void *&adjustedPtr) +{ + void *exception_ptr = static_cast<void*>(ex+1); + const std::type_info *ex_type = ex ? ex->exceptionType : 0; + + bool is_ptr = ex ? ex_type->__is_pointer_p() : false; + if (is_ptr) + { + exception_ptr = *static_cast<void**>(exception_ptr); + } + // Always match a catchall, even with a foreign exception + // + // Note: A 0 here is a catchall, not a cleanup, so we return true to + // indicate that we found a catch. + if (0 == type) + { + if (ex) + { + adjustedPtr = exception_ptr; + } + return true; + } + + if (0 == ex) { return false; } + + // If the types are the same, no casting is needed. + if (*type == *ex_type) + { + adjustedPtr = exception_ptr; + return true; + } + + + if (type->__do_catch(ex_type, &exception_ptr, 1)) + { + adjustedPtr = exception_ptr; + return true; + } + + return false; +} +/** + * Checks whether the exception matches the type specifiers in this action + * record. If the exception only matches cleanups, then this returns false. + * If it matches a catch (including a catchall) then it returns true. + * + * The selector argument is used to return the selector that is passed in the + * second exception register when installing the context. + */ +static handler_type check_action_record(_Unwind_Context *context, + dwarf_eh_lsda *lsda, + dw_eh_ptr_t action_record, + __cxa_exception *ex, + unsigned long *selector, + void *&adjustedPtr) +{ + if (!action_record) { return handler_cleanup; } + handler_type found = handler_none; + while (action_record) + { + int filter = read_sleb128(&action_record); + dw_eh_ptr_t action_record_offset_base = action_record; + int displacement = read_sleb128(&action_record); action_record = displacement ? - action_record_offset_base + displacement : 0; - // We only check handler types for C++ exceptions - foreign exceptions - // are only allowed for cleanups and catchalls. - if (filter > 0) - { - std::type_info *handler_type = get_type_info_entry(context, lsda, filter); - if (check_type_signature(ex, handler_type, adjustedPtr)) - { - *selector = filter; - return handler_catch; - } - } - else if (filter < 0 && 0 != ex) - { - bool matched = false; - *selector = filter; -#if defined(__arm__) && !defined(__ARM_DWARF_EH__) - filter++; - std::type_info *handler_type = get_type_info_entry(context, lsda, filter--); - while (handler_type) - { - if (check_type_signature(ex, handler_type, adjustedPtr)) - { - matched = true; - break; - } - handler_type = get_type_info_entry(context, lsda, filter--); - } -#else - unsigned char *type_index = reinterpret_cast<unsigned char*>(lsda->type_table) - filter - 1; - while (*type_index) - { - std::type_info *handler_type = get_type_info_entry(context, lsda, *(type_index++)); - // If the exception spec matches a permitted throw type for - // this function, don't report a handler - we are allowed to - // propagate this exception out. - if (check_type_signature(ex, handler_type, adjustedPtr)) - { - matched = true; - break; - } - } -#endif - if (matched) { continue; } - // If we don't find an allowed exception spec, we need to install - // the context for this action. The landing pad will then call the - // unexpected exception function. Treat this as a catch - return handler_catch; - } - else if (filter == 0) - { - *selector = filter; - found = handler_cleanup; - } - } - return found; -} - -static void pushCleanupException(_Unwind_Exception *exceptionObject, - __cxa_exception *ex) -{ -#if defined(__arm__) && !defined(__ARM_DWARF_EH__) - __cxa_thread_info *info = thread_info_fast(); - if (ex) - { - ex->cleanupCount++; - if (ex->cleanupCount > 1) - { - assert(exceptionObject == info->currentCleanup); - return; - } - ex->nextCleanup = info->currentCleanup; - } - info->currentCleanup = exceptionObject; -#endif -} - -/** - * The exception personality function. This is referenced in the unwinding - * DWARF metadata and is called by the unwind library for each C++ stack frame - * containing catch or cleanup code. - */ -extern "C" -BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0) + action_record_offset_base + displacement : 0; + // We only check handler types for C++ exceptions - foreign exceptions + // are only allowed for cleanups and catchalls. + if (filter > 0) + { + std::type_info *handler_type = get_type_info_entry(context, lsda, filter); + if (check_type_signature(ex, handler_type, adjustedPtr)) + { + *selector = filter; + return handler_catch; + } + } + else if (filter < 0 && 0 != ex) + { + bool matched = false; + *selector = filter; +#if defined(__arm__) && !defined(__ARM_DWARF_EH__) + filter++; + std::type_info *handler_type = get_type_info_entry(context, lsda, filter--); + while (handler_type) + { + if (check_type_signature(ex, handler_type, adjustedPtr)) + { + matched = true; + break; + } + handler_type = get_type_info_entry(context, lsda, filter--); + } +#else + unsigned char *type_index = reinterpret_cast<unsigned char*>(lsda->type_table) - filter - 1; + while (*type_index) + { + std::type_info *handler_type = get_type_info_entry(context, lsda, *(type_index++)); + // If the exception spec matches a permitted throw type for + // this function, don't report a handler - we are allowed to + // propagate this exception out. + if (check_type_signature(ex, handler_type, adjustedPtr)) + { + matched = true; + break; + } + } +#endif + if (matched) { continue; } + // If we don't find an allowed exception spec, we need to install + // the context for this action. The landing pad will then call the + // unexpected exception function. Treat this as a catch + return handler_catch; + } + else if (filter == 0) + { + *selector = filter; + found = handler_cleanup; + } + } + return found; +} + +static void pushCleanupException(_Unwind_Exception *exceptionObject, + __cxa_exception *ex) +{ +#if defined(__arm__) && !defined(__ARM_DWARF_EH__) + __cxa_thread_info *info = thread_info_fast(); + if (ex) + { + ex->cleanupCount++; + if (ex->cleanupCount > 1) + { + assert(exceptionObject == info->currentCleanup); + return; + } + ex->nextCleanup = info->currentCleanup; + } + info->currentCleanup = exceptionObject; +#endif +} + +/** + * The exception personality function. This is referenced in the unwinding + * DWARF metadata and is called by the unwind library for each C++ stack frame + * containing catch or cleanup code. + */ +extern "C" +BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0) #if defined(__SANITIZE_MEMORY__) __msan_unpoison(&version, sizeof(version)); __msan_unpoison(&actions, sizeof(actions)); @@ -1182,298 +1182,298 @@ BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0) __msan_unpoison(&exceptionObject, sizeof(exceptionObject)); __msan_unpoison(&context, sizeof(context)); #endif - // This personality function is for version 1 of the ABI. If you use it - // with a future version of the ABI, it won't know what to do, so it - // reports a fatal error and give up before it breaks anything. - if (1 != version) - { - return _URC_FATAL_PHASE1_ERROR; - } - __cxa_exception *ex = 0; - __cxa_exception *realEx = 0; - - // If this exception is throw by something else then we can't make any - // assumptions about its layout beyond the fields declared in - // _Unwind_Exception. - bool foreignException = !isCXXException(exceptionClass); - - // If this isn't a foreign exception, then we have a C++ exception structure - if (!foreignException) - { - ex = exceptionFromPointer(exceptionObject); - realEx = realExceptionFromException(ex); - } - -#if defined(__arm__) && !defined(__ARM_DWARF_EH__) - unsigned char *lsda_addr = - static_cast<unsigned char*>(_Unwind_GetLanguageSpecificData(context)); -#else - unsigned char *lsda_addr = - reinterpret_cast<unsigned char*>(static_cast<uintptr_t>(_Unwind_GetLanguageSpecificData(context))); -#endif - - // No LSDA implies no landing pads - try the next frame - if (0 == lsda_addr) { return continueUnwinding(exceptionObject, context); } - - // These two variables define how the exception will be handled. - dwarf_eh_action action = {0}; - unsigned long selector = 0; + // This personality function is for version 1 of the ABI. If you use it + // with a future version of the ABI, it won't know what to do, so it + // reports a fatal error and give up before it breaks anything. + if (1 != version) + { + return _URC_FATAL_PHASE1_ERROR; + } + __cxa_exception *ex = 0; + __cxa_exception *realEx = 0; + + // If this exception is throw by something else then we can't make any + // assumptions about its layout beyond the fields declared in + // _Unwind_Exception. + bool foreignException = !isCXXException(exceptionClass); + + // If this isn't a foreign exception, then we have a C++ exception structure + if (!foreignException) + { + ex = exceptionFromPointer(exceptionObject); + realEx = realExceptionFromException(ex); + } + +#if defined(__arm__) && !defined(__ARM_DWARF_EH__) + unsigned char *lsda_addr = + static_cast<unsigned char*>(_Unwind_GetLanguageSpecificData(context)); +#else + unsigned char *lsda_addr = + reinterpret_cast<unsigned char*>(static_cast<uintptr_t>(_Unwind_GetLanguageSpecificData(context))); +#endif + + // No LSDA implies no landing pads - try the next frame + if (0 == lsda_addr) { return continueUnwinding(exceptionObject, context); } + + // These two variables define how the exception will be handled. + dwarf_eh_action action = {0}; + unsigned long selector = 0; - // During the search phase, we do a complete lookup. If we return - // _URC_HANDLER_FOUND, then the phase 2 unwind will call this function with - // a _UA_HANDLER_FRAME action, telling us to install the handler frame. If - // we return _URC_CONTINUE_UNWIND, we may be called again later with a - // _UA_CLEANUP_PHASE action for this frame. - // - // The point of the two-stage unwind allows us to entirely avoid any stack - // unwinding if there is no handler. If there are just cleanups found, - // then we can just panic call an abort function. - // - // Matching a handler is much more expensive than matching a cleanup, - // because we don't need to bother doing type comparisons (or looking at - // the type table at all) for a cleanup. This means that there is no need - // to cache the result of finding a cleanup, because it's (quite) quick to - // look it up again from the action table. - if (actions & _UA_SEARCH_PHASE) - { - struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); - - if (!dwarf_eh_find_callsite(context, &lsda, &action)) - { - // EH range not found. This happens if exception is thrown and not - // caught inside a cleanup (destructor). We should call - // terminate() in this case. The catchTemp (landing pad) field of - // exception object will contain null when personality function is + // During the search phase, we do a complete lookup. If we return + // _URC_HANDLER_FOUND, then the phase 2 unwind will call this function with + // a _UA_HANDLER_FRAME action, telling us to install the handler frame. If + // we return _URC_CONTINUE_UNWIND, we may be called again later with a + // _UA_CLEANUP_PHASE action for this frame. + // + // The point of the two-stage unwind allows us to entirely avoid any stack + // unwinding if there is no handler. If there are just cleanups found, + // then we can just panic call an abort function. + // + // Matching a handler is much more expensive than matching a cleanup, + // because we don't need to bother doing type comparisons (or looking at + // the type table at all) for a cleanup. This means that there is no need + // to cache the result of finding a cleanup, because it's (quite) quick to + // look it up again from the action table. + if (actions & _UA_SEARCH_PHASE) + { + struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); + + if (!dwarf_eh_find_callsite(context, &lsda, &action)) + { + // EH range not found. This happens if exception is thrown and not + // caught inside a cleanup (destructor). We should call + // terminate() in this case. The catchTemp (landing pad) field of + // exception object will contain null when personality function is // called with _UA_HANDLER_FRAME action for phase 2 unwinding. - return _URC_HANDLER_FOUND; - } - - handler_type found_handler = check_action_record(context, &lsda, - action.action_record, realEx, &selector, ex->adjustedPtr); - // If there's no action record, we've only found a cleanup, so keep - // searching for something real - if (found_handler == handler_catch) - { - // Cache the results for the phase 2 unwind, if we found a handler - // and this is not a foreign exception. - if (ex) - { - saveLandingPad(context, exceptionObject, ex, selector, action.landing_pad); - ex->languageSpecificData = reinterpret_cast<const char*>(lsda_addr); - ex->actionRecord = reinterpret_cast<const char*>(action.action_record); - // ex->adjustedPtr is set when finding the action record. - } - return _URC_HANDLER_FOUND; - } - return continueUnwinding(exceptionObject, context); - } - - - // If this is a foreign exception, we didn't have anywhere to cache the - // lookup stuff, so we need to do it again. If this is either a forced - // unwind, a foreign exception, or a cleanup, then we just install the - // context for a cleanup. - if (!(actions & _UA_HANDLER_FRAME)) - { - // cleanup - struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); - dwarf_eh_find_callsite(context, &lsda, &action); - if (0 == action.landing_pad) { return continueUnwinding(exceptionObject, context); } - handler_type found_handler = check_action_record(context, &lsda, - action.action_record, realEx, &selector, ex->adjustedPtr); - // Ignore handlers this time. - if (found_handler != handler_cleanup) { return continueUnwinding(exceptionObject, context); } - pushCleanupException(exceptionObject, ex); - } - else if (foreignException) - { - struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); - dwarf_eh_find_callsite(context, &lsda, &action); - check_action_record(context, &lsda, action.action_record, realEx, - &selector, ex->adjustedPtr); - } - else if (ex->catchTemp == 0) - { - // Uncaught exception in cleanup, calling terminate - std::terminate(); - } - else - { - // Restore the saved info if we saved some last time. - loadLandingPad(context, exceptionObject, ex, &selector, &action.landing_pad); - ex->catchTemp = 0; - ex->handlerSwitchValue = 0; - } - - - _Unwind_SetIP(context, reinterpret_cast<unsigned long>(action.landing_pad)); - _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), - reinterpret_cast<unsigned long>(exceptionObject)); - _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), selector); - - return _URC_INSTALL_CONTEXT; -} - -/** - * ABI function called when entering a catch statement. The argument is the - * pointer passed out of the personality function. This is always the start of - * the _Unwind_Exception object. The return value for this function is the - * pointer to the caught exception, which is either the adjusted pointer (for - * C++ exceptions) of the unadjusted pointer (for foreign exceptions). - */ -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) + return _URC_HANDLER_FOUND; + } + + handler_type found_handler = check_action_record(context, &lsda, + action.action_record, realEx, &selector, ex->adjustedPtr); + // If there's no action record, we've only found a cleanup, so keep + // searching for something real + if (found_handler == handler_catch) + { + // Cache the results for the phase 2 unwind, if we found a handler + // and this is not a foreign exception. + if (ex) + { + saveLandingPad(context, exceptionObject, ex, selector, action.landing_pad); + ex->languageSpecificData = reinterpret_cast<const char*>(lsda_addr); + ex->actionRecord = reinterpret_cast<const char*>(action.action_record); + // ex->adjustedPtr is set when finding the action record. + } + return _URC_HANDLER_FOUND; + } + return continueUnwinding(exceptionObject, context); + } + + + // If this is a foreign exception, we didn't have anywhere to cache the + // lookup stuff, so we need to do it again. If this is either a forced + // unwind, a foreign exception, or a cleanup, then we just install the + // context for a cleanup. + if (!(actions & _UA_HANDLER_FRAME)) + { + // cleanup + struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); + dwarf_eh_find_callsite(context, &lsda, &action); + if (0 == action.landing_pad) { return continueUnwinding(exceptionObject, context); } + handler_type found_handler = check_action_record(context, &lsda, + action.action_record, realEx, &selector, ex->adjustedPtr); + // Ignore handlers this time. + if (found_handler != handler_cleanup) { return continueUnwinding(exceptionObject, context); } + pushCleanupException(exceptionObject, ex); + } + else if (foreignException) + { + struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); + dwarf_eh_find_callsite(context, &lsda, &action); + check_action_record(context, &lsda, action.action_record, realEx, + &selector, ex->adjustedPtr); + } + else if (ex->catchTemp == 0) + { + // Uncaught exception in cleanup, calling terminate + std::terminate(); + } + else + { + // Restore the saved info if we saved some last time. + loadLandingPad(context, exceptionObject, ex, &selector, &action.landing_pad); + ex->catchTemp = 0; + ex->handlerSwitchValue = 0; + } + + + _Unwind_SetIP(context, reinterpret_cast<unsigned long>(action.landing_pad)); + _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), + reinterpret_cast<unsigned long>(exceptionObject)); + _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), selector); + + return _URC_INSTALL_CONTEXT; +} + +/** + * ABI function called when entering a catch statement. The argument is the + * pointer passed out of the personality function. This is always the start of + * the _Unwind_Exception object. The return value for this function is the + * pointer to the caught exception, which is either the adjusted pointer (for + * C++ exceptions) of the unadjusted pointer (for foreign exceptions). + */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) extern "C" void *__cxa_begin_catch(void *e) noexcept -#else -extern "C" void *__cxa_begin_catch(void *e) -#endif -{ - // We can't call the fast version here, because if the first exception that - // we see is a foreign exception then we won't have called it yet. - __cxa_thread_info *ti = thread_info(); - __cxa_eh_globals *globals = &ti->globals; - _Unwind_Exception *exceptionObject = static_cast<_Unwind_Exception*>(e); - - if (isCXXException(exceptionObject->exception_class)) - { +#else +extern "C" void *__cxa_begin_catch(void *e) +#endif +{ + // We can't call the fast version here, because if the first exception that + // we see is a foreign exception then we won't have called it yet. + __cxa_thread_info *ti = thread_info(); + __cxa_eh_globals *globals = &ti->globals; + _Unwind_Exception *exceptionObject = static_cast<_Unwind_Exception*>(e); + + if (isCXXException(exceptionObject->exception_class)) + { // Only exceptions thrown with a C++ exception throwing function will // increment this, so don't decrement it here. globals->uncaughtExceptions--; - __cxa_exception *ex = exceptionFromPointer(exceptionObject); - - if (ex->handlerCount == 0) - { - // Add this to the front of the list of exceptions being handled - // and increment its handler count so that it won't be deleted - // prematurely. - ex->nextException = globals->caughtExceptions; - globals->caughtExceptions = ex; - } - - if (ex->handlerCount < 0) - { - // Rethrown exception is catched before end of catch block. - // Clear the rethrow flag (make value positive) - we are allowed - // to delete this exception at the end of the catch block, as long - // as it isn't thrown again later. + __cxa_exception *ex = exceptionFromPointer(exceptionObject); + + if (ex->handlerCount == 0) + { + // Add this to the front of the list of exceptions being handled + // and increment its handler count so that it won't be deleted + // prematurely. + ex->nextException = globals->caughtExceptions; + globals->caughtExceptions = ex; + } + + if (ex->handlerCount < 0) + { + // Rethrown exception is catched before end of catch block. + // Clear the rethrow flag (make value positive) - we are allowed + // to delete this exception at the end of the catch block, as long + // as it isn't thrown again later. - // Code pattern: - // - // try { - // throw x; - // } - // catch() { - // try { - // throw; - // } - // catch() { - // __cxa_begin_catch() <- we are here - // } - // } - ex->handlerCount = -ex->handlerCount + 1; - } - else - { - ex->handlerCount++; - } - ti->foreign_exception_state = __cxa_thread_info::none; + // Code pattern: + // + // try { + // throw x; + // } + // catch() { + // try { + // throw; + // } + // catch() { + // __cxa_begin_catch() <- we are here + // } + // } + ex->handlerCount = -ex->handlerCount + 1; + } + else + { + ex->handlerCount++; + } + ti->foreign_exception_state = __cxa_thread_info::none; - return ex->adjustedPtr; - } - else - { - // If this is a foreign exception, then we need to be able to - // store it. We can't chain foreign exceptions, so we give up - // if there are already some outstanding ones. - if (globals->caughtExceptions != 0) - { - std::terminate(); - } - globals->caughtExceptions = reinterpret_cast<__cxa_exception*>(exceptionObject); - ti->foreign_exception_state = __cxa_thread_info::caught; - } - // exceptionObject is the pointer to the _Unwind_Exception within the - // __cxa_exception. The throw object is after this - return (reinterpret_cast<char*>(exceptionObject) + sizeof(_Unwind_Exception)); -} - - - -/** - * ABI function called when exiting a catch block. This will free the current - * exception if it is no longer referenced in other catch blocks. - */ -extern "C" void __cxa_end_catch() -{ - // We can call the fast version here because the slow version is called in - // __cxa_throw(), which must have been called before we end a catch block - __cxa_thread_info *ti = thread_info_fast(); - __cxa_eh_globals *globals = &ti->globals; - __cxa_exception *ex = globals->caughtExceptions; - - assert(0 != ex && "Ending catch when no exception is on the stack!"); + return ex->adjustedPtr; + } + else + { + // If this is a foreign exception, then we need to be able to + // store it. We can't chain foreign exceptions, so we give up + // if there are already some outstanding ones. + if (globals->caughtExceptions != 0) + { + std::terminate(); + } + globals->caughtExceptions = reinterpret_cast<__cxa_exception*>(exceptionObject); + ti->foreign_exception_state = __cxa_thread_info::caught; + } + // exceptionObject is the pointer to the _Unwind_Exception within the + // __cxa_exception. The throw object is after this + return (reinterpret_cast<char*>(exceptionObject) + sizeof(_Unwind_Exception)); +} + + + +/** + * ABI function called when exiting a catch block. This will free the current + * exception if it is no longer referenced in other catch blocks. + */ +extern "C" void __cxa_end_catch() +{ + // We can call the fast version here because the slow version is called in + // __cxa_throw(), which must have been called before we end a catch block + __cxa_thread_info *ti = thread_info_fast(); + __cxa_eh_globals *globals = &ti->globals; + __cxa_exception *ex = globals->caughtExceptions; + + assert(0 != ex && "Ending catch when no exception is on the stack!"); - if (ti->foreign_exception_state != __cxa_thread_info::none) - { - if (ti->foreign_exception_state != __cxa_thread_info::rethrown) - { - _Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(ti->globals.caughtExceptions); + if (ti->foreign_exception_state != __cxa_thread_info::none) + { + if (ti->foreign_exception_state != __cxa_thread_info::rethrown) + { + _Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(ti->globals.caughtExceptions); if (e->exception_cleanup) e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e); - } + } globals->caughtExceptions = 0; - ti->foreign_exception_state = __cxa_thread_info::none; - return; - } - - bool deleteException = true; - - if (ex->handlerCount < 0) - { - // exception was rethrown. Exception should not be deleted even if - // handlerCount become zero. - // Code pattern: - // try { - // throw x; - // } - // catch() { - // { - // throw; - // } - // cleanup { - // __cxa_end_catch(); <- we are here - // } - // } - // + ti->foreign_exception_state = __cxa_thread_info::none; + return; + } + + bool deleteException = true; + + if (ex->handlerCount < 0) + { + // exception was rethrown. Exception should not be deleted even if + // handlerCount become zero. + // Code pattern: + // try { + // throw x; + // } + // catch() { + // { + // throw; + // } + // cleanup { + // __cxa_end_catch(); <- we are here + // } + // } + // - ex->handlerCount++; - deleteException = false; - } - else - { - ex->handlerCount--; - } - - if (ex->handlerCount == 0) - { - globals->caughtExceptions = ex->nextException; - if (deleteException) - { - releaseException(ex); - } - } -} - -/** - * ABI function. Returns the type of the current exception. - */ -extern "C" std::type_info *__cxa_current_exception_type() -{ - __cxa_eh_globals *globals = __cxa_get_globals(); - __cxa_exception *ex = globals->caughtExceptions; - return ex ? ex->exceptionType : 0; -} - -/** + ex->handlerCount++; + deleteException = false; + } + else + { + ex->handlerCount--; + } + + if (ex->handlerCount == 0) + { + globals->caughtExceptions = ex->nextException; + if (deleteException) + { + releaseException(ex); + } + } +} + +/** + * ABI function. Returns the type of the current exception. + */ +extern "C" std::type_info *__cxa_current_exception_type() +{ + __cxa_eh_globals *globals = __cxa_get_globals(); + __cxa_exception *ex = globals->caughtExceptions; + return ex ? ex->exceptionType : 0; +} + +/** * Cleanup, ensures that `__cxa_end_catch` is called to balance an explicit * `__cxa_begin_catch` call. */ @@ -1482,145 +1482,145 @@ static void end_catch(char *) __cxa_end_catch(); } /** - * ABI function, called when an exception specification is violated. - * - * This function does not return. - */ + * ABI function, called when an exception specification is violated. + * + * This function does not return. + */ extern "C" void __cxa_call_unexpected(void*exception) -{ - _Unwind_Exception *exceptionObject = static_cast<_Unwind_Exception*>(exception); +{ + _Unwind_Exception *exceptionObject = static_cast<_Unwind_Exception*>(exception); // Wrap the call to the unexpected handler in calls to `__cxa_begin_catch` // and `__cxa_end_catch` so that we correctly update exception counts if // the unexpected handler throws an exception. __cxa_begin_catch(exceptionObject); __attribute__((cleanup(end_catch))) char unused; - if (exceptionObject->exception_class == exception_class) - { - __cxa_exception *ex = exceptionFromPointer(exceptionObject); - if (ex->unexpectedHandler) - { - ex->unexpectedHandler(); + if (exceptionObject->exception_class == exception_class) + { + __cxa_exception *ex = exceptionFromPointer(exceptionObject); + if (ex->unexpectedHandler) + { + ex->unexpectedHandler(); // Should not be reached. - abort(); - } - } - std::unexpected(); + abort(); + } + } + std::unexpected(); // Should not be reached. - abort(); -} - -/** - * ABI function, returns the adjusted pointer to the exception object. - */ -extern "C" void *__cxa_get_exception_ptr(void *exceptionObject) -{ - return exceptionFromPointer(exceptionObject)->adjustedPtr; -} - -/** - * As an extension, we provide the ability for the unexpected and terminate - * handlers to be thread-local. We default to the standards-compliant - * behaviour where they are global. - */ -static bool thread_local_handlers = false; - - -namespace pathscale -{ - /** - * Sets whether unexpected and terminate handlers should be thread-local. - */ + abort(); +} + +/** + * ABI function, returns the adjusted pointer to the exception object. + */ +extern "C" void *__cxa_get_exception_ptr(void *exceptionObject) +{ + return exceptionFromPointer(exceptionObject)->adjustedPtr; +} + +/** + * As an extension, we provide the ability for the unexpected and terminate + * handlers to be thread-local. We default to the standards-compliant + * behaviour where they are global. + */ +static bool thread_local_handlers = false; + + +namespace pathscale +{ + /** + * Sets whether unexpected and terminate handlers should be thread-local. + */ void set_use_thread_local_handlers(bool flag) noexcept - { - thread_local_handlers = flag; - } - /** + { + thread_local_handlers = flag; + } + /** * Sets a thread-local unexpected handler. - */ + */ unexpected_handler set_unexpected(unexpected_handler f) noexcept - { - static __cxa_thread_info *info = thread_info(); - unexpected_handler old = info->unexpectedHandler; - info->unexpectedHandler = f; - return old; - } - /** + { + static __cxa_thread_info *info = thread_info(); + unexpected_handler old = info->unexpectedHandler; + info->unexpectedHandler = f; + return old; + } + /** * Sets a thread-local terminate handler. - */ + */ terminate_handler set_terminate(terminate_handler f) noexcept - { - static __cxa_thread_info *info = thread_info(); - terminate_handler old = info->terminateHandler; - info->terminateHandler = f; - return old; - } -} - -namespace std -{ - /** - * Sets the function that will be called when an exception specification is - * violated. - */ + { + static __cxa_thread_info *info = thread_info(); + terminate_handler old = info->terminateHandler; + info->terminateHandler = f; + return old; + } +} + +namespace std +{ + /** + * Sets the function that will be called when an exception specification is + * violated. + */ unexpected_handler set_unexpected(unexpected_handler f) noexcept - { - if (thread_local_handlers) { return pathscale::set_unexpected(f); } - - return ATOMIC_SWAP(&unexpectedHandler, f); - } - /** - * Sets the function that is called to terminate the program. - */ + { + if (thread_local_handlers) { return pathscale::set_unexpected(f); } + + return ATOMIC_SWAP(&unexpectedHandler, f); + } + /** + * Sets the function that is called to terminate the program. + */ terminate_handler set_terminate(terminate_handler f) noexcept - { - if (thread_local_handlers) { return pathscale::set_terminate(f); } - - return ATOMIC_SWAP(&terminateHandler, f); - } - /** - * Terminates the program, calling a custom terminate implementation if - * required. - */ + { + if (thread_local_handlers) { return pathscale::set_terminate(f); } + + return ATOMIC_SWAP(&terminateHandler, f); + } + /** + * Terminates the program, calling a custom terminate implementation if + * required. + */ void terminate() noexcept - { - static __cxa_thread_info *info = thread_info(); - if (0 != info && 0 != info->terminateHandler) - { - info->terminateHandler(); - // Should not be reached - a terminate handler is not expected to - // return. - abort(); - } - terminateHandler(); - } - /** - * Called when an unexpected exception is encountered (i.e. an exception - * violates an exception specification). This calls abort() unless a - * custom handler has been set.. - */ - void unexpected() - { - static __cxa_thread_info *info = thread_info(); - if (0 != info && 0 != info->unexpectedHandler) - { - info->unexpectedHandler(); - // Should not be reached - a terminate handler is not expected to - // return. - abort(); - } - unexpectedHandler(); - } - /** - * Returns whether there are any exceptions currently being thrown that - * have not been caught. This can occur inside a nested catch statement. - */ + { + static __cxa_thread_info *info = thread_info(); + if (0 != info && 0 != info->terminateHandler) + { + info->terminateHandler(); + // Should not be reached - a terminate handler is not expected to + // return. + abort(); + } + terminateHandler(); + } + /** + * Called when an unexpected exception is encountered (i.e. an exception + * violates an exception specification). This calls abort() unless a + * custom handler has been set.. + */ + void unexpected() + { + static __cxa_thread_info *info = thread_info(); + if (0 != info && 0 != info->unexpectedHandler) + { + info->unexpectedHandler(); + // Should not be reached - a terminate handler is not expected to + // return. + abort(); + } + unexpectedHandler(); + } + /** + * Returns whether there are any exceptions currently being thrown that + * have not been caught. This can occur inside a nested catch statement. + */ bool uncaught_exception() noexcept - { - __cxa_thread_info *info = thread_info(); - return info->globals.uncaughtExceptions != 0; - } - /** + { + __cxa_thread_info *info = thread_info(); + return info->globals.uncaughtExceptions != 0; + } + /** * Returns the number of exceptions currently being thrown that have not * been caught. This can occur inside a nested catch statement. */ @@ -1630,62 +1630,62 @@ namespace std return info->globals.uncaughtExceptions; } /** - * Returns the current unexpected handler. - */ + * Returns the current unexpected handler. + */ unexpected_handler get_unexpected() noexcept - { - __cxa_thread_info *info = thread_info(); - if (info->unexpectedHandler) - { - return info->unexpectedHandler; - } - return ATOMIC_LOAD(&unexpectedHandler); - } - /** - * Returns the current terminate handler. - */ + { + __cxa_thread_info *info = thread_info(); + if (info->unexpectedHandler) + { + return info->unexpectedHandler; + } + return ATOMIC_LOAD(&unexpectedHandler); + } + /** + * Returns the current terminate handler. + */ terminate_handler get_terminate() noexcept - { - __cxa_thread_info *info = thread_info(); - if (info->terminateHandler) - { - return info->terminateHandler; - } - return ATOMIC_LOAD(&terminateHandler); - } -} -#if defined(__arm__) && !defined(__ARM_DWARF_EH__) -extern "C" _Unwind_Exception *__cxa_get_cleanup(void) -{ - __cxa_thread_info *info = thread_info_fast(); - _Unwind_Exception *exceptionObject = info->currentCleanup; - if (isCXXException(exceptionObject->exception_class)) - { - __cxa_exception *ex = exceptionFromPointer(exceptionObject); - ex->cleanupCount--; - if (ex->cleanupCount == 0) - { - info->currentCleanup = ex->nextCleanup; - ex->nextCleanup = 0; - } - } - else - { - info->currentCleanup = 0; - } - return exceptionObject; -} - -asm ( -".pushsection .text.__cxa_end_cleanup \n" -".global __cxa_end_cleanup \n" -".type __cxa_end_cleanup, \"function\" \n" -"__cxa_end_cleanup: \n" -" push {r1, r2, r3, r4} \n" -" bl __cxa_get_cleanup \n" -" push {r1, r2, r3, r4} \n" -" b _Unwind_Resume \n" -" bl abort \n" -".popsection \n" -); -#endif + { + __cxa_thread_info *info = thread_info(); + if (info->terminateHandler) + { + return info->terminateHandler; + } + return ATOMIC_LOAD(&terminateHandler); + } +} +#if defined(__arm__) && !defined(__ARM_DWARF_EH__) +extern "C" _Unwind_Exception *__cxa_get_cleanup(void) +{ + __cxa_thread_info *info = thread_info_fast(); + _Unwind_Exception *exceptionObject = info->currentCleanup; + if (isCXXException(exceptionObject->exception_class)) + { + __cxa_exception *ex = exceptionFromPointer(exceptionObject); + ex->cleanupCount--; + if (ex->cleanupCount == 0) + { + info->currentCleanup = ex->nextCleanup; + ex->nextCleanup = 0; + } + } + else + { + info->currentCleanup = 0; + } + return exceptionObject; +} + +asm ( +".pushsection .text.__cxa_end_cleanup \n" +".global __cxa_end_cleanup \n" +".type __cxa_end_cleanup, \"function\" \n" +"__cxa_end_cleanup: \n" +" push {r1, r2, r3, r4} \n" +" bl __cxa_get_cleanup \n" +" push {r1, r2, r3, r4} \n" +" b _Unwind_Resume \n" +" bl abort \n" +".popsection \n" +); +#endif diff --git a/contrib/libs/cxxsupp/libcxxrt/guard.cc b/contrib/libs/cxxsupp/libcxxrt/guard.cc index 10978716e8..a8818db571 100644 --- a/contrib/libs/cxxsupp/libcxxrt/guard.cc +++ b/contrib/libs/cxxsupp/libcxxrt/guard.cc @@ -1,193 +1,193 @@ -/* - * Copyright 2010-2012 PathScale, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* + * Copyright 2010-2012 PathScale, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * guard.cc: Functions for thread-safe static initialisation. - * - * Static values in C++ can be initialised lazily their first use. This file - * contains functions that are used to ensure that two threads attempting to - * initialize the same static do not call the constructor twice. This is - * important because constructors can have side effects, so calling the - * constructor twice may be very bad. - * - * Statics that require initialisation are protected by a 64-bit value. Any - * platform that can do 32-bit atomic test and set operations can use this - * value as a low-overhead lock. Because statics (in most sane code) are - * accessed far more times than they are initialised, this lock implementation - * is heavily optimised towards the case where the static has already been - * initialised. - */ -#include <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <pthread.h> -#include <assert.h> -#include "atomic.h" - -// Older GCC doesn't define __LITTLE_ENDIAN__ -#ifndef __LITTLE_ENDIAN__ - // If __BYTE_ORDER__ is defined, use that instead -# ifdef __BYTE_ORDER__ -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define __LITTLE_ENDIAN__ -# endif - // x86 and ARM are the most common little-endian CPUs, so let's have a - // special case for them (ARM is already special cased). Assume everything - // else is big endian. -# elif defined(__x86_64) || defined(__i386) -# define __LITTLE_ENDIAN__ -# endif -#endif - - -/* - * The least significant bit of the guard variable indicates that the object - * has been initialised, the most significant bit is used for a spinlock. - */ -#ifdef __arm__ -// ARM ABI - 32-bit guards. -typedef uint32_t guard_t; -typedef uint32_t guard_lock_t; -static const uint32_t LOCKED = static_cast<guard_t>(1) << 31; -static const uint32_t INITIALISED = 1; -#define LOCK_PART(guard) (guard) -#define INIT_PART(guard) (guard) -#elif defined(_LP64) -typedef uint64_t guard_t; -typedef uint64_t guard_lock_t; -# if defined(__LITTLE_ENDIAN__) -static const guard_t LOCKED = static_cast<guard_t>(1) << 63; -static const guard_t INITIALISED = 1; -# else -static const guard_t LOCKED = 1; -static const guard_t INITIALISED = static_cast<guard_t>(1) << 56; -# endif -#define LOCK_PART(guard) (guard) -#define INIT_PART(guard) (guard) -#else -typedef uint32_t guard_lock_t; -# if defined(__LITTLE_ENDIAN__) -typedef struct { - uint32_t init_half; - uint32_t lock_half; -} guard_t; -static const uint32_t LOCKED = static_cast<guard_lock_t>(1) << 31; -static const uint32_t INITIALISED = 1; -# else -typedef struct { - uint32_t init_half; - uint32_t lock_half; -} guard_t; -static_assert(sizeof(guard_t) == sizeof(uint64_t), ""); -static const uint32_t LOCKED = 1; -static const uint32_t INITIALISED = static_cast<guard_lock_t>(1) << 24; -# endif -#define LOCK_PART(guard) (&(guard)->lock_half) -#define INIT_PART(guard) (&(guard)->init_half) -#endif -static const guard_lock_t INITIAL = 0; - -/** - * Acquires a lock on a guard, returning 0 if the object has already been - * initialised, and 1 if it has not. If the object is already constructed then - * this function just needs to read a byte from memory and return. - */ -extern "C" int __cxa_guard_acquire(volatile guard_t *guard_object) -{ - guard_lock_t old; - // Not an atomic read, doesn't establish a happens-before relationship, but - // if one is already established and we end up seeing an initialised state - // then it's a fast path, otherwise we'll do something more expensive than - // this test anyway... + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * guard.cc: Functions for thread-safe static initialisation. + * + * Static values in C++ can be initialised lazily their first use. This file + * contains functions that are used to ensure that two threads attempting to + * initialize the same static do not call the constructor twice. This is + * important because constructors can have side effects, so calling the + * constructor twice may be very bad. + * + * Statics that require initialisation are protected by a 64-bit value. Any + * platform that can do 32-bit atomic test and set operations can use this + * value as a low-overhead lock. Because statics (in most sane code) are + * accessed far more times than they are initialised, this lock implementation + * is heavily optimised towards the case where the static has already been + * initialised. + */ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <pthread.h> +#include <assert.h> +#include "atomic.h" + +// Older GCC doesn't define __LITTLE_ENDIAN__ +#ifndef __LITTLE_ENDIAN__ + // If __BYTE_ORDER__ is defined, use that instead +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define __LITTLE_ENDIAN__ +# endif + // x86 and ARM are the most common little-endian CPUs, so let's have a + // special case for them (ARM is already special cased). Assume everything + // else is big endian. +# elif defined(__x86_64) || defined(__i386) +# define __LITTLE_ENDIAN__ +# endif +#endif + + +/* + * The least significant bit of the guard variable indicates that the object + * has been initialised, the most significant bit is used for a spinlock. + */ +#ifdef __arm__ +// ARM ABI - 32-bit guards. +typedef uint32_t guard_t; +typedef uint32_t guard_lock_t; +static const uint32_t LOCKED = static_cast<guard_t>(1) << 31; +static const uint32_t INITIALISED = 1; +#define LOCK_PART(guard) (guard) +#define INIT_PART(guard) (guard) +#elif defined(_LP64) +typedef uint64_t guard_t; +typedef uint64_t guard_lock_t; +# if defined(__LITTLE_ENDIAN__) +static const guard_t LOCKED = static_cast<guard_t>(1) << 63; +static const guard_t INITIALISED = 1; +# else +static const guard_t LOCKED = 1; +static const guard_t INITIALISED = static_cast<guard_t>(1) << 56; +# endif +#define LOCK_PART(guard) (guard) +#define INIT_PART(guard) (guard) +#else +typedef uint32_t guard_lock_t; +# if defined(__LITTLE_ENDIAN__) +typedef struct { + uint32_t init_half; + uint32_t lock_half; +} guard_t; +static const uint32_t LOCKED = static_cast<guard_lock_t>(1) << 31; +static const uint32_t INITIALISED = 1; +# else +typedef struct { + uint32_t init_half; + uint32_t lock_half; +} guard_t; +static_assert(sizeof(guard_t) == sizeof(uint64_t), ""); +static const uint32_t LOCKED = 1; +static const uint32_t INITIALISED = static_cast<guard_lock_t>(1) << 24; +# endif +#define LOCK_PART(guard) (&(guard)->lock_half) +#define INIT_PART(guard) (&(guard)->init_half) +#endif +static const guard_lock_t INITIAL = 0; + +/** + * Acquires a lock on a guard, returning 0 if the object has already been + * initialised, and 1 if it has not. If the object is already constructed then + * this function just needs to read a byte from memory and return. + */ +extern "C" int __cxa_guard_acquire(volatile guard_t *guard_object) +{ + guard_lock_t old; + // Not an atomic read, doesn't establish a happens-before relationship, but + // if one is already established and we end up seeing an initialised state + // then it's a fast path, otherwise we'll do something more expensive than + // this test anyway... if (INITIALISED == __atomic_load_n(INIT_PART(guard_object), __ATOMIC_RELAXED)) - return 0; - // Spin trying to do the initialisation - for (;;) - { - // Loop trying to move the value of the guard from 0 (not - // locked, not initialised) to the locked-uninitialised - // position. - old = __sync_val_compare_and_swap(LOCK_PART(guard_object), - INITIAL, LOCKED); - if (old == INITIAL) { - // Lock obtained. If lock and init bit are - // in separate words, check for init race. - if (INIT_PART(guard_object) == LOCK_PART(guard_object)) - return 1; - if (INITIALISED != *INIT_PART(guard_object)) - return 1; - - // No need for a memory barrier here, - // see first comment. + return 0; + // Spin trying to do the initialisation + for (;;) + { + // Loop trying to move the value of the guard from 0 (not + // locked, not initialised) to the locked-uninitialised + // position. + old = __sync_val_compare_and_swap(LOCK_PART(guard_object), + INITIAL, LOCKED); + if (old == INITIAL) { + // Lock obtained. If lock and init bit are + // in separate words, check for init race. + if (INIT_PART(guard_object) == LOCK_PART(guard_object)) + return 1; + if (INITIALISED != *INIT_PART(guard_object)) + return 1; + + // No need for a memory barrier here, + // see first comment. __atomic_store_n(LOCK_PART(guard_object), INITIAL, __ATOMIC_RELAXED); - return 0; - } - // If lock and init bit are in the same word, check again - // if we are done. - if (INIT_PART(guard_object) == LOCK_PART(guard_object) && - old == INITIALISED) - return 0; - - assert(old == LOCKED); - // Another thread holds the lock. - // If lock and init bit are in different words, check - // if we are done before yielding and looping. - if (INIT_PART(guard_object) != LOCK_PART(guard_object) && - INITIALISED == *INIT_PART(guard_object)) - return 0; - sched_yield(); - } -} - -/** - * Releases the lock without marking the object as initialised. This function - * is called if initialising a static causes an exception to be thrown. - */ -extern "C" void __cxa_guard_abort(volatile guard_t *guard_object) -{ - __attribute__((unused)) - bool reset = __sync_bool_compare_and_swap(LOCK_PART(guard_object), - LOCKED, INITIAL); - assert(reset); -} -/** - * Releases the guard and marks the object as initialised. This function is - * called after successful initialisation of a static. - */ -extern "C" void __cxa_guard_release(volatile guard_t *guard_object) -{ - guard_lock_t old; - if (INIT_PART(guard_object) == LOCK_PART(guard_object)) - old = LOCKED; - else - old = INITIAL; - __attribute__((unused)) - bool reset = __sync_bool_compare_and_swap(INIT_PART(guard_object), - old, INITIALISED); - assert(reset); - if (INIT_PART(guard_object) != LOCK_PART(guard_object)) - *LOCK_PART(guard_object) = INITIAL; -} + return 0; + } + // If lock and init bit are in the same word, check again + // if we are done. + if (INIT_PART(guard_object) == LOCK_PART(guard_object) && + old == INITIALISED) + return 0; + + assert(old == LOCKED); + // Another thread holds the lock. + // If lock and init bit are in different words, check + // if we are done before yielding and looping. + if (INIT_PART(guard_object) != LOCK_PART(guard_object) && + INITIALISED == *INIT_PART(guard_object)) + return 0; + sched_yield(); + } +} + +/** + * Releases the lock without marking the object as initialised. This function + * is called if initialising a static causes an exception to be thrown. + */ +extern "C" void __cxa_guard_abort(volatile guard_t *guard_object) +{ + __attribute__((unused)) + bool reset = __sync_bool_compare_and_swap(LOCK_PART(guard_object), + LOCKED, INITIAL); + assert(reset); +} +/** + * Releases the guard and marks the object as initialised. This function is + * called after successful initialisation of a static. + */ +extern "C" void __cxa_guard_release(volatile guard_t *guard_object) +{ + guard_lock_t old; + if (INIT_PART(guard_object) == LOCK_PART(guard_object)) + old = LOCKED; + else + old = INITIAL; + __attribute__((unused)) + bool reset = __sync_bool_compare_and_swap(INIT_PART(guard_object), + old, INITIALISED); + assert(reset); + if (INIT_PART(guard_object) != LOCK_PART(guard_object)) + *LOCK_PART(guard_object) = INITIAL; +} diff --git a/contrib/libs/cxxsupp/libcxxrt/memory.cc b/contrib/libs/cxxsupp/libcxxrt/memory.cc index 694c5d5037..756d83a329 100644 --- a/contrib/libs/cxxsupp/libcxxrt/memory.cc +++ b/contrib/libs/cxxsupp/libcxxrt/memory.cc @@ -1,76 +1,76 @@ -/* - * Copyright 2010-2011 PathScale, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* + * Copyright 2010-2011 PathScale, Inc. All rights reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * memory.cc - Contains stub definition of C++ new/delete operators. - * - * These definitions are intended to be used for testing and are weak symbols - * to allow them to be replaced by definitions from a STL implementation. - * These versions simply wrap malloc() and free(), they do not provide a - * C++-specific allocator. - */ - -#include <stddef.h> -#include <stdlib.h> -#include "stdexcept.h" -#include "atomic.h" - - -namespace std -{ - struct nothrow_t {}; -} - - -/// The type of the function called when allocation fails. -typedef void (*new_handler)(); -/** - * The function to call when allocation fails. By default, there is no - * handler and a bad allocation exception is thrown if an allocation fails. - */ -static new_handler new_handl; - -namespace std -{ - /** - * Sets a function to be called when there is a failure in new. - */ - __attribute__((weak)) + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * memory.cc - Contains stub definition of C++ new/delete operators. + * + * These definitions are intended to be used for testing and are weak symbols + * to allow them to be replaced by definitions from a STL implementation. + * These versions simply wrap malloc() and free(), they do not provide a + * C++-specific allocator. + */ + +#include <stddef.h> +#include <stdlib.h> +#include "stdexcept.h" +#include "atomic.h" + + +namespace std +{ + struct nothrow_t {}; +} + + +/// The type of the function called when allocation fails. +typedef void (*new_handler)(); +/** + * The function to call when allocation fails. By default, there is no + * handler and a bad allocation exception is thrown if an allocation fails. + */ +static new_handler new_handl; + +namespace std +{ + /** + * Sets a function to be called when there is a failure in new. + */ + __attribute__((weak)) new_handler set_new_handler(new_handler handler) noexcept - { - return ATOMIC_SWAP(&new_handl, handler); - } - __attribute__((weak)) + { + return ATOMIC_SWAP(&new_handl, handler); + } + __attribute__((weak)) new_handler get_new_handler(void) noexcept - { - return ATOMIC_LOAD(&new_handl); - } -} - - + { + return ATOMIC_LOAD(&new_handl); + } +} + + #if __cplusplus < 201103L #define NOEXCEPT noexcept #define BADALLOC throw(std::bad_alloc) @@ -106,69 +106,69 @@ namespace } -__attribute__((weak)) +__attribute__((weak)) void* operator new(size_t size) BADALLOC -{ - if (0 == size) - { - size = 1; - } - void * mem = malloc(size); - while (0 == mem) - { - new_handler h = std::get_new_handler(); - if (0 != h) - { - h(); - } - else - { +{ + if (0 == size) + { + size = 1; + } + void * mem = malloc(size); + while (0 == mem) + { + new_handler h = std::get_new_handler(); + if (0 != h) + { + h(); + } + else + { #if !defined(_CXXRT_NO_EXCEPTIONS) throw std::bad_alloc(); #else break; #endif - } - mem = malloc(size); - } - - return mem; -} - - -__attribute__((weak)) + } + mem = malloc(size); + } + + return mem; +} + + +__attribute__((weak)) void* operator new(size_t size, const std::nothrow_t &) NOEXCEPT -{ +{ return noexcept_new<(::operator new)>(size); -} - - -__attribute__((weak)) +} + + +__attribute__((weak)) void operator delete(void * ptr) NOEXCEPT -{ - free(ptr); -} - - -__attribute__((weak)) +{ + free(ptr); +} + + +__attribute__((weak)) void * operator new[](size_t size) BADALLOC -{ - return ::operator new(size); -} - - -__attribute__((weak)) +{ + return ::operator new(size); +} + + +__attribute__((weak)) void * operator new[](size_t size, const std::nothrow_t &) NOEXCEPT -{ +{ return noexcept_new<(::operator new[])>(size); -} - - -__attribute__((weak)) +} + + +__attribute__((weak)) void operator delete[](void * ptr) NOEXCEPT -{ - ::operator delete(ptr); -} +{ + ::operator delete(ptr); +} // C++14 additional delete operators diff --git a/contrib/libs/cxxsupp/libcxxrt/stdexcept.cc b/contrib/libs/cxxsupp/libcxxrt/stdexcept.cc index 07c62a731b..2c92ef418b 100644 --- a/contrib/libs/cxxsupp/libcxxrt/stdexcept.cc +++ b/contrib/libs/cxxsupp/libcxxrt/stdexcept.cc @@ -1,98 +1,98 @@ -/* - * Copyright 2010-2011 PathScale, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* + * Copyright 2010-2011 PathScale, Inc. All rights reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * stdexcept.cc - provides stub implementations of the exceptions required by the runtime. - */ -#include "stdexcept.h" - -namespace std { - + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * stdexcept.cc - provides stub implementations of the exceptions required by the runtime. + */ +#include "stdexcept.h" + +namespace std { + exception::exception() noexcept {} exception::~exception() {} exception::exception(const exception&) noexcept {} exception& exception::operator=(const exception&) noexcept -{ - return *this; -} +{ + return *this; +} const char* exception::what() const noexcept -{ - return "std::exception"; -} - +{ + return "std::exception"; +} + bad_alloc::bad_alloc() noexcept {} bad_alloc::~bad_alloc() {} bad_alloc::bad_alloc(const bad_alloc&) noexcept {} bad_alloc& bad_alloc::operator=(const bad_alloc&) noexcept -{ - return *this; -} +{ + return *this; +} const char* bad_alloc::what() const noexcept -{ - return "cxxrt::bad_alloc"; -} - - - +{ + return "cxxrt::bad_alloc"; +} + + + bad_cast::bad_cast() noexcept {} bad_cast::~bad_cast() {} bad_cast::bad_cast(const bad_cast&) noexcept {} bad_cast& bad_cast::operator=(const bad_cast&) noexcept -{ - return *this; -} +{ + return *this; +} const char* bad_cast::what() const noexcept -{ - return "std::bad_cast"; -} - +{ + return "std::bad_cast"; +} + bad_typeid::bad_typeid() noexcept {} bad_typeid::~bad_typeid() {} bad_typeid::bad_typeid(const bad_typeid &__rhs) noexcept {} bad_typeid& bad_typeid::operator=(const bad_typeid &__rhs) noexcept -{ - return *this; -} - +{ + return *this; +} + const char* bad_typeid::what() const noexcept -{ - return "std::bad_typeid"; -} - +{ + return "std::bad_typeid"; +} + bad_array_new_length::bad_array_new_length() noexcept {} -bad_array_new_length::~bad_array_new_length() {} +bad_array_new_length::~bad_array_new_length() {} bad_array_new_length::bad_array_new_length(const bad_array_new_length&) noexcept {} bad_array_new_length& bad_array_new_length::operator=(const bad_array_new_length&) noexcept -{ - return *this; -} - +{ + return *this; +} + const char* bad_array_new_length::what() const noexcept -{ - return "std::bad_array_new_length"; -} - -} // namespace std +{ + return "std::bad_array_new_length"; +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxxrt/stdexcept.h b/contrib/libs/cxxsupp/libcxxrt/stdexcept.h index 13763f4824..6675f55fb5 100644 --- a/contrib/libs/cxxsupp/libcxxrt/stdexcept.h +++ b/contrib/libs/cxxsupp/libcxxrt/stdexcept.h @@ -1,96 +1,96 @@ -/* - * Copyright 2010-2011 PathScale, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* + * Copyright 2010-2011 PathScale, Inc. All rights reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * stdexcept.h - provides a stub version of <stdexcept>, which defines enough - * of the exceptions for the runtime to use. - */ - -namespace std -{ - - class exception - { - public: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * stdexcept.h - provides a stub version of <stdexcept>, which defines enough + * of the exceptions for the runtime to use. + */ + +namespace std +{ + + class exception + { + public: exception() noexcept; exception(const exception&) noexcept; exception& operator=(const exception&) noexcept; virtual ~exception(); virtual const char* what() const noexcept; - }; - - - /** - * Bad allocation exception. Thrown by ::operator new() if it fails. - */ - class bad_alloc: public exception - { - public: + }; + + + /** + * Bad allocation exception. Thrown by ::operator new() if it fails. + */ + class bad_alloc: public exception + { + public: bad_alloc() noexcept; bad_alloc(const bad_alloc&) noexcept; bad_alloc& operator=(const bad_alloc&) noexcept; ~bad_alloc(); virtual const char* what() const noexcept; - }; - - /** - * Bad cast exception. Thrown by the __cxa_bad_cast() helper function. - */ - class bad_cast: public exception { - public: + }; + + /** + * Bad cast exception. Thrown by the __cxa_bad_cast() helper function. + */ + class bad_cast: public exception { + public: bad_cast() noexcept; bad_cast(const bad_cast&) noexcept; bad_cast& operator=(const bad_cast&) noexcept; virtual ~bad_cast(); virtual const char* what() const noexcept; - }; - - /** - * Bad typeidexception. Thrown by the __cxa_bad_typeid() helper function. - */ - class bad_typeid: public exception - { - public: + }; + + /** + * Bad typeidexception. Thrown by the __cxa_bad_typeid() helper function. + */ + class bad_typeid: public exception + { + public: bad_typeid() noexcept; bad_typeid(const bad_typeid &__rhs) noexcept; virtual ~bad_typeid(); bad_typeid& operator=(const bad_typeid &__rhs) noexcept; virtual const char* what() const noexcept; - }; - - class bad_array_new_length: public bad_alloc - { - public: + }; + + class bad_array_new_length: public bad_alloc + { + public: bad_array_new_length() noexcept; bad_array_new_length(const bad_array_new_length&) noexcept; bad_array_new_length& operator=(const bad_array_new_length&) noexcept; - virtual ~bad_array_new_length(); + virtual ~bad_array_new_length(); virtual const char *what() const noexcept; - }; - - -} // namespace std - + }; + + +} // namespace std + diff --git a/contrib/libs/cxxsupp/libcxxrt/typeinfo.cc b/contrib/libs/cxxsupp/libcxxrt/typeinfo.cc index 976c59d7e3..c274daa408 100644 --- a/contrib/libs/cxxsupp/libcxxrt/typeinfo.cc +++ b/contrib/libs/cxxsupp/libcxxrt/typeinfo.cc @@ -1,70 +1,70 @@ -/* - * Copyright 2010-2012 PathScale, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* + * Copyright 2010-2012 PathScale, Inc. All rights reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "typeinfo.h" -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -using std::type_info; - -type_info::~type_info() {} - -bool type_info::operator==(const type_info &other) const -{ - return __type_name == other.__type_name; -} -bool type_info::operator!=(const type_info &other) const -{ - return __type_name != other.__type_name; -} -bool type_info::before(const type_info &other) const -{ - return __type_name < other.__type_name; -} -const char* type_info::name() const -{ - return __type_name; -} -type_info::type_info (const type_info& rhs) -{ - __type_name = rhs.__type_name; -} -type_info& type_info::operator= (const type_info& rhs) -{ - return *new type_info(rhs); -} - -ABI_NAMESPACE::__fundamental_type_info::~__fundamental_type_info() {} -ABI_NAMESPACE::__array_type_info::~__array_type_info() {} -ABI_NAMESPACE::__function_type_info::~__function_type_info() {} -ABI_NAMESPACE::__enum_type_info::~__enum_type_info() {} -ABI_NAMESPACE::__class_type_info::~__class_type_info() {} -ABI_NAMESPACE::__si_class_type_info::~__si_class_type_info() {} -ABI_NAMESPACE::__vmi_class_type_info::~__vmi_class_type_info() {} -ABI_NAMESPACE::__pbase_type_info::~__pbase_type_info() {} -ABI_NAMESPACE::__pointer_type_info::~__pointer_type_info() {} -ABI_NAMESPACE::__pointer_to_member_type_info::~__pointer_to_member_type_info() {} + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "typeinfo.h" +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +using std::type_info; + +type_info::~type_info() {} + +bool type_info::operator==(const type_info &other) const +{ + return __type_name == other.__type_name; +} +bool type_info::operator!=(const type_info &other) const +{ + return __type_name != other.__type_name; +} +bool type_info::before(const type_info &other) const +{ + return __type_name < other.__type_name; +} +const char* type_info::name() const +{ + return __type_name; +} +type_info::type_info (const type_info& rhs) +{ + __type_name = rhs.__type_name; +} +type_info& type_info::operator= (const type_info& rhs) +{ + return *new type_info(rhs); +} + +ABI_NAMESPACE::__fundamental_type_info::~__fundamental_type_info() {} +ABI_NAMESPACE::__array_type_info::~__array_type_info() {} +ABI_NAMESPACE::__function_type_info::~__function_type_info() {} +ABI_NAMESPACE::__enum_type_info::~__enum_type_info() {} +ABI_NAMESPACE::__class_type_info::~__class_type_info() {} +ABI_NAMESPACE::__si_class_type_info::~__si_class_type_info() {} +ABI_NAMESPACE::__vmi_class_type_info::~__vmi_class_type_info() {} +ABI_NAMESPACE::__pbase_type_info::~__pbase_type_info() {} +ABI_NAMESPACE::__pointer_type_info::~__pointer_type_info() {} +ABI_NAMESPACE::__pointer_to_member_type_info::~__pointer_to_member_type_info() {} diff --git a/contrib/libs/cxxsupp/libcxxrt/typeinfo.h b/contrib/libs/cxxsupp/libcxxrt/typeinfo.h index a8a1a980e9..db005dc6bc 100644 --- a/contrib/libs/cxxsupp/libcxxrt/typeinfo.h +++ b/contrib/libs/cxxsupp/libcxxrt/typeinfo.h @@ -1,313 +1,313 @@ -/* - * Copyright 2010-2011 PathScale, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* + * Copyright 2010-2011 PathScale, Inc. All rights reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stddef.h> -#include "abi_namespace.h" - -namespace ABI_NAMESPACE -{ - struct __class_type_info; -} -namespace std -{ - /** - * Standard type info class. The layout of this class is specified by the - * ABI. The layout of the vtable is not, but is intended to be - * compatible with the GNU ABI. - * - * Unlike the GNU version, the vtable layout is considered semi-private. - */ - class type_info - { - public: - /** - * Virtual destructor. This class must have one virtual function to - * ensure that it has a vtable. - */ - virtual ~type_info(); - bool operator==(const type_info &) const; - bool operator!=(const type_info &) const; - bool before(const type_info &) const; - const char* name() const; - type_info(); - private: - type_info(const type_info& rhs); - type_info& operator= (const type_info& rhs); - const char *__type_name; - /* - * The following functions are in this order to match the - * vtable layout of libsupc++. This allows libcxxrt to be used - * with libraries that depend on this. - * - * These functions are in the public headers for libstdc++, so - * we have to assume that someone will probably call them and - * expect them to work. Their names must also match the names used in - * libsupc++, so that code linking against this library can subclass - * type_info and correctly fill in the values in the vtables. - */ - public: - /** - * Returns true if this is some pointer type, false otherwise. - */ - virtual bool __is_pointer_p() const { return false; } - /** - * Returns true if this is some function type, false otherwise. - */ - virtual bool __is_function_p() const { return false; } - /** - * Catch function. Allows external libraries to implement - * their own basic types. This is used, for example, in the - * GNUstep Objective-C runtime to allow Objective-C types to be - * caught in G++ catch blocks. - * - * The outer parameter indicates the number of outer pointers - * in the high bits. The low bit indicates whether the - * pointers are const qualified. - */ - virtual bool __do_catch(const type_info *thrown_type, - void **thrown_object, - unsigned outer) const; - /** - * Performs an upcast. This is used in exception handling to - * cast from subclasses to superclasses. If the upcast is - * possible, it returns true and adjusts the pointer. If the - * upcast is not possible, it returns false and does not adjust - * the pointer. - */ - virtual bool __do_upcast( - const ABI_NAMESPACE::__class_type_info *target, - void **thrown_object) const - { - return false; - } - }; -} - - -namespace ABI_NAMESPACE -{ - /** - * Primitive type info, for intrinsic types. - */ - struct __fundamental_type_info : public std::type_info - { - virtual ~__fundamental_type_info(); - }; - /** - * Type info for arrays. - */ - struct __array_type_info : public std::type_info - { - virtual ~__array_type_info(); - }; - /** - * Type info for functions. - */ - struct __function_type_info : public std::type_info - { - virtual ~__function_type_info(); - virtual bool __is_function_p() const { return true; } - }; - /** - * Type info for enums. - */ - struct __enum_type_info : public std::type_info - { - virtual ~__enum_type_info(); - }; - - /** - * Base class for class type info. Used only for tentative definitions. - */ - struct __class_type_info : public std::type_info - { - virtual ~__class_type_info(); - /** - * Function implementing dynamic casts. - */ - virtual void *cast_to(void *obj, const struct __class_type_info *other) const; - virtual bool __do_upcast(const __class_type_info *target, - void **thrown_object) const - { - return this == target; - } - }; - - /** - * Single-inheritance class type info. This is used for classes containing - * a single non-virtual base class at offset 0. - */ - struct __si_class_type_info : public __class_type_info - { - virtual ~__si_class_type_info(); - const __class_type_info *__base_type; - virtual bool __do_upcast( - const ABI_NAMESPACE::__class_type_info *target, - void **thrown_object) const; - virtual void *cast_to(void *obj, const struct __class_type_info *other) const; - }; - - /** - * Type info for base classes. Classes with multiple bases store an array - * of these, one for each superclass. - */ - struct __base_class_type_info - { - const __class_type_info *__base_type; - private: - /** - * The high __offset_shift bits of this store the (signed) offset - * of the base class. The low bits store flags from - * __offset_flags_masks. - */ - long __offset_flags; - /** - * Flags used in the low bits of __offset_flags. - */ - enum __offset_flags_masks - { - /** This base class is virtual. */ - __virtual_mask = 0x1, - /** This base class is public. */ - __public_mask = 0x2, - /** The number of bits reserved for flags. */ - __offset_shift = 8 - }; - public: - /** - * Returns the offset of the base class. - */ - long offset() const - { - return __offset_flags >> __offset_shift; - } - /** - * Returns the flags. - */ - long flags() const - { - return __offset_flags & ((1 << __offset_shift) - 1); - } - /** - * Returns whether this is a public base class. - */ - bool isPublic() const { return flags() & __public_mask; } - /** - * Returns whether this is a virtual base class. - */ - bool isVirtual() const { return flags() & __virtual_mask; } - }; - - /** - * Type info for classes with virtual bases or multiple superclasses. - */ - struct __vmi_class_type_info : public __class_type_info - { - virtual ~__vmi_class_type_info(); - /** Flags describing this class. Contains values from __flags_masks. */ - unsigned int __flags; - /** The number of base classes. */ - unsigned int __base_count; + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stddef.h> +#include "abi_namespace.h" + +namespace ABI_NAMESPACE +{ + struct __class_type_info; +} +namespace std +{ + /** + * Standard type info class. The layout of this class is specified by the + * ABI. The layout of the vtable is not, but is intended to be + * compatible with the GNU ABI. + * + * Unlike the GNU version, the vtable layout is considered semi-private. + */ + class type_info + { + public: + /** + * Virtual destructor. This class must have one virtual function to + * ensure that it has a vtable. + */ + virtual ~type_info(); + bool operator==(const type_info &) const; + bool operator!=(const type_info &) const; + bool before(const type_info &) const; + const char* name() const; + type_info(); + private: + type_info(const type_info& rhs); + type_info& operator= (const type_info& rhs); + const char *__type_name; + /* + * The following functions are in this order to match the + * vtable layout of libsupc++. This allows libcxxrt to be used + * with libraries that depend on this. + * + * These functions are in the public headers for libstdc++, so + * we have to assume that someone will probably call them and + * expect them to work. Their names must also match the names used in + * libsupc++, so that code linking against this library can subclass + * type_info and correctly fill in the values in the vtables. + */ + public: + /** + * Returns true if this is some pointer type, false otherwise. + */ + virtual bool __is_pointer_p() const { return false; } + /** + * Returns true if this is some function type, false otherwise. + */ + virtual bool __is_function_p() const { return false; } + /** + * Catch function. Allows external libraries to implement + * their own basic types. This is used, for example, in the + * GNUstep Objective-C runtime to allow Objective-C types to be + * caught in G++ catch blocks. + * + * The outer parameter indicates the number of outer pointers + * in the high bits. The low bit indicates whether the + * pointers are const qualified. + */ + virtual bool __do_catch(const type_info *thrown_type, + void **thrown_object, + unsigned outer) const; + /** + * Performs an upcast. This is used in exception handling to + * cast from subclasses to superclasses. If the upcast is + * possible, it returns true and adjusts the pointer. If the + * upcast is not possible, it returns false and does not adjust + * the pointer. + */ + virtual bool __do_upcast( + const ABI_NAMESPACE::__class_type_info *target, + void **thrown_object) const + { + return false; + } + }; +} + + +namespace ABI_NAMESPACE +{ + /** + * Primitive type info, for intrinsic types. + */ + struct __fundamental_type_info : public std::type_info + { + virtual ~__fundamental_type_info(); + }; + /** + * Type info for arrays. + */ + struct __array_type_info : public std::type_info + { + virtual ~__array_type_info(); + }; + /** + * Type info for functions. + */ + struct __function_type_info : public std::type_info + { + virtual ~__function_type_info(); + virtual bool __is_function_p() const { return true; } + }; + /** + * Type info for enums. + */ + struct __enum_type_info : public std::type_info + { + virtual ~__enum_type_info(); + }; + + /** + * Base class for class type info. Used only for tentative definitions. + */ + struct __class_type_info : public std::type_info + { + virtual ~__class_type_info(); + /** + * Function implementing dynamic casts. + */ + virtual void *cast_to(void *obj, const struct __class_type_info *other) const; + virtual bool __do_upcast(const __class_type_info *target, + void **thrown_object) const + { + return this == target; + } + }; + + /** + * Single-inheritance class type info. This is used for classes containing + * a single non-virtual base class at offset 0. + */ + struct __si_class_type_info : public __class_type_info + { + virtual ~__si_class_type_info(); + const __class_type_info *__base_type; + virtual bool __do_upcast( + const ABI_NAMESPACE::__class_type_info *target, + void **thrown_object) const; + virtual void *cast_to(void *obj, const struct __class_type_info *other) const; + }; + + /** + * Type info for base classes. Classes with multiple bases store an array + * of these, one for each superclass. + */ + struct __base_class_type_info + { + const __class_type_info *__base_type; + private: + /** + * The high __offset_shift bits of this store the (signed) offset + * of the base class. The low bits store flags from + * __offset_flags_masks. + */ + long __offset_flags; + /** + * Flags used in the low bits of __offset_flags. + */ + enum __offset_flags_masks + { + /** This base class is virtual. */ + __virtual_mask = 0x1, + /** This base class is public. */ + __public_mask = 0x2, + /** The number of bits reserved for flags. */ + __offset_shift = 8 + }; + public: + /** + * Returns the offset of the base class. + */ + long offset() const + { + return __offset_flags >> __offset_shift; + } + /** + * Returns the flags. + */ + long flags() const + { + return __offset_flags & ((1 << __offset_shift) - 1); + } + /** + * Returns whether this is a public base class. + */ + bool isPublic() const { return flags() & __public_mask; } + /** + * Returns whether this is a virtual base class. + */ + bool isVirtual() const { return flags() & __virtual_mask; } + }; + + /** + * Type info for classes with virtual bases or multiple superclasses. + */ + struct __vmi_class_type_info : public __class_type_info + { + virtual ~__vmi_class_type_info(); + /** Flags describing this class. Contains values from __flags_masks. */ + unsigned int __flags; + /** The number of base classes. */ + unsigned int __base_count; + /** + * Array of base classes - this actually has __base_count elements, not + * 1. + */ + __base_class_type_info __base_info[1]; + + /** + * Flags used in the __flags field. + */ + enum __flags_masks + { + /** The class has non-diamond repeated inheritance. */ + __non_diamond_repeat_mask = 0x1, + /** The class is diamond shaped. */ + __diamond_shaped_mask = 0x2 + }; + virtual bool __do_upcast( + const ABI_NAMESPACE::__class_type_info *target, + void **thrown_object) const; + virtual void *cast_to(void *obj, const struct __class_type_info *other) const; + }; + + /** + * Base class used for both pointer and pointer-to-member type info. + */ + struct __pbase_type_info : public std::type_info + { + virtual ~__pbase_type_info(); + /** + * Flags. Values from __masks. + */ + unsigned int __flags; + /** + * The type info for the pointee. + */ + const std::type_info *__pointee; + + /** + * Masks used for qualifiers on the pointer. + */ + enum __masks + { + /** Pointer has const qualifier. */ + __const_mask = 0x1, + /** Pointer has volatile qualifier. */ + __volatile_mask = 0x2, + /** Pointer has restrict qualifier. */ + __restrict_mask = 0x4, + /** Pointer points to an incomplete type. */ + __incomplete_mask = 0x8, + /** Pointer is a pointer to a member of an incomplete class. */ + __incomplete_class_mask = 0x10 + }; + virtual bool __do_catch(const type_info *thrown_type, + void **thrown_object, + unsigned outer) const; + }; + + /** + * Pointer type info. + */ + struct __pointer_type_info : public __pbase_type_info + { + virtual ~__pointer_type_info(); + virtual bool __is_pointer_p() const { return true; } + }; + + /** + * Pointer to member type info. + */ + struct __pointer_to_member_type_info : public __pbase_type_info + { + virtual ~__pointer_to_member_type_info(); /** - * Array of base classes - this actually has __base_count elements, not - * 1. - */ - __base_class_type_info __base_info[1]; - - /** - * Flags used in the __flags field. - */ - enum __flags_masks - { - /** The class has non-diamond repeated inheritance. */ - __non_diamond_repeat_mask = 0x1, - /** The class is diamond shaped. */ - __diamond_shaped_mask = 0x2 - }; - virtual bool __do_upcast( - const ABI_NAMESPACE::__class_type_info *target, - void **thrown_object) const; - virtual void *cast_to(void *obj, const struct __class_type_info *other) const; - }; - - /** - * Base class used for both pointer and pointer-to-member type info. - */ - struct __pbase_type_info : public std::type_info - { - virtual ~__pbase_type_info(); - /** - * Flags. Values from __masks. - */ - unsigned int __flags; - /** - * The type info for the pointee. - */ - const std::type_info *__pointee; - - /** - * Masks used for qualifiers on the pointer. - */ - enum __masks - { - /** Pointer has const qualifier. */ - __const_mask = 0x1, - /** Pointer has volatile qualifier. */ - __volatile_mask = 0x2, - /** Pointer has restrict qualifier. */ - __restrict_mask = 0x4, - /** Pointer points to an incomplete type. */ - __incomplete_mask = 0x8, - /** Pointer is a pointer to a member of an incomplete class. */ - __incomplete_class_mask = 0x10 - }; - virtual bool __do_catch(const type_info *thrown_type, - void **thrown_object, - unsigned outer) const; - }; - - /** - * Pointer type info. - */ - struct __pointer_type_info : public __pbase_type_info - { - virtual ~__pointer_type_info(); - virtual bool __is_pointer_p() const { return true; } - }; - - /** - * Pointer to member type info. - */ - struct __pointer_to_member_type_info : public __pbase_type_info - { - virtual ~__pointer_to_member_type_info(); - /** - * Pointer to the class containing this member. - */ - const __class_type_info *__context; - }; - -} + * Pointer to the class containing this member. + */ + const __class_type_info *__context; + }; + +} diff --git a/contrib/libs/cxxsupp/libcxxrt/unwind.h b/contrib/libs/cxxsupp/libcxxrt/unwind.h index cd163ddfdc..ae60f16bfb 100644 --- a/contrib/libs/cxxsupp/libcxxrt/unwind.h +++ b/contrib/libs/cxxsupp/libcxxrt/unwind.h @@ -1,20 +1,20 @@ -#pragma once - +#pragma once + #include <contrib/libs/libunwind/include/unwind.h> - -#define DECLARE_PERSONALITY_FUNCTION(name) \ + +#define DECLARE_PERSONALITY_FUNCTION(name) \ _Unwind_Reason_Code name(int version,\ _Unwind_Action actions,\ uint64_t exceptionClass,\ struct _Unwind_Exception *exceptionObject,\ struct _Unwind_Context *context); -#define BEGIN_PERSONALITY_FUNCTION(name) \ +#define BEGIN_PERSONALITY_FUNCTION(name) \ _Unwind_Reason_Code name(int version,\ _Unwind_Action actions,\ uint64_t exceptionClass,\ struct _Unwind_Exception *exceptionObject,\ struct _Unwind_Context *context)\ -{ - -#define CALL_PERSONALITY_FUNCTION(name) name(version, actions, exceptionClass, exceptionObject, context) +{ + +#define CALL_PERSONALITY_FUNCTION(name) name(version, actions, exceptionClass, exceptionObject, context) diff --git a/contrib/libs/cxxsupp/libcxxrt/ya.make b/contrib/libs/cxxsupp/libcxxrt/ya.make index 12dccbd505..3de9f14fed 100644 --- a/contrib/libs/cxxsupp/libcxxrt/ya.make +++ b/contrib/libs/cxxsupp/libcxxrt/ya.make @@ -1,6 +1,6 @@ # Generated by devtools/yamaker from nixpkgs 9ee8bd188933750be0584f285daf9a295d0c8930. -LIBRARY() +LIBRARY() LICENSE( BSD-2-Clause AND @@ -18,7 +18,7 @@ OWNER( g:cpp-committee g:cpp-contrib ) - + VERSION(2021-09-08-14bf5d5526056ae1cc16f03b7b8e96108a1e38d0) ORIGINAL_SOURCE(https://github.com/libcxxrt/libcxxrt/archive/14bf5d5526056ae1cc16f03b7b8e96108a1e38d0.tar.gz) @@ -47,13 +47,13 @@ IF (SANITIZER_TYPE == undefined OR FUZZING) ENDIF() SRCS( - auxhelper.cc + auxhelper.cc dynamic_cast.cc - exception.cc - guard.cc + exception.cc + guard.cc memory.cc stdexcept.cc - typeinfo.cc -) - -END() + typeinfo.cc +) + +END() |