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.

633 lines
14 KiB

  1. /*++
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name:
  4. strlog.cxx
  5. Abstract:
  6. CStringTraceLog support
  7. Author:
  8. George V. Reilly (GeorgeRe) 22-Jun-1998
  9. Revision History:
  10. --*/
  11. #include "inetdbgp.h"
  12. /************************************************************
  13. * Dump String Trace Logs
  14. ************************************************************/
  15. // Dummy implementations so that we can link
  16. CStringTraceLog::CStringTraceLog(
  17. UINT cchEntrySize /* = 80 */,
  18. UINT cLogSize /* = 100 */)
  19. {}
  20. CStringTraceLog::~CStringTraceLog()
  21. {}
  22. VOID
  23. DumpStringTraceLog(
  24. IN PSTR lpArgumentString,
  25. IN BOOLEAN fReverse
  26. )
  27. /*++
  28. Routine Description:
  29. Dumps the specified print trace log either forwards (fReverse == FALSE)
  30. or backwards (fReverse == TRUE).
  31. Arguments:
  32. lpArgumentString - An expression specifying the print trace log to dump.
  33. fReverse - The dump direction.
  34. Return Value:
  35. None.
  36. --*/
  37. {
  38. ULONG_PTR stlLogAddress = 0;
  39. ULONG_PTR entryAddress;
  40. LONG numEntries;
  41. CStringTraceLog stlHeader;
  42. TRACE_LOG tlogHeader;
  43. CStringTraceLog::CLogEntry logEntry;
  44. LONG i;
  45. DWORD offset;
  46. PCHAR format;
  47. LONG index;
  48. LONG direction;
  49. PSTR cmdName;
  50. UCHAR symbol[MAX_PATH];
  51. INT nVerbose = 0;
  52. direction = fReverse ? -1 : 1;
  53. cmdName = fReverse ? "rst" : "st";
  54. //
  55. // Skip leading blanks.
  56. //
  57. while( *lpArgumentString == ' ' ||
  58. *lpArgumentString == '\t' ) {
  59. lpArgumentString++;
  60. }
  61. if( *lpArgumentString == '\0' ) {
  62. PrintUsage( cmdName );
  63. return;
  64. }
  65. if ( *lpArgumentString == '-' )
  66. {
  67. lpArgumentString++;
  68. if ( *lpArgumentString == 'h' )
  69. {
  70. PrintUsage( cmdName );
  71. return;
  72. }
  73. if ( *lpArgumentString == 'l' ) {
  74. lpArgumentString++;
  75. if ('0' <= *lpArgumentString && *lpArgumentString <= '9' ) {
  76. nVerbose = *lpArgumentString++ - '0';
  77. }
  78. }
  79. }
  80. while( *lpArgumentString == ' ' ||
  81. *lpArgumentString == '\t' ) {
  82. lpArgumentString++;
  83. }
  84. stlLogAddress = (ULONG_PTR)GetExpression( lpArgumentString );
  85. if( stlLogAddress == 0 ) {
  86. dprintf(
  87. "inetdbg.%s: cannot evaluate \"%s\"\n",
  88. cmdName,
  89. lpArgumentString
  90. );
  91. return;
  92. }
  93. //
  94. // Skip to end of expression, then skip any blanks.
  95. //
  96. while( *lpArgumentString != ' ' &&
  97. *lpArgumentString != '\t' &&
  98. *lpArgumentString != '\0' ) {
  99. lpArgumentString++;
  100. }
  101. //
  102. // Read the log header, perform some sanity checks.
  103. //
  104. if( !ReadMemory(
  105. stlLogAddress,
  106. &stlHeader,
  107. sizeof(stlHeader),
  108. NULL
  109. ) ) {
  110. dprintf(
  111. "inetdbg.%s: cannot read memory @ %p\n",
  112. cmdName,
  113. (PVOID)stlLogAddress
  114. );
  115. return;
  116. }
  117. if( !ReadMemory(
  118. stlHeader.m_ptlog,
  119. &tlogHeader,
  120. sizeof(tlogHeader),
  121. NULL
  122. ) ) {
  123. dprintf(
  124. "inetdbg.%s: cannot read tracelog memory @ %p\n",
  125. cmdName,
  126. (PVOID)stlHeader.m_ptlog
  127. );
  128. return;
  129. }
  130. dprintf(
  131. "inetdbg.%s: log @ %p:\n"
  132. " String Trace Log Signature = %08lx (%s)\n"
  133. " Trace Log Signature = %08lx (%s)\n"
  134. " LogSize = %lu\n"
  135. " NextEntry = %lu\n"
  136. " EntrySize = %lu\n"
  137. " LogBuffer = %p\n",
  138. cmdName,
  139. (PVOID)stlLogAddress,
  140. stlHeader.m_Signature,
  141. stlHeader.m_Signature == CStringTraceLog::SIGNATURE
  142. ? "OK"
  143. : stlHeader.m_Signature == CStringTraceLog::SIGNATURE_X
  144. ? "FREED"
  145. : "INVALID",
  146. tlogHeader.Signature,
  147. tlogHeader.Signature == TRACE_LOG_SIGNATURE
  148. ? "OK"
  149. : tlogHeader.Signature == TRACE_LOG_SIGNATURE_X
  150. ? "FREED"
  151. : "INVALID",
  152. tlogHeader.LogSize,
  153. tlogHeader.NextEntry,
  154. tlogHeader.EntrySize,
  155. tlogHeader.LogBuffer
  156. );
  157. if( tlogHeader.LogBuffer
  158. > ( (PUCHAR)stlHeader.m_ptlog + sizeof(tlogHeader) ) )
  159. {
  160. dprintf(
  161. " Extra Data @ %p\n",
  162. (PVOID)( stlLogAddress + sizeof(tlogHeader) )
  163. );
  164. }
  165. if( stlHeader.m_Signature != CStringTraceLog::SIGNATURE &&
  166. stlHeader.m_Signature != CStringTraceLog::SIGNATURE_X ) {
  167. dprintf(
  168. "inetdbg.%s: log @ %p has invalid signature: %08lx\n",
  169. cmdName,
  170. (PVOID)stlLogAddress,
  171. stlHeader.m_Signature
  172. );
  173. return;
  174. }
  175. if( (UINT) tlogHeader.EntrySize
  176. != sizeof(CStringTraceLog::CLogEntry) - CStringTraceLog::MAX_CCH + stlHeader.m_cch ) {
  177. dprintf(
  178. "inetdbg.%s: log @ %p is not a print trace log\n",
  179. cmdName,
  180. (PVOID)stlLogAddress
  181. );
  182. return;
  183. }
  184. if( tlogHeader.NextEntry == -1 ) {
  185. dprintf(
  186. "inetdbg.%s: empty log @ %p\n",
  187. cmdName,
  188. (PVOID)stlLogAddress
  189. );
  190. return;
  191. }
  192. //
  193. // Calculate the starting address and number of entries.
  194. //
  195. if( fReverse ) {
  196. if( tlogHeader.NextEntry < tlogHeader.LogSize ) {
  197. numEntries = tlogHeader.NextEntry + 1;
  198. index = tlogHeader.NextEntry;
  199. } else {
  200. numEntries = tlogHeader.LogSize;
  201. index = tlogHeader.NextEntry % tlogHeader.LogSize;
  202. }
  203. } else {
  204. if( tlogHeader.NextEntry < tlogHeader.LogSize ) {
  205. numEntries = tlogHeader.NextEntry + 1;
  206. index = 0;
  207. } else {
  208. numEntries = tlogHeader.LogSize;
  209. index = ( tlogHeader.NextEntry + 1 ) % tlogHeader.LogSize;
  210. }
  211. }
  212. entryAddress = (ULONG_PTR)tlogHeader.LogBuffer + (ULONG_PTR)( index * tlogHeader.EntrySize );
  213. if( entryAddress >=
  214. ( (ULONG_PTR)tlogHeader.LogBuffer + (ULONG_PTR)( numEntries * tlogHeader.EntrySize ) ) ) {
  215. dprintf(
  216. "inetdbg.%s: log @ %p has invalid data\n",
  217. cmdName,
  218. (PVOID)stlLogAddress
  219. );
  220. return;
  221. }
  222. //
  223. // Dump the log, which is stored in a circular buffer.
  224. //
  225. for( ;
  226. numEntries > 0 ;
  227. index += direction,
  228. numEntries--,
  229. entryAddress += ( direction * tlogHeader.EntrySize ) )
  230. {
  231. if( CheckControlC() ) {
  232. break;
  233. }
  234. if( index >= tlogHeader.LogSize ) {
  235. index = 0;
  236. entryAddress = (ULONG_PTR)tlogHeader.LogBuffer;
  237. } else if( index < 0 ) {
  238. index = tlogHeader.LogSize - 1;
  239. entryAddress = (ULONG_PTR)tlogHeader.LogBuffer
  240. + (ULONG_PTR)( index * tlogHeader.EntrySize );
  241. }
  242. if( !ReadMemory(
  243. entryAddress,
  244. &logEntry,
  245. tlogHeader.EntrySize,
  246. NULL
  247. ) ) {
  248. dprintf(
  249. "inetdbg.%s: cannot read memory @ %p\n",
  250. cmdName,
  251. (ULONG_PTR)entryAddress
  252. );
  253. return;
  254. }
  255. if (nVerbose == 0)
  256. {
  257. dprintf(
  258. "%04x: %s\n",
  259. logEntry.m_nThread,
  260. logEntry.m_ach
  261. );
  262. } else if (nVerbose == 1) {
  263. dprintf(
  264. "\n%6d: Thread = %04x, TimeStamp = %04x %04x %04x %04x\n"
  265. "%s\n",
  266. index,
  267. logEntry.m_nThread,
  268. HIWORD(logEntry.m_liTimeStamp.HighPart),
  269. LOWORD(logEntry.m_liTimeStamp.HighPart),
  270. HIWORD(logEntry.m_liTimeStamp.LowPart),
  271. LOWORD(logEntry.m_liTimeStamp.LowPart),
  272. logEntry.m_ach
  273. );
  274. }
  275. }
  276. } // DumpStringTraceLog
  277. DECLARE_API( st )
  278. /*++
  279. Routine Description:
  280. This function is called as an NTSD extension to format and dump
  281. a print trace log.
  282. Arguments:
  283. hCurrentProcess - Supplies a handle to the current process (at the
  284. time the extension was called).
  285. hCurrentThread - Supplies a handle to the current thread (at the
  286. time the extension was called).
  287. CurrentPc - Supplies the current pc at the time the extension is
  288. called.
  289. lpExtensionApis - Supplies the address of the functions callable
  290. by this extension.
  291. lpArgumentString - Supplies the asciiz string that describes the
  292. ansi string to be dumped.
  293. Return Value:
  294. None.
  295. --*/
  296. {
  297. INIT_API();
  298. DumpStringTraceLog( lpArgumentString, FALSE );
  299. } // DECLARE_API( st )
  300. DECLARE_API( rst )
  301. /*++
  302. Routine Description:
  303. This function is called as an NTSD extension to format and dump
  304. a print trace log backwards.
  305. Arguments:
  306. hCurrentProcess - Supplies a handle to the current process (at the
  307. time the extension was called).
  308. hCurrentThread - Supplies a handle to the current thread (at the
  309. time the extension was called).
  310. CurrentPc - Supplies the current pc at the time the extension is
  311. called.
  312. lpExtensionApis - Supplies the address of the functions callable
  313. by this extension.
  314. lpArgumentString - Supplies the asciiz string that describes the
  315. ansi string to be dumped.
  316. Return Value:
  317. None.
  318. --*/
  319. {
  320. INIT_API();
  321. DumpStringTraceLog( lpArgumentString, TRUE );
  322. } // DECLARE_API( rst )
  323. DECLARE_API( resetst )
  324. /*++
  325. Routine Description:
  326. This function is called as an NTSD extension to reset a print
  327. trace log back to its initial state.
  328. Arguments:
  329. hCurrentProcess - Supplies a handle to the current process (at the
  330. time the extension was called).
  331. hCurrentThread - Supplies a handle to the current thread (at the
  332. time the extension was called).
  333. CurrentPc - Supplies the current pc at the time the extension is
  334. called.
  335. lpExtensionApis - Supplies the address of the functions callable
  336. by this extension.
  337. lpArgumentString - Supplies the asciiz string that describes the
  338. ansi string to be dumped.
  339. Return Value:
  340. None.
  341. --*/
  342. {
  343. ULONG_PTR stlLogAddress = 0;
  344. CStringTraceLog stlHeader;
  345. TRACE_LOG tlogHeader;
  346. CStringTraceLog::CLogEntry logEntry;
  347. INIT_API();
  348. //
  349. // Skip leading blanks.
  350. //
  351. while( *lpArgumentString == ' ' ||
  352. *lpArgumentString == '\t' ) {
  353. lpArgumentString++;
  354. }
  355. if( *lpArgumentString == '\0' ) {
  356. PrintUsage( "resetst" );
  357. return;
  358. }
  359. stlLogAddress = GetExpression( lpArgumentString );
  360. if( stlLogAddress == 0 ) {
  361. dprintf(
  362. "inetdbg.resetst: cannot evaluate \"%s\"\n",
  363. lpArgumentString
  364. );
  365. return;
  366. }
  367. //
  368. // Read the log header, perform some sanity checks.
  369. //
  370. if( !ReadMemory(
  371. stlLogAddress,
  372. &stlHeader,
  373. sizeof(stlHeader),
  374. NULL
  375. ) ) {
  376. dprintf(
  377. "inetdbg.resetst: cannot read memory @ %p\n",
  378. stlLogAddress
  379. );
  380. return;
  381. }
  382. if( !ReadMemory(
  383. stlHeader.m_ptlog,
  384. &tlogHeader,
  385. sizeof(tlogHeader),
  386. NULL
  387. ) ) {
  388. dprintf(
  389. "inetdbg.resetst: cannot read tracelog memory @ %p\n",
  390. (PVOID)stlHeader.m_ptlog
  391. );
  392. return;
  393. }
  394. dprintf(
  395. "inetdbg.resetst: log @ %p:\n"
  396. " String Trace Log Signature = %08lx (%s)\n"
  397. " Trace Log Signature = %08lx (%s)\n"
  398. " LogSize = %lu\n"
  399. " NextEntry = %lu\n"
  400. " EntrySize = %lu\n"
  401. " LogBuffer = %08lp\n",
  402. (PVOID) stlLogAddress,
  403. stlHeader.m_Signature,
  404. stlHeader.m_Signature == CStringTraceLog::SIGNATURE
  405. ? "OK"
  406. : stlHeader.m_Signature == CStringTraceLog::SIGNATURE_X
  407. ? "FREED"
  408. : "INVALID",
  409. tlogHeader.Signature,
  410. tlogHeader.Signature == TRACE_LOG_SIGNATURE
  411. ? "OK"
  412. : tlogHeader.Signature == TRACE_LOG_SIGNATURE_X
  413. ? "FREED"
  414. : "INVALID",
  415. tlogHeader.LogSize,
  416. tlogHeader.NextEntry,
  417. tlogHeader.EntrySize,
  418. tlogHeader.LogBuffer
  419. );
  420. if( tlogHeader.LogBuffer
  421. > ( (PUCHAR)stlHeader.m_ptlog + sizeof(tlogHeader) ) )
  422. {
  423. dprintf(
  424. " Extra Data @ %p\n",
  425. (PVOID)( stlLogAddress + sizeof(tlogHeader) )
  426. );
  427. }
  428. if( stlHeader.m_Signature != CStringTraceLog::SIGNATURE &&
  429. stlHeader.m_Signature != CStringTraceLog::SIGNATURE_X ) {
  430. dprintf(
  431. "inetdbg.resetst: log @ %p has invalid signature %08lx:\n",
  432. (PVOID) stlLogAddress,
  433. stlHeader.m_Signature
  434. );
  435. return;
  436. }
  437. if( (UINT) tlogHeader.EntrySize
  438. != sizeof(CStringTraceLog::CLogEntry) - CStringTraceLog::MAX_CCH + stlHeader.m_cch ) {
  439. dprintf(
  440. "inetdbg.resetst: log @ %p is not a print trace log\n",
  441. (PVOID) stlLogAddress
  442. );
  443. return;
  444. }
  445. //
  446. // Reset it.
  447. //
  448. tlogHeader.NextEntry = -1;
  449. if( !WriteMemory(
  450. stlHeader.m_ptlog,
  451. &tlogHeader,
  452. sizeof(tlogHeader),
  453. NULL
  454. ) ) {
  455. dprintf(
  456. "inetdbg.resetst: cannot write memory @ %p\n",
  457. (PVOID) stlHeader.m_ptlog
  458. );
  459. return;
  460. }
  461. dprintf(
  462. "inetdbg.resetst: log @ %p reset\n",
  463. (PVOID) stlHeader.m_ptlog
  464. );
  465. } // DECLARE_API( resetst )