Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
8.6 KiB

  1. /***
  2. *chkesp.c
  3. *
  4. * Copyright (c) 1997-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Defines _chkesp() and other run-time error checking support routines.
  8. *
  9. *Revision History:
  10. * 05-22-98 JWM Support added for KFrei's RTC work; header added.
  11. * 07-28-98 JWM RTC update.
  12. * 10-30-98 KBF Quit messing with the CRT's Debug Heap flags
  13. * 11-19-98 KBF Added stuff to handle multiple callbacks
  14. * 11-24-98 KBF Added 3rd callback for memory/string function checks
  15. * 12-03-98 KBF Added 4th callback to disable mem/string function
  16. * checks temporarily
  17. * 05-11-99 KBF Wrap RTC support in #ifdef.
  18. *
  19. *******************************************************************************/
  20. #include <malloc.h>
  21. #include <dbgint.h>
  22. #include <windows.h>
  23. #include <rtcsup.h>
  24. /***
  25. *void __chkesp() - check to make sure esp was properly restored
  26. *
  27. *Purpose:
  28. * A debugging check called after every function call to make sure esp has
  29. * the same value before and after the call.
  30. *
  31. *Entry:
  32. * condition code: the ZF flag should be cleared if esp has changed
  33. *
  34. *Return:
  35. * <void>
  36. *
  37. *******************************************************************************/
  38. void __declspec(naked) _chkesp() {
  39. __asm {
  40. jne esperror ;
  41. ret
  42. esperror:
  43. ; function prolog
  44. push ebp
  45. mov ebp, esp
  46. sub esp, __LOCAL_SIZE
  47. push eax ; save the old return value
  48. push edx
  49. push ebx
  50. push esi
  51. push edi
  52. }
  53. /**
  54. * let the user know that there is a problem, and allow them to debug the
  55. * program.
  56. */
  57. #ifdef _DEBUG
  58. if (_CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, "",
  59. "The value of ESP was not properly saved across a function "
  60. "call. This is usually a result of calling a function "
  61. "declared with one calling convention with a function "
  62. "pointer declared with a different calling convention. " ) == 1)
  63. #endif
  64. {
  65. /* start the debugger */
  66. __asm int 3;
  67. }
  68. __asm {
  69. ; function epilog
  70. pop edi
  71. pop esi
  72. pop ebx
  73. pop edx ; restore the old return value
  74. pop eax
  75. mov esp, ebp
  76. pop ebp
  77. ret
  78. }
  79. }
  80. #ifdef _RTC
  81. /***
  82. *void __CRT_RTC_INIT() - Initialize the RTC subsystem (in section .CRT$XIC)
  83. *
  84. *Purpose:
  85. * Setup anything involving the RTC subsystem
  86. *
  87. *Entry:
  88. * The allocation hook - function to use to allocate memory
  89. * The release hook - function to use to release memory
  90. *
  91. *Return:
  92. * The default error reporting function
  93. *
  94. *******************************************************************************/
  95. #ifdef _RTC_ADVMEM
  96. // This stuff is currently disabled
  97. #define mk_list(type) \
  98. typedef struct type##_l { \
  99. int version; \
  100. type##_hook_fp funcptr; \
  101. } type##_l; \
  102. static struct { \
  103. int size; \
  104. int max; \
  105. type##_l *hooks; \
  106. } type##_list = {0,0,0}; \
  107. type##_hook_fp type##_hook = 0; \
  108. static int type##_version = 0
  109. mk_list(_RTC_Allocate);
  110. mk_list(_RTC_Free);
  111. mk_list(_RTC_MemCheck);
  112. mk_list(_RTC_FuncCheckSet);
  113. HANDLE _RTC_api_change_mutex = NULL;
  114. #define add_func(type, vers, fp) { \
  115. if (type##_version < vers) \
  116. { \
  117. type##_version = vers; \
  118. type##_hook = (type##_hook_fp)fp; \
  119. } \
  120. if (!type##_list.hooks) \
  121. { \
  122. type##_list.hooks = (type##_l*) \
  123. VirtualAlloc(0, 65536, MEM_RESERVE, PAGE_READWRITE); \
  124. } \
  125. if (type##_list.size == type##_list.max) \
  126. { \
  127. type##_list.max += 4096/sizeof(type##_l); \
  128. VirtualAlloc(type##_list.hooks, type##_list.max*sizeof(type##_l),\
  129. MEM_COMMIT, PAGE_READWRITE); \
  130. } \
  131. type##_list.hooks[type##_list.size].funcptr = (type##_hook_fp)fp; \
  132. type##_list.hooks[type##_list.size++].version = vers; \
  133. }
  134. #define del_func(type, fp) { \
  135. int i; \
  136. for (i = 0; i < type##_list.size; i++) \
  137. { \
  138. if (type##_list.hooks[i].funcptr == fp) \
  139. { \
  140. for (i++; i < type##_list.size; i++) \
  141. { \
  142. type##_list.hooks[i-1].funcptr = type##_list.hooks[i].funcptr; \
  143. type##_list.hooks[i-1].version = type##_list.hooks[i].version; \
  144. } \
  145. type##_list.size--; \
  146. break; \
  147. } \
  148. } \
  149. if (fp == (void*)type##_hook) \
  150. { \
  151. int hiver = 0; \
  152. type##_hook_fp candidate = 0; \
  153. for (i = 0; i < type##_list.size; i++) \
  154. { \
  155. if (type##_list.hooks[i].version > hiver) \
  156. { \
  157. hiver = type##_list.hooks[i].version; \
  158. candidate = type##_list.hooks[i].funcptr; \
  159. } \
  160. } \
  161. type##_hook = candidate; \
  162. type##_version = hiver; \
  163. } \
  164. }
  165. #endif
  166. /*
  167. funcs is a list of function pointers that are currently defined as:
  168. funcs[0] = Allocation hook
  169. funcs[1] = Free hook
  170. funcs[2] = Memory Check hook
  171. funcs[3] = Function Check enabler/disabler hook
  172. */
  173. _RTC_error_fn __cdecl
  174. _CRT_RTC_INIT(HANDLE mutex, void **funcs, int funccount, int version, int unloading)
  175. {
  176. #ifdef _RTC_ADVMEM
  177. // This stuff is currently disabled
  178. if (mutex && !_RTC_api_change_mutex)
  179. _RTC_api_change_mutex = mutex;
  180. if (funccount > 0)
  181. {
  182. if (!unloading)
  183. {
  184. switch (funccount)
  185. {
  186. default:
  187. case 4:
  188. add_func(_RTC_FuncCheckSet, version, funcs[3]);
  189. case 3:
  190. add_func(_RTC_MemCheck, version, funcs[2]);
  191. case 2:
  192. add_func(_RTC_Free, version, funcs[1]);
  193. case 1:
  194. add_func(_RTC_Allocate, version, funcs[0]);
  195. }
  196. } else {
  197. switch (funccount)
  198. {
  199. default:
  200. case 4:
  201. del_func(_RTC_FuncCheckSet, funcs[3]);
  202. case 3:
  203. del_func(_RTC_MemCheck, funcs[2]);
  204. case 2:
  205. del_func(_RTC_Free, funcs[1]);
  206. case 1:
  207. del_func(_RTC_Allocate, funcs[0]);
  208. }
  209. }
  210. }
  211. #endif
  212. #ifdef _DEBUG
  213. return &_CrtDbgReport;
  214. #else
  215. return 0;
  216. #endif
  217. }
  218. #endif