msvcrt/tests: Execute c++ related tests on 64-bit systems.

This commit is contained in:
Piotr Caban 2012-08-20 12:47:51 +02:00 committed by Alexandre Julliard
parent fef8a52fc9
commit 83024db0ae
1 changed files with 215 additions and 188 deletions

View File

@ -15,43 +15,34 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* NOTES
* This tests is only valid for ix86 platforms, on others it's a no-op.
* Some tests cannot be checked with ok(), for example the dtors. We simply
* call them to ensure we don't crash ;-)
*
* If we build this test with VC++ in debug mode, we will fail in _chkstk()
* or at program exit malloc() checking if these methods haven't been
* implemented correctly (they have).
*
* Tested with a range of native msvcrt's from v4 -> v7.
*/
#include "wine/test.h"
#include "winbase.h"
#include "winnt.h"
#ifndef __i386__
/* Skip these tests for non x86 platforms */
START_TEST(cpp)
{
}
#else
typedef void (*vtable_ptr)(void);
typedef struct __exception
{
void *vtable;
vtable_ptr *vtable;
char *name;
int do_free;
} exception;
typedef struct __type_info
{
void *vtable;
vtable_ptr *vtable;
char *name;
char mangled[16];
} type_info;
#undef __thiscall
#ifdef __i386__
#define __thiscall __stdcall
#else
#define __thiscall __cdecl
#endif
/* Function pointers. We need to use these to call these funcs as __thiscall */
static HMODULE hMsvcrt;
@ -61,56 +52,56 @@ static void* (__cdecl *pmalloc)(unsigned int);
static void (__cdecl *pfree)(void*);
/* exception */
static void (WINAPI *pexception_ctor)(exception*,LPCSTR*);
static void (WINAPI *pexception_copy_ctor)(exception*,exception*);
static void (WINAPI *pexception_default_ctor)(exception*);
static void (WINAPI *pexception_dtor)(exception*);
static exception* (WINAPI *pexception_opequals)(exception*,exception*);
static char* (WINAPI *pexception_what)(exception*);
static void* (WINAPI *pexception_vtable)(exception*);
static void (WINAPI *pexception_vector_dtor)(exception*,unsigned int);
static void (WINAPI *pexception_scalar_dtor)(exception*,unsigned int);
static void (__thiscall *pexception_ctor)(exception*,LPCSTR*);
static void (__thiscall *pexception_copy_ctor)(exception*,exception*);
static void (__thiscall *pexception_default_ctor)(exception*);
static void (__thiscall *pexception_dtor)(exception*);
static exception* (__thiscall *pexception_opequals)(exception*,exception*);
static char* (__thiscall *pexception_what)(exception*);
static vtable_ptr *pexception_vtable;
static void (__thiscall *pexception_vector_dtor)(exception*,unsigned int);
static void (__thiscall *pexception_scalar_dtor)(exception*,unsigned int);
/* bad_typeid */
static void (WINAPI *pbad_typeid_ctor)(exception*,LPCSTR);
static void (WINAPI *pbad_typeid_ctor_closure)(exception*);
static void (WINAPI *pbad_typeid_copy_ctor)(exception*,exception*);
static void (WINAPI *pbad_typeid_dtor)(exception*);
static exception* (WINAPI *pbad_typeid_opequals)(exception*,exception*);
static char* (WINAPI *pbad_typeid_what)(exception*);
static void* (WINAPI *pbad_typeid_vtable)(exception*);
static void (WINAPI *pbad_typeid_vector_dtor)(exception*,unsigned int);
static void (WINAPI *pbad_typeid_scalar_dtor)(exception*,unsigned int);
static void (__thiscall *pbad_typeid_ctor)(exception*,LPCSTR);
static void (__thiscall *pbad_typeid_ctor_closure)(exception*);
static void (__thiscall *pbad_typeid_copy_ctor)(exception*,exception*);
static void (__thiscall *pbad_typeid_dtor)(exception*);
static exception* (__thiscall *pbad_typeid_opequals)(exception*,exception*);
static char* (__thiscall *pbad_typeid_what)(exception*);
static vtable_ptr *pbad_typeid_vtable;
static void (__thiscall *pbad_typeid_vector_dtor)(exception*,unsigned int);
static void (__thiscall *pbad_typeid_scalar_dtor)(exception*,unsigned int);
/* bad_cast */
static void (WINAPI *pbad_cast_ctor)(exception*,LPCSTR*);
static void (WINAPI *pbad_cast_ctor2)(exception*,LPCSTR);
static void (WINAPI *pbad_cast_ctor_closure)(exception*);
static void (WINAPI *pbad_cast_copy_ctor)(exception*,exception*);
static void (WINAPI *pbad_cast_dtor)(exception*);
static exception* (WINAPI *pbad_cast_opequals)(exception*,exception*);
static char* (WINAPI *pbad_cast_what)(exception*);
static void* (WINAPI *pbad_cast_vtable)(exception*);
static void (WINAPI *pbad_cast_vector_dtor)(exception*,unsigned int);
static void (WINAPI *pbad_cast_scalar_dtor)(exception*,unsigned int);
static void (__thiscall *pbad_cast_ctor)(exception*,LPCSTR*);
static void (__thiscall *pbad_cast_ctor2)(exception*,LPCSTR);
static void (__thiscall *pbad_cast_ctor_closure)(exception*);
static void (__thiscall *pbad_cast_copy_ctor)(exception*,exception*);
static void (__thiscall *pbad_cast_dtor)(exception*);
static exception* (__thiscall *pbad_cast_opequals)(exception*,exception*);
static char* (__thiscall *pbad_cast_what)(exception*);
static vtable_ptr *pbad_cast_vtable;
static void (__thiscall *pbad_cast_vector_dtor)(exception*,unsigned int);
static void (__thiscall *pbad_cast_scalar_dtor)(exception*,unsigned int);
/* __non_rtti_object */
static void (WINAPI *p__non_rtti_object_ctor)(exception*,LPCSTR);
static void (WINAPI *p__non_rtti_object_copy_ctor)(exception*,exception*);
static void (WINAPI *p__non_rtti_object_dtor)(exception*);
static exception* (WINAPI *p__non_rtti_object_opequals)(exception*,exception*);
static char* (WINAPI *p__non_rtti_object_what)(exception*);
static void* (WINAPI *p__non_rtti_object_vtable)(exception*);
static void (WINAPI *p__non_rtti_object_vector_dtor)(exception*,unsigned int);
static void (WINAPI *p__non_rtti_object_scalar_dtor)(exception*,unsigned int);
static void (__thiscall *p__non_rtti_object_ctor)(exception*,LPCSTR);
static void (__thiscall *p__non_rtti_object_copy_ctor)(exception*,exception*);
static void (__thiscall *p__non_rtti_object_dtor)(exception*);
static exception* (__thiscall *p__non_rtti_object_opequals)(exception*,exception*);
static char* (__thiscall *p__non_rtti_object_what)(exception*);
static vtable_ptr *p__non_rtti_object_vtable;
static void (__thiscall *p__non_rtti_object_vector_dtor)(exception*,unsigned int);
static void (__thiscall *p__non_rtti_object_scalar_dtor)(exception*,unsigned int);
/* type_info */
static void (WINAPI *ptype_info_dtor)(type_info*);
static char* (WINAPI *ptype_info_raw_name)(type_info*);
static char* (WINAPI *ptype_info_name)(type_info*);
static int (WINAPI *ptype_info_before)(type_info*,type_info*);
static int (WINAPI *ptype_info_opequals_equals)(type_info*,type_info*);
static int (WINAPI *ptype_info_opnot_equals)(type_info*,type_info*);
static void (__thiscall *ptype_info_dtor)(type_info*);
static char* (__thiscall *ptype_info_raw_name)(type_info*);
static char* (__thiscall *ptype_info_name)(type_info*);
static int (__thiscall *ptype_info_before)(type_info*,type_info*);
static int (__thiscall *ptype_info_opequals_equals)(type_info*,type_info*);
static int (__thiscall *ptype_info_opnot_equals)(type_info*,type_info*);
/* RTTI */
static type_info* (__cdecl *p__RTtypeid)(void*);
@ -125,88 +116,130 @@ static char* (__cdecl *p__unDName)(char*,const char*,int,void*,void*,unsigned sh
static void* bAncientVersion;
/* Emulate a __thiscall */
#ifdef _MSC_VER
static inline void* do_call_func1(void *func, void *_this)
#ifdef __i386__
#include "pshpack1.h"
struct thiscall_thunk
{
volatile void* retval = 0;
__asm
{
push ecx
mov ecx, _this
call func
mov retval, eax
pop ecx
}
return (void*)retval;
BYTE pop_eax; /* popl %eax (ret addr) */
BYTE pop_edx; /* popl %edx (func) */
BYTE pop_ecx; /* popl %ecx (this) */
BYTE push_eax; /* pushl %eax */
WORD jmp_edx; /* jmp *%edx */
};
#include "poppack.h"
static void * (WINAPI *call_thiscall_func1)( void *func, void *this );
static void * (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
static void init_thiscall_thunk(void)
{
struct thiscall_thunk *thunk = VirtualAlloc( NULL, sizeof(*thunk),
MEM_COMMIT, PAGE_EXECUTE_READWRITE );
thunk->pop_eax = 0x58; /* popl %eax */
thunk->pop_edx = 0x5a; /* popl %edx */
thunk->pop_ecx = 0x59; /* popl %ecx */
thunk->push_eax = 0x50; /* pushl %eax */
thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
call_thiscall_func1 = (void *)thunk;
call_thiscall_func2 = (void *)thunk;
}
static inline void* do_call_func2(void *func, void *_this, const void* arg)
{
volatile void* retval = 0;
__asm
{
push ecx
push arg
mov ecx, _this
call func
mov retval, eax
pop ecx
}
return (void*)retval;
}
#define call_func1(func,_this) call_thiscall_func1(func,_this)
#define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)a)
#else
static void* do_call_func1(void *func, void *_this)
{
void *ret, *dummy;
__asm__ __volatile__ ("call *%2"
: "=a" (ret), "=c" (dummy)
: "g" (func), "1" (_this)
: "edx", "memory" );
return ret;
}
static void* do_call_func2(void *func, void *_this, const void* arg)
{
void *ret, *dummy;
__asm__ __volatile__ ("pushl %3\n\tcall *%2"
: "=a" (ret), "=c" (dummy)
: "r" (func), "r" (arg), "1" (_this)
: "edx", "memory" );
return ret;
}
#endif
#define call_func1(x,y) do_call_func1((void*)x,(void*)y)
#define call_func2(x,y,z) do_call_func2((void*)x,(void*)y,(const void*)z)
#define init_thiscall_thunk() do { } while(0)
#define call_func1(func,_this) func(_this)
#define call_func2(func,_this,a) func(_this,a)
#endif /* __i386__ */
/* Some exports are only available in later versions */
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
#define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
static void InitFunctionPtrs(void)
static BOOL InitFunctionPtrs(void)
{
hMsvcrt = GetModuleHandleA("msvcrt.dll");
if (!hMsvcrt)
hMsvcrt = GetModuleHandleA("msvcrtd.dll");
ok(hMsvcrt != 0, "GetModuleHandleA failed\n");
if (hMsvcrt)
if (!hMsvcrt)
{
if (sizeof(void *) > sizeof(int)) /* 64-bit has different names */
win_skip("Could not load msvcrt.dll");
return FALSE;
}
SET(pmalloc, "malloc");
SET(pfree, "free");
SET(pexception_vtable, "??_7exception@@6B@");
SET(pbad_typeid_vtable, "??_7bad_typeid@@6B@");
SET(pbad_cast_vtable, "??_7bad_cast@@6B@");
SET(p__non_rtti_object_vtable, "??_7__non_rtti_object@@6B@");
SET(p__RTtypeid, "__RTtypeid");
SET(p__RTCastToVoid, "__RTCastToVoid");
SET(p__RTDynamicCast, "__RTDynamicCast");
SET(p__unDName,"__unDName");
/* Extremely early versions export logic_error, and crash in RTTI */
SETNOFAIL(bAncientVersion, "??0logic_error@@QAE@ABQBD@Z");
if (sizeof(void *) > sizeof(int)) /* 64-bit initialization */
{
SETNOFAIL(poperator_new, "??_U@YAPEAX_K@Z");
SETNOFAIL(poperator_delete, "??_V@YAXPEAX@Z");
SET(pexception_ctor, "??0exception@@QEAA@AEBQEBD@Z");
SET(pexception_copy_ctor, "??0exception@@QEAA@AEBV0@@Z");
SET(pexception_default_ctor, "??0exception@@QEAA@XZ");
SET(pexception_dtor, "??1exception@@UEAA@XZ");
SET(pexception_opequals, "??4exception@@QEAAAEAV0@AEBV0@@Z");
SET(pexception_what, "?what@exception@@UEBAPEBDXZ");
pexception_vector_dtor = (void*)pexception_vtable[0];
pexception_scalar_dtor = (void*)pexception_vtable[0];
SET(pbad_typeid_ctor, "??0bad_typeid@@QEAA@PEBD@Z");
SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@@QEAAXXZ");
SET(pbad_typeid_copy_ctor, "??0bad_typeid@@QEAA@AEBV0@@Z");
SET(pbad_typeid_dtor, "??1bad_typeid@@UEAA@XZ");
SET(pbad_typeid_opequals, "??4bad_typeid@@QEAAAEAV0@AEBV0@@Z");
SET(pbad_typeid_what, "?what@exception@@UEBAPEBDXZ");
pbad_typeid_vector_dtor = (void*)pbad_typeid_vtable[0];
pbad_typeid_scalar_dtor = (void*)pbad_typeid_vtable[0];
SET(pbad_cast_ctor, "??0bad_cast@@QEAA@AEBQEBD@Z");
SET(pbad_cast_ctor2, "??0bad_cast@@QEAA@PEBD@Z");
SET(pbad_cast_ctor_closure, "??_Fbad_cast@@QEAAXXZ");
SET(pbad_cast_copy_ctor, "??0bad_cast@@QEAA@AEBV0@@Z");
SET(pbad_cast_dtor, "??1bad_cast@@UEAA@XZ");
SET(pbad_cast_opequals, "??4bad_cast@@QEAAAEAV0@AEBV0@@Z");
SET(pbad_cast_what, "?what@exception@@UEBAPEBDXZ");
pbad_cast_vector_dtor = (void*)pbad_cast_vtable[0];
pbad_cast_scalar_dtor = (void*)pbad_cast_vtable[0];
SET(p__non_rtti_object_ctor, "??0__non_rtti_object@@QEAA@PEBD@Z");
SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@@QEAA@AEBV0@@Z");
SET(p__non_rtti_object_dtor, "??1__non_rtti_object@@UEAA@XZ");
SET(p__non_rtti_object_opequals, "??4__non_rtti_object@@QEAAAEAV0@AEBV0@@Z");
SET(p__non_rtti_object_what, "?what@exception@@UEBAPEBDXZ");
p__non_rtti_object_vector_dtor = (void*)p__non_rtti_object_vtable[0];
p__non_rtti_object_scalar_dtor = (void*)p__non_rtti_object_vtable[0];
SET(ptype_info_dtor, "??1type_info@@UEAA@XZ");
SET(ptype_info_raw_name, "?raw_name@type_info@@QEBAPEBDXZ");
SET(ptype_info_name, "?name@type_info@@QEBAPEBDXZ");
SET(ptype_info_before, "?before@type_info@@QEBAHAEBV1@@Z");
SET(ptype_info_opequals_equals, "??8type_info@@QEBAHAEBV0@@Z");
SET(ptype_info_opnot_equals, "??9type_info@@QEBAHAEBV0@@Z");
}
else
{
SETNOFAIL(poperator_new, "??_U@YAPAXI@Z");
SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z");
}
SET(pmalloc, "malloc");
SET(pfree, "free");
if (!poperator_new)
poperator_new = pmalloc;
if (!poperator_delete)
poperator_delete = pfree;
SET(pexception_ctor, "??0exception@@QAE@ABQBD@Z");
SET(pexception_copy_ctor, "??0exception@@QAE@ABV0@@Z");
@ -214,7 +247,6 @@ static void InitFunctionPtrs(void)
SET(pexception_dtor, "??1exception@@UAE@XZ");
SET(pexception_opequals, "??4exception@@QAEAAV0@ABV0@@Z");
SET(pexception_what, "?what@exception@@UBEPBDXZ");
SET(pexception_vtable, "??_7exception@@6B@");
SET(pexception_vector_dtor, "??_Eexception@@UAEPAXI@Z");
SET(pexception_scalar_dtor, "??_Gexception@@UAEPAXI@Z");
@ -224,7 +256,6 @@ static void InitFunctionPtrs(void)
SET(pbad_typeid_dtor, "??1bad_typeid@@UAE@XZ");
SET(pbad_typeid_opequals, "??4bad_typeid@@QAEAAV0@ABV0@@Z");
SET(pbad_typeid_what, "?what@exception@@UBEPBDXZ");
SET(pbad_typeid_vtable, "??_7bad_typeid@@6B@");
SET(pbad_typeid_vector_dtor, "??_Ebad_typeid@@UAEPAXI@Z");
SET(pbad_typeid_scalar_dtor, "??_Gbad_typeid@@UAEPAXI@Z");
@ -237,7 +268,6 @@ static void InitFunctionPtrs(void)
SET(pbad_cast_dtor, "??1bad_cast@@UAE@XZ");
SET(pbad_cast_opequals, "??4bad_cast@@QAEAAV0@ABV0@@Z");
SET(pbad_cast_what, "?what@exception@@UBEPBDXZ");
SET(pbad_cast_vtable, "??_7bad_cast@@6B@");
SET(pbad_cast_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z");
SET(pbad_cast_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z");
@ -246,7 +276,6 @@ static void InitFunctionPtrs(void)
SET(p__non_rtti_object_dtor, "??1__non_rtti_object@@UAE@XZ");
SET(p__non_rtti_object_opequals, "??4__non_rtti_object@@QAEAAV0@ABV0@@Z");
SET(p__non_rtti_object_what, "?what@exception@@UBEPBDXZ");
SET(p__non_rtti_object_vtable, "??_7__non_rtti_object@@6B@");
SET(p__non_rtti_object_vector_dtor, "??_E__non_rtti_object@@UAEPAXI@Z");
SET(p__non_rtti_object_scalar_dtor, "??_G__non_rtti_object@@UAEPAXI@Z");
@ -256,16 +285,15 @@ static void InitFunctionPtrs(void)
SET(ptype_info_before, "?before@type_info@@QBEHABV1@@Z");
SET(ptype_info_opequals_equals, "??8type_info@@QBEHABV0@@Z");
SET(ptype_info_opnot_equals, "??9type_info@@QBEHABV0@@Z");
SET(p__RTtypeid, "__RTtypeid");
SET(p__RTCastToVoid, "__RTCastToVoid");
SET(p__RTDynamicCast, "__RTDynamicCast");
SET(p__unDName,"__unDName");
/* Extremely early versions export logic_error, and crash in RTTI */
SETNOFAIL(bAncientVersion, "??0logic_error@@QAE@ABQBD@Z");
}
if (!poperator_new)
poperator_new = pmalloc;
if (!poperator_delete)
poperator_delete = pfree;
init_thiscall_thunk();
return TRUE;
}
static void test_exception(void)
@ -346,14 +374,14 @@ static void test_exception(void)
call_func2(pexception_vector_dtor, pe, 1); /* Should delete pe as single element*/
}
pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
pe = poperator_new(sizeof(exception) * 4 + sizeof(size_t));
ok(pe != NULL, "new() failed\n");
if (pe)
{
/* vector dtor, multiple elements */
char name[] = "a constant";
*((int*)pe) = 3;
pe = (exception*)((int*)pe + 1);
*((size_t*)pe) = 3;
pe = (exception*)((size_t*)pe + 1);
call_func2(pexception_ctor, &pe[0], &e_name);
call_func2(pexception_ctor, &pe[1], &e_name);
call_func2(pexception_ctor, &pe[2], &e_name);
@ -471,13 +499,13 @@ static void test_bad_typeid(void)
call_func2(pbad_typeid_vector_dtor, pe, 1); /* Should delete pe as single element*/
}
pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
pe = poperator_new(sizeof(exception) * 4 + sizeof(size_t));
ok(pe != NULL, "new() failed\n");
if (pe)
{
/* vector dtor, multiple elements */
*((int*)pe) = 3;
pe = (exception*)((int*)pe + 1);
*((size_t*)pe) = 3;
pe = (exception*)((size_t*)pe + 1);
call_func2(pbad_typeid_ctor, &pe[0], e_name);
call_func2(pbad_typeid_ctor, &pe[1], e_name);
call_func2(pbad_typeid_ctor, &pe[2], e_name);
@ -599,13 +627,13 @@ static void test_bad_cast(void)
call_func2(pbad_cast_vector_dtor, pe, 1); /* Should delete pe as single element*/
}
pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
pe = poperator_new(sizeof(exception) * 4 + sizeof(size_t));
ok(pe != NULL, "new() failed\n");
if (pe)
{
/* vector dtor, multiple elements */
*((int*)pe) = 3;
pe = (exception*)((int*)pe + 1);
*((size_t*)pe) = 3;
pe = (exception*)((size_t*)pe + 1);
call_func2(pbad_cast_ctor, &pe[0], &e_name);
call_func2(pbad_cast_ctor, &pe[1], &e_name);
call_func2(pbad_cast_ctor, &pe[2], &e_name);
@ -701,13 +729,13 @@ static void test___non_rtti_object(void)
call_func2(p__non_rtti_object_vector_dtor, pe, 1); /* Should delete pe as single element*/
}
pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
pe = poperator_new(sizeof(exception) * 4 + sizeof(size_t));
ok(pe != NULL, "new() failed\n");
if (pe)
{
/* vector dtor, multiple elements */
*((int*)pe) = 3;
pe = (exception*)((int*)pe + 1);
*((size_t*)pe) = 3;
pe = (exception*)((size_t*)pe + 1);
call_func2(p__non_rtti_object_ctor, &pe[0], e_name);
call_func2(p__non_rtti_object_ctor, &pe[1], e_name);
call_func2(p__non_rtti_object_ctor, &pe[2], e_name);
@ -733,7 +761,6 @@ static void test___non_rtti_object(void)
call_func2(p__non_rtti_object_vector_dtor, &e, 0); /* Should delete e.name, but not e */
}
static void test_type_info(void)
{
static type_info t1 = { NULL, NULL,{'.','?','A','V','t','e','s','t','1','@','@',0,0,0,0,0 } };
@ -1081,7 +1108,8 @@ static void test_demangle(void)
START_TEST(cpp)
{
InitFunctionPtrs();
if (!InitFunctionPtrs())
return;
test_exception();
test_bad_typeid();
@ -1092,4 +1120,3 @@ START_TEST(cpp)
test_demangle_datatype();
test_demangle();
}
#endif /* __i386__ */