Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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