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

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