[Libreoffice-commits] .: bridges/source

Tor Lillqvist tml at kemper.freedesktop.org
Wed Feb 2 03:30:03 PST 2011


 bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx |  514 ++++++++++++--------
 1 file changed, 331 insertions(+), 183 deletions(-)

New commits:
commit 91fc632dce46c9c1b7edf81f0f556e2e0f498a93
Author: Tor Lillqvist <tlillqvist at novell.com>
Date:   Wed Feb 2 13:23:50 2011 +0200

    More work on except.cxx, intermediate commit
    
    Now I have some understanding what it is the code here should do, and
    have found 3rd-party documentation (in source code form even) for the
    exception-related data structures.
    
    It still crashes, but I hope that is just because of thinkos that need
    to be fixed by debugging, or reading the code. There are some horrible
    code with quite complex casts in places, I need to introduce some
    macros or inline functions instead to make the casting from RVAs to
    real pointers and back cleaner. Also maybe just use DWORD instead of
    sal_uInt32 for terseness, and use a specific typedef name for DWORDs
    that actually are RVAs for clarity?

diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
index 7cb9f73..a71591b 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
@@ -26,6 +26,150 @@
  *
  ************************************************************************/
 
+// Interesting info can be found in:
+
+// MSDN, obviously
+
+// http://www.osronline.com/article.cfm?article=469
+
+// ONTL, "Open NT Native Template Library", a C++ STL-like library
+// that can be used even when writing Windows drivers. This is some
+// quite badass code. The author has done impressive heavy spelunking
+// of MSVCR structures. http://code.google.com/p/ontl/
+
+// Geoff Chappell's pages:
+// http://members.ozemail.com.au/~geoffch/samples/programming/msvc/language/index.html
+
+// The below is from ONTL's ntl/nt/exception.hxx, cleaned up to keep just the _M_X64 parts:
+
+#if 0
+
+/* This information until the corresponding '#endif // 0' is covered
+ * by ONTL's license, which is said to be the "zlib/libgng license"
+ * below, which as far as I see is permissive enough to allow this
+ * information to be included here in this source file. Note that no
+ * actual code from ONTL below gets compiled into the object file.
+ */
+
+/*
+ * Copyright (c) 2011 <copyright holders> (The ONTL main
+ * developer(s) don't tell their real name(s) on the ONTL site.)
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ *     1. The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *
+ *     2. Altered source versions must be plainly marked as such, and must not be
+ *     misrepresented as being the original software.
+ *
+ *     3. This notice may not be removed or altered from any source
+ *     distribution.
+ *
+ */
+
+typedef uint32_t rva_t;
+
+///\note the calling convention should not matter since this has no arguments
+typedef void generic_function_t();
+
+  struct ptrtomember // _PMD
+  {
+    typedef __w64 int32_t  mdiff_t;
+    mdiff_t member_offset;
+    mdiff_t vbtable_offset; // -1 if not a virtual base
+    mdiff_t vdisp_offset;   // offset to the displacement value inside the vbtable
+
+    template<typename T>
+    T * operator()(T * const thisptr) const
+    {
+      uintptr_t tp = reinterpret_cast<uintptr_t>(thisptr);
+      uintptr_t ptr = tp + member_offset;
+      if ( vbtable_offset != -1 ) // !(vbtable_offset < 0)
+      {
+        ptr += *reinterpret_cast<mdiff_t*>( static_cast<intptr_t>(vdisp_offset + *reinterpret_cast<mdiff_t*>(tp + vbtable_offset)) )
+          + vbtable_offset;
+      }
+      return reinterpret_cast<T*>(ptr);
+    }
+  };
+
+struct catchabletype
+{
+    /** is simple type */
+    uint32_t    memmoveable : 1;
+    /** catchable as reference only */
+    uint32_t    refonly     : 1;
+    /** class with virtual base */
+    uint32_t    hasvirtbase : 1;
+    /** offset to the type descriptor */
+    rva_t       typeinfo;
+
+    /** catch type instance location within a thrown object  */
+    ptrtomember thiscast;
+    /** size of the simple type or offset into buffer of \c this pointer for catch object */
+    uint32_t    object_size;
+
+    union
+    {
+      rva_t               copyctor;
+      rva_t               copyctor2;
+    };
+  };
+
+#pragma pack(push, 4)
+  struct catchabletypearray
+  {
+    uint32_t        size;
+    rva_t           type[1];
+  };
+#pragma pack(pop)
+
+#pragma pack(push, 4)
+ struct throwinfo
+  {
+    typedef exception_disposition __cdecl forwardcompathandler_t(...);
+
+    /* 0x00 */  uint32_t  econst    : 1;
+    /* 0x00 */  uint32_t  evolatile : 1;
+    /* 0x00 */  uint32_t            : 1;
+    /* 0x00 */  uint32_t  e8        : 1;
+    /* 0x04 */  rva_t     exception_dtor;
+    /* 0x08 */  rva_t     forwardcompathandler;
+    /* 0x0C */  rva_t     catchabletypearray; ///< types able to catch the exception.
+  };
+#pragma pack(pop)
+
+  /// This type represents the catch clause
+  struct ehandler
+  {
+    //  union { uint32_t  adjectives; void * ptr; };
+    uint32_t isconst      : 1;
+    uint32_t isvolatile   : 1;
+    uint32_t isunaligned  : 1;// guess it is not used on x86
+    uint32_t isreference  : 1;
+
+    uint32_t              :27;
+    uint32_t ishz         : 1;
+
+    /** offset to the type descriptor of this catch object */
+    /*0x04*/ rva_t        typeinfo;         // dispType
+    /*0x08*/ int          eobject_bpoffset; // dispCatchObj
+    /** offset to the catch clause funclet */
+    /*0x0C*/ rva_t        handler;          // dispOfHandler
+    /*0x10*/ uint32_t     frame;            // dispFrame
+  }
+
+#endif // 0
+
 // MARKER(update_precomp.py): autogen include statement, do not remove
 #include "precompiled_bridges.hxx"
 
@@ -181,202 +325,185 @@ RTTInfos::~RTTInfos() throw ()
     }
 }
 
-struct ObjectFunction
-{
-    char somecode[12];
-    typelib_TypeDescription * _pTypeDescr; // type of object
-
-    inline static void * operator new ( size_t nSize );
-    inline static void operator delete ( void * pMem );
-    
-    ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ) throw ();
-    ~ObjectFunction() throw ();
-};
-
-inline void * ObjectFunction::operator new(
-    size_t nSize ) 
-{
-    void * pMem = rtl_allocateMemory( nSize );
-    if (pMem != 0)
-    {
-        DWORD old_protect;
-#if OSL_DEBUG_LEVEL > 0
-        BOOL success =
-#endif
-        VirtualProtect( pMem, nSize, PAGE_EXECUTE_READWRITE, &old_protect );
-        OSL_ENSURE( success, "VirtualProtect() failed!" );
-    }
-    return pMem;
-}
-
-inline void ObjectFunction::operator delete(
-    void * pMem )
-{
-    rtl_freeMemory( pMem );
-}
-
-ObjectFunction::ObjectFunction(
-    typelib_TypeDescription * pTypeDescr,
-    void * fpFunc ) throw ()
-    : _pTypeDescr( pTypeDescr )
-{
-    ::typelib_typedescription_acquire( _pTypeDescr );
-
-    unsigned char * pCode = (unsigned char *)somecode;
-    // a must be!
-    OSL_ENSURE( (void *)this == (void *)pCode, "### unexpected!" );
-
-    // push ObjectFunction this
-    *pCode++ = 0x68;
-    *(void **)pCode = this;
-    pCode += sizeof(void *);
-    // jmp rel64 fpFunc
-    *pCode++ = 0xe9;
-    *(sal_Int64 *)pCode = ((unsigned char *)fpFunc) - pCode - sizeof(sal_Int64);
-}
-
-ObjectFunction::~ObjectFunction() throw ()
-{
-    ::typelib_typedescription_release( _pTypeDescr );
-}
-
-
-void * __cdecl __copyConstruct(
+void * __cdecl copyConstruct(
     void * pExcThis,
     void * pSource,
-    ObjectFunction * pThis )
-    throw ()
+    typelib_TypeDescription * pTD ) throw ()
 {
-    ::uno_copyData( pExcThis, pSource, pThis->_pTypeDescr, cpp_acquire );
+    ::uno_copyData( pExcThis, pSource, pTD, cpp_acquire );
     return pExcThis;
 }
 
-void * __cdecl __destruct(
+void * __cdecl destruct(
     void * pExcThis,
-    ObjectFunction * pThis )
-    throw ()
+    typelib_TypeDescription * pTD ) throw ()
 {
-    ::uno_destructData( pExcThis, pThis->_pTypeDescr, cpp_release );
+    ::uno_destructData( pExcThis, pTD, cpp_release );
     return pExcThis;
 }
 
-#if 0
-
-// These are machine code snippets in asmbits.asm
+const int codeSnippetSize = 40;
 
-extern void *copyConstruct;
-extern void *destruct;
-
-#else
-
-static void whatthefuck_copyctor(sal_Int64 i, ...)
+void GenerateConstructorTrampoline(
+    sal_uChar * pCode,
+    typelib_TypeDescription * pTD ) throw ()
 {
-    MessageBoxA (NULL, "Shit!", "whatthefuck_copyctor in except.cxx", MB_OK);
+    // push typelib_TypeDescription pTD
+    *pCode++ = 0x68;
+    *(void **)pCode = pTD;
+    pCode += sizeof(void *);
+    // jmp rel64 fpFunc
+    *pCode++ = 0xe9;
+    *(sal_Int64 *)pCode = (sal_uChar *)&copyConstruct - pCode - sizeof(sal_Int64);
 }
 
-static void whatthefuck_dtor(sal_Int64 i, ...)
+void GenerateDestructorTrampoline(
+    sal_uChar * pCode,
+    typelib_TypeDescription * pTD ) throw ()
 {
-    MessageBoxA (NULL, "Shit!", "whatthefuck_dtor in except.cxx", MB_OK);
+    // mov rdx, pTD
+    *pCode++ = 0x68;
+    *(void **)pCode = pTD;
+    pCode += sizeof(void *);
+    // jmp rel64 fpFunc
+    *pCode++ = 0xe9;
+    *(sal_Int64 *)pCode = (sal_uChar *)destruct - pCode - sizeof(sal_Int64);
 }
 
-#endif
+// This looks like it is the struct catchabletype above
 
 struct ExceptionType
 {
-    sal_Int32           _n0;
-    type_info *         _pTypeInfo;
-    sal_Int32           _n1, _n2, _n3, _n4;
-    ObjectFunction *    _pCopyCtor;
-    sal_Int32           _n5;
-
-    inline ExceptionType( typelib_TypeDescription * pTypeDescr ) throw ()
+    sal_Int32   _n0;            // flags
+    sal_uInt32  _pTypeInfo;     // typeinfo
+    sal_Int32   _n1, _n2, _n3;  // thiscast
+    sal_Int32   _n4;            // object_size
+    sal_uInt32  _pCopyCtor;     // copyctor
+
+    inline ExceptionType(
+        sal_uChar * pCode,
+        sal_uInt64 pCodeBase,
+        typelib_TypeDescription * pTD ) throw ()
         : _n0( 0 )
         , _n1( 0 )
         , _n2( -1 )
         , _n3( 0 )
-        , _n4( pTypeDescr->nSize )
-#if 0
-        , _pCopyCtor( new ObjectFunction( pTypeDescr, copyConstruct ) )
-#else
-        , _pCopyCtor( (ObjectFunction*) whatthefuck_copyctor )
-#endif
-        , _n5( 0 )
-        { _pTypeInfo = mscx_getRTTI( pTypeDescr->pTypeName ); }
+        , _n4( pTD->nSize )
+        {
+            _pTypeInfo = (sal_uInt32) ((sal_uInt64) mscx_getRTTI( pTD->pTypeName ) - pCodeBase);
+            GenerateConstructorTrampoline( pCode, pTD );
+            _pCopyCtor = (sal_uInt32) ((sal_uInt64) pCode - pCodeBase);
+        }
     inline ~ExceptionType() throw ()
-        { delete _pCopyCtor; }
+        {
+        }
 };
 
+struct RaiseInfo;
+
+class ExceptionInfos
+{
+    Mutex           _aMutex;
+    t_string2PtrMap _allRaiseInfos;
+
+public:
+    static RaiseInfo * getRaiseInfo( typelib_TypeDescription * pTD ) throw ();
+
+    static DWORD allocationGranularity;
+
+    ExceptionInfos() throw ();
+    ~ExceptionInfos() throw ();
+};
+
+DWORD ExceptionInfos::allocationGranularity = 0;
+
+// This corresponds to the struct throwinfo described above.
+
 struct RaiseInfo
 {
     sal_Int32           _n0;
-    ObjectFunction *    _pDtor;
+    sal_uInt32          _pDtor;
     sal_Int32           _n2;
-    void *              _types;
-    sal_Int32           _n3, _n4;
+    sal_uInt32          _types;
+
+    // Additional fields
+    typelib_TypeDescription * _pTD;
+    sal_uChar *        _code;
+    sal_uInt64         _codeBase;
+
+    RaiseInfo( typelib_TypeDescription * pTD ) throw ();
 
-    RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ();
     ~RaiseInfo() throw ();
 };
 
-RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
+RaiseInfo::RaiseInfo( typelib_TypeDescription * pTD )throw ()
     : _n0( 0 )
-#if 0
-    , _pDtor( new ObjectFunction( pTypeDescr, destruct ) )
-#else
-    , _pDtor( (ObjectFunction*) whatthefuck_dtor )
-#endif
     , _n2( 0 )
-    , _n3( 0 )
-    , _n4( 0 )
+    , _pTD( pTD )
 {
-    typelib_CompoundTypeDescription * pCompTypeDescr;
+    typelib_CompoundTypeDescription * pCompTD;
+
+    // Count how many trampolines we need
+    int codeSize = codeSnippetSize;
 
-    // info count
-    sal_Int32 nLen = 0;
-    for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr;
-          pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
+    // Info count
+    int nLen = 0;
+    for ( pCompTD = (typelib_CompoundTypeDescription*)pTD;
+          pCompTD; pCompTD = pCompTD->pBaseTypeDescription )
     {
         ++nLen;
+        codeSize += codeSnippetSize;
     }
 
-    // info count accompanied by type info ptrs: type, base type, base base type, ...
-    _types = ::rtl_allocateMemory( sizeof(sal_Int64) + (sizeof(ExceptionType *) * nLen) );
-    *(sal_Int64 *)_types = nLen;
+    sal_uChar * pCode = _code = (sal_uChar *)::rtl_allocateMemory( codeSize );
+
+    _codeBase = (sal_uInt64)pCode & ~(ExceptionInfos::allocationGranularity-1);
+
+    DWORD old_protect;
+#if OSL_DEBUG_LEVEL > 0
+    BOOL success =
+#endif
+        VirtualProtect( pCode, codeSize, PAGE_EXECUTE_READWRITE, &old_protect );
+        OSL_ENSURE( success, "VirtualProtect() failed!" );
+
+    ::typelib_typedescription_acquire( pTD );
 
-    ExceptionType ** ppTypes = (ExceptionType **)((sal_Int64 *)_types + 1);
+    GenerateDestructorTrampoline( pCode, pTD );
+    _pDtor = (sal_Int32)((sal_uInt64)pCode - _codeBase);
+    pCode += codeSnippetSize;
 
-    sal_Int32 nPos = 0;
-    for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr;
-          pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
+    // Info count accompanied by type info ptrs: type, base type, base base type, ...
+    _types = (sal_Int32)((sal_uInt64)::rtl_allocateMemory( 4 + 4* nLen) - _codeBase);
+    *(sal_Int32 *)_types = nLen;
+
+    ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1);
+
+    int nPos = 0;
+    for ( pCompTD = (typelib_CompoundTypeDescription*)pTD;
+          pCompTD; pCompTD = pCompTD->pBaseTypeDescription )
     {
-        ppTypes[nPos++] = new ExceptionType( (typelib_TypeDescription *)pCompTypeDescr );
+        ppTypes[nPos++] =
+            new ExceptionType( pCode, _codeBase,
+                               (typelib_TypeDescription *)pCompTD );
+        pCode += codeSnippetSize;
     }
 }
 
 RaiseInfo::~RaiseInfo() throw ()
 {
-    ExceptionType ** ppTypes = (ExceptionType **)((sal_Int64 *)_types + 1);
-    for ( sal_Int32 nTypes = *(sal_Int64 *)_types; nTypes--; )
+    sal_uInt32 * pTypes =
+        (sal_uInt32 *)(_codeBase + _types) + 1;
+
+    for ( int nTypes = *(sal_uInt32 *)(_codeBase + _types); nTypes--; )
     {
-        delete ppTypes[nTypes];
+        delete (ExceptionType *) (_codeBase + pTypes[nTypes]);
     }
-    ::rtl_freeMemory( _types );
+    ::rtl_freeMemory( (void*)(_codeBase +_types) );
+    ::rtl_freeMemory( _code );
 
-    delete _pDtor;
+    ::typelib_typedescription_release( _pTD );
 }
 
-class ExceptionInfos
-{
-    Mutex           _aMutex;
-    t_string2PtrMap _allRaiseInfos;
-
-public:
-    static void * getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ();
-
-    ExceptionInfos() throw ();
-    ~ExceptionInfos() throw ();
-};
-
 ExceptionInfos::ExceptionInfos() throw ()
 {
 }
@@ -394,8 +521,8 @@ ExceptionInfos::~ExceptionInfos() throw ()
         delete (RaiseInfo *)iPos->second;
     }
 }
-void * ExceptionInfos::getRaiseInfo(
-    typelib_TypeDescription * pTypeDescr ) throw ()
+
+RaiseInfo * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTD ) throw ()
 {
     static ExceptionInfos * s_pInfos = 0;
     if (! s_pInfos)
@@ -403,6 +530,10 @@ void * ExceptionInfos::getRaiseInfo(
         MutexGuard aGuard( Mutex::getGlobalMutex() );
         if (! s_pInfos)
         {
+            SYSTEM_INFO systemInfo;
+            GetSystemInfo( &systemInfo );
+            allocationGranularity = systemInfo.dwAllocationGranularity;
+
 #ifdef LEAK_STATIC_DATA
             s_pInfos = new ExceptionInfos();
 #else
@@ -412,28 +543,29 @@ void * ExceptionInfos::getRaiseInfo(
         }
     }
 
-    OSL_ASSERT( pTypeDescr &&
-                (pTypeDescr->eTypeClass == typelib_TypeClass_STRUCT ||
-                 pTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION) );
+    OSL_ASSERT( pTD &&
+                (pTD->eTypeClass == typelib_TypeClass_STRUCT ||
+                 pTD->eTypeClass == typelib_TypeClass_EXCEPTION) );
 
-    void * pRaiseInfo;
+    RaiseInfo * pRaiseInfo;
 
-    OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTypeDescr->pTypeName );
+    OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTD->pTypeName );
     MutexGuard aGuard( s_pInfos->_aMutex );
     t_string2PtrMap::const_iterator const iFind(
         s_pInfos->_allRaiseInfos.find( rTypeName ) );
     if (iFind == s_pInfos->_allRaiseInfos.end())
     {
-        pRaiseInfo = new RaiseInfo( pTypeDescr );
-        // put into map
+        pRaiseInfo = new RaiseInfo( pTD );
+
+        // Put into map
         pair< t_string2PtrMap::iterator, bool > insertion(
-            s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, pRaiseInfo ) ) );
+            s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, (void *)pRaiseInfo ) ) );
         OSL_ENSURE( insertion.second, "### raise info insertion failed?!" );
     }
     else
     {
-        // reuse existing info
-        pRaiseInfo = iFind->second;
+        // Reuse existing info
+        pRaiseInfo = (RaiseInfo *)iFind->second;
     }
 
     return pRaiseInfo;
@@ -464,24 +596,25 @@ void mscx_raiseException(
     uno_Mapping * pUno2Cpp )
 {
     // no ctor/dtor in here: this leads to dtors called twice upon RaiseException()!
-    // thus this obj file will be compiled without opt, so no inling of
+    // thus this obj file will be compiled without opt, so no inlining of
     // ExceptionInfos::getRaiseInfo()
 
     // construct cpp exception object
-    typelib_TypeDescription * pTypeDescr = 0;
-    TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
+    typelib_TypeDescription * pTD = NULL;
+    TYPELIB_DANGER_GET( &pTD, pUnoExc->pType );
 
-    void * pCppExc = alloca( pTypeDescr->nSize );
-    ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
+    void * pCppExc = alloca( pTD->nSize );
+    ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTD, pUno2Cpp );
 
-    ULONG_PTR arFilterArgs[3];
+    ULONG_PTR arFilterArgs[4];
     arFilterArgs[0] = MSVC_magic_number;
     arFilterArgs[1] = (ULONG_PTR)pCppExc;
-    arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTypeDescr );
+    arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTD );
+    arFilterArgs[3] = ((RaiseInfo *)arFilterArgs[2])->_codeBase;
 
-    // destruct uno exception
+    // Destruct uno exception
     ::uno_any_destruct( pUnoExc, 0 );
-    TYPELIB_DANGER_RELEASE( pTypeDescr );
+    TYPELIB_DANGER_RELEASE( pTD );
 
     // last point to release anything not affected by stack unwinding
     RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs );
@@ -494,8 +627,10 @@ int mscx_filterCppException(
 {
     if (pPointers == 0)
         return EXCEPTION_CONTINUE_SEARCH;
+
     EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord;
-    // handle only C++ exceptions:
+
+    // Handle only C++ exceptions:
     if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
         return EXCEPTION_CONTINUE_SEARCH;
     
@@ -504,13 +639,13 @@ int mscx_filterCppException(
 
     if (rethrow && pRecord == pPointers->ExceptionRecord)
     {
-        // hack to get msvcrt internal _curexception field:
+        // Hack to get msvcrt internal _curexception field:
         pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >(
             reinterpret_cast< char * >( __pxcptinfoptrs() ) +
-            // as long as we don't demand msvcr source as build prerequisite
-            // (->platform sdk), we have to code those offsets here.
+            // As long as we don't demand MSVCR source as build prerequisite,
+            // we have to code those offsets here.
             //
-            // crt\src\mtdll.h:
+            // MSVS9/crt/src/mtdll.h:
             // offsetof (_tiddata, _curexception) -
             // offsetof (_tiddata, _tpxcptinfoptrs):
 #if _MSC_VER < 1500
@@ -522,34 +657,47 @@ int mscx_filterCppException(
 #endif
             );
     }
-    // rethrow: handle only C++ exceptions:
+
+    // Rethrow: handle only C++ exceptions:
     if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
         return EXCEPTION_CONTINUE_SEARCH;
     
-    if (pRecord->NumberParameters == 3 &&
-//          pRecord->ExceptionInformation[ 0 ] == MSVC_magic_number &&
-        pRecord->ExceptionInformation[ 1 ] != 0 &&
-        pRecord->ExceptionInformation[ 2 ] != 0)
+    if (pRecord->NumberParameters == 4 &&
+        pRecord->ExceptionInformation[0] == MSVC_magic_number &&
+        pRecord->ExceptionInformation[1] != 0 &&
+        pRecord->ExceptionInformation[2] != 0 &&
+        pRecord->ExceptionInformation[3] != 0)
     {
-        void * types = reinterpret_cast< RaiseInfo * >(
-            pRecord->ExceptionInformation[ 2 ] )->_types;
-        if (types != 0 && *reinterpret_cast< DWORD * >( types ) > 0) // count
+        // ExceptionInformation[1] is the address of the thrown object
+        // (or the address of a pointer to it, in most cases when it
+        // is a C++ class, obviously).
+
+        // [2] is the throwinfo pointer
+
+        // [3] is the image base address which is added the 32-bit
+        // rva_t fields in throwinfo to get actual 64-bit addresses
+
+        void * types =
+            (void *) (pRecord->ExceptionInformation[3] +
+                      ((RaiseInfo *)pRecord->ExceptionInformation[2])->_types);
+
+        if (types != 0 && *(DWORD *)types > 0)
         {
-            ExceptionType * pType = *reinterpret_cast< ExceptionType ** >(
-                reinterpret_cast< DWORD * >( types ) + 1 );
-            if (pType != 0 && pType->_pTypeInfo != 0)
+            DWORD pType = *((DWORD *)types + 1);
+            if (pType != 0 &&
+                ((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo != 0)
             {
                 OUString aRTTIname(
                     OStringToOUString(
                         reinterpret_cast< __type_info * >(
-                            pType->_pTypeInfo )->_m_d_name,
+                            ((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo )->_m_d_name,
                         RTL_TEXTENCODING_ASCII_US ) );
                 OUString aUNOname( toUNOname( aRTTIname ) );
                 
-                typelib_TypeDescription * pExcTypeDescr = 0;
+                typelib_TypeDescription * pExcTD = 0;
                 typelib_typedescription_getByName(
-                    &pExcTypeDescr, aUNOname.pData );
-                if (pExcTypeDescr == 0)
+                    &pExcTD, aUNOname.pData );
+                if (pExcTD == NULL)
                 {
                     OUStringBuffer buf;
                     buf.appendAscii(
@@ -578,16 +726,16 @@ int mscx_filterCppException(
                     // construct uno exception any
                     uno_any_constructAndConvert(
                         pUnoExc, (void *) pRecord->ExceptionInformation[1],
-                        pExcTypeDescr, pCpp2Uno );
+                        pExcTD, pCpp2Uno );
 #if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
                     if (! rethrow)
                     {
                         uno_destructData(
                             (void *) pRecord->ExceptionInformation[1],
-                            pExcTypeDescr, cpp_release );
+                            pExcTD, cpp_release );
                     }
 #endif
-                    typelib_typedescription_release( pExcTypeDescr );
+                    typelib_typedescription_release( pExcTD );
                 }
                 
                 return EXCEPTION_EXECUTE_HANDLER;


More information about the Libreoffice-commits mailing list