test: kdtrap.c Source File

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

# kdtrap.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004 Copyright (c) 1998  Intel Corporation
    00005
    00006 Module Name:
    00007
    00008     kdtrap.c
    00009
    00010 Abstract:
    00011
    00012     This module contains code to implement the target side of the portable
    00013     kernel debugger.
    00014
    00015 Author:
    00016
    00017     David N. Cutler 27-July-1990
    00018
    00019 Revision History:
    00020
    00021 --*/
    00022
    00023 #include "kdp.h"
    00024 #ifdef _GAMBIT_
    00025 #include "ssc.h"
    00026 #endif // _GAMBIT_
    00027
    00028
    00029 BOOLEAN
    00030 KdpTrap (
    00031     IN PKTRAP_FRAME TrapFrame,
    00032     IN PKEXCEPTION_FRAME ExceptionFrame,
    00033     IN PEXCEPTION_RECORD ExceptionRecord,
    00034     IN PCONTEXT ContextRecord,
    00035     IN KPROCESSOR_MODE PreviousMode,
    00036     IN BOOLEAN SecondChance
    00037     )
    00038
    00039 /*++
    00040
    00041 Routine Description:
    00042
    00043     This routine is called whenever a exception is dispatched and the kernel
    00044     debugger is active.
    00045
    00046 Arguments:
    00047
    00048     TrapFrame - Supplies a pointer to a trap frame that describes the
    00049         trap.
    00050
    00051     ExceptionFrame - Supplies a pointer to a exception frame that describes
    00052         the trap.
    00053
    00054     ExceptionRecord - Supplies a pointer to an exception record that
    00055         describes the exception.
    00056
    00057     ContextRecord - Supplies the context at the time of the exception.
    00058
    00059     PreviousMode - Supplies the previous processor mode.
    00060
    00061     SecondChance - Supplies a boolean value that determines whether this is
    00062         the second chance (TRUE) that the exception has been raised.
    00063
    00064 Return Value:
    00065
    00066     A value of TRUE is returned if the exception is handled. Otherwise a
    00067     value of FALSE is returned.
    00068
    00069 --*/
    00070
    00071 {
    00072
    00073     BOOLEAN Completion = FALSE;
    00074     BOOLEAN Enable;
    00075     BOOLEAN UnloadSymbols = FALSE;
    00076     ULONGLONG OldStIIP, OldStIPSR;
    00077     STRING Input;
    00078     STRING Output;
    00079     PKPRCB Prcb;
    00080
    00081     //
    00082     // Synchronize processor execution, save processor state, enter debugger,
    00083     // and flush the current TB.
    00084     //
    00085
    00086     KeFlushCurrentTb();
    00087
    00088     //
    00089     // If this is a breakpoint instruction, then check to determine if is
    00090     // an internal command.
    00091     //
    00092
    00093     if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
    00094         (ExceptionRecord->ExceptionInformation[0] >= DEBUG_PRINT_BREAKPOINT)) {
    00095
    00096         //
    00097         // Switch on the breakpoint code.
    00098         //
    00099
    00100         switch (ExceptionRecord->ExceptionInformation[0]) {
    00101
    00102             //
    00103             // Print a debug string.
    00104             //
    00105             // Arguments: IA64 passes arguments via RSE not GR's. Since arguments are not
    00106             //            part of CONTEXT struct, they need to be copies Temp registers.
    00107             //            (see NTOS/RTL/IA64/DEBUGSTB.S)
    00108             //
    00109             //   T0 - Supplies a pointer to an output string buffer.
    00110             //   T1 - Supplies the length of the output string buffer.
    00111             //
    00112
    00113         case DEBUG_PRINT_BREAKPOINT:
    00114
    00115             //
    00116             // Advance to next instruction slot so that the BREAK instruction
    00117             // does not get re-executed
    00118             //
    00119
    00120             RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
    00121                                ContextRecord->StIPSR,
    00122                                ContextRecord->StIIP);
    00123
    00124             Output.Buffer = (PCHAR)ContextRecord->IntT0;
    00125             Output.Length = (USHORT)ContextRecord->IntT1;
    00126
    00127             KdLogDbgPrint(&Output);
    00128
    00129             if (KdDebuggerNotPresent == FALSE) {
    00130
    00131                 Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
    00132                 if (KdpPrintString(&Output)) {
    00133                     ContextRecord->IntV0 = (ULONG)STATUS_BREAKPOINT;
    00134
    00135                 } else {
    00136                     ContextRecord->IntV0 = (ULONG)STATUS_SUCCESS;
    00137                 }
    00138                 KdExitDebugger(Enable);
    00139
    00140             } else {
    00141                 ContextRecord->IntV0 = (ULONG)STATUS_DEVICE_NOT_CONNECTED;
    00142             }
    00143
    00144             return TRUE;
    00145
    00146             //
    00147             // Print a debug prompt string, then input a string.
    00148             //
    00149             //   T0 - Supplies a pointer to an output string buffer.
    00150             //   T1 - Supplies the length of the output string buffer..
    00151             //   T2 - supplies a pointer to an input string buffer.
    00152             //   T3 - Supplies the length of the input string bufffer.
    00153             //
    00154
    00155         case DEBUG_PROMPT_BREAKPOINT:
    00156
    00157             //
    00158             // Advance to next instruction slot so that the BREAK instruction
    00159             // does not get re-executed
    00160             //
    00161
    00162             RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
    00163                                ContextRecord->StIPSR,
    00164                                ContextRecord->StIIP);
    00165
    00166             Output.Buffer = (PCHAR)ContextRecord->IntT0;
    00167             Output.Length = (USHORT)ContextRecord->IntT1;
    00168             Input.Buffer = (PCHAR)ContextRecord->IntT2;
    00169             Input.MaximumLength = (USHORT)ContextRecord->IntT3;
    00170
    00171             KdLogDbgPrint(&Output);
    00172
    00173             Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
    00174
    00175             KdpPromptString(&Output, &Input);
    00176
    00177             ContextRecord->IntV0 = Input.Length;
    00178
    00179             KdExitDebugger(Enable);
    00180             return TRUE;
    00181
    00182             //
    00183             // Load the symbolic information for an image.
    00184             //
    00185             // Arguments:
    00186             //
    00187             //    T0 - Supplies a pointer to an output string descriptor.
    00188             //    T1 - Supplies a the base address of the image.
    00189             //
    00190
    00191         case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT:
    00192             UnloadSymbols = TRUE;
    00193
    00194             //
    00195             // Fall through
    00196             //
    00197
    00198         case DEBUG_LOAD_SYMBOLS_BREAKPOINT:
    00199
    00200             //
    00201             // Advance to next instruction slot so that the BREAK instruction
    00202             // does not get re-executed
    00203             //
    00204
    00205             Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
    00206             Prcb = KeGetCurrentPrcb();
    00207             KiSaveProcessorControlState(&Prcb->ProcessorState);
    00208             OldStIPSR = ContextRecord->StIPSR;
    00209             OldStIIP = ContextRecord->StIIP;
    00210             RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
    00211                           ContextRecord,
    00212                           sizeof(CONTEXT));
    00213
    00214             if (KdDebuggerNotPresent == FALSE) {
    00215                 KdpReportLoadSymbolsStateChange((PSTRING)ContextRecord->IntT0,
    00216                                                 (PKD_SYMBOLS_INFO) ContextRecord->IntT1,
    00217                                                 UnloadSymbols,
    00218                                                 &Prcb->ProcessorState.ContextFrame);
    00219
    00220             }
    00221
    00222             RtlCopyMemory(ContextRecord,
    00223                           &Prcb->ProcessorState.ContextFrame,
    00224                           sizeof(CONTEXT));
    00225
    00226             KiRestoreProcessorControlState(&Prcb->ProcessorState);
    00227             KdExitDebugger(Enable);
    00228
    00229             //
    00230             // If the kernel debugger did not update the IP, then increment
    00231             // past the breakpoint instruction.
    00232             //
    00233
    00234             if ((ContextRecord->StIIP == OldStIIP) &&
    00235                 ((ContextRecord->StIPSR & IPSR_RI_MASK) == (OldStIPSR & IPSR_RI_MASK))) {
    00236                 RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
    00237                                ContextRecord->StIPSR,
    00238                                ContextRecord->StIIP);
    00239             }
    00240
    00241             return TRUE;
    00242
    00243             //
    00244             // Kernel breakin break
    00245             //
    00246
    00247         case BREAKIN_BREAKPOINT:
    00248
    00249            //
    00250            // Advance to next instruction slot so that the BREAK instruction
    00251            // does not get re-executed
    00252            //
    00253
    00254            RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
    00255                               ContextRecord->StIPSR,
    00256                               ContextRecord->StIIP);
    00257            break;
    00258
    00259             //
    00260             // Unknown internal command.
    00261             //
    00262
    00263         default:
    00264             break;
    00265         }
    00266
    00267     }
    00268
    00269     //
    00270     // Get here if single step or BREAKIN breakpoint
    00271     //
    00272
    00273     if  ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) ||
    00274           (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)  ||
    00275           (NtGlobalFlag & FLG_STOP_ON_EXCEPTION) ||
    00276           SecondChance) {
    00277
    00278          //
    00279          // Report state change to kernel debugger on host
    00280          //
    00281
    00282          Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
    00283          Prcb = KeGetCurrentPrcb();
    00284          KiSaveProcessorControlState(&Prcb->ProcessorState);
    00285
    00286          RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
    00287                           ContextRecord,
    00288                           sizeof (CONTEXT));
    00289
    00290          Completion = KdpReportExceptionStateChange(
    00291                           ExceptionRecord,
    00292                           &Prcb->ProcessorState.ContextFrame,
    00293                           SecondChance);
    00294
    00295          RtlCopyMemory(ContextRecord,
    00296                           &Prcb->ProcessorState.ContextFrame,
    00297                           sizeof (CONTEXT));
    00298
    00299          KiRestoreProcessorControlState(&Prcb->ProcessorState);
    00300          KdExitDebugger(Enable);
    00301
    00302
    00303          KdpControlCPressed = FALSE;
    00304
    00305     } else {
    00306
    00307          //
    00308          // This is real exception that user doesn't want to see,
    00309          // so do NOT report it to debugger.
    00310          //
    00311
    00312          // return FALSE;
    00313     }
    00314
    00315     //
    00316     // Always return TRUE if this is the first chance to handle the
    00317     // exception.  Otherwise, return the completion status of the
    00318     // state change reporting.
    00319     //
    00320
    00321     if( SecondChance ){
    00322         return Completion;
    00323     } else {
    00324         return TRUE;
    00325     }
    00326 }
    00327
    00328 BOOLEAN
    00329 KdIsThisAKdTrap (
    00330     IN PEXCEPTION_RECORD ExceptionRecord,
    00331     IN PCONTEXT ContextRecord,
    00332     IN KPROCESSOR_MODE PreviousMode
    00333     )
    00334
    00335 /*++
    00336
    00337 Routine Description:
    00338
    00339     This routine is called whenever a user-mode exception occurs and
    00340     it might be a kernel debugger exception (Like DbgPrint/DbgPrompt ).
    00341
    00342 Arguments:
    00343
    00344     ExceptionRecord - Supplies a pointer to an exception record that
    00345         describes the exception.
    00346
    00347     ContextRecord - Supplies the context at the time of the exception.
    00348
    00349     PreviousMode - Supplies the previous processor mode.
    00350
    00351 Return Value:
    00352
    00353     A value of TRUE is returned if this is for the kernel debugger.
    00354     Otherwise, a value of FALSE is returned.
    00355
    00356 --*/
    00357
    00358 {
    00359
    00360     ULONG_PTR BreakpointCode;
    00361
    00362     //
    00363     // Isolate the breakpoint code from the breakpoint instruction which
    00364     // is stored by the exception dispatch code in the information field
    00365     // of the exception record.
    00366     //
    00367
    00368     BreakpointCode = (ULONG) ExceptionRecord->ExceptionInformation[0];
    00369
    00370     //
    00371     // Switch on the breakpoint code.
    00372     //
    00373
    00374     switch (BreakpointCode) {
    00375
    00376         //
    00377         // Kernel breakpoint codes.
    00378         //
    00379
    00380     case BREAKIN_BREAKPOINT:
    00381     case KERNEL_BREAKPOINT:
    00382
    00383 #if DEVL
    00384
    00385         return TRUE;
    00386
    00387 #else
    00388
    00389         if (PreviousMode == KernelMode) {
    00390             return TRUE;
    00391
    00392         } else {
    00393             return FALSE;
    00394         }
    00395
    00396 #endif
    00397
    00398         //
    00399         // Debug print code.
    00400         //
    00401
    00402     case DEBUG_PRINT_BREAKPOINT:
    00403         return TRUE;
    00404
    00405         //
    00406         // Debug prompt code.
    00407         //
    00408
    00409     case DEBUG_PROMPT_BREAKPOINT:
    00410         return TRUE;
    00411
    00412         //
    00413         // Debug stop code.
    00414         //
    00415
    00416     case DEBUG_STOP_BREAKPOINT:
    00417
    00418 #if DEVL
    00419
    00420         return TRUE;
    00421
    00422 #else
    00423
    00424         if (PreviousMode == KernelMode) {
    00425             return TRUE;
    00426
    00427         } else {
    00428             return FALSE;
    00429         }
    00430
    00431 #endif
    00432
    00433         //
    00434         // Debug load symbols code.
    00435         //
    00436
    00437     case DEBUG_LOAD_SYMBOLS_BREAKPOINT:
    00438         if (PreviousMode == KernelMode) {
    00439             return TRUE;
    00440
    00441         } else {
    00442             return FALSE;
    00443         }
    00444
    00445         //
    00446         // Debug unload symbols code.
    00447         //
    00448
    00449     case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT:
    00450         if (PreviousMode == KernelMode) {
    00451             return TRUE;
    00452
    00453         } else {
    00454             return FALSE;
    00455         }
    00456
    00457         //
    00458         // All other codes.
    00459         //
    00460
    00461     default:
    00462         return FALSE;
    00463     }
    00464 }
    00465
    00466 BOOLEAN
    00467 KdpStub (
    00468     IN PKTRAP_FRAME TrapFrame,
    00469     IN PKEXCEPTION_FRAME ExceptionFrame,
    00470     IN PEXCEPTION_RECORD ExceptionRecord,
    00471     IN PCONTEXT ContextRecord,
    00472     IN KPROCESSOR_MODE PreviousMode,
    00473     IN BOOLEAN SecondChance
    00474     )
    00475
    00476 /*++
    00477
    00478 Routine Description:
    00479
    00480     This routine provides a kernel debugger stub routine that catchs debug
    00481     prints in checked systems when the kernel debugger is not active.
    00482
    00483 Arguments:
    00484
    00485     TrapFrame - Supplies a pointer to a trap frame that describes the
    00486         trap.
    00487
    00488     ExceptionFrame - Supplies a pointer to a exception frame that describes
    00489         the trap.
    00490
    00491     ExceptionRecord - Supplies a pointer to an exception record that
    00492         describes the exception.
    00493
    00494     ContextRecord - Supplies the context at the time of the exception.
    00495
    00496     PreviousMode - Supplies the previous processor mode.
    00497
    00498     SecondChance - Supplies a boolean value that determines whether this is
    00499         the second chance (TRUE) that the exception has been raised.
    00500
    00501 Return Value:
    00502
    00503     A value of TRUE is returned if the exception is handled. Otherwise a
    00504     value of FALSE is returned.
    00505
    00506 --*/
    00507
    00508 {
    00509
    00510     ULONG_PTR BreakpointCode;
    00511 #ifdef _GAMBIT_
    00512     PHYSICAL_ADDRESS PAddress;
    00513 #endif // _GAMBIT_
    00514
    00515     //
    00516     // Isolate the breakpoint code from the breakpoint instruction which
    00517     // is stored by the exception dispatch code in the information field
    00518     // of the exception record.
    00519     //
    00520
    00521     BreakpointCode = (ULONG) ExceptionRecord->ExceptionInformation[0];
    00522
    00523
    00524     //
    00525     // If the breakpoint is a debug print, debug load symbols, or debug
    00526     // unload symbols, then return TRUE. Otherwise, return FALSE;
    00527     //
    00528
    00529     if ((BreakpointCode == DEBUG_PRINT_BREAKPOINT) ||
    00530         (BreakpointCode == DEBUG_LOAD_SYMBOLS_BREAKPOINT) ||
    00531         (BreakpointCode == DEBUG_UNLOAD_SYMBOLS_BREAKPOINT)) {
    00532
    00533         //
    00534         // Advance to next instruction slot so that the BREAK instruction
    00535         // does not get re-executed
    00536         //
    00537
    00538         RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
    00539                           ContextRecord->StIPSR,
    00540                           ContextRecord->StIIP);
    00541
    00542
    00543 #ifdef _GAMBIT_
    00544         if (BreakpointCode == DEBUG_PRINT_BREAKPOINT) {
    00545             if ((PUCHAR)ContextRecord->IntT0) {
    00546                 PAddress = MmGetPhysicalAddress ((PUCHAR)ContextRecord->IntT0);
    00547                 if (PAddress.QuadPart != 0ULL) {
    00548                     SscDbgPrintf((PVOID)PAddress.QuadPart);
    00549                 }
    00550             }
    00551         }
    00552 #endif // _GAMBIT_
    00553
    00554         return TRUE;
    00555
    00556     } else {
    00557         return FALSE;
    00558     }
    00559 }