|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
pfmon.c
Abstract:
USAGE: pfmon [pfmon switches] command-line-of-application
Author:
Mark Lucovsky (markl) 26-Jan-1995
--*/
#include "pfmonp.h"
#define WORKING_SET_BUFFER_ENTRYS 4096
PSAPI_WS_WATCH_INFORMATION WorkingSetBuffer[WORKING_SET_BUFFER_ENTRYS];
#define MAX_SYMNAME_SIZE 1024
CHAR PcSymBuffer[sizeof(IMAGEHLP_SYMBOL)+MAX_SYMNAME_SIZE]; PIMAGEHLP_SYMBOL PcSymbol = (PIMAGEHLP_SYMBOL) PcSymBuffer; CHAR VaSymBuffer[sizeof(IMAGEHLP_SYMBOL)+MAX_SYMNAME_SIZE]; PIMAGEHLP_SYMBOL VaSymbol = (PIMAGEHLP_SYMBOL) VaSymBuffer;
#if defined (_WIN64)
#define ZERO_PTR "%016I64x"
#define ZEROD_PTR "%I64u"
#else
#define ZERO_PTR "%08x"
#define ZEROD_PTR "%u"
#endif
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { CHAR Line[256];
if (!InitializePfmon()) { ExitProcess( 1 ); } else { DebugEventLoop(); sprintf(Line,"\n PFMON: Total Faults %d (KM %d UM %d Soft %d, Hard %d, Code %d, Data %d)\n", TotalSoftFaults + TotalHardFaults, TotalKernelFaults, TotalUserFaults, TotalSoftFaults, TotalHardFaults, TotalCodeFaults, TotalDataFaults ); fprintf(stdout,"%s",Line); if ( LogFile ) { fprintf(LogFile,"%s",Line); fclose(LogFile); } ExitProcess( 0 ); }
return 0; }
VOID ProcessPfMonData( VOID ) { BOOL b; BOOL DidOne; INT i; PMODULE_INFO PcModule; PMODULE_INFO VaModule; ULONG_PTR PcOffset; DWORD_PTR VaOffset; CHAR PcLine[256]; CHAR VaLine[256]; CHAR PcModuleStr[256]; CHAR VaModuleStr[256]; LPVOID Pc; LPVOID Va; BOOL SoftFault; BOOL CodeFault; BOOL KillLog; static int cPfCnt = 0;
PcSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); PcSymbol->MaxNameLength = MAX_SYMNAME_SIZE; VaSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); VaSymbol->MaxNameLength = MAX_SYMNAME_SIZE;
//Get the buffer of recent page faults from the process's data structure
b = GetWsChanges(hProcess,&WorkingSetBuffer[0],sizeof(WorkingSetBuffer));
if ( b ) { DidOne = FALSE; i = 0; while (WorkingSetBuffer[i].FaultingPc) { if ( WorkingSetBuffer[i].FaultingVa ) { Pc = WorkingSetBuffer[i].FaultingPc; Va = WorkingSetBuffer[i].FaultingVa;
if ( (ULONG_PTR)Pc >= SystemRangeStart ) { TotalKernelFaults++; if ( !fKernel ) { i++; continue; } } else { TotalUserFaults++; if ( fKernelOnly ) { i++; continue; } }
//Check least sig bit which stores whether it was a hard
//or soft fault
if ( (ULONG_PTR)Va & 1 ) { TotalSoftFaults++; SoftFault = TRUE; } else { TotalHardFaults++; SoftFault = FALSE; }
Va = (LPVOID)( (ULONG_PTR)Va & ~1); if ( (LPVOID)((ULONG_PTR)Pc & ~1) == Va ) { CodeFault = TRUE; TotalCodeFaults++; } else { TotalDataFaults++; CodeFault = FALSE; }
PcModule = FindModuleContainingAddress(Pc); VaModule = FindModuleContainingAddress(Va);
if ( PcModule ) { PcModule->NumberCausedFaults++; sprintf(PcModuleStr, "%s", PcModule->ModuleName); } else { sprintf(PcModuleStr,"not found %p",Pc); PcModuleStr[0] = '\0'; }
//Va was either a code reference or global
//reference as opposed to a heap reference
if ( VaModule ) { if ( SoftFault ) { VaModule->NumberFaultedSoftVas++; } else { VaModule->NumberFaultedHardVas++; } sprintf(VaModuleStr, "%s", VaModule->ModuleName); } else VaModuleStr[0] = '\0';
if (SymGetSymFromAddr(hProcess, (ULONG_PTR)Pc, &PcOffset, PcSymbol)) { if ( PcOffset ) { sprintf(PcLine,"%s+0x%x",PcSymbol->Name,PcOffset); } else { sprintf(PcLine,"%s",PcSymbol->Name); } } else { sprintf(PcLine,""ZERO_PTR"",Pc); }
if (SymGetSymFromAddr(hProcess, (ULONG_PTR)Va, &VaOffset, VaSymbol)) { if ( VaOffset ) { sprintf(VaLine,"%s+0x%p",VaSymbol->Name,VaOffset); } else { sprintf(VaLine,"%s",VaSymbol->Name); } } else { sprintf(VaLine,""ZERO_PTR"",Va); }
KillLog = FALSE;
if ( fCodeOnly && !CodeFault ) { KillLog = TRUE; } if ( fHardOnly && SoftFault ) { KillLog = TRUE; }
if ( !KillLog ) { if ( !fLogOnly ) { if (!fDatabase) { fprintf(stdout,"%s%s : %s\n",SoftFault ? "SOFT: " : "HARD: ",PcLine,VaLine); } else {
//Addresses are printed out in decimal
//because most databases don't support
//hex formats
fprintf(stdout,"%8d\t%s\t%s\t%s\t"ZEROD_PTR"\t%s\t%s\t"ZEROD_PTR"\n", cPfCnt, SoftFault ? "SOFT" : "HARD", PcModuleStr, PcLine, (DWORD_PTR) Pc, VaModuleStr, VaLine, (DWORD_PTR) Va); } }
if ( LogFile ) { if (!fDatabase) { fprintf(LogFile,"%s%s : %s\n",SoftFault ? "SOFT: " : "HARD: ",PcLine,VaLine); } else { fprintf(LogFile,"%8d\t%s\t%s\t%s\t"ZEROD_PTR"\t%s\t%s\t"ZEROD_PTR"\n", cPfCnt, SoftFault ? "SOFT" : "HARD", PcModuleStr, PcLine, (DWORD_PTR) Pc, VaModuleStr, VaLine, (DWORD_PTR) Va); } } DidOne = TRUE; cPfCnt++; } } i++; }
if ( DidOne ) { if ( !fLogOnly && !fDatabase) { fprintf(stdout,"\n"); } }
//If the buffer overflowed then a non-zero value for
//the Va was stored in the last record.
if (WorkingSetBuffer[i].FaultingVa) fprintf(stdout,"Warning: Page fault buffer has overflowed\n"); } }
|