#ifndef KERNRATE_H_INCLUDED #define KERNRATE_H_INCLUDED /*++ Copyright (c) 1989-2002 Microsoft Corporation --*/ // // set the debug environment // #if DBG // NTBE environment #if NDEBUG #undef NDEBUG // : assert() is defined #endif // NDEBUG #define _DEBUG // : _ASSERT(), _ASSERTE() are defined. #define DEBUG 1 // our internal file debug flag #elif _DEBUG // VC++ environment #ifndef NEBUG #define NDEBUG #endif // !NDEBUG #define DEBUG 1 // our internal file debug flag #endif // // Include System Header files // #include #include #include #include #include //The debugger team recommends using dbghelp.h rather than imagehlp.h #include #include #include #include #include #include #include //MC #include //MC #include <..\pperf\pstat.h> #include ".\kernrate.rc" // // Constant Definitions // #define DEFAULT_ZOOM_BUCKET_SIZE 16 //Minimum is 4 bytes #define DEFAULT_LOG2_ZOOM_BUCKET 4 #define MINIMUM_ZOOM_BUCKET_SIZE 4 #define DEFAULT_SOURCE_CHANGE_INTERVAL 1000 //ms #define KRATE_DEFAULT_TIMESOURCE_RATE 25000 //Events/Hit #define DEFAULT_SLEEP_INTERVAL 0 #define MAX_SYMNAME_SIZE 1024 #define USER_SYMPATH_LENGTH 512 //specified on the command line #define TOTAL_SYMPATH_LENGTH 1024 #define SYM_VALUES_BUF_SIZE 160 #define SYM_KERNEL_HANDLE (HANDLE)-1 #define SYSTEM_PROCESS_NAME "System" #define TITLE_SIZE 64 #define PROCESS_NAME_SIZE 36 //without extension #define EXT_SIZE 4 //.exe #define PROCESS_SIZE (PROCESS_NAME_SIZE+EXT_SIZE+1) #define DEFAULT_MAX_TASKS 256 #define MAX_PROC_SAME_NAME 8 #define INITIAL_STEP 2 //Symbol enumeration default address stepping #define JIT_MAX_INITIAL_STEP 16 //Managed Code symbol enumeration maximum step size (bytes) #define LOCK_CONTENTION_MIN_COUNT 1000 #define MIN_HITS_TO_DISPLAY 1 #define SECONDS_TO_DELAY_PROFILE 0 #define SECONDS_TO_WAIT_CREATED_PROC 2 #define UINT64_MAXDWORD ((unsigned __int64)0xffffffff) #define DEFAULT_TOKEN_MAX_LENGTH 12 // strlen("dcacheacces") #define DEFAULT_DESCRIPTION_MAX_LENGTH 25 // strlen("Load Linked Instructions") #define MAX_DIGITS_IN_INPUT_STRING 9 // Max. allowed digits considered valid input for a number on the command line #if defined(_IA64_)|| defined(_AMD64_) #define MAX_SIMULTANEOUS_SOURCES 4 #else #define MAX_SIMULTANEOUS_SOURCES 1 #endif #if defined(DISASM_AVAILABLE) #undefine(DISASM_AVAILABLE) #endif //MC #define MANAGED_CODE_MAINLIB "mscoree.dll" // Presence of which indicates need to handle Managed Code #define MANAGED_CODE_SYMHLPLIB "ip2md.dll" // Symbol translation helper library for Managed Code //MC // // Macros // #define WIN2K_OS (gOSInfo.dwMajorVersion == 5 && gOSInfo.dwMinorVersion == 0) #define FPRINTF (void)fprintf #define RATE_DATA_FIXED_SIZE (5*sizeof(ULONGLONG)) #define RATE_DATA_VAR_SIZE ((sizeof(ULONGLONG *)+sizeof(HANDLE *)+sizeof(ULONG *)+sizeof(PULONG *))*gProfileProcessors) #define BUCKETS_NEEDED(length) ( length%gZoomBucket == 0? (length/gZoomBucket):(1+length/gZoomBucket) ) #define MODULE_SIZE (sizeof(MODULE)+(RATE_DATA_FIXED_SIZE + RATE_DATA_VAR_SIZE)*gSourceMaximum) #define IsValidHandle( _Hdl ) ( ( (_Hdl) != (HANDLE)0 ) && ( (_Hdl) != INVALID_HANDLE_VALUE ) ) #define VerbosePrint( _x_ ) vVerbosePrint _x_ #define ModuleFileName( _Module ) \ ( (_Module)->module_FileName ? (_Module)->module_FileName : (_Module)->module_Name ) #define ModuleFullName( _Module ) \ ( (_Module)->module_FullName ? (_Module)->module_FullName : ModuleFileName( _Module ) ) // // On Itanium it turns out that you may request a rate of let's say 800 but actually get 799... // The check for an exact match in this case will fail and the logic will force the default rate // The following allows a tollerance of 25 percent to be considered as a match // #define PERCENT_DIFF(a,b) ( a > b? (100*(a-b))/b : (100*(b-a))/b ) #define RATES_MATCH(a,b) ( PERCENT_DIFF(a,b) <= 25 ) // // Struct and Enum Type Definitions and Related Globals // typedef enum _KERNRATE_NAMESPACE { cMAPANDLOAD_READONLY = TRUE, cDONOT_ALLOCATE_DESTINATION_STRING = FALSE, } eKERNRATE_NAMESPACE; typedef enum _ACTION_TYPE { START = 0, STOP = 1, OUTPUT = 2, DEFAULT= 3 } ACTION_TYPE; // // Verbose Output Related // typedef enum _VERBOSE_ENUM { VERBOSE_NONE = 0, // VERBOSE_IMAGEHLP = 0x1, // VERBOSE_PROFILING = 0x2, // VERBOSE_INTERNALS = 0x4, // VERBOSE_MODULES = 0x8, // VERBOSE_DEFAULT = VERBOSE_IMAGEHLP, VERBOSE_MAX = VERBOSE_IMAGEHLP | VERBOSE_PROFILING | VERBOSE_INTERNALS | VERBOSE_MODULES } VERBOSE_ENUM; typedef struct _VERBOSE_DEFINITION { VERBOSE_ENUM VerboseEnum; const char * const VerboseString; } VERBOSE_DEFINITION, *PVERBOSE_DEFINITION; // // Profile Source Related // typedef struct _SOURCE { PCHAR Name; // pstat EVENTID.Description KPROFILE_SOURCE ProfileSource; PCHAR ShortName; // pstat EVENTID.ShortName ULONG DesiredInterval; // system default interval ULONG Interval; // user set interval (not guaranteed) BOOL bProfileStarted; } SOURCE, *PSOURCE; typedef struct _RATE_DATA { ULONGLONG StartTime; ULONGLONG TotalTime; ULONGLONG Rate; // Events/Second ULONGLONG GrandTotalCount; ULONGLONG DoubtfulCounts; ULONGLONG *TotalCount; HANDLE *ProfileHandle; ULONG *CurrentCount; PULONG *ProfileBuffer; } RATE_DATA, *PRATE_DATA; // // Module related definitions // typedef enum _MODULE_NAMESPACE { cMODULE_NAME_STRLEN = 132, // maximum module name, including '\0' } eMODULE_NAMESPACE; typedef struct _MODULE { struct _MODULE *Next; HANDLE hProcess; ULONG64 Base; ULONG Length; BOOL bZoom; union { BOOL bProfileStarted; BOOL bHasHits; } mu; CHAR module_Name[cMODULE_NAME_STRLEN]; // filename w/o its extension PCHAR module_FileName; // filename with its extension PCHAR module_FullName; // full pathname RATE_DATA Rate[]; } MODULE, *PMODULE; typedef struct _RATE_SUMMARY { ULONGLONG TotalCount; PMODULE *Modules; ULONG ModuleCount; } RATE_SUMMARY, *PRATE_SUMMARY; // // Process related definitions // typedef struct _PROC_PERF_INFO { ULONG NumberOfThreads; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; LARGE_INTEGER ReadOperationCount; LARGE_INTEGER WriteOperationCount; LARGE_INTEGER OtherOperationCount; LARGE_INTEGER ReadTransferCount; LARGE_INTEGER WriteTransferCount; LARGE_INTEGER OtherTransferCount; SIZE_T VirtualSize; ULONG HandleCount; ULONG PageFaultCount; SIZE_T WorkingSetSize; SIZE_T QuotaPagedPoolUsage; SIZE_T QuotaNonPagedPoolUsage; SIZE_T PagefileUsage; SIZE_T PeakPagefileUsage; SIZE_T PrivatePageCount; // If ever needed the following can be added // SIZE_T PeakVirtualSize; // SIZE_T PeakWorkingSetSize; // SIZE_T QuotaPeakPagedPoolUsage; // SIZE_T QuotaPeakNonPagedPoolUsage; } PROC_PERF_INFO, *PPROC_PERF_INFO; typedef struct _PROC_TO_MONITOR { struct _PROC_TO_MONITOR *Next; HANDLE ProcessHandle; LONGLONG Pid; ULONG Index; PCHAR ProcessName; ULONG ModuleCount; ULONG ZoomCount; PMODULE ModuleList; PMODULE ZoomList; PSOURCE Source; PROC_PERF_INFO ProcPerfInfoStart; PSYSTEM_THREAD_INFORMATION pProcThreadInfoStart; PRTL_DEBUG_INFORMATION pProcDebugInfoStart; PRTL_DEBUG_INFORMATION pProcDebugInfoStop; //MC DWORD *JITHeapLocationsStart; DWORD *JITHeapLocationsStop; //MC } PROC_TO_MONITOR, *PPROC_TO_MONITOR; // // These processor level enums should be defined in public headers. // ntexapi.h - NtQuerySystemInformation( SystemProcessorInformation). // // For Now Define them locally. // typedef enum _PROCESSOR_FAMILY { IA64_FAMILY_MERCED = 0x7, IA64_FAMILY_ITANIUM = IA64_FAMILY_MERCED, IA64_FAMILY_MCKINLEY = 0x1f } PROCESSOR_FAMILY; #if defined(_IA64_) #if 0 #define IA64ProcessorLevel2ProcessorFamily( (_ProcessorLevel >> 8) & 0xff ) #else // // BUGBUG - Thierry - 02/20/2002 // Fix until SYSTEM_PROCESSOR_INFORMATION is fixed in the OS. // #ifndef CV_IA64_CPUID3 #define CV_IA64_CPUID3 3331 #endif __inline USHORT IA64ProcessorLevel2ProcessorFamily( USHORT ProcessorLevel ) { return( (USHORT)((__getReg(CV_IA64_CPUID3) >> 24) & 0xff)); } #endif #endif // _IA64_ // // The Following is Defined in pstat.h but not for Win2K // The definition below allows for single source management for Win2K and above // #ifndef PSTAT_QUERY_EVENTS_INFO #define PSTAT_QUERY_EVENTS_INFO CTL_CODE (FILE_DEVICE_UNKNOWN, 5, METHOD_NEITHER, FILE_ANY_ACCESS) typedef struct _EVENTS_INFO { ULONG Events; ULONG TokenMaxLength; ULONG DescriptionMaxLength; ULONG OfficialTokenMaxLength; ULONG OfficialDescriptionMaxLength; } EVENTS_INFO, *PEVENTS_INFO; #endif #ifndef RTL_QUERY_PROCESS_NONINVASIVE #define RTL_QUERY_PROCESS_NONINVASIVE 0x80000000 #endif // // // typedef struct _TASK_LIST { LONGLONG ProcessId; CHAR ProcessName[PROCESS_SIZE]; PSYSTEM_THREAD_INFORMATION pProcessThreadInfo; PROC_PERF_INFO ProcessPerfInfo; } TASK_LIST, *PTASK_LIST; typedef struct _TASK_LIST_ENUM { PTASK_LIST tlist; ULONG numtasks; } TASK_LIST_ENUM, *PTASK_LIST_ENUM; typedef struct _uint64div { unsigned __int64 quot; unsigned __int64 rem; } uint64div_t; typedef struct _int64div { __int64 quot; __int64 rem; } int64div_t; typedef struct _InputCount { UCHAR InputOption; SHORT Allowed; SHORT ActualCount; } InputCount; // // Globals // // static CHAR gUserSymbolPath[USER_SYMPATH_LENGTH]; static CHAR gSymbolPath[TOTAL_SYMPATH_LENGTH]; static DWORD gSymOptions; PIMAGEHLP_SYMBOL64 gSymbol; BOOL bSymPathInitialized = FALSE; // static PMODULE gCurrentModule = (PMODULE)0; PMODULE gCallbackCurrent; ULONG gZoomCount; // PSYSTEM_BASIC_INFORMATION gSysBasicInfo; LONG gProfileProcessors; //Actual being profiled KAFFINITY gAffinityMask = 0; //Processor Afinity Mask for selected processor profiling ULONG gMaxSimultaneousSources; //Maximum allowed number of sources that can be turned on simultaneously CHAR gSystemProcessName[] = SYSTEM_PROCESS_NAME; OSVERSIONINFO gOSInfo; HANDLE ghDoneEvent; BOOL gProfilingDone = FALSE; // ULONG gNumProcToMonitor = 0; //Total Number of Processes To Monitor ULONG gKernelModuleCount = 0; PPROC_TO_MONITOR gProcessList = NULL; PPROC_TO_MONITOR gpProcDummy; PPROC_TO_MONITOR gpSysProc = NULL; PMODULE gCommonZoomList = NULL; //List of Zoom Modules Common to More Than One Process such as ntdll // long double gldElapsedSeconds; ULONG gTotalElapsedSeconds; // Sum On All Processors LARGE_INTEGER gTotalElapsedTime64; LARGE_INTEGER gTotal2ElapsedTime64; // ULONG gZoomBucket = DEFAULT_ZOOM_BUCKET_SIZE; ULONG gLog2ZoomBucket = DEFAULT_LOG2_ZOOM_BUCKET; ULONG gSourceMaximum = 0; ULONG gStaticCount = 0; ULONG gTotalActiveSources = 0; PSOURCE gStaticSource = NULL; // ULONG gNumTasksStart; ULONG gNumTasksStop; PTASK_LIST gTlistStart; double gTotalIdleTime = 0; //MC BOOL bMCHelperLoaded = FALSE; //Is Managed Code Helper Library Loaded BOOL bMCJitRangesExist = FALSE; //Were any JIT ranges found BOOL bImageHlpSymbolFound = FALSE; //SymEnumerateSymbols64 found at least one symbol HANDLE ghMCLib = NULL; //Handle to MC helper IP2MC.DLL WCHAR* gwszSymbol; //MC // // Print format for event strings // ULONG gTokenMaxLen = DEFAULT_TOKEN_MAX_LENGTH; ULONG gDescriptionMaxLen = DEFAULT_DESCRIPTION_MAX_LENGTH; // //Verbose Output related // VERBOSE_DEFINITION VerboseDefinition[] = { { VERBOSE_NONE, "None" }, { VERBOSE_IMAGEHLP, "Displays ImageHlp Operations" }, { VERBOSE_PROFILING, "Displays Profiling Operations and Per Bucket Information Including Symbol Verification" }, { VERBOSE_INTERNALS, "Displays Internals Operations" }, { VERBOSE_MODULES, "Displays Modules Operations" }, { VERBOSE_NONE, NULL } }; ULONG gVerbose = VERBOSE_NONE; BOOL bRoundingVerboseOutput = FALSE; // // User command-line input related // typedef enum _INPUT_ERROR_TYPE { INPUT_GOOD = 1, UNKNOWN_OPTION, BOGUS_ENTRY, MISSING_PARAMETER, MISSING_NUMBER, MISSING_REQUIRED_NUMBER, MISSING_STRING, MISSING_REQUIRED_STRING, INVALID_NUMBER } INPUT_ERROR_TYPE; typedef enum _INPUT_ORDER { ORDER_ANY, ORDER_STRING_FIRST, ORDER_NUMBER_FIRST } INPUT_ORDER; typedef enum _INPUT_OPTIONAL { OPTIONAL_ANY, OPTIONAL_STRING, OPTIONAL_NUMBER, OPTIONAL_NONE, } INPUT_OPTIONAL; BOOL bCombinedProfile = FALSE; // Do Both Kernel and User Process(es) LONG gChangeInterval = DEFAULT_SOURCE_CHANGE_INTERVAL; BOOL bWaitForUserInput = FALSE; // Wait for the user to press a key before starting the profile BOOL bWaitCreatedProcToSettle = FALSE; // Indication that one or more processes were created via the -o option BOOL bCreatedProcWaitForUserInput = FALSE; // Wait for the user to press a key to indicate a created process has settled (gone idle) LONG gSecondsToDelayProfile = SECONDS_TO_DELAY_PROFILE; // Wait for N seconds before starting the profile LONG gSecondsToWaitCreatedProc = SECONDS_TO_WAIT_CREATED_PROC; // Wait for N seconds for a created process to settle (go idle) LONG gSleepInterval = DEFAULT_SLEEP_INTERVAL; //Used to set the profile period BOOL bRawData = FALSE; BOOL bRawDisasm = FALSE; BOOL bProfileByProcessor = FALSE; BOOL bGetInterestingData = FALSE; // Get Interesting statistics (turns on several sources, depends on hits, not guaratied) BOOL bOldSampling = FALSE; // Use new sampling scheme (start all sources and let them run simultaneously) BOOL bIncludeGeneralInfo = TRUE; // Include system-wide and process-specific information (such as context switches, memory usage, etc.) BOOL bDisplayTaskSummary = FALSE; ULONG gMaxTasks = DEFAULT_MAX_TASKS; //Max Number of tasks accomodated in Kernrate's Task List BOOL bIncludeSystemLocksInfo = FALSE; // Get System lock contention info BOOL bIncludeUserProcLocksInfo= FALSE; // Get User process lock contention info ULONG gLockContentionMinCount = LOCK_CONTENTION_MIN_COUNT; // Default minimum count of lock contention for output processing ULONG gMinHitsToDisplay = MIN_HITS_TO_DISPLAY; BOOL bProcessDataHighPriority = FALSE; // User may opt to finish processing the collected data at high priority // This is useful on a very busy system if the momentary overhead is not an issue BOOL bSystemThreadsInfo = FALSE; // System-Process (kernel mode) threads BOOL bIncludeThreadsInfo = FALSE; // Get thread info (it will then be gathered for all running tasks) HANDLE ghInput = NULL, ghOutput = NULL, ghError = NULL; // // Most Static Sources desired intervals are computed to give approximately // one interrupt per millisecond and be a nice even power of 2 // enum _STATIC_SOURCE_TYPE { SOURCE_TIME = 0, }; // The following are defined in several headers, // were supported on ALPHA, but they currently have no x86 KE/HAL support except for Time and AlignFixup // Merced.c and Mckinley.c define the supported static sources on IA64 Merced/McKinley systems // Amd64.c defines the supported static sources on Amd64 systems SOURCE StaticSources[] = { {"Time", ProfileTime, "time" , 1000, KRATE_DEFAULT_TIMESOURCE_RATE}, {"Alignment Fixup", ProfileAlignmentFixup, "alignfixup" , 1,0}, {"Total Issues", ProfileTotalIssues, "totalissues", 131072,0}, {"Pipeline Dry", ProfilePipelineDry, "pipelinedry", 131072,0}, {"Load Instructions", ProfileLoadInstructions, "loadinst" , 65536,0}, {"Pipeline Frozen", ProfilePipelineFrozen, "pilelinefrz", 131072,0}, {"Branch Instructions", ProfileBranchInstructions, "branchinst" , 65536,0}, {"Total Nonissues", ProfileTotalNonissues, "totalnoniss", 131072,0}, {"Dcache Misses", ProfileDcacheMisses, "dcachemiss" , 16384,0}, {"Icache Misses", ProfileIcacheMisses, "icachemiss" , 16384,0}, {"Cache Misses", ProfileCacheMisses, "cachemiss" , 16384,0}, {"Branch Mispredictions", ProfileBranchMispredictions, "branchpred" , 16384,0}, {"Store Instructions", ProfileStoreInstructions, "storeinst" , 65536,0}, {"Floating Point Instr", ProfileFpInstructions, "fpinst" , 65536,0}, {"Integer Instructions", ProfileIntegerInstructions, "intinst" , 65536,0}, {"Dual Issues", Profile2Issue, "2issue" , 65536,0}, {"Triple Issues", Profile3Issue, "3issue" , 16384,0}, {"Quad Issues", Profile4Issue, "4issue" , 16384,0}, {"Special Instructions", ProfileSpecialInstructions, "specinst" , 16384,0}, {"Cycles", ProfileTotalCycles, "totalcycles", 655360,0}, {"Icache Issues", ProfileIcacheIssues, "icacheissue", 65536,0}, {"Dcache Accesses", ProfileDcacheAccesses, "dcacheacces", 65536,0}, {"MB Stall Cycles", ProfileMemoryBarrierCycles, "membarcycle", 32767,0}, {"Load Linked Instructions", ProfileLoadLinkedIssues, "loadlinkiss", 16384,0}, {NULL, ProfileMaximum, "", 0, 0} }; #if defined(_IA64_) #include "merced.c" #include "mckinley.c" #endif // _IA64_ #if defined(_AMD64_) #include "amd64.c" #endif // _AMD64_ // // "Interesting Data" constituents // KPROFILE_SOURCE IData[] = { #if defined(_IA64_) ProfileTotalIssues, //This source must always be first in the array ProfileLoadInstructions, ProfileStoreInstructions, ProfileBranchInstructions, ProfileFpInstructions, ProfileIntegerInstructions, ProfileCacheMisses, ProfileIcacheMisses, ProfileDcacheMisses, ProfileBranchMispredictions, ProfileTotalCycles #elif defined(_AMD64_) ProfileTotalIssues, ProfileBranchInstructions, ProfileFpInstructions, ProfileIcacheMisses, ProfileDcacheMisses, ProfileBranchMispredictions #else ProfileTotalIssues #endif }; PULONG gulActiveSources; // // For checking command line input options for unallowed duplicates // (0=no such option, -1=unlimited, -2 don't care) // InputCount InputOption[] = { { 'A', 1, 0 }, { 'B', 1, 0 }, { 'C', 1, 0 }, { 'D',-2, 0 }, { 'E',-2, 0 }, { 'F',-2, 0 }, { 'G', 1, 0 }, { 'H',-2, 0 }, { 'I',-1, 0 }, { 'J', 1, 0 }, { 'K', 1, 0 }, { 'L', 1, 0 }, { 'M', 1, 0 }, { 'N',-1, 0 }, { 'O',-1, 0 }, { 'P',-1, 0 }, { 'Q', 0, 0 }, { 'R',-2, 0 }, { 'S', 1, 0 }, { 'T', 1, 0 }, { 'U',-2, 0 }, { 'V',-1, 0 }, { 'W', 2, 0 }, { 'X', 1, 0 }, { 'Y', 0, 0 }, { 'Z',-1, 0 } }; InputCount wCount = {'W', 1, 0}; InputCount wpCount = {'W', 1, 0}; // // Function prototypes // VOID CleanZoomModuleList( PPROC_TO_MONITOR Proc ); VOID CreateDoneEvent( VOID ); //MC BOOL CreateJITZoomModuleCallback( IN PWCHAR wszSymName, IN LPSTR szSymName, IN ULONG64 Address, IN ULONG Size, IN PVOID Cxt ); //MC PMODULE CreateNewModule( IN PPROC_TO_MONITOR ProcToMonitor, IN PCHAR ModuleName, IN PCHAR ModuleFullName, IN ULONG64 ImageBase, IN ULONG ImageSize ); VOID CreateProfiles( IN PMODULE Root, IN PPROC_TO_MONITOR ProcToMonitor ); VOID CreateZoomedModuleList( IN PMODULE ZoomModule, IN ULONG RoundDown, IN PPROC_TO_MONITOR pProc ); BOOL CreateZoomModuleCallback( IN LPSTR szSymName, IN ULONG64 Address, IN ULONG Size, IN PVOID Cxt ); VOID DisplayRunningTasksSummary ( PTASK_LIST pTaskStart, PTASK_LIST pTaskStop ); VOID DisplaySystemWideInformation( PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemInfoBegin, PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemInfoEnd ); VOID DisplayTotalAndRate ( LONGLONG StartCount, LONGLONG StopCount, long double RateAgainst, PCHAR CounterName, PCHAR RateAgainstUnits ); BOOL EnumerateSymbolsByBuckets( IN HANDLE SymHandle, IN PMODULE Current, IN PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback, IN PVOID pProc ); VOID ExecuteProfiles( BOOL bMode ); VOID ExitWithMissingEntryMessage( PCHAR CurrentOption, PCHAR Remark, BOOL bUsage ); VOID ExitWithUnknownOptionMessage( PCHAR CurrentOption ); PMODULE FindModuleForAddress64( PPROC_TO_MONITOR ProcToMonitor, DWORD64 Address ); VOID GetConfiguration( int argc, char *argv[] ); PMODULE GetKernelModuleInformation( VOID ); VOID GetProcessLocksInformation ( PPROC_TO_MONITOR ProcToMonitor, ULONG Flags, ACTION_TYPE Action ); PMODULE GetProcessModuleInformation( IN PPROC_TO_MONITOR ProcToMonitor ); VOID GetProfileSystemInfo( ACTION_TYPE Action ); PSYSTEM_BASIC_INFORMATION GetSystemBasicInformation( VOID ); VOID GetSystemLocksInformation ( ACTION_TYPE Action ); DWORD GetTaskList( PTASK_LIST pTask, ULONG NumTasks ); ULONG HandleRedirections( IN PCHAR cmdLine, IN ULONG nCharsStart, OUT HANDLE *hInput, OUT HANDLE *hOutput, OUT HANDLE *hError ); BOOL HitsFound( IN PPROC_TO_MONITOR pProc, IN ULONG BucketIndex ); VOID InitAllProcessesModulesInfo( VOID ); BOOL InitializeAsDebugger(VOID); BOOL InitializeKernelProfile(VOID); VOID InitializeKernrate( int argc, char *argv[] ); PPROC_TO_MONITOR InitializeProcToMonitor( LONGLONG Pid ); ULONG InitializeProfileSourceInfo ( PPROC_TO_MONITOR ProcToMonitor ); VOID InitSymbolPath( HANDLE SymHandle ); VOID InvalidEntryMessage( PCHAR CurrentOption, PCHAR CurrentValue, PCHAR Remark, BOOL bUsage, BOOL bExit ); INPUT_ERROR_TYPE IsInputValid(int argc, int OptionIndex, PCHAR *Option, PCHAR AllowedTrailLetters, PLONG AssociatedNumber, PCHAR AssociatedString, ULONG MaxStringLength, INPUT_ORDER Order, INPUT_OPTIONAL Optional ); BOOL IsStringANumber( IN PCHAR String ); ULONG NextSource( IN ULONG CurrentSource, IN PMODULE ModuleList, IN PPROC_TO_MONITOR ProcToMonitor ); VOID OutputInterestingData( IN FILE *Out, IN RATE_DATA Data[] ); VOID OutputLine( IN FILE *Out, IN ULONG ProfileSourceIndex, IN PMODULE Module, IN PRATE_SUMMARY RateSummary, IN PPROC_TO_MONITOR ProcToMonitor ); VOID OutputLineFromAddress64( HANDLE hProc, DWORD64 qwAddr, PIMAGEHLP_LINE64 pLine ); VOID OutputLocksInformation( PRTL_PROCESS_LOCKS pLockInfoStart, PRTL_PROCESS_LOCKS pLockInfoStop, PPROC_TO_MONITOR Proc ); VOID OutputModuleList( IN FILE *Out, IN PMODULE ModuleList, IN ULONG NumberModules, IN PPROC_TO_MONITOR ProcToMonitor, IN PMODULE Parent ); VOID OutputPercentValue ( LONGLONG StartCount, LONGLONG StopCount, LARGE_INTEGER Base, PCHAR CounterName ); VOID OutputProcessPerfInfo ( PTASK_LIST pTask, ULONG NumTasks, PPROC_TO_MONITOR ProcToMonitor ); VOID OutputRawDataForZoomModule( IN FILE *Out, IN PPROC_TO_MONITOR ProcToMonitor, IN PMODULE Current ); VOID OutputResults( IN FILE *Out, IN PPROC_TO_MONITOR ProcToMonitor ); VOID OutputStartStopValues ( SIZE_T StartCount, SIZE_T StopCount, PCHAR CounterName ); VOID OutputThreadInfo ( PTASK_LIST pTask, DWORD TaskNumber, PPROC_TO_MONITOR ProcToMonitor ); BOOL PrivEnumerateSymbols( IN HANDLE SymHandle, IN PMODULE Current, IN PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback, IN PVOID pProc, IN DWORD64 BaseOptional, IN ULONG SizeOptional ); VOID SetProfileSourcesRates( PPROC_TO_MONITOR ProcToMonitor ); VOID StartSource( IN ULONG ProfileSource, IN PMODULE ModuleList, IN PPROC_TO_MONITOR ProcToMonitor ); VOID StopSource( IN ULONG ProfileSourceIndex, IN PMODULE ModuleList, IN PPROC_TO_MONITOR ProcToMonitor ); BOOL TkEnumerateSymbols( IN HANDLE SymHandle, IN PMODULE Current, IN PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback, IN PVOID pProc ); VOID UpdateProcessStartInfo( PPROC_TO_MONITOR ProcToMonitor, PTASK_LIST TaskListEntry, BOOL bIncludeProcessThreadsInfo ); VOID vVerbosePrint( ULONG Level, PCCHAR Msg, ... ); //MC // // Note: CLR currently does not support 64 bit. // // AttachToProcess is not reentrant, even for different PIDs! // only call once and pair with DetachFromProcess. extern void AttachToProcess(DWORD dwPid); extern void DetachFromProcess(); // 0 is error // 1 is normal JIT // 2 is ngen (prejitted module) // wszResult contains class/method (string) of given IP address // Note: The space is allocated by the routine itself! extern int IP2MD(DWORD_PTR test,WCHAR** wszResult); // return value is array of DWORDs, stored in pairs, null terminated. // first dword is start address, second dword is length. extern DWORD* GetJitRange(); typedef void (*PFN1)(DWORD); PFN1 pfnAttachToProcess; typedef void (*PFN2)(VOID); PFN2 pfnDetachFromProcess; typedef int (*PFN3)(DWORD_PTR, WCHAR**); PFN3 pfnIP2MD; typedef DWORD* (*PFN4)(VOID); PFN4 pfnGetJitRange; BOOL InitializeManagedCodeSupport( PPROC_TO_MONITOR ProcToMonitor ); BOOL JITEnumerateSymbols( IN PMODULE Current, IN PVOID pProc, IN DWORD64 BaseOptional, IN ULONG SizeOptional ); VOID OutputJITRangeComparison( PPROC_TO_MONITOR ProcToMonitor ); //MC PCHAR WaitReason [] = { {"Executive"}, {"FreePage"}, {"PageIn"}, {"PoolAllocation"}, {"DelayExecution"}, {"Suspended"}, {"UserRequest"}, {"WrExecutive"}, {"WrFreePage"}, {"WrPageIn"}, {"WrPoolAllocation"}, {"WrDelayExecution"}, {"WrSuspended"}, {"WrUserRequest"}, {"WrEventPair"}, {"WrQueue"}, {"WrLpcReceive"}, {"WrLpcReply"}, {"WrVirtualMemory"}, {"WrPageOut"}, {"WrRendezvous"}, {"Spare2"}, {"Spare3"}, {"Spare4"}, {"Spare5"}, {"Spare6"}, {"WrKernel"}, {"WrResource"}, {"WrPushLock"}, {"WrMutex"}, {"WrQuantumEnd"}, {"WrDispatchInt"}, {"WrPreempted"}, {"WrYieldExecution"}, {"MaximumWaitReason"} }; PCHAR ThreadState[] = { {"Initialized"}, {"Ready"}, {"Running"}, {"Standby"}, {"Terminated"}, {"Waiting"}, {"Transition"}, {"DeferredReady"} }; #endif /* !KERNRATE_H_INCLUDED */