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.

294 lines
7.3 KiB

  1. /***
  2. *validate.cpp - Routines to validate the data structures.
  3. *
  4. * Copyright (c) 1993-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Routines to validate the Exception Handling data structures.
  8. *
  9. * Entry points:
  10. *
  11. * Error reporting:
  12. * * EHRuntimeError - reports the error with
  13. * a popup or print to stderr, then quits.
  14. *
  15. * Pointer validation:
  16. * * _ValidateRead - Confirms that a pointer is valid for reading
  17. * * _ValidateWrite - Confirms that a pointer is valid for writing
  18. * * _ValidateExecute - Confirms that a pointer is valid to jump to
  19. *
  20. * Data structure dumpers:
  21. * * DumpTypeDescriptor
  22. * * DumpFuncInfo
  23. * * DumpThrowInfo
  24. *
  25. * Execution tracing (only in /DENABLE_EHTRACE builds):
  26. * * EHTraceOutput
  27. *
  28. *Revision History:
  29. * ??-??-93 BS Module created
  30. * 10-17-94 BWT Disable code for PPC.
  31. * 04-25-95 DAK Add Kernel EH Support
  32. * 05-17-99 PML Remove all Macintosh support.
  33. * 10-22-99 PML Add EHTRACE support
  34. *
  35. ****/
  36. #if defined(_NTSUBSET_)
  37. extern "C" {
  38. #include <nt.h>
  39. #include <ntrtl.h>
  40. #include <nturtl.h>
  41. #include <ntos.h>
  42. }
  43. #endif
  44. #include <windows.h>
  45. #include <eh.h>
  46. #include <ehassert.h>
  47. #pragma hdrstop
  48. #if defined(DEBUG)
  49. int __cdecl
  50. dprintf( char *format, ... )
  51. {
  52. static char buffer[512];
  53. int size = vsprintf( buffer, format, (char*)(&format+1) );
  54. #if defined(_NTSUBSET_)
  55. DbgPrint( buffer );
  56. #else
  57. OutputDebugString( buffer );
  58. #endif
  59. return size;
  60. }
  61. #endif
  62. BOOL
  63. _ValidateRead( const void *data, UINT size )
  64. {
  65. BOOL bValid = TRUE;
  66. #if defined(_NTSUBSET_)
  67. // bValid = MmIsSystemAddressAccessable( (PVOID) data );
  68. #else
  69. if ( IsBadReadPtr( data, size ) ) {
  70. dprintf( "_ValidateRead( %p, %d ): Invalid Pointer!", data, size );
  71. // terminate(); // terminate does not return.
  72. bValid = FALSE;
  73. }
  74. #endif
  75. return bValid;
  76. }
  77. BOOL
  78. _ValidateWrite( void *data, UINT size )
  79. {
  80. BOOL bValid = TRUE;
  81. #if defined(_NTSUBSET_)
  82. // bValid = MmIsSystemAddressAccessable( (PVOID) data );
  83. #else
  84. if ( IsBadWritePtr( data, size ) ) {
  85. dprintf( "_ValidateWrite( %p, %d ): Invalid Pointer!", data, size );
  86. // terminate(); // terminate does not return.
  87. bValid = FALSE;
  88. }
  89. #endif
  90. return bValid;
  91. }
  92. BOOL
  93. _ValidateExecute( FARPROC code )
  94. {
  95. BOOL bValid = TRUE;
  96. #if defined(_NTSUBSET_)
  97. bValid = _ValidateRead(code, sizeof(FARPROC) );
  98. #else
  99. if ( IsBadCodePtr( code ) ) {
  100. dprintf( "_ValidateExecute( %p ): Invalid Function Address!", code );
  101. // terminate(); // terminate does not return
  102. bValid = FALSE;
  103. }
  104. #endif
  105. return bValid;
  106. }
  107. #if defined(DEBUG) && defined(_M_IX86)
  108. //
  109. // dbRNListHead - returns current value of FS:0.
  110. //
  111. // For debugger use only, since debugger doesn't seem to be able to view the
  112. // teb.
  113. //
  114. EHRegistrationNode *dbRNListHead(void)
  115. {
  116. EHRegistrationNode *pRN;
  117. __asm {
  118. mov eax, dword ptr FS:[0]
  119. mov pRN, eax
  120. }
  121. return pRN;
  122. }
  123. #endif
  124. #ifdef ENABLE_EHTRACE
  125. #include <stdio.h>
  126. #include <stdarg.h>
  127. //
  128. // Current EH tracing depth, stack for saving levels during __finally block
  129. // or __except filter.
  130. //
  131. int __ehtrace_level;
  132. int __ehtrace_level_stack_depth;
  133. int __ehtrace_level_stack[128];
  134. //
  135. // EHTraceOutput - Dump formatted string to OutputDebugString
  136. //
  137. void __cdecl EHTraceOutput(const char *format, ...)
  138. {
  139. va_list arglist;
  140. char buf[1024];
  141. sprintf(buf, "%p ", &format);
  142. OutputDebugString(buf);
  143. va_start(arglist, format);
  144. _vsnprintf(buf, sizeof(buf), format, arglist);
  145. OutputDebugString(buf);
  146. }
  147. //
  148. // EHTraceIndent - Return string for current EH tracing depth
  149. //
  150. const char*EHTraceIndent(int level)
  151. {
  152. static char indentbuf[128 + 1];
  153. // Reset global level to recover from stack unwinds
  154. __ehtrace_level = level;
  155. int depth = max(0, level - 1);
  156. if (depth > (sizeof(indentbuf) - 1) / 2) {
  157. depth = (sizeof(indentbuf) - 1) / 2;
  158. }
  159. for (int i = 0; i < depth; ++i) {
  160. indentbuf[2 * i] = '|';
  161. indentbuf[2 * i + 1] = ' ';
  162. }
  163. indentbuf[2 * depth] = '\0';
  164. return indentbuf;
  165. }
  166. //
  167. // EHTraceFunc - Chop down __FUNCTION__ to simple name
  168. //
  169. const char *EHTraceFunc(const char *func)
  170. {
  171. static char namebuf[128];
  172. const char *p = func + strlen(func) - 1;
  173. if (*p != ')') {
  174. // Name already simple (no arg list found)
  175. return func;
  176. }
  177. // Skip backwards past the argument list
  178. int parendepth = 1;
  179. while (p > func && parendepth > 0) {
  180. switch (*--p) {
  181. case '(':
  182. --parendepth;
  183. break;
  184. case ')':
  185. ++parendepth;
  186. break;
  187. }
  188. }
  189. // Find beginning of name
  190. // TODO: Won't work for funcs which return func-ptrs
  191. const char *pEnd = p;
  192. while (p > func && p[-1] != ' ') {
  193. --p;
  194. }
  195. size_t len = min(pEnd - p, sizeof(namebuf) - 1);
  196. memcpy(namebuf, p, len);
  197. namebuf[len] = '\0';
  198. return namebuf;
  199. }
  200. //
  201. // EHTracePushLevel - Push current trace depth on stack to allow temporary
  202. // resetting of level with __finally block or __except filter.
  203. //
  204. void EHTracePushLevel(int new_level)
  205. {
  206. if (__ehtrace_level_stack_depth < sizeof(__ehtrace_level_stack) / sizeof(__ehtrace_level_stack[0])) {
  207. __ehtrace_level_stack[__ehtrace_level_stack_depth] = __ehtrace_level;
  208. }
  209. ++__ehtrace_level_stack_depth;
  210. __ehtrace_level = new_level;
  211. }
  212. //
  213. // EHTracePopLevel - Pop saved trace depth from stack on completion of
  214. // __finally block or __except filter, and optionally restore global depth.
  215. //
  216. void EHTracePopLevel(bool restore)
  217. {
  218. --__ehtrace_level_stack_depth;
  219. if (restore &&
  220. __ehtrace_level_stack_depth < sizeof(__ehtrace_level_stack) / sizeof(__ehtrace_level_stack[0]))
  221. {
  222. __ehtrace_level = __ehtrace_level_stack[__ehtrace_level_stack_depth];
  223. }
  224. }
  225. //
  226. // EHTraceExceptFilter - Dump trace info for __except filter. Trace level must
  227. // have been pushed before entry with EHTracePushLevel, so any functions called
  228. // for the 'expr' argument are dumped at the right level.
  229. //
  230. int EHTraceExceptFilter(const char *func, int expr)
  231. {
  232. EHTraceOutput("In : %s%s: __except filter returns %d (%s)\n",
  233. EHTraceIndent(__ehtrace_level), EHTraceFunc(func), expr,
  234. expr < 0 ? "EXCEPTION_CONTINUE_EXECUTION" :
  235. expr > 0 ? "EXCEPTION_EXECUTE_HANDLER" :
  236. "EXCEPTION_CONTINUE_SEARCH");
  237. EHTracePopLevel(expr <= 0);
  238. return expr;
  239. }
  240. //
  241. // EHTraceHandlerReturn - Dump trace info for exception handler return
  242. //
  243. void EHTraceHandlerReturn(const char *func, int level, EXCEPTION_DISPOSITION result)
  244. {
  245. EHTraceOutput( "Exit : %s%s: Handler returning %d (%s)\n", \
  246. EHTraceIndent(level), EHTraceFunc(func), result,
  247. result == ExceptionContinueExecution ? "ExceptionContinueExecution" :
  248. result == ExceptionContinueSearch ? "ExceptionContinueSearch" :
  249. result == ExceptionNestedException ? "ExceptionNestedException" :
  250. result == ExceptionCollidedUnwind ? "ExceptionCollidedUnwind" :
  251. "unknown" );
  252. }
  253. #endif /* ENABLE_EHTRACE */