Commit 5d5f5230 authored by Alexandre Julliard's avatar Alexandre Julliard

Output the virtual tables for the exception classes using assembly so

that they can have the correct layout, and get rid of the corresponding hacks in RTTI_GetObjectLocator. Build more of the code on non-i386 platforms too. Protect __RTDynamicCast and friends with exception handlers. Fix handling of the vtable pointer so that we don't need to declare all object pointers as type_info.
parent ec39d655
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* msvcrt.dll C++ objects * msvcrt.dll C++ objects
* *
* Copyright 2000 Jon Griffiths * Copyright 2000 Jon Griffiths
* Copyright 2003 Alexandre Julliard * Copyright 2003, 2004 Alexandre Julliard
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -37,29 +37,13 @@ ...@@ -37,29 +37,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
/*
* exception object: base for exception, bad_cast, bad_typeid, __non_rtti_object
*/
typedef struct
{
void* pfn_vector_dtor;
void* pfn_what;
} exception_vtable;
typedef struct __exception
{
const exception_vtable *vtable;
char *name; /* Name of this exception, always a new copy for each object */
int do_free; /* Whether to free 'name' in our dtor */
} exception;
typedef exception bad_cast; typedef exception bad_cast;
typedef exception bad_typeid; typedef exception bad_typeid;
typedef exception __non_rtti_object; typedef exception __non_rtti_object;
typedef struct _rtti_base_descriptor typedef struct _rtti_base_descriptor
{ {
type_info *type_descriptor; const type_info *type_descriptor;
int num_base_classes; int num_base_classes;
this_ptr_offsets offsets; /* offsets for computing the this pointer */ this_ptr_offsets offsets; /* offsets for computing the this pointer */
unsigned int attributes; unsigned int attributes;
...@@ -83,26 +67,41 @@ typedef struct _rtti_object_locator ...@@ -83,26 +67,41 @@ typedef struct _rtti_object_locator
unsigned int signature; unsigned int signature;
int base_class_offset; int base_class_offset;
unsigned int flags; unsigned int flags;
type_info *type_descriptor; const type_info *type_descriptor;
const rtti_object_hierarchy *type_hierarchy; const rtti_object_hierarchy *type_hierarchy;
} rtti_object_locator; } rtti_object_locator;
#ifdef __i386__ /* thiscall functions are i386-specific */ #ifdef __i386__ /* thiscall functions are i386-specific */
#define THISCALL(func) __thiscall_ ## func
#define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func)
#define DEFINE_THISCALL_WRAPPER(func) \ #define DEFINE_THISCALL_WRAPPER(func) \
extern void __thiscall_ ## func(); \ extern void THISCALL(func)(); \
__ASM_GLOBAL_FUNC(__thiscall_ ## func, \ __ASM_GLOBAL_FUNC(__thiscall_ ## func, \
"popl %eax\n\t" \ "popl %eax\n\t" \
"pushl %ecx\n\t" \ "pushl %ecx\n\t" \
"pushl %eax\n\t" \ "pushl %eax\n\t" \
"jmp " __ASM_NAME(#func) ) "jmp " __ASM_NAME(#func) )
#else /* __i386__ */
#define THISCALL(func) func
#define THISCALL_NAME(func) __ASM_NAME(#func)
#define DEFINE_THISCALL_WRAPPER(func) /* nothing */
#endif /* __i386__ */
const exception_vtable MSVCRT_exception_vtable; extern const vtable_ptr MSVCRT_exception_vtable;
const exception_vtable MSVCRT_bad_typeid_vtable; extern const vtable_ptr MSVCRT_bad_typeid_vtable;
const exception_vtable MSVCRT_bad_cast_vtable; extern const vtable_ptr MSVCRT_bad_cast_vtable;
const exception_vtable MSVCRT___non_rtti_object_vtable; extern const vtable_ptr MSVCRT___non_rtti_object_vtable;
static const exception_vtable MSVCRT_type_info_vtable; extern const vtable_ptr MSVCRT_type_info_vtable;
static inline const rtti_object_locator *get_obj_locator( void *cppobj )
{
const vtable_ptr *vtable = get_vtable( cppobj );
return (const rtti_object_locator *)vtable[-1];
}
static void dump_obj_locator( const rtti_object_locator *ptr ) static void dump_obj_locator( const rtti_object_locator *ptr )
{ {
...@@ -128,6 +127,14 @@ static void dump_obj_locator( const rtti_object_locator *ptr ) ...@@ -128,6 +127,14 @@ static void dump_obj_locator( const rtti_object_locator *ptr )
} }
} }
/* filter for page-fault exceptions */
static WINE_EXCEPTION_FILTER(page_fault)
{
if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
return EXCEPTION_EXECUTE_HANDLER;
return EXCEPTION_CONTINUE_SEARCH;
}
/* Internal common ctor for exception */ /* Internal common ctor for exception */
static void WINAPI EXCEPTION_ctor(exception *_this, const char** name) static void WINAPI EXCEPTION_ctor(exception *_this, const char** name)
{ {
...@@ -620,41 +627,36 @@ void * __stdcall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int fl ...@@ -620,41 +627,36 @@ void * __stdcall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int fl
/* vtables */ /* vtables */
const exception_vtable MSVCRT_exception_vtable = #define __ASM_VTABLE(name,funcs) \
{ __asm__(".align 4\n" \
__thiscall_MSVCRT_exception_vector_dtor, "\t.long " __ASM_NAME(#name "_rtti") "\n" \
__thiscall_MSVCRT_what_exception "\t.globl " __ASM_NAME("MSVCRT_" #name "_vtable") "\n" \
}; __ASM_NAME("MSVCRT_" #name "_vtable") ":\n" \
"\t.long " THISCALL_NAME(MSVCRT_ ## name ## _vector_dtor) "\n" \
funcs);
const exception_vtable MSVCRT_bad_typeid_vtable = #define __ASM_EXCEPTION_VTABLE(name) \
{ __ASM_VTABLE(name, "\t.long " THISCALL_NAME(MSVCRT_what_exception) );
__thiscall_MSVCRT_bad_typeid_vector_dtor,
__thiscall_MSVCRT_what_exception
};
const exception_vtable MSVCRT_bad_cast_vtable = #ifndef __GNUC__
{ void __asm_dummy_vtables(void) {
__thiscall_MSVCRT_bad_cast_vector_dtor, #endif
__thiscall_MSVCRT_what_exception
};
const exception_vtable MSVCRT___non_rtti_object_vtable = __ASM_VTABLE(type_info,"");
{ __ASM_EXCEPTION_VTABLE(exception);
__thiscall_MSVCRT___non_rtti_object_vector_dtor, __ASM_EXCEPTION_VTABLE(bad_typeid);
__thiscall_MSVCRT_what_exception __ASM_EXCEPTION_VTABLE(bad_cast);
}; __ASM_EXCEPTION_VTABLE(__non_rtti_object);
static const exception_vtable MSVCRT_type_info_vtable = #ifndef __GNUC__
{ }
__thiscall_MSVCRT_type_info_vector_dtor, #endif
NULL
};
/* Static RTTI for exported objects */ /* Static RTTI for exported objects */
static type_info exception_type_info = static const type_info exception_type_info =
{ {
(void*)&MSVCRT_type_info_vtable, &MSVCRT_type_info_vtable,
NULL, NULL,
".?AVexception@@" ".?AVexception@@"
}; };
...@@ -684,7 +686,7 @@ static const rtti_object_hierarchy exception_type_hierarchy = ...@@ -684,7 +686,7 @@ static const rtti_object_hierarchy exception_type_hierarchy =
&exception_rtti_base_array &exception_rtti_base_array
}; };
static const rtti_object_locator exception_rtti = const rtti_object_locator exception_rtti =
{ {
0, 0,
0, 0,
...@@ -699,12 +701,12 @@ static const cxx_type_info exception_cxx_type_info = ...@@ -699,12 +701,12 @@ static const cxx_type_info exception_cxx_type_info =
&exception_type_info, &exception_type_info,
{ 0, -1, 0 }, { 0, -1, 0 },
sizeof(exception), sizeof(exception),
(cxx_copy_ctor)__thiscall_MSVCRT_exception_copy_ctor (cxx_copy_ctor)THISCALL(MSVCRT_exception_copy_ctor)
}; };
static type_info bad_typeid_type_info = static const type_info bad_typeid_type_info =
{ {
(void*)&MSVCRT_type_info_vtable, &MSVCRT_type_info_vtable,
NULL, NULL,
".?AVbad_typeid@@" ".?AVbad_typeid@@"
}; };
...@@ -734,7 +736,7 @@ static const rtti_object_hierarchy bad_typeid_type_hierarchy = ...@@ -734,7 +736,7 @@ static const rtti_object_hierarchy bad_typeid_type_hierarchy =
&bad_typeid_rtti_base_array &bad_typeid_rtti_base_array
}; };
static const rtti_object_locator bad_typeid_rtti = const rtti_object_locator bad_typeid_rtti =
{ {
0, 0,
0, 0,
...@@ -749,12 +751,12 @@ static const cxx_type_info bad_typeid_cxx_type_info = ...@@ -749,12 +751,12 @@ static const cxx_type_info bad_typeid_cxx_type_info =
&bad_typeid_type_info, &bad_typeid_type_info,
{ 0, -1, 0 }, { 0, -1, 0 },
sizeof(exception), sizeof(exception),
(cxx_copy_ctor)__thiscall_MSVCRT_bad_typeid_copy_ctor (cxx_copy_ctor)THISCALL(MSVCRT_bad_typeid_copy_ctor)
}; };
static type_info bad_cast_type_info = static const type_info bad_cast_type_info =
{ {
(void*)&MSVCRT_type_info_vtable, &MSVCRT_type_info_vtable,
NULL, NULL,
".?AVbad_cast@@" ".?AVbad_cast@@"
}; };
...@@ -784,7 +786,7 @@ static const rtti_object_hierarchy bad_cast_type_hierarchy = ...@@ -784,7 +786,7 @@ static const rtti_object_hierarchy bad_cast_type_hierarchy =
&bad_cast_rtti_base_array &bad_cast_rtti_base_array
}; };
static const rtti_object_locator bad_cast_rtti = const rtti_object_locator bad_cast_rtti =
{ {
0, 0,
0, 0,
...@@ -799,12 +801,12 @@ static const cxx_type_info bad_cast_cxx_type_info = ...@@ -799,12 +801,12 @@ static const cxx_type_info bad_cast_cxx_type_info =
&bad_cast_type_info, &bad_cast_type_info,
{ 0, -1, 0 }, { 0, -1, 0 },
sizeof(exception), sizeof(exception),
(cxx_copy_ctor)__thiscall_MSVCRT_bad_cast_copy_ctor (cxx_copy_ctor)THISCALL(MSVCRT_bad_cast_copy_ctor)
}; };
static type_info __non_rtti_object_type_info = static const type_info __non_rtti_object_type_info =
{ {
(void*)&MSVCRT_type_info_vtable, &MSVCRT_type_info_vtable,
NULL, NULL,
".?AV__non_rtti_object@@" ".?AV__non_rtti_object@@"
}; };
...@@ -834,7 +836,7 @@ static const rtti_object_hierarchy __non_rtti_object_type_hierarchy = ...@@ -834,7 +836,7 @@ static const rtti_object_hierarchy __non_rtti_object_type_hierarchy =
&__non_rtti_object_rtti_base_array &__non_rtti_object_rtti_base_array
}; };
static const rtti_object_locator __non_rtti_object_rtti = const rtti_object_locator __non_rtti_object_rtti =
{ {
0, 0,
0, 0,
...@@ -849,12 +851,12 @@ static const cxx_type_info __non_rtti_object_cxx_type_info = ...@@ -849,12 +851,12 @@ static const cxx_type_info __non_rtti_object_cxx_type_info =
&__non_rtti_object_type_info, &__non_rtti_object_type_info,
{ 0, -1, 0 }, { 0, -1, 0 },
sizeof(exception), sizeof(exception),
(cxx_copy_ctor)__thiscall_MSVCRT___non_rtti_object_copy_ctor (cxx_copy_ctor)THISCALL(MSVCRT___non_rtti_object_copy_ctor)
}; };
static type_info type_info_type_info = static const type_info type_info_type_info =
{ {
(void*)&MSVCRT_type_info_vtable, &MSVCRT_type_info_vtable,
NULL, NULL,
".?AVtype_info@@" ".?AVtype_info@@"
}; };
...@@ -884,7 +886,7 @@ static const rtti_object_hierarchy type_info_type_hierarchy = ...@@ -884,7 +886,7 @@ static const rtti_object_hierarchy type_info_type_hierarchy =
&type_info_rtti_base_array &type_info_rtti_base_array
}; };
static const rtti_object_locator type_info_rtti = const rtti_object_locator type_info_rtti =
{ {
0, 0,
0, 0,
...@@ -909,7 +911,7 @@ static const cxx_type_info_table bad_cast_type_info_table = ...@@ -909,7 +911,7 @@ static const cxx_type_info_table bad_cast_type_info_table =
static const cxx_exception_type bad_cast_exception_type = static const cxx_exception_type bad_cast_exception_type =
{ {
0, 0,
(void*)__thiscall_MSVCRT_bad_cast_dtor, (void*)THISCALL(MSVCRT_bad_cast_dtor),
NULL, NULL,
&bad_cast_type_info_table &bad_cast_type_info_table
}; };
...@@ -927,7 +929,7 @@ static const cxx_type_info_table bad_typeid_type_info_table = ...@@ -927,7 +929,7 @@ static const cxx_type_info_table bad_typeid_type_info_table =
static const cxx_exception_type bad_typeid_exception_type = static const cxx_exception_type bad_typeid_exception_type =
{ {
0, 0,
(void*)__thiscall_MSVCRT_bad_typeid_dtor, (void*)THISCALL(MSVCRT_bad_typeid_dtor),
NULL, NULL,
&bad_cast_type_info_table &bad_cast_type_info_table
}; };
...@@ -935,13 +937,11 @@ static const cxx_exception_type bad_typeid_exception_type = ...@@ -935,13 +937,11 @@ static const cxx_exception_type bad_typeid_exception_type =
static const cxx_exception_type __non_rtti_object_exception_type = static const cxx_exception_type __non_rtti_object_exception_type =
{ {
0, 0,
(void*)__thiscall_MSVCRT___non_rtti_object_dtor, (void*)THISCALL(MSVCRT___non_rtti_object_dtor),
NULL, NULL,
&bad_typeid_type_info_table &bad_typeid_type_info_table
}; };
#endif /* __i386__ */
/****************************************************************** /******************************************************************
* ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@) * ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
...@@ -1025,52 +1025,6 @@ void MSVCRT_unexpected(void) ...@@ -1025,52 +1025,6 @@ void MSVCRT_unexpected(void)
MSVCRT_terminate(); MSVCRT_terminate();
} }
/* Get type info from an object (internal) */
static const rtti_object_locator* RTTI_GetObjectLocator(type_info *cppobj)
{
const rtti_object_locator *obj_locator = NULL;
#ifdef __i386__
const exception_vtable* vtable = (const exception_vtable*)cppobj->vtable;
/* Perhaps this is one of classes we export? */
if (vtable == &MSVCRT_exception_vtable)
{
TRACE("returning exception_rtti\n");
return &exception_rtti;
}
else if (vtable == &MSVCRT_bad_typeid_vtable)
{
TRACE("returning bad_typeid_rtti\n");
return &bad_typeid_rtti;
}
else if (vtable == &MSVCRT_bad_cast_vtable)
{
TRACE("returning bad_cast_rtti\n");
return &bad_cast_rtti;
}
else if (vtable == &MSVCRT___non_rtti_object_vtable)
{
TRACE("returning __non_rtti_object_rtti\n");
return &__non_rtti_object_rtti;
}
else if (vtable == &MSVCRT_type_info_vtable)
{
TRACE("returning type_info_rtti\n");
return &type_info_rtti;
}
#endif
if (!IsBadReadPtr(cppobj, sizeof(void *)) &&
!IsBadReadPtr(cppobj->vtable - 1,sizeof(void *)) &&
!IsBadReadPtr((void*)cppobj->vtable[-1], sizeof(rtti_object_locator)))
{
obj_locator = (rtti_object_locator *)cppobj->vtable[-1];
TRACE("returning type_info from vtable (%p)\n", obj_locator);
}
return obj_locator;
}
/****************************************************************** /******************************************************************
* __RTtypeid (MSVCRT.@) * __RTtypeid (MSVCRT.@)
...@@ -1090,39 +1044,32 @@ static const rtti_object_locator* RTTI_GetObjectLocator(type_info *cppobj) ...@@ -1090,39 +1044,32 @@ static const rtti_object_locator* RTTI_GetObjectLocator(type_info *cppobj)
* 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.
*/ */
type_info* MSVCRT___RTtypeid(type_info *cppobj) const type_info* MSVCRT___RTtypeid(void *cppobj)
{ {
const rtti_object_locator *obj_locator = RTTI_GetObjectLocator(cppobj); const type_info *ret;
#ifdef __i386__
if (!obj_locator)
{
static const char* szNullPtr = "Attempted a typeid of NULL pointer!";
static const char* szBadPtr = "Bad read pointer - no RTTI data!";
const cxx_exception_type *e_type;
exception e;
/* Throw a bad_typeid or __non_rtti_object exception */
if (!cppobj) if (!cppobj)
{ {
EXCEPTION_ctor(&e, &szNullPtr); bad_typeid e;
e.vtable = &MSVCRT_bad_typeid_vtable; MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
e_type = &bad_typeid_exception_type; _CxxThrowException( &e, &bad_typeid_exception_type );
return NULL;
} }
else
__TRY
{ {
EXCEPTION_ctor(&e, &szBadPtr); const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
e.vtable = &MSVCRT___non_rtti_object_vtable; ret = obj_locator->type_descriptor;
e_type = &__non_rtti_object_exception_type;
} }
__EXCEPT(page_fault)
_CxxThrowException(&e, e_type); {
DebugBreak(); __non_rtti_object e;
} MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
return obj_locator->type_descriptor; _CxxThrowException( &e, &bad_typeid_exception_type );
#else return NULL;
return NULL; }
#endif __ENDTRY
return ret;
} }
/****************************************************************** /******************************************************************
...@@ -1147,70 +1094,67 @@ type_info* MSVCRT___RTtypeid(type_info *cppobj) ...@@ -1147,70 +1094,67 @@ type_info* MSVCRT___RTtypeid(type_info *cppobj)
* 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.
*/ */
void* MSVCRT___RTDynamicCast(type_info *cppobj, int unknown, void* MSVCRT___RTDynamicCast(void *cppobj, int unknown,
type_info *src, type_info *dst, type_info *src, type_info *dst,
int do_throw) int do_throw)
{ {
const rtti_object_locator *obj_locator; void *ret;
/* Note: cppobj _isn't_ a type_info, we use that struct for its vtable ptr */
TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
if (!cppobj)
return 0;
obj_locator= RTTI_GetObjectLocator(cppobj);
if (unknown)
FIXME("Unknown parameter is non-zero: please report\n");
if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
/* To cast an object at runtime:
* 1.Find out the true type of the object from the typeinfo at vtable[-1]
* 2.Search for the destination type in the class hierarchy
* 3.If destination type is found, return base object address + dest offset
* Otherwise, fail the cast
*/
if (obj_locator)
{
int count = 0;
const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
const rtti_base_descriptor **base_desc = obj_bases->base_classes->bases;
int src_offset = obj_locator->base_class_offset, dst_offset = -1;
while (count < obj_bases->array_len) if (!cppobj) return NULL;
{
const type_info *typ = (*base_desc)->type_descriptor;
if (!strcmp(typ->mangled, dst->mangled)) TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
{ cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
/* compute the correct this pointer for that base class */
void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
return get_this_pointer( &(*base_desc)->offsets, this_ptr );
}
base_desc++;
count++;
}
if (dst_offset >= 0)
return (void*)((unsigned long)cppobj - src_offset + dst_offset);
}
#ifdef __i386__ if (unknown) FIXME("Unknown parameter is non-zero: please report\n");
/* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
* to a reference, since references cannot be NULL. /* To cast an object at runtime:
*/ * 1.Find out the true type of the object from the typeinfo at vtable[-1]
if (do_throw) * 2.Search for the destination type in the class hierarchy
{ * 3.If destination type is found, return base object address + dest offset
static const char* exception_text = "Bad dynamic_cast!"; * Otherwise, fail the cast
exception e; */
__TRY
/* Throw a bad_cast exception */ {
EXCEPTION_ctor(&e, &exception_text); int i;
e.vtable = &MSVCRT_bad_cast_vtable; const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
_CxxThrowException(&e, &bad_cast_exception_type); const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
DebugBreak(); const rtti_base_descriptor **base_desc = obj_bases->base_classes->bases;
}
#endif if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
return NULL;
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))
{
/* compute the correct this pointer for that base class */
void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
ret = get_this_pointer( &base_desc[i]->offsets, this_ptr );
break;
}
}
/* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
* to a reference, since references cannot be NULL.
*/
if (!ret && do_throw)
{
const char *msg = "Bad dynamic_cast!";
bad_cast e;
MSVCRT_bad_cast_ctor( &e, &msg );
_CxxThrowException( &e, &bad_cast_exception_type );
}
}
__EXCEPT(page_fault)
{
__non_rtti_object e;
MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
_CxxThrowException( &e, &bad_typeid_exception_type );
return NULL;
}
__ENDTRY
return ret;
} }
...@@ -1230,15 +1174,24 @@ void* MSVCRT___RTDynamicCast(type_info *cppobj, int unknown, ...@@ -1230,15 +1174,24 @@ void* MSVCRT___RTDynamicCast(type_info *cppobj, int unknown,
* 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.
*/ */
void* MSVCRT___RTCastToVoid(type_info *cppobj) void* MSVCRT___RTCastToVoid(void *cppobj)
{ {
const rtti_object_locator *obj_locator = RTTI_GetObjectLocator(cppobj); void *ret;
/* Note: cppobj _isn't_ a type_info, we use that struct for its vtable ptr */ if (!cppobj) return NULL;
TRACE("(%p)\n", cppobj);
/* Casts to void* simply cast to the base object */ __TRY
if (obj_locator) {
return (void*)((unsigned long)cppobj - obj_locator->base_class_offset); const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
return NULL; ret = (char *)cppobj - obj_locator->base_class_offset;
}
__EXCEPT(page_fault)
{
__non_rtti_object e;
MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
_CxxThrowException( &e, &bad_typeid_exception_type );
return NULL;
}
__ENDTRY
return ret;
} }
...@@ -379,7 +379,7 @@ DEFINE_REGS_ENTRYPOINT( __CxxFrameHandler, MSVCRT__CxxFrameHandler, 16, 0 ); ...@@ -379,7 +379,7 @@ DEFINE_REGS_ENTRYPOINT( __CxxFrameHandler, MSVCRT__CxxFrameHandler, 16, 0 );
/********************************************************************* /*********************************************************************
* _CxxThrowException (MSVCRT.@) * _CxxThrowException (MSVCRT.@)
*/ */
void _CxxThrowException( void *object, const cxx_exception_type *type ) void _CxxThrowException( exception *object, const cxx_exception_type *type )
{ {
DWORD args[3]; DWORD args[3];
......
...@@ -29,11 +29,19 @@ typedef void (*vtable_ptr)(); ...@@ -29,11 +29,19 @@ typedef void (*vtable_ptr)();
/* type_info object, see cpp.c for inplementation */ /* type_info object, see cpp.c for inplementation */
typedef struct __type_info typedef struct __type_info
{ {
vtable_ptr *vtable; const vtable_ptr *vtable;
char *name; /* Unmangled name, allocated lazily */ char *name; /* Unmangled name, allocated lazily */
char mangled[32]; /* Variable length, but we declare it large enough for static RTTI */ char mangled[32]; /* Variable length, but we declare it large enough for static RTTI */
} type_info; } type_info;
/* exception object */
typedef struct __exception
{
const vtable_ptr *vtable;
char *name; /* Name of this exception, always a new copy for each object */
int do_free; /* Whether to free 'name' in our dtor */
} exception;
/* the exception frame used by CxxFrameHandler */ /* the exception frame used by CxxFrameHandler */
typedef struct __cxx_exception_frame typedef struct __cxx_exception_frame
{ {
...@@ -96,7 +104,7 @@ typedef struct ...@@ -96,7 +104,7 @@ typedef struct
typedef struct __cxx_type_info typedef struct __cxx_type_info
{ {
UINT flags; /* flags (see CLASS_* flags below) */ UINT flags; /* flags (see CLASS_* flags below) */
type_info *type_info; /* C++ type info */ const type_info *type_info; /* C++ type info */
this_ptr_offsets offsets; /* offsets for computing the this pointer */ this_ptr_offsets offsets; /* offsets for computing the this pointer */
size_t size; /* object size */ size_t size; /* object size */
cxx_copy_ctor copy_ctor; /* copy constructor */ cxx_copy_ctor copy_ctor; /* copy constructor */
...@@ -125,7 +133,13 @@ typedef struct __cxx_exception_type ...@@ -125,7 +133,13 @@ typedef struct __cxx_exception_type
const cxx_type_info_table *type_info_table; /* list of types for this exception object */ const cxx_type_info_table *type_info_table; /* list of types for this exception object */
} cxx_exception_type; } cxx_exception_type;
void _CxxThrowException(void*,const cxx_exception_type*); void _CxxThrowException(exception*,const cxx_exception_type*);
/* get the vtable pointer for a C++ object */
static inline const vtable_ptr *get_vtable( void *obj )
{
return *(const vtable_ptr **)obj;
}
static inline const char *dbgstr_type_info( const type_info *info ) static inline const char *dbgstr_type_info( const type_info *info )
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment