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