msvcrt: Fixed RTTI structure on 64-bit systems.

This commit is contained in:
Piotr Caban 2012-09-07 11:01:17 +02:00 committed by Alexandre Julliard
parent c41fd08ddc
commit 8060752c09
4 changed files with 157 additions and 89 deletions

View File

@ -39,42 +39,6 @@ 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;
@ -93,6 +57,7 @@ static inline const rtti_object_locator *get_obj_locator( void *cppobj )
return (const rtti_object_locator *)vtable[-1];
}
#ifndef __x86_64__
static void dump_obj_locator( const rtti_object_locator *ptr )
{
int i;
@ -117,12 +82,13 @@ static void dump_obj_locator( const rtti_object_locator *ptr )
}
}
#ifdef __x86_64__
static void dump_obj_locator_x64( const rtti_object_locator_x64 *ptr )
#else
static void dump_obj_locator( const rtti_object_locator *ptr )
{
int i;
char *base = (char*)ptr - ptr->object_locator;
const rtti_object_hierarchy_x64 *h = (const rtti_object_hierarchy_x64*)(base + ptr->type_hierarchy);
char *base = ptr->signature == 0 ? (char*)GetModuleHandleW(NULL) : (char*)ptr - ptr->object_locator;
const rtti_object_hierarchy *h = (const rtti_object_hierarchy*)(base + ptr->type_hierarchy);
const type_info *type_descriptor = (const type_info*)(base + ptr->type_descriptor);
TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
@ -132,8 +98,8 @@ static void dump_obj_locator_x64( const rtti_object_locator_x64 *ptr )
h->signature, h->attributes, h->array_len, base + h->base_classes );
for (i = 0; i < h->array_len; i++)
{
const rtti_base_descriptor_x64 *bases = (rtti_base_descriptor_x64*)(base +
((const rtti_base_array_x64*)(base + h->base_classes))->bases[i]);
const rtti_base_descriptor *bases = (rtti_base_descriptor*)(base +
((const rtti_base_array*)(base + h->base_classes))->bases[i]);
TRACE( " base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
bases,
@ -739,6 +705,17 @@ DEFINE_EXCEPTION_TYPE_INFO( bad_typeid, 1, &exception_cxx_type_info, NULL );
DEFINE_EXCEPTION_TYPE_INFO( bad_cast, 1, &exception_cxx_type_info, NULL );
DEFINE_EXCEPTION_TYPE_INFO( __non_rtti_object, 2, &bad_typeid_cxx_type_info, &exception_cxx_type_info );
void msvcrt_init_exception(void *base)
{
#ifdef __x86_64__
init_type_info_rtti(base);
init_exception_rtti(base);
init_bad_typeid_rtti(base);
init_bad_cast_rtti(base);
init___non_rtti_object_rtti(base);
#endif
}
/******************************************************************
* ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
@ -906,15 +883,15 @@ const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
__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 */
const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
char *base;
if(obj_locator->signature == 0)
ret = obj_locator->type_descriptor;
base = (char*)GetModuleHandleW(NULL);
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);
}
base = (char*)obj_locator - obj_locator->object_locator;
ret = (type_info*)(base + obj_locator->type_descriptor);
}
__EXCEPT_PAGE_FAULT
{
@ -1031,48 +1008,31 @@ void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown,
{
int i;
const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
const rtti_object_hierarchy *obj_bases;
const rtti_base_array *base_array;
char *base;
if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
if(obj_locator->signature == 0)
{
const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases;
if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
ret = NULL;
for (i = 0; i < obj_bases->array_len; i++)
{
const type_info *typ = base_desc[i]->type_descriptor;
if (!strcmp(typ->mangled, dst->mangled))
{
void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
ret = get_this_pointer( &base_desc[i]->offsets, this_ptr );
break;
}
}
}
base = (char*)GetModuleHandleW(NULL);
else
base = (char*)obj_locator - obj_locator->object_locator;
obj_bases = (const rtti_object_hierarchy*)(base + obj_locator->type_hierarchy);
base_array = (const rtti_base_array*)(base + obj_bases->base_classes);
ret = NULL;
for (i = 0; i < obj_bases->array_len; i++)
{
const rtti_object_locator_x64 *obj_locator_x64 = (const rtti_object_locator_x64*)obj_locator;
const char *base = (const char*)obj_locator_x64 - obj_locator_x64->object_locator;
const rtti_object_hierarchy_x64 *obj_bases = (const rtti_object_hierarchy_x64*)(base + obj_locator_x64->type_hierarchy);
const rtti_base_array_x64 *base_array = (const rtti_base_array_x64*)(base + obj_bases->base_classes);
const rtti_base_descriptor *base_desc = (const rtti_base_descriptor*)(base + base_array->bases[i]);
const type_info *typ = (const type_info*)(base + base_desc->type_descriptor);
if (TRACE_ON(msvcrt)) dump_obj_locator_x64(obj_locator_x64);
ret = NULL;
for (i = 0; i < obj_bases->array_len; i++)
if (!strcmp(typ->mangled, dst->mangled))
{
const rtti_base_descriptor_x64 *base_desc = (const rtti_base_descriptor_x64*)(base + base_array->bases[i]);
const type_info *typ = (const type_info*)(base + base_desc->type_descriptor);
if (!strcmp(typ->mangled, dst->mangled))
{
void *this_ptr = (char *)cppobj - obj_locator_x64->base_class_offset;
ret = get_this_pointer( &base_desc->offsets, this_ptr );
break;
}
void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
ret = get_this_pointer( &base_desc->offsets, this_ptr );
break;
}
}
if (!ret && do_throw)

View File

@ -63,7 +63,9 @@
#endif /* _WIN64 */
#define DEFINE_RTTI_DATA(name, off, base_classes, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \
#ifndef __x86_64__
#define DEFINE_RTTI_DATA(name, off, base_classes_no, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \
static const type_info name ## _type_info = { \
&MSVCRT_type_info_vtable, \
NULL, \
@ -72,7 +74,7 @@
\
static const rtti_base_descriptor name ## _rtti_base_descriptor = { \
&name ##_type_info, \
base_classes, \
base_classes_no, \
{ 0, -1, 0}, \
64 \
}; \
@ -95,7 +97,7 @@ static const rtti_base_array name ## _rtti_base_array = { \
static const rtti_object_hierarchy name ## _hierarchy = { \
0, \
0, \
base_classes+1, \
base_classes_no+1, \
&name ## _rtti_base_array \
}; \
\
@ -107,6 +109,74 @@ const rtti_object_locator name ## _rtti = { \
&name ## _hierarchy \
}
#else
#define DEFINE_RTTI_DATA(name, off, base_classes_no, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \
static const type_info name ## _type_info = { \
&MSVCRT_type_info_vtable, \
NULL, \
mangled_name \
}; \
\
static rtti_base_descriptor name ## _rtti_base_descriptor = { \
0xdeadbeef, \
base_classes_no, \
{ 0, -1, 0}, \
64 \
}; \
\
static rtti_base_array name ## _rtti_base_array = { \
{ \
0xdeadbeef, \
0xdeadbeef, \
0xdeadbeef, \
0xdeadbeef, \
0xdeadbeef, \
0xdeadbeef, \
0xdeadbeef, \
0xdeadbeef, \
0xdeadbeef, \
0xdeadbeef, \
} \
}; \
\
static rtti_object_hierarchy name ## _hierarchy = { \
0, \
0, \
base_classes_no+1, \
0xdeadbeef \
}; \
\
rtti_object_locator name ## _rtti = { \
1, \
off, \
0, \
0xdeadbeef, \
0xdeadbeef, \
0xdeadbeef \
};\
\
static void init_ ## name ## _rtti(char *base) \
{ \
name ## _rtti_base_descriptor.type_descriptor = (char*)&name ## _type_info - base; \
name ## _rtti_base_array.bases[0] = (char*)&name ## _rtti_base_descriptor - base; \
name ## _rtti_base_array.bases[1] = (char*)cl1 - base; \
name ## _rtti_base_array.bases[2] = (char*)cl2 - base; \
name ## _rtti_base_array.bases[3] = (char*)cl3 - base; \
name ## _rtti_base_array.bases[4] = (char*)cl4 - base; \
name ## _rtti_base_array.bases[5] = (char*)cl5 - base; \
name ## _rtti_base_array.bases[6] = (char*)cl6 - base; \
name ## _rtti_base_array.bases[7] = (char*)cl7 - base; \
name ## _rtti_base_array.bases[8] = (char*)cl8 - base; \
name ## _rtti_base_array.bases[9] = (char*)cl9 - base; \
name ## _hierarchy.base_classes = (char*)&name ## _rtti_base_array - base; \
name ## _rtti.type_descriptor = (char*)&name ## _type_info - base; \
name ## _rtti.type_hierarchy = (char*)&name ## _hierarchy - base; \
name ## _rtti.object_locator = (char*)&name ## _rtti - base; \
}
#endif
#define DEFINE_RTTI_DATA0(name, off, mangled_name) \
DEFINE_RTTI_DATA(name, off, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name)
#define DEFINE_RTTI_DATA1(name, off, cl1, mangled_name) \
@ -122,7 +192,8 @@ const rtti_object_locator name ## _rtti = { \
#define DEFINE_RTTI_DATA9(name, off, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \
DEFINE_RTTI_DATA(name, off, 9, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name)
/* rtti */
#ifndef __x86_64__
typedef struct _rtti_base_descriptor
{
const type_info *type_descriptor;
@ -152,3 +223,38 @@ typedef struct _rtti_object_locator
const type_info *type_descriptor;
const rtti_object_hierarchy *type_hierarchy;
} rtti_object_locator;
#else
typedef struct
{
unsigned int type_descriptor;
int num_base_classes;
this_ptr_offsets offsets; /* offsets for computing the this pointer */
unsigned int attributes;
} rtti_base_descriptor;
typedef struct
{
unsigned int bases[10]; /* First element is the class itself */
} rtti_base_array;
typedef struct
{
unsigned int signature;
unsigned int attributes;
int array_len; /* Size of the array pointed to by 'base_classes' */
unsigned int base_classes;
} rtti_object_hierarchy;
typedef struct
{
unsigned int signature;
int base_class_offset;
unsigned int flags;
unsigned int type_descriptor;
unsigned int type_hierarchy;
unsigned int object_locator;
} rtti_object_locator;
#endif

View File

@ -97,6 +97,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
msvcrt_init_exception(hinstDLL);
if (!msvcrt_init_tls())
return FALSE;
msvcrt_init_mt_locks();

View File

@ -255,6 +255,7 @@ extern char* __cdecl __unDNameEx(char *,const char*,int,malloc_func_t,free_func_
extern void msvcrt_init_mt_locks(void) DECLSPEC_HIDDEN;
extern void msvcrt_free_mt_locks(void) DECLSPEC_HIDDEN;
extern void msvcrt_init_exception(void*) DECLSPEC_HIDDEN;
extern BOOL msvcrt_init_locale(void) DECLSPEC_HIDDEN;
extern void msvcrt_init_math(void) DECLSPEC_HIDDEN;
extern void msvcrt_init_io(void) DECLSPEC_HIDDEN;