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.

813 lines
19 KiB

  1. /*++
  2. Copyright (c) 1992-1999 Microsoft Corporation
  3. Module Name:
  4. kdexts.c
  5. Abstract:
  6. This function contains some example KD debugger extensions
  7. Author:
  8. John Vert (jvert) 6-Aug-1992
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
  13. // Forward function definitions
  14. PCHAR
  15. FindPreamble(
  16. CHAR * BufferPointer,
  17. BOOLEAN FirstTime
  18. );
  19. VOID
  20. ParseBuffer(
  21. CHAR * DataStart,
  22. ULONG SkipCnt
  23. );
  24. PCHAR
  25. ParseOidRecord(
  26. CHAR * DataStart,
  27. ULONG SkipCnt
  28. );
  29. PCHAR
  30. ParseTimeRecord(
  31. CHAR * DataStart,
  32. ULONG SkipCnt
  33. );
  34. PCHAR
  35. ParseStringRecord(
  36. CHAR * DataStart,
  37. ULONG SkipCnt
  38. );
  39. PCHAR
  40. ParseSchedRecord(
  41. CHAR * DataStart,
  42. ULONG SkipCnt
  43. );
  44. PCHAR
  45. ParseRecvRecord(
  46. CHAR * DataStart,
  47. ULONG SkipCnt
  48. );
  49. PCHAR
  50. ParseSendRecord(
  51. CHAR * DataStart,
  52. ULONG SkipCnt
  53. );
  54. static PCHAR SchedModules[] = {
  55. "NOP",
  56. "TB CONFORMER",
  57. "SHAPER",
  58. "DRR SEQ",
  59. "CBQ"};
  60. static PCHAR SchedActions[] = {
  61. "NOP",
  62. "ENQUEUE",
  63. "DEQUEUE",
  64. "CONFORMANCE",
  65. "DISCARD"};
  66. static PCHAR SendRecvActions[] = {
  67. "",
  68. "ENTER",
  69. "NO_RESOURCES",
  70. "LOW_RESOURCES",
  71. "INDICATING",
  72. "RETURNED",
  73. "NOT_OURS",
  74. "OURS",
  75. "RETURNING",
  76. "TRANSFERRING",
  77. "NOT READY"};
  78. static PCHAR RecvEvents[] = {
  79. "",
  80. "CL_RECV_PACKET",
  81. "MP_RETURN_PACKET",
  82. "CL_RECV_INDICATION",
  83. "CL_RECV_COMPLETE",
  84. "MP_TRANSFER_DATA",
  85. "CL_TRANSFER_COMPLETE"};
  86. static PCHAR SendEvents[] = {
  87. "",
  88. "MP_SEND",
  89. "MP_CO_SEND",
  90. "DUP_PACKET",
  91. "DROP_PACKET",
  92. "CL_SEND_COMPLETE" };
  93. //
  94. // globals
  95. //
  96. CHAR Preamble[] = {(CHAR)0xef,(CHAR)0xbe,(CHAR)0xad,(CHAR)0xde};
  97. ULONG ByteCheck = 0;
  98. ULONG SafetyLimit;
  99. BOOL
  100. SafeRead(
  101. DWORD offset,
  102. LPVOID lpBuffer,
  103. DWORD cb,
  104. LPDWORD lpcbBytesRead
  105. )
  106. {
  107. if(ByteCheck <= SafetyLimit){
  108. ReadMemory(offset, lpBuffer, cb, lpcbBytesRead);
  109. ByteCheck += cb;
  110. return TRUE;
  111. }
  112. else{
  113. dprintf("SafetyLimit of %d, exceeded, quitting!\n", SafetyLimit);
  114. return FALSE;
  115. }
  116. }
  117. DWORD
  118. MyOpenFile (
  119. IN PCHAR Name,
  120. IN PWINDBG_OUTPUT_ROUTINE out,
  121. OUT HANDLE *File
  122. )
  123. {
  124. HANDLE hFile;
  125. hFile = CreateFile(Name,
  126. GENERIC_WRITE | GENERIC_READ,
  127. 0,
  128. NULL,
  129. CREATE_ALWAYS ,
  130. FILE_ATTRIBUTE_NORMAL,
  131. NULL);
  132. if (INVALID_HANDLE_VALUE == hFile) {
  133. out ("MyOpenFile: CreateFile Failed.\n");
  134. }
  135. *File = hFile;
  136. return(INVALID_HANDLE_VALUE == hFile ? (!(ERROR_SUCCESS)) : ERROR_SUCCESS);
  137. }
  138. VOID
  139. MyWriteFile (
  140. PCHAR buffer,
  141. HANDLE file,
  142. IN PWINDBG_OUTPUT_ROUTINE out
  143. )
  144. {
  145. LONG len;
  146. BOOL bRv;
  147. DWORD dwWritten;
  148. if (!buffer) {
  149. out("MyWriteFile: Buffer is null\n");
  150. }
  151. len = strlen(buffer);
  152. bRv = WriteFile( file, buffer, len, &dwWritten, NULL );
  153. if (!bRv) {
  154. out("WriteFile: Puked\n");
  155. }
  156. }
  157. CHAR * BufferBase; // Start address of trace buffer, in host memory
  158. CHAR * BufferEnd; // End address of trace buffer, in host memory
  159. CHAR * BufferPointer; // Current location in host memory buffer
  160. LONG BufferSize; // Total size of host memory buffer, in bytes.
  161. LONG BufferCount; // Total count of traced bytes.
  162. LONG TotalValidBytesRead = 0;
  163. #define OUTPUT_ERROR 0
  164. #define OUTPUT_FILE 1
  165. #define OUTPUT_CONSOLE 2
  166. CHAR FileIt;
  167. HANDLE FileHandle;
  168. ULONG LineNumber = 0;
  169. DECLARE_API( tt )
  170. {
  171. DWORD hostAddress;
  172. CHAR DeviceName[] = "c:\\tmp\\";
  173. CHAR buffer[255];
  174. DWORD status;
  175. LONG pBufferBase;
  176. LONG pBufferCount;
  177. LONG pBufferSize;
  178. BOOL success;
  179. DWORD bytesread;
  180. CHAR *s, *dataStart;
  181. ULONG skip=0;
  182. char SchedBufBase[] = {"&psched!SchedTraceBuffer"};
  183. char SchedCount[] = {"&psched!SchedTraced"};
  184. char BuffSize[] = {"&psched!SchedBufferSize"};
  185. TotalValidBytesRead = 0;
  186. LineNumber = 0;
  187. FileIt = OUTPUT_ERROR;
  188. if ( *args != '\0' ) {
  189. // First argument is the file name.
  190. s = strtok((LPSTR)args, " ");
  191. strcpy( buffer, DeviceName );
  192. strcat( buffer, s );
  193. // next arg is the optional args.
  194. while((s = strtok(NULL, " ")) != NULL)
  195. {
  196. if(s[0] == '-')
  197. {
  198. switch(s[1])
  199. {
  200. case 's':
  201. case 'S':
  202. skip = atoi(&s[2]);
  203. break;
  204. default:
  205. dprintf("Usage: !tt [filename] [-S<#>] \n");
  206. dprintf(" S : No of records (from head) to skip \n");
  207. goto cleanup;
  208. }
  209. }
  210. }
  211. status = MyOpenFile( buffer, dprintf, &FileHandle );
  212. if ( status == ERROR_SUCCESS ) {
  213. FileIt = OUTPUT_FILE;
  214. }
  215. else {
  216. goto cleanup;
  217. }
  218. dprintf( "handle =%x status=%x FileIt=%d\n", FileHandle, status, FileIt );
  219. }
  220. else {
  221. FileIt = OUTPUT_CONSOLE;
  222. }
  223. hostAddress = GetExpression(SchedBufBase);
  224. pBufferBase = (LONG)hostAddress;
  225. if (!pBufferBase){
  226. dprintf("bad string conversion (%s) \n", SchedBufBase);
  227. goto cleanup;
  228. }
  229. hostAddress = GetExpression(SchedCount);
  230. pBufferCount = hostAddress;
  231. if (!pBufferCount) {
  232. dprintf( " bad string conversion (%s) \n", SchedCount );
  233. goto cleanup;
  234. }
  235. hostAddress = GetExpression(BuffSize);
  236. pBufferSize = hostAddress;
  237. if (!pBufferSize) {
  238. dprintf( " bad string conversion (%s) \n", SchedCount );
  239. goto cleanup;
  240. }
  241. success = ReadMemory((ULONG)pBufferCount, &BufferCount, sizeof(LONG), &bytesread );
  242. if (!success){
  243. dprintf("problems reading memory at %x for %x bytes\n", pBufferCount, sizeof(LONG));
  244. goto cleanup;
  245. }
  246. success = ReadMemory((ULONG)pBufferSize, &BufferSize, sizeof(LONG), &bytesread );
  247. if (!success){
  248. dprintf("problems reading memory at %x for %x bytes\n", pBufferSize, sizeof(LONG));
  249. goto cleanup;
  250. }
  251. success = ReadMemory((ULONG)pBufferBase, &BufferBase, sizeof(LONG), &bytesread );
  252. if (!success){
  253. dprintf("problems reading memory at %x for %x bytes\n", pBufferBase, sizeof(LONG));
  254. goto cleanup;
  255. }
  256. SafetyLimit = (ULONG)-1;
  257. if(!BufferCount){
  258. dprintf("No data in buffer.\n");
  259. goto cleanup;
  260. }
  261. dprintf("struct@%x, total bytes traced: %d, buffer size: %d\n", BufferBase, BufferCount, BufferSize);
  262. // Find the starting point. If we haven't wrapped the buffer, it's at BufferBase.
  263. // If we have wrapped the buffer, we start right after our current pointer.
  264. // In either case, BufferPointer is the host address at which we should
  265. // start looking for data.
  266. if(BufferCount <= BufferSize){
  267. BufferPointer = BufferBase;
  268. }
  269. else{
  270. BufferPointer = BufferBase + (BufferCount % BufferSize);
  271. }
  272. BufferEnd = BufferBase + BufferSize;
  273. // dataStart will point to the first location after the
  274. // first preamble (in host memory), or - will be zero,
  275. // indicating that no preamble was found.
  276. dataStart = FindPreamble(BufferPointer, TRUE);
  277. if(dataStart){
  278. ParseBuffer(dataStart, skip);
  279. }
  280. else{
  281. dprintf("Error reading token trace buffer. Could not find preamble.\n");
  282. }
  283. cleanup:
  284. if(FileIt == OUTPUT_FILE){
  285. CloseHandle( FileHandle );
  286. }
  287. }
  288. PCHAR
  289. FindPreamble(
  290. CHAR * BufferPointer,
  291. BOOLEAN FirstTime
  292. )
  293. {
  294. LONG count;
  295. LONG i;
  296. CHAR * readFrom;
  297. CHAR hold;
  298. BOOL success;
  299. DWORD bytesread;
  300. count = 0;
  301. i = 0;
  302. readFrom = BufferPointer;
  303. while(TRUE){
  304. success = SafeRead((ULONG)readFrom, &hold, 1, &bytesread );
  305. if (!success){
  306. dprintf("problems reading memory at %x for %x bytes\n", readFrom, 1);
  307. break;
  308. }
  309. if(hold == Preamble[i]){
  310. i++;
  311. }
  312. else{
  313. i=0;
  314. }
  315. if(i == sizeof(TRACE_PREAMBLE)){
  316. if(FirstTime){
  317. dprintf("Found start of first record at %d.\n", readFrom+1 - BufferBase);
  318. }
  319. TotalValidBytesRead += sizeof(TRACE_PREAMBLE);
  320. readFrom++;
  321. break;
  322. }
  323. readFrom++;
  324. if(readFrom > BufferEnd){
  325. readFrom = BufferBase;
  326. }
  327. count++;
  328. if(count == TRACE_BUFFER_SIZE){
  329. readFrom = 0;
  330. break;
  331. }
  332. }
  333. return(readFrom);
  334. }
  335. VOID
  336. ParseBuffer(
  337. CHAR * DataStart,
  338. ULONG SkipCnt
  339. )
  340. {
  341. CHAR * dataStart;
  342. CHAR * recordEnd;
  343. LONG records;
  344. BOOL success;
  345. CHAR hold;
  346. DWORD bytesread;
  347. records = 0;
  348. dataStart = DataStart;
  349. while(TRUE){
  350. success = SafeRead((ULONG)dataStart, &hold, 1, &bytesread );
  351. if (!success){
  352. dprintf("problems reading memory at %x for %x bytes\n", dataStart, 1);
  353. break;
  354. }
  355. switch(hold){
  356. case RECORD_TSTRING:
  357. recordEnd = ParseStringRecord(dataStart, SkipCnt);
  358. break;
  359. case RECORD_OID:
  360. recordEnd = ParseOidRecord(dataStart, SkipCnt);
  361. break;
  362. case RECORD_SCHED:
  363. recordEnd = ParseSchedRecord(dataStart, SkipCnt);
  364. break;
  365. case RECORD_RECV:
  366. recordEnd = ParseRecvRecord(dataStart, SkipCnt);
  367. break;
  368. case RECORD_SEND:
  369. recordEnd = ParseSendRecord(dataStart, SkipCnt);
  370. break;
  371. default:
  372. dprintf("Unrecognized record type!\n");
  373. }
  374. records++;
  375. if(TotalValidBytesRead >= BufferCount){
  376. dprintf("\nCompleted parsing trace buffer. %d records found.\n", records);
  377. break;
  378. }
  379. dataStart = FindPreamble(recordEnd, FALSE);
  380. if(dataStart == DataStart){
  381. dprintf("\nCompleted parsing trace buffer. %d records found.\n", records);
  382. break;
  383. }
  384. }
  385. }
  386. VOID
  387. GetBytesToRead(
  388. CHAR * DataStart,
  389. LONG RecordSize,
  390. LONG * BytesToReadFirst,
  391. LONG * BytesToReadNext
  392. )
  393. {
  394. if((DataStart + RecordSize - sizeof(TRACE_PREAMBLE)) > BufferEnd){
  395. *BytesToReadFirst = BufferEnd - DataStart;
  396. *BytesToReadNext = RecordSize - sizeof(TRACE_PREAMBLE) - *BytesToReadFirst;
  397. }
  398. else{
  399. *BytesToReadFirst = RecordSize - sizeof(TRACE_PREAMBLE);
  400. *BytesToReadNext = 0;
  401. }
  402. }
  403. PCHAR
  404. ParseAnyRecord(
  405. CHAR * DataStart,
  406. CHAR * Record,
  407. LONG RecordSize
  408. )
  409. {
  410. LONG bytesToReadFirst;
  411. LONG bytesToReadNext;
  412. BOOL success;
  413. CHAR * nextDataStart;
  414. DWORD bytesread;
  415. CHAR * pRecordData;
  416. CHAR buffer[255];
  417. GetBytesToRead(DataStart, RecordSize, &bytesToReadFirst, &bytesToReadNext);
  418. pRecordData = Record + sizeof(TRACE_PREAMBLE);
  419. success = SafeRead((ULONG)DataStart, pRecordData, bytesToReadFirst, &bytesread );
  420. TotalValidBytesRead += bytesToReadFirst;
  421. if (!success){
  422. dprintf("problems reading memory at %x for %x bytes\n", DataStart, 1);
  423. }
  424. nextDataStart = DataStart + bytesToReadFirst;
  425. if(bytesToReadNext){
  426. success = SafeRead((ULONG)BufferBase,
  427. pRecordData + bytesToReadFirst,
  428. bytesToReadNext,
  429. &bytesread);
  430. TotalValidBytesRead += bytesToReadNext;
  431. if (!success){
  432. dprintf("problems reading memory at %x for %x bytes\n", BufferBase, 1);
  433. }
  434. nextDataStart = BufferBase + bytesToReadNext;
  435. }
  436. return(nextDataStart);
  437. }
  438. PCHAR
  439. ParseOidRecord(
  440. CHAR * DataStart,
  441. ULONG SkipCnt
  442. )
  443. {
  444. TRACE_RECORD_OID record;
  445. CHAR buffer[255];
  446. CHAR * nextDataStart;
  447. static PCHAR OIDActions[] =
  448. {
  449. "",
  450. "MpSetInformation",
  451. "MpQueryInformation",
  452. "SetRequestComplete",
  453. "QueryRequestComplete"
  454. };
  455. nextDataStart = ParseAnyRecord(DataStart, (CHAR *)&record, sizeof(TRACE_RECORD_OID));
  456. if(++LineNumber < SkipCnt)
  457. return nextDataStart;
  458. if(record.Now.QuadPart){
  459. wsprintf(buffer, "[%4d]:[%u.%u]: OID: %5s:%9s:%08X:%08X:%08X \n",
  460. LineNumber,
  461. record.Now.HighPart,
  462. record.Now.LowPart,
  463. OIDActions[record.Action],
  464. record.Local == TRUE?"Local":"Non Local",
  465. record.Adapter,
  466. record.Oid,
  467. record.Status);
  468. }
  469. else {
  470. wsprintf(buffer, "[%4d]: OID: %5s:%9s:%08X:%08X:%08X \n",
  471. LineNumber,
  472. OIDActions[record.Action],
  473. record.Local == TRUE?"Local":"Non Local",
  474. record.Adapter,
  475. record.Oid,
  476. record.Status);
  477. }
  478. switch(FileIt)
  479. {
  480. case OUTPUT_FILE:
  481. MyWriteFile(buffer, FileHandle, dprintf);
  482. break;
  483. case OUTPUT_CONSOLE:
  484. dprintf(buffer);
  485. break;
  486. default:
  487. dprintf("Failed to create file! Check for tmp directory.\n");
  488. break;
  489. }
  490. return(nextDataStart);
  491. }
  492. PCHAR
  493. ParseStringRecord(
  494. CHAR * DataStart,
  495. ULONG SkipCnt
  496. )
  497. {
  498. TRACE_RECORD_STRING record;
  499. LONG bytesToReadFirst;
  500. LONG bytesToReadNext;
  501. BOOL success;
  502. CHAR * nextDataStart;
  503. DWORD bytesread;
  504. CHAR * pRecordData;
  505. CHAR buffer[255];
  506. nextDataStart = ParseAnyRecord(DataStart, (CHAR *)&record, sizeof(TRACE_RECORD_STRING));
  507. if(++LineNumber < SkipCnt)
  508. return nextDataStart;
  509. if(record.Now.QuadPart){
  510. wsprintf(buffer, "[%4d]:[%u.%u]:%s",
  511. LineNumber,
  512. record.Now.HighPart,
  513. record.Now.LowPart,
  514. record.StringStart);
  515. }
  516. else{
  517. wsprintf(buffer, "[%4d]:%s",
  518. LineNumber,
  519. record.StringStart);
  520. }
  521. switch(FileIt)
  522. {
  523. case OUTPUT_FILE:
  524. MyWriteFile(buffer, FileHandle, dprintf);
  525. break;
  526. case OUTPUT_CONSOLE:
  527. dprintf(buffer);
  528. break;
  529. default:
  530. dprintf("Failed to create file! Check for tmp directory.\n");
  531. break;
  532. }
  533. return(nextDataStart);
  534. }
  535. PCHAR
  536. ParseSchedRecord(
  537. CHAR * DataStart,
  538. ULONG SkipCnt
  539. )
  540. {
  541. TRACE_RECORD_SCHED record;
  542. LONG bytesToReadFirst;
  543. LONG bytesToReadNext;
  544. BOOL success;
  545. CHAR * nextDataStart;
  546. DWORD bytesread;
  547. CHAR * pRecordData;
  548. ULONG now;
  549. CHAR buffer[255];
  550. LARGE_INTEGER ConformanceTime;
  551. nextDataStart = ParseAnyRecord(DataStart, (CHAR *)&record, sizeof(TRACE_RECORD_SCHED));
  552. if(++LineNumber < SkipCnt)
  553. return nextDataStart;
  554. ConformanceTime.QuadPart = record.ConformanceTime;
  555. wsprintf(buffer,
  556. "[%4d]:[%u.%u]:%s:VC %x:%x:%u:%s:%d:%d:%u:%u\n",
  557. LineNumber,
  558. record.Now.HighPart,
  559. record.Now.LowPart,
  560. SchedModules[record.SchedulerComponent],
  561. record.VC,
  562. record.Packet,
  563. record.PacketLength,
  564. SchedActions[record.Action],
  565. record.Priority,
  566. ConformanceTime.HighPart,
  567. ConformanceTime.LowPart,
  568. record.PacketsInComponent);
  569. switch(FileIt)
  570. {
  571. case OUTPUT_FILE:
  572. MyWriteFile(buffer, FileHandle, dprintf);
  573. break;
  574. case OUTPUT_CONSOLE:
  575. dprintf(buffer);
  576. break;
  577. default:
  578. dprintf("Failed to create file! Check for tmp directory.\n");
  579. break;
  580. }
  581. return(nextDataStart);
  582. }
  583. PCHAR
  584. ParseRecvRecord(
  585. CHAR * DataStart,
  586. ULONG SkipCnt
  587. )
  588. {
  589. TRACE_RECORD_RECV record;
  590. LONG bytesToReadFirst;
  591. LONG bytesToReadNext;
  592. BOOL success;
  593. CHAR * nextDataStart;
  594. DWORD bytesread;
  595. CHAR * pRecordData;
  596. CHAR buffer[255];
  597. nextDataStart = ParseAnyRecord(DataStart, (CHAR *)&record,
  598. sizeof(TRACE_RECORD_RECV));
  599. if(++LineNumber < SkipCnt)
  600. return nextDataStart;
  601. wsprintf(buffer,
  602. "[%4d]:[%u.%u]:Adapter %08X:%s:%s:%x:%x \n",
  603. LineNumber,
  604. record.Now.HighPart,
  605. record.Now.LowPart,
  606. record.Adapter,
  607. RecvEvents[record.Event],
  608. SendRecvActions[record.Action],
  609. record.Packet1,
  610. record.Packet2);
  611. switch(FileIt)
  612. {
  613. case OUTPUT_FILE:
  614. MyWriteFile(buffer, FileHandle, dprintf);
  615. break;
  616. case OUTPUT_CONSOLE:
  617. dprintf(buffer);
  618. break;
  619. default:
  620. dprintf("Failed to create file! Check for tmp directory.\n");
  621. break;
  622. }
  623. return(nextDataStart);
  624. }
  625. PCHAR
  626. ParseSendRecord(
  627. CHAR * DataStart,
  628. ULONG SkipCnt
  629. )
  630. {
  631. TRACE_RECORD_SEND record;
  632. LONG bytesToReadFirst;
  633. LONG bytesToReadNext;
  634. BOOL success;
  635. CHAR * nextDataStart;
  636. DWORD bytesread;
  637. CHAR * pRecordData;
  638. CHAR buffer[255];
  639. nextDataStart = ParseAnyRecord(DataStart, (CHAR *)&record,
  640. sizeof(TRACE_RECORD_SEND));
  641. if(++LineNumber < SkipCnt)
  642. return nextDataStart;
  643. wsprintf(buffer,
  644. "[%4d]:[%u.%u]:Adapter %08X:%s:%s:%x:%x:%x\n",
  645. LineNumber,
  646. record.Now.HighPart,
  647. record.Now.LowPart,
  648. record.Adapter,
  649. SendEvents[record.Event],
  650. SendRecvActions[record.Action],
  651. record.Vc,
  652. record.Packet1,
  653. record.Packet2);
  654. switch(FileIt)
  655. {
  656. case OUTPUT_FILE:
  657. MyWriteFile(buffer, FileHandle, dprintf);
  658. break;
  659. case OUTPUT_CONSOLE:
  660. dprintf(buffer);
  661. break;
  662. default:
  663. dprintf("Failed to create file! Check for tmp directory.\n");
  664. break;
  665. }
  666. return(nextDataStart);
  667. }