Piotr Caban : msvcrt: Support 64-bit RTTI in __RTtypeid function.

Alexandre Julliard julliard at winehq.org
Wed Sep 5 15:36:45 CDT 2012


Module: wine
Branch: master
Commit: fbae5a95c3bf64400cfae2bc29a905dca022fe70
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=fbae5a95c3bf64400cfae2bc29a905dca022fe70

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed Sep  5 14:35:42 2012 +0200

msvcrt: Support 64-bit RTTI in __RTtypeid function.

---

 dlls/msvcrt/cpp.c       |   75 +++++++++++++++++++++++++++++++++++++++++++++++
 dlls/msvcrt/tests/cpp.c |   58 ++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/dlls/msvcrt/cpp.c b/dlls/msvcrt/cpp.c
index 3fa526e..b1512f5 100644
--- a/dlls/msvcrt/cpp.c
+++ b/dlls/msvcrt/cpp.c
@@ -39,6 +39,42 @@ typedef exception bad_cast;
 typedef exception bad_typeid;
 typedef exception __non_rtti_object;
 
+#ifdef __x86_64__
+
+/* x86_64 RTTI structures */
+typedef struct
+{
+    unsigned int type_descriptor;
+    int num_base_classes;
+    this_ptr_offsets offsets;
+    unsigned int attributes;
+} rtti_base_descriptor_x64;
+
+typedef struct
+{
+    unsigned bases[3];
+} rtti_base_array_x64;
+
+typedef struct
+{
+    unsigned int signature;
+    unsigned int attributes;
+    int array_len;
+    unsigned int base_classes;
+} rtti_object_hierarchy_x64;
+
+typedef struct
+{
+    unsigned int signature;
+    int base_class_offset;
+    unsigned int flags;
+    unsigned int type_descriptor;
+    unsigned int type_hierarchy;
+    unsigned int object_locator; /* not present if signature == 0 */
+} rtti_object_locator_x64;
+
+#endif
+
 extern const vtable_ptr MSVCRT_exception_vtable;
 extern const vtable_ptr MSVCRT_bad_typeid_vtable;
 extern const vtable_ptr MSVCRT_bad_cast_vtable;
@@ -794,6 +830,7 @@ void CDECL MSVCRT_unexpected(void)
  *  This function is usually called by compiler generated code as a result
  *  of using one of the C++ dynamic cast statements.
  */
+#ifndef __x86_64__
 const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
 {
     const type_info *ret;
@@ -822,6 +859,44 @@ const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
     return ret;
 }
 
+#else
+
+const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
+{
+    const type_info *ret;
+
+    if (!cppobj)
+    {
+        bad_typeid e;
+        MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
+        _CxxThrowException( &e, &bad_typeid_exception_type );
+        return NULL;
+    }
+
+    __TRY
+    {
+        const rtti_object_locator *obj_locator = (rtti_object_locator*)get_obj_locator( cppobj );
+        /* FIXME: Change signature==0 handling when wine generates correct RTTI data on 64-bit systems */
+        if(obj_locator->signature == 0)
+            ret = obj_locator->type_descriptor;
+        else
+        {
+            const rtti_object_locator_x64 *obj_locator_x64 = (const rtti_object_locator_x64*)obj_locator;
+            ret = (type_info*)((char*)obj_locator_x64 - obj_locator_x64->object_locator + obj_locator_x64->type_descriptor);
+        }
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        __non_rtti_object e;
+        MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
+        _CxxThrowException( &e, &bad_typeid_exception_type );
+        return NULL;
+    }
+    __ENDTRY
+    return ret;
+}
+#endif
+
 /******************************************************************
  *		__RTDynamicCast (MSVCRT.@)
  *
diff --git a/dlls/msvcrt/tests/cpp.c b/dlls/msvcrt/tests/cpp.c
index dbb948c..ddfb922 100644
--- a/dlls/msvcrt/tests/cpp.c
+++ b/dlls/msvcrt/tests/cpp.c
@@ -828,9 +828,63 @@ static void test_type_info(void)
   ok(res == 1, "expected 1, got %d\n", res);
 }
 
+#ifndef __x86_64__
+#define RTTI_SIGNATURE 0
+#define DEFINE_RTTI_REF(type, name) type *name
+#define RTTI_REF(instance, name) &instance.name
+#else
+#define RTTI_SIGNATURE 1
+#define DEFINE_RTTI_REF(type, name) unsigned name
+#define RTTI_REF(instance, name) FIELD_OFFSET(struct rtti_data, name)
+#endif
 /* Test RTTI functions */
 static void test_rtti(void)
 {
+  struct rtti_data
+  {
+    type_info type_info[4];
+
+    struct _rtti_base_descriptor
+    {
+      DEFINE_RTTI_REF(type_info, type_descriptor);
+      int num_base_classes;
+      struct {
+        int this_offset;
+        int vbase_descr;
+        int vbase_offset;
+      } this_ptr_offsets;
+      unsigned int attributes;
+    } base_descriptor[4];
+
+    struct _rtti_base_array {
+      DEFINE_RTTI_REF(struct _rtti_base_descriptor, bases[4]);
+    } base_array;
+
+    struct _rtti_object_hierarchy {
+      unsigned int signature;
+      unsigned int attributes;
+      int array_len;
+      DEFINE_RTTI_REF(struct _rtti_base_array, base_classes);
+    } object_hierarchy;
+
+    struct {
+      unsigned int signature;
+      int base_class_offset;
+      unsigned int flags;
+      DEFINE_RTTI_REF(type_info, type_descriptor);
+      DEFINE_RTTI_REF(struct _rtti_object_hierarchy, type_hierarchy);
+      DEFINE_RTTI_REF(void, object_locator);
+    } object_locator;
+  } simple_class_rtti = {
+    { {NULL, NULL, "simple_class"} },
+    { {RTTI_REF(simple_class_rtti, type_info[0]), 0, {0, 0, 0}, 0} },
+    { {RTTI_REF(simple_class_rtti, base_descriptor[0])} },
+    {0, 0, 1, RTTI_REF(simple_class_rtti, base_array)},
+    {RTTI_SIGNATURE, 0, 0, RTTI_REF(simple_class_rtti, type_info[0]), RTTI_REF(simple_class_rtti, object_hierarchy), RTTI_REF(simple_class_rtti, object_locator)}
+  };
+  void *simple_class_vtbl[2] = {&simple_class_rtti.object_locator};
+  void *simple_class = &simple_class_vtbl[1];
+
   static const char* e_name = "name";
   type_info *ti,*bti;
   exception e,b;
@@ -865,6 +919,10 @@ static void test_rtti(void)
 
   call_func1(pexception_dtor, &e);
   call_func1(pbad_typeid_dtor, &b);
+
+  ti = p__RTtypeid(&simple_class);
+  ok (ti && ti->mangled && !strcmp(ti->mangled, "simple_class"),
+          "incorrect rtti data\n");
 }
 
 struct _demangle {




More information about the wine-cvs mailing list