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 bad_typeid;
|
||||||
typedef exception __non_rtti_object;
|
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_exception_vtable;
|
||||||
extern const vtable_ptr MSVCRT_bad_typeid_vtable;
|
extern const vtable_ptr MSVCRT_bad_typeid_vtable;
|
||||||
extern const vtable_ptr MSVCRT_bad_cast_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
|
* This function is usually called by compiler generated code as a result
|
||||||
* of using one of the C++ dynamic cast statements.
|
* of using one of the C++ dynamic cast statements.
|
||||||
*/
|
*/
|
||||||
|
#ifndef __x86_64__
|
||||||
const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
|
const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
|
||||||
{
|
{
|
||||||
const type_info *ret;
|
const type_info *ret;
|
||||||
@ -822,6 +859,44 @@ const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
|
|||||||
return ret;
|
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.@)
|
* __RTDynamicCast (MSVCRT.@)
|
||||||
*
|
*
|
||||||
|
@ -828,9 +828,63 @@ static void test_type_info(void)
|
|||||||
ok(res == 1, "expected 1, got %d\n", res);
|
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 */
|
/* Test RTTI functions */
|
||||||
static void test_rtti(void)
|
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";
|
static const char* e_name = "name";
|
||||||
type_info *ti,*bti;
|
type_info *ti,*bti;
|
||||||
exception e,b;
|
exception e,b;
|
||||||
@ -865,6 +919,10 @@ static void test_rtti(void)
|
|||||||
|
|
||||||
call_func1(pexception_dtor, &e);
|
call_func1(pexception_dtor, &e);
|
||||||
call_func1(pbad_typeid_dtor, &b);
|
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 {
|
struct _demangle {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user