diff options
Diffstat (limited to 'bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx')
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx | 667 |
1 files changed, 447 insertions, 220 deletions
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 bb5c5b1922b8..2157568ad915 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx @@ -26,11 +26,227 @@ * ************************************************************************/ +// 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 eobject +{ + typedef void (* dtor_ptr )(eobject*); + typedef void (* ctor_ptr )(eobject*, eobject*); + typedef void (* ctor_ptr2)(eobject*, eobject*, int); +}; + +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 +} + +// ___BuildCatchObject +/// 15.3/16 When the exception-declaration specifies a class type, a copy +/// constructor is used to initialize either the object declared +/// in the exception-declaration or, +/// if the exception-declaration does not specify a name, +/// a temporary object of that type. +///\note This is the question may we optimize out the last case. +///\warning If the copy constructor throws an exception, std::unexpected would be called +void + constructcatchobject( + cxxregistration * cxxreg, + const ehandler * const catchblock, + catchabletype * const convertable, + const dispatcher_context* const dispatch + ) + const +{ + _EH_TRACE_ENTER(); + // build helper + __try { + struct typeinfo_t { void* vtbl; void* spare; char name[1]; }; + enum catchable_info { cidefault, cicomplex, civirtual } cinfo = cidefault; + + const typeinfo_t* ti = catchblock->typeinfo ? dispatch->va<typeinfo_t*>(catchblock->typeinfo) : NULL; + if(ti && *ti->name && (catchblock->eobject_bpoffset || catchblock->ishz)){ + eobject** objplace = catchblock->ishz + ? reinterpret_cast<eobject**>(cxxreg) + : reinterpret_cast<eobject**>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers); + if(catchblock->isreference){ + // just ref/pointer + *objplace = adjust_pointer(get_object(), convertable); + }else if(convertable->memmoveable){ + // POD + std::memcpy(objplace, get_object(), convertable->object_size); + if(convertable->object_size == sizeof(void*) && *objplace) + *objplace = adjust_pointer((void*)*objplace, convertable); + }else{ + // if copy ctor exists, call it; binary copy otherwise + if(convertable->copyctor){ + cinfo = convertable->hasvirtbase ? civirtual : cicomplex; + }else{ + std::memcpy(objplace, (const void*)adjust_pointer(get_object(), convertable), convertable->object_size); + } + } + } + // end of build helper + if(cinfo != cidefault){ + eobject* objthis = catchblock->ishz + ? reinterpret_cast<eobject*>(cxxreg) + : reinterpret_cast<eobject*>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers); + void* copyctor = thrown_va(convertable->copyctor); + eobject* copyarg = adjust_pointer(get_object(), convertable); + if(cinfo == cicomplex) + (eobject::ctor_ptr (copyctor))(objthis, copyarg); + else + (eobject::ctor_ptr2(copyctor))(objthis, copyarg, 1); + } + } + __except(cxxregistration::unwindfilter(static_cast<nt::ntstatus>(_exception_code()))) + { + nt::exception::inconsistency(); + } + _EH_TRACE_LEAVE(); +} + +#endif // 0 + // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_bridges.hxx" #pragma warning( disable : 4237 ) -#include <hash_map> +#include <boost/unordered_map.hpp> #include <sal/config.h> #include <malloc.h> #include <new.h> @@ -45,7 +261,6 @@ #include "mscx.hxx" - #pragma pack(push, 8) using namespace ::com::sun::star::uno; @@ -56,8 +271,9 @@ using namespace ::rtl; namespace CPPU_CURRENT_NAMESPACE { -//================================================================================================== -static inline OUString toUNOname( OUString const & rRTTIname ) throw () +static inline OUString toUNOname( + OUString const & rRTTIname ) + throw () { OUStringBuffer aRet( 64 ); OUString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz@yyy@xxx@@ @@ -74,8 +290,10 @@ static inline OUString toUNOname( OUString const & rRTTIname ) throw () } return aRet.makeStringAndClear(); } -//================================================================================================== -static inline OUString toRTTIname( OUString const & rUNOname ) throw () + +static inline OUString toRTTIname( + OUString const & rUNOname ) + throw () { OUStringBuffer aRet( 64 ); aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM(".?AV") ); // class ".?AV"; struct ".?AU" @@ -91,15 +309,10 @@ static inline OUString toRTTIname( OUString const & rUNOname ) throw () return aRet.makeStringAndClear(); } +//RTTI simulation -//################################################################################################## -//#### RTTI simulation ############################################################################# -//################################################################################################## - - -typedef hash_map< OUString, void *, OUStringHash, equal_to< OUString > > t_string2PtrMap; +typedef boost::unordered_map< OUString, void *, OUStringHash, equal_to< OUString > > t_string2PtrMap; -//================================================================================================== class RTTInfos { Mutex _aMutex; @@ -113,7 +326,6 @@ public: ~RTTInfos(); }; -//================================================================================================== class __type_info { friend type_info * RTTInfos::getRTTI( OUString const & ) throw (); @@ -131,11 +343,11 @@ private: void * _m_data; char _m_d_name[1]; }; -//__________________________________________________________________________________________________ + __type_info::~__type_info() throw () { } -//__________________________________________________________________________________________________ + type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw () { // a must be @@ -164,11 +376,11 @@ type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw () return (type_info *)iFind->second; } } -//__________________________________________________________________________________________________ + RTTInfos::RTTInfos() throw () { } -//__________________________________________________________________________________________________ + RTTInfos::~RTTInfos() throw () { #if OSL_DEBUG_LEVEL > 1 @@ -185,208 +397,206 @@ RTTInfos::~RTTInfos() throw () } } - -//################################################################################################## -//#### Exception raising ########################################################################### -//################################################################################################## - - -//================================================================================================== -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 * pExcThis, void * pSource, ObjectFunction * pThis ) - throw () +void * __cdecl copyConstruct( + void * pExcThis, + void * pSource, + 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 * pExcThis, ObjectFunction * pThis ) - throw () + +void * __cdecl destruct( + void * pExcThis, + typelib_TypeDescription * pTD ) throw () { - ::uno_destructData( pExcThis, pThis->_pTypeDescr, cpp_release ); + ::uno_destructData( pExcThis, pTD, cpp_release ); return pExcThis; } +const int codeSnippetSize = 40; -#if 0 +void GenerateConstructorTrampoline( + unsigned char * code, + typelib_TypeDescription * pTD ) throw () +{ + unsigned char *p = code; -// These are machine code snippets in asmbits.asm + // mov r8, pTD + *p++ = 0x49; *p++ = 0xB8; + *((void **)p) = pTD; p += 8; -extern void *copyConstruct; -extern void *destruct; + // mov r11, copyConstruct + *p++ = 0x49; *p++ = 0xBB; + *((void **)p) = ©Construct; p += 8; -#else + // jmp r11 + *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3; -static void whatthefuck_copyctor(sal_Int64 i, ...) -{ - MessageBoxA (NULL, "Shit!", "whatthefuck_copyctor in except.cxx", MB_OK); + OSL_ASSERT( p < code + codeSnippetSize ); } -static void whatthefuck_dtor(sal_Int64 i, ...) +void GenerateDestructorTrampoline( + unsigned char * code, + typelib_TypeDescription * pTD ) throw () { - MessageBoxA (NULL, "Shit!", "whatthefuck_dtor in except.cxx", MB_OK); + unsigned char *p = code; + + // mov rdx, pTD + *p++ = 0x48; *p++ = 0xBA; + *((void **)p) = pTD; p += 8; + + // mov r11, destruct + *p++ = 0x49; *p++ = 0xBB; + *((void **)p) = &destruct; p += 8; + + // jmp r11 + *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3; + + OSL_ASSERT( p < code + codeSnippetSize ); } -#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 ) + { + // As _n0 is always initialized to zero, that means the + // hasvirtbase flag (see the ONTL catchabletype struct) is + // off, and thus the copyctor is of the ctor_ptr kind. + _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 ); + + GenerateDestructorTrampoline( pCode, pTD ); + _pDtor = (sal_Int32)((sal_uInt64)pCode - _codeBase); + pCode += codeSnippetSize; + + // 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_Int64 *)_types + 1); + ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1); - sal_Int32 nPos = 0; - for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr; - pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + 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 () { } -//__________________________________________________________________________________________________ + ExceptionInfos::~ExceptionInfos() throw () { #if OSL_DEBUG_LEVEL > 1 @@ -400,8 +610,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) @@ -409,6 +619,10 @@ void * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTypeDescr ) thro MutexGuard aGuard( Mutex::getGlobalMutex() ); if (! s_pInfos) { + SYSTEM_INFO systemInfo; + GetSystemInfo( &systemInfo ); + allocationGranularity = systemInfo.dwAllocationGranularity; + #ifdef LEAK_STATIC_DATA s_pInfos = new ExceptionInfos(); #else @@ -418,41 +632,36 @@ void * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTypeDescr ) thro } } - 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; } - -//################################################################################################## -//#### exported #################################################################################### -//################################################################################################## - - -//################################################################################################## -type_info * mscx_getRTTI( OUString const & rUNOname ) +type_info * mscx_getRTTI( + OUString const & rUNOname ) { static RTTInfos * s_pRTTIs = 0; if (! s_pRTTIs) @@ -471,41 +680,46 @@ type_info * mscx_getRTTI( OUString const & rUNOname ) return s_pRTTIs->getRTTI( rUNOname ); } -//################################################################################################## -void mscx_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +void mscx_raiseException( + uno_Any * pUnoExc, + 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 ); } -//############################################################################## int mscx_filterCppException( - EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) + EXCEPTION_POINTERS * pPointers, + uno_Any * pUnoExc, + uno_Mapping * pCpp2Uno ) { 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; @@ -514,13 +728,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 @@ -532,34 +746,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( @@ -588,16 +815,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; |