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.

245 lines
5.9 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. calldata.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. David N. Cutler (davec) 22-May-1994
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. typedef struct CALL_HASH_READ {
  16. ULONG64 CallersAddress;
  17. ULONG64 CallersCaller;
  18. ULONG CallCount;
  19. } CALL_HASH_READ, *PCALL_HASH_READ;
  20. int __cdecl
  21. HashCompare(
  22. const void * Element1,
  23. const void * Element2
  24. );
  25. DECLARE_API( calldata )
  26. /*++
  27. Routine Description:
  28. Dump call data hash table
  29. Arguments:
  30. arg - name-of-hash-table
  31. Return Value:
  32. None
  33. --*/
  34. {
  35. UCHAR Buffer[256];
  36. ULONG64 Displacement=0;
  37. ULONG64 End=0;
  38. ULONG Index;
  39. ULONG64 CallData;
  40. ULONG64 Next;
  41. ULONG Result;
  42. UCHAR TableName[80];
  43. PCALL_HASH_READ CallerArray;
  44. ULONG NumberCallers = 0;
  45. ULONG ArraySize = 1000;
  46. ULONG64 HashTable_Flink;
  47. //
  48. // If a table name was not specified, then don't attempt to dump the
  49. // table.
  50. //
  51. if (args[0] == '\0') {
  52. dprintf("A call data table name must be specified\n");
  53. return E_INVALIDARG;
  54. }
  55. //
  56. // Get the address of the specified call performance data and read the
  57. // contents of the structure.
  58. //
  59. strcpy(&TableName[0], args);
  60. dprintf("**** Dump Call Performance Data For %s ****\n\n", &TableName[0]);
  61. CallData = GetExpression(&TableName[0]);
  62. if ((CallData == 0) ||
  63. (GetFieldValue(CallData, "_CALL_PERFORMANCE_DATA", "HashTable.Flink", HashTable_Flink)
  64. != FALSE)) {
  65. //
  66. // The target build does not support specified call performance data.
  67. //
  68. dprintf("%08p: No call performance data available\n", CallData);
  69. } else {
  70. ULONG HashTableOffset;
  71. GetFieldOffset("_CALL_PERFORMANCE_DATA", "HashTable", &HashTableOffset);
  72. //
  73. // Dump the specified call data.
  74. //
  75. CallerArray = LocalAlloc(LMEM_FIXED, sizeof(CALL_HASH_READ) * ArraySize);
  76. if (CallerArray==NULL) {
  77. dprintf("Couldn't allocate memory for caller array\n");
  78. return E_INVALIDARG;
  79. }
  80. dprintf("Loading data");
  81. for (Index = 0; Index < CALL_HASH_TABLE_SIZE; Index += 1) {
  82. UCHAR CallHash[] = "_CALL_HASH_ENTRY";
  83. End = HashTableOffset + CallData + GetTypeSize("_LIST_ENTRY") * Index;
  84. GetFieldValue(End, "_LIST_ENTRY", "Flink", Next);
  85. while (Next != End) {
  86. if (!GetFieldValue(Next, CallHash, "CallersCaller", CallerArray[NumberCallers].CallersCaller) &&
  87. !GetFieldValue(Next, CallHash, "CallersAddress", CallerArray[NumberCallers].CallersAddress) &&
  88. !GetFieldValue(Next, CallHash, "CallCount", CallerArray[NumberCallers].CallCount)) {
  89. NumberCallers++;
  90. if (NumberCallers == ArraySize) {
  91. //
  92. // Grow the caller array
  93. //
  94. PCALL_HASH_READ NewArray;
  95. ArraySize = ArraySize * 2;
  96. NewArray = LocalAlloc(LMEM_FIXED, sizeof(CALL_HASH_READ) * ArraySize);
  97. if (NewArray == NULL) {
  98. dprintf("Couldn't allocate memory to extend caller array\n");
  99. LocalFree(CallerArray);
  100. return E_INVALIDARG;
  101. }
  102. CopyMemory(NewArray, CallerArray, sizeof(CALL_HASH_READ) * NumberCallers);
  103. LocalFree(CallerArray);
  104. CallerArray = NewArray;
  105. }
  106. if ((NumberCallers % 10) == 0) {
  107. dprintf(".");
  108. }
  109. }
  110. GetFieldValue(Next, CallHash, "ListEntry.Flink", Next);
  111. if (CheckControlC()) {
  112. LocalFree(CallerArray);
  113. return E_INVALIDARG;
  114. }
  115. }
  116. if (CheckControlC()) {
  117. return E_INVALIDARG;
  118. }
  119. }
  120. qsort((PVOID)CallerArray,
  121. NumberCallers,
  122. sizeof(CALL_HASH_READ),
  123. HashCompare);
  124. dprintf("\n Number Caller/Caller's Caller\n\n");
  125. for (Index = 0; Index < NumberCallers; Index++) {
  126. GetSymbol(CallerArray[Index].CallersAddress,
  127. Buffer,
  128. &Displacement);
  129. dprintf("%10d %s", CallerArray[Index].CallCount, Buffer);
  130. if (Displacement != 0) {
  131. dprintf("+0x%1p", Displacement);
  132. }
  133. if (CallerArray[Index].CallersCaller != 0) {
  134. dprintf("\n");
  135. GetSymbol(CallerArray[Index].CallersCaller,
  136. Buffer,
  137. &Displacement);
  138. dprintf(" %s", Buffer);
  139. if (Displacement != 0) {
  140. dprintf("+0x%1p", Displacement);
  141. }
  142. }
  143. dprintf("\n");
  144. if (CheckControlC()) {
  145. break;
  146. }
  147. }
  148. LocalFree(CallerArray);
  149. }
  150. return S_OK;
  151. }
  152. int __cdecl
  153. HashCompare(
  154. const void * Element1,
  155. const void * Element2
  156. )
  157. /*++
  158. Routine Description:
  159. Provides a comparison of hash elements for the qsort library function
  160. Arguments:
  161. Element1 - Supplies pointer to the key for the search
  162. Element2 - Supplies element to be compared to the key
  163. Return Value:
  164. > 0 - Element1 < Element2
  165. = 0 - Element1 == Element2
  166. < 0 - Element1 > Element2
  167. --*/
  168. {
  169. PCALL_HASH_READ Hash1 = (PCALL_HASH_READ)Element1;
  170. PCALL_HASH_READ Hash2 = (PCALL_HASH_READ)Element2;
  171. if (Hash1->CallCount < Hash2->CallCount) {
  172. return(1);
  173. }
  174. else if (Hash1->CallCount > Hash2->CallCount) {
  175. return(-1);
  176. } else {
  177. return(0);
  178. }
  179. }