bridges/source/cpp_uno/msvc_win32_intel/except.cxx | 66 ++++++++++++++++++-- bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx | 57 ++++++++++++++++- bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx | 6 - cppuhelper/Module_cppuhelper.mk | 2 4 files changed, 117 insertions(+), 14 deletions(-)
New commits: commit 654bd1ab45a0f24571f029fcd247cf28db575871 Author: Stephan Bergmann <sberg...@redhat.com> AuthorDate: Tue Aug 7 18:03:00 2018 +0200 Commit: Stephan Bergmann <sberg...@redhat.com> CommitDate: Thu Aug 9 15:55:39 2018 +0200 No need for CppunitTest_cppuhelper_qa_misc to be a subsequentcheck Change-Id: I5b27c4803a9927ff9e2be084e7abbae7fdf94f55 Reviewed-on: https://gerrit.libreoffice.org/58696 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sberg...@redhat.com> diff --git a/cppuhelper/Module_cppuhelper.mk b/cppuhelper/Module_cppuhelper.mk index 296b85daf3f9..10d51758d662 100644 --- a/cppuhelper/Module_cppuhelper.mk +++ b/cppuhelper/Module_cppuhelper.mk @@ -19,11 +19,11 @@ $(eval $(call gb_Module_add_targets,cppuhelper,\ $(eval $(call gb_Module_add_check_targets,cppuhelper,\ CppunitTest_cppuhelper_cppu_ifcontainer \ CppunitTest_cppuhelper_cppu_unourl \ + CppunitTest_cppuhelper_qa_misc \ )) # CppunitTest_cppuhelper_qa_weak depends on module bridges $(eval $(call gb_Module_add_subsequentcheck_targets,cppuhelper,\ - CppunitTest_cppuhelper_qa_misc \ CppunitTest_cppuhelper_qa_weak \ )) commit 8313116f962ac87e103ea22aafb58700b8c695da Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Wed Aug 8 12:42:32 2018 +0200 Commit: Stephan Bergmann <sberg...@redhat.com> CommitDate: Thu Aug 9 15:55:28 2018 +0200 Don't use internal __CxxDetectRethrow: it has side effects Since the __CxxDetectRethrow may increment __ProcessingThrow, which then must be decremented in __CxxUnregisterExceptionObject, and the latter does many other funny things with exception handling CRT machinery, we cannot use those internal functions (neither alone, nor together), or we end up breaking runtime's expectations: the runtime code checks __ProcessingThrow left and right, expecting its non-0 value to indicate "we are unwinding... possibly called from a dtor()". In this case, e.g., std::current_exception returns nullptr inside catch block. This creates our own copy of __CxxDetectRethrow, which does not mangle the global state, and just performs the same checks. This is a dirty hack, and it relies on current layout of the exception description layout - so must be synchronized in the event of changes! Change-Id: I2c475fbc2468073b796c7e9d0f4dfcd315896489 Reviewed-on: https://gerrit.libreoffice.org/58730 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sberg...@redhat.com> diff --git a/bridges/source/cpp_uno/msvc_win32_intel/except.cxx b/bridges/source/cpp_uno/msvc_win32_intel/except.cxx index 3ce8f5c50db9..7af24e97c868 100644 --- a/bridges/source/cpp_uno/msvc_win32_intel/except.cxx +++ b/bridges/source/cpp_uno/msvc_win32_intel/except.cxx @@ -23,16 +23,16 @@ #include <typeinfo.h> #include <signal.h> -#include "rtl/alloc.h" -#include "rtl/strbuf.hxx" -#include "rtl/ustrbuf.hxx" +#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 <com/sun/star/uno/Any.hxx> #include <unordered_map> #include "msci.hxx" -#include "except.hxx" +#include <except.hxx> #pragma pack(push, 8) @@ -468,6 +468,60 @@ void msci_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) 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 = ('msc' | 0xE0000000); // The NT Exception # that msvcrt uses + 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 = *(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 ) { @@ -478,7 +532,7 @@ int msci_filterCppException( if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode) return EXCEPTION_CONTINUE_SEARCH; - bool rethrow = __CxxDetectRethrow( &pRecord ); + const bool rethrow = __DetectRethrow(&pRecord); assert(pRecord == pPointers->ExceptionRecord); if (rethrow && pRecord == pPointers->ExceptionRecord) 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 86753103a751..c03716151bbc 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx @@ -782,6 +782,61 @@ void mscx_raiseException( 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) EHParameters + { + DWORD magicNumber; + PVOID pExceptionObject; + PVOID pThrowInfo; + PVOID pThrowImageBase; + } params; + }; + + constexpr auto PER_IS_MSVC_EH = [](EHExceptionRecord* p) { + constexpr DWORD EH_EXCEPTION_NUMBER = ('msc' | 0xE0000000); // The NT Exception # that msvcrt uses + 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 = *(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, @@ -796,7 +851,7 @@ int mscx_filterCppException( if (pRecord == nullptr || pRecord->ExceptionCode != MSVC_ExceptionCode) return EXCEPTION_CONTINUE_SEARCH; - bool rethrow = __CxxDetectRethrow( &pRecord ); + const bool rethrow = __DetectRethrow(&pRecord); assert(pRecord == pPointers->ExceptionRecord); if (rethrow && pRecord == pPointers->ExceptionRecord) diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx b/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx index f2ccfbf4ab44..078fd23fd11f 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx @@ -47,11 +47,5 @@ void mscx_raiseException( } -//TODO: Work around missing __CxxDetectRethrow in clang-cl for now (predefined -// in cl, <www.geoffchappell.com/studies/msvc/language/predefined/index.html>): -#if defined __clang__ -extern "C" int __cdecl __CxxDetectRethrow(void *); -#endif - #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits