Windows NT 4.0 source code leak
 
 
 
 
 
 

240 lines
5.6 KiB

/*++
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
#include "search.h"
int _CRTAPI1
HashCompare(
const void * Element1,
const void * Element2
);
DECLARE_API( calldata )
/*++
Routine Description:
Dump call data hash table
Arguments:
arg - name-of-has-table
Return Value:
None
--*/
{
UCHAR Buffer[80];
ULONG Displacement;
ULONG End;
CALL_HASH_ENTRY HashEntry;
ULONG Index;
ULONG CallData;
CALL_PERFORMANCE_DATA CallDataContents;
PLIST_ENTRY Next;
ULONG Result;
UCHAR TableName[80];
PCALL_HASH_ENTRY CallerArray;
ULONG NumberCallers = 0;
ULONG ArraySize = 1000;
//
// 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;
}
//
// Get the address of the specified call performance data and read the
// contents of the structure.
//
strcpy(&TableName[0], args);
dprintf("**** Dump Call Performance Data For %s ****\n\n", &TableName[0]);
CallData = GetExpression(&TableName[0]);
if ((CallData == 0) ||
(ReadMemory((DWORD)CallData,
&CallDataContents,
sizeof(CALL_PERFORMANCE_DATA),
&Result) == FALSE)) {
//
// The target build does not support specified call performance data.
//
dprintf("%08lx: No call performance data available\n", Result);
} else {
//
// Dump the specified call data.
//
CallerArray = LocalAlloc(LMEM_FIXED, sizeof(CALL_HASH_ENTRY) * ArraySize);
if (CallerArray==NULL) {
dprintf("Couldn't allocate memory for caller array\n");
return;
}
dprintf("Loading data");
for (Index = 0; Index < CALL_HASH_TABLE_SIZE; Index += 1) {
End = FIELD_OFFSET(CALL_PERFORMANCE_DATA, HashTable) +
CallData + sizeof(LIST_ENTRY) * Index;
Next = CallDataContents.HashTable[Index].Flink;
while ((ULONG)Next != End) {
if (ReadMemory((DWORD)Next,
&HashEntry,
sizeof(CALL_HASH_ENTRY),
&Result) != FALSE) {
CallerArray[NumberCallers++] = HashEntry;
if (NumberCallers == ArraySize) {
//
// Grow the caller array
//
PCALL_HASH_ENTRY NewArray;
ArraySize = ArraySize * 2;
NewArray = LocalAlloc(LMEM_FIXED, sizeof(CALL_HASH_ENTRY) * ArraySize);
if (NewArray == NULL) {
dprintf("Couldn't allocate memory to extend caller array\n");
LocalFree(CallerArray);
return;
}
CopyMemory(NewArray, CallerArray, sizeof(CALL_HASH_ENTRY) * NumberCallers);
LocalFree(CallerArray);
CallerArray = NewArray;
}
if ((NumberCallers % 10) == 0) {
dprintf(".");
}
}
Next = HashEntry.ListEntry.Flink;
if (CheckControlC()) {
LocalFree(CallerArray);
return;
}
}
if (CheckControlC()) {
return;
}
}
qsort((PVOID)CallerArray,
NumberCallers,
sizeof(CALL_HASH_ENTRY),
HashCompare);
dprintf("\n Number Caller/Caller's Caller\n\n");
for (Index = 0; Index < NumberCallers; Index++) {
GetSymbol(CallerArray[Index].CallersAddress,
&Buffer[0],
&Displacement);
dprintf("%10d %s", CallerArray[Index].CallCount, &Buffer[0]);
if (Displacement != 0) {
dprintf("+0x%x", Displacement);
}
if (CallerArray[Index].CallersCaller != NULL) {
dprintf("\n");
GetSymbol(CallerArray[Index].CallersCaller,
&Buffer[0],
&Displacement);
dprintf(" %s", &Buffer[0]);
if (Displacement != 0) {
dprintf("+0x%x", Displacement);
}
}
dprintf("\n");
if (CheckControlC()) {
break;
}
}
LocalFree(CallerArray);
}
return;
}
int _CRTAPI1
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_ENTRY Hash1 = (PCALL_HASH_ENTRY)Element1;
PCALL_HASH_ENTRY Hash2 = (PCALL_HASH_ENTRY)Element2;
if (Hash1->CallCount < Hash2->CallCount) {
return(1);
}
else if (Hash1->CallCount > Hash2->CallCount) {
return(-1);
} else {
return(0);
}
}