241 lines
8.6 KiB
C
241 lines
8.6 KiB
C
/***
|
|
*chkesp.c
|
|
*
|
|
* Copyright (c) 1997-2001, Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose:
|
|
* Defines _chkesp() and other run-time error checking support routines.
|
|
*
|
|
*Revision History:
|
|
* 05-22-98 JWM Support added for KFrei's RTC work; header added.
|
|
* 07-28-98 JWM RTC update.
|
|
* 10-30-98 KBF Quit messing with the CRT's Debug Heap flags
|
|
* 11-19-98 KBF Added stuff to handle multiple callbacks
|
|
* 11-24-98 KBF Added 3rd callback for memory/string function checks
|
|
* 12-03-98 KBF Added 4th callback to disable mem/string function
|
|
* checks temporarily
|
|
* 05-11-99 KBF Wrap RTC support in #ifdef.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include <malloc.h>
|
|
#include <dbgint.h>
|
|
#include <windows.h>
|
|
#include <rtcsup.h>
|
|
|
|
/***
|
|
*void __chkesp() - check to make sure esp was properly restored
|
|
*
|
|
*Purpose:
|
|
* A debugging check called after every function call to make sure esp has
|
|
* the same value before and after the call.
|
|
*
|
|
*Entry:
|
|
* condition code: the ZF flag should be cleared if esp has changed
|
|
*
|
|
*Return:
|
|
* <void>
|
|
*
|
|
*******************************************************************************/
|
|
void __declspec(naked) _chkesp() {
|
|
__asm {
|
|
jne esperror ;
|
|
ret
|
|
|
|
esperror:
|
|
; function prolog
|
|
|
|
push ebp
|
|
mov ebp, esp
|
|
sub esp, __LOCAL_SIZE
|
|
|
|
push eax ; save the old return value
|
|
push edx
|
|
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
}
|
|
|
|
/**
|
|
* let the user know that there is a problem, and allow them to debug the
|
|
* program.
|
|
*/
|
|
#ifdef _DEBUG
|
|
if (_CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, "",
|
|
"The value of ESP was not properly saved across a function "
|
|
"call. This is usually a result of calling a function "
|
|
"declared with one calling convention with a function "
|
|
"pointer declared with a different calling convention. " ) == 1)
|
|
#endif
|
|
{
|
|
|
|
/* start the debugger */
|
|
__asm int 3;
|
|
}
|
|
|
|
__asm {
|
|
; function epilog
|
|
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
|
|
pop edx ; restore the old return value
|
|
pop eax
|
|
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret
|
|
}
|
|
}
|
|
|
|
#ifdef _RTC
|
|
/***
|
|
*void __CRT_RTC_INIT() - Initialize the RTC subsystem (in section .CRT$XIC)
|
|
*
|
|
*Purpose:
|
|
* Setup anything involving the RTC subsystem
|
|
*
|
|
*Entry:
|
|
* The allocation hook - function to use to allocate memory
|
|
* The release hook - function to use to release memory
|
|
*
|
|
*Return:
|
|
* The default error reporting function
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#ifdef _RTC_ADVMEM
|
|
// This stuff is currently disabled
|
|
#define mk_list(type) \
|
|
typedef struct type##_l { \
|
|
int version; \
|
|
type##_hook_fp funcptr; \
|
|
} type##_l; \
|
|
static struct { \
|
|
int size; \
|
|
int max; \
|
|
type##_l *hooks; \
|
|
} type##_list = {0,0,0}; \
|
|
type##_hook_fp type##_hook = 0; \
|
|
static int type##_version = 0
|
|
|
|
mk_list(_RTC_Allocate);
|
|
mk_list(_RTC_Free);
|
|
mk_list(_RTC_MemCheck);
|
|
mk_list(_RTC_FuncCheckSet);
|
|
HANDLE _RTC_api_change_mutex = NULL;
|
|
|
|
#define add_func(type, vers, fp) { \
|
|
if (type##_version < vers) \
|
|
{ \
|
|
type##_version = vers; \
|
|
type##_hook = (type##_hook_fp)fp; \
|
|
} \
|
|
if (!type##_list.hooks) \
|
|
{ \
|
|
type##_list.hooks = (type##_l*) \
|
|
VirtualAlloc(0, 65536, MEM_RESERVE, PAGE_READWRITE); \
|
|
} \
|
|
if (type##_list.size == type##_list.max) \
|
|
{ \
|
|
type##_list.max += 4096/sizeof(type##_l); \
|
|
VirtualAlloc(type##_list.hooks, type##_list.max*sizeof(type##_l),\
|
|
MEM_COMMIT, PAGE_READWRITE); \
|
|
} \
|
|
type##_list.hooks[type##_list.size].funcptr = (type##_hook_fp)fp; \
|
|
type##_list.hooks[type##_list.size++].version = vers; \
|
|
}
|
|
|
|
#define del_func(type, fp) { \
|
|
int i; \
|
|
for (i = 0; i < type##_list.size; i++) \
|
|
{ \
|
|
if (type##_list.hooks[i].funcptr == fp) \
|
|
{ \
|
|
for (i++; i < type##_list.size; i++) \
|
|
{ \
|
|
type##_list.hooks[i-1].funcptr = type##_list.hooks[i].funcptr; \
|
|
type##_list.hooks[i-1].version = type##_list.hooks[i].version; \
|
|
} \
|
|
type##_list.size--; \
|
|
break; \
|
|
} \
|
|
} \
|
|
if (fp == (void*)type##_hook) \
|
|
{ \
|
|
int hiver = 0; \
|
|
type##_hook_fp candidate = 0; \
|
|
for (i = 0; i < type##_list.size; i++) \
|
|
{ \
|
|
if (type##_list.hooks[i].version > hiver) \
|
|
{ \
|
|
hiver = type##_list.hooks[i].version; \
|
|
candidate = type##_list.hooks[i].funcptr; \
|
|
} \
|
|
} \
|
|
type##_hook = candidate; \
|
|
type##_version = hiver; \
|
|
} \
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
funcs is a list of function pointers that are currently defined as:
|
|
funcs[0] = Allocation hook
|
|
funcs[1] = Free hook
|
|
funcs[2] = Memory Check hook
|
|
funcs[3] = Function Check enabler/disabler hook
|
|
*/
|
|
|
|
_RTC_error_fn __cdecl
|
|
_CRT_RTC_INIT(HANDLE mutex, void **funcs, int funccount, int version, int unloading)
|
|
{
|
|
#ifdef _RTC_ADVMEM
|
|
// This stuff is currently disabled
|
|
if (mutex && !_RTC_api_change_mutex)
|
|
_RTC_api_change_mutex = mutex;
|
|
if (funccount > 0)
|
|
{
|
|
if (!unloading)
|
|
{
|
|
switch (funccount)
|
|
{
|
|
default:
|
|
case 4:
|
|
add_func(_RTC_FuncCheckSet, version, funcs[3]);
|
|
case 3:
|
|
add_func(_RTC_MemCheck, version, funcs[2]);
|
|
case 2:
|
|
add_func(_RTC_Free, version, funcs[1]);
|
|
case 1:
|
|
add_func(_RTC_Allocate, version, funcs[0]);
|
|
}
|
|
} else {
|
|
switch (funccount)
|
|
{
|
|
default:
|
|
case 4:
|
|
del_func(_RTC_FuncCheckSet, funcs[3]);
|
|
case 3:
|
|
del_func(_RTC_MemCheck, funcs[2]);
|
|
case 2:
|
|
del_func(_RTC_Free, funcs[1]);
|
|
case 1:
|
|
del_func(_RTC_Allocate, funcs[0]);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
return &_CrtDbgReport;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
#endif
|