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.

862 lines
15 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. dbgutil.c
  5. Abstract:
  6. Utility functions for dealing with the kernel debugger.
  7. Author:
  8. Keith Moore (keithmo) 17-Jun-1998
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. //
  15. // Private constants.
  16. //
  17. #define EXT_DLL "kdexts.dll"
  18. //
  19. // Private globals.
  20. //
  21. PSTR WeekdayNames[] =
  22. {
  23. "Sunday",
  24. "Monday",
  25. "Tuesday",
  26. "Wednesday",
  27. "Thursday",
  28. "Friday",
  29. "Saturday"
  30. };
  31. PSTR MonthNames[] =
  32. {
  33. "",
  34. "January",
  35. "February",
  36. "March",
  37. "April",
  38. "May",
  39. "June",
  40. "July",
  41. "August",
  42. "September",
  43. "October",
  44. "November",
  45. "December"
  46. };
  47. HMODULE ExtensionDll = NULL;
  48. //
  49. // Public functions.
  50. //
  51. VOID
  52. SystemTimeToString(
  53. IN LONGLONG Value,
  54. OUT PSTR Buffer
  55. )
  56. /*++
  57. Routine Description:
  58. Maps a LONGLONG representing system time to a displayable string.
  59. Arguments:
  60. Value - The LONGLONG time to map.
  61. Buffer - Receives the mapped time.
  62. Return Value:
  63. None.
  64. --*/
  65. {
  66. NTSTATUS status;
  67. LARGE_INTEGER systemTime;
  68. LARGE_INTEGER localTime;
  69. TIME_FIELDS timeFields;
  70. systemTime.QuadPart = Value;
  71. status = RtlSystemTimeToLocalTime( &systemTime, &localTime );
  72. if( !NT_SUCCESS(status) ) {
  73. sprintf( Buffer, "%I64d", Value );
  74. return;
  75. }
  76. RtlTimeToTimeFields( &localTime, &timeFields );
  77. sprintf(
  78. Buffer,
  79. "%s %s %2d %4d %02d:%02d:%02d.%03d",
  80. WeekdayNames[timeFields.Weekday],
  81. MonthNames[timeFields.Month],
  82. timeFields.Day,
  83. timeFields.Year,
  84. timeFields.Hour,
  85. timeFields.Minute,
  86. timeFields.Second,
  87. timeFields.Milliseconds
  88. );
  89. } // SystemTimeToString
  90. PSTR
  91. SignatureToString(
  92. IN ULONG CurrentSignature,
  93. IN ULONG ValidSignature,
  94. IN ULONG FreedSignature,
  95. OUT PSTR Buffer
  96. )
  97. {
  98. PSTR pstr = Buffer;
  99. int i;
  100. UCHAR ch;
  101. *pstr++ = '\'';
  102. for (i = 0; i < 4; ++i)
  103. {
  104. ch = (UCHAR)((CurrentSignature >> (8 * i)) & 0xFF);
  105. *pstr++ = isprint(ch) ? (ch) : '?';
  106. }
  107. *pstr++ = '\'';
  108. *pstr++ = ' ';
  109. *pstr = '\0';
  110. if (CurrentSignature == ValidSignature)
  111. {
  112. strcat(pstr, "OK");
  113. }
  114. else if (CurrentSignature == FreedSignature)
  115. {
  116. strcat(pstr, "FREED");
  117. }
  118. else
  119. {
  120. strcat(pstr, "INVALID");
  121. }
  122. return Buffer;
  123. } // SignatureToString
  124. PSTR
  125. ParseStateToString(
  126. IN PARSE_STATE State
  127. )
  128. {
  129. PSTR result;
  130. switch (State)
  131. {
  132. case ParseVerbState:
  133. result = "ParseVerbState";
  134. break;
  135. case ParseUrlState:
  136. result = "ParseUrlState";
  137. break;
  138. case ParseVersionState:
  139. result = "ParseVersionState";
  140. break;
  141. case ParseHeadersState:
  142. result = "ParseHeadersState";
  143. break;
  144. case ParseCookState:
  145. result = "ParseCookState";
  146. break;
  147. case ParseEntityBodyState:
  148. result = "ParseEntityBodyState";
  149. break;
  150. case ParseTrailerState:
  151. result = "ParseTrailerState";
  152. break;
  153. case ParseDoneState:
  154. result = "ParseDoneState";
  155. break;
  156. case ParseErrorState:
  157. result = "ParseErrorState";
  158. break;
  159. default:
  160. result = "INVALID";
  161. break;
  162. }
  163. return result;
  164. } // ParseStateToString
  165. PSTR
  166. UlEnabledStateToString(
  167. IN HTTP_ENABLED_STATE State
  168. )
  169. {
  170. PSTR result;
  171. switch (State)
  172. {
  173. case HttpEnabledStateActive:
  174. result = "HttpEnabledStateActive";
  175. break;
  176. case HttpEnabledStateInactive:
  177. result = "HttpEnabledStateInactive";
  178. break;
  179. default:
  180. result = "INVALID";
  181. break;
  182. }
  183. return result;
  184. }
  185. PSTR
  186. CachePolicyToString(
  187. IN HTTP_CACHE_POLICY_TYPE PolicyType
  188. )
  189. {
  190. PSTR result;
  191. switch (PolicyType)
  192. {
  193. case HttpCachePolicyNocache:
  194. result = "HttpCachePolicyNocache";
  195. break;
  196. case HttpCachePolicyUserInvalidates:
  197. result = "HttpCachePolicyUserInvalidates";
  198. break;
  199. case HttpCachePolicyTimeToLive:
  200. result = "HttpCachePolicyTimeToLive";
  201. break;
  202. default:
  203. result = "INVALID";
  204. break;
  205. }
  206. return result;
  207. }
  208. PSTR
  209. VerbToString(
  210. IN HTTP_VERB Verb
  211. )
  212. {
  213. PSTR result;
  214. switch (Verb)
  215. {
  216. case HttpVerbUnparsed:
  217. result = "UnparsedVerb";
  218. break;
  219. case HttpVerbGET:
  220. result = "GET";
  221. break;
  222. case HttpVerbPUT:
  223. result = "PUT";
  224. break;
  225. case HttpVerbHEAD:
  226. result = "HEAD";
  227. break;
  228. case HttpVerbPOST:
  229. result = "POST";
  230. break;
  231. case HttpVerbDELETE:
  232. result = "DELETE";
  233. break;
  234. case HttpVerbTRACE:
  235. result = "TRACE";
  236. break;
  237. case HttpVerbOPTIONS:
  238. result = "OPTIONS";
  239. break;
  240. case HttpVerbCONNECT:
  241. result = "CONNECT";
  242. break;
  243. case HttpVerbMOVE:
  244. result = "MOVE";
  245. break;
  246. case HttpVerbCOPY:
  247. result = "COPY";
  248. break;
  249. case HttpVerbPROPFIND:
  250. result = "PROPFIND";
  251. break;
  252. case HttpVerbPROPPATCH:
  253. result = "PROPPATCH";
  254. break;
  255. case HttpVerbMKCOL:
  256. result = "MKCOL";
  257. break;
  258. case HttpVerbLOCK:
  259. result = "LOCK";
  260. break;
  261. case HttpVerbUNLOCK:
  262. result = "LOCK";
  263. break;
  264. case HttpVerbSEARCH:
  265. result = "SEARCH";
  266. break;
  267. case HttpVerbUnknown:
  268. result = "UnknownVerb";
  269. break;
  270. case HttpVerbInvalid:
  271. result = "InvalidVerb";
  272. break;
  273. default:
  274. result = "INVALID";
  275. break;
  276. }
  277. return result;
  278. } // VerbToString
  279. PSTR
  280. VersionToString(
  281. IN HTTP_VERSION Version
  282. )
  283. {
  284. PSTR result;
  285. if (HTTP_EQUAL_VERSION(Version, 0, 9))
  286. {
  287. result = "Version09";
  288. }
  289. else
  290. if (HTTP_EQUAL_VERSION(Version, 1, 0))
  291. {
  292. result = "Version10";
  293. }
  294. else
  295. if (HTTP_EQUAL_VERSION(Version, 1, 1))
  296. {
  297. result = "Version11";
  298. }
  299. else
  300. {
  301. result = "INVALID";
  302. }
  303. return result;
  304. } // VersionToString
  305. PSTR
  306. QueueStateToString(
  307. IN QUEUE_STATE QueueState
  308. )
  309. {
  310. PSTR result;
  311. switch (QueueState)
  312. {
  313. case QueueUnroutedState:
  314. result = "QueueUnroutedState";
  315. break;
  316. case QueueDeliveredState:
  317. result = "QueueDeliveredState";
  318. break;
  319. case QueueCopiedState:
  320. result = "QueueCopiedState";
  321. break;
  322. case QueueUnlinkedState:
  323. result = "QueueUnlinkedState";
  324. break;
  325. default:
  326. result = "INVALID";
  327. break;
  328. }
  329. return result;
  330. }
  331. VOID
  332. BuildSymbol(
  333. IN PVOID RemoteAddress,
  334. OUT PSTR Symbol
  335. )
  336. {
  337. ULONG_PTR offset;
  338. CHAR tmpSymbol[MAX_SYMBOL_LENGTH];
  339. tmpSymbol[0] = '\0';
  340. GetSymbol( RemoteAddress, tmpSymbol, &offset );
  341. if (tmpSymbol[0] == '\0')
  342. {
  343. Symbol[0] = '\0';
  344. }
  345. else
  346. if (offset == 0)
  347. {
  348. strcpy( Symbol, (PCHAR)tmpSymbol );
  349. }
  350. else
  351. {
  352. sprintf( Symbol, "%s+0x%p", tmpSymbol, offset );
  353. }
  354. } // BuildSymbol
  355. PSTR
  356. GetSpinlockState(
  357. IN PUL_SPIN_LOCK SpinLock
  358. )
  359. {
  360. if (*((PULONG_PTR)SpinLock) == 0)
  361. {
  362. return "FREE";
  363. }
  364. else
  365. {
  366. return "ACQUIRED";
  367. }
  368. } // GetSpinlockState
  369. BOOLEAN
  370. EnumLinkedList(
  371. IN PLIST_ENTRY RemoteListHead,
  372. IN PENUM_LINKED_LIST_CALLBACK Callback,
  373. IN PVOID Context
  374. )
  375. {
  376. LIST_ENTRY localListEntry;
  377. PLIST_ENTRY nextRemoteListEntry;
  378. ULONG result;
  379. //
  380. // Try to read the list head.
  381. //
  382. if (!ReadMemory(
  383. (ULONG_PTR)RemoteListHead,
  384. &localListEntry,
  385. sizeof(localListEntry),
  386. &result
  387. ))
  388. {
  389. return FALSE;
  390. }
  391. //
  392. // Loop through the entries.
  393. //
  394. nextRemoteListEntry = localListEntry.Flink;
  395. while (nextRemoteListEntry != RemoteListHead)
  396. {
  397. if (CheckControlC())
  398. {
  399. break;
  400. }
  401. if (!(Callback)( nextRemoteListEntry, Context ))
  402. {
  403. break;
  404. }
  405. if (!ReadMemory(
  406. (ULONG_PTR)nextRemoteListEntry,
  407. &localListEntry,
  408. sizeof(localListEntry),
  409. &result
  410. ))
  411. {
  412. return FALSE;
  413. }
  414. nextRemoteListEntry = localListEntry.Flink;
  415. }
  416. return TRUE;
  417. } // EnumLinkedList
  418. BOOLEAN
  419. EnumSList(
  420. IN PSLIST_HEADER RemoteSListHead,
  421. IN PENUM_SLIST_CALLBACK Callback,
  422. IN PVOID Context
  423. )
  424. {
  425. SLIST_HEADER localSListHead;
  426. SINGLE_LIST_ENTRY localSListEntry;
  427. PSINGLE_LIST_ENTRY nextRemoteSListEntry;
  428. ULONG result;
  429. //
  430. // Try to read the list head.
  431. //
  432. if (!ReadMemory(
  433. (ULONG_PTR)RemoteSListHead,
  434. &localSListHead,
  435. sizeof(localSListHead),
  436. &result
  437. ))
  438. {
  439. return FALSE;
  440. }
  441. //
  442. // Loop through the entries.
  443. //
  444. nextRemoteSListEntry = SLIST_HEADER_NEXT(&localSListHead);
  445. while (nextRemoteSListEntry != NULL)
  446. {
  447. if (CheckControlC())
  448. {
  449. break;
  450. }
  451. if (!(Callback)( nextRemoteSListEntry, Context ))
  452. {
  453. break;
  454. }
  455. if (!ReadMemory(
  456. (ULONG_PTR)nextRemoteSListEntry,
  457. &localSListEntry,
  458. sizeof(localSListEntry),
  459. &result
  460. ))
  461. {
  462. return FALSE;
  463. }
  464. nextRemoteSListEntry = localSListEntry.Next;
  465. }
  466. return TRUE;
  467. } // EnumSList
  468. PSTR
  469. BuildResourceState(
  470. IN PUL_ERESOURCE LocalAddress,
  471. OUT PSTR Buffer
  472. )
  473. {
  474. PERESOURCE pResource;
  475. pResource = (PERESOURCE)LocalAddress;
  476. if (pResource->ActiveCount == 0)
  477. {
  478. sprintf(
  479. Buffer,
  480. "UNOWNED"
  481. );
  482. }
  483. else
  484. {
  485. if ((pResource->Flag & ResourceOwnedExclusive) != 0)
  486. {
  487. sprintf(
  488. Buffer,
  489. "OWNED EXCLUSIVE BY %p [%ld]",
  490. pResource->OwnerThreads[0].OwnerThread,
  491. pResource->OwnerThreads[0].OwnerCount
  492. );
  493. }
  494. else
  495. {
  496. sprintf(
  497. Buffer,
  498. "OWNED SHARED"
  499. );
  500. }
  501. }
  502. return Buffer;
  503. } // BuildResourceState
  504. BOOLEAN
  505. IsThisACheckedBuild(
  506. VOID
  507. )
  508. {
  509. ULONG_PTR address;
  510. ULONG value = 0;
  511. ULONG result;
  512. BOOLEAN isChecked = FALSE;
  513. address = GetExpression( "&http!g_UlCheckedBuild" );
  514. if (address != 0)
  515. {
  516. if (ReadMemory(
  517. address,
  518. &value,
  519. sizeof(value),
  520. &result
  521. ))
  522. {
  523. isChecked = (value != 0);
  524. }
  525. }
  526. return isChecked;
  527. } // IsThisACheckedBuild
  528. VOID
  529. DumpBitVector(
  530. IN PSTR Prefix1,
  531. IN PSTR Prefix2,
  532. IN ULONG Vector,
  533. IN PVECTORMAP VectorMap
  534. )
  535. {
  536. while ((Vector != 0) && (VectorMap->Vector != 0))
  537. {
  538. if (Vector & VectorMap->Vector)
  539. {
  540. dprintf(
  541. "%s%s%s\n",
  542. Prefix1,
  543. Prefix2,
  544. VectorMap->Name
  545. );
  546. Vector &= ~(VectorMap->Vector);
  547. }
  548. VectorMap++;
  549. }
  550. if (Vector != 0)
  551. {
  552. dprintf(
  553. "%s%sExtra Bits = %08lx\n",
  554. Prefix1,
  555. Prefix2,
  556. Vector
  557. );
  558. }
  559. } // DumpBitVector
  560. VOID
  561. DumpRawData(
  562. IN PSTR Prefix,
  563. IN ULONG_PTR RemoteAddress,
  564. IN ULONG BufferLength
  565. )
  566. {
  567. PSTR lineScan;
  568. ULONG lineLength;
  569. ULONG i;
  570. ULONG result;
  571. UCHAR ch;
  572. UCHAR rawData[16];
  573. CHAR formattedData[sizeof("1234567812345678 11 22 33 44 55 66 77 88-99 aa bb cc dd ee ff 00 123456789abcdef0")];
  574. while (BufferLength > 0)
  575. {
  576. lineLength = (BufferLength > 16) ? 16 : BufferLength;
  577. if (!ReadMemory(
  578. RemoteAddress,
  579. rawData,
  580. lineLength,
  581. &result
  582. ))
  583. {
  584. dprintf( "%sCannot read memory @ %p\n", Prefix, RemoteAddress );
  585. break;
  586. }
  587. lineScan = formattedData;
  588. lineScan += sprintf( lineScan, "%p ", RemoteAddress );
  589. for (i = 0 ; i < 16 ; i++)
  590. {
  591. if (i < lineLength)
  592. {
  593. lineScan += sprintf(
  594. lineScan,
  595. "%02X%c",
  596. rawData[i],
  597. (i == 7)
  598. ? '-'
  599. : ' '
  600. );
  601. }
  602. else
  603. {
  604. *lineScan++ = ' ';
  605. *lineScan++ = ' ';
  606. *lineScan++ = ' ';
  607. }
  608. }
  609. *lineScan++ = ' ';
  610. *lineScan++ = ' ';
  611. for (i = 0 ; i < 16 ; i++)
  612. {
  613. if (i < lineLength)
  614. {
  615. ch = rawData[i];
  616. if ((ch < ' ') || (ch > '~'))
  617. {
  618. ch = '.';
  619. }
  620. }
  621. else
  622. {
  623. ch = ' ';
  624. }
  625. *lineScan++ = ch;
  626. }
  627. *lineScan = '\0';
  628. dprintf(
  629. "%s%s\n",
  630. Prefix,
  631. formattedData
  632. );
  633. BufferLength -= lineLength;
  634. RemoteAddress += (ULONG_PTR)lineLength;
  635. }
  636. } // DumpRawData
  637. BOOLEAN
  638. CallExtensionRoutine(
  639. IN PSTR RoutineName,
  640. IN PSTR ArgumentString
  641. )
  642. {
  643. #if _WIN64
  644. PWINDBG_EXTENSION_ROUTINE64 ExtRoutine;
  645. #else
  646. PWINDBG_EXTENSION_ROUTINE ExtRoutine;
  647. #endif
  648. BOOLEAN result = FALSE;
  649. #ifdef EXT_DLL
  650. if (ExtensionDll == NULL)
  651. {
  652. ExtensionDll = LoadLibraryA( EXT_DLL );
  653. }
  654. #endif
  655. if (ExtensionDll != NULL)
  656. {
  657. #if _WIN64
  658. ExtRoutine = (PWINDBG_EXTENSION_ROUTINE64)GetProcAddress(
  659. ExtensionDll,
  660. RoutineName
  661. );
  662. #else
  663. ExtRoutine = (PWINDBG_EXTENSION_ROUTINE)GetProcAddress(
  664. ExtensionDll,
  665. RoutineName
  666. );
  667. #endif
  668. if (ExtRoutine != NULL)
  669. {
  670. (ExtRoutine)(
  671. g_hCurrentProcess,
  672. g_hCurrentThread,
  673. g_dwCurrentPc,
  674. g_dwProcessor,
  675. ArgumentString
  676. );
  677. result = TRUE;
  678. }
  679. }
  680. return result;
  681. } // CallExtensionRoutine