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

Generated on Sat May 15 19:40:33 2004 for test by doxygen 1.3.7