diff options
Diffstat (limited to 'bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx')
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx index 0908c7666b50..577c318c5767 100644 --- a/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx +++ b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx @@ -18,6 +18,10 @@ */ +#include <sal/config.h> + +#include <typeinfo> + #include <malloc.h> #include <com/sun/star/uno/genfunc.hxx> @@ -124,23 +128,80 @@ std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize( return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize; } +namespace { + +// Some dummy type whose RTTI is used in the synthesized proxy vtables to make uses of dynamic_cast +// on such proxy objects not crash: +struct ProxyRtti {}; + +// The following vtable RTTI data is based on how the code at +// <https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/MicrosoftCXXABI.cpp> computes +// such data: + +struct RttiClassHierarchyDescriptor; + +#pragma warning (push) +#pragma warning (disable: 4324) // "structure was padded due to alignment specifier" + +struct alignas(16) RttiBaseClassDescriptor { + sal_uInt32 n0 = reinterpret_cast<sal_uInt32>(&typeid(ProxyRtti)); + sal_uInt32 n1 = 0; + sal_uInt32 n2 = 0; + sal_uInt32 n3 = 0xFFFFFFFF; + sal_uInt32 n4 = 0; + sal_uInt32 n5 = 0x40; + sal_uInt32 n6; + RttiBaseClassDescriptor(RttiClassHierarchyDescriptor const * chd): + n6(reinterpret_cast<sal_uInt32>(chd)) {} +}; + +struct alignas(4) RttiBaseClassArray { + sal_uInt32 n0; + sal_uInt32 n1 = 0; + RttiBaseClassArray(RttiBaseClassDescriptor const * bcd): n0(reinterpret_cast<sal_uInt32>(bcd)) + {} +}; + +struct alignas(4) RttiClassHierarchyDescriptor { + sal_uInt32 n0 = 0; + sal_uInt32 n1 = 0; + sal_uInt32 n2 = 1; + sal_uInt32 n3; + RttiClassHierarchyDescriptor(RttiBaseClassArray const * bca): + n3(reinterpret_cast<sal_uInt32>(bca)) {} +}; + +struct alignas(16) RttiCompleteObjectLocator { + sal_uInt32 n0 = 0; + sal_uInt32 n1 = 0; + sal_uInt32 n2 = 0; + sal_uInt32 n3 = reinterpret_cast<sal_uInt32>(&typeid(ProxyRtti)); + sal_uInt32 n4; + RttiCompleteObjectLocator(RttiClassHierarchyDescriptor const * chd): + n4(reinterpret_cast<sal_uInt32>(chd)) {} +}; + +struct Rtti { + RttiBaseClassDescriptor bcd; + RttiBaseClassArray bca; + RttiClassHierarchyDescriptor chd; + RttiCompleteObjectLocator col; + Rtti(): bcd(&chd), bca(&bcd), chd(&bca), col(&chd) {} +}; + +#pragma warning (pop) + +} + bridges::cpp_uno::shared::VtableFactory::Slot * bridges::cpp_uno::shared::VtableFactory::initializeBlock( void * block, sal_Int32 slotCount, sal_Int32, typelib_InterfaceTypeDescription *) { - struct Rtti { - sal_Int32 n0, n1, n2; - type_info * rtti; - Rtti(): - n0(0), n1(0), n2(0), - rtti(RTTInfos::get("com.sun.star.uno.XInterface")) - {} - }; static Rtti rtti; Slot * slots = mapBlockToVtable(block); - slots[-1].fn = &rtti; + slots[-1].fn = &rtti.col; return slots + slotCount; } |