msvcrt: Add __ExceptionPtr* functions implementation.

This commit is contained in:
Piotr Caban 2014-05-06 16:24:53 +02:00 committed by Alexandre Julliard
parent 1be4654842
commit 868e009e79
3 changed files with 240 additions and 20 deletions

View File

@ -412,18 +412,18 @@
@ stub -arch=win64 ?__ExceptionPtrAssign@@YAXPEAXPEBX@Z
@ stub -arch=win32 ?__ExceptionPtrCompare@@YA_NPBX0@Z
@ stub -arch=win64 ?__ExceptionPtrCompare@@YA_NPEBX0@Z
@ stub -arch=win32 ?__ExceptionPtrCopy@@YAXPAXPBX@Z
@ stub -arch=win64 ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z
@ cdecl -arch=win32 ?__ExceptionPtrCopy@@YAXPAXPBX@Z(ptr ptr) __ExceptionPtrCopy
@ cdecl -arch=win64 ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z(ptr ptr) __ExceptionPtrCopy
@ stub -arch=win32 ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z
@ stub -arch=win64 ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z
@ stub -arch=win32 ?__ExceptionPtrCreate@@YAXPAX@Z
@ stub -arch=win64 ?__ExceptionPtrCreate@@YAXPEAX@Z
@ stub -arch=win32 ?__ExceptionPtrCurrentException@@YAXPAX@Z
@ stub -arch=win64 ?__ExceptionPtrCurrentException@@YAXPEAX@Z
@ stub -arch=win32 ?__ExceptionPtrDestroy@@YAXPAX@Z
@ stub -arch=win64 ?__ExceptionPtrDestroy@@YAXPEAX@Z
@ stub -arch=win32 ?__ExceptionPtrRethrow@@YAXPBX@Z
@ stub -arch=win64 ?__ExceptionPtrRethrow@@YAXPEBX@Z
@ cdecl -arch=win32 ?__ExceptionPtrCreate@@YAXPAX@Z(ptr) __ExceptionPtrCreate
@ cdecl -arch=win64 ?__ExceptionPtrCreate@@YAXPEAX@Z(ptr) __ExceptionPtrCreate
@ cdecl -arch=win32 ?__ExceptionPtrCurrentException@@YAXPAX@Z(ptr) __ExceptionPtrCurrentException
@ cdecl -arch=win64 ?__ExceptionPtrCurrentException@@YAXPEAX@Z(ptr) __ExceptionPtrCurrentException
@ cdecl -arch=win32 ?__ExceptionPtrDestroy@@YAXPAX@Z(ptr) __ExceptionPtrDestroy
@ cdecl -arch=win64 ?__ExceptionPtrDestroy@@YAXPEAX@Z(ptr) __ExceptionPtrDestroy
@ cdecl -arch=win32 ?__ExceptionPtrRethrow@@YAXPBX@Z(ptr) __ExceptionPtrRethrow
@ cdecl -arch=win64 ?__ExceptionPtrRethrow@@YAXPEBX@Z(ptr) __ExceptionPtrRethrow
@ cdecl __uncaught_exception() MSVCRT___uncaught_exception
@ stub ?_inconsistency@@YAXXZ
@ cdecl -arch=win32 ?_invalid_parameter@@YAXPBG00II@Z(wstr wstr wstr long long) MSVCRT__invalid_parameter

View File

@ -690,18 +690,18 @@
@ stub -arch=win64 ?__ExceptionPtrAssign@@YAXPEAXPEBX@Z
@ stub -arch=win32 ?__ExceptionPtrCompare@@YA_NPBX0@Z
@ stub -arch=win64 ?__ExceptionPtrCompare@@YA_NPEBX0@Z
@ stub -arch=win32 ?__ExceptionPtrCopy@@YAXPAXPBX@Z
@ stub -arch=win64 ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z
@ cdecl -arch=win32 ?__ExceptionPtrCopy@@YAXPAXPBX@Z(ptr ptr) __ExceptionPtrCopy
@ cdecl -arch=win64 ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z(ptr ptr) __ExceptionPtrCopy
@ stub -arch=win32 ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z
@ stub -arch=win64 ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z
@ stub -arch=win32 ?__ExceptionPtrCreate@@YAXPAX@Z
@ stub -arch=win64 ?__ExceptionPtrCreate@@YAXPEAX@Z
@ stub -arch=win32 ?__ExceptionPtrCurrentException@@YAXPAX@Z
@ stub -arch=win64 ?__ExceptionPtrCurrentException@@YAXPEAX@Z
@ stub -arch=win32 ?__ExceptionPtrDestroy@@YAXPAX@Z
@ stub -arch=win64 ?__ExceptionPtrDestroy@@YAXPEAX@Z
@ stub -arch=win32 ?__ExceptionPtrRethrow@@YAXPBX@Z
@ stub -arch=win64 ?__ExceptionPtrRethrow@@YAXPEBX@Z
@ cdecl -arch=win32 ?__ExceptionPtrCreate@@YAXPAX@Z(ptr) __ExceptionPtrCreate
@ cdecl -arch=win64 ?__ExceptionPtrCreate@@YAXPEAX@Z(ptr) __ExceptionPtrCreate
@ cdecl -arch=win32 ?__ExceptionPtrCurrentException@@YAXPAX@Z(ptr) __ExceptionPtrCurrentException
@ cdecl -arch=win64 ?__ExceptionPtrCurrentException@@YAXPEAX@Z(ptr) __ExceptionPtrCurrentException
@ cdecl -arch=win32 ?__ExceptionPtrDestroy@@YAXPAX@Z(ptr) __ExceptionPtrDestroy
@ cdecl -arch=win64 ?__ExceptionPtrDestroy@@YAXPEAX@Z(ptr) __ExceptionPtrDestroy
@ cdecl -arch=win32 ?__ExceptionPtrRethrow@@YAXPBX@Z(ptr) __ExceptionPtrRethrow
@ cdecl -arch=win64 ?__ExceptionPtrRethrow@@YAXPEBX@Z(ptr) __ExceptionPtrRethrow
@ stub -arch=win32 ?__ExceptionPtrSwap@@YAXPAX0@Z
@ stub -arch=win64 ?__ExceptionPtrSwap@@YAXPEAX0@Z
@ stub -arch=win32 ?__ExceptionPtrToBool@@YA_NPBX@Z

View File

@ -1211,3 +1211,223 @@ const char * __thiscall type_info_name_internal_method(type_info * _this, struct
return MSVCRT_type_info_name(_this);
}
/* std::exception_ptr class helpers */
typedef struct
{
EXCEPTION_RECORD *rec;
int *ref; /* not binary compatible with native msvcr100 */
} exception_ptr;
/*********************************************************************
* ?__ExceptionPtrCreate@@YAXPAX@Z
* ?__ExceptionPtrCreate@@YAXPEAX@Z
*/
void __cdecl __ExceptionPtrCreate(exception_ptr *ep)
{
TRACE("(%p)\n", ep);
ep->rec = NULL;
ep->ref = NULL;
}
#ifdef __i386__
static inline void call_dtor(const cxx_exception_type *type, void *func, void *object)
{
__asm__ __volatile__("call *%0" : : "m" (func), "c" (object) : "eax", "edx", "memory");
}
#elif __x86_64__
static inline void call_dtor(const cxx_exception_type *type, unsigned int dtor, void *object)
{
char *base = RtlPcToFileHeader((void*)type, (void**)&base);
void (__cdecl *func)(void*) = (void*)(base + dtor);
func(object);
}
#else
#define call_dtor(type, func, object) ((void (__cdecl*)(void*))(func))(object)
#endif
/*********************************************************************
* ?__ExceptionPtrDestroy@@YAXPAX@Z
* ?__ExceptionPtrDestroy@@YAXPEAX@Z
*/
void __cdecl __ExceptionPtrDestroy(exception_ptr *ep)
{
TRACE("(%p)\n", ep);
if (!ep->rec)
return;
if (!InterlockedDecrement(ep->ref))
{
if (ep->rec->ExceptionCode == CXX_EXCEPTION)
{
const cxx_exception_type *type = (void*)ep->rec->ExceptionInformation[2];
void *obj = (void*)ep->rec->ExceptionInformation[1];
if (type && type->destructor) call_dtor(type, type->destructor, obj);
HeapFree(GetProcessHeap(), 0, obj);
}
HeapFree(GetProcessHeap(), 0, ep->rec);
HeapFree(GetProcessHeap(), 0, ep->ref);
}
}
/*********************************************************************
* ?__ExceptionPtrCopy@@YAXPAXPBX@Z
* ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z
*/
void __cdecl __ExceptionPtrCopy(exception_ptr *ep, const exception_ptr *copy)
{
TRACE("(%p %p)\n", ep, copy);
/* don't destroy object stored in ep */
*ep = *copy;
if (ep->ref)
InterlockedIncrement(copy->ref);
}
/*********************************************************************
* ?__ExceptionPtrRethrow@@YAXPBX@Z
* ?__ExceptionPtrRethrow@@YAXPEBX@Z
*/
void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep)
{
TRACE("(%p)\n", ep);
if (!ep->rec)
{
static const char *exception_msg = "bad exception";
exception e;
MSVCRT_exception_ctor(&e, &exception_msg);
_CxxThrowException(&e, &exception_exception_type);
return;
}
RaiseException(ep->rec->ExceptionCode, ep->rec->ExceptionFlags & (~EH_UNWINDING),
ep->rec->NumberParameters, ep->rec->ExceptionInformation);
}
#ifdef __i386__
static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
{
TRACE( "calling copy ctor %p object %p src %p\n", func, this, src );
if (has_vbase)
/* in that case copy ctor takes an extra bool indicating whether to copy the base class */
__asm__ __volatile__("pushl $1; pushl %2; call *%0"
: : "m" (func), "c" (this), "m" (src) : "eax", "edx", "memory" );
else
__asm__ __volatile__("pushl %2; call *%0"
: : "m" (func), "c" (this), "m" (src) : "eax", "edx", "memory" );
}
#else
static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
{
TRACE( "calling copy ctor %p object %p src %p\n", func, this, src );
if (has_vbase)
((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1);
else
((void (__cdecl*)(void*, void*))func)(this, src);
}
#endif
/*********************************************************************
* ?__ExceptionPtrCurrentException@@YAXPAX@Z
* ?__ExceptionPtrCurrentException@@YAXPEAX@Z
*/
#ifndef __x86_64__
void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
{
EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record;
TRACE("(%p)\n", ep);
if (!rec)
{
ep->rec = NULL;
ep->ref = NULL;
return;
}
ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
*ep->rec = *rec;
*ep->ref = 1;
if (ep->rec->ExceptionCode == CXX_EXCEPTION)
{
const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
const cxx_type_info *ti;
void **data, *obj;
ti = et->type_info_table->info[0];
data = HeapAlloc(GetProcessHeap(), 0, ti->size);
obj = (void*)ep->rec->ExceptionInformation[1];
if (ti->flags & CLASS_IS_SIMPLE_TYPE)
{
memcpy(data, obj, ti->size);
if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
}
else if (ti->copy_ctor)
{
call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj),
ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
}
else
memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
}
return;
}
#else
void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
{
EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record;
TRACE("(%p)\n", ep);
if (!rec)
{
ep->rec = NULL;
ep->ref = NULL;
return;
}
ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
*ep->rec = *rec;
*ep->ref = 1;
if (ep->rec->ExceptionCode == CXX_EXCEPTION)
{
const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
const cxx_type_info *ti;
void **data, *obj;
char *base = RtlPcToFileHeader((void*)et, (void**)&base);
ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + et->type_info_table))->info[0]);
data = HeapAlloc(GetProcessHeap(), 0, ti->size);
obj = (void*)ep->rec->ExceptionInformation[1];
if (ti->flags & CLASS_IS_SIMPLE_TYPE)
{
memcpy(data, obj, ti->size);
if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
}
else if (ti->copy_ctor)
{
call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj),
ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
}
else
memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
}
return;
}
#endif