]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/libs/exception/src/clone_current_exception_non_intrusive.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / exception / src / clone_current_exception_non_intrusive.cpp
index 1710cd74ac067a7666d03092a3ce3fecc781d920..7ebd7b5894ee115f043783b1bd0173e85c89ef24 100644 (file)
 #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)
+#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>
-#ifndef BOOST_NO_RTTI
-#include <typeinfo>
-#endif
 #include <windows.h>
 #include <malloc.h>
 
@@ -32,8 +31,10 @@ namespace
 
 #if _MSC_VER==1310
     int const exception_info_offset=0x74;
-#elif (_MSC_VER==1400 || _MSC_VER==1500)
+#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
@@ -58,7 +59,11 @@ namespace
 
     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
@@ -72,10 +77,18 @@ namespace
     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
         {
@@ -83,45 +96,46 @@ namespace
         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;
-#ifndef BOOST_NO_RTTI
-        void const * type_info;
-#else
-        std::type_info * type_info;
-#endif
+        int type_info;
         int this_offset;
         int vbase_descr;
         int vbase_offset;
         unsigned long size;
-        cpp_copy_constructor copy_constructor;
+        int copy_constructor;
         };
 
     struct
     cpp_type_info_table
         {
         unsigned count;
-        const cpp_type_info * info[1];
+        int info;
         };
 
     struct
     cpp_exception_type
         {
         unsigned flags;
-        destructor_ptr destructor;
-        void(*custom_handler)();
-        cpp_type_info_table const * type_info_table;
+        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 ):
-            et_(et)
+        exception_object_deleter( cpp_exception_type const & et, size_t image_base ):
+            et_(et),
+            image_base_(image_base)
             {
             }
 
@@ -129,45 +143,54 @@ namespace
         operator()( void * obj )
             {
             BOOST_ASSERT(obj!=0);
-            dummy_exception_type * dummy_exception_ptr=reinterpret_cast<dummy_exception_type *>(obj);
-            (dummy_exception_ptr->*(et_.destructor))();
+            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 )
+    get_cpp_type_info( cpp_exception_type const & et, size_t image_base )
         {
-        cpp_type_info const * ti = et.type_info_table->info[0];
+        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 )
+    copy_msvc_exception( void * dst, void * src, cpp_type_info const & ti, size_t image_base )
         {
-        if( !(ti.flags & class_is_simple_type) && ti.copy_constructor.normal_copy_constructor )
+        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 = reinterpret_cast<dummy_exception_type *>(dst);
+            dummy_exception_type * dummy_exception_ptr = static_cast<dummy_exception_type *>(dst);
             if( ti.flags & class_has_virtual_base )
-                (dummy_exception_ptr->*(ti.copy_constructor.copy_constructor_with_virtual_base))(src,dst);
+                (dummy_exception_ptr->*(copy_constructor.copy_constructor_with_virtual_base))(src,dst);
             else
-                (dummy_exception_ptr->*(ti.copy_constructor.normal_copy_constructor))(src);
+                (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 )
+    clone_msvc_exception( void * src, cpp_exception_type const & et, size_t image_base )
         {
-        assert(src!=0);
-        cpp_type_info const & ti=get_cpp_type_info(et);
+        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);
+                copy_msvc_exception(dst,src,ti,image_base);
                 }
             catch(
             ... )
@@ -175,7 +198,7 @@ namespace
                 free(dst);
                 throw;
                 }
-            return boost::shared_ptr<void>(dst,exception_object_deleter(et));
+            return boost::shared_ptr<void>(dst,exception_object_deleter(et,image_base));
             }
         else
             throw std::bad_alloc();
@@ -189,13 +212,21 @@ namespace
         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 ):
+        cloned_exception( void * exc, cpp_exception_type const & et, size_t image_base ):
             et_(et),
-            exc_(clone_msvc_exception(exc,et_))
+            image_base_(image_base),
+            exc_(clone_msvc_exception(exc,et_,image_base))
             {
             }
 
@@ -206,19 +237,22 @@ namespace
         boost::exception_detail::clone_base const *
         clone() const
             {
-            return new cloned_exception(exc_.get(),et_);
+            return new cloned_exception(exc_.get(),et_,image_base_);
             }
 
         void
         rethrow() const
             {
-            cpp_type_info const & ti=get_cpp_type_info(et_);
+            cpp_type_info const & ti=get_cpp_type_info(et_,image_base_);
             void * dst = _alloca(ti.size);
-            copy_msvc_exception(dst,exc_.get(),ti);
+            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);
             }
         };
@@ -237,8 +271,7 @@ namespace
         {
         BOOST_ASSERT(exception_info_offset>=0);
         BOOST_ASSERT(info_!=0);
-        EXCEPTION_POINTERS * info=reinterpret_cast<EXCEPTION_POINTERS *>(info_);
-        EXCEPTION_RECORD * record=info->ExceptionRecord;
+        EXCEPTION_RECORD* record = static_cast<EXCEPTION_POINTERS *>(info_)->ExceptionRecord;
         if( is_cpp_exception(record) )
             {
             if( !record->ExceptionInformation[2] )
@@ -246,9 +279,7 @@ namespace
             if( is_cpp_exception(record) && record->ExceptionInformation[2] )
                 try
                     {
-                    ptr = new cloned_exception(
-                            reinterpret_cast<void *>(record->ExceptionInformation[1]),
-                            *reinterpret_cast<cpp_exception_type const *>(record->ExceptionInformation[2]));
+                    ptr = new cloned_exception(record);
                     result = boost::exception_detail::clone_current_exception_result::success;
                     }
                 catch(
@@ -301,8 +332,6 @@ boost
 //On all other compilers, return clone_current_exception_result::not_supported.
 //On such platforms, only the intrusive enable_current_exception() cloning will work.
 
-#include <boost/config.hpp>
-
 namespace
 boost
     {