diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2020-08-02 09:02:30 +0200 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2020-09-17 00:01:21 +0200 |
commit | 8c3e6666c5ef612a20575e0ebcd5757ba21c47f8 (patch) | |
tree | 8d5e9c9368940c7b06c67f8f1875fc456c4656b6 /bridges/source | |
parent | 52ac46d798a1787baca33cdf9e1c2fd768559522 (diff) |
WIN bridges: unify exception handling
This is almost just refactoring, but with classes like type_info_
and __type_info, just following the code became tendious. I tried
to come up with better names... and in the end included some minor
code changes described below.
This patch moves the "common" code for MSVC exception handling
into msvc_shared/except.cxx. Still it contains a few small ifdefs,
so it doesn't feel like clean separation, but a lot of duplicate
code is dropped this way.
The "major" code change for amd64 is the drop of the duplicate
static RTTInfo object originally used by mscx_getRTTI and
mscx_getRTTI_len, by merging of both functions into the single,
new get() function to use a single std::find call.
Change-Id: Ib07d40e2794cde79156be3324c80ccf21a6aa8ed
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102864
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Diffstat (limited to 'bridges/source')
-rw-r--r-- | bridges/source/cpp_uno/msvc_shared/except.cxx | 338 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx | 7 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_intel/except.cxx | 442 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_intel/msci.hxx | 49 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx | 4 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx | 26 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx | 530 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx | 49 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx | 4 |
9 files changed, 407 insertions, 1042 deletions
diff --git a/bridges/source/cpp_uno/msvc_shared/except.cxx b/bridges/source/cpp_uno/msvc_shared/except.cxx new file mode 100644 index 000000000000..af6ae6934e60 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_shared/except.cxx @@ -0,0 +1,338 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <memory> + +#include <malloc.h> +#include <new.h> +#include <typeinfo> +#include <signal.h> + +#include <rtl/alloc.h> +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/Any.hxx> +#include <unordered_map> +#include <except.hxx> +#include <msvc/except.hxx> + +#if defined(_M_IX86) +#include <msvc/x86.hxx> +#elif defined(_M_AMD64) +#include <msvc/amd64.hxx> +#else +#error "Unsupported machine type" +#endif + +#pragma pack(push, 8) + +using namespace ::com::sun::star; + +static OUString toUNOname(OUString const& rRTTIname) throw() +{ + OUStringBuffer aRet(64); + OUString aStr(rRTTIname.copy(4, rRTTIname.getLength() - 4 - 2)); // filter .?AUzzz@yyy@xxx@@ + sal_Int32 nPos = aStr.getLength(); + while (nPos > 0) + { + sal_Int32 n = aStr.lastIndexOf('@', nPos); + aRet.append(aStr.copy(n + 1, nPos - n - 1)); + if (n >= 0) + aRet.append('.'); + nPos = n; + } + return aRet.makeStringAndClear(); +} + +static OUString toRTTIname(OUString const& rUNOname) throw() +{ + OUStringBuffer aRet(64); + aRet.appendAscii(".?AV"); // class ".?AV"; struct ".?AU" + sal_Int32 nPos = rUNOname.getLength(); + while (nPos > 0) + { + sal_Int32 n = rUNOname.lastIndexOf('.', nPos); + aRet.append(rUNOname.copy(n + 1, nPos - n - 1)); + aRet.append('@'); + nPos = n; + } + aRet.append('@'); + return aRet.makeStringAndClear(); +} + +ExceptionTypeInfo::~ExceptionTypeInfo() throw() { (void)m_data; } + +ExceptionTypeInfoWrapper* RTTInfos::getInfo(OUString const& rUNOname) throw() +{ + ExceptionTypeInfoWrapper* pRTTI; + t_string2PtrMap::const_iterator const iFind(m_allRTTI.find(rUNOname)); + + if (iFind != m_allRTTI.end()) + pRTTI = static_cast<ExceptionTypeInfoWrapper*>(iFind->second); + else + { + OString aRawName(OUStringToOString(toRTTIname(rUNOname), RTL_TEXTENCODING_ASCII_US)); + // Wrap new ExceptionTypeInfo in ExceptionTypeInfoWrapper to preserve length info + pRTTI = new (std::malloc(sizeof(ExceptionTypeInfoWrapper) + aRawName.getLength())) + ExceptionTypeInfoWrapper(nullptr, aRawName.getStr()); + + std::pair<t_string2PtrMap::iterator, bool> insertion( + m_allRTTI.insert(t_string2PtrMap::value_type(rUNOname, pRTTI))); + assert(insertion.second && "### rtti insertion failed?!"); + } + + return pRTTI; +} + +type_info* RTTInfos::get(OUString const& rUNOname, int* len) throw() +{ + static RTTInfos* s_pRTTIs = new RTTInfos(); + + static_assert(sizeof(ExceptionTypeInfo) == sizeof(std::type_info), + "### type info structure size differ!"); + + osl::MutexGuard aGuard(s_pRTTIs->m_aMutex); + ExceptionTypeInfoWrapper* pETIW = s_pRTTIs->getInfo(rUNOname); + if (len) + *len = pETIW->get_type_info_size(); + return pETIW->get_type_info(); +} + +RTTInfos::RTTInfos() throw() {} + +DWORD ExceptionInfos::allocationGranularity = 0; + +ExceptionInfos::ExceptionInfos() throw() {} + +ExceptionInfos::~ExceptionInfos() throw() +{ + SAL_INFO("bridges", "> freeing exception infos... <"); + + osl::MutexGuard aGuard(m_aMutex); + for (auto& rEntry : m_allRaiseInfos) + delete reinterpret_cast<RaiseInfo*>(rEntry.second); +} + +RaiseInfo* ExceptionInfos::getRaiseInfo(typelib_TypeDescription* pTD) throw() +{ + static ExceptionInfos* s_pInfos = []() { +#ifdef _M_AMD64 + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + allocationGranularity = systemInfo.dwAllocationGranularity; +#endif + return new ExceptionInfos(); + }(); + + assert(pTD + && (pTD->eTypeClass == typelib_TypeClass_STRUCT + || pTD->eTypeClass == typelib_TypeClass_EXCEPTION)); + + RaiseInfo* pRaiseInfo; + + OUString const& rTypeName = OUString::unacquired(&pTD->pTypeName); + osl::MutexGuard aGuard(s_pInfos->m_aMutex); + t_string2PtrMap::const_iterator const iFind(s_pInfos->m_allRaiseInfos.find(rTypeName)); + if (iFind != s_pInfos->m_allRaiseInfos.end()) + pRaiseInfo = static_cast<RaiseInfo*>(iFind->second); + else + { + pRaiseInfo = new RaiseInfo(pTD); + + std::pair<t_string2PtrMap::iterator, bool> insertion(s_pInfos->m_allRaiseInfos.insert( + t_string2PtrMap::value_type(rTypeName, static_cast<void*>(pRaiseInfo)))); + assert(insertion.second && "### raise info insertion failed?!"); + } + + return pRaiseInfo; +} + +void msvc_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 inlining of + // ExceptionInfos::getRaiseInfo() + + // construct cpp exception object + typelib_TypeDescription* pTD = nullptr; + TYPELIB_DANGER_GET(&pTD, pUnoExc->pType); + + void* pCppExc = alloca(pTD->nSize); + ::uno_copyAndConvertData(pCppExc, pUnoExc->pData, pTD, pUno2Cpp); + + ULONG_PTR arFilterArgs[MSVC_EH_PARAMETERS]; + arFilterArgs[0] = MSVC_EH_MAGIC_PARAM; + arFilterArgs[1] = reinterpret_cast<ULONG_PTR>(pCppExc); + arFilterArgs[2] = reinterpret_cast<ULONG_PTR>(ExceptionInfos::getRaiseInfo(pTD)); +#if MSVC_EH_PARAMETERS == 4 + arFilterArgs[3] = reinterpret_cast<RaiseInfo*>(arFilterArgs[2])->_codeBase; +#endif + + // Destruct uno exception + ::uno_any_destruct(pUnoExc, nullptr); + TYPELIB_DANGER_RELEASE(pTD); + + // last point to release anything not affected by stack unwinding + RaiseException(MSVC_EH_MAGIC_CODE, EXCEPTION_NONCONTINUABLE, MSVC_EH_PARAMETERS, arFilterArgs); +} + +// This function does the same check as __CxxDetectRethrow from msvcrt (see its +// crt/src/vcruntime/mgdframe.cpp). But it does not alter the global state, i.e. it does not +// increment __ProcessingThrow, and so does not break following exception handling. We rely on the +// definition of EHExceptionRecord, PER_IS_MSVC_EH and PER_PTHROW, that are current as of msvcrt +// 2017 (14.14.26428). +static bool DetectRethrow(void* ppExcept) +{ + struct EHExceptionRecord + { + DWORD ExceptionCode; + DWORD ExceptionFlags; + struct _EXCEPTION_RECORD* ExceptionRecord; + PVOID ExceptionAddress; + DWORD NumberParameters; +#if MSVC_EH_PARAMETERS == 3 + struct EHParameters +#else + struct alignas(8) +#endif + { + DWORD magicNumber; + PVOID pExceptionObject; + PVOID pThrowInfo; +#if MSVC_EH_PARAMETERS == 4 + PVOID pThrowImageBase; +#endif + } params; + }; + + constexpr auto PER_IS_MSVC_EH = [](EHExceptionRecord* p) { + return p->ExceptionCode == MSVC_EH_MAGIC_CODE && p->NumberParameters == MSVC_EH_PARAMETERS + && (p->params.magicNumber == MSVC_EH_MAGIC_PARAM + || p->params.magicNumber == MSVC_EH_MAGIC_PARAM + 1 + || p->params.magicNumber == MSVC_EH_MAGIC_PARAM + 2); + }; + + constexpr auto PER_PTHROW = [](EHExceptionRecord* p) { return p->params.pThrowInfo; }; + + EHExceptionRecord* pExcept; + if (!ppExcept) + return false; + pExcept = *static_cast<EHExceptionRecord**>(ppExcept); + if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) == nullptr) + return true; + return false; +} + +int msvc_filterCppException(EXCEPTION_POINTERS* pPointers, uno_Any* pUnoExc, uno_Mapping* pCpp2Uno) +{ + if (pPointers == nullptr) + return EXCEPTION_CONTINUE_SEARCH; + + EXCEPTION_RECORD* pRecord = pPointers->ExceptionRecord; + + // Handle only C++ exceptions: + if (pRecord == nullptr || pRecord->ExceptionCode != MSVC_EH_MAGIC_CODE) + return EXCEPTION_CONTINUE_SEARCH; + + const bool rethrow = DetectRethrow(&pRecord); + assert(pRecord == pPointers->ExceptionRecord); + + if (rethrow && pRecord == pPointers->ExceptionRecord) + pRecord = *reinterpret_cast<EXCEPTION_RECORD**>(__current_exception()); + + // Rethrow: handle only C++ exceptions: + if (pRecord == nullptr || pRecord->ExceptionCode != MSVC_EH_MAGIC_CODE) + return EXCEPTION_CONTINUE_SEARCH; + + if (pRecord->NumberParameters == MSVC_EH_PARAMETERS +#if MSVC_EH_PARAMETERS == 4 + && pRecord->ExceptionInformation[0] == MSVC_EH_MAGIC_PARAM +#endif + && pRecord->ExceptionInformation[1] != 0 && pRecord->ExceptionInformation[2] != 0 +#if MSVC_EH_PARAMETERS == 4 + && pRecord->ExceptionInformation[3] != 0 +#endif + ) + { + // 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 pThrowInfo pointer + RaiseInfo* pInfo = reinterpret_cast<RaiseInfo*>(pRecord->ExceptionInformation[2]); + +#if MSVC_EH_PARAMETERS == 3 + ULONG_PTR base = 0; + DWORD* types = reinterpret_cast<DWORD*>(pInfo->_types); +#else + // [3] is the image base address which is added the 32-bit + // rva_t fields in throwinfo to get actual 64-bit addresses + ULONG_PTR base = pRecord->ExceptionInformation[3]; + DWORD* types = reinterpret_cast<DWORD*>(base + pInfo->_types); +#endif + if (types != nullptr && types[0] != 0 && types[1] != 0) + { + ExceptionType* et = reinterpret_cast<ExceptionType*>(base + types[1]); + if (et->_pTypeInfo != 0) + { + OUString aRTTIname(OStringToOUString( + reinterpret_cast<ExceptionTypeInfo*>(base + et->_pTypeInfo)->m_d_name, + RTL_TEXTENCODING_ASCII_US)); + OUString aUNOname(toUNOname(aRTTIname)); + + typelib_TypeDescription* pExcTD = nullptr; + typelib_typedescription_getByName(&pExcTD, aUNOname.pData); + if (pExcTD == nullptr) + { + OUString sMsg = "[mscx_uno bridge error] UNO type of C++ exception unknown: \"" + + aUNOname + "\", RTTI-name=\"" + aRTTIname + "\"!"; + + uno::RuntimeException exc(sMsg); + uno_type_any_constructAndConvert( + pUnoExc, &exc, cppu::UnoType<decltype(exc)>::get().getTypeLibType(), + pCpp2Uno); + } + else + { + // construct uno exception any + uno_any_constructAndConvert( + pUnoExc, reinterpret_cast<void*>(pRecord->ExceptionInformation[1]), pExcTD, + pCpp2Uno); + typelib_typedescription_release(pExcTD); + } + + return EXCEPTION_EXECUTE_HANDLER; + } + } + } + + // though this unknown exception leaks now, no user-defined exception + // is ever thrown through the binary C-UNO dispatcher call stack. + uno::RuntimeException exc("[mscx_uno bridge error] unexpected C++ exception occurred!"); + uno_type_any_constructAndConvert( + pUnoExc, &exc, cppu::UnoType<decltype(exc)>::get().getTypeLibType(), pCpp2Uno); + return EXCEPTION_EXECUTE_HANDLER; +} + +#pragma pack(pop) diff --git a/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx index 24a0837a6e30..22e91e4ba8d3 100644 --- a/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx +++ b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx @@ -30,7 +30,7 @@ #include "types.hxx" #include "vtablefactory.hxx" -#include "msci.hxx" +#include <msvc/x86.hxx> using namespace ::com::sun::star; @@ -167,7 +167,7 @@ static inline typelib_TypeClass cpp2uno_call( if (pReturnTD) TYPELIB_DANGER_RELEASE(pReturnTD); - CPPU_CURRENT_NAMESPACE::msci_raiseException( + msvc_raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp()); // has to destruct the any // is here for dummy @@ -451,8 +451,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock( type_info * rtti; Rtti(): n0(0), n1(0), n2(0), - rtti(CPPU_CURRENT_NAMESPACE::msci_getRTTI( - "com.sun.star.uno.XInterface")) + rtti(RTTInfos::get("com.sun.star.uno.XInterface")) {} }; static Rtti rtti; diff --git a/bridges/source/cpp_uno/msvc_win32_intel/except.cxx b/bridges/source/cpp_uno/msvc_win32_intel/except.cxx index 360abb038bec..d65152b29dbe 100644 --- a/bridges/source/cpp_uno/msvc_win32_intel/except.cxx +++ b/bridges/source/cpp_uno/msvc_win32_intel/except.cxx @@ -31,157 +31,14 @@ #include <com/sun/star/uno/Any.hxx> #include <unordered_map> -#include "msci.hxx" +#include <msvc/x86.hxx> #include <except.hxx> - #pragma pack(push, 8) -using namespace ::com::sun::star::uno; -using namespace ::std; -using namespace ::osl; - -namespace CPPU_CURRENT_NAMESPACE -{ - -static inline OUString toUNOname( OUString const & rRTTIname ) throw () -{ - OUStringBuffer aRet( 64 ); - OUString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz@yyy@xxx@@ - sal_Int32 nPos = aStr.getLength(); - while (nPos > 0) - { - sal_Int32 n = aStr.lastIndexOf( '@', nPos ); - aRet.append( aStr.copy( n +1, nPos -n -1 ) ); - if (n >= 0) - { - aRet.append( '.' ); - } - nPos = n; - } - return aRet.makeStringAndClear(); -} - -static inline OUString toRTTIname( OUString const & rUNOname ) throw () -{ - OUStringBuffer aRet( 64 ); - aRet.appendAscii( ".?AV" ); // class ".?AV"; struct ".?AU" - sal_Int32 nPos = rUNOname.getLength(); - while (nPos > 0) - { - sal_Int32 n = rUNOname.lastIndexOf( '.', nPos ); - aRet.append( rUNOname.copy( n +1, nPos -n -1 ) ); - aRet.append( '@' ); - nPos = n; - } - aRet.append( '@' ); - return aRet.makeStringAndClear(); -} - - -//#### RTTI simulation ############################################################################# - - -typedef std::unordered_map< OUString, void * > t_string2PtrMap; - -class RTTInfos -{ - Mutex _aMutex; - t_string2PtrMap _allRTTI; - - static OUString toRawName( OUString const & rUNOname ) throw (); -public: - type_info * getRTTI( OUString const & rUNOname ) throw (); - - RTTInfos(); - ~RTTInfos(); -}; - -class __type_info -{ - friend type_info * RTTInfos::getRTTI( OUString const & ) throw (); - friend int msci_filterCppException( - LPEXCEPTION_POINTERS, uno_Any *, uno_Mapping * ); - -public: - virtual ~__type_info() throw (); - - inline __type_info( void * m_data, const char * m_d_name ) throw () - : _m_data( m_data ) - { ::strcpy( _m_d_name, m_d_name ); } // #100211# - checked - -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 - static_assert(sizeof(__type_info) == sizeof(type_info), "### type info structure size differ!"); - - MutexGuard aGuard( _aMutex ); - t_string2PtrMap::const_iterator const iFind( _allRTTI.find( rUNOname ) ); - - // check if type is already available - if (iFind == _allRTTI.end()) - { - // insert new type_info - OString aRawName( OUStringToOString( toRTTIname( rUNOname ), RTL_TEXTENCODING_ASCII_US ) ); - __type_info * pRTTI = new( std::malloc( sizeof(__type_info) + aRawName.getLength() ) ) - __type_info( NULL, aRawName.getStr() ); - - // put into map - pair< t_string2PtrMap::iterator, bool > insertion( - _allRTTI.insert( t_string2PtrMap::value_type( rUNOname, pRTTI ) ) ); - assert(insertion.second && "### rtti insertion failed?!"); - - return reinterpret_cast<type_info*>(pRTTI); - } - else - { - return reinterpret_cast<type_info*>(iFind->second); - } -} - -RTTInfos::RTTInfos() throw () -{ -} - -RTTInfos::~RTTInfos() throw () -{ - SAL_INFO("bridges", "> freeing generated RTTI infos... <"); - - MutexGuard aGuard( _aMutex ); - for ( auto& rEntry : _allRTTI ) - { - __type_info * pType = reinterpret_cast<__type_info*>(rEntry.second); - pType->~__type_info(); // obsolete, but good style... - std::free( pType ); - } -} - +using namespace ::com::sun::star; -//#### 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 * ObjectFunction::operator new ( size_t nSize ) { void * pMem = std::malloc( nSize ); if (pMem != 0) @@ -195,12 +52,11 @@ inline void * ObjectFunction::operator new ( size_t nSize ) return pMem; } -inline void ObjectFunction::operator delete ( void * pMem ) +void ObjectFunction::operator delete ( void * pMem ) { std::free( pMem ); } - ObjectFunction::ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ) throw () : _pTypeDescr( pTypeDescr ) { @@ -227,14 +83,14 @@ ObjectFunction::~ObjectFunction() throw () static void * __cdecl __copyConstruct( void * pExcThis, void * pSource, ObjectFunction * pThis ) throw () { - ::uno_copyData( pExcThis, pSource, pThis->_pTypeDescr, cpp_acquire ); + ::uno_copyData(pExcThis, pSource, pThis->_pTypeDescr, uno::cpp_acquire); return pExcThis; } static void * __cdecl __destruct( void * pExcThis, ObjectFunction * pThis ) throw () { - ::uno_destructData( pExcThis, pThis->_pTypeDescr, cpp_release ); + ::uno_destructData(pExcThis, pThis->_pTypeDescr, uno::cpp_release); return pExcThis; } @@ -265,47 +121,22 @@ static __declspec(naked) void destruct() throw () } } -struct ExceptionType +ExceptionType::ExceptionType( typelib_TypeDescription * pTypeDescr ) throw () + : _n0( 0 ) + , _n1( 0 ) + , _n2( -1 ) + , _n3( 0 ) + , _n4( pTypeDescr->nSize ) + , _pCopyCtor( new ObjectFunction( pTypeDescr, copyConstruct ) ) + , _n5( 0 ) { - sal_Int32 _n0; - type_info * _pTypeInfo; - sal_Int32 _n1, _n2, _n3, _n4; - ObjectFunction * _pCopyCtor; - sal_Int32 _n5; - - explicit ExceptionType( typelib_TypeDescription * pTypeDescr ) throw () - : _n0( 0 ) - , _n1( 0 ) - , _n2( -1 ) - , _n3( 0 ) - , _n4( pTypeDescr->nSize ) - , _pCopyCtor( new ObjectFunction( pTypeDescr, copyConstruct ) ) - , _n5( 0 ) - { - _pTypeInfo = msci_getRTTI( pTypeDescr->pTypeName ); - } - - ~ExceptionType() throw () - { - delete _pCopyCtor; - } - - // Copy assignment is forbidden and not implemented. - ExceptionType (const ExceptionType &) = delete; - ExceptionType & operator= (const ExceptionType &) = delete; -}; + _pTypeInfo = RTTInfos::get(pTypeDescr->pTypeName); +} -struct RaiseInfo +ExceptionType::~ExceptionType() throw () { - sal_Int32 _n0; - ObjectFunction * _pDtor; - sal_Int32 _n2; - void * _types; - sal_Int32 _n3, _n4; - - explicit RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw (); - ~RaiseInfo() throw (); -}; + delete _pCopyCtor; +} RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw () : _n0( 0 ) @@ -353,241 +184,6 @@ RaiseInfo::~RaiseInfo() throw () delete _pDtor; } -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 () -{ - SAL_INFO("bridges", "> freeing exception infos... <"); - - MutexGuard aGuard( _aMutex ); - for ( auto& rEntry : _allRaiseInfos ) - { - delete reinterpret_cast<RaiseInfo*>(rEntry.second); - } -} - -void * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw () -{ - static ExceptionInfos* s_pInfos = new ExceptionInfos(); - - assert( pTypeDescr && - (pTypeDescr->eTypeClass == typelib_TypeClass_STRUCT || - pTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION) ); - - void * pRaiseInfo; - - OUString const & rTypeName = OUString::unacquired( &pTypeDescr->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 - pair< t_string2PtrMap::iterator, bool > insertion( - s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, pRaiseInfo ) ) ); - assert(insertion.second && "### raise info insertion failed?!"); - } - else - { - // reuse existing info - pRaiseInfo = iFind->second; - } - - return pRaiseInfo; -} - - -//#### exported #################################################################################### - - -type_info * msci_getRTTI( OUString const & rUNOname ) -{ - static RTTInfos* s_pRTTIs = new RTTInfos(); - return s_pRTTIs->getRTTI( rUNOname ); -} - -void msci_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 inlining of - // ExceptionInfos::getRaiseInfo() - - // construct cpp exception object - typelib_TypeDescription * pTypeDescr = 0; - TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); - - void * pCppExc = alloca( pTypeDescr->nSize ); - ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); - - // a must be - static_assert(sizeof(sal_Int32) == sizeof(void *), - "### pointer size differs from sal_Int32!" ); - DWORD arFilterArgs[3]; - arFilterArgs[0] = MSVC_magic_number; - arFilterArgs[1] = (DWORD)pCppExc; - arFilterArgs[2] = (DWORD)ExceptionInfos::getRaiseInfo( pTypeDescr ); - - // destruct uno exception - ::uno_any_destruct( pUnoExc, 0 ); - TYPELIB_DANGER_RELEASE( pTypeDescr ); - - // last point to release anything not affected by stack unwinding - RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs ); -} - -namespace -{ -// This function does the same check as __CxxDetectRethrow from msvcrt (see its -// crt/src/vcruntime/mgdframe.cpp). But it does not alter the global state, i.e. it does not -// increment __ProcessingThrow, and so does not break following exception handling. We rely on the -// definition of EHExceptionRecord, PER_IS_MSVC_EH and PER_PTHROW, that are current as of msvcrt -// 2017 (14.14.26428). -bool DetectRethrow(void* ppExcept) -{ - struct EHExceptionRecord - { - DWORD ExceptionCode; - DWORD ExceptionFlags; - struct _EXCEPTION_RECORD* ExceptionRecord; - PVOID ExceptionAddress; - DWORD NumberParameters; - struct EHParameters - { - DWORD magicNumber; - PVOID pExceptionObject; - PVOID pThrowInfo; - } params; - }; - - constexpr auto PER_IS_MSVC_EH = [](EHExceptionRecord* p) { - constexpr DWORD EH_EXCEPTION_NUMBER = 0xE06D7363; // The NT Exception # that msvcrt uses ('msc' | 0xE0000000) - constexpr DWORD EH_MAGIC_NUMBER1 = 0x19930520; // latest magic # in thrown object - constexpr DWORD EH_MAGIC_NUMBER2 = 0x19930521; // latest magic # in func info for exception specs - constexpr DWORD EH_MAGIC_NUMBER3 = 0x19930522; // latest magic # - constexpr DWORD EH_EXCEPTION_PARAMETERS = 3; // Number of parameters in exception record for x86 - - return p->ExceptionCode == EH_EXCEPTION_NUMBER - && p->NumberParameters == EH_EXCEPTION_PARAMETERS - && (p->params.magicNumber == EH_MAGIC_NUMBER1 - || p->params.magicNumber == EH_MAGIC_NUMBER2 - || p->params.magicNumber == EH_MAGIC_NUMBER3); - }; - - constexpr auto PER_PTHROW = [](EHExceptionRecord* p) { - return p->params.pThrowInfo; - }; - - EHExceptionRecord* pExcept; - if (!ppExcept) - return false; - pExcept = *static_cast<EHExceptionRecord**>(ppExcept); - if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) == nullptr) - { - return true; - } - return false; -} -} - -int msci_filterCppException( - 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: - if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode) - return EXCEPTION_CONTINUE_SEARCH; - - const bool rethrow = DetectRethrow(&pRecord); - assert(pRecord == pPointers->ExceptionRecord); - - if (rethrow && pRecord == pPointers->ExceptionRecord) - { - pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >(__current_exception()); - } - // 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) - { - void * types = reinterpret_cast< RaiseInfo * >( - pRecord->ExceptionInformation[ 2 ] )->_types; - if (types != 0 && *reinterpret_cast< DWORD * >( types ) > 0) // count - { - ExceptionType * pType = *reinterpret_cast< ExceptionType ** >( - reinterpret_cast< DWORD * >( types ) + 1 ); - if (pType != 0 && pType->_pTypeInfo != 0) - { - OUString aRTTIname( - OStringToOUString( - reinterpret_cast< __type_info * >( - pType->_pTypeInfo )->_m_d_name, - RTL_TEXTENCODING_ASCII_US ) ); - OUString aUNOname( toUNOname( aRTTIname ) ); - - typelib_TypeDescription * pExcTypeDescr = 0; - typelib_typedescription_getByName( - &pExcTypeDescr, aUNOname.pData ); - if (pExcTypeDescr == 0) - { - OUString sMsg = "[msci_uno bridge error] UNO type of " - "C++ exception unknown: \"" - + aUNOname + "\", RTTI-name=\"" - + aRTTIname + "\"!"; - RuntimeException exc( sMsg ); - uno_type_any_constructAndConvert( - pUnoExc, &exc, - cppu::UnoType<decltype(exc)>::get().getTypeLibType(), pCpp2Uno ); - // msvcr80.dll cleans up, different from former msvcrs - // if (! rethrow): - // though this unknown exception leaks now, no user-defined - // exception is ever thrown through the binary C-UNO dispatcher - // call stack. - } - else - { - // construct uno exception any - uno_any_constructAndConvert( - pUnoExc, (void *) pRecord->ExceptionInformation[1], - pExcTypeDescr, pCpp2Uno ); - typelib_typedescription_release( pExcTypeDescr ); - } - - return EXCEPTION_EXECUTE_HANDLER; - } - } - } - // though this unknown exception leaks now, no user-defined exception - // is ever thrown through the binary C-UNO dispatcher call stack. - RuntimeException exc( "[msci_uno bridge error] unexpected " - "C++ exception occurred!" ); - uno_type_any_constructAndConvert( - pUnoExc, &exc, cppu::UnoType<decltype(exc)>::get().getTypeLibType(), pCpp2Uno ); - return EXCEPTION_EXECUTE_HANDLER; -} - -} - #pragma pack(pop) /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_intel/msci.hxx b/bridges/source/cpp_uno/msvc_win32_intel/msci.hxx deleted file mode 100644 index 9ee63d338656..000000000000 --- a/bridges/source/cpp_uno/msvc_win32_intel/msci.hxx +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ -#pragma once - -#if !defined WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif -#include <windows.h> - -#include "rtl/ustring.hxx" - - -class type_info; -typedef struct _uno_Any uno_Any; -typedef struct _uno_Mapping uno_Mapping; - -namespace CPPU_CURRENT_NAMESPACE -{ - -const DWORD MSVC_ExceptionCode = 0xe06d7363; -const long MSVC_magic_number = 0x19930520L; - -type_info * msci_getRTTI( OUString const & rUNOname ); - -int msci_filterCppException( - EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ); - -void msci_raiseException( - uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); - -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx b/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx index bd7e5046d209..570495294e36 100644 --- a/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx +++ b/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx @@ -28,7 +28,7 @@ #include <unointerfaceproxy.hxx> #include <vtables.hxx> -#include "msci.hxx" +#include <msvc/except.hxx> using namespace ::com::sun::star; @@ -259,7 +259,7 @@ void cpp_call( (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); } - __except (CPPU_CURRENT_NAMESPACE::msci_filterCppException( + __except (msvc_filterCppException( GetExceptionInformation(), *ppUnoExc, pThis->getBridge()->getCpp2Uno() )) { diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx index a229db4c2ffe..6ed58ed4c9e6 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx @@ -31,7 +31,7 @@ #include <vtablefactory.hxx> #include "call.hxx" -#include "mscx.hxx" +#include <msvc/amd64.hxx> using namespace ::com::sun::star; @@ -154,7 +154,7 @@ static typelib_TypeClass cpp2uno_call( if (pReturnTD) TYPELIB_DANGER_RELEASE(pReturnTD); - CPPU_CURRENT_NAMESPACE::mscx_raiseException( + msvc_raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp()); // has to destruct the any // is here for dummy @@ -341,6 +341,7 @@ extern "C" typelib_TypeClass cpp_vtable_call( } int const codeSnippetSize = 48; +typedef enum { REGPARAM_INT, REGPARAM_FLT } RegParamKind; extern "C" char privateSnippetExecutor; @@ -352,7 +353,7 @@ extern "C" char privateSnippetExecutor; static unsigned char * codeSnippet( unsigned char * code, - CPPU_CURRENT_NAMESPACE::RegParamKind param_kind[4], + RegParamKind param_kind[4], sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset ) { @@ -360,7 +361,7 @@ static unsigned char * codeSnippet( unsigned char *p = code; // Spill parameters - if ( param_kind[0] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT ) + if (param_kind[0] == REGPARAM_INT) { // mov qword ptr 8[rsp], rcx *p++ = 0x48; *p++ = 0x89; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x08; @@ -370,7 +371,7 @@ static unsigned char * codeSnippet( // movsd qword ptr 8[rsp], xmm0 *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08; } - if ( param_kind[1] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT ) + if ( param_kind[1] == REGPARAM_INT ) { // mov qword ptr 16[rsp], rdx *p++ = 0x48; *p++ = 0x89; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10; @@ -380,7 +381,7 @@ static unsigned char * codeSnippet( // movsd qword ptr 16[rsp], xmm1 *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x10; } - if ( param_kind[2] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT ) + if ( param_kind[2] == REGPARAM_INT ) { // mov qword ptr 24[rsp], r8 *p++ = 0x4C; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18; @@ -390,7 +391,7 @@ static unsigned char * codeSnippet( // movsd qword ptr 24[rsp], xmm2 *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18; } - if ( param_kind[3] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT ) + if ( param_kind[3] == REGPARAM_INT ) { // mov qword ptr 32[rsp], r9 *p++ = 0x4C;*p++ = 0x89; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x20; @@ -443,8 +444,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock( type_info * rtti; Rtti(): n0(0), n1(0), n2(0), - rtti(CPPU_CURRENT_NAMESPACE::mscx_getRTTI( - "com.sun.star.uno.XInterface")) + rtti(RTTInfos::get("com.sun.star.uno.XInterface")) {} }; static Rtti rtti; @@ -471,11 +471,11 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( TYPELIB_DANGER_GET( &pTD, type->ppMembers[ member ] ); assert(pTD); - CPPU_CURRENT_NAMESPACE::RegParamKind param_kind[4]; + RegParamKind param_kind[4]; int nr = 0; for (int i = 0; i < 4; ++i) - param_kind[i] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT; + param_kind[i] = REGPARAM_INT; // 'this' ++nr; @@ -498,7 +498,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( // Setter if ( pAttrTD->eTypeClass == typelib_TypeClass_FLOAT || pAttrTD->eTypeClass == typelib_TypeClass_DOUBLE ) - param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT; + param_kind[nr++] = REGPARAM_FLT; TYPELIB_DANGER_RELEASE( pAttrTD ); @@ -530,7 +530,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( if ( pParamTD->eTypeClass == typelib_TypeClass_FLOAT || pParamTD->eTypeClass == typelib_TypeClass_DOUBLE ) - param_kind[nr] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT; + param_kind[nr] = REGPARAM_FLT; TYPELIB_DANGER_RELEASE( pParamTD ); } 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 daa0426a2c17..24c3716333aa 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx @@ -247,199 +247,21 @@ void #include <rtl/strbuf.hxx> #include <rtl/ustrbuf.hxx> #include <sal/log.hxx> -#include <osl/mutex.hxx> #include <com/sun/star/uno/Any.hxx> -#include <unordered_map> -#include "mscx.hxx" +#include <msvc/amd64.hxx> #include <except.hxx> #pragma pack(push, 8) -using namespace ::com::sun::star::uno; -using namespace ::std; -using namespace ::osl; - -namespace CPPU_CURRENT_NAMESPACE -{ - static int mscx_getRTTI_len(OUString const & rUNOname); - - -static OUString toUNOname( - OUString const & rRTTIname ) - throw () -{ - OUStringBuffer aRet( 64 ); - OUString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz@yyy@xxx@@ - sal_Int32 nPos = aStr.getLength(); - while (nPos > 0) - { - sal_Int32 n = aStr.lastIndexOf( '@', nPos ); - aRet.append( aStr.copy( n +1, nPos -n -1 ) ); - if (n >= 0) - { - aRet.append( '.' ); - } - nPos = n; - } - return aRet.makeStringAndClear(); -} - -static OUString toRTTIname( - OUString const & rUNOname ) - throw () -{ - OUStringBuffer aRet( 64 ); - aRet.append( ".?AV" ); // class ".?AV"; struct ".?AU" - sal_Int32 nPos = rUNOname.getLength(); - while (nPos > 0) - { - sal_Int32 n = rUNOname.lastIndexOf( '.', nPos ); - aRet.append( rUNOname.copy( n +1, nPos -n -1 ) ); - aRet.append( '@' ); - nPos = n; - } - aRet.append( '@' ); - return aRet.makeStringAndClear(); -} - -//RTTI simulation - -typedef std::unordered_map< OUString, void * > t_string2PtrMap; - -namespace { - -class type_info_descriptor; - -class RTTInfos -{ - Mutex _aMutex; - t_string2PtrMap _allRTTI; - -public: - type_info * getRTTI( OUString const & rUNOname ) throw (); - int getRTTI_len(OUString const & rUNOname) throw (); - type_info_descriptor * insert_new_type_info_descriptor(OUString const & rUNOname); - - RTTInfos() throw (); -}; -class type_info_ -{ - friend type_info * RTTInfos::getRTTI( OUString const & ) throw (); - friend int mscx::mscx_filterCppException( - EXCEPTION_POINTERS *, uno_Any *, uno_Mapping * ); - -public: - virtual ~type_info_() throw (); - - type_info_( void * m_data, const char * m_d_name ) throw () - : _m_data( m_data ) - { ::strcpy( _m_d_name, m_d_name ); } // #100211# - checked - -private: - void * _m_data; - char _m_d_name[1]; -}; - -} - -type_info_::~type_info_() throw () -{ - (void)_m_data; -} - -namespace { - -class type_info_descriptor -{ -private: - int type_info_size; - type_info_ info; - -public: - - type_info_descriptor(void * m_data, const char * m_d_name) throw () - : info(m_data, m_d_name) - { - type_info_size = sizeof(type_info_) + strlen(m_d_name); - } - - type_info * get_type_info() - { - return reinterpret_cast<type_info *>(&info); - } - int get_type_info_size() - { - return type_info_size; - } -}; - -} - -type_info_descriptor * RTTInfos::insert_new_type_info_descriptor(OUString const & rUNOname) { - - // insert new type_info - OString aRawName(OUStringToOString(toRTTIname(rUNOname), RTL_TEXTENCODING_ASCII_US)); - type_info_descriptor * pRTTI = new(std::malloc(sizeof(type_info_descriptor) + aRawName.getLength())) - type_info_descriptor(nullptr, aRawName.getStr()); - - // put into map - pair< t_string2PtrMap::iterator, bool > insertion( - _allRTTI.insert(t_string2PtrMap::value_type(rUNOname, pRTTI))); - assert(insertion.second && "### rtti insertion failed?!"); - - return pRTTI; -} -type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw () -{ - // a must be - static_assert(sizeof(type_info_) == sizeof(type_info), "### type info structure size differ!"); - - MutexGuard aGuard( _aMutex ); - t_string2PtrMap::const_iterator const iFind( _allRTTI.find( rUNOname ) ); - - // check if type is already available - if (iFind == _allRTTI.end()) - { - // Wrap new type_info_ in type_info_descriptor to preserve length info - type_info_descriptor * pRTTI = insert_new_type_info_descriptor(rUNOname); - return pRTTI->get_type_info(); - } - else - { - return static_cast<type_info_descriptor *>(iFind->second)->get_type_info(); - } -} - -int RTTInfos::getRTTI_len(OUString const & rUNOname) throw () -{ - MutexGuard aGuard(_aMutex); - t_string2PtrMap::const_iterator const iFind(_allRTTI.find(rUNOname)); - - // Wrap new type_info_ in type_info_descriptor to preserve length info - // check if type is already available - if (iFind == _allRTTI.end()) - { - // Wrap new type_info_ in type_info_descriptor to preserve length info - type_info_descriptor * pRTTI = insert_new_type_info_descriptor(rUNOname); - return pRTTI->get_type_info_size(); - } - else - { - return static_cast<type_info_descriptor *>(iFind->second)->get_type_info_size(); - } -} - -RTTInfos::RTTInfos() throw () -{ -} +using namespace ::com::sun::star; static void * __cdecl copyConstruct( void * pExcThis, void * pSource, typelib_TypeDescription * pTD ) throw () { - ::uno_copyData( pExcThis, pSource, pTD, cpp_acquire ); + ::uno_copyData(pExcThis, pSource, pTD, uno::cpp_acquire); return pExcThis; } @@ -447,7 +269,7 @@ static void * __cdecl destruct( void * pExcThis, typelib_TypeDescription * pTD ) throw () { - ::uno_destructData( pExcThis, pTD, cpp_release ); + ::uno_destructData(pExcThis, pTD, uno::cpp_release); return pExcThis; } @@ -493,85 +315,29 @@ static void GenerateDestructorTrampoline( assert( p < code + codeSnippetSize ); } -namespace { - -// This looks like it is the struct catchabletype above - -struct ExceptionType -{ - sal_Int32 _n0; // flags - sal_uInt32 _pTypeInfo; // typeinfo - sal_Int32 _n1, _n2, _n3; // thiscast - sal_Int32 _n4; // object_size - sal_uInt32 _pCopyCtor; // copyctor - type_info_ type_info; - - - ExceptionType( - unsigned char * pCode, - sal_uInt64 pCodeBase, - typelib_TypeDescription * pTD ) throw () - : _n0( 0 ) - , _n1( 0 ) - , _n2( -1 ) - , _n3( 0 ) - , _n4( pTD->nSize) - , type_info(nullptr, "") - { - // 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. - memcpy(static_cast<void *>(&type_info), static_cast<void *>(mscx_getRTTI(pTD->pTypeName)), mscx_getRTTI_len(pTD->pTypeName)); - _pTypeInfo = static_cast<sal_uInt32>( - reinterpret_cast<sal_uInt64>(&type_info) - pCodeBase); - GenerateConstructorTrampoline( pCode, pTD ); - assert( - pCodeBase <= reinterpret_cast<sal_uInt64>(pCode) - && (reinterpret_cast<sal_uInt64>(pCode) - pCodeBase - < 0x100000000)); - _pCopyCtor = static_cast<sal_uInt32>( - reinterpret_cast<sal_uInt64>(pCode) - pCodeBase); - } -}; - -struct RaiseInfo; - -class ExceptionInfos -{ - Mutex _aMutex; - t_string2PtrMap _allRaiseInfos; - -public: - static RaiseInfo * getRaiseInfo( typelib_TypeDescription * pTD ) throw (); - - static DWORD allocationGranularity; - - ExceptionInfos() throw (); -}; - -} - -DWORD ExceptionInfos::allocationGranularity = 0; - -// This corresponds to the struct throwinfo described above. - -namespace { - -struct RaiseInfo -{ - sal_Int32 _n0; - sal_uInt32 _pDtor; - sal_Int32 _n2; - sal_uInt32 _types; - - // Additional fields - typelib_TypeDescription * _pTD; - unsigned char * _code; - sal_uInt64 _codeBase; - - explicit RaiseInfo(typelib_TypeDescription * pTD) throw (); -}; - +ExceptionType::ExceptionType(unsigned char * pCode, sal_uInt64 pCodeBase, + typelib_TypeDescription * pTD) throw () + : _n0(0) + , _n1(0) + , _n2(-1) + , _n3(0) + , _n4(pTD->nSize) + , exc_type_info(nullptr, "") +{ + // 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. + + int len; + type_info* pRTTI = RTTInfos::get(pTD->pTypeName, &len); + + memcpy(static_cast<void*>(&exc_type_info), static_cast<void*>(pRTTI), len); + _pTypeInfo = static_cast<sal_uInt32>(reinterpret_cast<sal_uInt64>(&exc_type_info) - pCodeBase); + GenerateConstructorTrampoline(pCode, pTD); + + assert(pCodeBase <= reinterpret_cast<sal_uInt64>(pCode) + && (reinterpret_cast<sal_uInt64>(pCode) - pCodeBase < 0x100000000)); + _pCopyCtor = static_cast<sal_uInt32>(reinterpret_cast<sal_uInt64>(pCode) - pCodeBase); } /* Rewrite of 32-Bit-Code to work under 64 Bit: @@ -595,6 +361,7 @@ RaiseInfo::RaiseInfo(typelib_TypeDescription * pTD)throw () // Count how many trampolines we need int codeSize = codeSnippetSize; + // Info count int nLen = 0; for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); @@ -616,7 +383,8 @@ RaiseInfo::RaiseInfo(typelib_TypeDescription * pTD)throw () for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); pCompTD; pCompTD = pCompTD->pBaseTypeDescription) { - int typeInfoLen = mscx_getRTTI_len(pCompTD->aBase.pTypeName); + int typeInfoLen; + RTTInfos::get(pCompTD->aBase.pTypeName, &typeInfoLen); // Mem has to be on 4-byte Boundary if (typeInfoLen % 4 != 0) { @@ -692,244 +460,6 @@ RaiseInfo::RaiseInfo(typelib_TypeDescription * pTD)throw () assert(etMem + etMemOffset == pCode + totalSize); } -ExceptionInfos::ExceptionInfos() throw () -{ -} - -RaiseInfo * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTD ) throw () -{ - static ExceptionInfos* s_pInfos = []() { - SYSTEM_INFO systemInfo; - GetSystemInfo(&systemInfo); - allocationGranularity = systemInfo.dwAllocationGranularity; - - return new ExceptionInfos(); - }(); - - assert( pTD && - (pTD->eTypeClass == typelib_TypeClass_STRUCT || - pTD->eTypeClass == typelib_TypeClass_EXCEPTION) ); - - RaiseInfo * pRaiseInfo; - - OUString const & rTypeName = OUString::unacquired( &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( pTD ); - - // Put into map - pair< t_string2PtrMap::iterator, bool > insertion( - s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, static_cast<void *>(pRaiseInfo) ) ) ); - assert(insertion.second && "### raise info insertion failed?!"); - } - else - { - // Reuse existing info - pRaiseInfo = static_cast<RaiseInfo *>(iFind->second); - } - - return pRaiseInfo; -} - -type_info * mscx_getRTTI( - OUString const & rUNOname ) -{ - static RTTInfos* s_pRTTIs = new RTTInfos(); - return s_pRTTIs->getRTTI( rUNOname ); -} -int mscx_getRTTI_len( - OUString const & rUNOname) -{ - static RTTInfos* s_pRTTIs = new RTTInfos(); - return s_pRTTIs->getRTTI_len(rUNOname); -} - - -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 inlining of - // ExceptionInfos::getRaiseInfo() - - // construct cpp exception object - typelib_TypeDescription * pTD = nullptr; - TYPELIB_DANGER_GET( &pTD, pUnoExc->pType ); - - void * pCppExc = alloca( pTD->nSize ); - ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTD, pUno2Cpp ); - - ULONG_PTR arFilterArgs[4]; - arFilterArgs[0] = MSVC_magic_number; - arFilterArgs[1] = reinterpret_cast<ULONG_PTR>(pCppExc); - arFilterArgs[2] = reinterpret_cast<ULONG_PTR>(ExceptionInfos::getRaiseInfo( pTD )); - arFilterArgs[3] = reinterpret_cast<RaiseInfo *>(arFilterArgs[2])->_codeBase; - - // Destruct uno exception - ::uno_any_destruct( pUnoExc, nullptr ); - TYPELIB_DANGER_RELEASE( pTD ); - - // last point to release anything not affected by stack unwinding - RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 4, arFilterArgs); -} - -namespace -{ -// This function does the same check as __CxxDetectRethrow from msvcrt (see its -// crt/src/vcruntime/mgdframe.cpp). But it does not alter the global state, i.e. it does not -// increment __ProcessingThrow, and so does not break following exception handling. We rely on the -// definition of EHExceptionRecord, PER_IS_MSVC_EH and PER_PTHROW, that are current as of msvcrt -// 2017 (14.14.26428). -bool DetectRethrow(void* ppExcept) -{ - struct EHExceptionRecord - { - DWORD ExceptionCode; - DWORD ExceptionFlags; - struct _EXCEPTION_RECORD* ExceptionRecord; - PVOID ExceptionAddress; - DWORD NumberParameters; - struct alignas(8) - { - DWORD magicNumber; - PVOID pExceptionObject; - PVOID pThrowInfo; - PVOID pThrowImageBase; - } params; - }; - - constexpr auto PER_IS_MSVC_EH = [](EHExceptionRecord* p) { - constexpr DWORD EH_EXCEPTION_NUMBER = 0xE06D7363; // The NT Exception # that msvcrt uses ('msc' | 0xE0000000) - constexpr DWORD EH_MAGIC_NUMBER1 = 0x19930520; // latest magic # in thrown object - constexpr DWORD EH_MAGIC_NUMBER2 = 0x19930521; // latest magic # in func info for exception specs - constexpr DWORD EH_MAGIC_NUMBER3 = 0x19930522; // latest magic # - constexpr DWORD EH_EXCEPTION_PARAMETERS = 4; // Number of parameters in exception record for AMD64 - - return p->ExceptionCode == EH_EXCEPTION_NUMBER - && p->NumberParameters == EH_EXCEPTION_PARAMETERS - && (p->params.magicNumber == EH_MAGIC_NUMBER1 - || p->params.magicNumber == EH_MAGIC_NUMBER2 - || p->params.magicNumber == EH_MAGIC_NUMBER3); - }; - - constexpr auto PER_PTHROW = [](EHExceptionRecord* p) { - return p->params.pThrowInfo; - }; - - EHExceptionRecord* pExcept; - if (!ppExcept) - return false; - pExcept = *static_cast<EHExceptionRecord**>(ppExcept); - if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) == nullptr) - { - return true; - } - return false; -} -} - -int mscx_filterCppException( - EXCEPTION_POINTERS * pPointers, - uno_Any * pUnoExc, - uno_Mapping * pCpp2Uno ) -{ - if (pPointers == nullptr) - return EXCEPTION_CONTINUE_SEARCH; - - EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord; - - // Handle only C++ exceptions: - if (pRecord == nullptr || pRecord->ExceptionCode != MSVC_ExceptionCode) - return EXCEPTION_CONTINUE_SEARCH; - - const bool rethrow = DetectRethrow(&pRecord); - assert(pRecord == pPointers->ExceptionRecord); - - if (rethrow && pRecord == pPointers->ExceptionRecord) - { - pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >(__current_exception()); - } - - // Rethrow: handle only C++ exceptions: - if (pRecord == nullptr || pRecord->ExceptionCode != MSVC_ExceptionCode) - return EXCEPTION_CONTINUE_SEARCH; - - if (pRecord->NumberParameters == 4 && - pRecord->ExceptionInformation[0] == MSVC_magic_number && - pRecord->ExceptionInformation[1] != 0 && - pRecord->ExceptionInformation[2] != 0 && - pRecord->ExceptionInformation[3] != 0) - { - // 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 - ULONG_PTR base = pRecord->ExceptionInformation[3]; - DWORD * types = reinterpret_cast<DWORD *>( - base - + (reinterpret_cast<RaiseInfo *>(pRecord->ExceptionInformation[2]) - ->_types)); - if (types != nullptr && types[0] != 0) - { - DWORD pType = types[1]; - ExceptionType * et - = reinterpret_cast<ExceptionType *>(base + pType); - if (pType != 0 && et->_pTypeInfo != 0) - { - OUString aRTTIname( - OStringToOUString( - (reinterpret_cast<type_info_ *>(base + et->_pTypeInfo) - ->_m_d_name), - RTL_TEXTENCODING_ASCII_US)); - OUString aUNOname( toUNOname( aRTTIname ) ); - - typelib_TypeDescription * pExcTD = nullptr; - typelib_typedescription_getByName( - &pExcTD, aUNOname.pData ); - if (pExcTD == nullptr) - { - OUString sMsg = "[mscx_uno bridge error] UNO type of " - "C++ exception unknown: \"" - + aUNOname + "\", RTTI-name=\"" - + aRTTIname + "\"!"; - - RuntimeException exc( sMsg ); - uno_type_any_constructAndConvert( - pUnoExc, &exc, - cppu::UnoType<decltype(exc)>::get().getTypeLibType(), pCpp2Uno ); - } - else - { - // construct uno exception any - uno_any_constructAndConvert( - pUnoExc, reinterpret_cast<void *>(pRecord->ExceptionInformation[1]), - pExcTD, pCpp2Uno ); - typelib_typedescription_release( pExcTD ); - } - - return EXCEPTION_EXECUTE_HANDLER; - } - } - } - // though this unknown exception leaks now, no user-defined exception - // is ever thrown through the binary C-UNO dispatcher call stack. - RuntimeException exc( "[mscx_uno bridge error] unexpected " - "C++ exception occurred!" ); - uno_type_any_constructAndConvert( - pUnoExc, &exc, cppu::UnoType<decltype(exc)>::get().getTypeLibType(), pCpp2Uno ); - return EXCEPTION_EXECUTE_HANDLER; -} - -} - #pragma pack(pop) /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx b/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx deleted file mode 100644 index 88d3dcd68950..000000000000 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ -#pragma once - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> - -#include <rtl/ustring.hxx> - - -class type_info; -typedef struct _uno_Any uno_Any; -typedef struct _uno_Mapping uno_Mapping; - -namespace CPPU_CURRENT_NAMESPACE -{ - -const DWORD MSVC_ExceptionCode = 0xe06d7363; -const long MSVC_magic_number = 0x19930520L; - -typedef enum { REGPARAM_INT, REGPARAM_FLT } RegParamKind; - -type_info * mscx_getRTTI( OUString const & rUNOname ); - -int mscx_filterCppException( - EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ); - -void mscx_raiseException( - uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); - -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx index aa0cdda9de3d..938775629c17 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx @@ -31,7 +31,7 @@ #include <unointerfaceproxy.hxx> #include <vtables.hxx> -#include "mscx.hxx" +#include <msvc/except.hxx> #if OSL_DEBUG_LEVEL > 1 #include <stdio.h> @@ -221,7 +221,7 @@ bool cpp_call( aCppArgs[24].i, aCppArgs[25].i, aCppArgs[26].i, aCppArgs[27].i, aCppArgs[28].i, aCppArgs[29].i, aCppArgs[30].i, aCppArgs[31].i ); } - __except (CPPU_CURRENT_NAMESPACE::mscx_filterCppException( + __except (msvc_filterCppException( GetExceptionInformation(), *ppUnoExc, pThis->getBridge()->getCpp2Uno() )) { |