Leaked source code of windows server 2003
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.

247 lines
6.2 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. if (StringCchCopy(&TableName[0], sizeof(TableName), args) != S_OK)
  60. {
  61. TableName[0] = 0;
  62. }
  63. dprintf("**** Dump Call Performance Data For %s ****\n\n", &TableName[0]);
  64. CallData = GetExpression(&TableName[0]);
  65. if ((CallData == 0) ||
  66. (GetFieldValue(CallData, "_CALL_PERFORMANCE_DATA", "HashTable.Flink", HashTable_Flink)
  67. != FALSE)) {
  68. //
  69. // The target build does not support specified call performance data.
  70. //
  71. dprintf("%08p: No call performance data available\n", CallData);
  72. } else {
  73. ULONG HashTableOffset;
  74. GetFieldOffset("_CALL_PERFORMANCE_DATA", "HashTable", &HashTableOffset);
  75. //
  76. // Dump the specified call data.
  77. //
  78. CallerArray = LocalAlloc(LMEM_FIXED, sizeof(CALL_HASH_READ) * ArraySize);
  79. if (CallerArray==NULL) {
  80. dprintf("Couldn't allocate memory for caller array\n");
  81. return E_INVALIDARG;
  82. }
  83. dprintf("Loading data");
  84. for (Index = 0; Index < CALL_HASH_TABLE_SIZE; Index += 1) {
  85. UCHAR CallHash[] = "_CALL_HASH_ENTRY";
  86. End = HashTableOffset + CallData + GetTypeSize("_LIST_ENTRY") * Index;
  87. GetFieldValue(End, "_LIST_ENTRY", "Flink", Next);
  88. while (Next != End) {
  89. if (!GetFieldValue(Next, CallHash, "CallersCaller", CallerArray[NumberCallers].CallersCaller) &&
  90. !GetFieldValue(Next, CallHash, "CallersAddress", CallerArray[NumberCallers].CallersAddress) &&
  91. !GetFieldValue(Next, CallHash, "CallCount", CallerArray[NumberCallers].CallCount)) {
  92. NumberCallers++;
  93. if (NumberCallers == ArraySize) {
  94. //
  95. // Grow the caller array
  96. //
  97. PCALL_HASH_READ NewArray;
  98. ArraySize = ArraySize * 2;
  99. NewArray = LocalAlloc(LMEM_FIXED, sizeof(CALL_HASH_READ) * ArraySize);
  100. if (NewArray == NULL) {
  101. dprintf("Couldn't allocate memory to extend caller array\n");
  102. LocalFree(CallerArray);
  103. return E_INVALIDARG;
  104. }
  105. CopyMemory(NewArray, CallerArray, sizeof(CALL_HASH_READ) * NumberCallers);
  106. LocalFree(CallerArray);
  107. CallerArray = NewArray;
  108. }
  109. if ((NumberCallers % 10) == 0) {
  110. dprintf(".");
  111. }
  112. }
  113. GetFieldValue(Next, CallHash, "ListEntry.Flink", Next);
  114. if (CheckControlC()) {
  115. LocalFree(CallerArray);
  116. return E_INVALIDARG;
  117. }
  118. }
  119. if (CheckControlC()) {
  120. return E_INVALIDARG;
  121. }
  122. }
  123. qsort((PVOID)CallerArray,
  124. NumberCallers,
  125. sizeof(CALL_HASH_READ),
  126. HashCompare);
  127. dprintf("\n Number Caller/Caller's Caller\n\n");
  128. for (Index = 0; Index < NumberCallers; Index++) {
  129. GetSymbol(CallerArray[Index].CallersAddress,
  130. Buffer,
  131. &Displacement);
  132. dprintf("%10d %s", CallerArray[Index].CallCount, Buffer);
  133. if (Displacement != 0) {
  134. dprintf("+0x%1p", Displacement);
  135. }
  136. if (CallerArray[Index].CallersCaller != 0) {
  137. dprintf("\n");
  138. GetSymbol(CallerArray[Index].CallersCaller,
  139. Buffer,
  140. &Displacement);
  141. dprintf(" %s", Buffer);
  142. if (Displacement != 0) {
  143. dprintf("+0x%1p", Displacement);
  144. }
  145. }
  146. dprintf("\n");
  147. if (CheckControlC()) {
  148. break;
  149. }
  150. }
  151. LocalFree(CallerArray);
  152. }
  153. return S_OK;
  154. }
  155. int __cdecl
  156. HashCompare(
  157. const void * Element1,
  158. const void * Element2
  159. )
  160. /*++
  161. Routine Description:
  162. Provides a comparison of hash elements for the qsort library function
  163. Arguments:
  164. Element1 - Supplies pointer to the key for the search
  165. Element2 - Supplies element to be compared to the key
  166. Return Value:
  167. > 0 - Element1 < Element2
  168. = 0 - Element1 == Element2
  169. < 0 - Element1 > Element2
  170. --*/
  171. {
  172. PCALL_HASH_READ Hash1 = (PCALL_HASH_READ)Element1;
  173. PCALL_HASH_READ Hash2 = (PCALL_HASH_READ)Element2;
  174. if (Hash1->CallCount < Hash2->CallCount) {
  175. return(1);
  176. }
  177. else if (Hash1->CallCount > Hash2->CallCount) {
  178. return(-1);
  179. } else {
  180. return(0);
  181. }
  182. }