test: kdapi.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# kdapi.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     kdapi.c
    00008
    00009 Abstract:
    00010
    00011     Implementation of Kernel Debugger portable remote APIs.
    00012
    00013 Author:
    00014
    00015     Mark Lucovsky (markl) 31-Aug-1990
    00016
    00017 Revision History:
    00018
    00019     John Vert (jvert) 28-May-1991
    00020
    00021         Added APIs for reading and writing physical memory
    00022         (KdpReadPhysicalMemory and KdpWritePhysicalMemory)
    00023
    00024     Wesley Witt (wesw) 18-Aug-1993
    00025
    00026         Added KdpGetVersion, KdpWriteBreakPointEx, & KdpRestoreBreakPointEx
    00027
    00028
    00029 --*/
    00030
    00031 #include "kdp.h"
    00032
    00033 #if ACCASM && !defined(_MSC_VER)
    00034 long asm(const char *,...);
    00035 #pragma intrinsic(asm)
    00036 #endif
    00037
    00038 LARGE_INTEGER KdpQueryPerformanceCounter (
    00039     IN PKTRAP_FRAME TrapFrame
    00040     );
    00041
    00042 extern LARGE_INTEGER Magic10000;
    00043 #define SHIFT10000   13
    00044 #define Convert100nsToMilliseconds(LARGE_INTEGER) (                         \
    00045     RtlExtendedMagicDivide( (LARGE_INTEGER), Magic10000, SHIFT10000 )       \
    00046     )
    00047
    00048 //
    00049 // Define forward referenced function prototypes.
    00050 //
    00051
    00052 VOID
    00053 KdpProcessInternalBreakpoint (
    00054     ULONG BreakpointNumber
    00055     );
    00056
    00057 VOID
    00058 KdpGetVersion(
    00059     IN PDBGKD_MANIPULATE_STATE64 m
    00060     );
    00061
    00062 NTSTATUS
    00063 KdpNotSupported(
    00064     IN PDBGKD_MANIPULATE_STATE64 m
    00065     );
    00066
    00067 VOID
    00068 KdpCauseBugCheck(
    00069     IN PDBGKD_MANIPULATE_STATE64 m
    00070     );
    00071
    00072 NTSTATUS
    00073 KdpWriteBreakPointEx(
    00074     IN PDBGKD_MANIPULATE_STATE64 m,
    00075     IN PSTRING AdditionalData,
    00076     IN PCONTEXT Context
    00077     );
    00078
    00079 VOID
    00080 KdpRestoreBreakPointEx(
    00081     IN PDBGKD_MANIPULATE_STATE64 m,
    00082     IN PSTRING AdditionalData,
    00083     IN PCONTEXT Context
    00084     );
    00085
    00086 VOID
    00087 KdpSearchMemory(
    00088     IN PDBGKD_MANIPULATE_STATE64 m,
    00089     IN PSTRING AdditionalData,
    00090     IN PCONTEXT Context
    00091     );
    00092
    00093 ULONG
    00094 KdpSearchHammingDistance (
    00095     ULONG_PTR Left,
    00096     ULONG_PTR Right
    00097     );
    00098
    00099 LOGICAL
    00100 KdpSearchPhysicalPage (
    00101     IN PFN_NUMBER PageFrameIndex,
    00102     ULONG_PTR RangeStart,
    00103     ULONG_PTR RangeEnd,
    00104     ULONG Flags
    00105     );
    00106
    00107 LOGICAL
    00108 KdpSearchPhysicalMemoryRequested (
    00109     VOID
    00110     );
    00111
    00112 LOGICAL
    00113 KdpSearchPhysicalPageRange (
    00114     VOID
    00115     );
    00116
    00117
    00118 #if i386
    00119 VOID
    00120 InternalBreakpointCheck (
    00121     PKDPC Dpc,
    00122     PVOID DeferredContext,
    00123     PVOID SystemArgument1,
    00124     PVOID SystemArgument2
    00125     );
    00126
    00127 VOID
    00128 KdGetInternalBreakpoint(
    00129     IN PDBGKD_MANIPULATE_STATE64 m
    00130     );
    00131
    00132 long
    00133 SymNumFor(
    00134     ULONG_PTR pc
    00135     );
    00136
    00137 void PotentialNewSymbol (ULONG_PTR pc);
    00138
    00139 void DumpTraceData(PSTRING MessageData);
    00140
    00141 BOOLEAN
    00142 TraceDataRecordCallInfo(
    00143     ULONG InstructionsTraced,
    00144     LONG CallLevelChange,
    00145     ULONG_PTR pc
    00146     );
    00147
    00148 BOOLEAN
    00149 SkippingWhichBP (
    00150     PVOID thread,
    00151     PULONG BPNum
    00152     );
    00153
    00154 BOOLEAN
    00155 KdpCheckTracePoint(
    00156     IN PEXCEPTION_RECORD ExceptionRecord,
    00157     IN OUT PCONTEXT ContextRecord
    00158     );
    00159
    00160 ULONG_PTR
    00161 KdpGetReturnAddress(
    00162     IN PCONTEXT ContextRecord
    00163     );
    00164
    00165 ULONG_PTR
    00166 KdpGetCallNextOffset (
    00167     ULONG_PTR Pc,
    00168     IN PCONTEXT ContextRecord
    00169     );
    00170
    00171 LONG
    00172 KdpLevelChange (
    00173     ULONG_PTR Pc,
    00174     PCONTEXT ContextRecord,
    00175     IN OUT PBOOLEAN SpecialCall
    00176     );
    00177
    00178 #endif // i386
    00179
    00180 #ifdef ALLOC_PRAGMA
    00181 #pragma alloc_text(PAGEKD, KdEnterDebugger)
    00182 #pragma alloc_text(PAGEKD, KdExitDebugger)
    00183 #pragma alloc_text(PAGEKD, KdpTimeSlipDpcRoutine)
    00184 #pragma alloc_text(PAGEKD, KdpTimeSlipWork)
    00185 #pragma alloc_text(PAGEKD, KdpSendWaitContinue)
    00186 #pragma alloc_text(PAGEKD, KdpReadVirtualMemory)
    00187 //#pragma alloc_text(PAGEKD, KdpReadVirtualMemory64)
    00188 #pragma alloc_text(PAGEKD, KdpWriteVirtualMemory)
    00189 //#pragma alloc_text(PAGEKD, KdpWriteVirtualMemory64)
    00190 #pragma alloc_text(PAGEKD, KdpGetContext)
    00191 #pragma alloc_text(PAGEKD, KdpSetContext)
    00192 #pragma alloc_text(PAGEKD, KdpWriteBreakpoint)
    00193 #pragma alloc_text(PAGEKD, KdpRestoreBreakpoint)
    00194 #pragma alloc_text(PAGEKD, KdpReportExceptionStateChange)
    00195 #pragma alloc_text(PAGEKD, KdpReportLoadSymbolsStateChange)
    00196 #pragma alloc_text(PAGEKD, KdpReadPhysicalMemory)
    00197 #pragma alloc_text(PAGEKD, KdpWritePhysicalMemory)
    00198 #pragma alloc_text(PAGEKD, KdpGetVersion)
    00199 #pragma alloc_text(PAGEKD, KdpNotSupported)
    00200 #pragma alloc_text(PAGEKD, KdpCauseBugCheck)
    00201 #pragma alloc_text(PAGEKD, KdpWriteBreakPointEx)
    00202 #pragma alloc_text(PAGEKD, KdpRestoreBreakPointEx)
    00203 #pragma alloc_text(PAGEKD, KdpSearchMemory)
    00204 #pragma alloc_text(PAGEKD, KdpSearchHammingDistance)
    00205 #pragma alloc_text(PAGEKD, KdpSearchPhysicalPage)
    00206 #pragma alloc_text(PAGEKD, KdpSearchPhysicalMemoryRequested)
    00207 #pragma alloc_text(PAGEKD, KdpSearchPhysicalPageRange)
    00208 #if DBG
    00209 #pragma alloc_text(PAGEKD, KdpDprintf)
    00210 #endif
    00211 #if i386
    00212 #pragma alloc_text(PAGEKD, InternalBreakpointCheck)
    00213 #pragma alloc_text(PAGEKD, KdSetInternalBreakpoint)
    00214 #pragma alloc_text(PAGEKD, KdGetTraceInformation)
    00215 #pragma alloc_text(PAGEKD, KdGetInternalBreakpoint)
    00216 #pragma alloc_text(PAGEKD, SymNumFor)
    00217 #pragma alloc_text(PAGEKD, PotentialNewSymbol)
    00218 #pragma alloc_text(PAGEKD, DumpTraceData)
    00219 #pragma alloc_text(PAGEKD, TraceDataRecordCallInfo)
    00220 #pragma alloc_text(PAGEKD, SkippingWhichBP)
    00221 #pragma alloc_text(PAGEKD, KdQuerySpecialCalls)
    00222 #pragma alloc_text(PAGEKD, KdSetSpecialCall)
    00223 #pragma alloc_text(PAGEKD, KdClearSpecialCalls)
    00224 #pragma alloc_text(PAGEKD, KdpCheckTracePoint)
    00225 #pragma alloc_text(PAGEKD, KdpProcessInternalBreakpoint)
    00226 #pragma alloc_text(PAGEKD, KdpCheckLowMemory)
    00227 #endif // i386
    00228 #endif // ALLOC_PRAGMA
    00229
    00230
    00231 //
    00232 // This variable has a count for each time KdDisableDebugger has been called.
    00233 //
    00234 LONG KdDisableCount = 0 ;
    00235 BOOLEAN KdPreviouslyEnabled ;
    00236
    00237
    00238 #if DBG
    00239 VOID
    00240 KdpDprintf(
    00241     IN PCHAR f,
    00242     ...
    00243     )
    00244 /*++
    00245
    00246 Routine Description:
    00247
    00248     Printf routine for the debugger that is safer than DbgPrint.  Calls
    00249     the packet driver instead of reentering the debugger.
    00250
    00251 Arguments:
    00252
    00253     f - Supplies printf format
    00254
    00255 Return Value:
    00256
    00257     None
    00258
    00259 --*/
    00260 {
    00261     char    buf[100];
    00262     STRING  Output;
    00263     va_list mark;
    00264
    00265     va_start(mark, f);
    00266     _vsnprintf(buf, 100, f, mark);
    00267     va_end(mark);
    00268
    00269     Output.Buffer = buf;
    00270     Output.Length = strlen(Output.Buffer);
    00271     KdpPrintString(&Output);
    00272 }
    00273 #endif // DBG
    00274
    00275
    00276 BOOLEAN
    00277 KdEnterDebugger(
    00278     IN PKTRAP_FRAME TrapFrame,
    00279     IN PKEXCEPTION_FRAME ExceptionFrame
    00280     )
    00281
    00282 /*++
    00283
    00284 Routine Description:
    00285
    00286     This function is used to enter the kernel debugger. Its purpose
    00287     is to freeze all other processors and aqcuire the kernel debugger
    00288     comm port.
    00289
    00290 Arguments:
    00291
    00292     TrapFrame - Supplies a pointer to a trap frame that describes the
    00293         trap.
    00294
    00295     ExceptionFrame - Supplies a pointer to an exception frame that
    00296         describes the trap.
    00297
    00298 Return Value:
    00299
    00300     Returns the previous interrupt enable.
    00301
    00302 --*/
    00303
    00304 {
    00305
    00306     BOOLEAN Enable;
    00307     TIME_FIELDS TimeFields;
    00308 #if DBG
    00309     extern ULONG KiFreezeFlag;
    00310 #endif
    00311
    00312     //
    00313     // HACKHACK - do some crude timer support
    00314     //            but not if called from KdSetOwedBreakpoints()
    00315     //
    00316
    00317     if (TrapFrame) {
    00318         KdTimerStop = KdpQueryPerformanceCounter (TrapFrame);
    00319         KdTimerDifference.QuadPart = KdTimerStop.QuadPart - KdTimerStart.QuadPart;
    00320     } else {
    00321         KdTimerStop.QuadPart = 0;
    00322     }
    00323
    00324     //
    00325     // Freeze all other processors, raise IRQL to HIGH_LEVEL, and save debug
    00326     // port state.  We lock the port so that KdPollBreakin and a debugger
    00327     // operation don't interfere with each other.
    00328     //
    00329
    00330     Enable = KeFreezeExecution(TrapFrame, ExceptionFrame);
    00331     KdpPortLocked = KiTryToAcquireSpinLock(&KdpDebuggerLock);
    00332     KdPortSave();
    00333     KdEnteredDebugger = TRUE;
    00334
    00335 #if DBG
    00336
    00337     if ((KiFreezeFlag & FREEZE_BACKUP) != 0) {
    00338         DPRINT(("FreezeLock was jammed!  Backup SpinLock was used!\n"));
    00339     }
    00340
    00341     if ((KiFreezeFlag & FREEZE_SKIPPED_PROCESSOR) != 0) {
    00342         DPRINT(("Some processors not frozen in debugger!\n"));
    00343     }
    00344
    00345     if (KdpPortLocked == FALSE) {
    00346         DPRINT(("Port lock was not acquired!\n"));
    00347     }
    00348
    00349 #endif
    00350
    00351     return Enable;
    00352 }
    00353
    00354 VOID
    00355 KdExitDebugger(
    00356     IN BOOLEAN Enable
    00357     )
    00358
    00359 /*++
    00360
    00361 Routine Description:
    00362
    00363     This function is used to exit the kernel debugger. It is the reverse
    00364     of KdEnterDebugger.
    00365
    00366 Arguments:
    00367
    00368     Enable - Supplies the previous interrupt enable which is to be restored.
    00369
    00370 Return Value:
    00371
    00372     None.
    00373
    00374 --*/
    00375
    00376 {
    00377     ULONG ElapsedTime;
    00378     ULARGE_INTEGER TimeDifference;
    00379     TIME_FIELDS TimeFields;
    00380     ULONG Pending;
    00381
    00382     //
    00383     // restore stuff and exit
    00384     //
    00385
    00386     KdPortRestore();
    00387     if (KdpPortLocked) {
    00388         KdpPortUnlock();
    00389     }
    00390
    00391     KeThawExecution(Enable);
    00392
    00393     //
    00394     // Do some crude timer support.  If KdEnterDebugger didn't
    00395     // Query the performance counter, then don't do it here either.
    00396     //
    00397
    00398     if (KdTimerStop.QuadPart == 0) {
    00399         KdTimerStart = KdTimerStop;
    00400     } else {
    00401         KdTimerStart = KeQueryPerformanceCounter(NULL);
    00402     }
    00403
    00404     //
    00405     // Process a time slip
    00406     //
    00407
    00408     if (!PoHiberInProgress) {
    00409
    00410         Pending = InterlockedIncrement(&KdpTimeSlipPending);
    00411
    00412         //
    00413         // If there's wasn't a time slip pending, queue the DPC to handle it
    00414         //
    00415
    00416         if (Pending == 1) {
    00417             InterlockedIncrement(&KdpTimeSlipPending);
    00418             KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL);
    00419         }
    00420     }
    00421
    00422     return;
    00423 }
    00424
    00425
    00426 VOID
    00427 KdUpdateTimeSlipEvent(
    00428     PVOID Event
    00429     )
    00430
    00431 /*++
    00432
    00433 Routine Description:
    00434
    00435     Update the reference to an event object which will be signalled when
    00436     the debugger has caused the system clock to skew.
    00437
    00438 Arguments:
    00439
    00440     Event - Supplies a pointer to an event object
    00441
    00442 Return Value:
    00443
    00444     None
    00445
    00446 --*/
    00447
    00448 {
    00449     KIRQL OldIrql;
    00450
    00451     KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
    00452
    00453     //
    00454     // Dereference the old event and forget about it.
    00455     // Remember the new event if there is one.
    00456     //
    00457
    00458     if (KdpTimeSlipEvent != NULL) {
    00459         ObDereferenceObject(KdpTimeSlipEvent);
    00460     }
    00461
    00462     KdpTimeSlipEvent = Event;
    00463
    00464     KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
    00465 }
    00466
    00467 VOID
    00468 KdpTimeSlipDpcRoutine (
    00469     PKDPC Dpc,
    00470     PVOID DeferredContext,
    00471     PVOID SystemArgument1,
    00472     PVOID SystemArgument2
    00473     )
    00474 {
    00475     LONG OldCount, NewCount, j;
    00476
    00477     //
    00478     // Reset pending count.  If the current count is 1, then clear
    00479     // the pending count.  if the current count is greater then 1,
    00480     // then set to one and update the time now.
    00481     //
    00482
    00483     j = KdpTimeSlipPending;
    00484     do {
    00485         OldCount = j;
    00486         NewCount = OldCount > 1 ? 1 : 0;
    00487
    00488         j = InterlockedCompareExchange(&KdpTimeSlipPending, NewCount, OldCount);
    00489
    00490     } while (j != OldCount);
    00491
    00492     //
    00493     // If new count is non-zero, then process a time slip now
    00494     //
    00495
    00496     if (NewCount) {
    00497         ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
    00498     }
    00499 }
    00500
    00501 VOID
    00502 KdpTimeSlipWork (
    00503     IN PVOID Context
    00504     )
    00505 {
    00506     KIRQL               OldIrql;
    00507     LARGE_INTEGER       DueTime;
    00508
    00509     //
    00510     // Update time from the real time clock
    00511     //
    00512
    00513     ExAcquireTimeRefreshLock();
    00514     ExUpdateSystemTimeFromCmos (FALSE, 0);
    00515     ExReleaseTimeRefreshLock();
    00516
    00517     //
    00518     // If there's a time service installed, signal it's time slip event
    00519     //
    00520
    00521     KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
    00522     if (KdpTimeSlipEvent) {
    00523         KeSetEvent (KdpTimeSlipEvent, 0, FALSE);
    00524     }
    00525     KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
    00526
    00527     //
    00528     // Insert a forced delay between time slip operations
    00529     //
    00530
    00531     DueTime.QuadPart = -1800000000;
    00532     KeSetTimer (&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
    00533 }
    00534
    00535 #if i386
    00536 VOID
    00537 InternalBreakpointCheck (
    00538     PKDPC Dpc,
    00539     PVOID DeferredContext,
    00540     PVOID SystemArgument1,
    00541     PVOID SystemArgument2
    00542     )
    00543 {
    00544     LARGE_INTEGER dueTime;
    00545     ULONG i;
    00546
    00547     UNREFERENCED_PARAMETER(Dpc);
    00548     UNREFERENCED_PARAMETER(DeferredContext);
    00549     UNREFERENCED_PARAMETER(SystemArgument1);
    00550     UNREFERENCED_PARAMETER(SystemArgument2);
    00551
    00552     dueTime.LowPart = (ULONG)(-1 * 10 * 1000 * 1000);
    00553     dueTime.HighPart = -1;
    00554
    00555     KeSetTimer(
    00556         &InternalBreakpointTimer,
    00557         dueTime,
    00558         &InternalBreakpointCheckDpc
    00559         );
    00560
    00561     for ( i = 0 ; i < KdpNumInternalBreakpoints; i++ ) {
    00562         if ( !(KdpInternalBPs[i].Flags & DBGKD_INTERNAL_BP_FLAG_INVALID) &&
    00563              (KdpInternalBPs[i].Flags & DBGKD_INTERNAL_BP_FLAG_COUNTONLY) ) {
    00564
    00565             PDBGKD_INTERNAL_BREAKPOINT b = KdpInternalBPs + i;
    00566             ULONG callsThisPeriod;
    00567
    00568             callsThisPeriod = b->Calls - b->CallsLastCheck;
    00569             if ( callsThisPeriod > b->MaxCallsPerPeriod ) {
    00570                 b->MaxCallsPerPeriod = callsThisPeriod;
    00571             }
    00572             b->CallsLastCheck = b->Calls;
    00573         }
    00574     }
    00575
    00576     return;
    00577
    00578 } // InternalBreakpointCheck
    00579
    00580
    00581 VOID
    00582 KdSetInternalBreakpoint (
    00583     IN PDBGKD_MANIPULATE_STATE64 m
    00584     )
    00585
    00586 /*++
    00587
    00588 Routine Description:
    00589
    00590     This function sets an internal breakpoint.  "Internal breakpoint"
    00591     means one in which control is not returned to the kernel debugger at
    00592     all, but rather just update internal counting routines and resume.
    00593
    00594 Arguments:
    00595
    00596     m - Supplies the state manipulation message.
    00597
    00598 Return Value:
    00599
    00600     None.
    00601 --*/
    00602
    00603 {
    00604     ULONG i;
    00605     PDBGKD_INTERNAL_BREAKPOINT bp = NULL;
    00606     ULONG savedFlags;
    00607
    00608     for ( i = 0 ; i < KdpNumInternalBreakpoints; i++ ) {
    00609         if ( KdpInternalBPs[i].Addr ==
    00610                             m->u.SetInternalBreakpoint.BreakpointAddress ) {
    00611             bp = &KdpInternalBPs[i];
    00612             break;
    00613         }
    00614     }
    00615
    00616     if ( !bp ) {
    00617         for ( i = 0; i < KdpNumInternalBreakpoints; i++ ) {
    00618             if ( KdpInternalBPs[i].Flags & DBGKD_INTERNAL_BP_FLAG_INVALID ) {
    00619                 bp = &KdpInternalBPs[i];
    00620                 break;
    00621             }
    00622         }
    00623     }
    00624
    00625     if ( !bp ) {
    00626         if ( KdpNumInternalBreakpoints >= DBGKD_MAX_INTERNAL_BREAKPOINTS ) {
    00627             return; // no space.  Probably should report error.
    00628         }
    00629         bp = &KdpInternalBPs[KdpNumInternalBreakpoints++];
    00630         bp->Flags |= DBGKD_INTERNAL_BP_FLAG_INVALID; // force initialization
    00631     }
    00632
    00633     if ( bp->Flags & DBGKD_INTERNAL_BP_FLAG_INVALID ) {
    00634         if ( m->u.SetInternalBreakpoint.Flags &
    00635                                         DBGKD_INTERNAL_BP_FLAG_INVALID ) {
    00636             return; // tried clearing a non-existant BP.  Ignore the request
    00637         }
    00638         bp->Calls = bp->MaxInstructions = bp->TotalInstructions = 0;
    00639         bp->CallsLastCheck = bp->MaxCallsPerPeriod = 0;
    00640         bp->MinInstructions = 0xffffffff;
    00641         bp->Handle = 0;
    00642         bp->Thread = 0;
    00643     }
    00644
    00645     savedFlags = bp->Flags;
    00646     bp->Flags = m->u.SetInternalBreakpoint.Flags; // this could possibly invalidate the BP
    00647     bp->Addr = m->u.SetInternalBreakpoint.BreakpointAddress;
    00648
    00649     if ( bp->Flags & (DBGKD_INTERNAL_BP_FLAG_INVALID |
    00650                       DBGKD_INTERNAL_BP_FLAG_SUSPENDED) ) {
    00651
    00652         if ( (bp->Flags & DBGKD_INTERNAL_BP_FLAG_INVALID) &&
    00653              (bp->Thread != 0) ) {
    00654             // The breakpoint is active; defer its deletion
    00655             bp->Flags &= ~DBGKD_INTERNAL_BP_FLAG_INVALID;
    00656             bp->Flags |= DBGKD_INTERNAL_BP_FLAG_DYING;
    00657         }
    00658
    00659         // This is really a CLEAR bp request.
    00660
    00661         if ( bp->Handle != 0 ) {
    00662             KdpDeleteBreakpoint( bp->Handle );
    00663         }
    00664         bp->Handle = 0;
    00665
    00666         return;
    00667     }
    00668
    00669     // now set the real breakpoint and remember its handle.
    00670
    00671     if ( savedFlags & (DBGKD_INTERNAL_BP_FLAG_INVALID |
    00672                        DBGKD_INTERNAL_BP_FLAG_SUSPENDED) ) {
    00673         // breakpoint was invalid; activate it now
    00674         bp->Handle = KdpAddBreakpoint( (PVOID)bp->Addr );
    00675     }
    00676
    00677     if ( BreakpointsSuspended ) {
    00678         KdpSuspendBreakpoint( bp->Handle );
    00679     }
    00680
    00681 } // KdSetInternalBreakpoint
    00682
    00683 NTSTATUS
    00684 KdGetTraceInformation(
    00685     PVOID SystemInformation,
    00686     ULONG SystemInformationLength,
    00687     PULONG ReturnLength
    00688     )
    00689
    00690 /*++
    00691
    00692 Routine Description:
    00693
    00694     This function gets data about an internal breakpoint and returns it
    00695     in a buffer provided for it.  It is designed to be called from
    00696     NTQuerySystemInformation.  It is morally equivalent to GetInternalBP
    00697     except that it communicates locally, and returns all the breakpoints
    00698     at once.
    00699
    00700 Arguments:
    00701
    00702     SystemInforamtion - the buffer into which to write the result.
    00703     SystemInformationLength - the maximum length to write
    00704     RetrunLength - How much data was really written
    00705
    00706 Return Value:
    00707
    00708     None.
    00709
    00710 --*/
    00711
    00712 {
    00713     ULONG numEntries = 0;
    00714     ULONG i = 0;
    00715     PDBGKD_GET_INTERNAL_BREAKPOINT64 outPtr;
    00716
    00717     for ( i = 0; i < KdpNumInternalBreakpoints; i++ ) {
    00718         if ( !(KdpInternalBPs[i].Flags & DBGKD_INTERNAL_BP_FLAG_INVALID) ) {
    00719             numEntries++;
    00720         }
    00721     }
    00722
    00723     *ReturnLength = numEntries * sizeof(DBGKD_GET_INTERNAL_BREAKPOINT64);
    00724     if ( *ReturnLength > SystemInformationLength ) {
    00725         return STATUS_INFO_LENGTH_MISMATCH;
    00726     }
    00727
    00728     //
    00729     // We've got enough space.  Copy it in.
    00730     //
    00731
    00732     outPtr = (PDBGKD_GET_INTERNAL_BREAKPOINT64)SystemInformation;
    00733     for ( i = 0; i < KdpNumInternalBreakpoints; i++ ) {
    00734         if ( !(KdpInternalBPs[i].Flags & DBGKD_INTERNAL_BP_FLAG_INVALID) ) {
    00735             outPtr->BreakpointAddress = KdpInternalBPs[i].Addr;
    00736             outPtr->Flags = KdpInternalBPs[i].Flags;
    00737             outPtr->Calls = KdpInternalBPs[i].Calls;
    00738             outPtr->MaxCallsPerPeriod = KdpInternalBPs[i].MaxCallsPerPeriod;
    00739             outPtr->MinInstructions = KdpInternalBPs[i].MinInstructions;
    00740             outPtr->MaxInstructions = KdpInternalBPs[i].MaxInstructions;
    00741             outPtr->TotalInstructions = KdpInternalBPs[i].TotalInstructions;
    00742             outPtr++;
    00743         }
    00744     }
    00745
    00746     return STATUS_SUCCESS;
    00747
    00748 } // KdGetTraceInformation
    00749
    00750 VOID
    00751 KdGetInternalBreakpoint(
    00752     IN PDBGKD_MANIPULATE_STATE64 m
    00753     )
    00754
    00755 /*++
    00756
    00757 Routine Description:
    00758
    00759     This function gets data about an internal breakpoint and returns it
    00760     to the calling debugger.
    00761
    00762 Arguments:
    00763
    00764     m - Supplies the state manipulation message.
    00765
    00766 Return Value:
    00767
    00768     None.
    00769
    00770 --*/
    00771
    00772 {
    00773     ULONG i;
    00774     PDBGKD_INTERNAL_BREAKPOINT bp = NULL;
    00775     STRING messageHeader;
    00776
    00777     messageHeader.Length = sizeof(*m);
    00778     messageHeader.Buffer = (PCHAR)m;
    00779
    00780     for ( i = 0; i < KdpNumInternalBreakpoints; i++ ) {
    00781         if ( !(KdpInternalBPs[i].Flags & (DBGKD_INTERNAL_BP_FLAG_INVALID |
    00782                                           DBGKD_INTERNAL_BP_FLAG_SUSPENDED)) &&
    00783              (KdpInternalBPs[i].Addr ==
    00784                         m->u.GetInternalBreakpoint.BreakpointAddress) ) {
    00785             bp = &KdpInternalBPs[i];
    00786             break;
    00787         }
    00788     }
    00789
    00790     if ( !bp ) {
    00791         m->u.GetInternalBreakpoint.Flags = DBGKD_INTERNAL_BP_FLAG_INVALID;
    00792         m->u.GetInternalBreakpoint.Calls = 0;
    00793         m->u.GetInternalBreakpoint.MaxCallsPerPeriod = 0;
    00794         m->u.GetInternalBreakpoint.MinInstructions = 0;
    00795         m->u.GetInternalBreakpoint.MaxInstructions = 0;
    00796         m->u.GetInternalBreakpoint.TotalInstructions = 0;
    00797         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    00798     } else {
    00799         m->u.GetInternalBreakpoint.Flags = bp->Flags;
    00800         m->u.GetInternalBreakpoint.Calls = bp->Calls;
    00801         m->u.GetInternalBreakpoint.MaxCallsPerPeriod = bp->MaxCallsPerPeriod;
    00802         m->u.GetInternalBreakpoint.MinInstructions = bp->MinInstructions;
    00803         m->u.GetInternalBreakpoint.MaxInstructions = bp->MaxInstructions;
    00804         m->u.GetInternalBreakpoint.TotalInstructions = bp->TotalInstructions;
    00805         m->ReturnStatus = STATUS_SUCCESS;
    00806     }
    00807
    00808     m->ApiNumber = DbgKdGetInternalBreakPointApi;
    00809
    00810     KdpSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
    00811                     &messageHeader,
    00812                     NULL
    00813                     );
    00814
    00815     return;
    00816
    00817 } // KdGetInternalBreakpoint
    00818 #endif // i386
    00819
    00820 KCONTINUE_STATUS
    00821 KdpSendWaitContinue (
    00822     IN ULONG OutPacketType,
    00823     IN PSTRING OutMessageHeader,
    00824     IN PSTRING OutMessageData OPTIONAL,
    00825     IN OUT PCONTEXT ContextRecord
    00826     )
    00827
    00828 /*++
    00829
    00830 Routine Description:
    00831
    00832     This function sends a packet, and then waits for a continue message.
    00833     BreakIns received while waiting will always cause a resend of the
    00834     packet originally sent out.  While waiting, manipulate messages
    00835     will be serviced.
    00836
    00837     A resend always resends the original event sent to the debugger,
    00838     not the last response to some debugger command.
    00839
    00840 Arguments:
    00841
    00842     OutPacketType - Supplies the type of packet to send.
    00843
    00844     OutMessageHeader - Supplies a pointer to a string descriptor that describes
    00845         the message information.
    00846
    00847     OutMessageData - Supplies a pointer to a string descriptor that describes
    00848         the optional message data.
    00849
    00850     ContextRecord - Exception context
    00851
    00852 Return Value:
    00853
    00854     A value of TRUE is returned if the continue message indicates
    00855     success, Otherwise, a value of FALSE is returned.
    00856
    00857 --*/
    00858
    00859 {
    00860
    00861     ULONG Length;
    00862     STRING MessageData;
    00863     STRING MessageHeader;
    00864     DBGKD_MANIPULATE_STATE64 ManipulateState;
    00865     ULONG ReturnCode;
    00866     NTSTATUS Status;
    00867     KCONTINUE_STATUS ContinueStatus;
    00868
    00869     //
    00870     // Loop servicing state manipulation message until a continue message
    00871     // is received.
    00872     //
    00873
    00874     MessageHeader.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
    00875     MessageHeader.Buffer = (PCHAR)&ManipulateState;
    00876     MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE;
    00877     MessageData.Buffer = (PCHAR)KdpMessageBuffer;
    00878
    00879 ResendPacket:
    00880
    00881     //
    00882     // Send event notification packet to debugger on host.  Come back
    00883     // here any time we see a breakin sequence.
    00884     //
    00885
    00886     KdpSendPacket(
    00887                   OutPacketType,
    00888                   OutMessageHeader,
    00889                   OutMessageData
    00890                   );
    00891
    00892     //
    00893     // After sending packet, if there is no response from debugger
    00894     // AND the packet is for reporting symbol (un)load, the debugger
    00895     // will be declared to be not present.  Note If the packet is for
    00896     // reporting exception, the KdpSendPacket will never stop.
    00897     //
    00898
    00899     if (KdDebuggerNotPresent) {
    00900         return ContinueSuccess;
    00901     }
    00902
    00903     while (TRUE) {
    00904
    00905         //
    00906         // Wait for State Manipulate Packet without timeout.
    00907         //
    00908
    00909         do {
    00910
    00911             ReturnCode = KdpReceivePacket(
    00912                             PACKET_TYPE_KD_STATE_MANIPULATE,
    00913                             &MessageHeader,
    00914                             &MessageData,
    00915                             &Length
    00916                             );
    00917             if (ReturnCode == (USHORT)KDP_PACKET_RESEND) {
    00918                 goto ResendPacket;
    00919             }
    00920         } while (ReturnCode == KDP_PACKET_TIMEOUT);
    00921
    00922         //
    00923         // Switch on the return message API number.
    00924         //
    00925
    00926         switch (ManipulateState.ApiNumber) {
    00927
    00928         case DbgKdReadVirtualMemoryApi:
    00929             KdpReadVirtualMemory(&ManipulateState,&MessageData,ContextRecord);
    00930             break;
    00931 #if 0
    00932         case DbgKdReadVirtualMemory64Api:
    00933             KdpReadVirtualMemory64(&ManipulateState,&MessageData,ContextRecord);
    00934             break;
    00935 #endif
    00936         case DbgKdWriteVirtualMemoryApi:
    00937             KdpWriteVirtualMemory(&ManipulateState,&MessageData,ContextRecord);
    00938             break;
    00939 #if 0
    00940         case DbgKdWriteVirtualMemory64Api:
    00941             KdpWriteVirtualMemory64(&ManipulateState,&MessageData,ContextRecord);
    00942             break;
    00943 #endif
    00944
    00945         case DbgKdCheckLowMemoryApi:
    00946             KdpCheckLowMemory (&ManipulateState);
    00947             break;
    00948
    00949         case DbgKdReadPhysicalMemoryApi:
    00950             KdpReadPhysicalMemory(&ManipulateState,&MessageData,ContextRecord);
    00951             break;
    00952
    00953         case DbgKdWritePhysicalMemoryApi:
    00954             KdpWritePhysicalMemory(&ManipulateState,&MessageData,ContextRecord);
    00955             break;
    00956
    00957         case DbgKdGetContextApi:
    00958             KdpGetContext(&ManipulateState,&MessageData,ContextRecord);
    00959             break;
    00960
    00961         case DbgKdSetContextApi:
    00962             KdpSetContext(&ManipulateState,&MessageData,ContextRecord);
    00963             break;
    00964
    00965         case DbgKdWriteBreakPointApi:
    00966             KdpWriteBreakpoint(&ManipulateState,&MessageData,ContextRecord);
    00967             break;
    00968
    00969         case DbgKdRestoreBreakPointApi:
    00970             KdpRestoreBreakpoint(&ManipulateState,&MessageData,ContextRecord);
    00971             break;
    00972
    00973         case DbgKdReadControlSpaceApi:
    00974             KdpReadControlSpace(&ManipulateState,&MessageData,ContextRecord);
    00975             break;
    00976
    00977         case DbgKdWriteControlSpaceApi:
    00978             KdpWriteControlSpace(&ManipulateState,&MessageData,ContextRecord);
    00979             break;
    00980
    00981         case DbgKdReadIoSpaceApi:
    00982             KdpReadIoSpace(&ManipulateState,&MessageData,ContextRecord);
    00983             break;
    00984
    00985         case DbgKdWriteIoSpaceApi:
    00986             KdpWriteIoSpace(&ManipulateState,&MessageData,ContextRecord);
    00987             break;
    00988
    00989 #ifdef _ALPHA_
    00990
    00991         case DbgKdReadIoSpaceExtendedApi:
    00992             KdpReadIoSpaceExtended(&ManipulateState,&MessageData,ContextRecord);
    00993             break;
    00994
    00995         case DbgKdWriteIoSpaceExtendedApi:
    00996             KdpWriteIoSpaceExtended(&ManipulateState,&MessageData,ContextRecord);
    00997             break;
    00998
    00999         case DbgKdGetBusDataApi:
    01000             KdpGetBusData(&ManipulateState,&MessageData,ContextRecord);
    01001             break;
    01002
    01003         case DbgKdSetBusDataApi:
    01004             KdpSetBusData(&ManipulateState,&MessageData,ContextRecord);
    01005             break;
    01006
    01007 #endif // _ALPHA_
    01008
    01009         case DbgKdContinueApi:
    01010             if (NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus) != FALSE) {
    01011                 return ContinueSuccess;
    01012             } else {
    01013                 return ContinueError;
    01014             }
    01015             break;
    01016
    01017         case DbgKdContinueApi2:
    01018             if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus) != FALSE) {
    01019                 KdpGetStateChange(&ManipulateState,ContextRecord);
    01020                 return ContinueSuccess;
    01021             } else {
    01022                 return ContinueError;
    01023             }
    01024             break;
    01025
    01026         case DbgKdRebootApi:
    01027             KdpReboot();
    01028             break;
    01029
    01030 #if i386
    01031         case DbgKdReadMachineSpecificRegister:
    01032             KdpReadMachineSpecificRegister(&ManipulateState,&MessageData,ContextRecord);
    01033             break;
    01034
    01035         case DbgKdWriteMachineSpecificRegister:
    01036             KdpWriteMachineSpecificRegister(&ManipulateState,&MessageData,ContextRecord);
    01037             break;
    01038
    01039         case DbgKdSetSpecialCallApi:
    01040             KdSetSpecialCall(&ManipulateState,ContextRecord);
    01041             break;
    01042
    01043         case DbgKdClearSpecialCallsApi:
    01044             KdClearSpecialCalls();
    01045             break;
    01046
    01047         case DbgKdSetInternalBreakPointApi:
    01048             KdSetInternalBreakpoint(&ManipulateState);
    01049             break;
    01050
    01051         case DbgKdGetInternalBreakPointApi:
    01052             KdGetInternalBreakpoint(&ManipulateState);
    01053             break;
    01054 #endif
    01055
    01056         case DbgKdGetVersionApi:
    01057             KdpGetVersion(&ManipulateState);
    01058             break;
    01059
    01060         case DbgKdCauseBugCheckApi:
    01061             KdpCauseBugCheck(&ManipulateState);
    01062             break;
    01063
    01064         case DbgKdPageInApi:
    01065             KdpNotSupported(&ManipulateState);
    01066             break;
    01067
    01068         case DbgKdWriteBreakPointExApi:
    01069             Status = KdpWriteBreakPointEx(&ManipulateState,
    01070                                           &MessageData,
    01071                                           ContextRecord);
    01072             if (Status) {
    01073                 ManipulateState.ApiNumber = DbgKdContinueApi;
    01074                 ManipulateState.u.Continue.ContinueStatus = Status;
    01075                 return ContinueError;
    01076             }
    01077             break;
    01078
    01079         case DbgKdRestoreBreakPointExApi:
    01080             KdpRestoreBreakPointEx(&ManipulateState,&MessageData,ContextRecord);
    01081             break;
    01082
    01083         case DbgKdSwitchProcessor:
    01084             KdPortRestore ();
    01085             ContinueStatus = KeSwitchFrozenProcessor(ManipulateState.Processor);
    01086             KdPortSave ();
    01087             return ContinueStatus;
    01088
    01089         case DbgKdSearchMemoryApi:
    01090             KdpSearchMemory(&ManipulateState, &MessageData, ContextRecord);
    01091             break;
    01092
    01093             //
    01094             // Invalid message.
    01095             //
    01096
    01097         default:
    01098             MessageData.Length = 0;
    01099             ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
    01100             KdpSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, &MessageData);
    01101             break;
    01102         }
    01103
    01104 #ifdef _ALPHA_
    01105
    01106         //
    01107         //jnfix
    01108         // this is embarrasing, we have an icache coherency problem that
    01109         // the following imb fixes, later we must track this down to the
    01110         // exact offending API but for now this statement allows the stub
    01111         // work to appropriately for Alpha.
    01112         //
    01113
    01114 #if defined(_MSC_VER)
    01115         __PAL_IMB();
    01116 #else
    01117         asm( "call_pal 0x86" );   // x86 = imb
    01118 #endif
    01119
    01120 #endif
    01121
    01122     }
    01123 }
    01124
    01125 VOID
    01126 KdpReadVirtualMemory(
    01127     IN PDBGKD_MANIPULATE_STATE64 m,
    01128     IN PSTRING AdditionalData,
    01129     IN PCONTEXT Context
    01130     )
    01131
    01132 /*++
    01133
    01134 Routine Description:
    01135
    01136     This function is called in response to a read virtual memory 32-bit
    01137     state manipulation message. Its function is to read virtual memory
    01138     and return.
    01139
    01140 Arguments:
    01141
    01142     m - Supplies a pointer to the state manipulation message.
    01143
    01144     AdditionalData - Supplies a pointer to a descriptor for the data to read.
    01145
    01146     Context - Supplies a pointer to the current context.
    01147
    01148 Return Value:
    01149
    01150     None.
    01151
    01152 --*/
    01153
    01154 {
    01155     ULONG Length;
    01156     STRING MessageHeader;
    01157 #if defined(_ALPHA_) && !defined(_AXP64_)
    01158     UCHAR * POINTER_64 Address;
    01159     PUCHAR Destination;
    01160     UCHAR * POINTER_64 Source;
    01161     PUCHAR Source32;
    01162 #endif
    01163
    01164     //
    01165     // Trim the transfer count to fit in a single message.
    01166     //
    01167
    01168     Length = m->u.ReadMemory.TransferCount;
    01169     if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) {
    01170         Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
    01171     }
    01172
    01173     //
    01174     // Move the data to the destination buffer.
    01175     //
    01176
    01177 #if defined(_ALPHA_) && !defined(_AXP64_)
    01178
    01179     AdditionalData->Length = (USHORT)Length;
    01180
    01181     Destination = AdditionalData->Buffer;
    01182     Source = (UCHAR * POINTER_64)m->u.ReadMemory.TargetBaseAddress;
    01183     Source32 = (PUCHAR)m->u.ReadMemory.TargetBaseAddress;
    01184     while (Length > 0) {
    01185         if ((LONGLONG)Source != (LONGLONG)((LONG)Source)) {
    01186             if ((Address = MmDbgReadCheck64(Source)) == NULL64) {
    01187                 break;
    01188             }
    01189         } else {
    01190             if ((Address = MmDbgReadCheck(Source32)) == NULL64) {
    01191                 break;
    01192             }
    01193         }
    01194
    01195         *Destination++ = *Address;
    01196         Source   += 1;
    01197         Source32 += 1;
    01198         Length -= 1;
    01199     }
    01200
    01201     //
    01202     // If all the data is read, then return a success status. Otherwise,
    01203     // return an unsuccessful status.
    01204     //
    01205
    01206     m->ReturnStatus = STATUS_SUCCESS;
    01207     if (Length != 0) {
    01208         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    01209     }
    01210
    01211     //
    01212     // Set the actual number of bytes read, initialize the message header,
    01213     // and send the reply packet to the host debugger.
    01214     //
    01215
    01216     m->u.ReadMemory.ActualBytesRead = AdditionalData->Length - Length;
    01217 #else
    01218     AdditionalData->Length = (USHORT)KdpMoveMemory(AdditionalData->Buffer,
    01219                                                    (PVOID)m->u.ReadMemory.TargetBaseAddress,
    01220                                                    Length);
    01221
    01222     //
    01223     // If all the data is read, then return a success status. Otherwise,
    01224     // return an unsuccessful status.
    01225     //
    01226
    01227     m->ReturnStatus = STATUS_SUCCESS;
    01228     if (Length != AdditionalData->Length) {
    01229         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    01230     }
    01231
    01232     //
    01233     // Set the actual number of bytes read, initialize the message header,
    01234     // and send the reply packet to the host debugger.
    01235     //
    01236
    01237     m->u.ReadMemory.ActualBytesRead = AdditionalData->Length;
    01238 #endif
    01239
    01240     MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
    01241     MessageHeader.Buffer = (PCHAR)m;
    01242     KdpSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
    01243                   &MessageHeader,
    01244                   AdditionalData);
    01245
    01246     return;
    01247 }
    01248
    01249 #if 0
    01250 VOID
    01251 KdpReadVirtualMemory64(
    01252     IN PDBGKD_MANIPULATE_STATE64 m,
    01253     IN PSTRING AdditionalData,
    01254     IN PCONTEXT Context
    01255     )
    01256
    01257 /*++
    01258
    01259 Routine Description:
    01260
    01261     This function is called in response of a read virtual memory 64-bit
    01262     state manipulation message. Its function is to read virtual memory
    01263     and return.
    01264
    01265 Arguments:
    01266
    01267     m - Supplies a pointer to a state manipulation message.
    01268
    01269     AdditionalData - Supplies a pointer to descriptor for the data to read.
    01270
    01271     Context - Supplies a pointer to the current context.
    01272
    01273 Return Value:
    01274
    01275     None.
    01276
    01277 --*/
    01278
    01279 {
    01280
    01281     UCHAR * POINTER_64 Address;
    01282     PUCHAR Destination;
    01283     ULONG Length;
    01284     STRING MessageHeader;
    01285     UCHAR * POINTER_64 Source;
    01286
    01287     //
    01288     // Trim the transfer count to fit in a single message.
    01289     //
    01290
    01291     Length = m->u.ReadMemory64.TransferCount;
    01292     if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) {
    01293         Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
    01294     }
    01295
    01296     //
    01297     // Move the data to the destination buffer.
    01298     //
    01299
    01300     AdditionalData->Length = (USHORT)Length;
    01301
    01302 #if defined(_MIPS_) || defined(_ALPHA_)
    01303
    01304     Destination = AdditionalData->Buffer;
    01305     Source = (UCHAR * POINTER_64)m->u.ReadMemory64.TargetBaseAddress;
    01306     while (Length > 0) {
    01307         if ((Address = MmDbgReadCheck64(Source)) == NULL64) {
    01308             break;
    01309         }
    01310
    01311         *Destination++ = *Address;
    01312         Source += 1;
    01313         Length -= 1;
    01314     }
    01315
    01316 #endif
    01317
    01318     //
    01319     // If all the data is read, then return a success status. Otherwise,
    01320     // return an unsuccessful status.
    01321     //
    01322
    01323     m->ReturnStatus = STATUS_SUCCESS;
    01324     if (Length != 0) {
    01325         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    01326     }
    01327
    01328     //
    01329     // Set the actual number of bytes read, initialize the message header,
    01330     // and send the reply packet to the host debugger.
    01331     //
    01332
    01333     m->u.ReadMemory64.ActualBytesRead = AdditionalData->Length - Length;
    01334     MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
    01335     MessageHeader.Buffer = (PCHAR)m;
    01336     KdpSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
    01337                   &MessageHeader,
    01338                   AdditionalData);
    01339
    01340     return;
    01341 }
    01342 #endif
    01343
    01344 VOID
    01345 KdpWriteVirtualMemory(
    01346     IN PDBGKD_MANIPULATE_STATE64 m,
    01347     IN PSTRING AdditionalData,
    01348     IN PCONTEXT Context
    01349     )
    01350
    01351 /*++
    01352
    01353 Routine Description:
    01354
    01355     This function is called in response of a write virtual memory 32-bit
    01356     state manipulation message. Its function is to write virtual memory
    01357     and return.
    01358
    01359 Arguments:
    01360
    01361     m - Supplies a pointer to the state manipulation message.
    01362
    01363     AdditionalData - Supplies a pointer to a descriptor for the data to write.
    01364
    01365     Context - Supplies a pointer to the current context.
    01366
    01367 Return Value:
    01368
    01369     None.
    01370
    01371 --*/
    01372
    01373 {
    01374
    01375     ULONG Length;
    01376     STRING MessageHeader;
    01377     HARDWARE_PTE Opaque;
    01378
    01379 #if defined(_ALPHA_) && !defined(_AXP64_)
    01380     UCHAR * POINTER_64 Address;
    01381     UCHAR * POINTER_64 Destination;
    01382     PUCHAR Address32;
    01383     PUCHAR Source;
    01384     PUCHAR Destination32;
    01385
    01386
    01387     //
    01388     // Move the data to the destination buffer.
    01389     //
    01390
    01391     Length = AdditionalData->Length;
    01392
    01393     Destination = (UCHAR * POINTER_64)m->u.WriteMemory.TargetBaseAddress;
    01394     Destination32 = (PUCHAR)m->u.WriteMemory.TargetBaseAddress;
    01395     Source = AdditionalData->Buffer;
    01396     while (Length > 0) {
    01397         Address=Destination;
    01398         Address32 = NULL;
    01399         if ((LONGLONG)Destination != (LONGLONG)((LONG)Destination)) {
    01400             if ((Address = MmDbgWriteCheck64(Destination)) == NULL64) {
    01401                 break;
    01402             }
    01403         } else {
    01404             if ((Address32 = MmDbgWriteCheck(Destination32, &Opaque)) == NULL) {
    01405                 break;
    01406             }
    01407         }
    01408
    01409         if (Address32 != NULL) {
    01410             *Address32 = *Source++;
    01411             MmDbgReleaseAddress(Address32, &Opaque);
    01412         }
    01413         else {
    01414             *Address = *Source++;
    01415         }
    01416         Destination   += 1;
    01417         Destination32 += 1;
    01418         Length -= 1;
    01419     }
    01420
    01421     //
    01422     // If all the data is written, then return a success status. Otherwise,
    01423     // return an unsuccessful status.
    01424     //
    01425
    01426     m->ReturnStatus = STATUS_SUCCESS;
    01427     if (Length != 0) {
    01428         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    01429     }
    01430
    01431     //
    01432     // Set the actual number of bytes written, initialize the message header,
    01433     // and send the reply packet to the host debugger.
    01434     //
    01435
    01436     m->u.WriteMemory.ActualBytesWritten = AdditionalData->Length - Length;
    01437     MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
    01438     MessageHeader.Buffer = (PCHAR)m;
    01439     KdpSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
    01440                   &MessageHeader,
    01441                   NULL);
    01442
    01443     return;
    01444 #else
    01445
    01446     //
    01447     // Move the data to the destination buffer.
    01448     //
    01449
    01450     Length = KdpMoveMemory((PVOID)m->u.WriteMemory.TargetBaseAddress,
    01451                            AdditionalData->Buffer,
    01452                            AdditionalData->Length);
    01453
    01454     //
    01455     // If all the data is written, then return a success status. Otherwise,
    01456     // return an unsuccessful status.
    01457     //
    01458
    01459     m->ReturnStatus = STATUS_SUCCESS;
    01460     if (Length != AdditionalData->Length) {
    01461         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    01462     }
    01463
    01464     //
    01465     // Set the actual number of bytes written, initialize the message header,
    01466     // and send the reply packet to the host debugger.
    01467     //
    01468
    01469     m->u.WriteMemory.ActualBytesWritten = Length;
    01470     MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
    01471     MessageHeader.Buffer = (PCHAR)m;
    01472     KdpSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
    01473                   &MessageHeader,
    01474                   NULL);
    01475
    01476     return;
    01477 #endif
    01478 }
    01479
    01480 #if 0
    01481 VOID
    01482 KdpWriteVirtualMemory64(
    01483     IN PDBGKD_MANIPULATE_STATE64 m,
    01484     IN PSTRING AdditionalData,
    01485     IN PCONTEXT Context
    01486     )
    01487
    01488 /*++
    01489
    01490 Routine Description:
    01491
    01492     This function is called in response of a write virtual memory 64-bit
    01493     state manipulation message. Its function is to write virtual memory
    01494     and return.
    01495
    01496 Arguments:
    01497
    01498     m - Supplies a pointer to the state manipulation message.
    01499
    01500     AdditionalData - Supplies a pointer to a descriptor for the data to write.
    01501
    01502     Context - Supplies a pointer to the current context.
    01503
    01504 Return Value:
    01505
    01506     None.
    01507
    01508 --*/
    01509
    01510 {
    01511
    01512     UCHAR * POINTER_64 Address;
    01513     UCHAR * POINTER_64 Destination;
    01514     ULONG Length;
    01515     STRING MessageHeader;
    01516     PUCHAR Source;
    01517     ULONG_PTR Opaque;
    01518
    01519     //
    01520     // Move the data to the destination buffer.
    01521     //
    01522
    01523     Length = AdditionalData->Length;
    01524
    01525 #if defined(_MIPS_) || defined(_ALPHA_)
    01526
    01527     Destination = (UCHAR * POINTER_64)m->u.WriteMemory64.TargetBaseAddress;
    01528     Source = AdditionalData->Buffer;
    01529     while (Length > 0) {
    01530         if ((Address = MmDbgWriteCheck64(Destination, &Opaque)) == NULL64) {
    01531             break;
    01532         }
    01533
    01534         *Address = *Source++;
    01535         Destination += 1;
    01536         Length -= 1;
    01537     }
    01538
    01539 #endif
    01540
    01541     //
    01542     // If all the data is written, then return a success status. Otherwise,
    01543     // return an unsuccessful status.
    01544     //
    01545
    01546     m->ReturnStatus = STATUS_SUCCESS;
    01547     if (Length != 0) {
    01548         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    01549     }
    01550
    01551     //
    01552     // Set the actual number of bytes written, initialize the message header,
    01553     // and send the reply packet to the host debugger.
    01554     //
    01555
    01556     m->u.WriteMemory64.ActualBytesWritten = AdditionalData->Length - Length;
    01557     MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
    01558     MessageHeader.Buffer = (PCHAR)m;
    01559     KdpSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
    01560                   &MessageHeader,
    01561                   NULL);
    01562
    01563     return;
    01564 }
    01565 #endif
    01566
    01567
    01568 VOID
    01569 KdpGetContext(
    01570     IN PDBGKD_MANIPULATE_STATE64 m,
    01571     IN PSTRING AdditionalData,
    01572     IN PCONTEXT Context
    01573     )
    01574
    01575 /*++
    01576
    01577 Routine Description:
    01578
    01579     This function is called in response of a get context state
    01580     manipulation message.  Its function is to return the current
    01581     context.
    01582
    01583 Arguments:
    01584
    01585     m - Supplies the state manipulation message.
    01586
    01587     AdditionalData - Supplies any additional data for the message.
    01588
    01589     Context - Supplies the current context.
    01590
    01591 Return Value:
    01592
    01593     None.
    01594
    01595 --*/
    01596
    01597 {
    01598     PDBGKD_GET_CONTEXT a = &m->u.GetContext;
    01599     STRING MessageHeader;
    01600
    01601     MessageHeader.Length = sizeof(*m);
    01602     MessageHeader.Buffer = (PCHAR)m;
    01603
    01604     ASSERT(AdditionalData->Length == 0);
    01605
    01606     if (m->Processor >= (USHORT)KeNumberProcessors) {
    01607         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    01608     } else {
    01609         m->ReturnStatus = STATUS_SUCCESS;
    01610         AdditionalData->Length = sizeof(CONTEXT);
    01611         if (m->Processor == (USHORT)KeGetCurrentPrcb()->Number) {
    01612             KdpQuickMoveMemory(AdditionalData->Buffer, (PCHAR)Context, sizeof(CONTEXT));
    01613         } else {
    01614             KdpQuickMoveMemory(AdditionalData->Buffer,
    01615                           (PCHAR)&KiProcessorBlock[m->Processor]->ProcessorState.ContextFrame,
    01616                           sizeof(CONTEXT)
    01617                          );
    01618         }
    01619     }
    01620
    01621     KdpSendPacket(
    01622                   PACKET_TYPE_KD_STATE_MANIPULATE,
    01623                   &MessageHeader,
    01624                   AdditionalData
    01625                   );
    01626 }
    01627
    01628 VOID
    01629 KdpSetContext(
    01630     IN PDBGKD_MANIPULATE_STATE64 m,
    01631     IN PSTRING AdditionalData,
    01632     IN PCONTEXT Context
    01633     )
    01634
    01635 /*++
    01636
    01637 Routine Description:
    01638
    01639     This function is called in response of a set context state
    01640     manipulation message.  Its function is set the current
    01641     context.
    01642
    01643 Arguments:
    01644
    01645     m - Supplies the state manipulation message.
    01646
    01647     AdditionalData - Supplies any additional data for the message.
    01648
    01649     Context - Supplies the current context.
    01650
    01651 Return Value:
    01652
    01653     None.
    01654
    01655 --*/
    01656
    01657 {
    01658     PDBGKD_SET_CONTEXT a = &m->u.SetContext;
    01659     STRING MessageHeader;
    01660
    01661     MessageHeader.Length = sizeof(*m);
    01662     MessageHeader.Buffer = (PCHAR)m;
    01663
    01664     ASSERT(AdditionalData->Length == sizeof(CONTEXT));
    01665
    01666     if (m->Processor >= (USHORT)KeNumberProcessors) {
    01667         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    01668     } else {
    01669         m->ReturnStatus = STATUS_SUCCESS;
    01670         if (m->Processor == (USHORT)KeGetCurrentPrcb()->Number) {
    01671             KdpQuickMoveMemory((PCHAR)Context, AdditionalData->Buffer, sizeof(CONTEXT));
    01672         } else {
    01673             KdpQuickMoveMemory((PCHAR)&KiProcessorBlock[m->Processor]->ProcessorState.ContextFrame,
    01674                           AdditionalData->Buffer,
    01675                           sizeof(CONTEXT)
    01676                          );
    01677         }
    01678     }
    01679
    01680     KdpSendPacket(
    01681                   PACKET_TYPE_KD_STATE_MANIPULATE,
    01682                   &MessageHeader,
    01683                   NULL
    01684                   );
    01685 }
    01686
    01687 VOID
    01688 KdpWriteBreakpoint(
    01689     IN PDBGKD_MANIPULATE_STATE64 m,
    01690     IN PSTRING AdditionalData,
    01691     IN PCONTEXT Context
    01692     )
    01693
    01694 /*++
    01695
    01696 Routine Description:
    01697
    01698     This function is called in response of a write breakpoint state
    01699     manipulation message.  Its function is to write a breakpoint
    01700     and return a handle to the breakpoint.
    01701
    01702 Arguments:
    01703
    01704     m - Supplies the state manipulation message.
    01705
    01706     AdditionalData - Supplies any additional data for the message.
    01707
    01708     Context - Supplies the current context.
    01709
    01710 Return Value:
    01711
    01712     None.
    01713
    01714 --*/
    01715
    01716 {
    01717     PDBGKD_WRITE_BREAKPOINT64 a = &m->u.WriteBreakPoint;
    01718     STRING MessageHeader;
    01719
    01720     MessageHeader.Length = sizeof(*m);
    01721     MessageHeader.Buffer = (PCHAR)m;
    01722
    01723     ASSERT(AdditionalData->Length == 0);
    01724
    01725     a->BreakPointHandle = KdpAddBreakpoint((PVOID)a->BreakPointAddress);
    01726     if (a->BreakPointHandle != 0) {
    01727         m->ReturnStatus = STATUS_SUCCESS;
    01728     } else {
    01729         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    01730     }
    01731     KdpSendPacket(
    01732                   PACKET_TYPE_KD_STATE_MANIPULATE,
    01733                   &MessageHeader,
    01734                   NULL
    01735                   );
    01736     UNREFERENCED_PARAMETER(Context);
    01737 }
    01738
    01739 VOID
    01740 KdpRestoreBreakpoint(
    01741     IN PDBGKD_MANIPULATE_STATE64 m,
    01742     IN PSTRING AdditionalData,
    01743     IN PCONTEXT Context
    01744     )
    01745
    01746 /*++
    01747
    01748 Routine Description:
    01749
    01750     This function is called in response of a restore breakpoint state
    01751     manipulation message.  Its function is to restore a breakpoint
    01752     using the specified handle.
    01753
    01754 Arguments:
    01755
    01756     m - Supplies the state manipulation message.
    01757
    01758     AdditionalData - Supplies any additional data for the message.
    01759
    01760     Context - Supplies the current context.
    01761
    01762 Return Value:
    01763
    01764     None.
    01765
    01766 --*/
    01767
    01768 {
    01769     PDBGKD_RESTORE_BREAKPOINT a = &m->u.RestoreBreakPoint;
    01770     STRING MessageHeader;
    01771
    01772     MessageHeader.Length = sizeof(*m);
    01773     MessageHeader.Buffer = (PCHAR)m;
    01774
    01775     ASSERT(AdditionalData->Length == 0);
    01776     if (KdpDeleteBreakpoint(a->BreakPointHandle)) {
    01777         m->ReturnStatus = STATUS_SUCCESS;
    01778     } else {
    01779         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    01780     }
    01781     KdpSendPacket(
    01782                   PACKET_TYPE_KD_STATE_MANIPULATE,
    01783                   &MessageHeader,
    01784                   NULL
    01785                   );
    01786     UNREFERENCED_PARAMETER(Context);
    01787 }
    01788
    01789 #if i386
    01790 long
    01791 SymNumFor(
    01792     ULONG pc
    01793     )
    01794 {
    01795     ULONG index;
    01796
    01797     for (index = 0; index < NumTraceDataSyms; index++) {
    01798         if ((TraceDataSyms[index].SymMin <= pc) &&
    01799             (TraceDataSyms[index].SymMax > pc)) return(index);
    01800     }
    01801     return(-1);
    01802 }
    01803
    01804 BOOLEAN TraceDataBufferFilled = FALSE;
    01805
    01806 void PotentialNewSymbol (ULONG pc)
    01807 {
    01808     if (!TraceDataBufferFilled &&
    01809         -1 != SymNumFor(pc)) {     // we've already seen this one
    01810         return;
    01811     }
    01812
    01813     TraceDataBufferFilled = FALSE;
    01814
    01815     // OK, we've got to start up a TraceDataRecord
    01816     TraceDataBuffer[TraceDataBufferPosition].s.LevelChange = 0;
    01817
    01818     if (-1 != SymNumFor(pc)) {
    01819         int sym = SymNumFor(pc);
    01820         TraceDataBuffer[TraceDataBufferPosition].s.SymbolNumber = (UCHAR) sym;
    01821         KdpCurrentSymbolStart = TraceDataSyms[sym].SymMin;
    01822         KdpCurrentSymbolEnd = TraceDataSyms[sym].SymMax;
    01823
    01824         return;  // we've already seen this one
    01825     }
    01826
    01827     TraceDataSyms[NextTraceDataSym].SymMin = KdpCurrentSymbolStart;
    01828     TraceDataSyms[NextTraceDataSym].SymMax = KdpCurrentSymbolEnd;
    01829
    01830     TraceDataBuffer[TraceDataBufferPosition].s.SymbolNumber = NextTraceDataSym;
    01831
    01832     // Bump the "next" pointer, wrapping if necessary.  Also bump the
    01833     // "valid" pointer if we need to.
    01834     NextTraceDataSym = (NextTraceDataSym + 1) % 256;
    01835     if (NumTraceDataSyms < NextTraceDataSym) {
    01836         NumTraceDataSyms = NextTraceDataSym;
    01837     }
    01838
    01839 }
    01840
    01841 void DumpTraceData(PSTRING MessageData)
    01842 {
    01843
    01844  TraceDataBuffer[0].LongNumber = TraceDataBufferPosition;
    01845  MessageData->Length = sizeof(TraceDataBuffer[0]) * TraceDataBufferPosition;
    01846  MessageData->Buffer = (PVOID)TraceDataBuffer;
    01847  TraceDataBufferPosition = 1;
    01848 }
    01849
    01850 BOOLEAN
    01851 TraceDataRecordCallInfo(
    01852     ULONG InstructionsTraced,
    01853     LONG CallLevelChange,
    01854     ULONG pc
    01855     )
    01856 {
    01857     // We've just exited a symbol scope.  The InstructionsTraced number goes
    01858     // with the old scope, the CallLevelChange goes with the new, and the
    01859     // pc fills in the symbol for the new TraceData record.
    01860
    01861     long SymNum = SymNumFor(pc);
    01862
    01863     if (KdpNextCallLevelChange != 0) {
    01864         TraceDataBuffer[TraceDataBufferPosition].s.LevelChange =
    01865                                                 (char) KdpNextCallLevelChange;
    01866         KdpNextCallLevelChange = 0;
    01867     }
    01868
    01869
    01870     if (InstructionsTraced >= TRACE_DATA_INSTRUCTIONS_BIG) {
    01871        TraceDataBuffer[TraceDataBufferPosition].s.Instructions =
    01872            TRACE_DATA_INSTRUCTIONS_BIG;
    01873        TraceDataBuffer[TraceDataBufferPosition+1].LongNumber =
    01874            InstructionsTraced;
    01875        TraceDataBufferPosition += 2;
    01876     } else {
    01877        TraceDataBuffer[TraceDataBufferPosition].s.Instructions =
    01878            (unsigned short)InstructionsTraced;
    01879        TraceDataBufferPosition++;
    01880     }
    01881
    01882     if ((TraceDataBufferPosition + 2 >= TRACE_DATA_BUFFER_MAX_SIZE) ||
    01883         (-1 == SymNum)) {
    01884         if (TraceDataBufferPosition +2 >= TRACE_DATA_BUFFER_MAX_SIZE) {
    01885             TraceDataBufferFilled = TRUE;
    01886         }
    01887        KdpNextCallLevelChange = CallLevelChange;
    01888        return FALSE;
    01889     }
    01890
    01891     TraceDataBuffer[TraceDataBufferPosition].s.LevelChange =(char)CallLevelChange;
    01892     TraceDataBuffer[TraceDataBufferPosition].s.SymbolNumber = (UCHAR) SymNum;
    01893     KdpCurrentSymbolStart = TraceDataSyms[SymNum].SymMin;
    01894     KdpCurrentSymbolEnd = TraceDataSyms[SymNum].SymMax;
    01895
    01896     return TRUE;
    01897 }
    01898
    01899 BOOLEAN
    01900 SkippingWhichBP (
    01901     PVOID thread,
    01902     PULONG BPNum
    01903     )
    01904
    01905 /*
    01906  * Return TRUE iff the pc corresponds to an internal breakpoint
    01907  * that has just been replaced for execution.  If TRUE, then return
    01908  * the breakpoint number in BPNum.
    01909  */
    01910
    01911 {
    01912     ULONG index;
    01913
    01914     if (!IntBPsSkipping) return FALSE;
    01915
    01916     for (index = 0; index < KdpNumInternalBreakpoints; index++) {
    01917         if (!(KdpInternalBPs[index].Flags & DBGKD_INTERNAL_BP_FLAG_INVALID) &&
    01918             (KdpInternalBPs[index].Thread == thread)) {
    01919             *BPNum = index;
    01920             return TRUE;
    01921         }
    01922     }
    01923     return FALSE; // didn't match any
    01924 }
    01925
    01926
    01927 NTSTATUS
    01928 KdQuerySpecialCalls (
    01929     IN PDBGKD_MANIPULATE_STATE64 m,
    01930     ULONG Length,
    01931     PULONG RequiredLength
    01932     )
    01933 {
    01934     *RequiredLength = sizeof(DBGKD_MANIPULATE_STATE64) +
    01935                         (sizeof(ULONG) * KdNumberOfSpecialCalls);
    01936
    01937     if ( Length < *RequiredLength ) {
    01938         return STATUS_INFO_LENGTH_MISMATCH;
    01939     }
    01940
    01941     m->u.QuerySpecialCalls.NumberOfSpecialCalls = KdNumberOfSpecialCalls;
    01942         RtlCopyMemory(
    01943         m + 1,
    01944         KdSpecialCalls,
    01945         sizeof(ULONG) * KdNumberOfSpecialCalls
    01946         );
    01947
    01948     return STATUS_SUCCESS;
    01949
    01950 } // KdQuerySpecialCalls
    01951
    01952
    01953 VOID
    01954 KdSetSpecialCall (
    01955     IN PDBGKD_MANIPULATE_STATE64 m,
    01956     IN PCONTEXT ContextRecord
    01957     )
    01958
    01959 /*++
    01960
    01961 Routine Description:
    01962
    01963     This function sets the addresses of the "special" call addresses
    01964     that the watchtrace facility pushes back to the kernel debugger
    01965     rather than stepping through.
    01966
    01967 Arguments:
    01968
    01969     m - Supplies the state manipulation message.
    01970
    01971 Return Value:
    01972
    01973     None.
    01974 --*/
    01975
    01976 {
    01977     if ( KdNumberOfSpecialCalls >= DBGKD_MAX_SPECIAL_CALLS ) {
    01978         return; // too bad
    01979     }
    01980
    01981     KdSpecialCalls[KdNumberOfSpecialCalls++] = (ULONG_PTR)m->u.SetSpecialCall.SpecialCall;
    01982
    01983     NextTraceDataSym = 0;
    01984     NumTraceDataSyms = 0;
    01985     KdpNextCallLevelChange = 0;
    01986     if (ContextRecord && !InstrCountInternal) {
    01987         InitialSP = ContextRecord->Esp;
    01988     }
    01989
    01990 } // KdSetSpecialCall
    01991
    01992
    01993 VOID
    01994 KdClearSpecialCalls (
    01995     VOID
    01996     )
    01997
    01998 /*++
    01999
    02000 Routine Description:
    02001
    02002     This function clears the addresses of the "special" call addresses
    02003     that the watchtrace facility pushes back to the kernel debugger
    02004     rather than stepping through.
    02005
    02006 Arguments:
    02007
    02008     None.
    02009
    02010 Return Value:
    02011
    02012     None.
    02013
    02014 --*/
    02015
    02016 {
    02017     KdNumberOfSpecialCalls = 0;
    02018     return;
    02019
    02020 } // KdClearSpecialCalls
    02021
    02022
    02023 BOOLEAN
    02024 KdpCheckTracePoint(
    02025     IN PEXCEPTION_RECORD ExceptionRecord,
    02026     IN OUT PCONTEXT ContextRecord
    02027     )
    02028 {
    02029     ULONG pc = (ULONG)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord);
    02030     LONG BpNum;
    02031     ULONG SkippedBPNum;
    02032     BOOLEAN AfterSC = FALSE;
    02033
    02034     if (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) {
    02035         if (WatchStepOverSuspended) {
    02036             //
    02037             //  For background, see the comment below where WSOThread is
    02038             //  wrong.  We've now stepped over the breakpoint in the non-traced
    02039             //  thread, and need to replace it and restart the non-traced
    02040             //  thread at full speed.
    02041             //
    02042
    02043             WatchStepOverHandle = KdpAddBreakpoint((PVOID)WatchStepOverBreakAddr);
    02044             WatchStepOverSuspended = FALSE;
    02045             ContextRecord->EFlags &= ~0x100L; /* clear trace flag */
    02046             return TRUE; // resume non-traced thread at full speed
    02047         }
    02048
    02049         if ((!SymbolRecorded) && (KdpCurrentSymbolStart != 0) && (KdpCurrentSymbolEnd != 0)) {
    02050             //
    02051             //  We need to use oldpc here, because this may have been
    02052             //  a 1 instruction call.  We've ALREADY executed the instruction
    02053             //  that the new symbol is for, and if the pc has moved out of
    02054             //  range, we might screw up.  Hence, use the pc from when
    02055             //  SymbolRecorded was set.  Yuck.
    02056             //
    02057
    02058             PotentialNewSymbol(oldpc);
    02059             SymbolRecorded = TRUE;
    02060         }
    02061
    02062         if (!InstrCountInternal &&
    02063             SkippingWhichBP((PVOID)KeGetCurrentThread(),&SkippedBPNum)) {
    02064
    02065             //
    02066             //  We just single-stepped over a temporarily removed internal
    02067             //  breakpoint.
    02068             //  If it's a COUNTONLY breakpoint:
    02069             //      Put the breakpoint instruction back and resume
    02070             //      regular execution.
    02071             //
    02072
    02073             if (KdpInternalBPs[SkippedBPNum].Flags &
    02074                 DBGKD_INTERNAL_BP_FLAG_COUNTONLY) {
    02075
    02076                 IntBPsSkipping --;
    02077
    02078                 KdpRestoreAllBreakpoints();
    02079
    02080                 ContextRecord->EFlags &= ~0x100L;  // Clear trace flag
    02081                 KdpInternalBPs[SkippedBPNum].Thread = 0;
    02082
    02083                 if (KdpInternalBPs[SkippedBPNum].Flags &
    02084                         DBGKD_INTERNAL_BP_FLAG_DYING) {
    02085                     KdpDeleteBreakpoint(KdpInternalBPs[SkippedBPNum].Handle);
    02086                     KdpInternalBPs[SkippedBPNum].Flags |=
    02087                             DBGKD_INTERNAL_BP_FLAG_INVALID; // bye, bye
    02088                 }
    02089
    02090                 return TRUE;
    02091             }
    02092
    02093             //
    02094             //  If it's not:
    02095             //      set up like it's a ww, by setting Begin and KdpCurrentSymbolEnd
    02096             //      and bop off into single step land.  We probably ought to
    02097             //      disable all breakpoints here, too, so that we don't do
    02098             //      anything foul like trying two non-COUNTONLY's at the
    02099             //      same time or something...
    02100             //
    02101
    02102             KdpCurrentSymbolEnd = 0;
    02103             KdpCurrentSymbolStart = (ULONG_PTR) KdpInternalBPs[SkippedBPNum].ReturnAddress;
    02104
    02105             ContextRecord->EFlags |= 0x100L; /* Trace on. */
    02106             InitialSP = ContextRecord->Esp;
    02107
    02108             InstructionsTraced = 1;  /* Count the initial call instruction. */
    02109             InstrCountInternal = TRUE;
    02110         }
    02111
    02112     } /* if single step */
    02113     else if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) {
    02114         if (WatchStepOver && pc == WatchStepOverBreakAddr) {
    02115             //
    02116             //  This is a breakpoint after completion of a "special call"
    02117             //
    02118
    02119             if ((WSOThread != (PVOID)KeGetCurrentThread()) ||
    02120                 (WSOEsp + 0x20 < ContextRecord->Esp) ||
    02121                 (ContextRecord->Esp + 0x20 < WSOEsp)) {
    02122                 //
    02123                 //  Here's the story up to this point: the traced thread
    02124                 //  cruised along until it it a special call.  The tracer
    02125                 //  placed a breakpoint on the instruction immediately after
    02126                 //  the special call returns and restarted the traced thread
    02127                 //  at full speed.  Then, some *other* thread hit the
    02128                 //  breakpoint.  So, to correct for this, we're going to
    02129                 //  remove the breakpoint, single step the non-traced
    02130                 //  thread one instruction, replace the breakpoint,
    02131                 //  restart the non-traced thread at full speed, and wait
    02132                 //  for the traced thread to get to this breakpoint, just
    02133                 //  like we were when this happened.  The assumption
    02134                 //  here is that the traced thread won't hit the breakpoint
    02135                 //  while it's removed, which I believe to be true, because
    02136                 //  I don't think a context switch can occur during a single
    02137                 //  step operation.
    02138                 //
    02139                 //  For extra added fun, it's possible to execute interrupt
    02140                 //  routines IN THE SAME THREAD!!!  That's why we need to keep
    02141                 //  the stack pointer as well as the thread address: the APC
    02142                 //  code can result in pushing on the stack and doing a call
    02143                 //  that's really part on an interrupt service routine in the
    02144                 //  context of the current thread.  Lovely, isn't it?
    02145                 //
    02146
    02147                 WatchStepOverSuspended = TRUE;
    02148                 KdpDeleteBreakpoint(WatchStepOverHandle);
    02149                 ContextRecord->EFlags |= 0x100L; // Set trace flag
    02150                 return TRUE; // single step "non-traced" thread
    02151             }
    02152
    02153             //
    02154             //  we're in the thread we started in; resume in single-step mode
    02155             //  to continue the trace.
    02156             //
    02157
    02158             WatchStepOver = FALSE;
    02159             KdpDeleteBreakpoint(WatchStepOverHandle);
    02160             ContextRecord->EFlags |= 0x100L; // back to single step mode
    02161             AfterSC = TRUE; // put us into the regular watchStep code
    02162
    02163         } else {
    02164
    02165             for ( BpNum = 0; BpNum < (LONG) KdpNumInternalBreakpoints; BpNum++ ) {
    02166                 if ( !(KdpInternalBPs[BpNum].Flags &
    02167                        (DBGKD_INTERNAL_BP_FLAG_INVALID |
    02168                         DBGKD_INTERNAL_BP_FLAG_SUSPENDED) ) &&
    02169                      (KdpInternalBPs[BpNum].Addr == pc) ) {
    02170                     break;
    02171                 }
    02172             }
    02173
    02174             if ( BpNum < (LONG) KdpNumInternalBreakpoints ) {
    02175
    02176                 //
    02177                 //  This is an internal monitoring breakpoint.
    02178                 //  Restore the instruction and start in single-step
    02179                 //  mode so that we can retore the breakpoint once the
    02180                 //  instruction executes, or continue stepping if this isn't
    02181                 //  a COUNTONLY breakpoint.
    02182                 //
    02183
    02184                 KdpProcessInternalBreakpoint( BpNum );
    02185                 KdpInternalBPs[BpNum].Thread = (PVOID)KeGetCurrentThread();
    02186                 IntBPsSkipping ++;
    02187
    02188                 KdpSuspendAllBreakpoints();
    02189
    02190                 ContextRecord->EFlags |= 0x100L;  // Set trace flag
    02191                 if (!(KdpInternalBPs[BpNum].Flags &
    02192                         DBGKD_INTERNAL_BP_FLAG_COUNTONLY)) {
    02193                     KdpInternalBPs[BpNum].ReturnAddress =
    02194                                     KdpGetReturnAddress( ContextRecord );
    02195                 }
    02196                 return TRUE;
    02197             }
    02198         }
    02199     } /* if breakpoint */
    02200
    02201 //  if (AfterSC) {
    02202 //      DPRINT(( "1: KdpCurrentSymbolStart %x  KdpCurrentSymbolEnd %x\n", KdpCurrentSymbolStart, KdpCurrentSymbolEnd ));
    02203 //  }
    02204
    02205     if ((AfterSC || ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) &&
    02206         KdpCurrentSymbolStart != 0 &&
    02207         ((KdpCurrentSymbolEnd == 0 && ContextRecord->Esp <= InitialSP) ||
    02208          (KdpCurrentSymbolStart <= pc && pc < KdpCurrentSymbolEnd))) {
    02209         ULONG lc;
    02210         BOOLEAN IsSpecialCall;
    02211
    02212         //
    02213         //  We've taken a step trace, but are still executing in the current
    02214         //  function.  Remember that we executed an instruction and see if the
    02215         //  instruction changes the call level.
    02216         //
    02217
    02218         lc = KdpLevelChange( pc, ContextRecord, &IsSpecialCall );
    02219         InstructionsTraced++;
    02220         CallLevelChange += lc;
    02221
    02222         //
    02223         //  See if instruction is a transfer to a special routine, one that we
    02224         //  cannot trace through since it may swap contexts
    02225         //
    02226
    02227         if (IsSpecialCall) {
    02228
    02229 //  DPRINT( ("2: pc=%x, level change %d\n", pc, lc) );
    02230
    02231             //
    02232             //  We are about to transfer to a special call routine.  Since we
    02233             //  cannot trace through this routine, we execute it atomically by
    02234             //  setting a breakpoint at the next logical offset.
    02235             //
    02236             //  Note in the case of an indirect jump to a special call routine, the
    02237             //  level change will be -1 and the next offset will be the ULONG that's
    02238             //  on the top of the stack.
    02239             //
    02240             //  However, we've already adjusted the level based on this
    02241             //  instruction.  We need to undo this except for the magic -1 call.
    02242             //
    02243
    02244             if (lc != -1) {
    02245                 CallLevelChange -= lc;
    02246             }
    02247
    02248             //
    02249             //  Set up for stepping over a procedure
    02250             //
    02251
    02252             WatchStepOver = TRUE;
    02253             WatchStepOverBreakAddr = KdpGetCallNextOffset( pc, ContextRecord );
    02254             WSOThread = (PVOID)KeGetCurrentThread( );
    02255             WSOEsp = ContextRecord->Esp;
    02256
    02257             //
    02258             //  Establish the breakpoint
    02259             //
    02260
    02261             WatchStepOverHandle = KdpAddBreakpoint( (PVOID)WatchStepOverBreakAddr );
    02262
    02263
    02264             //
    02265             //  Note that we are continuing rather than tracing and rely on hitting
    02266             //  the breakpoint in the current thread context to resume the watch
    02267             //  action.
    02268             //
    02269
    02270             ContextRecord->EFlags &= ~0x100L;
    02271             return TRUE;
    02272         }
    02273
    02274         //
    02275         //  Resume execution with the trace flag set.  Avoid going over the wire to
    02276         //  the remote debugger.
    02277         //
    02278
    02279         ContextRecord->EFlags |= 0x100L;  // Set trace flag
    02280
    02281         return TRUE;
    02282     }
    02283
    02284     if ((AfterSC || (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)) &&
    02285         (KdpCurrentSymbolStart != 0)) {
    02286         //
    02287         // We're WatchTracing, but have just changed symbol range.
    02288         // Fill in the call record and return to the debugger if
    02289         // either we're full or the pc is outside of the known
    02290         // symbol scopes.  Otherwise, resume stepping.
    02291         //
    02292         int lc;
    02293         BOOLEAN IsSpecialCall;
    02294
    02295         InstructionsTraced++; // don't forget to count the call/ret instruction.
    02296
    02297 //  if (AfterSC) {
    02298 //      DPRINT(( "3: InstrCountInternal: %x\n", InstrCountInternal ));
    02299 //  }
    02300
    02301         if (InstrCountInternal) {
    02302
    02303             // We've just finished processing a non-COUNTONLY breakpoint.
    02304             // Record the appropriate data and resume full speed execution.
    02305
    02306             SkippingWhichBP((PVOID)KeGetCurrentThread(),&SkippedBPNum);
    02307
    02308             KdpInternalBPs[SkippedBPNum].Calls++;
    02309
    02310
    02311             if (KdpInternalBPs[SkippedBPNum].MinInstructions > InstructionsTraced) {
    02312                 KdpInternalBPs[SkippedBPNum].MinInstructions = InstructionsTraced;
    02313             }
    02314             if (KdpInternalBPs[SkippedBPNum].MaxInstructions < InstructionsTraced) {
    02315                 KdpInternalBPs[SkippedBPNum].MaxInstructions = InstructionsTraced;
    02316             }
    02317             KdpInternalBPs[SkippedBPNum].TotalInstructions += InstructionsTraced;
    02318
    02319             KdpInternalBPs[SkippedBPNum].Thread = 0;
    02320
    02321             IntBPsSkipping--;
    02322             InstrCountInternal = FALSE;
    02323             KdpCurrentSymbolStart = 0;
    02324             KdpRestoreAllBreakpoints();
    02325
    02326             if (KdpInternalBPs[SkippedBPNum].Flags &
    02327                     DBGKD_INTERNAL_BP_FLAG_DYING) {
    02328                 KdpDeleteBreakpoint(KdpInternalBPs[SkippedBPNum].Handle);
    02329                 KdpInternalBPs[SkippedBPNum].Flags |=
    02330                         DBGKD_INTERNAL_BP_FLAG_INVALID; // bye, bye
    02331             }
    02332
    02333             ContextRecord->EFlags &= ~0x100L; // clear trace flag
    02334             return TRUE; // Back to normal execution.
    02335         }
    02336
    02337         if (TraceDataRecordCallInfo( InstructionsTraced, CallLevelChange, pc)) {
    02338
    02339             //
    02340             //  Everything was cool internally.  We can keep executing without
    02341             //  going back to the remote debugger.
    02342             //
    02343             //  We have to compute lc after calling
    02344             //  TraceDataRecordCallInfo, because LevelChange relies on
    02345             //  KdpCurrentSymbolStart and KdpCurrentSymbolEnd corresponding to
    02346             //  the pc.
    02347             //
    02348
    02349             lc = KdpLevelChange( pc, ContextRecord, &IsSpecialCall );
    02350             InstructionsTraced = 0;
    02351             CallLevelChange = lc;
    02352
    02353             //
    02354             //  See if instruction is a transfer to a special routine, one that we
    02355             //  cannot trace through since it may swap contexts
    02356             //
    02357
    02358             if (IsSpecialCall) {
    02359
    02360 //  DPRINT(( "4: pc=%x, level change %d\n", pc, lc));
    02361
    02362                 //
    02363                 //  We are about to transfer to a special call routine.  Since we
    02364                 //  cannot trace through this routine, we execute it atomically by
    02365                 //  setting a breakpoint at the next logical offset.
    02366                 //
    02367                 //  Note in the case of an indirect jump to a special call routine, the
    02368                 //  level change will be -1 and the next offset will be the ULONG that's
    02369                 //  on the top of the stack.
    02370                 //
    02371                 //  However, we've already adjusted the level based on this
    02372                 //  instruction.  We need to undo this except for the magic -1 call.
    02373                 //
    02374
    02375                 if (lc != -1) {
    02376                     CallLevelChange -= lc;
    02377                 }
    02378
    02379                 //
    02380                 //  Set up for stepping over a procedure
    02381                 //
    02382
    02383                 WatchStepOver = TRUE;
    02384                 WSOThread = (PVOID)KeGetCurrentThread();
    02385
    02386                 //
    02387                 //  Establish the breakpoint
    02388                 //
    02389
    02390                 WatchStepOverHandle =
    02391                     KdpAddBreakpoint( (PVOID)KdpGetCallNextOffset( pc, ContextRecord ));
    02392
    02393                 //
    02394                 //  Resume execution with the trace flag set.  Avoid going over the wire to
    02395                 //  the remote debugger.
    02396                 //
    02397
    02398                 ContextRecord->EFlags &= ~0x100L;
    02399                 return TRUE;
    02400             }
    02401
    02402             ContextRecord->EFlags |= 0x100L; // Set trace flag
    02403             return TRUE; // Off we go
    02404         }
    02405
    02406         lc = KdpLevelChange( pc, ContextRecord, &IsSpecialCall );
    02407         InstructionsTraced = 0;
    02408         CallLevelChange = lc;
    02409
    02410         // We need to go back to the remote debugger.  Just fall through.
    02411
    02412         if ((lc != 0) && IsSpecialCall) {
    02413             // We're hosed
    02414             DPRINT(( "Special call on first entry to symbol scope @ %x\n", pc ));
    02415         }
    02416     }
    02417
    02418     SymbolRecorded = FALSE;
    02419     oldpc = pc;
    02420
    02421     return FALSE;
    02422 }
    02423 #endif // i386
    02424
    02425 BOOLEAN
    02426 KdpSwitchProcessor (
    02427     IN PEXCEPTION_RECORD ExceptionRecord,
    02428     IN OUT PCONTEXT ContextRecord,
    02429     IN BOOLEAN SecondChance
    02430     )
    02431 {
    02432     BOOLEAN Status;
    02433
    02434     //
    02435     // Save port state
    02436     //
    02437
    02438     KdPortSave ();
    02439
    02440     //
    02441     // Process state change for this processor
    02442     //
    02443
    02444     Status = KdpReportExceptionStateChange (
    02445                 ExceptionRecord,
    02446                 ContextRecord,
    02447                 SecondChance
    02448                 );
    02449
    02450     //
    02451     // Restore port state and return status
    02452     //
    02453
    02454     KdPortRestore ();
    02455     return Status;
    02456 }
    02457
    02458 BOOLEAN
    02459 KdpReportExceptionStateChange (
    02460     IN PEXCEPTION_RECORD ExceptionRecord,
    02461     IN OUT PCONTEXT ContextRecord,
    02462     IN BOOLEAN SecondChance
    02463     )
    02464
    02465 /*++
    02466
    02467 Routine Description:
    02468
    02469     This routine sends an exception state change packet to the kernel
    02470     debugger and waits for a manipulate state message.
    02471
    02472 Arguments:
    02473
    02474     ExceptionRecord - Supplies a pointer to an exception record.
    02475
    02476     ContextRecord - Supplies a pointer to a context record.
    02477
    02478     SecondChance - Supplies a boolean value that determines whether this is
    02479         the first or second chance for the exception.
    02480
    02481 Return Value:
    02482
    02483     A value of TRUE is returned if the exception is handled. Otherwise, a
    02484     value of FALSE is returned.
    02485
    02486 --*/
    02487
    02488 {
    02489     STRING MessageData;
    02490     STRING MessageHeader;
    02491     DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
    02492     KCONTINUE_STATUS Status;
    02493
    02494 #if i386
    02495     if (KdpCheckTracePoint(ExceptionRecord,ContextRecord)) return TRUE;
    02496 #endif
    02497
    02498     do {
    02499
    02500         //
    02501         // Construct the wait state change message and message descriptor.
    02502         //
    02503
    02504         KdpSetStateChange(&WaitStateChange,
    02505                             ExceptionRecord,
    02506                             ContextRecord,
    02507                             SecondChance
    02508                             );
    02509
    02510         MessageHeader.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
    02511         MessageHeader.Buffer = (PCHAR)&WaitStateChange;
    02512
    02513 #if i386
    02514         //
    02515         // Construct the wait state change data and data descriptor.
    02516         //
    02517
    02518         DumpTraceData(&MessageData);
    02519 #else
    02520         MessageData.Length = 0;
    02521 #endif
    02522
    02523         //
    02524         // Send packet to the kernel debugger on the host machine,
    02525         // wait for answer.
    02526         //
    02527
    02528         Status = KdpSendWaitContinue(
    02529                     PACKET_TYPE_KD_STATE_CHANGE64,
    02530                     &MessageHeader,
    02531                     &MessageData,
    02532                     ContextRecord
    02533                     );
    02534
    02535     } while (Status == ContinueProcessorReselected) ;
    02536
    02537     return (BOOLEAN) Status;
    02538 }
    02539
    02540
    02541 BOOLEAN
    02542 KdpReportLoadSymbolsStateChange (
    02543     IN PSTRING PathName,
    02544     IN PKD_SYMBOLS_INFO SymbolInfo,
    02545     IN BOOLEAN UnloadSymbols,
    02546     IN OUT PCONTEXT ContextRecord
    02547     )
    02548
    02549 /*++
    02550
    02551 Routine Description:
    02552
    02553     This routine sends a load symbols state change packet to the kernel
    02554     debugger and waits for a manipulate state message.
    02555
    02556 Arguments:
    02557
    02558     PathName - Supplies a pointer to the pathname of the image whose
    02559         symbols are to be loaded.
    02560
    02561     BaseOfDll - Supplies the base address where the image was loaded.
    02562
    02563     ProcessId - Unique 32-bit identifier for process that is using
    02564         the symbols.  -1 for system process.
    02565
    02566     CheckSum - Unique 32-bit identifier from image header.
    02567
    02568     UnloadSymbol - TRUE if the symbols that were previously loaded for
    02569         the named image are to be unloaded from the debugger.
    02570
    02571 Return Value:
    02572
    02573     A value of TRUE is returned if the exception is handled. Otherwise, a
    02574     value of FALSE is returned.
    02575
    02576 --*/
    02577
    02578 {
    02579
    02580     PSTRING AdditionalData;
    02581     STRING MessageData;
    02582     STRING MessageHeader;
    02583     DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
    02584     KCONTINUE_STATUS Status;
    02585
    02586     do {
    02587
    02588         //
    02589         // Construct the wait state change message and message descriptor.
    02590         //
    02591
    02592         WaitStateChange.NewState = DbgKdLoadSymbolsStateChange;
    02593         WaitStateChange.ProcessorLevel = KeProcessorLevel;
    02594         WaitStateChange.Processor = (USHORT)KeGetCurrentPrcb()->Number;
    02595         WaitStateChange.NumberProcessors = (ULONG)KeNumberProcessors;
    02596         WaitStateChange.Thread = (ULONG64)(LONG64)(LONG_PTR) KeGetCurrentThread();
    02597         WaitStateChange.ProgramCounter = (ULONG64)(LONG64)(LONG_PTR) CONTEXT_TO_PROGRAM_COUNTER(ContextRecord);
    02598         KdpSetLoadState(&WaitStateChange, ContextRecord);
    02599         WaitStateChange.u.LoadSymbols.UnloadSymbols = UnloadSymbols;
    02600         WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)SymbolInfo->BaseOfDll;
    02601         WaitStateChange.u.LoadSymbols.ProcessId = (ULONG) SymbolInfo->ProcessId;
    02602         WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
    02603         WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
    02604         if (ARGUMENT_PRESENT( PathName )) {
    02605             WaitStateChange.u.LoadSymbols.PathNameLength =
    02606                 KdpMoveMemory(
    02607                     (PCHAR)KdpPathBuffer,
    02608                     (PCHAR)PathName->Buffer,
    02609                     PathName->Length
    02610                     ) + 1;
    02611
    02612             MessageData.Buffer = KdpPathBuffer;
    02613             MessageData.Length = (USHORT)WaitStateChange.u.LoadSymbols.PathNameLength;
    02614             MessageData.Buffer[MessageData.Length-1] = '\0';
    02615             AdditionalData = &MessageData;
    02616         } else {
    02617             WaitStateChange.u.LoadSymbols.PathNameLength = 0;
    02618             AdditionalData = NULL;
    02619         }
    02620
    02621         MessageHeader.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
    02622         MessageHeader.Buffer = (PCHAR)&WaitStateChange;
    02623
    02624         //
    02625         // Send packet to the kernel debugger on the host machine, wait
    02626         // for the reply.
    02627         //
    02628
    02629         Status = KdpSendWaitContinue(
    02630                     PACKET_TYPE_KD_STATE_CHANGE64,
    02631                     &MessageHeader,
    02632                     AdditionalData,
    02633                     ContextRecord
    02634                     );
    02635
    02636     } while (Status == ContinueProcessorReselected);
    02637
    02638     return (BOOLEAN) Status;
    02639 }
    02640
    02641
    02642 VOID
    02643 KdpReadPhysicalMemory(
    02644     IN PDBGKD_MANIPULATE_STATE64 m,
    02645     IN PSTRING AdditionalData,
    02646     IN PCONTEXT Context
    02647     )
    02648
    02649 /*++
    02650
    02651 Routine Description:
    02652
    02653     This function is called in response to a read physical memory
    02654     state manipulation message. Its function is to read physical memory
    02655     and return.
    02656
    02657 Arguments:
    02658
    02659     m - Supplies the state manipulation message.
    02660
    02661     AdditionalData - Supplies any additional data for the message.
    02662
    02663     Context - Supplies the current context.
    02664
    02665 Return Value:
    02666
    02667     None.
    02668
    02669 --*/
    02670
    02671 {
    02672     PDBGKD_READ_MEMORY64 a = &m->u.ReadMemory;
    02673     ULONG Length;
    02674     STRING MessageHeader;
    02675     PVOID64 VirtualAddress;
    02676     PHYSICAL_ADDRESS Source;
    02677     UCHAR UNALIGNED *Destination;
    02678     ULONG NumberBytes;
    02679     ULONG BytesLeft;
    02680
    02681     MessageHeader.Length = sizeof(*m);
    02682     MessageHeader.Buffer = (PCHAR)m;
    02683
    02684     //
    02685     // make sure that nothing but a read memory message was transmitted
    02686     //
    02687
    02688     ASSERT(AdditionalData->Length == 0);
    02689
    02690     //
    02691     // Trim transfer count to fit in a single message
    02692     //
    02693
    02694     if (a->TransferCount > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) {
    02695         Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
    02696     } else {
    02697         Length = a->TransferCount;
    02698     }
    02699
    02700     //
    02701     // Since the MmDbgTranslatePhysicalAddress64 only maps in one physical
    02702     // page at a time (on non-alpha systems),
    02703     // we need to break the memory move up into smaller
    02704     // moves which don't cross page boundaries.  It is important that we
    02705     // access physical memory on naturally-aligned boundaries and with the
    02706     // largest size possible.  (We could be accessing memory-mapped I/O
    02707     // space).  These rules allow kdexts to read physical memory reliably.
    02708     //
    02709
    02710     Source.QuadPart = a->TargetBaseAddress;
    02711     Destination = AdditionalData->Buffer;
    02712     while (Length > 0) {
    02713         VirtualAddress = MmDbgTranslatePhysicalAddress64(Source);
    02714         if (VirtualAddress == NULL64) {
    02715             break;
    02716         }
    02717         NumberBytes = PAGE_SIZE - BYTE_OFFSET(Source.LowPart);
    02718         if (NumberBytes > Length) {
    02719             NumberBytes = Length;
    02720         }
    02721
    02722 #ifdef _ALPHA_
    02723         BytesLeft = NumberBytes;
    02724         while (BytesLeft > 0) {
    02725             __MB();
    02726
    02727             if (((ULONG64)VirtualAddress & 7) == 0 && BytesLeft > 7) {
    02728                 *((ULONGLONG UNALIGNED *)Destination)++ =
    02729                     *((ULONGLONG * POINTER_64)VirtualAddress)++;
    02730                 BytesLeft -= 8;
    02731             } else {
    02732                 if (((ULONG64)VirtualAddress & 3) == 0 && BytesLeft > 3) {
    02733                     *((ULONG UNALIGNED *)Destination)++ =
    02734                         *((ULONG * POINTER_64)VirtualAddress)++;
    02735                     BytesLeft -= 4;
    02736                 } else {
    02737                     if (((ULONG64)VirtualAddress & 1) == 0 && BytesLeft > 1) {
    02738                         *((USHORT UNALIGNED *)Destination)++ =
    02739                             *((USHORT * POINTER_64)VirtualAddress)++;
    02740                         BytesLeft -= 2;
    02741                     } else {
    02742                         *Destination++ =
    02743                             *((UCHAR * POINTER_64)VirtualAddress)++;
    02744                         BytesLeft -= 1;
    02745                     }
    02746                 }
    02747             }
    02748         }
    02749 #else
    02750         KdpMoveMemory(Destination, VirtualAddress, NumberBytes);
    02751         Destination += NumberBytes;
    02752
    02753 #endif
    02754         Source.QuadPart += NumberBytes;
    02755         Length -= NumberBytes;
    02756         AdditionalData->Length += (USHORT)NumberBytes;
    02757     }
    02758
    02759     if (Length == 0) {
    02760         m->ReturnStatus = STATUS_SUCCESS;
    02761     } else {
    02762         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    02763     }
    02764
    02765     a->ActualBytesRead = AdditionalData->Length;
    02766
    02767     KdpSendPacket(
    02768                   PACKET_TYPE_KD_STATE_MANIPULATE,
    02769                   &MessageHeader,
    02770                   AdditionalData
    02771                   );
    02772     UNREFERENCED_PARAMETER(Context);
    02773
    02774 }
    02775
    02776
    02777
    02778 VOID
    02779 KdpWritePhysicalMemory(
    02780     IN PDBGKD_MANIPULATE_STATE64 m,
    02781     IN PSTRING AdditionalData,
    02782     IN PCONTEXT Context
    02783     )
    02784
    02785 /*++
    02786
    02787 Routine Description:
    02788
    02789     This function is called in response to a write physical memory
    02790     state manipulation message. Its function is to write physical memory
    02791     and return.
    02792
    02793 Arguments:
    02794
    02795     m - Supplies the state manipulation message.
    02796
    02797     AdditionalData - Supplies any additional data for the message.
    02798
    02799     Context - Supplies the current context.
    02800
    02801 Return Value:
    02802
    02803     None.
    02804
    02805 --*/
    02806
    02807 {
    02808     PDBGKD_WRITE_MEMORY64 a = &m->u.WriteMemory;
    02809     STRING MessageHeader;
    02810     ULONG Length;
    02811     PVOID64 VirtualAddress;
    02812     PHYSICAL_ADDRESS Destination;
    02813     UCHAR UNALIGNED *Source;
    02814     ULONG NumberBytes;
    02815     ULONG BytesLeft;
    02816
    02817     MessageHeader.Length = sizeof(*m);
    02818     MessageHeader.Buffer = (PCHAR)m;
    02819
    02820
    02821     Length = a->TransferCount;
    02822
    02823     //
    02824     // The following code depends on the existence of the
    02825     // MmDbgTranslatePhysicalAddress64() routine.  This has only been
    02826     // implemented for Alpha.
    02827     //
    02828
    02829     //
    02830     // Since the MmDbgTranslatePhysicalAddress64 only maps in one physical
    02831     // page at a time, we need to break the memory move up into smaller
    02832     // moves which don't cross page boundaries.  It is important that we
    02833     // access physical memory on naturally-aligned boundaries and with the
    02834     // largest size possible.  (We could be accessing memory-mapped I/O
    02835     // space).  These rules allow kdexts to write physical memory reliably.
    02836     //
    02837
    02838     Source = AdditionalData->Buffer;
    02839     Destination.QuadPart = a->TargetBaseAddress;
    02840     while (Length > 0) {
    02841         VirtualAddress = MmDbgTranslatePhysicalAddress64(Destination);
    02842         if (VirtualAddress == NULL64) {
    02843             break;
    02844         }
    02845         NumberBytes = PAGE_SIZE - BYTE_OFFSET(Destination.LowPart);
    02846         if (NumberBytes > Length) {
    02847             NumberBytes = Length;
    02848         }
    02849 #ifdef _ALPHA_
    02850         BytesLeft = NumberBytes;
    02851         while (BytesLeft > 0) {
    02852             if (((ULONG64)VirtualAddress & 7) == 0 && BytesLeft > 7) {
    02853                 *((ULONGLONG * POINTER_64)VirtualAddress)++ =
    02854                     *((ULONGLONG UNALIGNED *)Source)++;
    02855                 BytesLeft -= 8;
    02856             } else {
    02857                 if (((ULONG64)VirtualAddress & 3) == 0 && BytesLeft > 3) {
    02858                     *((ULONG * POINTER_64)VirtualAddress)++ =
    02859                         *((ULONG UNALIGNED *)Source)++;
    02860                     BytesLeft -= 4;
    02861                 } else {
    02862                     if (((ULONG64)VirtualAddress & 1) == 0 && BytesLeft > 1) {
    02863                         *((USHORT * POINTER_64)VirtualAddress)++ =
    02864                             *((USHORT UNALIGNED *)Source)++;
    02865                         BytesLeft -= 2;
    02866                     } else {
    02867                         *((UCHAR * POINTER_64)VirtualAddress)++ =
    02868                             *(UCHAR UNALIGNED *)Source++;
    02869                         BytesLeft -= 1;
    02870                     }
    02871                 }
    02872             }
    02873
    02874             __MB();
    02875         }
    02876 #else
    02877         KdpMoveMemory(VirtualAddress, Source, NumberBytes);
    02878         Source += NumberBytes;
    02879
    02880 #endif
    02881         Destination.QuadPart += NumberBytes;
    02882         Length -= NumberBytes;
    02883         a->ActualBytesWritten += NumberBytes;
    02884     }
    02885
    02886     if (Length == 0) {
    02887         m->ReturnStatus = STATUS_SUCCESS;
    02888     } else {
    02889         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    02890     }
    02891
    02892     KdpSendPacket(
    02893                   PACKET_TYPE_KD_STATE_MANIPULATE,
    02894                   &MessageHeader,
    02895                   NULL
    02896                   );
    02897     UNREFERENCED_PARAMETER(Context);
    02898 }
    02899
    02900
    02901
    02902 #if i386
    02903 VOID
    02904 KdpProcessInternalBreakpoint (
    02905     ULONG BreakpointNumber
    02906     )
    02907 {
    02908     static BOOLEAN timerStarted = FALSE;
    02909     LARGE_INTEGER dueTime;
    02910
    02911     if ( !(KdpInternalBPs[BreakpointNumber].Flags &
    02912            DBGKD_INTERNAL_BP_FLAG_COUNTONLY) ) {
    02913         return;     // We only deal with COUNTONLY breakpoints
    02914     }
    02915
    02916     //
    02917     // We've hit a real internal breakpoint; make sure the timeout is
    02918     // kicked off.
    02919     //
    02920
    02921     if ( !timerStarted ) { // ok, maybe there's a prettier way to do this.
    02922         dueTime.LowPart = (ULONG)(-1 * 10 * 1000 * 1000);
    02923         dueTime.HighPart = -1;
    02924         KeInitializeDpc(
    02925             &InternalBreakpointCheckDpc,
    02926             &InternalBreakpointCheck,
    02927             NULL
    02928             );
    02929         KeInitializeTimer( &InternalBreakpointTimer );
    02930         KeSetTimer(
    02931             &InternalBreakpointTimer,
    02932             dueTime,
    02933             &InternalBreakpointCheckDpc
    02934             );
    02935         timerStarted = TRUE;
    02936     }
    02937
    02938     KdpInternalBPs[BreakpointNumber].Calls++;
    02939
    02940 } // KdpProcessInternalBreakpoint
    02941 #endif
    02942
    02943
    02944 VOID
    02945 KdpGetVersion(
    02946     IN PDBGKD_MANIPULATE_STATE64 m
    02947     )
    02948
    02949 /*++
    02950
    02951 Routine Description:
    02952
    02953     This function returns to the caller a general information packet
    02954     that contains useful information to a debugger.  This packet is also
    02955     used for a debugger to determine if the writebreakpointex and
    02956     readbreakpointex apis are available.
    02957
    02958 Arguments:
    02959
    02960     m - Supplies the state manipulation message.
    02961
    02962 Return Value:
    02963
    02964     None.
    02965
    02966 --*/
    02967
    02968 {
    02969     STRING                   messageHeader;
    02970
    02971
    02972     messageHeader.Length = sizeof(*m);
    02973     messageHeader.Buffer = (PCHAR)m;
    02974
    02975     RtlZeroMemory(&m->u.GetVersion64, sizeof(m->u.GetVersion64));
    02976     //
    02977     // the current build number
    02978     //
    02979     m->u.GetVersion64.MinorVersion = (short)NtBuildNumber;
    02980     m->u.GetVersion64.MajorVersion = (short)((NtBuildNumber >> 28) & 0xFFFFFFF);
    02981
    02982     //
    02983     // kd protocol version number.  this should be incremented if the
    02984     // protocol changes.
    02985     //
    02986     m->u.GetVersion64.ProtocolVersion = 5;
    02987     m->u.GetVersion64.Flags = DBGKD_VERS_FLAG_DATA;
    02988
    02989 #if !defined(NT_UP)
    02990     m->u.GetVersion64.Flags |= DBGKD_VERS_FLAG_MP;
    02991 #endif
    02992
    02993 #if defined(_M_IX86)
    02994     m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_I386;
    02995 #elif defined(_M_MRX000)
    02996     m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_R4000;
    02997 #elif defined(_M_ALPHA)
    02998     m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_ALPHA;
    02999 #if defined(_AXP64_)
    03000     m->u.GetVersion64.Flags |= DBGKD_VERS_FLAG_PTR64;
    03001 #endif
    03002 #elif defined(_M_PPC)
    03003     m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_POWERPC;
    03004 #elif defined(_M_IA64)
    03005     m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_IA64;
    03006     m->u.GetVersion64.Flags |= DBGKD_VERS_FLAG_PTR64;
    03007 #else
    03008 #error( "unknown target machine" );
    03009 #endif
    03010
    03011     //
    03012     // address of the loader table
    03013     //
    03014     m->u.GetVersion64.PsLoadedModuleList = (ULONG64)(LONG64)(LONG_PTR)&PsLoadedModuleList;
    03015
    03016     //
    03017     // If the debugger is being initialized during boot, PsNtosImageBase
    03018     // and PsLoadedModuleList are not yet valid.  KdInitSystem got
    03019     // the image base from the loader block.
    03020     // On the other hand, if the debugger was initialized by a bugcheck,
    03021     // it didn't get a loader block to look at, but the system was
    03022     // running so the other variables are valid.
    03023     //
    03024
    03025     if (KdpNtosImageBase) {
    03026         m->u.GetVersion64.KernBase = (ULONG64)(LONG64)(LONG_PTR)KdpNtosImageBase;
    03027     } else {
    03028         m->u.GetVersion64.KernBase = (ULONG64)(LONG64)(LONG_PTR)PsNtosImageBase;
    03029     }
    03030
    03031     m->u.GetVersion64.DebuggerDataList = (ULONG64)(LONG64)(LONG_PTR)&KdpDebuggerDataListHead;
    03032
    03033     //
    03034     // the usual stuff
    03035     //
    03036     m->ReturnStatus = STATUS_SUCCESS;
    03037     m->ApiNumber = DbgKdGetVersionApi;
    03038
    03039     KdpSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
    03040                   &messageHeader,
    03041                   NULL
    03042                  );
    03043
    03044     return;
    03045 } // KdGetVersion
    03046
    03047
    03048 NTSTATUS
    03049 KdpNotSupported(
    03050     IN PDBGKD_MANIPULATE_STATE64 m
    03051     )
    03052
    03053 /*++
    03054
    03055 Routine Description:
    03056
    03057     This routine returns STATUS_UNSUCCESSFUL to the debugger
    03058
    03059 Arguments:
    03060
    03061     m - Supplies a DBGKD_MANIPULATE_STATE64 struct to answer with
    03062
    03063 Return Value:
    03064
    03065     0, to indicate that the system should not continue
    03066
    03067 --*/
    03068
    03069 {
    03070     STRING          MessageHeader;
    03071
    03072     //
    03073     // setup packet
    03074     //
    03075     MessageHeader.Length = sizeof(*m);
    03076     MessageHeader.Buffer = (PCHAR)m;
    03077     m->ReturnStatus = STATUS_UNSUCCESSFUL;
    03078
    03079     //
    03080     // send back our response
    03081     //
    03082     KdpSendPacket(
    03083         PACKET_TYPE_KD_STATE_MANIPULATE,
    03084         &MessageHeader,
    03085         NULL
    03086         );
    03087
    03088     //
    03089     // return the caller's continue status value.  if this is a non-zero
    03090     // value the system is continued using this value as the continuestatus.
    03091     //
    03092     return 0;
    03093 } // KdpNotSupported
    03094
    03095
    03096 VOID
    03097 KdpCauseBugCheck(
    03098     IN PDBGKD_MANIPULATE_STATE64 m
    03099     )
    03100
    03101 /*++
    03102
    03103 Routine Description:
    03104
    03105     This routine causes a bugcheck.  It is used for testing the debugger.
    03106
    03107 Arguments:
    03108
    03109     m - Supplies the state manipulation message.
    03110
    03111 Return Value:
    03112
    03113     None.
    03114
    03115 --*/
    03116
    03117 {
    03118
    03119     KeBugCheckEx( MANUALLY_INITIATED_CRASH, 0, 0, 0, 0 );
    03120
    03121 } // KdCauseBugCheck
    03122
    03123
    03124 NTSTATUS
    03125 KdpWriteBreakPointEx(
    03126     IN PDBGKD_MANIPULATE_STATE64 m,
    03127     IN PSTRING AdditionalData,
    03128     IN PCONTEXT Context
    03129     )
    03130
    03131 /*++
    03132
    03133 Routine Description:
    03134
    03135     This function is called in response of a write breakpoint state 'ex'
    03136     manipulation message.  Its function is to clear breakpoints, write
    03137     new breakpoints, and continue the target system.  The clearing of
    03138     breakpoints is conditional based on the presence of breakpoint handles.
    03139     The setting of breakpoints is conditional based on the presence of
    03140     valid, non-zero, addresses.  The continueing of the target system
    03141     is conditional based on a non-zero continuestatus.
    03142
    03143     This api allows a debugger to clear breakpoints, add new breakpoint,
    03144     and continue the target system all in one api packet.  This reduces the
    03145     amount of traffic across the wire and greatly improves source stepping.
    03146
    03147
    03148 Arguments:
    03149
    03150     m - Supplies the state manipulation message.
    03151
    03152     AdditionalData - Supplies any additional data for the message.
    03153
    03154     Context - Supplies the current context.
    03155
    03156 Return Value:
    03157
    03158     None.
    03159
    03160 --*/
    03161
    03162 {
    03163     PDBGKD_BREAKPOINTEX       a = &m->u.BreakPointEx;
    03164     PDBGKD_WRITE_BREAKPOINT64 b;
    03165     STRING                    MessageHeader;
    03166     ULONG                     i;
    03167     DBGKD_WRITE_BREAKPOINT64  BpBuf[BREAKPOINT_TABLE_SIZE];
    03168
    03169
    03170     MessageHeader.Length = sizeof(*m);
    03171     MessageHeader.Buffer = (PCHAR)m;
    03172
    03173     //
    03174     // verify that the packet size is correct
    03175     //
    03176     if (AdditionalData->Length !=
    03177                          a->BreakPointCount*sizeof(DBGKD_WRITE_BREAKPOINT64)) {
    03178         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    03179         KdpSendPacket(
    03180                       PACKET_TYPE_KD_STATE_MANIPULATE,
    03181                       &MessageHeader,
    03182                       AdditionalData
    03183                       );
    03184         return m->ReturnStatus;
    03185     }
    03186
    03187     KdpMoveMemory((PUCHAR)BpBuf,
    03188                   AdditionalData->Buffer,
    03189                   a->BreakPointCount*sizeof(DBGKD_WRITE_BREAKPOINT64));
    03190
    03191     //
    03192     // assume success
    03193     //
    03194     m->ReturnStatus = STATUS_SUCCESS;
    03195
    03196     //
    03197     // loop thru the breakpoint handles passed in from the debugger and
    03198     // clear any breakpoint that has a non-zero handle
    03199     //
    03200     b = BpBuf;
    03201     for (i=0; i<a->BreakPointCount; i++,b++) {
    03202         if (b->BreakPointHandle) {
    03203             if (!KdpDeleteBreakpoint(b->BreakPointHandle)) {
    03204                 m->ReturnStatus = STATUS_UNSUCCESSFUL;
    03205             }
    03206             b->BreakPointHandle = 0;
    03207         }
    03208     }
    03209
    03210     //
    03211     // loop thru the breakpoint addesses passed in from the debugger and
    03212     // add any new breakpoints that have a non-zero address
    03213     //
    03214     b = BpBuf;
    03215     for (i=0; i<a->BreakPointCount; i++,b++) {
    03216         if (b->BreakPointAddress) {
    03217             b->BreakPointHandle = KdpAddBreakpoint( (PVOID)b->BreakPointAddress );
    03218             if (!b->BreakPointHandle) {
    03219                 m->ReturnStatus = STATUS_UNSUCCESSFUL;
    03220             }
    03221         }
    03222     }
    03223
    03224     //
    03225     // send back our response
    03226     //
    03227
    03228     KdpMoveMemory(AdditionalData->Buffer,
    03229                   (PUCHAR)BpBuf,
    03230                   a->BreakPointCount*sizeof(DBGKD_WRITE_BREAKPOINT64));
    03231
    03232     KdpSendPacket(
    03233                   PACKET_TYPE_KD_STATE_MANIPULATE,
    03234                   &MessageHeader,
    03235                   AdditionalData
    03236                   );
    03237
    03238     //
    03239     // return the caller's continue status value.  if this is a non-zero
    03240     // value the system is continued using this value as the continuestatus.
    03241     //
    03242     return a->ContinueStatus;
    03243 }
    03244
    03245
    03246 VOID
    03247 KdpRestoreBreakPointEx(
    03248     IN PDBGKD_MANIPULATE_STATE64 m,
    03249     IN PSTRING AdditionalData,
    03250     IN PCONTEXT Context
    03251     )
    03252
    03253 /*++
    03254
    03255 Routine Description:
    03256
    03257     This function is called in response of a restore breakpoint state 'ex'
    03258     manipulation message.  Its function is to clear a list of breakpoints.
    03259
    03260 Arguments:
    03261
    03262     m - Supplies the state manipulation message.
    03263
    03264     AdditionalData - Supplies any additional data for the message.
    03265
    03266     Context - Supplies the current context.
    03267
    03268 Return Value:
    03269
    03270     None.
    03271
    03272 --*/
    03273
    03274 {
    03275     PDBGKD_BREAKPOINTEX         a = &m->u.BreakPointEx;
    03276     PDBGKD_RESTORE_BREAKPOINT   b;
    03277     STRING                      MessageHeader;
    03278     ULONG                       i;
    03279     DBGKD_RESTORE_BREAKPOINT    BpBuf[BREAKPOINT_TABLE_SIZE];
    03280
    03281
    03282     MessageHeader.Length = sizeof(*m);
    03283     MessageHeader.Buffer = (PCHAR)m;
    03284
    03285     //
    03286     // verify that the packet size is correct
    03287     //
    03288     if (AdditionalData->Length !=
    03289                        a->BreakPointCount*sizeof(DBGKD_RESTORE_BREAKPOINT)) {
    03290         m->ReturnStatus = STATUS_UNSUCCESSFUL;
    03291         KdpSendPacket(
    03292                       PACKET_TYPE_KD_STATE_MANIPULATE,
    03293                       &MessageHeader,
    03294                       AdditionalData
    03295                       );
    03296         return;
    03297     }
    03298
    03299     KdpMoveMemory((PUCHAR)BpBuf,
    03300                   AdditionalData->Buffer,
    03301                   a->BreakPointCount*sizeof(DBGKD_RESTORE_BREAKPOINT));
    03302
    03303     //
    03304     // assume success
    03305     //
    03306     m->ReturnStatus = STATUS_SUCCESS;
    03307
    03308     //
    03309     // loop thru the breakpoint handles passed in from the debugger and
    03310     // clear any breakpoint that has a non-zero handle
    03311     //
    03312     b = BpBuf;
    03313     for (i=0; i<a->BreakPointCount; i++,b++) {
    03314         if (!KdpDeleteBreakpoint(b->BreakPointHandle)) {
    03315             m->ReturnStatus = STATUS_UNSUCCESSFUL;
    03316         }
    03317     }
    03318
    03319     //
    03320     // send back our response
    03321     //
    03322     KdpSendPacket(
    03323                   PACKET_TYPE_KD_STATE_MANIPULATE,
    03324                   &MessageHeader,
    03325                   AdditionalData
    03326                   );
    03327 }
    03328
    03329 VOID
    03330 KdDisableDebugger(
    03331     VOID
    03332     )
    03333 /*++
    03334
    03335 Routine Description:
    03336
    03337     This function is called to disable the debugger.
    03338
    03339 Arguments:
    03340
    03341     None.
    03342
    03343 Return Value:
    03344
    03345     None.
    03346
    03347 --*/
    03348
    03349 {
    03350     KIRQL oldIrql ;
    03351
    03352     KeRaiseIrql(DISPATCH_LEVEL, &oldIrql) ;
    03353     KdpPortLock();
    03354
    03355     if (!KdDisableCount) {
    03356
    03357         KdPreviouslyEnabled = KdDebuggerEnabled && (!KdPitchDebugger) ;
    03358         if (KdDebuggerEnabled) {
    03359
    03360             KdpSuspendAllBreakpoints() ;
    03361             KiDebugRoutine = KdpStub;
    03362             KdDebuggerEnabled = FALSE ;
    03363         }
    03364     }
    03365     KdDisableCount++ ;
    03366     KdpPortUnlock();
    03367     KeLowerIrql(oldIrql);
    03368 }
    03369
    03370 VOID
    03371 KdEnableDebugger(
    03372    VOID
    03373    )
    03374 /*++
    03375
    03376 Routine Description:
    03377
    03378     This function is called to reenable the debugger after a call to
    03379     KdDisableDebugger.
    03380
    03381 Arguments:
    03382
    03383     None.
    03384
    03385 Return Value:
    03386
    03387     None.
    03388
    03389 --*/
    03390 {
    03391     KIRQL oldIrql ;
    03392
    03393     KeRaiseIrql(DISPATCH_LEVEL, &oldIrql) ;
    03394     KdpPortLock();
    03395
    03396     ASSERT(KdDisableCount > 0) ;
    03397     KdDisableCount-- ;
    03398
    03399     if (!KdDisableCount) {
    03400         if (KdPreviouslyEnabled) {
    03401
    03402             //
    03403             // Ugly HACKHACK - Make sure the timers aren't reset.
    03404             //
    03405             PoHiberInProgress = TRUE ;
    03406             KdInitSystem(NULL, FALSE) ;
    03407             KdpRestoreAllBreakpoints();
    03408             PoHiberInProgress = FALSE ;
    03409         }
    03410     }
    03411     KdpPortUnlock();
    03412     KeLowerIrql(oldIrql);
    03413 }
    03414
    03415
    03416 VOID
    03417 KdpSearchMemory(
    03418     IN PDBGKD_MANIPULATE_STATE64 m,
    03419     IN PSTRING AdditionalData,
    03420     IN PCONTEXT Context
    03421     )
    03422
    03423 /*++
    03424
    03425 Routine Description:
    03426
    03427     This function implements a memory pattern searcher.  This will
    03428     find an instance of a pattern that begins in the range
    03429     SearchAddress..SearchAddress+SearchLength.  The pattern may
    03430     end outside of the range.
    03431
    03432 Arguments:
    03433
    03434     m - Supplies the state manipulation message.
    03435
    03436     AdditionalData - Supplies the pattern to search for
    03437
    03438     Context - Supplies the current context.
    03439
    03440 Return Value:
    03441
    03442     None.
    03443
    03444 --*/
    03445
    03446 {
    03447     PUCHAR Pattern = AdditionalData->Buffer;
    03448     ULONG_PTR StartAddress = (ULONG_PTR)m->u.SearchMemory.SearchAddress;
    03449     ULONG_PTR EndAddress = (ULONG_PTR)(StartAddress + m->u.SearchMemory.SearchLength);
    03450     ULONG PatternLength = m->u.SearchMemory.PatternLength;
    03451
    03452     STRING MessageHeader;
    03453     ULONG MaskIndex;
    03454     PUCHAR PatternTail;
    03455     PUCHAR DataTail;
    03456     ULONG TailLength;
    03457     ULONG Data;
    03458     ULONG FirstWordPattern[4];
    03459     ULONG FirstWordMask[4];
    03460
    03461
    03462     //
    03463     // On failure, return STATUS_NO_MORE_ENTRIES.  DON'T RETURN
    03464     // STATUS_UNSUCCESSFUL!  That return status indicates that the
    03465     // operation is not supported, and the debugger will fall back
    03466     // to a debugger-side search.
    03467     //
    03468
    03469     m->ReturnStatus = STATUS_NO_MORE_ENTRIES;
    03470
    03471     //
    03472     // Do a fast search for the beginning of the pattern
    03473     //
    03474
    03475     if (PatternLength > 3) {
    03476         FirstWordMask[0] = 0xffffffff;
    03477     } else {
    03478         FirstWordMask[0] = 0xffffffff >> (8*(4-PatternLength));
    03479     }
    03480
    03481     FirstWordMask[1] = FirstWordMask[0] << 8;
    03482     FirstWordMask[2] = FirstWordMask[1] << 8;
    03483     FirstWordMask[3] = FirstWordMask[2] << 8;
    03484
    03485     FirstWordPattern[0] = 0;
    03486     KdpQuickMoveMemory((PVOID)FirstWordPattern,
    03487                        Pattern,
    03488                        PatternLength < 5 ? PatternLength : 4);
    03489
    03490     FirstWordPattern[1] = FirstWordPattern[0] << 8;
    03491     FirstWordPattern[2] = FirstWordPattern[1] << 8;
    03492     FirstWordPattern[3] = FirstWordPattern[2] << 8;
    03493
    03494
    03495 /*
    03496 {
    03497     int i;
    03498     for (i = 0; i < (int)PatternLength; i++) {
    03499         KdpDprintf("%08x: %02x\n", &Pattern[i], Pattern[i]);
    03500     }
    03501     for (i = 0; i < 4; i++) {
    03502         KdpDprintf("%d: %08x %08x\n", i, FirstWordPattern[i], FirstWordMask[i]);
    03503     }
    03504 }
    03505 */
    03506
    03507
    03508
    03509     //
    03510     // Get starting mask
    03511     //
    03512
    03513     MaskIndex = (ULONG) (StartAddress & 3);
    03514     StartAddress = StartAddress & ~3;
    03515
    03516     //
    03517     // check that the starting page is available
    03518     //
    03519
    03520     if (MmDbgReadCheck((PVOID)StartAddress) == NULL) {
    03521         StartAddress = (StartAddress + PAGE_SIZE) & ~(PAGE_SIZE-1);
    03522         MaskIndex = 0;
    03523     }
    03524
    03525     while (StartAddress < EndAddress) {
    03526
    03527         //
    03528         // check when starting a new page
    03529         //
    03530         if ((StartAddress & (PAGE_SIZE-1)) == 0) {
    03531             if (MmDbgReadCheck((PVOID)StartAddress) == NULL) {
    03532                 StartAddress = StartAddress + PAGE_SIZE;
    03533                 continue;
    03534             }
    03535         }
    03536
    03537         //
    03538         // search for a match in each of the 4 starting positions
    03539         //
    03540
    03541         Data = *(ULONG*)StartAddress;
    03542 //KdpDprintf("\n%08x: %08x ", StartAddress, Data);
    03543
    03544         for ( ; MaskIndex < 4; MaskIndex++) {
    03545 //KdpDprintf(" %d", MaskIndex);
    03546
    03547             if ( (Data & FirstWordMask[MaskIndex]) == FirstWordPattern[MaskIndex]) {
    03548
    03549                 //
    03550                 // first word matched
    03551                 //
    03552
    03553                 if ( (4-MaskIndex) >= PatternLength ) {
    03554
    03555                     //
    03556                     // string is all in this word; good match
    03557                     //
    03558 //KdpDprintf(" %d hit, complete\n", MaskIndex);
    03559
    03560                     m->u.SearchMemory.FoundAddress = StartAddress + MaskIndex;
    03561                     m->ReturnStatus = STATUS_SUCCESS;
    03562                     goto done;
    03563
    03564                 } else {
    03565
    03566                     //
    03567                     // string is longer; see if tail matches
    03568                     //
    03569 //KdpDprintf(" %d hit, check tail\n", MaskIndex);
    03570
    03571                     PatternTail = Pattern + 4 - MaskIndex;
    03572                     DataTail = (PUCHAR)StartAddress + 4;
    03573                     TailLength = PatternLength - 4 + MaskIndex;
    03574
    03575 //KdpDprintf("Pattern == %08x\n", Pattern);
    03576 //KdpDprintf("PatternTail == %08x\n", PatternTail);
    03577 //KdpDprintf("DataTail == %08x\n", DataTail);
    03578
    03579                     while (TailLength) {
    03580                         if ( ((ULONG_PTR)DataTail & (PAGE_SIZE-1)) == 0 &&
    03581                              MmDbgReadCheck(DataTail) == FALSE) {
    03582 //KdpDprintf("Tail failed: page not present at %08x\n", DataTail);
    03583                             break;
    03584                         } else
    03585 {
    03586 //KdpDprintf("D: %02x  P: %02x\n", *DataTail, *PatternTail);
    03587
    03588                         if (*DataTail != *PatternTail) {
    03589 //KdpDprintf("Tail failed at %08x\n", DataTail);
    03590                             break;
    03591                         } else {
    03592                             DataTail++;
    03593                             PatternTail++;
    03594                             TailLength--;
    03595                         }
    03596 }
    03597                     }
    03598
    03599                     if (TailLength == 0) {
    03600
    03601                         //
    03602                         // A winner
    03603                         //
    03604
    03605                         m->u.SearchMemory.FoundAddress = StartAddress + MaskIndex;
    03606                         m->ReturnStatus = STATUS_SUCCESS;
    03607                         goto done;
    03608
    03609                     }
    03610                 }
    03611             }
    03612         }
    03613
    03614         StartAddress += 4;
    03615         MaskIndex = 0;
    03616     }
    03617
    03618 done:
    03619 //KdpDprintf("\n");
    03620     MessageHeader.Length = sizeof(*m);
    03621     MessageHeader.Buffer = (PCHAR)m;
    03622
    03623     KdpSendPacket(
    03624         PACKET_TYPE_KD_STATE_MANIPULATE,
    03625         &MessageHeader,
    03626         NULL
    03627         );
    03628
    03629 }
    03630
    03631
    03632 VOID
    03633 KdpCheckLowMemory(
    03634     IN PDBGKD_MANIPULATE_STATE64 Message
    03635     )
    03636
    03637 /*++
    03638
    03639 Routine Description:
    03640
    03641
    03642 Arguments:
    03643
    03644     Message - Supplies the state manipulation message.
    03645
    03646 Return Value:
    03647
    03648     None.
    03649
    03650 Description:
    03651
    03652     This function gets called when the !chklowmem
    03653     debugger extension is used.
    03654
    03655 --*/
    03656
    03657 {
    03658 //+silviuc: move to a header
    03659 #if defined (_X86PAE_)
    03660     LOGICAL
    03661         MiCheckPhysicalPagePattern (
    03662         PFN_NUMBER Page,
    03663         PULONG CorruptionOffset
    03664         );
    03665
    03666     extern PFN_NUMBER MmLowestPhysicalPage;
    03667     extern PFN_NUMBER MmHighestPhysicalPage;
    03668     extern LOGICAL MiNoLowMemory;
    03669 #endif // #if defined (_X86PAE_)
    03670 //-silviuc
    03671
    03672     STRING MessageHeader;
    03673     PFN_NUMBER Page;
    03674     PHYSICAL_ADDRESS P;
    03675     PVOID64 VirtualAddress;
    03676     ULONG CorruptionOffset;
    03677
    03678     Message->ReturnStatus = STATUS_SUCCESS;
    03679     MessageHeader.Length = sizeof(*Message);
    03680     MessageHeader.Buffer = (PCHAR)Message;
    03681
    03682     if (KdpSearchPhysicalMemoryRequested()) {
    03683
    03684         //
    03685         // This is a !search kd extension call.
    03686         //
    03687
    03688         KdpSearchPhysicalPageRange();
    03689     }
    03690     else {
    03691
    03692         //
    03693         // Check PAE low physical memory
    03694         //
    03695
    03696 #if defined (_X86PAE_)
    03697
    03698         if (MiNoLowMemory) {
    03699
    03700             for (Page = MmLowestPhysicalPage;
    03701                 Page < MmHighestPhysicalPage && Page < 1024 * 1024;
    03702                 Page += 1) {
    03703
    03704
    03705                 if (! MiCheckPhysicalPagePattern (Page, &CorruptionOffset)) {
    03706                     Message->ReturnStatus = Page;
    03707                     break;
    03708                 }
    03709             }
    03710         }
    03711
    03712 #endif // #if defined (_X86PAE_)
    03713     }
    03714
    03715     //
    03716     // Acknowledge the packet received.
    03717     //
    03718
    03719     KdpSendPacket (
    03720         PACKET_TYPE_KD_STATE_MANIPULATE,
    03721         &MessageHeader,
    03722         NULL
    03723         );
    03724 }
    03725
    03726
    03727
    03728 //
    03729 // !search support routines
    03730 //
    03731
    03732
    03733
    03734 ULONG
    03735 KdpSearchHammingDistance (
    03736     ULONG_PTR Left,
    03737     ULONG_PTR Right
    03738     )
    03739 /*++
    03740
    03741 Routine Description:
    03742
    03743     This routine computes the Hamming distance (# of positions where the
    03744     values are different).
    03745
    03746     If this function becomes a bottleneck we should switch to a function
    03747     table version.
    03748
    03749 Arguments:
    03750
    03751     Left, Right operand.
    03752
    03753 Return Value:
    03754
    03755     Hamming distance.
    03756
    03757 Environment:
    03758
    03759     Any.
    03760
    03761 --*/
    03762
    03763 {
    03764     ULONG_PTR Value;
    03765     ULONG Index;
    03766     ULONG Distance;
    03767
    03768     Value = Left ^ Right;
    03769     Distance = 0;
    03770
    03771     for (Index = 0; Index < 8 * sizeof(ULONG_PTR); Index++) {
    03772
    03773         if ((Value & (ULONG_PTR)0x01)) {
    03774
    03775             Distance += 1;
    03776         }
    03777
    03778         Value >>= 1;
    03779     }
    03780
    03781     return Distance;
    03782 }
    03783
    03784
    03785
    03786 LOGICAL
    03787 KdpSearchPhysicalPage (
    03788     IN PFN_NUMBER PageFrameIndex,
    03789     ULONG_PTR RangeStart,
    03790     ULONG_PTR RangeEnd,
    03791     ULONG Flags
    03792     )
    03793 /*++
    03794
    03795 Routine Description:
    03796
    03797     This routine searches the physical page corresponding to a
    03798     certain PFN index for any ULONG_PTR values in range [Start..End].
    03799
    03800 Arguments:
    03801
    03802     PageFrameIndex - PFN index
    03803
    03804     RangeStart - lowest possible value searched for
    03805
    03806     RangeEnd - highest possible value searched for
    03807
    03808     Flags - flags to control the search
    03809
    03810 Return Value:
    03811
    03812     TRUE if a hit has been found, FALSE otherwise.
    03813     The function stops after the first hit in the page is
    03814     encountered and the infromation related to the hit (PFN index,
    03815     offset, corrsponding VA) is registered in the hit database.
    03816
    03817 Environment:
    03818
    03819     Call triggered only from Kd extension.
    03820
    03821 --*/
    03822
    03823 {
    03824     PCHAR Va;
    03825     ULONG Index;
    03826     PHYSICAL_ADDRESS Pa;
    03827     ULONG_PTR Value;
    03828
    03829     //
    03830     // Map the physical page using the debug PTE.
    03831     //
    03832
    03833     Pa.QuadPart = ((ULONGLONG)PageFrameIndex) << PAGE_SHIFT;
    03834
    03835     Va = (PCHAR) MmDbgTranslatePhysicalAddress64 (Pa);
    03836
    03837     for (Index = 0; Index < PAGE_SIZE - sizeof(ULONG_PTR); Index += 1, Va += 1) {
    03838
    03839         Value = *((PULONG_PTR)Va);
    03840
    03841         if ((Value >= RangeStart && Value <= RangeEnd)
    03842             || KdpSearchHammingDistance(Value, RangeStart) == 1) {
    03843
    03844             if (KdpSearchPageHitIndex < SEARCH_PAGE_HIT_DATABASE_SIZE) {
    03845
    03846                 KdpSearchPageHits[KdpSearchPageHitIndex] = PageFrameIndex;
    03847                 KdpSearchPageHitOffsets[KdpSearchPageHitIndex] = Index;
    03848
    03849                 KdpSearchPageHitIndex += 1;
    03850             }
    03851
    03852             if ((Flags & KDP_SEARCH_ALL_OFFSETS_IN_PAGE)) {
    03853
    03854                 continue;
    03855             }
    03856             else {
    03857
    03858                 return TRUE;
    03859             }
    03860         }
    03861     }
    03862
    03863     return FALSE;
    03864 }
    03865
    03866
    03867
    03868 LOGICAL
    03869 KdpSearchPhysicalMemoryRequested (
    03870     VOID
    03871     )
    03872 /*++
    03873
    03874 Routine Description:
    03875
    03876     This routine determines if a physical range search has been
    03877     requested. This is controlled by a global variable set in
    03878     the `!search' debug extension.
    03879
    03880 Arguments:
    03881
    03882     None
    03883
    03884 Return Value:
    03885
    03886     TRUE if physical range search was requested.
    03887
    03888
    03889 Environment:
    03890
    03891     Call triggered only from Kd extension.
    03892
    03893 --*/
    03894 {
    03895     if (KdpSearchInProgress) {
    03896
    03897         return TRUE;
    03898     }
    03899     else {
    03900
    03901         return FALSE;
    03902     }
    03903
    03904 }
    03905
    03906
    03907
    03908 LOGICAL
    03909 KdpSearchPhysicalPageRange (
    03910     VOID
    03911     )
    03912 /*++
    03913
    03914 Routine Description:
    03915
    03916     This routine will start a search in a range of physical pages in case
    03917     `KdpSearchInProgress' is true. the parameters for the search are picked up
    03918     from global vairiables that are set inside a kernel debugger extension.
    03919
    03920 Arguments:
    03921
    03922     None
    03923
    03924 Return Value:
    03925
    03926     TRUE if the function executed a search and FALSE otherwise.
    03927     The results of the search are specified in the KdpSearchPageHits
    03928     and related variables. this global variables offers the mechanism
    03929     for the debugger extension to pickup the results of the search.
    03930
    03931
    03932 Environment:
    03933
    03934     Call triggered only from Kd extension.
    03935
    03936     Note. The !search extension make sure that the range requested
    03937     is part of the system memory therefore we do not have to
    03938     worry about sparse PFN databases here.
    03939
    03940 --*/
    03941
    03942 {
    03943     PFN_NUMBER CurrentFrame;
    03944     ULONG Flags;
    03945
    03946     //
    03947     // The debugger extension is supposed to set KdpSearchInProgress
    03948     // to TRUE if a search is requested.
    03949     //
    03950
    03951     if (!KdpSearchInProgress) {
    03952
    03953         return FALSE;
    03954     }
    03955
    03956
    03957     Flags = 0;
    03958
    03959     //
    03960     // If the search range is only one page we will give all
    03961     // hits inside a page. By default we get only the first hit inside
    03962     // a page.
    03963     //
    03964
    03965     if (KdpSearchEndPageFrame == KdpSearchStartPageFrame) {
    03966
    03967         KdpSearchEndPageFrame += 1;
    03968
    03969         Flags |= KDP_SEARCH_ALL_OFFSETS_IN_PAGE;
    03970     }
    03971
    03972     for (CurrentFrame = KdpSearchStartPageFrame;
    03973          CurrentFrame < KdpSearchEndPageFrame;
    03974          CurrentFrame += 1) {
    03975
    03976         KdpSearchPhysicalPage (CurrentFrame,
    03977                               KdpSearchAddressRangeStart,
    03978                               KdpSearchAddressRangeEnd,
    03979                               Flags);
    03980
    03981     }
    03982
    03983     return TRUE;
    03984 }
    03985
    03986