Exemplo n.º 1
0
VOID
__cdecl
KdpDprintf(IN PCHAR Format,
           ...)
{
    STRING String;
    CHAR Buffer[100];
    USHORT Length;
    va_list ap;

    /* Format the string */
    va_start(ap, Format);
    Length = (USHORT)_vsnprintf(Buffer,
                                sizeof(Buffer),
                                Format,
                                ap);

    /* Set it up */
    String.Buffer = Buffer;
    String.Length = Length + 1;

    /* Send it to the debugger directly */
    KdpPrintString(&String);
    va_end(ap);
}
Exemplo n.º 2
0
BOOLEAN
KdpTrap (
    IN PKTRAP_FRAME TrapFrame,
    IN PKEXCEPTION_FRAME ExceptionFrame,
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN PCONTEXT ContextRecord,
    IN KPROCESSOR_MODE PreviousMode,
    IN BOOLEAN SecondChance
    )

/*++

Routine Description:

    This routine is called whenever a exception is dispatched and the kernel
    debugger is active.

Arguments:

    TrapFrame - Supplies a pointer to a trap frame that describes the
        trap.

    ExceptionFrame - Supplies a pointer to a exception frame that describes
        the trap.

    ExceptionRecord - Supplies a pointer to an exception record that
        describes the exception.

    ContextRecord - Supplies the context at the time of the exception.

    PreviousMode - Supplies the previous processor mode.

    SecondChance - Supplies a boolean value that determines whether this is
        the second chance (TRUE) that the exception has been raised.

Return Value:

    A value of TRUE is returned if the exception is handled. Otherwise a
    value of FALSE is returned.

--*/

{

    BOOLEAN Completion;
    BOOLEAN Enable;
    BOOLEAN UnloadSymbols = FALSE;
    ULONG OldIar;
    STRING Input;
    STRING Output;
    PKPRCB Prcb;

    //
    // Synchronize processor execution, save processor state, enter debugger,
    // and flush the current TB.
    //

re_enter_debugger:
    Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
    Prcb = KeGetCurrentPrcb();
    KiSaveProcessorState(TrapFrame, ExceptionFrame);
    KeFlushCurrentTb();

    //
    // If this is a breakpoint instruction, then check to determine if is
    // an internal command.
    //

    if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
       ((ExceptionRecord->ExceptionInformation[0] & BREAKPOINT_CODE_MASK)
                              >= DEBUG_PRINT_BREAKPOINT)) {

        //
        // Switch on the breakpoint code.
        //

        switch (ExceptionRecord->ExceptionInformation[0] & BREAKPOINT_CODE_MASK) {

            //
            // Print a debug string.
            //
            // Arguments:
            //
            //   a0 - Supplies a pointer to an output string buffer.
            //   a1 - Supplies the length of the output string buffer.
            //

        case DEBUG_PRINT_BREAKPOINT:
            ContextRecord->Iar += 4;
            Output.Buffer = (PCHAR)ContextRecord->Gpr3;
            Output.Length = (USHORT)ContextRecord->Gpr4;
            if (KdDebuggerNotPresent == FALSE) {
                if (KdpPrintString(&Output)) {
                    ContextRecord->Gpr3 = (ULONG)STATUS_BREAKPOINT;

                } else {
                    ContextRecord->Gpr3 = (ULONG)STATUS_SUCCESS;
                }

            } else {
                ContextRecord->Gpr3 = (ULONG)STATUS_DEVICE_NOT_CONNECTED;
            }

            KiRestoreProcessorState(TrapFrame, ExceptionFrame);
            KdExitDebugger(Enable);
            return TRUE;

            //
            // Print a debug prompt string, then input a string.
            //
            //   r.3 - Supplies a pointer to an output string buffer.
            //   r.4 - Supplies the length of the output string buffer..
            //   r.5 - supplies a pointer to an input string buffer.
            //   r.6 - Supplies the length of the input string bufffer.
            //

        case DEBUG_PROMPT_BREAKPOINT:
            ContextRecord->Iar += 4;
            Output.Buffer = (PCHAR)ContextRecord->Gpr3;
            Output.Length = (USHORT)ContextRecord->Gpr4;
            Input.Buffer = (PCHAR)ContextRecord->Gpr5;
            Input.MaximumLength = (USHORT)ContextRecord->Gpr6;
            KdpPromptString(&Output, &Input);
            ContextRecord->Gpr3 = Input.Length;
            KiRestoreProcessorState(TrapFrame, ExceptionFrame);
            KdExitDebugger(Enable);
            return TRUE;

            //
            // Load the symbolic information for an image.
            //
            // Arguments:
            //
            //    r.3 - Supplies a pointer to an output string descriptor.
            //    r.4 - Supplies a the base address of the image.
            //

        case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT:
            UnloadSymbols = TRUE;

            //
            // Fall through
            //

        case DEBUG_LOAD_SYMBOLS_BREAKPOINT:
            OldIar = ContextRecord->Iar;
            if (KdDebuggerNotPresent == FALSE) {
                KdpReportLoadSymbolsStateChange((PSTRING)ContextRecord->Gpr3,
                                                (PKD_SYMBOLS_INFO) ContextRecord->Gpr4,
                                                UnloadSymbols,
                                                &Prcb->ProcessorState.ContextFrame);

            }

            RtlCopyMemory(ContextRecord,
                          &Prcb->ProcessorState.ContextFrame,
                          sizeof(CONTEXT));

            KiRestoreProcessorState(TrapFrame, ExceptionFrame);
            KdExitDebugger(Enable);

            //
            // If the kernel debugger did not update the IAR, then increment
            // past the breakpoint instruction.
            //

            if (ContextRecord->Iar == OldIar) {
                ContextRecord->Iar += 4;
            }

            return TRUE;

            //
            // Unknown internal command.
            //

        default:
            break;
        }
    }

    //
    // Report state change to kernel debugger on host machine.
    //

    Completion = KdpReportExceptionStateChange(
                    ExceptionRecord,
                    &Prcb->ProcessorState.ContextFrame,
                    SecondChance);

    RtlCopyMemory(ContextRecord,
                  &Prcb->ProcessorState.ContextFrame,
                  sizeof(CONTEXT));

    KiRestoreProcessorState(TrapFrame, ExceptionFrame);
    KdExitDebugger(Enable);

    //
    // check to see if the user of the remote debugger
    // requested memory to be paged in
    //
    if (KdpPageInAddress) {

        if (KeGetCurrentIrql() <= APC_LEVEL) {

            //
            // if the IQRL is below DPC level then cause
            // the page fault to occur and then re-enter
            // the debugger.  this whole process is transparent
            // to the user.
            //
            KdpPageInData( (PUCHAR)KdpPageInAddress );
            KdpPageInAddress = 0;
            KdpControlCPending = FALSE;
            goto re_enter_debugger;

        } else {

            //
            // we cannot take a page fault
            // here so a worker item is queued to take the
            // page fault.  after the worker item takes the
            // page fault it sets the contol-c flag so that
            // the user re-enters the debugger just as if
            // control-c was pressed.
            //
            if (KdpControlCPressed) {
                ExInitializeWorkItem(
                    &KdpPageInWorkItem,
                    (PWORKER_THREAD_ROUTINE) KdpPageInData,
                    (PVOID) KdpPageInAddress
                    );
                ExQueueWorkItem( &KdpPageInWorkItem, DelayedWorkQueue );
                KdpPageInAddress = 0;
            }
        }
    }

    KdpControlCPressed = FALSE;

    return Completion;
}
Exemplo n.º 3
0
ULONG
NTAPI
KdpServiceDispatcher(ULONG Service,
                     PVOID Buffer1,
                     ULONG Buffer1Length)
{
    ULONG Result = 0;

    switch (Service)
    {
        case BREAKPOINT_PRINT: /* DbgPrint */
            Result = KdpPrintString(Buffer1, Buffer1Length);
            break;

#if DBG
        case ' soR': /* ROS-INTERNAL */
        {
            switch ((ULONG_PTR)Buffer1)
            {
                case DumpAllThreads:
                    PspDumpThreads(TRUE);
                    break;

                case DumpUserThreads:
                    PspDumpThreads(FALSE);
                    break;

                case KdSpare3:
                    MmDumpArmPfnDatabase(FALSE);
                    break;

                default:
                    break;
            }
            break;
        }

#if defined(_M_IX86) && !defined(_WINKD_) // See ke/i386/traphdlr.c
        /* Register a debug callback */
        case 'CsoR':
        {
            switch (Buffer1Length)
            {
                case ID_Win32PreServiceHook:
                    KeWin32PreServiceHook = Buffer1;
                    break;

                case ID_Win32PostServiceHook:
                    KeWin32PostServiceHook = Buffer1;
                    break;

            }
            break;
        }
#endif

        /* Special  case for stack frame dumps */
        case 'DsoR':
        {
            KeRosDumpStackFrames((PULONG)Buffer1, Buffer1Length);
            break;
        }

#if defined(KDBG)
        /* Register KDBG CLI callback */
        case 'RbdK':
        {
            Result = KdbRegisterCliCallback(Buffer1, Buffer1Length);
            break;
        }
#endif /* KDBG */
#endif /* DBG */
        default:
            DPRINT1("Invalid debug service call!\n");
            HalDisplayString("Invalid debug service call!\r\n");
            break;
    }

    return Result;
}
Exemplo n.º 4
0
NTSTATUS
NTAPI
KdpPrint(IN ULONG ComponentId,
         IN ULONG Level,
         IN LPSTR String,
         IN USHORT Length,
         IN KPROCESSOR_MODE PreviousMode,
         IN PKTRAP_FRAME TrapFrame,
         IN PKEXCEPTION_FRAME ExceptionFrame,
         OUT PBOOLEAN Handled)
{
    NTSTATUS ReturnStatus;
    BOOLEAN Enable;
    STRING OutputString;

    /* Assume failure */
    *Handled = FALSE;

    /* Validate the mask */
    if (Level < 32) Level = 1 << Level;
    if (!(Kd_WIN2000_Mask & Level) ||
            ((ComponentId < KdComponentTableSize) &&
             !(*KdComponentTable[ComponentId] & Level)))
    {
        /* Mask validation failed */
        *Handled = TRUE;
        return STATUS_SUCCESS;
    }

    /* Normalize the length */
    Length = min(Length, 512);

    /* Check if we need to verify the buffer */
    if (PreviousMode != KernelMode)
    {
        /* FIXME: Support user-mode */
    }

    /* Setup the output string */
    OutputString.Buffer = String;
    OutputString.Length = Length;

    /* Log the print */
    //KdLogDbgPrint(&OutputString);

    /* Check for a debugger */
    if (KdDebuggerNotPresent)
    {
        /* Fail */
        *Handled = TRUE;
        return STATUS_DEVICE_NOT_CONNECTED;
    }

    /* Enter the debugger */
    Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);

    /* Print the string */
    if (KdpPrintString(&OutputString))
    {
        /* User pressed CTRL-C, breakpoint on return */
        ReturnStatus = STATUS_BREAKPOINT;
    }
    else
    {
        /* String was printed */
        ReturnStatus = STATUS_SUCCESS;
    }

    /* Exit the debugger and return */
    KdExitDebugger(Enable);
    *Handled = TRUE;
    return ReturnStatus;
}
Exemplo n.º 5
0
BOOLEAN
KdpTrap (
    IN PKTRAP_FRAME TrapFrame,
    IN PKEXCEPTION_FRAME ExceptionFrame,
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN PCONTEXT ContextRecord,
    IN KPROCESSOR_MODE PreviousMode,
    IN BOOLEAN SecondChance
    )

/*++

Routine Description:

    This routine is called whenever a exception is dispatched and the kernel
    debugger is active.

Arguments:

    TrapFrame - Supplies a pointer to a trap frame that describes the
        trap.

    ExceptionFrame - Supplies a pointer to a exception frame that describes
        the trap.

    ExceptionRecord - Supplies a pointer to an exception record that
        describes the exception.

    ContextRecord - Supplies the context at the time of the exception.

    PreviousMode - Supplies the previous processor mode.

    SecondChance - Supplies a boolean value that determines whether this is
        the second chance (TRUE) that the exception has been raised.

Return Value:

    A value of TRUE is returned if the exception is handled. Otherwise a
    value of FALSE is returned.

--*/

{

    BOOLEAN Completion;
    BOOLEAN Enable;
    BOOLEAN UnloadSymbols = FALSE;
    STRING Input;
    ULONGLONG OldFir;
    STRING Output;
    PKPRCB Prcb;

    //
    // Enter debugger and synchronize processor execution.
    //

    //
    // If this is a breakpoint instruction, then check to determine if is
    // an internal command.
    //

    if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
        (ExceptionRecord->ExceptionInformation[0] >= DEBUG_PRINT_BREAKPOINT)){

        //
        // Switch on the breakpoint code.
        //

        switch (ExceptionRecord->ExceptionInformation[0]) {

            //
            // Print a debug string.
            //
            // Arguments:
            //
            //   a0 - Supplies a pointer to an output string buffer.
            //   a1 - Supplies the length of the output string buffer.
            //

        case DEBUG_PRINT_BREAKPOINT:
            ContextRecord->Fir += 4;
            Output.Buffer = (PCHAR)ContextRecord->IntA0;
            Output.Length = (USHORT)ContextRecord->IntA1;

            KdLogDbgPrint(&Output);

            if (KdDebuggerNotPresent == FALSE) {

                Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
                if (KdpPrintString(&Output)) {
                    ContextRecord->IntV0 = (ULONG)STATUS_BREAKPOINT;
                } else {
                    ContextRecord->IntV0 = (ULONG)STATUS_SUCCESS;
                }
                KdExitDebugger(Enable);

            } else {
                ContextRecord->IntV0 = (ULONG)STATUS_DEVICE_NOT_CONNECTED;
            }

            return TRUE;


            //
            // Stop in the debugger
            //
            // As this is not a normal breakpoint we must increment the
            // context past the breakpoint instruction
            //

        case BREAKIN_BREAKPOINT:
            ContextRecord->Fir += 4;
            break;

            //
            // Print a debug prompt string, then input a string.
            //
            //   a0 - Supplies a pointer to an output string buffer.
            //   a1 - Supplies the length of the output string buffer..
            //   a2 - supplies a pointer to an input string buffer.
            //   a3 - Supplies the length of the input string bufffer.
            //

        case DEBUG_PROMPT_BREAKPOINT:
            ContextRecord->Fir += 4;
            Output.Buffer = (PCHAR)ContextRecord->IntA0;
            Output.Length = (USHORT)ContextRecord->IntA1;
            Input.Buffer = (PCHAR)ContextRecord->IntA2;
            Input.MaximumLength = (USHORT)ContextRecord->IntA3;

            KdLogDbgPrint(&Output);

            Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);

            KdpPromptString(&Output, &Input);

            ContextRecord->IntV0 = Input.Length;

            KdExitDebugger(Enable);
            return TRUE;

            //
            // Load the symbolic information for an image.
            //
            // Arguments:
            //
            //    a0 - Supplies a pointer to an output string descriptor.
            //    a1 - Supplies a the base address of the image.
            //    a2 - Supplies the current process id.
            //

        case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT:
            UnloadSymbols = TRUE;

            //
            // Fall through
            //

        case DEBUG_LOAD_SYMBOLS_BREAKPOINT:
            Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
            Prcb = KeGetCurrentPrcb();
            OldFir = ContextRecord->Fir;
            RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
                          ContextRecord,
                          sizeof(CONTEXT));

            if (KdDebuggerNotPresent == FALSE) {
                KdpReportLoadSymbolsStateChange((PSTRING)ContextRecord->IntA0,
                                                (PKD_SYMBOLS_INFO) ContextRecord->IntA1,
                                                UnloadSymbols,
                                                &Prcb->ProcessorState.ContextFrame);

            }

            RtlCopyMemory(ContextRecord,
                          &Prcb->ProcessorState.ContextFrame,
                          sizeof(CONTEXT));

            KdExitDebugger(Enable);

            //
            // If the kernel debugger did not update the FIR, then increment
            // past the breakpoint instruction.
            //

            if (ContextRecord->Fir == OldFir) {
                ContextRecord->Fir += 4;
            }

            return TRUE;

            //
            // Unknown internal command.
            //

        default:
            break;
        }
    }

    //
    // Report state change to kernel debugger on host machine.
    //

    Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
    Prcb = KeGetCurrentPrcb();

    RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
                    ContextRecord,
                    sizeof (CONTEXT));

    Completion = KdpReportExceptionStateChange(ExceptionRecord,
                                               &Prcb->ProcessorState.ContextFrame,
                                               SecondChance);

    RtlCopyMemory(ContextRecord,
                  &Prcb->ProcessorState.ContextFrame,
                  sizeof(CONTEXT));

    KdExitDebugger(Enable);

    KdpControlCPressed = FALSE;

    //
    // Always return TRUE if this is the first chance to handle the
    // exception.  Otherwise, return the completion status of the
    // state change reporting.
    //

    if( SecondChance ){
        return Completion;
    } else {
        return TRUE;
    }
}