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.

425 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. poolfilt.cpp
  5. Abstract:
  6. This module filters out the useful information from a sorted poolsnap output file.
  7. Author:
  8. Matt Bandy (t-mattba) 27-Jul-1998
  9. Revision History:
  10. 27-Jul-1998 t-mattba
  11. Modified module to conform to coding standards.
  12. --*/
  13. #include <nt.h>
  14. #include <tchar.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #define PF_NEW_TAG 0
  19. #define PF_UPDATE 1
  20. // globals
  21. LONG MinimumAllocationsChangeToReport=1;
  22. LONG MinimumBytesChangeToReport=1;
  23. BOOLEAN ReportIncreasesOnly = TRUE;
  24. VOID
  25. PrintUsage(
  26. )
  27. /*++
  28. Routine Description:
  29. This routine prints an informational message about the proper usage of POOLFILT.
  30. Arguments:
  31. None.
  32. Return value:
  33. None.
  34. --*/
  35. {
  36. _ftprintf(stderr, _T("Summarizes possible leaks in a sorted poolsnap output file.\n\n"));
  37. _ftprintf(stderr, _T("POOLFILT file [/MINALLOCS:n] [/MINBYTES:n] [/ALL]\n\n"));
  38. _ftprintf(stderr, _T("file The sorted poolsnap output file to summarize.\n"));
  39. _ftprintf(stderr, _T("/MINALLOCS:n Reports only tags where open allocations change by at least n.\n"));
  40. _ftprintf(stderr, _T("/MINBYTES:n Reports only tags where bytes allocated change by at least n.\n"));
  41. _ftprintf(stderr, _T("/ALL Reports decreases as well as increases.\n"));
  42. }
  43. VOID
  44. PrintTagInformation(
  45. IN BOOLEAN AllocationsAlwaysGrow,
  46. IN BOOLEAN BytesAlwaysGrow,
  47. IN LPTSTR TagName,
  48. IN LONG InitialAllocations,
  49. IN LONG FinalAllocations,
  50. IN LONG InitialBytes,
  51. IN LONG FinalBytes
  52. )
  53. /*++
  54. Routine Description:
  55. This routine reports the memory usage of a single process.
  56. Arguments:
  57. AllocationsAlwaysGrow - TRUE if number of open allocations monotonically increases.
  58. BytesAlwaysGrow - TRUE if number of bytes allocated monotonically increases.
  59. TagName - the name of the tag being reported.
  60. InitialAllocations - initial number of open allocations for this tag.
  61. FinalAllocations - final number fo open allocations for this tag.
  62. InitialBytes - initial number of bytes allocated for this tag.
  63. FinalBytes - final number of bytes allocated for this tag.
  64. Return value:
  65. None.
  66. --*/
  67. {
  68. _TCHAR AllocationsString[64];
  69. _TCHAR BytesString[64];
  70. if(((!ReportIncreasesOnly) &&
  71. (abs(FinalAllocations - InitialAllocations) >=
  72. MinimumAllocationsChangeToReport)) ||
  73. (FinalAllocations - InitialAllocations >=
  74. MinimumAllocationsChangeToReport)) {
  75. _stprintf(AllocationsString, _T("%10d->%10d"), InitialAllocations, FinalAllocations);
  76. } else {
  77. _tcscpy(AllocationsString, _T(" "));
  78. }
  79. if(((!ReportIncreasesOnly) &&
  80. (abs(FinalBytes - InitialBytes) >=
  81. MinimumBytesChangeToReport)) ||
  82. (FinalBytes - InitialBytes >=
  83. MinimumBytesChangeToReport)) {
  84. _stprintf(BytesString, _T("%10d->%10d"), InitialBytes, FinalBytes);
  85. } else {
  86. _tcscpy(BytesString, _T(" "));
  87. }
  88. _tprintf(_T("%c%c %s %s %s\n"),
  89. (AllocationsAlwaysGrow && (FinalAllocations != InitialAllocations) ? _T('!') : _T(' ')),
  90. (BytesAlwaysGrow && (FinalBytes != InitialBytes) ? _T('!') : _T(' ')),
  91. TagName, AllocationsString, BytesString);
  92. }
  93. LONG _cdecl
  94. _tmain(
  95. IN LONG argc,
  96. IN LPTSTR argv[]
  97. )
  98. /*++
  99. Routine Description:
  100. This routine parses program arguments, reads the input file, and outputs the result.
  101. Arguments:
  102. argc - Number of command line arguments.
  103. argv - Command line arguments.
  104. Return value:
  105. 0 if filtering is successful, 1 otherwise.
  106. --*/
  107. {
  108. try {
  109. _TCHAR LineBuffer[256];
  110. _TCHAR PoolTag[11];
  111. LONG CurrentState = PF_NEW_TAG;
  112. LONG InitialAllocations = 0;
  113. LONG FinalAllocations = 0;
  114. LONG NewAllocations = 0;
  115. LONG InitialBytes = 0;
  116. LONG FinalBytes = 0;
  117. LONG NewBytes = 0;
  118. BOOLEAN AllocationsAlwaysGrow = TRUE;
  119. BOOLEAN BytesAlwaysGrow = TRUE;
  120. LPTSTR InputFileName = NULL;
  121. BOOLEAN InterpretedArgument = FALSE;
  122. FILE *InputFile = NULL;
  123. // make sure PoolTag is properly terminated
  124. PoolTag[10]=_T('\0');
  125. // process arguments
  126. for(LONG n = 1; n < argc; n++) {
  127. InterpretedArgument = FALSE;
  128. switch(argv[n][0]) {
  129. case _T('-'):
  130. case _T('/'):
  131. // it's a switch
  132. if(!_tcsnicmp(argv[n]+1, _T("minallocs:"), 10)) {
  133. MinimumAllocationsChangeToReport = _ttoi(argv[n]+11);
  134. InterpretedArgument = TRUE;
  135. }
  136. if(!_tcsnicmp(argv[n]+1, _T("minbytes:"), 9)) {
  137. MinimumBytesChangeToReport = _ttoi(argv[n]+10);
  138. InterpretedArgument = TRUE;
  139. }
  140. if(!_tcsicmp(argv[n]+1, _T("all"))) {
  141. ReportIncreasesOnly = FALSE;
  142. InterpretedArgument = TRUE;
  143. }
  144. break;
  145. default:
  146. // it's a filename
  147. if(InputFileName != NULL) {
  148. // already have the filename
  149. PrintUsage();
  150. return 1;
  151. }
  152. InputFileName = argv[n];
  153. InterpretedArgument = TRUE;
  154. break;
  155. }
  156. if(!InterpretedArgument) {
  157. PrintUsage();
  158. return 1;
  159. }
  160. }
  161. if(InputFileName == NULL) {
  162. // user didn't specify filename
  163. PrintUsage();
  164. return 1;
  165. }
  166. InputFile = _tfopen(InputFileName, _T("rt"));
  167. if(InputFile == NULL) {
  168. _ftprintf(stderr, _T("Cannot open input file."));
  169. return 1;
  170. }
  171. // get first line
  172. _fgetts(LineBuffer, 256, InputFile);
  173. // simple check for sorted poolsnap output
  174. if(_tcsncmp(LineBuffer, _T(" Tag Type Allocs Frees Diff Bytes Per Alloc"), 60)) {
  175. _ftprintf(stderr, _T("Input is not a sorted poolsnap log."));
  176. return 1;
  177. }
  178. // get next line
  179. _fgetts(LineBuffer, 256, InputFile);
  180. while(!feof(InputFile)) {
  181. if(!_tcscmp(LineBuffer,_T("\n"))) {
  182. CurrentState = PF_NEW_TAG;
  183. if(ReportIncreasesOnly) {
  184. if(((FinalAllocations - InitialAllocations) >= MinimumAllocationsChangeToReport)
  185. || ((FinalBytes - InitialBytes) >= MinimumBytesChangeToReport)) {
  186. PrintTagInformation(AllocationsAlwaysGrow, BytesAlwaysGrow,
  187. PoolTag, InitialAllocations, FinalAllocations,
  188. InitialBytes, FinalBytes);
  189. }
  190. } else {
  191. if((abs(FinalAllocations - InitialAllocations) >= MinimumAllocationsChangeToReport)
  192. || (abs(FinalBytes - InitialBytes) >= MinimumBytesChangeToReport)) {
  193. PrintTagInformation(AllocationsAlwaysGrow, BytesAlwaysGrow,
  194. PoolTag, InitialAllocations, FinalAllocations,
  195. InitialBytes, FinalBytes);
  196. }
  197. }
  198. } else {
  199. if(_tcslen(LineBuffer) <= 42) {
  200. _ftprintf(stderr, _T("Format violated.\n"));
  201. return 1;
  202. }
  203. switch(CurrentState) {
  204. case PF_NEW_TAG:
  205. // get tag and paged/non-paged
  206. _tcsncpy(PoolTag, LineBuffer+1, 10);
  207. // get allocs
  208. _stscanf(LineBuffer+32, _T("%d"), &InitialAllocations);
  209. // get bytes
  210. _stscanf(LineBuffer+42, _T("%d"), &InitialBytes);
  211. // assume this always grows until we find a counterexample
  212. AllocationsAlwaysGrow = TRUE;
  213. BytesAlwaysGrow = TRUE;
  214. // this is initial and final until we find another
  215. FinalAllocations = InitialAllocations;
  216. FinalBytes = InitialBytes;
  217. // keep updating this tag
  218. CurrentState = PF_UPDATE;
  219. break;
  220. case PF_UPDATE:
  221. // get allocs
  222. _stscanf(LineBuffer+32, _T("%d"), &NewAllocations);
  223. // get bytes
  224. _stscanf(LineBuffer+42, _T("%d"), &NewBytes);
  225. // did allocs decrease?
  226. if(NewAllocations < FinalAllocations) {
  227. AllocationsAlwaysGrow = FALSE;
  228. }
  229. // did bytes decrease?
  230. if(NewBytes < FinalBytes) {
  231. BytesAlwaysGrow = FALSE;
  232. }
  233. // copy new to final
  234. FinalAllocations = NewAllocations;
  235. FinalBytes = NewBytes;
  236. break;
  237. }
  238. }
  239. // get next line
  240. _fgetts(LineBuffer, 256, InputFile);
  241. }
  242. // done
  243. fclose(InputFile);
  244. return 0;
  245. } catch (...) {
  246. // this is mostly intended to catch out-of-memory conditions
  247. _tprintf(_T("\nAn exception was detected. POOLFILT aborted.\n"));
  248. return 1;
  249. }
  250. }