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.

273 lines
8.0 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. pfmon.c
  5. Abstract:
  6. USAGE: pfmon [pfmon switches] command-line-of-application
  7. Author:
  8. Mark Lucovsky (markl) 26-Jan-1995
  9. --*/
  10. #include "pfmonp.h"
  11. #define WORKING_SET_BUFFER_ENTRYS 4096
  12. PSAPI_WS_WATCH_INFORMATION WorkingSetBuffer[WORKING_SET_BUFFER_ENTRYS];
  13. #define MAX_SYMNAME_SIZE 1024
  14. CHAR PcSymBuffer[sizeof(IMAGEHLP_SYMBOL)+MAX_SYMNAME_SIZE];
  15. PIMAGEHLP_SYMBOL PcSymbol = (PIMAGEHLP_SYMBOL) PcSymBuffer;
  16. CHAR VaSymBuffer[sizeof(IMAGEHLP_SYMBOL)+MAX_SYMNAME_SIZE];
  17. PIMAGEHLP_SYMBOL VaSymbol = (PIMAGEHLP_SYMBOL) VaSymBuffer;
  18. #if defined (_WIN64)
  19. #define ZERO_PTR "%016I64x"
  20. #define ZEROD_PTR "%I64u"
  21. #else
  22. #define ZERO_PTR "%08x"
  23. #define ZEROD_PTR "%u"
  24. #endif
  25. int
  26. WINAPI
  27. WinMain(
  28. HINSTANCE hInstance,
  29. HINSTANCE hPrevInstance,
  30. LPSTR lpCmdLine,
  31. int nShowCmd
  32. )
  33. {
  34. CHAR Line[256];
  35. if (!InitializePfmon()) {
  36. ExitProcess( 1 );
  37. }
  38. else {
  39. DebugEventLoop();
  40. sprintf(Line,"\n PFMON: Total Faults %d (KM %d UM %d Soft %d, Hard %d, Code %d, Data %d)\n",
  41. TotalSoftFaults + TotalHardFaults,
  42. TotalKernelFaults,
  43. TotalUserFaults,
  44. TotalSoftFaults,
  45. TotalHardFaults,
  46. TotalCodeFaults,
  47. TotalDataFaults
  48. );
  49. fprintf(stdout,"%s",Line);
  50. if ( LogFile ) {
  51. fprintf(LogFile,"%s",Line);
  52. fclose(LogFile);
  53. }
  54. ExitProcess( 0 );
  55. }
  56. return 0;
  57. }
  58. VOID
  59. ProcessPfMonData(
  60. VOID
  61. )
  62. {
  63. BOOL b;
  64. BOOL DidOne;
  65. INT i;
  66. PMODULE_INFO PcModule;
  67. PMODULE_INFO VaModule;
  68. ULONG_PTR PcOffset;
  69. DWORD_PTR VaOffset;
  70. CHAR PcLine[256];
  71. CHAR VaLine[256];
  72. CHAR PcModuleStr[256];
  73. CHAR VaModuleStr[256];
  74. LPVOID Pc;
  75. LPVOID Va;
  76. BOOL SoftFault;
  77. BOOL CodeFault;
  78. BOOL KillLog;
  79. static int cPfCnt = 0;
  80. PcSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
  81. PcSymbol->MaxNameLength = MAX_SYMNAME_SIZE;
  82. VaSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
  83. VaSymbol->MaxNameLength = MAX_SYMNAME_SIZE;
  84. //Get the buffer of recent page faults from the process's data structure
  85. b = GetWsChanges(hProcess,&WorkingSetBuffer[0],sizeof(WorkingSetBuffer));
  86. if ( b ) {
  87. DidOne = FALSE;
  88. i = 0;
  89. while (WorkingSetBuffer[i].FaultingPc) {
  90. if ( WorkingSetBuffer[i].FaultingVa ) {
  91. Pc = WorkingSetBuffer[i].FaultingPc;
  92. Va = WorkingSetBuffer[i].FaultingVa;
  93. if ( (ULONG_PTR)Pc >= SystemRangeStart ) {
  94. TotalKernelFaults++;
  95. if ( !fKernel ) {
  96. i++;
  97. continue;
  98. }
  99. }
  100. else {
  101. TotalUserFaults++;
  102. if ( fKernelOnly ) {
  103. i++;
  104. continue;
  105. }
  106. }
  107. //Check least sig bit which stores whether it was a hard
  108. //or soft fault
  109. if ( (ULONG_PTR)Va & 1 ) {
  110. TotalSoftFaults++;
  111. SoftFault = TRUE;
  112. }
  113. else {
  114. TotalHardFaults++;
  115. SoftFault = FALSE;
  116. }
  117. Va = (LPVOID)( (ULONG_PTR)Va & ~1);
  118. if ( (LPVOID)((ULONG_PTR)Pc & ~1) == Va ) {
  119. CodeFault = TRUE;
  120. TotalCodeFaults++;
  121. }
  122. else {
  123. TotalDataFaults++;
  124. CodeFault = FALSE;
  125. }
  126. PcModule = FindModuleContainingAddress(Pc);
  127. VaModule = FindModuleContainingAddress(Va);
  128. if ( PcModule ) {
  129. PcModule->NumberCausedFaults++;
  130. sprintf(PcModuleStr, "%s", PcModule->ModuleName);
  131. }
  132. else {
  133. sprintf(PcModuleStr,"not found %p",Pc);
  134. PcModuleStr[0] = '\0';
  135. }
  136. //Va was either a code reference or global
  137. //reference as opposed to a heap reference
  138. if ( VaModule ) {
  139. if ( SoftFault ) {
  140. VaModule->NumberFaultedSoftVas++;
  141. }
  142. else {
  143. VaModule->NumberFaultedHardVas++;
  144. }
  145. sprintf(VaModuleStr, "%s", VaModule->ModuleName);
  146. }
  147. else
  148. VaModuleStr[0] = '\0';
  149. if (SymGetSymFromAddr(hProcess, (ULONG_PTR)Pc, &PcOffset, PcSymbol)) {
  150. if ( PcOffset ) {
  151. sprintf(PcLine,"%s+0x%x",PcSymbol->Name,PcOffset);
  152. }
  153. else {
  154. sprintf(PcLine,"%s",PcSymbol->Name);
  155. }
  156. }
  157. else {
  158. sprintf(PcLine,""ZERO_PTR"",Pc);
  159. }
  160. if (SymGetSymFromAddr(hProcess, (ULONG_PTR)Va, &VaOffset, VaSymbol)) {
  161. if ( VaOffset ) {
  162. sprintf(VaLine,"%s+0x%p",VaSymbol->Name,VaOffset);
  163. }
  164. else {
  165. sprintf(VaLine,"%s",VaSymbol->Name);
  166. }
  167. }
  168. else {
  169. sprintf(VaLine,""ZERO_PTR"",Va);
  170. }
  171. KillLog = FALSE;
  172. if ( fCodeOnly && !CodeFault ) {
  173. KillLog = TRUE;
  174. }
  175. if ( fHardOnly && SoftFault ) {
  176. KillLog = TRUE;
  177. }
  178. if ( !KillLog ) {
  179. if ( !fLogOnly ) {
  180. if (!fDatabase) {
  181. fprintf(stdout,"%s%s : %s\n",SoftFault ? "SOFT: " : "HARD: ",PcLine,VaLine);
  182. }
  183. else {
  184. //Addresses are printed out in decimal
  185. //because most databases don't support
  186. //hex formats
  187. fprintf(stdout,"%8d\t%s\t%s\t%s\t"ZEROD_PTR"\t%s\t%s\t"ZEROD_PTR"\n",
  188. cPfCnt,
  189. SoftFault ? "SOFT" : "HARD",
  190. PcModuleStr,
  191. PcLine,
  192. (DWORD_PTR) Pc,
  193. VaModuleStr,
  194. VaLine,
  195. (DWORD_PTR) Va);
  196. }
  197. }
  198. if ( LogFile ) {
  199. if (!fDatabase) {
  200. fprintf(LogFile,"%s%s : %s\n",SoftFault ? "SOFT: " : "HARD: ",PcLine,VaLine);
  201. }
  202. else {
  203. fprintf(LogFile,"%8d\t%s\t%s\t%s\t"ZEROD_PTR"\t%s\t%s\t"ZEROD_PTR"\n",
  204. cPfCnt,
  205. SoftFault ? "SOFT" : "HARD",
  206. PcModuleStr,
  207. PcLine,
  208. (DWORD_PTR) Pc,
  209. VaModuleStr,
  210. VaLine,
  211. (DWORD_PTR) Va);
  212. }
  213. }
  214. DidOne = TRUE;
  215. cPfCnt++;
  216. }
  217. }
  218. i++;
  219. }
  220. if ( DidOne ) {
  221. if ( !fLogOnly && !fDatabase) {
  222. fprintf(stdout,"\n");
  223. }
  224. }
  225. //If the buffer overflowed then a non-zero value for
  226. //the Va was stored in the last record.
  227. if (WorkingSetBuffer[i].FaultingVa)
  228. fprintf(stdout,"Warning: Page fault buffer has overflowed\n");
  229. }
  230. }