aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/boost/exception/src
diff options
context:
space:
mode:
authorbugaevskiy <bugaevskiy@yandex-team.com>2022-08-05 21:02:31 +0300
committerbugaevskiy <bugaevskiy@yandex-team.com>2022-08-05 21:02:31 +0300
commite2d7dcfcf2f7491a197faa5f43ef5e401600b1c2 (patch)
treef454b9c1ef310e6d879fd48c220e9a23302c51f8 /contrib/restricted/boost/exception/src
parentbe3095272e41e3ff7b868826c884699e9596fa43 (diff)
downloadydb-e2d7dcfcf2f7491a197faa5f43ef5e401600b1c2.tar.gz
Reimport boost/exception as a separate project
Diffstat (limited to 'contrib/restricted/boost/exception/src')
-rw-r--r--contrib/restricted/boost/exception/src/clone_current_exception_non_intrusive.cpp349
1 files changed, 349 insertions, 0 deletions
diff --git a/contrib/restricted/boost/exception/src/clone_current_exception_non_intrusive.cpp b/contrib/restricted/boost/exception/src/clone_current_exception_non_intrusive.cpp
new file mode 100644
index 00000000000..54b056d8d0e
--- /dev/null
+++ b/contrib/restricted/boost/exception/src/clone_current_exception_non_intrusive.cpp
@@ -0,0 +1,349 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the Boost Software License, Version 1.0. (See accompanying
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//This MSVC-specific cpp file implements non-intrusive cloning of exception objects.
+//Based on an exception_ptr implementation by Anthony Williams.
+
+#ifdef BOOST_NO_EXCEPTIONS
+#error This file requires exception handling to be enabled.
+#endif
+
+#include <boost/config.hpp>
+#include <boost/exception/detail/clone_current_exception.hpp>
+
+#if defined(BOOST_ENABLE_NON_INTRUSIVE_EXCEPTION_PTR) && defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+
+//Non-intrusive cloning support implemented below, only for MSVC versions mentioned above.
+//Thanks Anthony Williams!
+//Thanks to Martin Weiss for implementing 64-bit support!
+
+#include <boost/exception/exception.hpp>
+#include <boost/shared_ptr.hpp>
+#include <windows.h>
+#include <malloc.h>
+
+namespace
+ {
+ unsigned const exception_maximum_parameters=15;
+ unsigned const exception_noncontinuable=1;
+
+#if _MSC_VER==1310
+ int const exception_info_offset=0x74;
+#elif ((_MSC_VER==1400 || _MSC_VER==1500) && !defined _M_X64)
+ int const exception_info_offset=0x80;
+#elif ((_MSC_VER==1400 || _MSC_VER==1500) && defined _M_X64)
+ int const exception_info_offset=0xE0;
+#else
+ int const exception_info_offset=-1;
+#endif
+
+ struct
+ exception_record
+ {
+ unsigned long ExceptionCode;
+ unsigned long ExceptionFlags;
+ exception_record * ExceptionRecord;
+ void * ExceptionAddress;
+ unsigned long NumberParameters;
+ ULONG_PTR ExceptionInformation[exception_maximum_parameters];
+ };
+
+ struct
+ exception_pointers
+ {
+ exception_record * ExceptionRecord;
+ void * ContextRecord;
+ };
+
+ unsigned const cpp_exception_code=0xE06D7363;
+ unsigned const cpp_exception_magic_flag=0x19930520;
+#ifdef _M_X64
+ unsigned const cpp_exception_parameter_count=4;
+#else
+ unsigned const cpp_exception_parameter_count=3;
+#endif
+
+ struct
+ dummy_exception_type
+ {
+ };
+
+ typedef int(dummy_exception_type::*normal_copy_constructor_ptr)(void * src);
+ typedef int(dummy_exception_type::*copy_constructor_with_virtual_base_ptr)(void * src,void * dst);
+ typedef void (dummy_exception_type::*destructor_ptr)();
+
+ union
+ cpp_copy_constructor
+ {
+ void * address;
+ normal_copy_constructor_ptr normal_copy_constructor;
+ copy_constructor_with_virtual_base_ptr copy_constructor_with_virtual_base;
+ };
+
+ union
+ cpp_destructor
+ {
+ void * address;
+ destructor_ptr destructor;
+ };
+
+ enum
+ cpp_type_flags
+ {
+ class_is_simple_type=1,
+ class_has_virtual_base=4
+ };
+
+ // ATTENTION: On x86 fields such as type_info and copy_constructor are really pointers
+ // but on 64bit these are 32bit offsets from HINSTANCE. Hints on the 64bit handling from
+ // http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx .
+ struct
+ cpp_type_info
+ {
+ unsigned flags;
+ int type_info;
+ int this_offset;
+ int vbase_descr;
+ int vbase_offset;
+ unsigned long size;
+ int copy_constructor;
+ };
+
+ struct
+ cpp_type_info_table
+ {
+ unsigned count;
+ int info;
+ };
+
+ struct
+ cpp_exception_type
+ {
+ unsigned flags;
+ int destructor;
+ int custom_handler;
+ int type_info_table;
+ };
+
+ struct
+ exception_object_deleter
+ {
+ cpp_exception_type const & et_;
+ size_t image_base_;
+
+ exception_object_deleter( cpp_exception_type const & et, size_t image_base ):
+ et_(et),
+ image_base_(image_base)
+ {
+ }
+
+ void
+ operator()( void * obj )
+ {
+ BOOST_ASSERT(obj!=0);
+ dummy_exception_type* dummy_exception_ptr = static_cast<dummy_exception_type *>(obj);
+ if( et_.destructor )
+ {
+ cpp_destructor destructor;
+ destructor.address = reinterpret_cast<void *>(et_.destructor + image_base_);
+ (dummy_exception_ptr->*(destructor.destructor))();
+ }
+ free(obj);
+ }
+ };
+
+ cpp_type_info const &
+ get_cpp_type_info( cpp_exception_type const & et, size_t image_base )
+ {
+ cpp_type_info_table * const typearray = reinterpret_cast<cpp_type_info_table * const>(et.type_info_table + image_base);
+ cpp_type_info * const ti = reinterpret_cast<cpp_type_info * const>(typearray->info + image_base);
+ BOOST_ASSERT(ti!=0);
+ return *ti;
+ }
+
+ void
+ copy_msvc_exception( void * dst, void * src, cpp_type_info const & ti, size_t image_base )
+ {
+ cpp_copy_constructor copy_constructor;
+ copy_constructor.address = reinterpret_cast<void *>(ti.copy_constructor + image_base);
+
+ if( !(ti.flags & class_is_simple_type) && copy_constructor.normal_copy_constructor )
+ {
+ dummy_exception_type * dummy_exception_ptr = static_cast<dummy_exception_type *>(dst);
+ if( ti.flags & class_has_virtual_base )
+ (dummy_exception_ptr->*(copy_constructor.copy_constructor_with_virtual_base))(src,dst);
+ else
+ (dummy_exception_ptr->*(copy_constructor.normal_copy_constructor))(src);
+ }
+ else
+ memmove(dst,src,ti.size);
+ }
+
+ boost::shared_ptr<void>
+ clone_msvc_exception( void * src, cpp_exception_type const & et, size_t image_base )
+ {
+ BOOST_ASSERT(src!=0);
+ cpp_type_info const & ti=get_cpp_type_info(et,image_base);
+ if( void * dst = malloc(ti.size) )
+ {
+ try
+ {
+ copy_msvc_exception(dst,src,ti,image_base);
+ }
+ catch(
+ ... )
+ {
+ free(dst);
+ throw;
+ }
+ return boost::shared_ptr<void>(dst,exception_object_deleter(et,image_base));
+ }
+ else
+ throw std::bad_alloc();
+ }
+
+ class
+ cloned_exception:
+ public boost::exception_detail::clone_base
+ {
+ cloned_exception( cloned_exception const & );
+ cloned_exception & operator=( cloned_exception const & );
+
+ cpp_exception_type const & et_;
+ size_t image_base_;
+ boost::shared_ptr<void> exc_;
+
+ public:
+ cloned_exception( EXCEPTION_RECORD const * record ):
+ et_(*reinterpret_cast<cpp_exception_type const *>(record->ExceptionInformation[2])),
+ image_base_((cpp_exception_parameter_count==4) ? record->ExceptionInformation[3] : 0),
+ exc_(clone_msvc_exception(reinterpret_cast<void *>(record->ExceptionInformation[1]),et_,image_base_))
+ {
+ }
+
+ cloned_exception( void * exc, cpp_exception_type const & et, size_t image_base ):
+ et_(et),
+ image_base_(image_base),
+ exc_(clone_msvc_exception(exc,et_,image_base))
+ {
+ }
+
+ ~cloned_exception()
+ {
+ }
+
+ boost::exception_detail::clone_base const *
+ clone() const
+ {
+ return new cloned_exception(exc_.get(),et_,image_base_);
+ }
+
+ void
+ rethrow() const
+ {
+ cpp_type_info const & ti=get_cpp_type_info(et_,image_base_);
+ void * dst = _alloca(ti.size);
+ copy_msvc_exception(dst,exc_.get(),ti,image_base_);
+ ULONG_PTR args[cpp_exception_parameter_count];
+ args[0]=cpp_exception_magic_flag;
+ args[1]=reinterpret_cast<ULONG_PTR>(dst);
+ args[2]=reinterpret_cast<ULONG_PTR>(&et_);
+ if (cpp_exception_parameter_count==4)
+ args[3]=image_base_;
+
+ RaiseException(cpp_exception_code,EXCEPTION_NONCONTINUABLE,cpp_exception_parameter_count,args);
+ }
+ };
+
+ bool
+ is_cpp_exception( EXCEPTION_RECORD const * record )
+ {
+ return record &&
+ (record->ExceptionCode==cpp_exception_code) &&
+ (record->NumberParameters==cpp_exception_parameter_count) &&
+ (record->ExceptionInformation[0]==cpp_exception_magic_flag);
+ }
+
+ unsigned long
+ exception_cloning_filter( int & result, boost::exception_detail::clone_base const * & ptr, void * info_ )
+ {
+ BOOST_ASSERT(exception_info_offset>=0);
+ BOOST_ASSERT(info_!=0);
+ EXCEPTION_RECORD* record = static_cast<EXCEPTION_POINTERS *>(info_)->ExceptionRecord;
+ if( is_cpp_exception(record) )
+ {
+ if( !record->ExceptionInformation[2] )
+ record = *reinterpret_cast<EXCEPTION_RECORD * *>(reinterpret_cast<char *>(_errno())+exception_info_offset);
+ if( is_cpp_exception(record) && record->ExceptionInformation[2] )
+ try
+ {
+ ptr = new cloned_exception(record);
+ result = boost::exception_detail::clone_current_exception_result::success;
+ }
+ catch(
+ std::bad_alloc & )
+ {
+ result = boost::exception_detail::clone_current_exception_result::bad_alloc;
+ }
+ catch(
+ ... )
+ {
+ result = boost::exception_detail::clone_current_exception_result::bad_exception;
+ }
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+ }
+
+namespace
+boost
+ {
+ namespace
+ exception_detail
+ {
+ int
+ clone_current_exception_non_intrusive( clone_base const * & cloned )
+ {
+ BOOST_ASSERT(!cloned);
+ int result = clone_current_exception_result::not_supported;
+ if( exception_info_offset>=0 )
+ {
+ clone_base const * ptr=0;
+ __try
+ {
+ throw;
+ }
+ __except(exception_cloning_filter(result,ptr,GetExceptionInformation()))
+ {
+ }
+ if( result==clone_current_exception_result::success )
+ cloned=ptr;
+ }
+ BOOST_ASSERT(result!=clone_current_exception_result::success || cloned);
+ return result;
+ }
+ }
+ }
+
+#else
+
+//On all other compilers, return clone_current_exception_result::not_supported.
+//On such platforms, only the intrusive enable_current_exception() cloning will work.
+
+namespace
+boost
+ {
+ namespace
+ exception_detail
+ {
+ int
+ clone_current_exception_non_intrusive( clone_base const * & )
+ {
+ return clone_current_exception_result::not_supported;
+ }
+ }
+ }
+
+#endif