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.

4768 lines
115 KiB

  1. /*++
  2. Copyright (c) 1990-2001 Microsoft Corporation
  3. Module Name:
  4. kdapi.c
  5. Abstract:
  6. Implementation of Kernel Debugger portable remote APIs.
  7. Author:
  8. Mark Lucovsky (markl) 31-Aug-1990
  9. Revision History:
  10. John Vert (jvert) 28-May-1991
  11. Added APIs for reading and writing physical memory
  12. (KdpReadPhysicalMemory and KdpWritePhysicalMemory)
  13. Wesley Witt (wesw) 18-Aug-1993
  14. Added KdpGetVersion, KdpWriteBreakPointEx, & KdpRestoreBreakPointEx
  15. --*/
  16. #include "kdp.h"
  17. #if ACCASM && !defined(_MSC_VER)
  18. long asm(const char *,...);
  19. #pragma intrinsic(asm)
  20. #endif
  21. // XXX drewb - Shortcut to avoid cross-depot checkin
  22. // build delay. These constants are defined in ntdbg.h
  23. // from the sdktools depot. Once the internal sdktools
  24. // ntdbg.h is updated from ntdbg.w this can be removed.
  25. #ifndef DBGKD_CACHING_UNKNOWN
  26. #define DBGKD_CACHING_UNKNOWN 0
  27. #define DBGKD_CACHING_CACHED 1
  28. #define DBGKD_CACHING_UNCACHED 2
  29. #define DBGKD_CACHING_WRITE_COMBINED 3
  30. #endif
  31. BOOLEAN KdpContextSent;
  32. LARGE_INTEGER KdpQueryPerformanceCounter (
  33. IN PKTRAP_FRAME TrapFrame
  34. );
  35. extern LARGE_INTEGER Magic10000;
  36. #define SHIFT10000 13
  37. #define Convert100nsToMilliseconds(LARGE_INTEGER) ( \
  38. RtlExtendedMagicDivide( (LARGE_INTEGER), Magic10000, SHIFT10000 ) \
  39. )
  40. //
  41. // Define forward referenced function prototypes.
  42. //
  43. VOID
  44. KdpProcessInternalBreakpoint (
  45. ULONG BreakpointNumber
  46. );
  47. VOID
  48. KdpGetVersion(
  49. IN PDBGKD_MANIPULATE_STATE64 m
  50. );
  51. NTSTATUS
  52. KdpNotSupported(
  53. IN PDBGKD_MANIPULATE_STATE64 m
  54. );
  55. VOID
  56. KdpCauseBugCheck(
  57. IN PDBGKD_MANIPULATE_STATE64 m
  58. );
  59. NTSTATUS
  60. KdpWriteBreakPointEx(
  61. IN PDBGKD_MANIPULATE_STATE64 m,
  62. IN PSTRING AdditionalData,
  63. IN PCONTEXT Context
  64. );
  65. VOID
  66. KdpRestoreBreakPointEx(
  67. IN PDBGKD_MANIPULATE_STATE64 m,
  68. IN PSTRING AdditionalData,
  69. IN PCONTEXT Context
  70. );
  71. VOID
  72. KdpSearchMemory(
  73. IN PDBGKD_MANIPULATE_STATE64 m,
  74. IN PSTRING AdditionalData,
  75. IN PCONTEXT Context
  76. );
  77. ULONG
  78. KdpSearchHammingDistance (
  79. ULONG_PTR Left,
  80. ULONG_PTR Right
  81. );
  82. LOGICAL
  83. KdpSearchPhysicalPage (
  84. IN PFN_NUMBER PageFrameIndex,
  85. ULONG_PTR RangeStart,
  86. ULONG_PTR RangeEnd,
  87. ULONG Flags
  88. );
  89. LOGICAL
  90. KdpSearchPhysicalMemoryRequested (
  91. VOID
  92. );
  93. LOGICAL
  94. KdpSearchPhysicalPageRange (
  95. VOID
  96. );
  97. VOID
  98. KdpFillMemory(
  99. IN PDBGKD_MANIPULATE_STATE64 m,
  100. IN PSTRING AdditionalData,
  101. IN PCONTEXT Context
  102. );
  103. VOID
  104. KdpQueryMemory(
  105. IN PDBGKD_MANIPULATE_STATE64 m,
  106. IN PCONTEXT Context
  107. );
  108. #if i386
  109. VOID
  110. InternalBreakpointCheck (
  111. PKDPC Dpc,
  112. PVOID DeferredContext,
  113. PVOID SystemArgument1,
  114. PVOID SystemArgument2
  115. );
  116. VOID
  117. KdGetInternalBreakpoint(
  118. IN PDBGKD_MANIPULATE_STATE64 m
  119. );
  120. long
  121. SymNumFor(
  122. ULONG_PTR pc
  123. );
  124. void PotentialNewSymbol (ULONG_PTR pc);
  125. void DumpTraceData(PSTRING MessageData);
  126. BOOLEAN
  127. TraceDataRecordCallInfo(
  128. ULONG InstructionsTraced,
  129. LONG CallLevelChange,
  130. ULONG_PTR pc
  131. );
  132. BOOLEAN
  133. SkippingWhichBP (
  134. PVOID thread,
  135. PULONG BPNum
  136. );
  137. ULONG_PTR
  138. KdpGetReturnAddress(
  139. IN PCONTEXT ContextRecord
  140. );
  141. ULONG_PTR
  142. KdpGetCallNextOffset (
  143. ULONG_PTR Pc,
  144. IN PCONTEXT ContextRecord
  145. );
  146. LONG
  147. KdpLevelChange (
  148. ULONG_PTR Pc,
  149. PCONTEXT ContextRecord,
  150. IN OUT PBOOLEAN SpecialCall
  151. );
  152. #endif // i386
  153. #ifdef ALLOC_PRAGMA
  154. #pragma alloc_text(PAGEKD, KdEnterDebugger)
  155. #pragma alloc_text(PAGEKD, KdExitDebugger)
  156. #pragma alloc_text(PAGEKD, KdpTimeSlipDpcRoutine)
  157. #pragma alloc_text(PAGEKD, KdpTimeSlipWork)
  158. #pragma alloc_text(PAGEKD, KdpSendWaitContinue)
  159. #pragma alloc_text(PAGEKD, KdpReadVirtualMemory)
  160. //#pragma alloc_text(PAGEKD, KdpReadVirtualMemory64)
  161. #pragma alloc_text(PAGEKD, KdpWriteVirtualMemory)
  162. //#pragma alloc_text(PAGEKD, KdpWriteVirtualMemory64)
  163. #pragma alloc_text(PAGEKD, KdpGetContext)
  164. #pragma alloc_text(PAGEKD, KdpSetContext)
  165. #pragma alloc_text(PAGEKD, KdpWriteBreakpoint)
  166. #pragma alloc_text(PAGEKD, KdpRestoreBreakpoint)
  167. #pragma alloc_text(PAGEKD, KdpReportExceptionStateChange)
  168. #pragma alloc_text(PAGEKD, KdpReportLoadSymbolsStateChange)
  169. #pragma alloc_text(PAGEKD, KdpReportCommandStringStateChange)
  170. #pragma alloc_text(PAGEKD, KdpReadPhysicalMemory)
  171. #pragma alloc_text(PAGEKD, KdpWritePhysicalMemory)
  172. #pragma alloc_text(PAGEKD, KdpReadControlSpace)
  173. #pragma alloc_text(PAGEKD, KdpWriteControlSpace)
  174. #pragma alloc_text(PAGEKD, KdpReadIoSpace)
  175. #pragma alloc_text(PAGEKD, KdpWriteIoSpace)
  176. #pragma alloc_text(PAGEKD, KdpReadIoSpaceExtended)
  177. #pragma alloc_text(PAGEKD, KdpWriteIoSpaceExtended)
  178. #pragma alloc_text(PAGEKD, KdpReadMachineSpecificRegister)
  179. #pragma alloc_text(PAGEKD, KdpWriteMachineSpecificRegister)
  180. #pragma alloc_text(PAGEKD, KdpGetBusData)
  181. #pragma alloc_text(PAGEKD, KdpSetBusData)
  182. #pragma alloc_text(PAGEKD, KdpGetVersion)
  183. #pragma alloc_text(PAGEKD, KdpNotSupported)
  184. #pragma alloc_text(PAGEKD, KdpCauseBugCheck)
  185. #pragma alloc_text(PAGEKD, KdpWriteBreakPointEx)
  186. #pragma alloc_text(PAGEKD, KdpRestoreBreakPointEx)
  187. #pragma alloc_text(PAGEKD, KdpSearchMemory)
  188. #pragma alloc_text(PAGEKD, KdpSearchHammingDistance)
  189. #pragma alloc_text(PAGEKD, KdpSearchPhysicalPage)
  190. #pragma alloc_text(PAGEKD, KdpSearchPhysicalMemoryRequested)
  191. #pragma alloc_text(PAGEKD, KdpSearchPhysicalPageRange)
  192. #pragma alloc_text(PAGEKD, KdpCheckLowMemory)
  193. #pragma alloc_text(PAGEKD, KdpFillMemory)
  194. #pragma alloc_text(PAGEKD, KdpQueryMemory)
  195. #pragma alloc_text(PAGEKD, KdpSysGetVersion)
  196. #pragma alloc_text(PAGEKD, KdpSysReadBusData)
  197. #pragma alloc_text(PAGEKD, KdpSysWriteBusData)
  198. #pragma alloc_text(PAGEKD, KdpSysCheckLowMemory)
  199. #pragma alloc_text(PAGEKD, KdpSendTraceData)
  200. #pragma alloc_text(PAGEKD, KdReportTraceData)
  201. #if DBG
  202. #pragma alloc_text(PAGEKD, KdpDprintf)
  203. #endif
  204. #if i386
  205. #pragma alloc_text(PAGEKD, InternalBreakpointCheck)
  206. #pragma alloc_text(PAGEKD, KdSetInternalBreakpoint)
  207. #pragma alloc_text(PAGEKD, KdGetTraceInformation)
  208. #pragma alloc_text(PAGEKD, KdGetInternalBreakpoint)
  209. #pragma alloc_text(PAGEKD, SymNumFor)
  210. #pragma alloc_text(PAGEKD, PotentialNewSymbol)
  211. #pragma alloc_text(PAGEKD, DumpTraceData)
  212. #pragma alloc_text(PAGEKD, TraceDataRecordCallInfo)
  213. #pragma alloc_text(PAGEKD, SkippingWhichBP)
  214. #pragma alloc_text(PAGEKD, KdQuerySpecialCalls)
  215. #pragma alloc_text(PAGEKD, KdSetSpecialCall)
  216. #pragma alloc_text(PAGEKD, KdClearSpecialCalls)
  217. #pragma alloc_text(PAGEKD, KdpCheckTracePoint)
  218. #pragma alloc_text(PAGEKD, KdpProcessInternalBreakpoint)
  219. #endif // i386
  220. #endif // ALLOC_PRAGMA
  221. //
  222. // This variable has a count for each time KdDisableDebugger has been called.
  223. //
  224. LONG KdDisableCount = 0 ;
  225. BOOLEAN KdPreviouslyEnabled = FALSE ;
  226. #if DBG
  227. VOID
  228. KdpDprintf(
  229. IN PCHAR f,
  230. ...
  231. )
  232. /*++
  233. Routine Description:
  234. Printf routine for the debugger that is safer than DbgPrint. Calls
  235. the packet driver instead of reentering the debugger.
  236. Arguments:
  237. f - Supplies printf format
  238. Return Value:
  239. None
  240. --*/
  241. {
  242. char buf[100];
  243. STRING Output;
  244. va_list mark;
  245. va_start(mark, f);
  246. _vsnprintf(buf, 100, f, mark);
  247. va_end(mark);
  248. Output.Buffer = buf;
  249. Output.Length = (USHORT) strlen(Output.Buffer);
  250. KdpPrintString(&Output);
  251. }
  252. #endif // DBG
  253. BOOLEAN
  254. KdEnterDebugger(
  255. IN PKTRAP_FRAME TrapFrame,
  256. IN PKEXCEPTION_FRAME ExceptionFrame
  257. )
  258. /*++
  259. Routine Description:
  260. This function is used to enter the kernel debugger. Its purpose
  261. is to freeze all other processors and aqcuire the kernel debugger
  262. comm port.
  263. Arguments:
  264. TrapFrame - Supplies a pointer to a trap frame that describes the
  265. trap.
  266. ExceptionFrame - Supplies a pointer to an exception frame that
  267. describes the trap.
  268. Return Value:
  269. Returns the previous interrupt enable.
  270. --*/
  271. {
  272. BOOLEAN Enable;
  273. TIME_FIELDS TimeFields;
  274. #if DBG
  275. extern ULONG KiFreezeFlag;
  276. #endif
  277. //
  278. // HACKHACK - do some crude timer support
  279. // but not if called from KdSetOwedBreakpoints()
  280. //
  281. if (TrapFrame) {
  282. KdTimerStop = KdpQueryPerformanceCounter (TrapFrame);
  283. KdTimerDifference.QuadPart = KdTimerStop.QuadPart - KdTimerStart.QuadPart;
  284. } else {
  285. KdTimerStop.QuadPart = 0;
  286. }
  287. //
  288. // Freeze all other processors, raise IRQL to HIGH_LEVEL, and save debug
  289. // port state. We lock the port so that KdPollBreakin and a debugger
  290. // operation don't interfere with each other.
  291. //
  292. Enable = KeFreezeExecution(TrapFrame, ExceptionFrame);
  293. KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
  294. KdSave(FALSE);
  295. KdEnteredDebugger = TRUE;
  296. #if DBG
  297. if ((KiFreezeFlag & FREEZE_BACKUP) != 0) {
  298. DPRINT(("FreezeLock was jammed! Backup SpinLock was used!\n"));
  299. }
  300. if ((KiFreezeFlag & FREEZE_SKIPPED_PROCESSOR) != 0) {
  301. DPRINT(("Some processors not frozen in debugger!\n"));
  302. }
  303. if (KdpPortLocked == FALSE) {
  304. DPRINT(("Port lock was not acquired!\n"));
  305. }
  306. #endif
  307. return Enable;
  308. }
  309. VOID
  310. KdExitDebugger(
  311. IN BOOLEAN Enable
  312. )
  313. /*++
  314. Routine Description:
  315. This function is used to exit the kernel debugger. It is the reverse
  316. of KdEnterDebugger.
  317. Arguments:
  318. Enable - Supplies the previous interrupt enable which is to be restored.
  319. Return Value:
  320. None.
  321. --*/
  322. {
  323. ULONG ElapsedTime;
  324. ULARGE_INTEGER TimeDifference;
  325. TIME_FIELDS TimeFields;
  326. ULONG Pending;
  327. //
  328. // restore stuff and exit
  329. //
  330. KdRestore(FALSE);
  331. if (KdpPortLocked) {
  332. KdpPortUnlock();
  333. }
  334. KeThawExecution(Enable);
  335. //
  336. // Do some crude timer support. If KdEnterDebugger didn't
  337. // Query the performance counter, then don't do it here either.
  338. //
  339. if (KdTimerStop.QuadPart == 0) {
  340. KdTimerStart = KdTimerStop;
  341. } else {
  342. KdTimerStart = KeQueryPerformanceCounter(NULL);
  343. }
  344. //
  345. // Process a time slip
  346. //
  347. if (!PoHiberInProgress) {
  348. Pending = InterlockedIncrement(&KdpTimeSlipPending);
  349. //
  350. // If there's wasn't a time slip pending, queue the DPC to handle it
  351. //
  352. if (Pending == 1) {
  353. InterlockedIncrement(&KdpTimeSlipPending);
  354. KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL);
  355. }
  356. }
  357. return;
  358. }
  359. VOID
  360. KdUpdateTimeSlipEvent(
  361. PVOID Event
  362. )
  363. /*++
  364. Routine Description:
  365. Update the reference to an event object which will be signalled when
  366. the debugger has caused the system clock to skew.
  367. Arguments:
  368. Event - Supplies a pointer to an event object
  369. Return Value:
  370. None
  371. --*/
  372. {
  373. KIRQL OldIrql;
  374. KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
  375. //
  376. // Dereference the old event and forget about it.
  377. // Remember the new event if there is one.
  378. //
  379. if (KdpTimeSlipEvent != NULL) {
  380. ObDereferenceObject(KdpTimeSlipEvent);
  381. }
  382. KdpTimeSlipEvent = Event;
  383. KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
  384. }
  385. VOID
  386. KdpTimeSlipDpcRoutine (
  387. PKDPC Dpc,
  388. PVOID DeferredContext,
  389. PVOID SystemArgument1,
  390. PVOID SystemArgument2
  391. )
  392. {
  393. LONG OldCount, NewCount, j;
  394. //
  395. // Reset pending count. If the current count is 1, then clear
  396. // the pending count. if the current count is greater then 1,
  397. // then set to one and update the time now.
  398. //
  399. j = KdpTimeSlipPending;
  400. do {
  401. OldCount = j;
  402. NewCount = OldCount > 1 ? 1 : 0;
  403. j = InterlockedCompareExchange(&KdpTimeSlipPending, NewCount, OldCount);
  404. } while (j != OldCount);
  405. //
  406. // If new count is non-zero, then process a time slip now
  407. //
  408. if (NewCount) {
  409. ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
  410. }
  411. }
  412. VOID
  413. KdpTimeSlipWork (
  414. IN PVOID Context
  415. )
  416. {
  417. KIRQL OldIrql;
  418. LARGE_INTEGER DueTime;
  419. //
  420. // Update time from the real time clock.
  421. // If the lock is held by somebody else, don't bother as it's not worth
  422. // tying up a worker thread.
  423. //
  424. if (ExAcquireTimeRefreshLock(FALSE)) {
  425. ExUpdateSystemTimeFromCmos (FALSE, 0);
  426. ExReleaseTimeRefreshLock();
  427. //
  428. // If there's a time service installed, signal it's time slip event
  429. //
  430. KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
  431. if (KdpTimeSlipEvent) {
  432. KeSetEvent (KdpTimeSlipEvent, 0, FALSE);
  433. }
  434. KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
  435. //
  436. // Insert a forced delay between time slip operations
  437. //
  438. DueTime.QuadPart = -1800000000;
  439. KeSetTimer (&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
  440. }
  441. }
  442. #if i386
  443. #if 0
  444. #define INTBP_PRINT(Args) DPRINT(Args)
  445. #else
  446. #define INTBP_PRINT(Args)
  447. #endif
  448. VOID
  449. InternalBreakpointCheck (
  450. PKDPC Dpc,
  451. PVOID DeferredContext,
  452. PVOID SystemArgument1,
  453. PVOID SystemArgument2
  454. )
  455. {
  456. LARGE_INTEGER dueTime;
  457. ULONG i;
  458. UNREFERENCED_PARAMETER(Dpc);
  459. UNREFERENCED_PARAMETER(DeferredContext);
  460. UNREFERENCED_PARAMETER(SystemArgument1);
  461. UNREFERENCED_PARAMETER(SystemArgument2);
  462. dueTime.LowPart = (ULONG)(-1 * 10 * 1000 * 1000);
  463. dueTime.HighPart = -1;
  464. KeSetTimer(
  465. &InternalBreakpointTimer,
  466. dueTime,
  467. &InternalBreakpointCheckDpc
  468. );
  469. for ( i = 0 ; i < KdpNumInternalBreakpoints; i++ ) {
  470. if ( !(KdpInternalBPs[i].Flags & DBGKD_INTERNAL_BP_FLAG_INVALID) &&
  471. (KdpInternalBPs[i].Flags & DBGKD_INTERNAL_BP_FLAG_COUNTONLY) ) {
  472. PDBGKD_INTERNAL_BREAKPOINT b = KdpInternalBPs + i;
  473. ULONG callsThisPeriod;
  474. callsThisPeriod = b->Calls - b->CallsLastCheck;
  475. if ( callsThisPeriod > b->MaxCallsPerPeriod ) {
  476. b->MaxCallsPerPeriod = callsThisPeriod;
  477. }
  478. b->CallsLastCheck = b->Calls;
  479. }
  480. }
  481. return;
  482. } // InternalBreakpointCheck
  483. VOID
  484. KdSetInternalBreakpoint (
  485. IN PDBGKD_MANIPULATE_STATE64 m
  486. )
  487. /*++
  488. Routine Description:
  489. This function sets an internal breakpoint. "Internal breakpoint"
  490. means one in which control is not returned to the kernel debugger at
  491. all, but rather just update internal counting routines and resume.
  492. Arguments:
  493. m - Supplies the state manipulation message.
  494. Return Value:
  495. None.
  496. --*/
  497. {
  498. ULONG i;
  499. PDBGKD_INTERNAL_BREAKPOINT bp = NULL;
  500. ULONG savedFlags;
  501. for ( i = 0 ; i < KdpNumInternalBreakpoints; i++ ) {
  502. if ( KdpInternalBPs[i].Addr ==
  503. m->u.SetInternalBreakpoint.BreakpointAddress ) {
  504. bp = &KdpInternalBPs[i];
  505. break;
  506. }
  507. }
  508. if ( !bp ) {
  509. for ( i = 0; i < KdpNumInternalBreakpoints; i++ ) {
  510. if ( KdpInternalBPs[i].Flags & DBGKD_INTERNAL_BP_FLAG_INVALID ) {
  511. bp = &KdpInternalBPs[i];
  512. break;
  513. }
  514. }
  515. }
  516. if ( !bp ) {
  517. if ( KdpNumInternalBreakpoints >= DBGKD_MAX_INTERNAL_BREAKPOINTS ) {
  518. return; // no space. Probably should report error.
  519. }
  520. bp = &KdpInternalBPs[KdpNumInternalBreakpoints++];
  521. bp->Flags |= DBGKD_INTERNAL_BP_FLAG_INVALID; // force initialization
  522. }
  523. if ( bp->Flags & DBGKD_INTERNAL_BP_FLAG_INVALID ) {
  524. if ( m->u.SetInternalBreakpoint.Flags &
  525. DBGKD_INTERNAL_BP_FLAG_INVALID ) {
  526. return; // tried clearing a non-existant BP. Ignore the request
  527. }
  528. bp->Calls = bp->MaxInstructions = bp->TotalInstructions = 0;
  529. bp->CallsLastCheck = bp->MaxCallsPerPeriod = 0;
  530. bp->MinInstructions = 0xffffffff;
  531. bp->Handle = 0;
  532. bp->Thread = 0;
  533. }
  534. savedFlags = bp->Flags;
  535. bp->Flags = m->u.SetInternalBreakpoint.Flags; // this could possibly invalidate the BP
  536. bp->Addr = m->u.SetInternalBreakpoint.BreakpointAddress;
  537. if ( bp->Flags & (DBGKD_INTERNAL_BP_FLAG_INVALID |
  538. DBGKD_INTERNAL_BP_FLAG_SUSPENDED) ) {
  539. if ( (bp->Flags & DBGKD_INTERNAL_BP_FLAG_INVALID) &&
  540. (bp->Thread != 0) ) {
  541. // The breakpoint is active; defer its deletion
  542. bp->Flags &= ~DBGKD_INTERNAL_BP_FLAG_INVALID;
  543. bp->Flags |= DBGKD_INTERNAL_BP_FLAG_DYING;
  544. }
  545. // This is really a CLEAR bp request.
  546. if ( bp->Handle != 0 ) {
  547. KdpDeleteBreakpoint( bp->Handle );
  548. }
  549. bp->Handle = 0;
  550. return;
  551. }
  552. // now set the real breakpoint and remember its handle.
  553. if ( savedFlags & (DBGKD_INTERNAL_BP_FLAG_INVALID |
  554. DBGKD_INTERNAL_BP_FLAG_SUSPENDED) ) {
  555. // breakpoint was invalid; activate it now
  556. bp->Handle = KdpAddBreakpoint( (PVOID)bp->Addr );
  557. INTBP_PRINT(("Added intbp %d of %d at %I64x, flags %x, handle %x\n",
  558. (ULONG)(bp - KdpInternalBPs), KdpNumInternalBreakpoints,
  559. bp->Addr, bp->Flags, bp->Handle));
  560. }
  561. if ( BreakpointsSuspended ) {
  562. KdpSuspendBreakpoint( bp->Handle );
  563. }
  564. } // KdSetInternalBreakpoint
  565. NTSTATUS
  566. KdGetTraceInformation(
  567. PVOID SystemInformation,
  568. ULONG SystemInformationLength,
  569. PULONG ReturnLength
  570. )
  571. /*++
  572. Routine Description:
  573. This function gets data about an internal breakpoint and returns it
  574. in a buffer provided for it. It is designed to be called from
  575. NTQuerySystemInformation. It is morally equivalent to GetInternalBP
  576. except that it communicates locally, and returns all the breakpoints
  577. at once.
  578. Arguments:
  579. SystemInforamtion - the buffer into which to write the result.
  580. SystemInformationLength - the maximum length to write
  581. RetrunLength - How much data was really written
  582. Return Value:
  583. None.
  584. --*/
  585. {
  586. ULONG numEntries = 0;
  587. ULONG i = 0;
  588. PDBGKD_GET_INTERNAL_BREAKPOINT64 outPtr;
  589. for ( i = 0; i < KdpNumInternalBreakpoints; i++ ) {
  590. if ( !(KdpInternalBPs[i].Flags & DBGKD_INTERNAL_BP_FLAG_INVALID) ) {
  591. numEntries++;
  592. }
  593. }
  594. *ReturnLength = numEntries * sizeof(DBGKD_GET_INTERNAL_BREAKPOINT64);
  595. if ( *ReturnLength > SystemInformationLength ) {
  596. return STATUS_INFO_LENGTH_MISMATCH;
  597. }
  598. //
  599. // We've got enough space. Copy it in.
  600. //
  601. outPtr = (PDBGKD_GET_INTERNAL_BREAKPOINT64)SystemInformation;
  602. for ( i = 0; i < KdpNumInternalBreakpoints; i++ ) {
  603. if ( !(KdpInternalBPs[i].Flags & DBGKD_INTERNAL_BP_FLAG_INVALID) ) {
  604. outPtr->BreakpointAddress = KdpInternalBPs[i].Addr;
  605. outPtr->Flags = KdpInternalBPs[i].Flags;
  606. outPtr->Calls = KdpInternalBPs[i].Calls;
  607. outPtr->MaxCallsPerPeriod = KdpInternalBPs[i].MaxCallsPerPeriod;
  608. outPtr->MinInstructions = KdpInternalBPs[i].MinInstructions;
  609. outPtr->MaxInstructions = KdpInternalBPs[i].MaxInstructions;
  610. outPtr->TotalInstructions = KdpInternalBPs[i].TotalInstructions;
  611. outPtr++;
  612. }
  613. }
  614. return STATUS_SUCCESS;
  615. } // KdGetTraceInformation
  616. VOID
  617. KdGetInternalBreakpoint(
  618. IN PDBGKD_MANIPULATE_STATE64 m
  619. )
  620. /*++
  621. Routine Description:
  622. This function gets data about an internal breakpoint and returns it
  623. to the calling debugger.
  624. Arguments:
  625. m - Supplies the state manipulation message.
  626. Return Value:
  627. None.
  628. --*/
  629. {
  630. ULONG i;
  631. PDBGKD_INTERNAL_BREAKPOINT bp = NULL;
  632. STRING messageHeader;
  633. messageHeader.Length = sizeof(*m);
  634. messageHeader.Buffer = (PCHAR)m;
  635. for ( i = 0; i < KdpNumInternalBreakpoints; i++ ) {
  636. if ( !(KdpInternalBPs[i].Flags & (DBGKD_INTERNAL_BP_FLAG_INVALID |
  637. DBGKD_INTERNAL_BP_FLAG_SUSPENDED)) &&
  638. (KdpInternalBPs[i].Addr ==
  639. m->u.GetInternalBreakpoint.BreakpointAddress) ) {
  640. bp = &KdpInternalBPs[i];
  641. break;
  642. }
  643. }
  644. if ( !bp ) {
  645. m->u.GetInternalBreakpoint.Flags = DBGKD_INTERNAL_BP_FLAG_INVALID;
  646. m->u.GetInternalBreakpoint.Calls = 0;
  647. m->u.GetInternalBreakpoint.MaxCallsPerPeriod = 0;
  648. m->u.GetInternalBreakpoint.MinInstructions = 0;
  649. m->u.GetInternalBreakpoint.MaxInstructions = 0;
  650. m->u.GetInternalBreakpoint.TotalInstructions = 0;
  651. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  652. } else {
  653. m->u.GetInternalBreakpoint.Flags = bp->Flags;
  654. m->u.GetInternalBreakpoint.Calls = bp->Calls;
  655. m->u.GetInternalBreakpoint.MaxCallsPerPeriod = bp->MaxCallsPerPeriod;
  656. m->u.GetInternalBreakpoint.MinInstructions = bp->MinInstructions;
  657. m->u.GetInternalBreakpoint.MaxInstructions = bp->MaxInstructions;
  658. m->u.GetInternalBreakpoint.TotalInstructions = bp->TotalInstructions;
  659. m->ReturnStatus = STATUS_SUCCESS;
  660. }
  661. m->ApiNumber = DbgKdGetInternalBreakPointApi;
  662. KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  663. &messageHeader,
  664. NULL,
  665. &KdpContext
  666. );
  667. return;
  668. } // KdGetInternalBreakpoint
  669. #endif // i386
  670. KCONTINUE_STATUS
  671. KdpSendWaitContinue (
  672. IN ULONG OutPacketType,
  673. IN PSTRING OutMessageHeader,
  674. IN PSTRING OutMessageData OPTIONAL,
  675. IN OUT PCONTEXT ContextRecord
  676. )
  677. /*++
  678. Routine Description:
  679. This function sends a packet, and then waits for a continue message.
  680. BreakIns received while waiting will always cause a resend of the
  681. packet originally sent out. While waiting, manipulate messages
  682. will be serviced.
  683. A resend always resends the original event sent to the debugger,
  684. not the last response to some debugger command.
  685. Arguments:
  686. OutPacketType - Supplies the type of packet to send.
  687. OutMessageHeader - Supplies a pointer to a string descriptor that describes
  688. the message information.
  689. OutMessageData - Supplies a pointer to a string descriptor that describes
  690. the optional message data.
  691. ContextRecord - Exception context
  692. Return Value:
  693. A value of TRUE is returned if the continue message indicates
  694. success, Otherwise, a value of FALSE is returned.
  695. --*/
  696. {
  697. ULONG Length;
  698. STRING MessageData;
  699. STRING MessageHeader;
  700. DBGKD_MANIPULATE_STATE64 ManipulateState;
  701. ULONG ReturnCode;
  702. NTSTATUS Status;
  703. KCONTINUE_STATUS ContinueStatus;
  704. //
  705. // Loop servicing state manipulation message until a continue message
  706. // is received.
  707. //
  708. MessageHeader.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
  709. MessageHeader.Buffer = (PCHAR)&ManipulateState;
  710. MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE;
  711. MessageData.Buffer = (PCHAR)KdpMessageBuffer;
  712. KdpContextSent = FALSE;
  713. ResendPacket:
  714. //
  715. // Send event notification packet to debugger on host. Come back
  716. // here any time we see a breakin sequence.
  717. //
  718. KdSendPacket(
  719. OutPacketType,
  720. OutMessageHeader,
  721. OutMessageData,
  722. &KdpContext
  723. );
  724. //
  725. // After sending packet, if there is no response from debugger
  726. // AND the packet is for reporting symbol (un)load, the debugger
  727. // will be declared to be not present. Note If the packet is for
  728. // reporting exception, the KdSendPacket will never stop.
  729. //
  730. if (KdDebuggerNotPresent) {
  731. return ContinueSuccess;
  732. }
  733. while (TRUE) {
  734. //
  735. // Wait for State Manipulate Packet without timeout.
  736. //
  737. do {
  738. ReturnCode = KdReceivePacket(
  739. PACKET_TYPE_KD_STATE_MANIPULATE,
  740. &MessageHeader,
  741. &MessageData,
  742. &Length,
  743. &KdpContext
  744. );
  745. if (ReturnCode == (USHORT)KDP_PACKET_RESEND) {
  746. goto ResendPacket;
  747. }
  748. } while (ReturnCode == KDP_PACKET_TIMEOUT);
  749. //
  750. // Switch on the return message API number.
  751. //
  752. switch (ManipulateState.ApiNumber) {
  753. case DbgKdReadVirtualMemoryApi:
  754. KdpReadVirtualMemory(&ManipulateState,&MessageData,ContextRecord);
  755. break;
  756. #if 0
  757. case DbgKdReadVirtualMemory64Api:
  758. KdpReadVirtualMemory64(&ManipulateState,&MessageData,ContextRecord);
  759. break;
  760. #endif
  761. case DbgKdWriteVirtualMemoryApi:
  762. KdpWriteVirtualMemory(&ManipulateState,&MessageData,ContextRecord);
  763. break;
  764. #if 0
  765. case DbgKdWriteVirtualMemory64Api:
  766. KdpWriteVirtualMemory64(&ManipulateState,&MessageData,ContextRecord);
  767. break;
  768. #endif
  769. case DbgKdCheckLowMemoryApi:
  770. KdpCheckLowMemory (&ManipulateState);
  771. break;
  772. case DbgKdReadPhysicalMemoryApi:
  773. KdpReadPhysicalMemory(&ManipulateState,&MessageData,ContextRecord);
  774. break;
  775. case DbgKdWritePhysicalMemoryApi:
  776. KdpWritePhysicalMemory(&ManipulateState,&MessageData,ContextRecord);
  777. break;
  778. case DbgKdGetContextApi:
  779. KdpGetContext(&ManipulateState,&MessageData,ContextRecord);
  780. break;
  781. case DbgKdSetContextApi:
  782. KdpSetContext(&ManipulateState,&MessageData,ContextRecord);
  783. break;
  784. case DbgKdWriteBreakPointApi:
  785. KdpWriteBreakpoint(&ManipulateState,&MessageData,ContextRecord);
  786. break;
  787. case DbgKdRestoreBreakPointApi:
  788. KdpRestoreBreakpoint(&ManipulateState,&MessageData,ContextRecord);
  789. break;
  790. case DbgKdReadControlSpaceApi:
  791. KdpReadControlSpace(&ManipulateState,&MessageData,ContextRecord);
  792. break;
  793. case DbgKdWriteControlSpaceApi:
  794. KdpWriteControlSpace(&ManipulateState,&MessageData,ContextRecord);
  795. break;
  796. case DbgKdReadIoSpaceApi:
  797. KdpReadIoSpace(&ManipulateState,&MessageData,ContextRecord);
  798. break;
  799. case DbgKdWriteIoSpaceApi:
  800. KdpWriteIoSpace(&ManipulateState,&MessageData,ContextRecord);
  801. break;
  802. case DbgKdReadIoSpaceExtendedApi:
  803. KdpReadIoSpaceExtended(&ManipulateState,&MessageData,ContextRecord);
  804. break;
  805. case DbgKdWriteIoSpaceExtendedApi:
  806. KdpWriteIoSpaceExtended(&ManipulateState,&MessageData,ContextRecord);
  807. break;
  808. case DbgKdReadMachineSpecificRegister:
  809. KdpReadMachineSpecificRegister(&ManipulateState,&MessageData,ContextRecord);
  810. break;
  811. case DbgKdWriteMachineSpecificRegister:
  812. KdpWriteMachineSpecificRegister(&ManipulateState,&MessageData,ContextRecord);
  813. break;
  814. case DbgKdGetBusDataApi:
  815. KdpGetBusData(&ManipulateState,&MessageData,ContextRecord);
  816. break;
  817. case DbgKdSetBusDataApi:
  818. KdpSetBusData(&ManipulateState,&MessageData,ContextRecord);
  819. break;
  820. case DbgKdContinueApi:
  821. if (NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus) != FALSE) {
  822. return ContinueSuccess;
  823. } else {
  824. return ContinueError;
  825. }
  826. break;
  827. case DbgKdContinueApi2:
  828. if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus) != FALSE) {
  829. KdpGetStateChange(&ManipulateState,ContextRecord);
  830. return ContinueSuccess;
  831. } else {
  832. return ContinueError;
  833. }
  834. break;
  835. case DbgKdRebootApi:
  836. HalReturnToFirmware(HalRebootRoutine);
  837. break;
  838. #if defined(i386)
  839. case DbgKdSetSpecialCallApi:
  840. KdSetSpecialCall(&ManipulateState,ContextRecord);
  841. break;
  842. case DbgKdClearSpecialCallsApi:
  843. KdClearSpecialCalls();
  844. break;
  845. case DbgKdSetInternalBreakPointApi:
  846. KdSetInternalBreakpoint(&ManipulateState);
  847. break;
  848. case DbgKdGetInternalBreakPointApi:
  849. KdGetInternalBreakpoint(&ManipulateState);
  850. break;
  851. case DbgKdClearAllInternalBreakpointsApi:
  852. KdpNumInternalBreakpoints = 0;
  853. break;
  854. #endif // i386
  855. case DbgKdGetVersionApi:
  856. KdpGetVersion(&ManipulateState);
  857. break;
  858. case DbgKdCauseBugCheckApi:
  859. KdpCauseBugCheck(&ManipulateState);
  860. break;
  861. case DbgKdPageInApi:
  862. KdpNotSupported(&ManipulateState);
  863. break;
  864. case DbgKdWriteBreakPointExApi:
  865. Status = KdpWriteBreakPointEx(&ManipulateState,
  866. &MessageData,
  867. ContextRecord);
  868. if (Status) {
  869. ManipulateState.ApiNumber = DbgKdContinueApi;
  870. ManipulateState.u.Continue.ContinueStatus = Status;
  871. return ContinueError;
  872. }
  873. break;
  874. case DbgKdRestoreBreakPointExApi:
  875. KdpRestoreBreakPointEx(&ManipulateState,&MessageData,ContextRecord);
  876. break;
  877. case DbgKdSwitchProcessor:
  878. KdRestore(FALSE);
  879. ContinueStatus = KeSwitchFrozenProcessor(ManipulateState.Processor);
  880. KdSave(FALSE);
  881. return ContinueStatus;
  882. case DbgKdSearchMemoryApi:
  883. KdpSearchMemory(&ManipulateState, &MessageData, ContextRecord);
  884. break;
  885. case DbgKdFillMemoryApi:
  886. KdpFillMemory(&ManipulateState, &MessageData, ContextRecord);
  887. break;
  888. case DbgKdQueryMemoryApi:
  889. KdpQueryMemory(&ManipulateState, ContextRecord);
  890. break;
  891. //
  892. // Invalid message.
  893. //
  894. default:
  895. MessageData.Length = 0;
  896. ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
  897. KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, &MessageData, &KdpContext);
  898. break;
  899. }
  900. }
  901. }
  902. VOID
  903. KdpReadVirtualMemory(
  904. IN PDBGKD_MANIPULATE_STATE64 m,
  905. IN PSTRING AdditionalData,
  906. IN PCONTEXT Context
  907. )
  908. /*++
  909. Routine Description:
  910. This function is called in response to a read virtual memory 32-bit
  911. state manipulation message. Its function is to read virtual memory
  912. and return.
  913. Arguments:
  914. m - Supplies a pointer to the state manipulation message.
  915. AdditionalData - Supplies a pointer to a descriptor for the data to read.
  916. Context - Supplies a pointer to the current context.
  917. Return Value:
  918. None.
  919. --*/
  920. {
  921. ULONG Length;
  922. STRING MessageHeader;
  923. //
  924. // Trim the transfer count to fit in a single message.
  925. //
  926. Length = m->u.ReadMemory.TransferCount;
  927. if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) {
  928. Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
  929. }
  930. //
  931. // Move the data to the destination buffer.
  932. //
  933. m->ReturnStatus =
  934. KdpCopyMemoryChunks(m->u.ReadMemory.TargetBaseAddress,
  935. AdditionalData->Buffer,
  936. Length,
  937. 0,
  938. MMDBG_COPY_UNSAFE,
  939. &Length);
  940. //
  941. // Set the actual number of bytes read, initialize the message header,
  942. // and send the reply packet to the host debugger.
  943. //
  944. AdditionalData->Length = (USHORT)Length;
  945. m->u.ReadMemory.ActualBytesRead = Length;
  946. MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
  947. MessageHeader.Buffer = (PCHAR)m;
  948. KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  949. &MessageHeader,
  950. AdditionalData,
  951. &KdpContext);
  952. return;
  953. }
  954. VOID
  955. KdpWriteVirtualMemory(
  956. IN PDBGKD_MANIPULATE_STATE64 m,
  957. IN PSTRING AdditionalData,
  958. IN PCONTEXT Context
  959. )
  960. /*++
  961. Routine Description:
  962. This function is called in response of a write virtual memory 32-bit
  963. state manipulation message. Its function is to write virtual memory
  964. and return.
  965. Arguments:
  966. m - Supplies a pointer to the state manipulation message.
  967. AdditionalData - Supplies a pointer to a descriptor for the data to write.
  968. Context - Supplies a pointer to the current context.
  969. Return Value:
  970. None.
  971. --*/
  972. {
  973. STRING MessageHeader;
  974. //
  975. // Move the data to the destination buffer.
  976. //
  977. m->ReturnStatus =
  978. KdpCopyMemoryChunks(m->u.WriteMemory.TargetBaseAddress,
  979. AdditionalData->Buffer,
  980. AdditionalData->Length,
  981. 0,
  982. MMDBG_COPY_WRITE | MMDBG_COPY_UNSAFE,
  983. &m->u.WriteMemory.ActualBytesWritten);
  984. //
  985. // Set the actual number of bytes written, initialize the message header,
  986. // and send the reply packet to the host debugger.
  987. //
  988. MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
  989. MessageHeader.Buffer = (PCHAR)m;
  990. KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  991. &MessageHeader,
  992. NULL,
  993. &KdpContext);
  994. return;
  995. }
  996. VOID
  997. KdpGetContext(
  998. IN PDBGKD_MANIPULATE_STATE64 m,
  999. IN PSTRING AdditionalData,
  1000. IN PCONTEXT Context
  1001. )
  1002. /*++
  1003. Routine Description:
  1004. This function is called in response of a get context state
  1005. manipulation message. Its function is to return the current
  1006. context.
  1007. Arguments:
  1008. m - Supplies the state manipulation message.
  1009. AdditionalData - Supplies any additional data for the message.
  1010. Context - Supplies the current context.
  1011. Return Value:
  1012. None.
  1013. --*/
  1014. {
  1015. PDBGKD_GET_CONTEXT a = &m->u.GetContext;
  1016. STRING MessageHeader;
  1017. MessageHeader.Length = sizeof(*m);
  1018. MessageHeader.Buffer = (PCHAR)m;
  1019. ASSERT(AdditionalData->Length == 0);
  1020. if (m->Processor >= (USHORT)KeNumberProcessors) {
  1021. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  1022. } else {
  1023. m->ReturnStatus = STATUS_SUCCESS;
  1024. AdditionalData->Length = sizeof(CONTEXT);
  1025. if (m->Processor == (USHORT)KeGetCurrentPrcb()->Number) {
  1026. KdpQuickMoveMemory(AdditionalData->Buffer, (PCHAR)Context, sizeof(CONTEXT));
  1027. } else {
  1028. KdpQuickMoveMemory(AdditionalData->Buffer,
  1029. (PCHAR)&KiProcessorBlock[m->Processor]->ProcessorState.ContextFrame,
  1030. sizeof(CONTEXT)
  1031. );
  1032. }
  1033. KdpContextSent = TRUE;
  1034. }
  1035. KdSendPacket(
  1036. PACKET_TYPE_KD_STATE_MANIPULATE,
  1037. &MessageHeader,
  1038. AdditionalData,
  1039. &KdpContext
  1040. );
  1041. }
  1042. VOID
  1043. KdpSetContext(
  1044. IN PDBGKD_MANIPULATE_STATE64 m,
  1045. IN PSTRING AdditionalData,
  1046. IN PCONTEXT Context
  1047. )
  1048. /*++
  1049. Routine Description:
  1050. This function is called in response of a set context state
  1051. manipulation message. Its function is set the current
  1052. context.
  1053. Arguments:
  1054. m - Supplies the state manipulation message.
  1055. AdditionalData - Supplies any additional data for the message.
  1056. Context - Supplies the current context.
  1057. Return Value:
  1058. None.
  1059. --*/
  1060. {
  1061. PDBGKD_SET_CONTEXT a = &m->u.SetContext;
  1062. STRING MessageHeader;
  1063. MessageHeader.Length = sizeof(*m);
  1064. MessageHeader.Buffer = (PCHAR)m;
  1065. ASSERT(AdditionalData->Length == sizeof(CONTEXT));
  1066. if ((m->Processor >= (USHORT)KeNumberProcessors) ||
  1067. (KdpContextSent == FALSE)) {
  1068. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  1069. } else {
  1070. m->ReturnStatus = STATUS_SUCCESS;
  1071. if (m->Processor == (USHORT)KeGetCurrentPrcb()->Number) {
  1072. KdpQuickMoveMemory((PCHAR)Context, AdditionalData->Buffer, sizeof(CONTEXT));
  1073. } else {
  1074. KdpQuickMoveMemory((PCHAR)&KiProcessorBlock[m->Processor]->ProcessorState.ContextFrame,
  1075. AdditionalData->Buffer,
  1076. sizeof(CONTEXT)
  1077. );
  1078. }
  1079. }
  1080. KdSendPacket(
  1081. PACKET_TYPE_KD_STATE_MANIPULATE,
  1082. &MessageHeader,
  1083. NULL,
  1084. &KdpContext
  1085. );
  1086. }
  1087. VOID
  1088. KdpWriteBreakpoint(
  1089. IN PDBGKD_MANIPULATE_STATE64 m,
  1090. IN PSTRING AdditionalData,
  1091. IN PCONTEXT Context
  1092. )
  1093. /*++
  1094. Routine Description:
  1095. This function is called in response of a write breakpoint state
  1096. manipulation message. Its function is to write a breakpoint
  1097. and return a handle to the breakpoint.
  1098. Arguments:
  1099. m - Supplies the state manipulation message.
  1100. AdditionalData - Supplies any additional data for the message.
  1101. Context - Supplies the current context.
  1102. Return Value:
  1103. None.
  1104. --*/
  1105. {
  1106. PDBGKD_WRITE_BREAKPOINT64 a = &m->u.WriteBreakPoint;
  1107. STRING MessageHeader;
  1108. MessageHeader.Length = sizeof(*m);
  1109. MessageHeader.Buffer = (PCHAR)m;
  1110. ASSERT(AdditionalData->Length == 0);
  1111. a->BreakPointHandle = KdpAddBreakpoint((PVOID)a->BreakPointAddress);
  1112. if (a->BreakPointHandle != 0) {
  1113. m->ReturnStatus = STATUS_SUCCESS;
  1114. } else {
  1115. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  1116. }
  1117. KdSendPacket(
  1118. PACKET_TYPE_KD_STATE_MANIPULATE,
  1119. &MessageHeader,
  1120. NULL,
  1121. &KdpContext
  1122. );
  1123. UNREFERENCED_PARAMETER(Context);
  1124. }
  1125. VOID
  1126. KdpRestoreBreakpoint(
  1127. IN PDBGKD_MANIPULATE_STATE64 m,
  1128. IN PSTRING AdditionalData,
  1129. IN PCONTEXT Context
  1130. )
  1131. /*++
  1132. Routine Description:
  1133. This function is called in response of a restore breakpoint state
  1134. manipulation message. Its function is to restore a breakpoint
  1135. using the specified handle.
  1136. Arguments:
  1137. m - Supplies the state manipulation message.
  1138. AdditionalData - Supplies any additional data for the message.
  1139. Context - Supplies the current context.
  1140. Return Value:
  1141. None.
  1142. --*/
  1143. {
  1144. PDBGKD_RESTORE_BREAKPOINT a = &m->u.RestoreBreakPoint;
  1145. STRING MessageHeader;
  1146. MessageHeader.Length = sizeof(*m);
  1147. MessageHeader.Buffer = (PCHAR)m;
  1148. ASSERT(AdditionalData->Length == 0);
  1149. if (KdpDeleteBreakpoint(a->BreakPointHandle)) {
  1150. m->ReturnStatus = STATUS_SUCCESS;
  1151. } else {
  1152. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  1153. }
  1154. KdSendPacket(
  1155. PACKET_TYPE_KD_STATE_MANIPULATE,
  1156. &MessageHeader,
  1157. NULL,
  1158. &KdpContext
  1159. );
  1160. UNREFERENCED_PARAMETER(Context);
  1161. }
  1162. #if defined(_X86_)
  1163. long
  1164. SymNumFor(
  1165. ULONG pc
  1166. )
  1167. {
  1168. ULONG index;
  1169. for (index = 0; index < NumTraceDataSyms; index++) {
  1170. if ((TraceDataSyms[index].SymMin <= pc) &&
  1171. (TraceDataSyms[index].SymMax > pc)) return(index);
  1172. }
  1173. return(-1);
  1174. }
  1175. #if 0
  1176. #define TRACE_PRINT(Args) DPRINT(Args)
  1177. #else
  1178. #define TRACE_PRINT(Args)
  1179. #endif
  1180. BOOLEAN TraceDataBufferFilled = FALSE;
  1181. void PotentialNewSymbol (ULONG pc)
  1182. {
  1183. if (!TraceDataBufferFilled &&
  1184. -1 != SymNumFor(pc)) { // we've already seen this one
  1185. TRACE_PRINT(("PNS %x repeat %d\n", pc, SymNumFor(pc)));
  1186. return;
  1187. }
  1188. TraceDataBufferFilled = FALSE;
  1189. // OK, we've got to start up a TraceDataRecord
  1190. TraceDataBuffer[TraceDataBufferPosition].s.LevelChange = 0;
  1191. if (-1 != SymNumFor(pc)) {
  1192. int sym = SymNumFor(pc);
  1193. TraceDataBuffer[TraceDataBufferPosition].s.SymbolNumber = (UCHAR) sym;
  1194. KdpCurrentSymbolStart = TraceDataSyms[sym].SymMin;
  1195. KdpCurrentSymbolEnd = TraceDataSyms[sym].SymMax;
  1196. TRACE_PRINT(("PNS %x repeat %d at %d\n",
  1197. pc, sym, TraceDataBufferPosition));
  1198. return; // we've already seen this one
  1199. }
  1200. TraceDataSyms[NextTraceDataSym].SymMin = KdpCurrentSymbolStart;
  1201. TraceDataSyms[NextTraceDataSym].SymMax = KdpCurrentSymbolEnd;
  1202. TraceDataBuffer[TraceDataBufferPosition].s.SymbolNumber = NextTraceDataSym;
  1203. // Bump the "next" pointer, wrapping if necessary. Also bump the
  1204. // "valid" pointer if we need to.
  1205. NextTraceDataSym = (NextTraceDataSym + 1) % 256;
  1206. if (NumTraceDataSyms < NextTraceDataSym) {
  1207. NumTraceDataSyms = NextTraceDataSym;
  1208. }
  1209. TRACE_PRINT(("PNS %x in %x - %x, next %d, num %d\n", pc,
  1210. KdpCurrentSymbolStart, KdpCurrentSymbolEnd,
  1211. NextTraceDataSym, NumTraceDataSyms));
  1212. }
  1213. void DumpTraceData(PSTRING MessageData)
  1214. {
  1215. TraceDataBuffer[0].LongNumber = TraceDataBufferPosition;
  1216. MessageData->Length =
  1217. (USHORT)(sizeof(TraceDataBuffer[0]) * TraceDataBufferPosition);
  1218. MessageData->Buffer = (PVOID)TraceDataBuffer;
  1219. TRACE_PRINT(("DumpTraceData returns %d records\n",
  1220. TraceDataBufferPosition));
  1221. TraceDataBufferPosition = 1;
  1222. }
  1223. BOOLEAN
  1224. TraceDataRecordCallInfo(
  1225. ULONG InstructionsTraced,
  1226. LONG CallLevelChange,
  1227. ULONG pc
  1228. )
  1229. {
  1230. // We've just exited a symbol scope. The InstructionsTraced number goes
  1231. // with the old scope, the CallLevelChange goes with the new, and the
  1232. // pc fills in the symbol for the new TraceData record.
  1233. long SymNum = SymNumFor(pc);
  1234. if (KdpNextCallLevelChange != 0) {
  1235. TraceDataBuffer[TraceDataBufferPosition].s.LevelChange =
  1236. (char) KdpNextCallLevelChange;
  1237. KdpNextCallLevelChange = 0;
  1238. }
  1239. if (InstructionsTraced >= TRACE_DATA_INSTRUCTIONS_BIG) {
  1240. TraceDataBuffer[TraceDataBufferPosition].s.Instructions =
  1241. TRACE_DATA_INSTRUCTIONS_BIG;
  1242. TraceDataBuffer[TraceDataBufferPosition+1].LongNumber =
  1243. InstructionsTraced;
  1244. TraceDataBufferPosition += 2;
  1245. } else {
  1246. TraceDataBuffer[TraceDataBufferPosition].s.Instructions =
  1247. (unsigned short)InstructionsTraced;
  1248. TraceDataBufferPosition++;
  1249. }
  1250. if ((TraceDataBufferPosition + 2 >= TRACE_DATA_BUFFER_MAX_SIZE) ||
  1251. (-1 == SymNum)) {
  1252. if (TraceDataBufferPosition +2 >= TRACE_DATA_BUFFER_MAX_SIZE) {
  1253. TraceDataBufferFilled = TRUE;
  1254. }
  1255. KdpNextCallLevelChange = CallLevelChange;
  1256. TRACE_PRINT(("TDRCI nosym %x, lc %d, pos %d\n", pc, CallLevelChange,
  1257. TraceDataBufferPosition));
  1258. return FALSE;
  1259. }
  1260. TraceDataBuffer[TraceDataBufferPosition].s.LevelChange =(char)CallLevelChange;
  1261. TraceDataBuffer[TraceDataBufferPosition].s.SymbolNumber = (UCHAR) SymNum;
  1262. KdpCurrentSymbolStart = TraceDataSyms[SymNum].SymMin;
  1263. KdpCurrentSymbolEnd = TraceDataSyms[SymNum].SymMax;
  1264. TRACE_PRINT(("TDRCI sym %d for %x, %x - %x, lc %d, pos %d\n", SymNum, pc,
  1265. KdpCurrentSymbolStart, KdpCurrentSymbolEnd, CallLevelChange,
  1266. TraceDataBufferPosition));
  1267. return TRUE;
  1268. }
  1269. BOOLEAN
  1270. SkippingWhichBP (
  1271. PVOID thread,
  1272. PULONG BPNum
  1273. )
  1274. /*
  1275. * Return TRUE iff the pc corresponds to an internal breakpoint
  1276. * that has just been replaced for execution. If TRUE, then return
  1277. * the breakpoint number in BPNum.
  1278. */
  1279. {
  1280. ULONG index;
  1281. if (!IntBPsSkipping) return FALSE;
  1282. for (index = 0; index < KdpNumInternalBreakpoints; index++) {
  1283. if (!(KdpInternalBPs[index].Flags & DBGKD_INTERNAL_BP_FLAG_INVALID) &&
  1284. (KdpInternalBPs[index].Thread == thread)) {
  1285. *BPNum = index;
  1286. return TRUE;
  1287. }
  1288. }
  1289. return FALSE; // didn't match any
  1290. }
  1291. NTSTATUS
  1292. KdQuerySpecialCalls (
  1293. IN PDBGKD_MANIPULATE_STATE64 m,
  1294. ULONG Length,
  1295. PULONG RequiredLength
  1296. )
  1297. {
  1298. *RequiredLength = sizeof(DBGKD_MANIPULATE_STATE64) +
  1299. (sizeof(ULONG) * KdNumberOfSpecialCalls);
  1300. if ( Length < *RequiredLength ) {
  1301. return STATUS_INFO_LENGTH_MISMATCH;
  1302. }
  1303. m->u.QuerySpecialCalls.NumberOfSpecialCalls = KdNumberOfSpecialCalls;
  1304. KdpQuickMoveMemory(
  1305. (PCHAR)(m + 1),
  1306. (PCHAR)KdSpecialCalls,
  1307. sizeof(ULONG) * KdNumberOfSpecialCalls
  1308. );
  1309. return STATUS_SUCCESS;
  1310. } // KdQuerySpecialCalls
  1311. VOID
  1312. KdSetSpecialCall (
  1313. IN PDBGKD_MANIPULATE_STATE64 m,
  1314. IN PCONTEXT ContextRecord
  1315. )
  1316. /*++
  1317. Routine Description:
  1318. This function sets the addresses of the "special" call addresses
  1319. that the watchtrace facility pushes back to the kernel debugger
  1320. rather than stepping through.
  1321. Arguments:
  1322. m - Supplies the state manipulation message.
  1323. Return Value:
  1324. None.
  1325. --*/
  1326. {
  1327. if ( KdNumberOfSpecialCalls >= DBGKD_MAX_SPECIAL_CALLS ) {
  1328. return; // too bad
  1329. }
  1330. KdSpecialCalls[KdNumberOfSpecialCalls++] = (ULONG_PTR)m->u.SetSpecialCall.SpecialCall;
  1331. NextTraceDataSym = 0;
  1332. NumTraceDataSyms = 0;
  1333. KdpNextCallLevelChange = 0;
  1334. if (ContextRecord && !InstrCountInternal) {
  1335. InitialSP = ContextRecord->Esp;
  1336. }
  1337. } // KdSetSpecialCall
  1338. VOID
  1339. KdClearSpecialCalls (
  1340. VOID
  1341. )
  1342. /*++
  1343. Routine Description:
  1344. This function clears the addresses of the "special" call addresses
  1345. that the watchtrace facility pushes back to the kernel debugger
  1346. rather than stepping through.
  1347. Arguments:
  1348. None.
  1349. Return Value:
  1350. None.
  1351. --*/
  1352. {
  1353. KdNumberOfSpecialCalls = 0;
  1354. return;
  1355. } // KdClearSpecialCalls
  1356. BOOLEAN
  1357. KdpCheckTracePoint(
  1358. IN PEXCEPTION_RECORD ExceptionRecord,
  1359. IN OUT PCONTEXT ContextRecord
  1360. )
  1361. {
  1362. ULONG pc = (ULONG)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord);
  1363. LONG BpNum;
  1364. ULONG SkippedBPNum;
  1365. BOOLEAN AfterSC = FALSE;
  1366. if (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) {
  1367. if (WatchStepOverSuspended) {
  1368. //
  1369. // For background, see the comment below where WSOThread is
  1370. // wrong. We've now stepped over the breakpoint in the non-traced
  1371. // thread, and need to replace it and restart the non-traced
  1372. // thread at full speed.
  1373. //
  1374. WatchStepOverHandle = KdpAddBreakpoint((PVOID)WatchStepOverBreakAddr);
  1375. WatchStepOverSuspended = FALSE;
  1376. ContextRecord->EFlags &= ~0x100L; /* clear trace flag */
  1377. return TRUE; // resume non-traced thread at full speed
  1378. }
  1379. if ((!SymbolRecorded) && (KdpCurrentSymbolStart != 0) && (KdpCurrentSymbolEnd != 0)) {
  1380. //
  1381. // We need to use oldpc here, because this may have been
  1382. // a 1 instruction call. We've ALREADY executed the instruction
  1383. // that the new symbol is for, and if the pc has moved out of
  1384. // range, we might mess up. Hence, use the pc from when
  1385. // SymbolRecorded was set. Yuck.
  1386. //
  1387. PotentialNewSymbol(oldpc);
  1388. SymbolRecorded = TRUE;
  1389. }
  1390. if (!InstrCountInternal &&
  1391. SkippingWhichBP((PVOID)KeGetCurrentThread(),&SkippedBPNum)) {
  1392. //
  1393. // We just single-stepped over a temporarily removed internal
  1394. // breakpoint.
  1395. // If it's a COUNTONLY breakpoint:
  1396. // Put the breakpoint instruction back and resume
  1397. // regular execution.
  1398. //
  1399. if (KdpInternalBPs[SkippedBPNum].Flags &
  1400. DBGKD_INTERNAL_BP_FLAG_COUNTONLY) {
  1401. IntBPsSkipping --;
  1402. KdpRestoreAllBreakpoints();
  1403. ContextRecord->EFlags &= ~0x100L; // Clear trace flag
  1404. KdpInternalBPs[SkippedBPNum].Thread = 0;
  1405. if (KdpInternalBPs[SkippedBPNum].Flags &
  1406. DBGKD_INTERNAL_BP_FLAG_DYING) {
  1407. KdpDeleteBreakpoint(KdpInternalBPs[SkippedBPNum].Handle);
  1408. KdpInternalBPs[SkippedBPNum].Flags |=
  1409. DBGKD_INTERNAL_BP_FLAG_INVALID; // bye, bye
  1410. }
  1411. return TRUE;
  1412. }
  1413. //
  1414. // If it's not:
  1415. // set up like it's a ww, by setting Begin and KdpCurrentSymbolEnd
  1416. // and bop off into single step land. We probably ought to
  1417. // disable all breakpoints here, too, so that we don't do
  1418. // anything foul like trying two non-COUNTONLY's at the
  1419. // same time or something...
  1420. //
  1421. KdpCurrentSymbolEnd = 0;
  1422. KdpCurrentSymbolStart = (ULONG_PTR) KdpInternalBPs[SkippedBPNum].ReturnAddress;
  1423. ContextRecord->EFlags |= 0x100L; /* Trace on. */
  1424. InitialSP = ContextRecord->Esp;
  1425. InstructionsTraced = 1; /* Count the initial call instruction. */
  1426. InstrCountInternal = TRUE;
  1427. }
  1428. } /* if single step */
  1429. else if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) {
  1430. if (WatchStepOver && pc == WatchStepOverBreakAddr) {
  1431. //
  1432. // This is a breakpoint after completion of a "special call"
  1433. //
  1434. if ((WSOThread != (PVOID)KeGetCurrentThread()) ||
  1435. (WSOEsp + 0x20 < ContextRecord->Esp) ||
  1436. (ContextRecord->Esp + 0x20 < WSOEsp)) {
  1437. //
  1438. // Here's the story up to this point: the traced thread
  1439. // cruised along until it it a special call. The tracer
  1440. // placed a breakpoint on the instruction immediately after
  1441. // the special call returns and restarted the traced thread
  1442. // at full speed. Then, some *other* thread hit the
  1443. // breakpoint. So, to correct for this, we're going to
  1444. // remove the breakpoint, single step the non-traced
  1445. // thread one instruction, replace the breakpoint,
  1446. // restart the non-traced thread at full speed, and wait
  1447. // for the traced thread to get to this breakpoint, just
  1448. // like we were when this happened. The assumption
  1449. // here is that the traced thread won't hit the breakpoint
  1450. // while it's removed, which I believe to be true, because
  1451. // I don't think a context switch can occur during a single
  1452. // step operation.
  1453. //
  1454. // For extra added fun, it's possible to execute interrupt
  1455. // routines IN THE SAME THREAD!!! That's why we need to keep
  1456. // the stack pointer as well as the thread address: the APC
  1457. // code can result in pushing on the stack and doing a call
  1458. // that's really part on an interrupt service routine in the
  1459. // context of the current thread. Lovely, isn't it?
  1460. //
  1461. WatchStepOverSuspended = TRUE;
  1462. KdpDeleteBreakpoint(WatchStepOverHandle);
  1463. ContextRecord->EFlags |= 0x100L; // Set trace flag
  1464. return TRUE; // single step "non-traced" thread
  1465. }
  1466. //
  1467. // we're in the thread we started in; resume in single-step mode
  1468. // to continue the trace.
  1469. //
  1470. WatchStepOver = FALSE;
  1471. KdpDeleteBreakpoint(WatchStepOverHandle);
  1472. ContextRecord->EFlags |= 0x100L; // back to single step mode
  1473. AfterSC = TRUE; // put us into the regular watchStep code
  1474. } else {
  1475. for ( BpNum = 0; BpNum < (LONG) KdpNumInternalBreakpoints; BpNum++ ) {
  1476. if ( !(KdpInternalBPs[BpNum].Flags &
  1477. (DBGKD_INTERNAL_BP_FLAG_INVALID |
  1478. DBGKD_INTERNAL_BP_FLAG_SUSPENDED) ) &&
  1479. ((ULONG_PTR)KdpInternalBPs[BpNum].Addr == pc) ) {
  1480. break;
  1481. }
  1482. }
  1483. if ( BpNum < (LONG) KdpNumInternalBreakpoints ) {
  1484. //
  1485. // This is an internal monitoring breakpoint.
  1486. // Restore the instruction and start in single-step
  1487. // mode so that we can retore the breakpoint once the
  1488. // instruction executes, or continue stepping if this isn't
  1489. // a COUNTONLY breakpoint.
  1490. //
  1491. KdpProcessInternalBreakpoint( BpNum );
  1492. KdpInternalBPs[BpNum].Thread = (PVOID)KeGetCurrentThread();
  1493. IntBPsSkipping ++;
  1494. KdpSuspendAllBreakpoints();
  1495. ContextRecord->EFlags |= 0x100L; // Set trace flag
  1496. if (!(KdpInternalBPs[BpNum].Flags &
  1497. DBGKD_INTERNAL_BP_FLAG_COUNTONLY)) {
  1498. KdpInternalBPs[BpNum].ReturnAddress =
  1499. KdpGetReturnAddress( ContextRecord );
  1500. }
  1501. return TRUE;
  1502. }
  1503. }
  1504. } /* if breakpoint */
  1505. // if (AfterSC) {
  1506. // DPRINT(( "1: KdpCurrentSymbolStart %x KdpCurrentSymbolEnd %x\n", KdpCurrentSymbolStart, KdpCurrentSymbolEnd ));
  1507. // }
  1508. if ((AfterSC || ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) &&
  1509. KdpCurrentSymbolStart != 0 &&
  1510. ((KdpCurrentSymbolEnd == 0 && ContextRecord->Esp <= InitialSP) ||
  1511. (KdpCurrentSymbolStart <= pc && pc < KdpCurrentSymbolEnd))) {
  1512. ULONG lc;
  1513. BOOLEAN IsSpecialCall;
  1514. //
  1515. // We've taken a step trace, but are still executing in the current
  1516. // function. Remember that we executed an instruction and see if the
  1517. // instruction changes the call level.
  1518. //
  1519. lc = KdpLevelChange( pc, ContextRecord, &IsSpecialCall );
  1520. InstructionsTraced++;
  1521. CallLevelChange += lc;
  1522. //
  1523. // See if instruction is a transfer to a special routine, one that we
  1524. // cannot trace through since it may swap contexts
  1525. //
  1526. if (IsSpecialCall) {
  1527. // DPRINT( ("2: pc=%x, level change %d\n", pc, lc) );
  1528. //
  1529. // We are about to transfer to a special call routine. Since we
  1530. // cannot trace through this routine, we execute it atomically by
  1531. // setting a breakpoint at the next logical offset.
  1532. //
  1533. // Note in the case of an indirect jump to a special call routine, the
  1534. // level change will be -1 and the next offset will be the ULONG that's
  1535. // on the top of the stack.
  1536. //
  1537. // However, we've already adjusted the level based on this
  1538. // instruction. We need to undo this except for the magic -1 call.
  1539. //
  1540. if (lc != -1) {
  1541. CallLevelChange -= lc;
  1542. }
  1543. //
  1544. // Set up for stepping over a procedure
  1545. //
  1546. WatchStepOver = TRUE;
  1547. WatchStepOverBreakAddr = KdpGetCallNextOffset( pc, ContextRecord );
  1548. WSOThread = (PVOID)KeGetCurrentThread( );
  1549. WSOEsp = ContextRecord->Esp;
  1550. //
  1551. // Establish the breakpoint
  1552. //
  1553. WatchStepOverHandle = KdpAddBreakpoint( (PVOID)WatchStepOverBreakAddr );
  1554. //
  1555. // Note that we are continuing rather than tracing and rely on hitting
  1556. // the breakpoint in the current thread context to resume the watch
  1557. // action.
  1558. //
  1559. ContextRecord->EFlags &= ~0x100L;
  1560. return TRUE;
  1561. }
  1562. //
  1563. // Resume execution with the trace flag set. Avoid going over the wire to
  1564. // the remote debugger.
  1565. //
  1566. ContextRecord->EFlags |= 0x100L; // Set trace flag
  1567. return TRUE;
  1568. }
  1569. if ((AfterSC || (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)) &&
  1570. (KdpCurrentSymbolStart != 0)) {
  1571. //
  1572. // We're WatchTracing, but have just changed symbol range.
  1573. // Fill in the call record and return to the debugger if
  1574. // either we're full or the pc is outside of the known
  1575. // symbol scopes. Otherwise, resume stepping.
  1576. //
  1577. int lc;
  1578. BOOLEAN IsSpecialCall;
  1579. InstructionsTraced++; // don't forget to count the call/ret instruction.
  1580. // if (AfterSC) {
  1581. // DPRINT(( "3: InstrCountInternal: %x\n", InstrCountInternal ));
  1582. // }
  1583. if (InstrCountInternal) {
  1584. // We've just finished processing a non-COUNTONLY breakpoint.
  1585. // Record the appropriate data and resume full speed execution.
  1586. if (SkippingWhichBP((PVOID)KeGetCurrentThread(),&SkippedBPNum)) {
  1587. KdpInternalBPs[SkippedBPNum].Calls++;
  1588. if (KdpInternalBPs[SkippedBPNum].MinInstructions > InstructionsTraced) {
  1589. KdpInternalBPs[SkippedBPNum].MinInstructions = InstructionsTraced;
  1590. }
  1591. if (KdpInternalBPs[SkippedBPNum].MaxInstructions < InstructionsTraced) {
  1592. KdpInternalBPs[SkippedBPNum].MaxInstructions = InstructionsTraced;
  1593. }
  1594. KdpInternalBPs[SkippedBPNum].TotalInstructions += InstructionsTraced;
  1595. KdpInternalBPs[SkippedBPNum].Thread = 0;
  1596. IntBPsSkipping--;
  1597. KdpRestoreAllBreakpoints();
  1598. if (KdpInternalBPs[SkippedBPNum].Flags &
  1599. DBGKD_INTERNAL_BP_FLAG_DYING) {
  1600. KdpDeleteBreakpoint(KdpInternalBPs[SkippedBPNum].Handle);
  1601. KdpInternalBPs[SkippedBPNum].Flags |=
  1602. DBGKD_INTERNAL_BP_FLAG_INVALID; // bye, bye
  1603. }
  1604. }
  1605. KdpCurrentSymbolStart = 0;
  1606. InstrCountInternal = FALSE;
  1607. ContextRecord->EFlags &= ~0x100L; // clear trace flag
  1608. return TRUE; // Back to normal execution.
  1609. }
  1610. if (TraceDataRecordCallInfo( InstructionsTraced, CallLevelChange, pc)) {
  1611. //
  1612. // Everything was cool internally. We can keep executing without
  1613. // going back to the remote debugger.
  1614. //
  1615. // We have to compute lc after calling
  1616. // TraceDataRecordCallInfo, because LevelChange relies on
  1617. // KdpCurrentSymbolStart and KdpCurrentSymbolEnd corresponding to
  1618. // the pc.
  1619. //
  1620. lc = KdpLevelChange( pc, ContextRecord, &IsSpecialCall );
  1621. InstructionsTraced = 0;
  1622. CallLevelChange = lc;
  1623. //
  1624. // See if instruction is a transfer to a special routine, one that we
  1625. // cannot trace through since it may swap contexts
  1626. //
  1627. if (IsSpecialCall) {
  1628. // DPRINT(( "4: pc=%x, level change %d\n", pc, lc));
  1629. //
  1630. // We are about to transfer to a special call routine. Since we
  1631. // cannot trace through this routine, we execute it atomically by
  1632. // setting a breakpoint at the next logical offset.
  1633. //
  1634. // Note in the case of an indirect jump to a special call routine, the
  1635. // level change will be -1 and the next offset will be the ULONG that's
  1636. // on the top of the stack.
  1637. //
  1638. // However, we've already adjusted the level based on this
  1639. // instruction. We need to undo this except for the magic -1 call.
  1640. //
  1641. if (lc != -1) {
  1642. CallLevelChange -= lc;
  1643. }
  1644. //
  1645. // Set up for stepping over a procedure
  1646. //
  1647. WatchStepOver = TRUE;
  1648. WSOThread = (PVOID)KeGetCurrentThread();
  1649. //
  1650. // Establish the breakpoint
  1651. //
  1652. WatchStepOverHandle =
  1653. KdpAddBreakpoint( (PVOID)KdpGetCallNextOffset( pc, ContextRecord ));
  1654. //
  1655. // Resume execution with the trace flag set. Avoid going over the wire to
  1656. // the remote debugger.
  1657. //
  1658. ContextRecord->EFlags &= ~0x100L;
  1659. return TRUE;
  1660. }
  1661. ContextRecord->EFlags |= 0x100L; // Set trace flag
  1662. return TRUE; // Off we go
  1663. }
  1664. lc = KdpLevelChange( pc, ContextRecord, &IsSpecialCall );
  1665. InstructionsTraced = 0;
  1666. CallLevelChange = lc;
  1667. // We need to go back to the remote debugger. Just fall through.
  1668. if ((lc != 0) && IsSpecialCall) {
  1669. // We're hosed
  1670. DPRINT(( "Special call on first entry to symbol scope @ %x\n", pc ));
  1671. }
  1672. }
  1673. SymbolRecorded = FALSE;
  1674. oldpc = pc;
  1675. return FALSE;
  1676. }
  1677. #endif // defined(_X86_)
  1678. VOID
  1679. KdpSetCommonState(
  1680. IN ULONG NewState,
  1681. IN PCONTEXT ContextRecord,
  1682. OUT PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
  1683. )
  1684. {
  1685. BOOLEAN DeletedBps;
  1686. PCHAR PcMemory;
  1687. ULONG InstrCount;
  1688. PUCHAR InstrStream;
  1689. WaitStateChange->NewState = NewState;
  1690. WaitStateChange->ProcessorLevel = KeProcessorLevel;
  1691. WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
  1692. WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
  1693. WaitStateChange->Thread = (ULONG64)(LONG64)(LONG_PTR)KeGetCurrentThread();
  1694. PcMemory = (PCHAR)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord);
  1695. WaitStateChange->ProgramCounter = (ULONG64)(LONG64)(LONG_PTR)PcMemory;
  1696. RtlZeroMemory(&WaitStateChange->AnyControlReport,
  1697. sizeof(WaitStateChange->AnyControlReport));
  1698. //
  1699. // Copy instruction stream immediately following location of event.
  1700. //
  1701. InstrStream = WaitStateChange->ControlReport.InstructionStream;
  1702. KdpCopyFromPtr(InstrStream, PcMemory, DBGKD_MAXSTREAM, &InstrCount);
  1703. WaitStateChange->ControlReport.InstructionCount = (USHORT)InstrCount;
  1704. //
  1705. // Clear breakpoints in copied area.
  1706. // If there were any breakpoints cleared, recopy the instruction area
  1707. // without them.
  1708. //
  1709. if (KdpDeleteBreakpointRange(PcMemory, PcMemory + InstrCount - 1)) {
  1710. KdpCopyFromPtr(InstrStream, PcMemory, InstrCount, &InstrCount);
  1711. }
  1712. }
  1713. BOOLEAN
  1714. KdpSwitchProcessor (
  1715. IN PEXCEPTION_RECORD ExceptionRecord,
  1716. IN OUT PCONTEXT ContextRecord,
  1717. IN BOOLEAN SecondChance
  1718. )
  1719. {
  1720. BOOLEAN Status;
  1721. //
  1722. // Save port state
  1723. //
  1724. KdSave(FALSE);
  1725. //
  1726. // Process state change for this processor
  1727. //
  1728. Status = KdpReportExceptionStateChange (
  1729. ExceptionRecord,
  1730. ContextRecord,
  1731. SecondChance
  1732. );
  1733. //
  1734. // Restore port state and return status
  1735. //
  1736. KdRestore(FALSE);
  1737. return Status;
  1738. }
  1739. BOOLEAN
  1740. KdpReportExceptionStateChange (
  1741. IN PEXCEPTION_RECORD ExceptionRecord,
  1742. IN OUT PCONTEXT ContextRecord,
  1743. IN BOOLEAN SecondChance
  1744. )
  1745. /*++
  1746. Routine Description:
  1747. This routine sends an exception state change packet to the kernel
  1748. debugger and waits for a manipulate state message.
  1749. Arguments:
  1750. ExceptionRecord - Supplies a pointer to an exception record.
  1751. ContextRecord - Supplies a pointer to a context record.
  1752. SecondChance - Supplies a boolean value that determines whether this is
  1753. the first or second chance for the exception.
  1754. Return Value:
  1755. A value of TRUE is returned if the exception is handled. Otherwise, a
  1756. value of FALSE is returned.
  1757. --*/
  1758. {
  1759. STRING MessageData;
  1760. STRING MessageHeader;
  1761. DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
  1762. KCONTINUE_STATUS Status;
  1763. #if i386
  1764. if (KdpCheckTracePoint(ExceptionRecord,ContextRecord)) return TRUE;
  1765. #endif
  1766. do {
  1767. //
  1768. // Construct the wait state change message and message descriptor.
  1769. //
  1770. KdpSetCommonState(DbgKdExceptionStateChange, ContextRecord,
  1771. &WaitStateChange);
  1772. if (sizeof(EXCEPTION_RECORD) ==
  1773. sizeof(WaitStateChange.u.Exception.ExceptionRecord)) {
  1774. KdpQuickMoveMemory((PCHAR)&WaitStateChange.u.Exception.ExceptionRecord,
  1775. (PCHAR)ExceptionRecord,
  1776. sizeof(EXCEPTION_RECORD));
  1777. } else {
  1778. ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
  1779. &WaitStateChange.u.Exception.ExceptionRecord);
  1780. }
  1781. WaitStateChange.u.Exception.FirstChance = !SecondChance;
  1782. KdpSetStateChange(&WaitStateChange,
  1783. ExceptionRecord,
  1784. ContextRecord,
  1785. SecondChance
  1786. );
  1787. MessageHeader.Length = sizeof(WaitStateChange);
  1788. MessageHeader.Buffer = (PCHAR)&WaitStateChange;
  1789. #if i386
  1790. //
  1791. // Construct the wait state change data and data descriptor.
  1792. //
  1793. DumpTraceData(&MessageData);
  1794. #else
  1795. MessageData.Length = 0;
  1796. #endif
  1797. //
  1798. // Send packet to the kernel debugger on the host machine,
  1799. // wait for answer.
  1800. //
  1801. Status = KdpSendWaitContinue(
  1802. PACKET_TYPE_KD_STATE_CHANGE64,
  1803. &MessageHeader,
  1804. &MessageData,
  1805. ContextRecord
  1806. );
  1807. } while (Status == ContinueProcessorReselected) ;
  1808. return (BOOLEAN) Status;
  1809. }
  1810. BOOLEAN
  1811. KdpReportLoadSymbolsStateChange (
  1812. IN PSTRING PathName,
  1813. IN PKD_SYMBOLS_INFO SymbolInfo,
  1814. IN BOOLEAN UnloadSymbols,
  1815. IN OUT PCONTEXT ContextRecord
  1816. )
  1817. /*++
  1818. Routine Description:
  1819. This routine sends a load symbols state change packet to the kernel
  1820. debugger and waits for a manipulate state message.
  1821. Arguments:
  1822. PathName - Supplies a pointer to the pathname of the image whose
  1823. symbols are to be loaded.
  1824. BaseOfDll - Supplies the base address where the image was loaded.
  1825. ProcessId - Unique 32-bit identifier for process that is using
  1826. the symbols. -1 for system process.
  1827. CheckSum - Unique 32-bit identifier from image header.
  1828. UnloadSymbol - TRUE if the symbols that were previously loaded for
  1829. the named image are to be unloaded from the debugger.
  1830. Return Value:
  1831. A value of TRUE is returned if the exception is handled. Otherwise, a
  1832. value of FALSE is returned.
  1833. --*/
  1834. {
  1835. PSTRING AdditionalData;
  1836. STRING MessageData;
  1837. STRING MessageHeader;
  1838. DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
  1839. KCONTINUE_STATUS Status;
  1840. do {
  1841. //
  1842. // Construct the wait state change message and message descriptor.
  1843. //
  1844. KdpSetCommonState(DbgKdLoadSymbolsStateChange, ContextRecord,
  1845. &WaitStateChange);
  1846. KdpSetContextState(&WaitStateChange, ContextRecord);
  1847. WaitStateChange.u.LoadSymbols.UnloadSymbols = UnloadSymbols;
  1848. WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)SymbolInfo->BaseOfDll;
  1849. WaitStateChange.u.LoadSymbols.ProcessId = (ULONG) SymbolInfo->ProcessId;
  1850. WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
  1851. WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
  1852. if (ARGUMENT_PRESENT( PathName )) {
  1853. KdpCopyFromPtr(KdpPathBuffer,
  1854. PathName->Buffer,
  1855. PathName->Length,
  1856. &WaitStateChange.u.LoadSymbols.PathNameLength);
  1857. WaitStateChange.u.LoadSymbols.PathNameLength++;
  1858. MessageData.Buffer = KdpPathBuffer;
  1859. MessageData.Length = (USHORT)WaitStateChange.u.LoadSymbols.PathNameLength;
  1860. MessageData.Buffer[MessageData.Length-1] = '\0';
  1861. AdditionalData = &MessageData;
  1862. } else {
  1863. WaitStateChange.u.LoadSymbols.PathNameLength = 0;
  1864. AdditionalData = NULL;
  1865. }
  1866. MessageHeader.Length = sizeof(WaitStateChange);
  1867. MessageHeader.Buffer = (PCHAR)&WaitStateChange;
  1868. //
  1869. // Send packet to the kernel debugger on the host machine, wait
  1870. // for the reply.
  1871. //
  1872. Status = KdpSendWaitContinue(
  1873. PACKET_TYPE_KD_STATE_CHANGE64,
  1874. &MessageHeader,
  1875. AdditionalData,
  1876. ContextRecord
  1877. );
  1878. } while (Status == ContinueProcessorReselected);
  1879. return (BOOLEAN) Status;
  1880. }
  1881. VOID
  1882. KdpReportCommandStringStateChange (
  1883. IN PSTRING Name,
  1884. IN PSTRING Command,
  1885. IN OUT PCONTEXT ContextRecord
  1886. )
  1887. /*++
  1888. Routine Description:
  1889. This routine sends a command string packet to the kernel
  1890. debugger and waits for a manipulate state message.
  1891. Arguments:
  1892. Name - Identifies the originator of the command.
  1893. Command - Command string.
  1894. ContextRecord - Context information.
  1895. Return Value:
  1896. None.
  1897. --*/
  1898. {
  1899. STRING MessageData;
  1900. STRING MessageHeader;
  1901. DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
  1902. KCONTINUE_STATUS Status;
  1903. ULONG Length, Copied;
  1904. do {
  1905. //
  1906. // Construct the wait state change message and message descriptor.
  1907. //
  1908. KdpSetCommonState(DbgKdCommandStringStateChange, ContextRecord,
  1909. &WaitStateChange);
  1910. KdpSetContextState(&WaitStateChange, ContextRecord);
  1911. RtlZeroMemory(&WaitStateChange.u.CommandString,
  1912. sizeof(WaitStateChange.u.CommandString));
  1913. //
  1914. // Transfer the string data into the message buffer.
  1915. // The name is just a simple identifier so limit
  1916. // it to a relatively short length.
  1917. //
  1918. MessageData.Buffer = KdpMessageBuffer;
  1919. if (Name->Length > 127) {
  1920. Length = 127;
  1921. } else {
  1922. Length = Name->Length;
  1923. }
  1924. KdpCopyFromPtr(MessageData.Buffer, Name->Buffer, Length, &Copied);
  1925. MessageData.Length = (USHORT)Copied + 1;
  1926. MessageData.Buffer[MessageData.Length - 1] = '\0';
  1927. Length = PACKET_MAX_SIZE - sizeof(WaitStateChange) -
  1928. MessageData.Length;
  1929. if (Command->Length < Length) {
  1930. Length = Command->Length;
  1931. }
  1932. KdpCopyFromPtr(MessageData.Buffer + MessageData.Length,
  1933. Command->Buffer, Length, &Copied);
  1934. Length = Copied + 1;
  1935. MessageData.Length += (USHORT)Length;
  1936. MessageData.Buffer[MessageData.Length - 1] = '\0';
  1937. MessageHeader.Length = sizeof(WaitStateChange);
  1938. MessageHeader.Buffer = (PCHAR)&WaitStateChange;
  1939. //
  1940. // Send packet to the kernel debugger on the host machine, wait
  1941. // for the reply.
  1942. //
  1943. Status = KdpSendWaitContinue(
  1944. PACKET_TYPE_KD_STATE_CHANGE64,
  1945. &MessageHeader,
  1946. &MessageData,
  1947. ContextRecord
  1948. );
  1949. } while (Status == ContinueProcessorReselected);
  1950. }
  1951. VOID
  1952. KdpReadPhysicalMemory(
  1953. IN PDBGKD_MANIPULATE_STATE64 m,
  1954. IN PSTRING AdditionalData,
  1955. IN PCONTEXT Context
  1956. )
  1957. /*++
  1958. Routine Description:
  1959. This function is called in response to a read physical memory
  1960. state manipulation message. Its function is to read physical memory
  1961. and return.
  1962. Arguments:
  1963. m - Supplies the state manipulation message.
  1964. AdditionalData - Supplies any additional data for the message.
  1965. Context - Supplies the current context.
  1966. Return Value:
  1967. None.
  1968. --*/
  1969. {
  1970. PDBGKD_READ_MEMORY64 a = &m->u.ReadMemory;
  1971. ULONG Length;
  1972. STRING MessageHeader;
  1973. ULONG MmFlags;
  1974. MessageHeader.Length = sizeof(*m);
  1975. MessageHeader.Buffer = (PCHAR)m;
  1976. //
  1977. // make sure that nothing but a read memory message was transmitted
  1978. //
  1979. ASSERT(AdditionalData->Length == 0);
  1980. //
  1981. // Trim transfer count to fit in a single message
  1982. //
  1983. if (a->TransferCount > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) {
  1984. Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
  1985. } else {
  1986. Length = a->TransferCount;
  1987. }
  1988. //
  1989. // Initially there was no way to control the caching
  1990. // flags for physical memory access. Such control
  1991. // is necessary for robust physical access, though,
  1992. // as the proper kind of access must be made to avoid
  1993. // breaking the processor TBs. Rather than create a
  1994. // new protocol request, the ActualBytes field
  1995. // has been overridden to pass flags on input. Prior
  1996. // versions of the debugger set this to zero so this
  1997. // is a compatible change.
  1998. //
  1999. MmFlags = MMDBG_COPY_PHYSICAL | MMDBG_COPY_UNSAFE;
  2000. switch(a->ActualBytesRead)
  2001. {
  2002. case DBGKD_CACHING_CACHED:
  2003. MmFlags |= MMDBG_COPY_CACHED;
  2004. break;
  2005. case DBGKD_CACHING_UNCACHED:
  2006. MmFlags |= MMDBG_COPY_UNCACHED;
  2007. break;
  2008. case DBGKD_CACHING_WRITE_COMBINED:
  2009. MmFlags |= MMDBG_COPY_WRITE_COMBINED;
  2010. break;
  2011. }
  2012. m->ReturnStatus =
  2013. KdpCopyMemoryChunks(a->TargetBaseAddress,
  2014. AdditionalData->Buffer,
  2015. Length,
  2016. 0,
  2017. MmFlags,
  2018. &Length);
  2019. AdditionalData->Length = (USHORT)Length;
  2020. a->ActualBytesRead = Length;
  2021. KdSendPacket(
  2022. PACKET_TYPE_KD_STATE_MANIPULATE,
  2023. &MessageHeader,
  2024. AdditionalData,
  2025. &KdpContext
  2026. );
  2027. UNREFERENCED_PARAMETER(Context);
  2028. }
  2029. VOID
  2030. KdpWritePhysicalMemory(
  2031. IN PDBGKD_MANIPULATE_STATE64 m,
  2032. IN PSTRING AdditionalData,
  2033. IN PCONTEXT Context
  2034. )
  2035. /*++
  2036. Routine Description:
  2037. This function is called in response to a write physical memory
  2038. state manipulation message. Its function is to write physical memory
  2039. and return.
  2040. Arguments:
  2041. m - Supplies the state manipulation message.
  2042. AdditionalData - Supplies any additional data for the message.
  2043. Context - Supplies the current context.
  2044. Return Value:
  2045. None.
  2046. --*/
  2047. {
  2048. PDBGKD_WRITE_MEMORY64 a = &m->u.WriteMemory;
  2049. STRING MessageHeader;
  2050. ULONG MmFlags;
  2051. MessageHeader.Length = sizeof(*m);
  2052. MessageHeader.Buffer = (PCHAR)m;
  2053. // See ReadPhysical for an explanation of the ActualBytes usage.
  2054. MmFlags = MMDBG_COPY_PHYSICAL | MMDBG_COPY_WRITE | MMDBG_COPY_UNSAFE;
  2055. switch(a->ActualBytesWritten)
  2056. {
  2057. case DBGKD_CACHING_CACHED:
  2058. MmFlags |= MMDBG_COPY_CACHED;
  2059. break;
  2060. case DBGKD_CACHING_UNCACHED:
  2061. MmFlags |= MMDBG_COPY_UNCACHED;
  2062. break;
  2063. case DBGKD_CACHING_WRITE_COMBINED:
  2064. MmFlags |= MMDBG_COPY_WRITE_COMBINED;
  2065. break;
  2066. }
  2067. m->ReturnStatus =
  2068. KdpCopyMemoryChunks(a->TargetBaseAddress,
  2069. AdditionalData->Buffer,
  2070. a->TransferCount,
  2071. 0,
  2072. MmFlags,
  2073. &a->ActualBytesWritten);
  2074. KdSendPacket(
  2075. PACKET_TYPE_KD_STATE_MANIPULATE,
  2076. &MessageHeader,
  2077. NULL,
  2078. &KdpContext
  2079. );
  2080. UNREFERENCED_PARAMETER(Context);
  2081. }
  2082. VOID
  2083. KdpReadControlSpace(
  2084. IN PDBGKD_MANIPULATE_STATE64 m,
  2085. IN PSTRING AdditionalData,
  2086. IN PCONTEXT Context
  2087. )
  2088. /*++
  2089. Routine Description:
  2090. This function is called in response of a read control space state
  2091. manipulation message. Its function is to read implementation
  2092. specific system data.
  2093. Arguments:
  2094. m - Supplies the state manipulation message.
  2095. AdditionalData - Supplies any additional data for the message.
  2096. Context - Supplies the current context.
  2097. Return Value:
  2098. None.
  2099. --*/
  2100. {
  2101. PDBGKD_READ_MEMORY64 a = &m->u.ReadMemory;
  2102. STRING MessageHeader;
  2103. ULONG Length;
  2104. MessageHeader.Length = sizeof(*m);
  2105. MessageHeader.Buffer = (PCHAR)m;
  2106. ASSERT(AdditionalData->Length == 0);
  2107. if (a->TransferCount > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) {
  2108. Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
  2109. } else {
  2110. Length = a->TransferCount;
  2111. }
  2112. m->ReturnStatus = KdpSysReadControlSpace(m->Processor,
  2113. a->TargetBaseAddress,
  2114. AdditionalData->Buffer,
  2115. Length, &Length);
  2116. AdditionalData->Length = (USHORT)Length;
  2117. a->ActualBytesRead = Length;
  2118. KdSendPacket(
  2119. PACKET_TYPE_KD_STATE_MANIPULATE,
  2120. &MessageHeader,
  2121. AdditionalData,
  2122. &KdpContext
  2123. );
  2124. UNREFERENCED_PARAMETER(Context);
  2125. }
  2126. VOID
  2127. KdpWriteControlSpace(
  2128. IN PDBGKD_MANIPULATE_STATE64 m,
  2129. IN PSTRING AdditionalData,
  2130. IN PCONTEXT Context
  2131. )
  2132. /*++
  2133. Routine Description:
  2134. This function is called in response of a write control space state
  2135. manipulation message. Its function is to write implementation
  2136. specific system data.
  2137. Arguments:
  2138. m - Supplies the state manipulation message.
  2139. AdditionalData - Supplies any additional data for the message.
  2140. Context - Supplies the current context.
  2141. Return Value:
  2142. None.
  2143. --*/
  2144. {
  2145. PDBGKD_WRITE_MEMORY64 a = &m->u.WriteMemory;
  2146. ULONG Length;
  2147. STRING MessageHeader;
  2148. MessageHeader.Length = sizeof(*m);
  2149. MessageHeader.Buffer = (PCHAR)m;
  2150. m->ReturnStatus = KdpSysWriteControlSpace(m->Processor,
  2151. a->TargetBaseAddress,
  2152. AdditionalData->Buffer,
  2153. AdditionalData->Length,
  2154. &Length);
  2155. a->ActualBytesWritten = Length;
  2156. KdSendPacket(
  2157. PACKET_TYPE_KD_STATE_MANIPULATE,
  2158. &MessageHeader,
  2159. AdditionalData,
  2160. &KdpContext
  2161. );
  2162. UNREFERENCED_PARAMETER(Context);
  2163. }
  2164. VOID
  2165. KdpReadIoSpace(
  2166. IN PDBGKD_MANIPULATE_STATE64 m,
  2167. IN PSTRING AdditionalData,
  2168. IN PCONTEXT Context
  2169. )
  2170. /*++
  2171. Routine Description:
  2172. This function is called in response of a read io space state
  2173. manipulation message. Its function is to read system io
  2174. locations.
  2175. Arguments:
  2176. m - Supplies the state manipulation message.
  2177. AdditionalData - Supplies any additional data for the message.
  2178. Context - Supplies the current context.
  2179. Return Value:
  2180. None.
  2181. --*/
  2182. {
  2183. PDBGKD_READ_WRITE_IO64 a = &m->u.ReadWriteIo;
  2184. STRING MessageHeader;
  2185. ULONG Length;
  2186. MessageHeader.Length = sizeof(*m);
  2187. MessageHeader.Buffer = (PCHAR)m;
  2188. ASSERT(AdditionalData->Length == 0);
  2189. // Zero-fill the entire value so that shorter reads
  2190. // do not leave unset bytes.
  2191. a->DataValue = 0;
  2192. m->ReturnStatus = KdpSysReadIoSpace(Isa, 0, 1, a->IoAddress,
  2193. &a->DataValue, a->DataSize, &Length);
  2194. KdSendPacket(
  2195. PACKET_TYPE_KD_STATE_MANIPULATE,
  2196. &MessageHeader,
  2197. NULL,
  2198. &KdpContext
  2199. );
  2200. UNREFERENCED_PARAMETER(Context);
  2201. }
  2202. VOID
  2203. KdpWriteIoSpace(
  2204. IN PDBGKD_MANIPULATE_STATE64 m,
  2205. IN PSTRING AdditionalData,
  2206. IN PCONTEXT Context
  2207. )
  2208. /*++
  2209. Routine Description:
  2210. This function is called in response of a write io space state
  2211. manipulation message. Its function is to write to system io
  2212. locations.
  2213. Arguments:
  2214. m - Supplies the state manipulation message.
  2215. AdditionalData - Supplies any additional data for the message.
  2216. Context - Supplies the current context.
  2217. Return Value:
  2218. None.
  2219. --*/
  2220. {
  2221. PDBGKD_READ_WRITE_IO64 a = &m->u.ReadWriteIo;
  2222. STRING MessageHeader;
  2223. ULONG Length;
  2224. MessageHeader.Length = sizeof(*m);
  2225. MessageHeader.Buffer = (PCHAR)m;
  2226. ASSERT(AdditionalData->Length == 0);
  2227. m->ReturnStatus = KdpSysWriteIoSpace(Isa, 0, 1, a->IoAddress,
  2228. &a->DataValue, a->DataSize, &Length);
  2229. KdSendPacket(
  2230. PACKET_TYPE_KD_STATE_MANIPULATE,
  2231. &MessageHeader,
  2232. NULL,
  2233. &KdpContext
  2234. );
  2235. UNREFERENCED_PARAMETER(Context);
  2236. }
  2237. VOID
  2238. KdpReadIoSpaceExtended(
  2239. IN PDBGKD_MANIPULATE_STATE64 m,
  2240. IN PSTRING AdditionalData,
  2241. IN PCONTEXT Context
  2242. )
  2243. /*++
  2244. Routine Description:
  2245. This function is called in response of a read io space extended state
  2246. manipulation message. Its function is to read system io
  2247. locations.
  2248. Arguments:
  2249. m - Supplies the state manipulation message.
  2250. AdditionalData - Supplies any additional data for the message.
  2251. Context - Supplies the current context.
  2252. Return Value:
  2253. None.
  2254. --*/
  2255. {
  2256. PDBGKD_READ_WRITE_IO_EXTENDED64 a = &m->u.ReadWriteIoExtended;
  2257. STRING MessageHeader;
  2258. ULONG Length;
  2259. MessageHeader.Length = sizeof(*m);
  2260. MessageHeader.Buffer = (PCHAR)m;
  2261. ASSERT(AdditionalData->Length == 0);
  2262. // Zero-fill the entire value so that shorter reads
  2263. // do not leave unset bytes.
  2264. a->DataValue = 0;
  2265. m->ReturnStatus = KdpSysReadIoSpace(a->InterfaceType, a->BusNumber,
  2266. a->AddressSpace, a->IoAddress,
  2267. &a->DataValue, a->DataSize, &Length);
  2268. KdSendPacket(
  2269. PACKET_TYPE_KD_STATE_MANIPULATE,
  2270. &MessageHeader,
  2271. NULL,
  2272. &KdpContext
  2273. );
  2274. UNREFERENCED_PARAMETER(Context);
  2275. }
  2276. VOID
  2277. KdpWriteIoSpaceExtended(
  2278. IN PDBGKD_MANIPULATE_STATE64 m,
  2279. IN PSTRING AdditionalData,
  2280. IN PCONTEXT Context
  2281. )
  2282. /*++
  2283. Routine Description:
  2284. This function is called in response of a write io space extended state
  2285. manipulation message. Its function is to write to system io
  2286. locations.
  2287. Arguments:
  2288. m - Supplies the state manipulation message.
  2289. AdditionalData - Supplies any additional data for the message.
  2290. Context - Supplies the current context.
  2291. Return Value:
  2292. None.
  2293. --*/
  2294. {
  2295. PDBGKD_READ_WRITE_IO_EXTENDED64 a = &m->u.ReadWriteIoExtended;
  2296. STRING MessageHeader;
  2297. ULONG Length;
  2298. MessageHeader.Length = sizeof(*m);
  2299. MessageHeader.Buffer = (PCHAR)m;
  2300. ASSERT(AdditionalData->Length == 0);
  2301. m->ReturnStatus = KdpSysWriteIoSpace(a->InterfaceType, a->BusNumber,
  2302. a->AddressSpace, a->IoAddress,
  2303. &a->DataValue, a->DataSize, &Length);
  2304. KdSendPacket(
  2305. PACKET_TYPE_KD_STATE_MANIPULATE,
  2306. &MessageHeader,
  2307. NULL,
  2308. &KdpContext
  2309. );
  2310. UNREFERENCED_PARAMETER(Context);
  2311. }
  2312. VOID
  2313. KdpReadMachineSpecificRegister(
  2314. IN PDBGKD_MANIPULATE_STATE64 m,
  2315. IN PSTRING AdditionalData,
  2316. IN PCONTEXT Context
  2317. )
  2318. /*++
  2319. Routine Description:
  2320. This function is called in response of a read MSR
  2321. manipulation message. Its function is to read the MSR.
  2322. Arguments:
  2323. m - Supplies the state manipulation message.
  2324. AdditionalData - Supplies any additional data for the message.
  2325. Context - Supplies the current context.
  2326. Return Value:
  2327. None.
  2328. --*/
  2329. {
  2330. PDBGKD_READ_WRITE_MSR a = &m->u.ReadWriteMsr;
  2331. STRING MessageHeader;
  2332. ULARGE_INTEGER l;
  2333. MessageHeader.Length = sizeof(*m);
  2334. MessageHeader.Buffer = (PCHAR)m;
  2335. ASSERT(AdditionalData->Length == 0);
  2336. m->ReturnStatus = KdpSysReadMsr(a->Msr, &l.QuadPart);
  2337. a->DataValueLow = l.LowPart;
  2338. a->DataValueHigh = l.HighPart;
  2339. KdSendPacket(
  2340. PACKET_TYPE_KD_STATE_MANIPULATE,
  2341. &MessageHeader,
  2342. NULL,
  2343. &KdpContext
  2344. );
  2345. UNREFERENCED_PARAMETER(Context);
  2346. }
  2347. VOID
  2348. KdpWriteMachineSpecificRegister(
  2349. IN PDBGKD_MANIPULATE_STATE64 m,
  2350. IN PSTRING AdditionalData,
  2351. IN PCONTEXT Context
  2352. )
  2353. /*++
  2354. Routine Description:
  2355. This function is called in response of a write of a MSR
  2356. manipulation message. Its function is to write to the MSR
  2357. Arguments:
  2358. m - Supplies the state manipulation message.
  2359. AdditionalData - Supplies any additional data for the message.
  2360. Context - Supplies the current context.
  2361. Return Value:
  2362. None.
  2363. --*/
  2364. {
  2365. PDBGKD_READ_WRITE_MSR a = &m->u.ReadWriteMsr;
  2366. STRING MessageHeader;
  2367. ULARGE_INTEGER l;
  2368. MessageHeader.Length = sizeof(*m);
  2369. MessageHeader.Buffer = (PCHAR)m;
  2370. ASSERT(AdditionalData->Length == 0);
  2371. l.HighPart = a->DataValueHigh;
  2372. l.LowPart = a->DataValueLow;
  2373. m->ReturnStatus = KdpSysWriteMsr(a->Msr, &l.QuadPart);
  2374. KdSendPacket(
  2375. PACKET_TYPE_KD_STATE_MANIPULATE,
  2376. &MessageHeader,
  2377. NULL,
  2378. &KdpContext
  2379. );
  2380. UNREFERENCED_PARAMETER(Context);
  2381. }
  2382. VOID
  2383. KdpGetBusData (
  2384. IN PDBGKD_MANIPULATE_STATE64 m,
  2385. IN PSTRING AdditionalData,
  2386. IN PCONTEXT Context
  2387. )
  2388. /*++
  2389. Routine Description:
  2390. This function is called in response to a get bus data state
  2391. manipulation message. Its function is to read I/O configuration
  2392. space.
  2393. Arguments:
  2394. m - Supplies the state manipulation message.
  2395. AdditionalData - Supplies any additional data for the message.
  2396. Context - Supplies the current context.
  2397. Return Value:
  2398. None.
  2399. --*/
  2400. {
  2401. PDBGKD_GET_SET_BUS_DATA a = &m->u.GetSetBusData;
  2402. ULONG Length;
  2403. STRING MessageHeader;
  2404. MessageHeader.Length = sizeof(*m);
  2405. MessageHeader.Buffer = (PCHAR)m;
  2406. ASSERT(AdditionalData->Length == 0);
  2407. //
  2408. // Trim length to fit in a single message
  2409. //
  2410. if (a->Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) {
  2411. Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
  2412. } else {
  2413. Length = a->Length;
  2414. }
  2415. m->ReturnStatus = KdpSysReadBusData(a->BusDataType, a->BusNumber,
  2416. a->SlotNumber, a->Offset,
  2417. AdditionalData->Buffer,
  2418. Length, &Length);
  2419. a->Length = Length;
  2420. AdditionalData->Length = (USHORT)Length;
  2421. KdSendPacket(
  2422. PACKET_TYPE_KD_STATE_MANIPULATE,
  2423. &MessageHeader,
  2424. AdditionalData,
  2425. &KdpContext
  2426. );
  2427. }
  2428. VOID
  2429. KdpSetBusData (
  2430. IN PDBGKD_MANIPULATE_STATE64 m,
  2431. IN PSTRING AdditionalData,
  2432. IN PCONTEXT Context
  2433. )
  2434. /*++
  2435. Routine Description:
  2436. This function is called in response to a set bus data state
  2437. manipulation message. Its function is to write I/O configuration
  2438. space.
  2439. Arguments:
  2440. m - Supplies the state manipulation message.
  2441. AdditionalData - Supplies any additional data for the message.
  2442. Context - Supplies the current context.
  2443. Return Value:
  2444. None.
  2445. --*/
  2446. {
  2447. PDBGKD_GET_SET_BUS_DATA a = &m->u.GetSetBusData;
  2448. ULONG Length;
  2449. STRING MessageHeader;
  2450. MessageHeader.Length = sizeof(*m);
  2451. MessageHeader.Buffer = (PCHAR)m;
  2452. m->ReturnStatus = KdpSysWriteBusData(a->BusDataType, a->BusNumber,
  2453. a->SlotNumber, a->Offset,
  2454. AdditionalData->Buffer,
  2455. a->Length, &Length);
  2456. a->Length = Length;
  2457. KdSendPacket(
  2458. PACKET_TYPE_KD_STATE_MANIPULATE,
  2459. &MessageHeader,
  2460. NULL,
  2461. &KdpContext
  2462. );
  2463. }
  2464. #if i386
  2465. VOID
  2466. KdpProcessInternalBreakpoint (
  2467. ULONG BreakpointNumber
  2468. )
  2469. {
  2470. if ( !(KdpInternalBPs[BreakpointNumber].Flags &
  2471. DBGKD_INTERNAL_BP_FLAG_COUNTONLY) ) {
  2472. return; // We only deal with COUNTONLY breakpoints
  2473. }
  2474. //
  2475. // We've hit a real internal breakpoint; make sure the timeout is
  2476. // kicked off.
  2477. //
  2478. if ( !BreakPointTimerStarted ) { // ok, maybe there's a prettier way to do this.
  2479. KeInitializeDpc(
  2480. &InternalBreakpointCheckDpc,
  2481. &InternalBreakpointCheck,
  2482. NULL
  2483. );
  2484. KeInitializeTimer( &InternalBreakpointTimer );
  2485. // KeSetTimer can only be called at <= DISPATCH_LEVEL
  2486. // so just queue the timer DPC routine directly for
  2487. // the initial check.
  2488. KeInsertQueueDpc(&InternalBreakpointCheckDpc, NULL, NULL);
  2489. BreakPointTimerStarted = TRUE;
  2490. }
  2491. KdpInternalBPs[BreakpointNumber].Calls++;
  2492. } // KdpProcessInternalBreakpoint
  2493. #endif
  2494. VOID
  2495. KdpGetVersion(
  2496. IN PDBGKD_MANIPULATE_STATE64 m
  2497. )
  2498. /*++
  2499. Routine Description:
  2500. This function returns to the caller a general information packet
  2501. that contains useful information to a debugger. This packet is also
  2502. used for a debugger to determine if the writebreakpointex and
  2503. readbreakpointex apis are available.
  2504. Arguments:
  2505. m - Supplies the state manipulation message.
  2506. Return Value:
  2507. None.
  2508. --*/
  2509. {
  2510. STRING messageHeader;
  2511. messageHeader.Length = sizeof(*m);
  2512. messageHeader.Buffer = (PCHAR)m;
  2513. KdpSysGetVersion(&m->u.GetVersion64);
  2514. //
  2515. // the usual stuff
  2516. //
  2517. m->ReturnStatus = STATUS_SUCCESS;
  2518. m->ApiNumber = DbgKdGetVersionApi;
  2519. KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  2520. &messageHeader,
  2521. NULL,
  2522. &KdpContext
  2523. );
  2524. return;
  2525. } // KdGetVersion
  2526. NTSTATUS
  2527. KdpNotSupported(
  2528. IN PDBGKD_MANIPULATE_STATE64 m
  2529. )
  2530. /*++
  2531. Routine Description:
  2532. This routine returns STATUS_UNSUCCESSFUL to the debugger
  2533. Arguments:
  2534. m - Supplies a DBGKD_MANIPULATE_STATE64 struct to answer with
  2535. Return Value:
  2536. 0, to indicate that the system should not continue
  2537. --*/
  2538. {
  2539. STRING MessageHeader;
  2540. //
  2541. // setup packet
  2542. //
  2543. MessageHeader.Length = sizeof(*m);
  2544. MessageHeader.Buffer = (PCHAR)m;
  2545. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  2546. //
  2547. // send back our response
  2548. //
  2549. KdSendPacket(
  2550. PACKET_TYPE_KD_STATE_MANIPULATE,
  2551. &MessageHeader,
  2552. NULL,
  2553. &KdpContext
  2554. );
  2555. //
  2556. // return the caller's continue status value. if this is a non-zero
  2557. // value the system is continued using this value as the continuestatus.
  2558. //
  2559. return 0;
  2560. } // KdpNotSupported
  2561. VOID
  2562. KdpCauseBugCheck(
  2563. IN PDBGKD_MANIPULATE_STATE64 m
  2564. )
  2565. /*++
  2566. Routine Description:
  2567. This routine causes a bugcheck. It is used for testing the debugger.
  2568. Arguments:
  2569. m - Supplies the state manipulation message.
  2570. Return Value:
  2571. None.
  2572. --*/
  2573. {
  2574. KeBugCheckEx( MANUALLY_INITIATED_CRASH, 0, 0, 0, 0 );
  2575. } // KdCauseBugCheck
  2576. NTSTATUS
  2577. KdpWriteBreakPointEx(
  2578. IN PDBGKD_MANIPULATE_STATE64 m,
  2579. IN PSTRING AdditionalData,
  2580. IN PCONTEXT Context
  2581. )
  2582. /*++
  2583. Routine Description:
  2584. This function is called in response of a write breakpoint state 'ex'
  2585. manipulation message. Its function is to clear breakpoints, write
  2586. new breakpoints, and continue the target system. The clearing of
  2587. breakpoints is conditional based on the presence of breakpoint handles.
  2588. The setting of breakpoints is conditional based on the presence of
  2589. valid, non-zero, addresses. The continueing of the target system
  2590. is conditional based on a non-zero continuestatus.
  2591. This api allows a debugger to clear breakpoints, add new breakpoint,
  2592. and continue the target system all in one api packet. This reduces the
  2593. amount of traffic across the wire and greatly improves source stepping.
  2594. Arguments:
  2595. m - Supplies the state manipulation message.
  2596. AdditionalData - Supplies any additional data for the message.
  2597. Context - Supplies the current context.
  2598. Return Value:
  2599. None.
  2600. --*/
  2601. {
  2602. PDBGKD_BREAKPOINTEX a = &m->u.BreakPointEx;
  2603. PDBGKD_WRITE_BREAKPOINT64 b;
  2604. STRING MessageHeader;
  2605. ULONG i;
  2606. ULONG Size;
  2607. DBGKD_WRITE_BREAKPOINT64 BpBuf[BREAKPOINT_TABLE_SIZE];
  2608. MessageHeader.Length = sizeof(*m);
  2609. MessageHeader.Buffer = (PCHAR)m;
  2610. //
  2611. // verify that the packet size is correct
  2612. //
  2613. if (AdditionalData->Length !=
  2614. a->BreakPointCount * sizeof(DBGKD_WRITE_BREAKPOINT64))
  2615. {
  2616. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  2617. KdSendPacket(
  2618. PACKET_TYPE_KD_STATE_MANIPULATE,
  2619. &MessageHeader,
  2620. AdditionalData,
  2621. &KdpContext
  2622. );
  2623. return m->ReturnStatus;
  2624. }
  2625. KdpCopyFromPtr(BpBuf,
  2626. AdditionalData->Buffer,
  2627. a->BreakPointCount * sizeof(DBGKD_WRITE_BREAKPOINT64),
  2628. &Size);
  2629. if (Size == a->BreakPointCount * sizeof(DBGKD_WRITE_BREAKPOINT64))
  2630. {
  2631. m->ReturnStatus = STATUS_SUCCESS;
  2632. }
  2633. else
  2634. {
  2635. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  2636. KdSendPacket(
  2637. PACKET_TYPE_KD_STATE_MANIPULATE,
  2638. &MessageHeader,
  2639. AdditionalData,
  2640. &KdpContext
  2641. );
  2642. return m->ReturnStatus;
  2643. }
  2644. //
  2645. // loop thru the breakpoint handles passed in from the debugger and
  2646. // clear any breakpoint that has a non-zero handle
  2647. //
  2648. b = BpBuf;
  2649. for (i=0; i<a->BreakPointCount; i++,b++) {
  2650. if (b->BreakPointHandle) {
  2651. if (!KdpDeleteBreakpoint(b->BreakPointHandle)) {
  2652. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  2653. }
  2654. b->BreakPointHandle = 0;
  2655. }
  2656. }
  2657. //
  2658. // loop thru the breakpoint addesses passed in from the debugger and
  2659. // add any new breakpoints that have a non-zero address
  2660. //
  2661. b = BpBuf;
  2662. for (i=0; i<a->BreakPointCount; i++,b++) {
  2663. if (b->BreakPointAddress) {
  2664. b->BreakPointHandle = KdpAddBreakpoint( (PVOID)b->BreakPointAddress );
  2665. if (!b->BreakPointHandle) {
  2666. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  2667. }
  2668. }
  2669. }
  2670. //
  2671. // send back our response
  2672. //
  2673. KdpCopyToPtr(AdditionalData->Buffer,
  2674. BpBuf,
  2675. a->BreakPointCount * sizeof(DBGKD_WRITE_BREAKPOINT64),
  2676. &Size);
  2677. KdSendPacket(
  2678. PACKET_TYPE_KD_STATE_MANIPULATE,
  2679. &MessageHeader,
  2680. AdditionalData,
  2681. &KdpContext
  2682. );
  2683. //
  2684. // return the caller's continue status value. if this is a non-zero
  2685. // value the system is continued using this value as the continuestatus.
  2686. //
  2687. return a->ContinueStatus;
  2688. }
  2689. VOID
  2690. KdpRestoreBreakPointEx(
  2691. IN PDBGKD_MANIPULATE_STATE64 m,
  2692. IN PSTRING AdditionalData,
  2693. IN PCONTEXT Context
  2694. )
  2695. /*++
  2696. Routine Description:
  2697. This function is called in response of a restore breakpoint state 'ex'
  2698. manipulation message. Its function is to clear a list of breakpoints.
  2699. Arguments:
  2700. m - Supplies the state manipulation message.
  2701. AdditionalData - Supplies any additional data for the message.
  2702. Context - Supplies the current context.
  2703. Return Value:
  2704. None.
  2705. --*/
  2706. {
  2707. PDBGKD_BREAKPOINTEX a = &m->u.BreakPointEx;
  2708. PDBGKD_RESTORE_BREAKPOINT b;
  2709. STRING MessageHeader;
  2710. ULONG i;
  2711. ULONG Size;
  2712. DBGKD_RESTORE_BREAKPOINT BpBuf[BREAKPOINT_TABLE_SIZE];
  2713. MessageHeader.Length = sizeof(*m);
  2714. MessageHeader.Buffer = (PCHAR)m;
  2715. //
  2716. // verify that the packet size is correct
  2717. //
  2718. if (AdditionalData->Length !=
  2719. a->BreakPointCount*sizeof(DBGKD_RESTORE_BREAKPOINT))
  2720. {
  2721. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  2722. }
  2723. else
  2724. {
  2725. KdpCopyFromPtr(BpBuf,
  2726. AdditionalData->Buffer,
  2727. a->BreakPointCount * sizeof(DBGKD_RESTORE_BREAKPOINT),
  2728. &Size);
  2729. if (Size == a->BreakPointCount*sizeof(DBGKD_RESTORE_BREAKPOINT))
  2730. {
  2731. m->ReturnStatus = STATUS_SUCCESS;
  2732. //
  2733. // loop thru the breakpoint handles passed in from the debugger and
  2734. // clear any breakpoint that has a non-zero handle
  2735. //
  2736. b = BpBuf;
  2737. for (i=0; i<a->BreakPointCount; i++,b++) {
  2738. if (!KdpDeleteBreakpoint(b->BreakPointHandle)) {
  2739. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  2740. }
  2741. }
  2742. }
  2743. else
  2744. {
  2745. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  2746. }
  2747. }
  2748. //
  2749. // send back our response
  2750. //
  2751. KdSendPacket(
  2752. PACKET_TYPE_KD_STATE_MANIPULATE,
  2753. &MessageHeader,
  2754. AdditionalData,
  2755. &KdpContext
  2756. );
  2757. }
  2758. VOID
  2759. KdDisableDebugger(
  2760. VOID
  2761. )
  2762. /*++
  2763. Routine Description:
  2764. This function is called to disable the debugger.
  2765. Arguments:
  2766. None.
  2767. Return Value:
  2768. None.
  2769. --*/
  2770. {
  2771. KIRQL oldIrql ;
  2772. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql) ;
  2773. KdpPortLock();
  2774. if (!KdDisableCount) {
  2775. KdPreviouslyEnabled = KdDebuggerEnabled && (!KdPitchDebugger) ;
  2776. if (KdDebuggerEnabled) {
  2777. KdpSuspendAllBreakpoints() ;
  2778. KiDebugRoutine = KdpStub;
  2779. KdDebuggerEnabled = FALSE ;
  2780. }
  2781. }
  2782. KdDisableCount++ ;
  2783. KdpPortUnlock();
  2784. KeLowerIrql(oldIrql);
  2785. }
  2786. VOID
  2787. KdEnableDebugger(
  2788. VOID
  2789. )
  2790. /*++
  2791. Routine Description:
  2792. This function is called to reenable the debugger after a call to
  2793. KdDisableDebugger.
  2794. Arguments:
  2795. None.
  2796. Return Value:
  2797. None.
  2798. --*/
  2799. {
  2800. KIRQL oldIrql ;
  2801. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql) ;
  2802. KdpPortLock();
  2803. ASSERT(KdDisableCount > 0) ;
  2804. KdDisableCount-- ;
  2805. if (!KdDisableCount) {
  2806. if (KdPreviouslyEnabled) {
  2807. //
  2808. // Ugly HACKHACK - Make sure the timers aren't reset.
  2809. //
  2810. PoHiberInProgress = TRUE ;
  2811. KdInitSystem(0, NULL);
  2812. KdpRestoreAllBreakpoints();
  2813. PoHiberInProgress = FALSE ;
  2814. }
  2815. }
  2816. KdpPortUnlock();
  2817. KeLowerIrql(oldIrql);
  2818. }
  2819. VOID
  2820. KdpSearchMemory(
  2821. IN PDBGKD_MANIPULATE_STATE64 m,
  2822. IN PSTRING AdditionalData,
  2823. IN PCONTEXT Context
  2824. )
  2825. /*++
  2826. Routine Description:
  2827. This function implements a memory pattern searcher. This will
  2828. find an instance of a pattern that begins in the range
  2829. SearchAddress..SearchAddress+SearchLength. The pattern may
  2830. end outside of the range.
  2831. Arguments:
  2832. m - Supplies the state manipulation message.
  2833. AdditionalData - Supplies the pattern to search for
  2834. Context - Supplies the current context.
  2835. Return Value:
  2836. None.
  2837. --*/
  2838. {
  2839. PUCHAR Pattern = AdditionalData->Buffer;
  2840. ULONG_PTR StartAddress = (ULONG_PTR)m->u.SearchMemory.SearchAddress;
  2841. ULONG_PTR EndAddress = (ULONG_PTR)(StartAddress + m->u.SearchMemory.SearchLength);
  2842. ULONG PatternLength = m->u.SearchMemory.PatternLength;
  2843. STRING MessageHeader;
  2844. ULONG MaskIndex;
  2845. PUCHAR PatternTail;
  2846. ULONG_PTR DataTail;
  2847. ULONG TailLength;
  2848. ULONG Data;
  2849. ULONG FirstWordPattern[4];
  2850. ULONG FirstWordMask[4];
  2851. UCHAR DataTailVal;
  2852. //
  2853. // On failure, return STATUS_NO_MORE_ENTRIES. DON'T RETURN
  2854. // STATUS_UNSUCCESSFUL! That return status indicates that the
  2855. // operation is not supported, and the debugger will fall back
  2856. // to a debugger-side search.
  2857. //
  2858. m->ReturnStatus = STATUS_NO_MORE_ENTRIES;
  2859. //
  2860. // Do a fast search for the beginning of the pattern
  2861. //
  2862. if (PatternLength > 3) {
  2863. FirstWordMask[0] = 0xffffffff;
  2864. } else {
  2865. FirstWordMask[0] = 0xffffffff >> (8*(4-PatternLength));
  2866. }
  2867. FirstWordMask[1] = FirstWordMask[0] << 8;
  2868. FirstWordMask[2] = FirstWordMask[1] << 8;
  2869. FirstWordMask[3] = FirstWordMask[2] << 8;
  2870. FirstWordPattern[0] = 0;
  2871. KdpQuickMoveMemory((PVOID)FirstWordPattern,
  2872. Pattern,
  2873. PatternLength < 5 ? PatternLength : 4);
  2874. FirstWordPattern[1] = FirstWordPattern[0] << 8;
  2875. FirstWordPattern[2] = FirstWordPattern[1] << 8;
  2876. FirstWordPattern[3] = FirstWordPattern[2] << 8;
  2877. /*
  2878. {
  2879. int i;
  2880. for (i = 0; i < (int)PatternLength; i++) {
  2881. KdpDprintf("%08x: %02x\n", &Pattern[i], Pattern[i]);
  2882. }
  2883. for (i = 0; i < 4; i++) {
  2884. KdpDprintf("%d: %08x %08x\n", i, FirstWordPattern[i], FirstWordMask[i]);
  2885. }
  2886. }
  2887. */
  2888. //
  2889. // Get starting mask
  2890. //
  2891. MaskIndex = (ULONG) (StartAddress & 3);
  2892. StartAddress = StartAddress & ~3;
  2893. while (StartAddress < EndAddress) {
  2894. // Get the current data DWORD. StartAddress is
  2895. // properly aligned and we only need the one DWORD
  2896. // so we can directly call MmDbgCopyMemory.
  2897. if (!NT_SUCCESS(MmDbgCopyMemory(StartAddress, &Data, 4,
  2898. MMDBG_COPY_UNSAFE))) {
  2899. //KdpDprintf("\n%08x: Inaccessible\n", StartAddress);
  2900. StartAddress += 4;
  2901. MaskIndex = 0;
  2902. continue;
  2903. }
  2904. //
  2905. // search for a match in each of the 4 starting positions
  2906. //
  2907. //KdpDprintf("\n%08x: %08x ", StartAddress, Data);
  2908. for ( ; MaskIndex < 4; MaskIndex++) {
  2909. //KdpDprintf(" %d", MaskIndex);
  2910. if ( (Data & FirstWordMask[MaskIndex]) == FirstWordPattern[MaskIndex]) {
  2911. //
  2912. // first word matched
  2913. //
  2914. if ( (4-MaskIndex) >= PatternLength ) {
  2915. //
  2916. // string is all in this word; good match
  2917. //
  2918. //KdpDprintf(" %d hit, complete\n", MaskIndex);
  2919. m->u.SearchMemory.FoundAddress = StartAddress + MaskIndex;
  2920. m->ReturnStatus = STATUS_SUCCESS;
  2921. goto done;
  2922. } else {
  2923. //
  2924. // string is longer; see if tail matches
  2925. //
  2926. //KdpDprintf(" %d hit, check tail\n", MaskIndex);
  2927. PatternTail = Pattern + 4 - MaskIndex;
  2928. DataTail = StartAddress + 4;
  2929. TailLength = PatternLength - 4 + MaskIndex;
  2930. //KdpDprintf("Pattern == %08x\n", Pattern);
  2931. //KdpDprintf("PatternTail == %08x\n", PatternTail);
  2932. //KdpDprintf("DataTail == %08x\n", DataTail);
  2933. while (TailLength) {
  2934. if (!NT_SUCCESS(MmDbgCopyMemory(DataTail,
  2935. &DataTailVal,
  2936. 1,
  2937. MMDBG_COPY_UNSAFE))) {
  2938. //KdpDprintf("Tail %08x: Inaccessible\n", DataTail);
  2939. break;
  2940. }
  2941. //KdpDprintf("D: %02x P: %02x\n", DataTailVal, *PatternTail);
  2942. if (DataTailVal != *PatternTail) {
  2943. //KdpDprintf("Tail failed at %08x\n", DataTail);
  2944. break;
  2945. } else {
  2946. DataTail++;
  2947. PatternTail++;
  2948. TailLength--;
  2949. }
  2950. }
  2951. if (TailLength == 0) {
  2952. //
  2953. // A winner
  2954. //
  2955. m->u.SearchMemory.FoundAddress = StartAddress + MaskIndex;
  2956. m->ReturnStatus = STATUS_SUCCESS;
  2957. goto done;
  2958. }
  2959. }
  2960. }
  2961. }
  2962. StartAddress += 4;
  2963. MaskIndex = 0;
  2964. }
  2965. done:
  2966. //KdpDprintf("\n");
  2967. MessageHeader.Length = sizeof(*m);
  2968. MessageHeader.Buffer = (PCHAR)m;
  2969. KdSendPacket(
  2970. PACKET_TYPE_KD_STATE_MANIPULATE,
  2971. &MessageHeader,
  2972. NULL,
  2973. &KdpContext
  2974. );
  2975. }
  2976. VOID
  2977. KdpCheckLowMemory(
  2978. IN PDBGKD_MANIPULATE_STATE64 Message
  2979. )
  2980. /*++
  2981. Routine Description:
  2982. Arguments:
  2983. Message - Supplies the state manipulation message.
  2984. Return Value:
  2985. None.
  2986. Description:
  2987. This function gets called when the !chklowmem
  2988. debugger extension is used.
  2989. --*/
  2990. {
  2991. STRING MessageHeader;
  2992. MessageHeader.Length = sizeof(*Message);
  2993. MessageHeader.Buffer = (PCHAR)Message;
  2994. Message->ReturnStatus = KdpSysCheckLowMemory();
  2995. //
  2996. // Acknowledge the packet received.
  2997. //
  2998. KdSendPacket (
  2999. PACKET_TYPE_KD_STATE_MANIPULATE,
  3000. &MessageHeader,
  3001. NULL,
  3002. &KdpContext
  3003. );
  3004. }
  3005. //
  3006. // !search support routines
  3007. //
  3008. ULONG
  3009. KdpSearchHammingDistance (
  3010. ULONG_PTR Left,
  3011. ULONG_PTR Right
  3012. )
  3013. /*++
  3014. Routine Description:
  3015. This routine computes the Hamming distance (# of positions where the
  3016. values are different).
  3017. If this function becomes a bottleneck we should switch to a function
  3018. table version.
  3019. Arguments:
  3020. Left, Right operand.
  3021. Return Value:
  3022. Hamming distance.
  3023. Environment:
  3024. Any.
  3025. --*/
  3026. {
  3027. ULONG_PTR Value;
  3028. ULONG Index;
  3029. ULONG Distance;
  3030. Value = Left ^ Right;
  3031. Distance = 0;
  3032. for (Index = 0; Index < 8 * sizeof(ULONG_PTR); Index++) {
  3033. if ((Value & (ULONG_PTR)0x01)) {
  3034. Distance += 1;
  3035. }
  3036. Value >>= 1;
  3037. }
  3038. return Distance;
  3039. }
  3040. LOGICAL
  3041. KdpSearchPhysicalPage (
  3042. IN PFN_NUMBER PageFrameIndex,
  3043. ULONG_PTR RangeStart,
  3044. ULONG_PTR RangeEnd,
  3045. ULONG Flags
  3046. )
  3047. /*++
  3048. Routine Description:
  3049. This routine searches the physical page corresponding to a
  3050. certain PFN index for any ULONG_PTR values in range [Start..End].
  3051. Arguments:
  3052. PageFrameIndex - PFN index
  3053. RangeStart - lowest possible value searched for
  3054. RangeEnd - highest possible value searched for
  3055. Flags - flags to control the search
  3056. Return Value:
  3057. TRUE if a hit has been found, FALSE otherwise.
  3058. The function stops after the first hit in the page is
  3059. encountered and the information related to the hit (PFN index,
  3060. offset, corresponding VA) is registered in the hit database.
  3061. Environment:
  3062. Call triggered only from Kd extension.
  3063. --*/
  3064. {
  3065. LOGICAL Status;
  3066. NTSTATUS CopyStatus;
  3067. ULONG Index;
  3068. PHYSICAL_ADDRESS Pa;
  3069. Pa.QuadPart = ((ULONGLONG)PageFrameIndex) << PAGE_SHIFT;
  3070. Status = FALSE;
  3071. if (KdpSearchPfnValue) {
  3072. HARDWARE_PTE PteValue;
  3073. //
  3074. // We need to search for a PFN
  3075. //
  3076. for (Index = 0; Index < PAGE_SIZE; Index += sizeof(HARDWARE_PTE)) {
  3077. CopyStatus = MmDbgCopyMemory ((ULONG64)(Pa.QuadPart) + Index,
  3078. &PteValue,
  3079. sizeof PteValue,
  3080. MMDBG_COPY_PHYSICAL | MMDBG_COPY_UNSAFE);
  3081. if (NT_SUCCESS(CopyStatus)) {
  3082. if (PteValue.PageFrameNumber == RangeStart) {
  3083. if (KdpSearchPageHitIndex < SEARCH_PAGE_HIT_DATABASE_SIZE) {
  3084. KdpSearchPageHits[KdpSearchPageHitIndex] = PageFrameIndex;
  3085. KdpSearchPageHitOffsets[KdpSearchPageHitIndex] = Index;
  3086. KdpSearchPageHitIndex += 1;
  3087. }
  3088. if ((Flags & KDP_SEARCH_ALL_OFFSETS_IN_PAGE) == 0) {
  3089. Status = TRUE;
  3090. break;
  3091. }
  3092. }
  3093. }
  3094. }
  3095. }
  3096. else {
  3097. ULONG_PTR Value;
  3098. //
  3099. // We need to search for an address pattern
  3100. //
  3101. for (Index = 0; Index < PAGE_SIZE; Index += sizeof(ULONG_PTR)) {
  3102. CopyStatus = MmDbgCopyMemory ((ULONG64)(Pa.QuadPart) + Index,
  3103. &Value,
  3104. sizeof Value,
  3105. MMDBG_COPY_PHYSICAL | MMDBG_COPY_UNSAFE);
  3106. if (NT_SUCCESS(CopyStatus)) {
  3107. if ((Value >= RangeStart && Value <= RangeEnd) ||
  3108. (KdpSearchHammingDistance(Value, RangeStart) == 1)) {
  3109. if (KdpSearchPageHitIndex < SEARCH_PAGE_HIT_DATABASE_SIZE) {
  3110. KdpSearchPageHits[KdpSearchPageHitIndex] = PageFrameIndex;
  3111. KdpSearchPageHitOffsets[KdpSearchPageHitIndex] = Index;
  3112. KdpSearchPageHitIndex += 1;
  3113. }
  3114. if ((Flags & KDP_SEARCH_ALL_OFFSETS_IN_PAGE) == 0) {
  3115. Status = TRUE;
  3116. break;
  3117. }
  3118. }
  3119. }
  3120. }
  3121. }
  3122. return Status;
  3123. }
  3124. LOGICAL
  3125. KdpSearchPhysicalMemoryRequested (
  3126. VOID
  3127. )
  3128. /*++
  3129. Routine Description:
  3130. This routine determines if a physical range search has been
  3131. requested. This is controlled by a global variable set in
  3132. the `!search' debug extension.
  3133. Arguments:
  3134. None
  3135. Return Value:
  3136. TRUE if physical range search was requested.
  3137. Environment:
  3138. Call triggered only from Kd extension.
  3139. --*/
  3140. {
  3141. if (KdpSearchInProgress) {
  3142. return TRUE;
  3143. }
  3144. else {
  3145. return FALSE;
  3146. }
  3147. }
  3148. LOGICAL
  3149. KdpSearchPhysicalPageRange (
  3150. VOID
  3151. )
  3152. /*++
  3153. Routine Description:
  3154. This routine will start a search in a range of physical pages in case
  3155. `KdpSearchInProgress' is true. the parameters for the search are picked up
  3156. from global vairiables that are set inside a kernel debugger extension.
  3157. Arguments:
  3158. None
  3159. Return Value:
  3160. TRUE if the function executed a search and FALSE otherwise.
  3161. The results of the search are specified in the KdpSearchPageHits
  3162. and related variables. this global variables offers the mechanism
  3163. for the debugger extension to pickup the results of the search.
  3164. Environment:
  3165. Call triggered only from Kd extension.
  3166. Note. The !search extension make sure that the range requested
  3167. is part of the system memory therefore we do not have to
  3168. worry about sparse PFN databases here.
  3169. --*/
  3170. {
  3171. PFN_NUMBER CurrentFrame;
  3172. ULONG Flags;
  3173. //
  3174. // The debugger extension is supposed to set KdpSearchInProgress
  3175. // to TRUE if a search is requested.
  3176. //
  3177. if (!KdpSearchInProgress) {
  3178. return FALSE;
  3179. }
  3180. Flags = 0;
  3181. //
  3182. // If the search range is only one page we will give all
  3183. // hits inside a page. By default we get only the first hit inside
  3184. // a page.
  3185. //
  3186. if (KdpSearchEndPageFrame == KdpSearchStartPageFrame) {
  3187. KdpSearchEndPageFrame += 1;
  3188. Flags |= KDP_SEARCH_ALL_OFFSETS_IN_PAGE;
  3189. }
  3190. for (CurrentFrame = KdpSearchStartPageFrame;
  3191. CurrentFrame < KdpSearchEndPageFrame;
  3192. CurrentFrame += 1) {
  3193. KdpSearchPhysicalPage (CurrentFrame,
  3194. KdpSearchAddressRangeStart,
  3195. KdpSearchAddressRangeEnd,
  3196. Flags);
  3197. }
  3198. return TRUE;
  3199. }
  3200. VOID
  3201. KdpFillMemory(
  3202. IN PDBGKD_MANIPULATE_STATE64 m,
  3203. IN PSTRING AdditionalData,
  3204. IN PCONTEXT Context
  3205. )
  3206. /*++
  3207. Routine Description:
  3208. Fill a section of memory with a given pattern.
  3209. Arguments:
  3210. m - Supplies the state manipulation message.
  3211. AdditionalData - Supplies the pattern to search for.
  3212. Context - Supplies the current context.
  3213. Return Value:
  3214. None.
  3215. --*/
  3216. {
  3217. STRING MessageHeader;
  3218. NTSTATUS Status = STATUS_SUCCESS;
  3219. ULONG Length = m->u.FillMemory.Length;
  3220. PUCHAR Pattern = AdditionalData->Buffer;
  3221. PUCHAR Pat = Pattern;
  3222. PUCHAR PatEnd = Pat + m->u.FillMemory.PatternLength;
  3223. ULONG Filled = 0;
  3224. ULONG ChunkFlags = MMDBG_COPY_WRITE | MMDBG_COPY_UNSAFE;
  3225. if (m->u.FillMemory.Flags & DBGKD_FILL_MEMORY_PHYSICAL) {
  3226. ChunkFlags |= MMDBG_COPY_PHYSICAL;
  3227. } else if (!(m->u.FillMemory.Flags & DBGKD_FILL_MEMORY_VIRTUAL)) {
  3228. Status = STATUS_INVALID_PARAMETER;
  3229. }
  3230. if (NT_SUCCESS(Status)) {
  3231. ULONG64 Address = m->u.FillMemory.Address;
  3232. while (Length-- > 0) {
  3233. ULONG Done;
  3234. if (!NT_SUCCESS(Status =
  3235. KdpCopyMemoryChunks(Address, Pat, 1, 0,
  3236. ChunkFlags, &Done))) {
  3237. break;
  3238. }
  3239. Address++;
  3240. if (++Pat == PatEnd) {
  3241. Pat = Pattern;
  3242. }
  3243. Filled++;
  3244. }
  3245. // If nothing was filled return an error, otherwise
  3246. // consider it a success.
  3247. Status = Filled > 0 ? STATUS_SUCCESS : Status;
  3248. }
  3249. m->ReturnStatus = Status;
  3250. m->u.FillMemory.Length = Filled;
  3251. MessageHeader.Length = sizeof(*m);
  3252. MessageHeader.Buffer = (PCHAR)m;
  3253. KdSendPacket(
  3254. PACKET_TYPE_KD_STATE_MANIPULATE,
  3255. &MessageHeader,
  3256. NULL,
  3257. &KdpContext
  3258. );
  3259. }
  3260. VOID
  3261. KdpQueryMemory(
  3262. IN PDBGKD_MANIPULATE_STATE64 m,
  3263. IN PCONTEXT Context
  3264. )
  3265. /*++
  3266. Routine Description:
  3267. Query what kind of memory a particular address refers to.
  3268. Arguments:
  3269. m - Supplies the state manipulation message.
  3270. Context - Supplies the current context.
  3271. Return Value:
  3272. None.
  3273. --*/
  3274. {
  3275. STRING MessageHeader;
  3276. NTSTATUS Status = STATUS_SUCCESS;
  3277. if (m->u.QueryMemory.AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL) {
  3278. PVOID Addr = (PVOID)(ULONG_PTR)m->u.QueryMemory.Address;
  3279. //
  3280. // Right now all we check for is user/session/kernel.
  3281. //
  3282. if (Addr < MM_HIGHEST_USER_ADDRESS) {
  3283. m->u.QueryMemory.AddressSpace = DBGKD_QUERY_MEMORY_PROCESS;
  3284. } else if (MmIsSessionAddress(Addr)) {
  3285. m->u.QueryMemory.AddressSpace = DBGKD_QUERY_MEMORY_SESSION;
  3286. } else {
  3287. m->u.QueryMemory.AddressSpace = DBGKD_QUERY_MEMORY_KERNEL;
  3288. }
  3289. // Always return the most permissive flags.
  3290. m->u.QueryMemory.Flags =
  3291. DBGKD_QUERY_MEMORY_READ |
  3292. DBGKD_QUERY_MEMORY_WRITE |
  3293. DBGKD_QUERY_MEMORY_EXECUTE;
  3294. } else {
  3295. Status = STATUS_INVALID_PARAMETER;
  3296. }
  3297. m->ReturnStatus = Status;
  3298. m->u.QueryMemory.Reserved = 0;
  3299. MessageHeader.Length = sizeof(*m);
  3300. MessageHeader.Buffer = (PCHAR)m;
  3301. KdSendPacket(
  3302. PACKET_TYPE_KD_STATE_MANIPULATE,
  3303. &MessageHeader,
  3304. NULL,
  3305. &KdpContext
  3306. );
  3307. }
  3308. VOID
  3309. KdpSysGetVersion(
  3310. PDBGKD_GET_VERSION64 Version
  3311. )
  3312. /*++
  3313. Routine Description:
  3314. This function returns to the caller a general information packet
  3315. that contains useful information to a debugger. This packet is also
  3316. used for a debugger to determine if the writebreakpointex and
  3317. readbreakpointex apis are available.
  3318. Arguments:
  3319. Version - Supplies the structure to fill in
  3320. Return Value:
  3321. None.
  3322. --*/
  3323. {
  3324. *Version = KdVersionBlock;
  3325. }
  3326. NTSTATUS
  3327. KdpSysReadBusData(
  3328. BUS_DATA_TYPE BusDataType,
  3329. ULONG BusNumber,
  3330. ULONG SlotNumber,
  3331. ULONG Address,
  3332. PVOID Buffer,
  3333. ULONG Request,
  3334. PULONG Actual
  3335. )
  3336. /*++
  3337. Routine Description:
  3338. Reads I/O configuration space.
  3339. Arguments:
  3340. BusDataType - Bus data type.
  3341. BusNumber - Bus number.
  3342. SlotNumber - Slot number.
  3343. Address - Configuration space address.
  3344. Buffer - Data buffer.
  3345. Request - Amount of data to move.
  3346. Actual - Amount of data actually moved.
  3347. Return Value:
  3348. NTSTATUS.
  3349. --*/
  3350. {
  3351. *Actual = HalGetBusDataByOffset(BusDataType, BusNumber, SlotNumber,
  3352. Buffer, Address, Request);
  3353. return *Actual == Request ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  3354. }
  3355. NTSTATUS
  3356. KdpSysWriteBusData(
  3357. BUS_DATA_TYPE BusDataType,
  3358. ULONG BusNumber,
  3359. ULONG SlotNumber,
  3360. ULONG Address,
  3361. PVOID Buffer,
  3362. ULONG Request,
  3363. PULONG Actual
  3364. )
  3365. /*++
  3366. Routine Description:
  3367. Writes I/O configuration space.
  3368. Arguments:
  3369. BusDataType - Bus data type.
  3370. BusNumber - Bus number.
  3371. SlotNumber - Slot number.
  3372. Address - Configuration space address.
  3373. Buffer - Data buffer.
  3374. Request - Amount of data to move.
  3375. Actual - Amount of data actually moved.
  3376. Return Value:
  3377. NTSTATUS.
  3378. --*/
  3379. {
  3380. *Actual = HalSetBusDataByOffset(BusDataType, BusNumber, SlotNumber,
  3381. Buffer, Address, Request);
  3382. return *Actual == Request ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  3383. }
  3384. NTSTATUS
  3385. KdpSysCheckLowMemory(
  3386. VOID
  3387. )
  3388. /*++
  3389. Routine Description:
  3390. Arguments:
  3391. None.
  3392. Return Value:
  3393. NTSTATUS.
  3394. Description:
  3395. This function gets called when the !chklowmem
  3396. debugger extension is used.
  3397. --*/
  3398. {
  3399. PFN_NUMBER Page;
  3400. PFN_NUMBER NextPage;
  3401. PHYSICAL_ADDRESS P;
  3402. PVOID64 VirtualAddress;
  3403. ULONG CorruptionOffset;
  3404. NTSTATUS Status;
  3405. Status = STATUS_SUCCESS;
  3406. if (KdpSearchPhysicalMemoryRequested()) {
  3407. //
  3408. // This is a !search kd extension call.
  3409. //
  3410. KdpSearchPhysicalPageRange();
  3411. }
  3412. else {
  3413. //
  3414. // Check low physical memory on machines with more than 4GB.
  3415. //
  3416. Page = 0;
  3417. do {
  3418. if (! MmDbgIsLowMemOk (Page, &NextPage, &CorruptionOffset)) {
  3419. Status = (NTSTATUS) Page;
  3420. break;
  3421. }
  3422. Page = NextPage;
  3423. } while (Page != 0);
  3424. }
  3425. return Status;
  3426. }
  3427. //----------------------------------------------------------------------------
  3428. //
  3429. // Tracing data support.
  3430. //
  3431. //----------------------------------------------------------------------------
  3432. VOID
  3433. KdpSendTraceData(
  3434. PSTRING Data
  3435. )
  3436. {
  3437. ULONG Length;
  3438. STRING MessageData;
  3439. STRING MessageHeader;
  3440. DBGKD_TRACE_IO TraceIo;
  3441. //
  3442. // Move the output string to the message buffer.
  3443. //
  3444. KdpCopyFromPtr(KdpMessageBuffer,
  3445. Data->Buffer,
  3446. Data->Length,
  3447. &Length);
  3448. //
  3449. // If the total message length is greater than the maximum packet size,
  3450. // then truncate the output string.
  3451. //
  3452. if ((sizeof(TraceIo) + Length) > PACKET_MAX_SIZE) {
  3453. Length = PACKET_MAX_SIZE - sizeof(TraceIo);
  3454. }
  3455. //
  3456. // Construct the print string message and message descriptor.
  3457. //
  3458. TraceIo.ApiNumber = DbgKdPrintTraceApi;
  3459. TraceIo.ProcessorLevel = KeProcessorLevel;
  3460. TraceIo.Processor = (USHORT)KeGetCurrentPrcb()->Number;
  3461. TraceIo.u.PrintTrace.LengthOfData = Length;
  3462. MessageHeader.Length = sizeof(TraceIo);
  3463. MessageHeader.Buffer = (PCHAR)&TraceIo;
  3464. //
  3465. // Construct the print string data and data descriptor.
  3466. //
  3467. MessageData.Length = (USHORT)Length;
  3468. MessageData.Buffer = KdpMessageBuffer;
  3469. //
  3470. // Send packet to the kernel debugger on the host machine.
  3471. //
  3472. KdSendPacket(
  3473. PACKET_TYPE_KD_TRACE_IO,
  3474. &MessageHeader,
  3475. &MessageData,
  3476. &KdpContext
  3477. );
  3478. }
  3479. VOID
  3480. KdReportTraceData(
  3481. IN struct _WMI_BUFFER_HEADER* Buffer,
  3482. IN PVOID Context
  3483. )
  3484. {
  3485. BOOLEAN Enable;
  3486. STRING Data;
  3487. Data.Buffer = (PCHAR)Buffer;
  3488. if (Buffer->Wnode.BufferSize > 0xffff) {
  3489. Data.Length = 0xffff;
  3490. } else {
  3491. Data.Length = (USHORT)Buffer->Wnode.BufferSize;
  3492. }
  3493. if (KdDebuggerNotPresent == FALSE) {
  3494. Enable = KdEnterDebugger(NULL, NULL);
  3495. KdpSendTraceData(&Data);
  3496. KdExitDebugger(Enable);
  3497. }
  3498. }
  3499. //----------------------------------------------------------------------------
  3500. //
  3501. // Debugger hibernate/suspend support.
  3502. //
  3503. //----------------------------------------------------------------------------
  3504. NTSTATUS
  3505. KdPowerTransition(
  3506. DEVICE_POWER_STATE newDeviceState
  3507. )
  3508. {
  3509. NTSTATUS status = STATUS_SUCCESS;
  3510. switch(newDeviceState) {
  3511. case PowerDeviceD0:
  3512. KdD0Transition();
  3513. break;
  3514. case PowerDeviceD3:
  3515. KdD3Transition();
  3516. break;
  3517. default:
  3518. status = STATUS_INVALID_PARAMETER_1;
  3519. }
  3520. return status;
  3521. }