Module: wine Branch: master Commit: fbae5a95c3bf64400cfae2bc29a905dca022fe70 URL: http://source.winehq.org/git/wine.git/?a=commit;h=fbae5a95c3bf64400cfae2bc29...
Author: Piotr Caban piotr@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 {