|
|
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
calldata.c
Abstract:
WinDbg Extension Api
Author:
David N. Cutler (davec) 22-May-1994
Environment:
User Mode.
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
typedef struct CALL_HASH_READ { ULONG64 CallersAddress; ULONG64 CallersCaller; ULONG CallCount; } CALL_HASH_READ, *PCALL_HASH_READ;
int __cdecl HashCompare( const void * Element1, const void * Element2 );
DECLARE_API( calldata )
/*++
Routine Description:
Dump call data hash table
Arguments:
arg - name-of-hash-table
Return Value:
None
--*/
{ UCHAR Buffer[256]; ULONG64 Displacement=0; ULONG64 End=0; ULONG Index; ULONG64 CallData; ULONG64 Next; ULONG Result; UCHAR TableName[80]; PCALL_HASH_READ CallerArray; ULONG NumberCallers = 0; ULONG ArraySize = 1000; ULONG64 HashTable_Flink;
//
// If a table name was not specified, then don't attempt to dump the
// table.
//
if (args[0] == '\0') { dprintf("A call data table name must be specified\n"); return E_INVALIDARG; }
//
// Get the address of the specified call performance data and read the
// contents of the structure.
//
if (StringCchCopy(&TableName[0], sizeof(TableName), args) != S_OK) { TableName[0] = 0; } dprintf("**** Dump Call Performance Data For %s ****\n\n", &TableName[0]); CallData = GetExpression(&TableName[0]); if ((CallData == 0) || (GetFieldValue(CallData, "_CALL_PERFORMANCE_DATA", "HashTable.Flink", HashTable_Flink) != FALSE)) {
//
// The target build does not support specified call performance data.
//
dprintf("%08p: No call performance data available\n", CallData);
} else { ULONG HashTableOffset; GetFieldOffset("_CALL_PERFORMANCE_DATA", "HashTable", &HashTableOffset);
//
// Dump the specified call data.
//
CallerArray = LocalAlloc(LMEM_FIXED, sizeof(CALL_HASH_READ) * ArraySize); if (CallerArray==NULL) { dprintf("Couldn't allocate memory for caller array\n"); return E_INVALIDARG; }
dprintf("Loading data"); for (Index = 0; Index < CALL_HASH_TABLE_SIZE; Index += 1) { UCHAR CallHash[] = "_CALL_HASH_ENTRY";
End = HashTableOffset + CallData + GetTypeSize("_LIST_ENTRY") * Index;
GetFieldValue(End, "_LIST_ENTRY", "Flink", Next);
while (Next != End) { if (!GetFieldValue(Next, CallHash, "CallersCaller", CallerArray[NumberCallers].CallersCaller) && !GetFieldValue(Next, CallHash, "CallersAddress", CallerArray[NumberCallers].CallersAddress) && !GetFieldValue(Next, CallHash, "CallCount", CallerArray[NumberCallers].CallCount)) {
NumberCallers++;
if (NumberCallers == ArraySize) {
//
// Grow the caller array
//
PCALL_HASH_READ NewArray;
ArraySize = ArraySize * 2; NewArray = LocalAlloc(LMEM_FIXED, sizeof(CALL_HASH_READ) * ArraySize); if (NewArray == NULL) { dprintf("Couldn't allocate memory to extend caller array\n"); LocalFree(CallerArray); return E_INVALIDARG; } CopyMemory(NewArray, CallerArray, sizeof(CALL_HASH_READ) * NumberCallers); LocalFree(CallerArray); CallerArray = NewArray; }
if ((NumberCallers % 10) == 0) { dprintf("."); } }
GetFieldValue(Next, CallHash, "ListEntry.Flink", Next); if (CheckControlC()) { LocalFree(CallerArray); return E_INVALIDARG; } } if (CheckControlC()) { return E_INVALIDARG; } }
qsort((PVOID)CallerArray, NumberCallers, sizeof(CALL_HASH_READ), HashCompare);
dprintf("\n Number Caller/Caller's Caller\n\n");
for (Index = 0; Index < NumberCallers; Index++) { GetSymbol(CallerArray[Index].CallersAddress, Buffer, &Displacement);
dprintf("%10d %s", CallerArray[Index].CallCount, Buffer); if (Displacement != 0) { dprintf("+0x%1p", Displacement); }
if (CallerArray[Index].CallersCaller != 0) { dprintf("\n"); GetSymbol(CallerArray[Index].CallersCaller, Buffer, &Displacement);
dprintf(" %s", Buffer); if (Displacement != 0) { dprintf("+0x%1p", Displacement); } } dprintf("\n"); if (CheckControlC()) { break; } }
LocalFree(CallerArray); }
return S_OK; }
int __cdecl HashCompare( const void * Element1, const void * Element2 )
/*++
Routine Description:
Provides a comparison of hash elements for the qsort library function
Arguments:
Element1 - Supplies pointer to the key for the search
Element2 - Supplies element to be compared to the key
Return Value:
> 0 - Element1 < Element2 = 0 - Element1 == Element2 < 0 - Element1 > Element2
--*/
{ PCALL_HASH_READ Hash1 = (PCALL_HASH_READ)Element1; PCALL_HASH_READ Hash2 = (PCALL_HASH_READ)Element2;
if (Hash1->CallCount < Hash2->CallCount) { return(1); } else if (Hash1->CallCount > Hash2->CallCount) { return(-1); } else { return(0); }
}
|