msvcrt: Support 64-bit RTTI in __RTtypeid function.

This commit is contained in:
Piotr Caban 2012-09-05 14:35:42 +02:00 committed by Alexandre Julliard
parent 63be52e2aa
commit fbae5a95c3
2 changed files with 133 additions and 0 deletions

View File

@ -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.@)
*

View File

@ -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 {