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.

341 lines
7.4 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. time.c
  5. Abstract:
  6. Implements the timelog command.
  7. Author:
  8. Michael Courage (mcourage) 8-Mar-2000
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. //
  15. // Private constants.
  16. //
  17. //
  18. // Private globals.
  19. //
  20. PSTR g_pTimeActions[] =
  21. {
  22. "CREATE CONNECTION",
  23. "CREATE REQUEST ",
  24. "ROUTE REQUEST ",
  25. "COPY REQUEST ",
  26. "SEND RESPONSE ",
  27. "SEND COMPLETE "
  28. };
  29. C_ASSERT( DIM(g_pTimeActions) == TIME_ACTION_COUNT );
  30. //
  31. // Public functions.
  32. //
  33. DECLARE_API( timelog )
  34. /*++
  35. Routine Description:
  36. Dumps the time trace log.
  37. Arguments:
  38. None.
  39. Return Value:
  40. None.
  41. --*/
  42. {
  43. ULONG_PTR address = 0;
  44. ULONG_PTR context = 0;
  45. ULONG_PTR flags = 0;
  46. ULONG_PTR entryAddress;
  47. ULONG_PTR logPointer;
  48. ULONG result;
  49. TRACE_LOG logHeader;
  50. LONGLONG numEntries;
  51. TIME_TRACE_LOG_ENTRY logEntry;
  52. PSTR pAction;
  53. LONGLONG index;
  54. ULONG offset1;
  55. ULONG offset2;
  56. UCHAR invalidAction[sizeof("2047")];
  57. ULONGLONG PreviousTime = 0;
  58. USHORT PreviousProcessor = -1;
  59. ULONG64 context64 = 0;
  60. ULONG64 flags64 = 0;
  61. SNAPSHOT_EXTENSION_DATA();
  62. //
  63. // Snag the optional context and flags from the command line.
  64. //
  65. if (GetExpressionEx(args, &context64, &args))
  66. GetExpressionEx(args, &flags64, &args);
  67. context = (ULONG_PTR) context64;
  68. flags = (ULONG_PTR) flags64;
  69. //
  70. // Find the log.
  71. //
  72. address = GetExpression( "&http!g_pTimeTraceLog" );
  73. if (address == 0)
  74. {
  75. dprintf( "timelog: cannot find http!g_pTimeTraceLog\n" );
  76. return;
  77. }
  78. //
  79. // Read the pointer.
  80. //
  81. if (!ReadMemory(
  82. address,
  83. &logPointer,
  84. sizeof(logPointer),
  85. &result
  86. ))
  87. {
  88. dprintf(
  89. "timelog: cannot read PTRACE_LOG @ %p\n",
  90. address
  91. );
  92. return;
  93. }
  94. //
  95. // Read the log header.
  96. //
  97. if (!ReadMemory(
  98. logPointer,
  99. &logHeader,
  100. sizeof(logHeader),
  101. &result
  102. ))
  103. {
  104. dprintf(
  105. "timelog: cannot read TRACE_LOG @ %p\n",
  106. logPointer
  107. );
  108. return;
  109. }
  110. dprintf(
  111. "timelog: log @ %p\n"
  112. " Signature = %08lx '%c%c%c%c' (%s)\n"
  113. " TypeSignature = %08lx '%c%c%c%c'\n"
  114. " LogSize = %lu\n"
  115. " NextEntry = %I64d\n"
  116. " EntrySize = %lu\n"
  117. " LogBuffer = %p\n",
  118. address,
  119. logHeader.Signature,
  120. DECODE_SIGNATURE(logHeader.Signature),
  121. logHeader.Signature == TRACE_LOG_SIGNATURE
  122. ? "OK"
  123. : logHeader.Signature == TRACE_LOG_SIGNATURE_X
  124. ? "FREED"
  125. : "INVALID",
  126. logHeader.TypeSignature,
  127. DECODE_SIGNATURE(logHeader.TypeSignature),
  128. logHeader.LogSize,
  129. logHeader.NextEntry,
  130. logHeader.EntrySize,
  131. logHeader.pLogBuffer
  132. );
  133. if (logHeader.pLogBuffer > ( (PUCHAR)address + sizeof(logHeader) ))
  134. {
  135. dprintf(
  136. " ExtraData @ %p\n",
  137. address + sizeof(logHeader)
  138. );
  139. }
  140. if (logHeader.Signature != TRACE_LOG_SIGNATURE &&
  141. logHeader.Signature != TRACE_LOG_SIGNATURE_X)
  142. {
  143. dprintf(
  144. "timelog: log @ %p has invalid signature %08lx:\n",
  145. address,
  146. logHeader.Signature
  147. );
  148. return;
  149. }
  150. if (logHeader.EntrySize != sizeof(logEntry)
  151. || logHeader.TypeSignature != TIME_TRACE_LOG_SIGNATURE)
  152. {
  153. dprintf(
  154. "timelog: log @ %p is not a time trace log\n",
  155. address
  156. );
  157. return;
  158. }
  159. if (logHeader.NextEntry == -1)
  160. {
  161. dprintf(
  162. "timelog: empty log @ %p\n",
  163. address
  164. );
  165. return;
  166. }
  167. //
  168. // Calculate the log size to dump.
  169. //
  170. if (logHeader.NextEntry < logHeader.LogSize)
  171. {
  172. numEntries = logHeader.NextEntry + 1;
  173. index = 0;
  174. }
  175. else
  176. {
  177. numEntries = logHeader.LogSize;
  178. index = (logHeader.NextEntry + 1) % logHeader.LogSize;
  179. }
  180. entryAddress = (ULONG_PTR)logHeader.pLogBuffer +
  181. (ULONG_PTR)( index * sizeof(logEntry) );
  182. if (entryAddress >=
  183. ( (ULONG_PTR)logHeader.pLogBuffer + (ULONG_PTR)( numEntries * sizeof(logEntry) ) ) )
  184. {
  185. dprintf(
  186. "timelog: log @ %p has invalid data\n",
  187. address
  188. );
  189. return;
  190. }
  191. //
  192. // Dump the log.
  193. //
  194. for (;
  195. numEntries > 0 ;
  196. index++,
  197. numEntries--,
  198. entryAddress += sizeof(logEntry))
  199. {
  200. if (CheckControlC())
  201. {
  202. break;
  203. }
  204. if (index >= logHeader.LogSize)
  205. {
  206. index = 0;
  207. entryAddress = (ULONG_PTR)logHeader.pLogBuffer;
  208. }
  209. if (!ReadMemory(
  210. entryAddress,
  211. &logEntry,
  212. sizeof(logEntry),
  213. NULL
  214. ))
  215. {
  216. dprintf(
  217. "timelog: cannot read memory @ %p\n",
  218. entryAddress
  219. );
  220. return;
  221. }
  222. if (context == 0 ||
  223. context == (ULONG_PTR)logEntry.ConnectionId)
  224. {
  225. if (logEntry.Action < TIME_ACTION_COUNT)
  226. {
  227. pAction = g_pTimeActions[logEntry.Action];
  228. }
  229. else
  230. {
  231. sprintf( (char*)invalidAction, "%lu", (ULONG)logEntry.Action );
  232. pAction = (PSTR) invalidAction;
  233. }
  234. if (flags & 1)
  235. {
  236. dprintf(
  237. "\nCPU=%lu Conn=%I64x Req=%I64x Act=%s\n"
  238. " Time=%I64x ",
  239. (ULONG)logEntry.Processor,
  240. logEntry.ConnectionId,
  241. logEntry.RequestId,
  242. pAction,
  243. logEntry.TimeStamp,
  244. (logEntry.TimeStamp - PreviousTime),
  245. (logEntry.TimeStamp - PreviousTime) / 10
  246. );
  247. } else {
  248. dprintf(
  249. "C=%I64x R=%I64x A=%s ",
  250. logEntry.ConnectionId,
  251. logEntry.RequestId,
  252. pAction
  253. );
  254. }
  255. if (logEntry.Processor == PreviousProcessor) {
  256. ULONGLONG Delta;
  257. Delta = (logEntry.TimeStamp - PreviousTime);
  258. if (flags & 1) {
  259. dprintf(
  260. "Delta=%I64x (%I64d Kcycles)\n",
  261. Delta,
  262. Delta / 1024
  263. );
  264. } else {
  265. dprintf(
  266. "(%I64d) D=%I64x\n",
  267. Delta / 1024,
  268. Delta
  269. );
  270. }
  271. } else {
  272. dprintf("cpu switch\n");
  273. }
  274. PreviousTime = logEntry.TimeStamp;
  275. PreviousProcessor = logEntry.Processor;
  276. }
  277. }
  278. } // timelog