Leaked source code of windows server 2003
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.

339 lines
10 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. verifier.cxx
  5. Abstract:
  6. This file contains the verifier related routines
  7. for the kernel debugger extensions dll.
  8. Author:
  9. Jason Hartman (JasonHa)
  10. Environment:
  11. User Mode
  12. --*/
  13. #include "precomp.hxx"
  14. // Pool tracking is always disabled for graphic drivers. (NTBUG:421768)
  15. #define GRAPHICS_DRIVER_POOL_TRACKING_SUPPORTED 0
  16. /******************************Public*Routine******************************\
  17. * DECLARE_API( verifier )
  18. *
  19. * Dumps the stack backtraces in the tracked pool. Only for checked Hydra.
  20. *
  21. \**************************************************************************/
  22. CHAR szVSTATE[] = "win32k!VSTATE";
  23. #if GRAPHICS_DRIVER_POOL_TRACKING_SUPPORTED
  24. CHAR szVERIFIERTRACKHDR[] = "win32k!VERIFIERTRACKHDR";
  25. #endif
  26. const PSZ gpszVerifierFuncs[] = {
  27. "EngAllocMem ",
  28. "EngFreeMem ",
  29. "EngAllocUserMem ",
  30. "EngFreeUserMem ",
  31. "EngCreateBitmap ",
  32. "EngCreateDeviceSurface",
  33. "EngCreateDeviceBitmap ",
  34. "EngCreatePalette ",
  35. "EngCreateClip ",
  36. "EngCreatePath ",
  37. "EngCreateWnd ",
  38. "EngCreateDriverObj ",
  39. "BRUSHOBJ_pvAllocRbrush",
  40. "CLIPOBJ_ppoGetPath ",
  41. };
  42. #define NUM_VER_FUNCS (sizeof(gpszVerifierFuncs)/sizeof(gpszVerifierFuncs[0]))
  43. DECLARE_API( verifier )
  44. {
  45. ULONG error;
  46. ULONG64 offVState;
  47. #define GetVSTATEField(field,local) \
  48. GetFieldValue(offVState, szVSTATE, field, local)
  49. // VSTATE fields
  50. FLONG fl;
  51. #if GRAPHICS_DRIVER_POOL_TRACKING_SUPPORTED
  52. ULONG64 pList;
  53. #endif
  54. #if GRAPHICS_DRIVER_POOL_TRACKING_SUPPORTED
  55. BOOL bDump = FALSE;
  56. #endif
  57. BOOL bStats = FALSE;
  58. //
  59. // Parse arguments.
  60. //
  61. PARSE_ARGUMENTS(verifier_help);
  62. if(parse_iFindSwitch(tokens, ntok, 'h')!=-1) { goto verifier_help; }
  63. #if GRAPHICS_DRIVER_POOL_TRACKING_SUPPORTED
  64. if(parse_iFindSwitch(tokens, ntok, 'd')!=-1) { bDump = TRUE; }
  65. #endif
  66. if(parse_iFindSwitch(tokens, ntok, 's')!=-1) { bStats = TRUE; }
  67. //
  68. // Get global veriferier address (VSTATE gvs)
  69. //
  70. offVState = GetExpression(GDISymbol(gvs));
  71. if (! offVState)
  72. {
  73. ReloadSymbols(GDIModule());
  74. offVState = GetExpression(GDISymbol(gvs));
  75. if (! offVState)
  76. {
  77. dprintf(" GetExpression(\"%s\") returned 0.\n", GDISymbol(gvs));
  78. dprintf(" Please fix symbols and try again.\n");
  79. EXIT_API(S_OK);
  80. }
  81. }
  82. //
  83. // Always dump the verifier state.
  84. //
  85. dprintf("Global VSTATE (@ %#p)\n", offVState);
  86. if (error = (ULONG)InitTypeRead(offVState, win32k!VSTATE))
  87. {
  88. dprintf(" unable to get contents of verifier state\n");
  89. dprintf(" (InitTypeRead returned %s)\n", pszWinDbgError(error));
  90. EXIT_API(S_OK);
  91. }
  92. fl = (FLONG)ReadField(fl);
  93. dprintf(" fl = 0x%08lx\n", fl);
  94. if (fl = (FLONG)flPrintFlags(afdDVERIFIER, (ULONG64)fl))
  95. {
  96. dprintf(" Unknown flags: 0x%08lx\n", fl);
  97. }
  98. dprintf(" bSystemStable = %s\n" , ReadField(bSystemStable) ? "TRUE" : "FALSE");
  99. dprintf(" ulRandomSeed = 0x%08lx\n", (ULONG)ReadField(ulRandomSeed));
  100. dprintf(" ulFailureMask = 0x%08lx\n", (ULONG)ReadField(ulFailureMask));
  101. dprintf(" ulDebugLevel = %ld\n" , (ULONG)ReadField(ulDebugLevel));
  102. #if GRAPHICS_DRIVER_POOL_TRACKING_SUPPORTED
  103. dprintf(" hsemPoolTracker = %#p\n" , ReadField(hsemPoolTracker));
  104. pList = ReadField(lePoolTrackerHead.Flink);
  105. dprintf(" lePoolTrackerHead.Flink = %#p\n" , pList);
  106. dprintf(" lePoolTrackerHead.Blink = %#p\n" , ReadField(lePoolTrackerHead.Blink));
  107. #endif
  108. //
  109. // Optionally dump the statistics for each function hooked by verifier.
  110. //
  111. if (bStats)
  112. {
  113. FIELD_INFO Array = {
  114. DbgStr("avs"), DbgStr(""),
  115. 0, DBG_DUMP_FIELD_FULL_NAME,
  116. 0, NULL
  117. };
  118. FIELD_INFO Entry = {
  119. DbgStr("avs[0]"), DbgStr(""),
  120. 0, DBG_DUMP_FIELD_FULL_NAME,
  121. 0, NULL
  122. };
  123. SYM_DUMP_PARAM Sym = {
  124. sizeof (SYM_DUMP_PARAM), DbgStr(szVSTATE),
  125. DBG_DUMP_NO_PRINT, offVState,
  126. NULL, NULL, NULL,
  127. 1, &Array
  128. };
  129. // Read size of the statistics array
  130. error = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
  131. if (!error)
  132. {
  133. // Read size of a single statistics entry
  134. Sym.Fields = &Entry;
  135. error = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
  136. }
  137. if (error || (Entry.size == 0))
  138. {
  139. dprintf("\n Unable to get verifier statistics.\n");
  140. if (error)
  141. {
  142. if (error == FIELDS_DID_NOT_MATCH)
  143. {
  144. dprintf(" * " GDIModule() " was not built with VERIFIER_STATISTICS defined.\n");
  145. }
  146. else
  147. {
  148. dprintf(" Last error was %s\n.", pszWinDbgError(error));
  149. }
  150. }
  151. }
  152. else
  153. {
  154. char szBuffer[80]; // Composition buffer for field names
  155. int ArraySize = Array.size/Entry.size; // Number of hooked functions
  156. int i;
  157. ULONG ulAttempts;
  158. ULONG ulFailures;
  159. dprintf("\nVerifier statistics:\n");
  160. dprintf("Function Attempts Failures\n");
  161. dprintf("---------------------- ---------- ----------\n");
  162. // Read and print statistics for each hooked function
  163. for (i = 0; i < ArraySize && !CheckControlC(); i++)
  164. {
  165. sprintf(szBuffer, "avs[%d].ulAttempts", i);
  166. error = GetVSTATEField(szBuffer, ulAttempts);
  167. if (error) break;
  168. sprintf(szBuffer, "avs[%d].ulFailures", i);
  169. error = GetVSTATEField(szBuffer, ulFailures);
  170. if (error) break;
  171. dprintf("%s 0x%08lx 0x%08lx\n",
  172. ((i < NUM_VER_FUNCS) ?
  173. gpszVerifierFuncs[i] :
  174. " * Uknown Interface * "),
  175. ulAttempts,
  176. ulFailures);
  177. }
  178. if (i == 0)
  179. {
  180. dprintf(" ** No Statistics Available **\n");
  181. }
  182. else if (i > NUM_VER_FUNCS)
  183. {
  184. dprintf("\n * - .verifier extension needs updated.\n");
  185. }
  186. if (error)
  187. {
  188. dprintf(" Last statistic read returned %s.\n", szBuffer, pszWinDbgError(error));
  189. }
  190. }
  191. }
  192. #if GRAPHICS_DRIVER_POOL_TRACKING_SUPPORTED
  193. //
  194. // Optionally dump tracked pool.
  195. //
  196. if (bDump)
  197. {
  198. if (fl & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS)
  199. {
  200. FIELD_INFO SizeInfo = {DbgStr("ulSize"), NULL, 0, 0, 0, NULL};
  201. SYM_DUMP_PARAM Sym = {
  202. sizeof(SYM_DUMP_PARAM), DbgStr(szVERIFIERTRACKHDR),
  203. DBG_DUMP_NO_PRINT, 0, NULL, NULL, NULL,
  204. 1, &SizeInfo
  205. };
  206. BYTE Tag[4]; // Allocation tag
  207. ULONG64 Size; // Size of allocation
  208. ULONG SizeSize;
  209. ULONG SizeHdr; // Size of header struct (offset to allocation)
  210. // Read sizeof of ulSize field
  211. error = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
  212. SizeSize = (error) ? sizeof(Size) : SizeInfo.size;
  213. // Read sizeof VERIFIERTRACKHDR structure
  214. Sym.Options |= DBG_DUMP_GET_SIZE_ONLY;
  215. SizeHdr = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
  216. dprintf("\nTracked VerifierEngAllocMem allocations\n");
  217. dprintf("Tag \tSize %s\tAddr \n", (SizeSize == sizeof(ULONG)) ? "" : " ");
  218. dprintf("----\t--------%s\t----------------\n", (SizeSize == sizeof(ULONG)) ? "" : "--------");
  219. // Are there any allocations?
  220. if (pList)
  221. {
  222. ULONG64 pListHead = pList;
  223. // Read until we loop back to the first allocation.
  224. do
  225. {
  226. // Attempt to read allocation info
  227. error = GetFieldValue(pList, szVERIFIERTRACKHDR, "ulTag", Tag);
  228. if (error) break;
  229. error = GetFieldValue(pList, szVERIFIERTRACKHDR, "ulSize", Size);
  230. if (error) break;
  231. // Print Tag
  232. dprintf("%c%c%c%c", Tag[0], Tag[1], Tag[2], Tag[3]);
  233. // Print allocation size
  234. if (SizeSize == sizeof(ULONG))
  235. {
  236. dprintf("\t%08X", (ULONG)Size);
  237. }
  238. else
  239. {
  240. dprintf("\t%I64X", Size);
  241. }
  242. // Print start address of allocation
  243. if (SizeHdr != 0)
  244. {
  245. dprintf("\t%p\n", pList+SizeHdr);
  246. }
  247. else
  248. {
  249. dprintf("\t%p+??\n", pList);
  250. }
  251. // Get next allocation
  252. error = GetFieldValue(pList, GDIType(LIST_ENTRY), "FLink", pList);
  253. } while (pList != pListHead && !error && !CheckControlC());
  254. }
  255. else
  256. {
  257. dprintf(" ** No tracked allocations.\n");
  258. }
  259. }
  260. else
  261. dprintf("\nPool tracking not enabled\n");
  262. }
  263. #endif
  264. EXIT_API(S_OK);
  265. //
  266. // Debugger extension help.
  267. //
  268. verifier_help:
  269. dprintf("Usage: verifier [-?h"
  270. #if GRAPHICS_DRIVER_POOL_TRACKING_SUPPORTED
  271. "d"
  272. #endif
  273. "s]\n");
  274. #if GRAPHICS_DRIVER_POOL_TRACKING_SUPPORTED
  275. dprintf(" d - Dump tracked pool (if pool tracking enabled)\n");
  276. #endif
  277. dprintf(" s - Dump allocation statistics\n");
  278. EXIT_API(S_OK);
  279. }