msvcrt: Support 64-bit RTTI in __RTtypeid function.
This commit is contained in:
parent
63be52e2aa
commit
fbae5a95c3
|
@ -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.@)
|
||||
*
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue