summaryrefslogtreecommitdiff
path: root/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx')
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx89
1 files changed, 80 insertions, 9 deletions
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 159eb99a4756..974a4a94d48b 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
@@ -18,6 +18,12 @@
*/
+#include <sal/config.h>
+
+#include <cassert>
+#include <limits>
+#include <typeinfo>
+
#include <malloc.h>
#include <com/sun/star/uno/genfunc.hxx>
@@ -34,6 +40,8 @@
#include <msvc/cpp2uno.hxx>
#include <msvc/amd64.hxx>
+extern "C" IMAGE_DOS_HEADER const __ImageBase;
+
using namespace ::com::sun::star;
extern "C" typelib_TypeClass cpp_vtable_call(sal_Int64 nOffsetAndIndex, void ** pCallStack)
@@ -141,24 +149,87 @@ std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(
return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
}
+static sal_uInt32 imageRelative(void const * p) {
+ assert(
+ reinterpret_cast<sal_uIntPtr>(p) >= reinterpret_cast<sal_uIntPtr>(&__ImageBase)
+ && reinterpret_cast<sal_uIntPtr>(p) - reinterpret_cast<sal_uIntPtr>(&__ImageBase)
+ <= std::numeric_limits<sal_uInt32>::max());
+ return reinterpret_cast<sal_uIntPtr>(p) - reinterpret_cast<sal_uIntPtr>(&__ImageBase);
+}
+
+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, and on how <https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483>
+// "Accessing the current module’s HINSTANCE from a static library" obtians __ImageBase:
+
+struct RttiClassHierarchyDescriptor;
+
+#pragma warning (push)
+#pragma warning (disable: 4324) // "structure was padded due to alignment specifier"
+
+struct alignas(16) RttiBaseClassDescriptor {
+ sal_uInt32 n0 = imageRelative(&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(imageRelative(chd)) {}
+};
+
+struct alignas(4) RttiBaseClassArray {
+ sal_uInt32 n0;
+ sal_uInt32 n1 = 0;
+ RttiBaseClassArray(RttiBaseClassDescriptor const * bcd): n0(imageRelative(bcd)) {}
+};
+
+struct alignas(8) RttiClassHierarchyDescriptor {
+ sal_uInt32 n0 = 0;
+ sal_uInt32 n1 = 0;
+ sal_uInt32 n2 = 1;
+ sal_uInt32 n3;
+ RttiClassHierarchyDescriptor(RttiBaseClassArray const * bca): n3(imageRelative(bca)) {}
+};
+
+struct alignas(16) RttiCompleteObjectLocator {
+ sal_uInt32 n0 = 1;
+ sal_uInt32 n1 = 0;
+ sal_uInt32 n2 = 0;
+ sal_uInt32 n3 = imageRelative(&typeid(ProxyRtti));
+ sal_uInt32 n4;
+ sal_uInt32 n5 = imageRelative(this);
+ RttiCompleteObjectLocator(RttiClassHierarchyDescriptor const * chd): n4(imageRelative(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;
}