示例#1
0
USHORT
NTAPI
KdpPrompt(IN LPSTR PromptString,
          IN USHORT PromptLength,
          OUT LPSTR ResponseString,
          IN USHORT MaximumResponseLength,
          IN KPROCESSOR_MODE PreviousMode,
          IN PKTRAP_FRAME TrapFrame,
          IN PKEXCEPTION_FRAME ExceptionFrame)
{
    STRING PromptBuffer, ResponseBuffer;
    BOOLEAN Enable, Resend;

    /* Normalize the lengths */
    PromptLength = min(PromptLength, 512);
    MaximumResponseLength = min(MaximumResponseLength, 512);

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

    /* Setup the prompt and response  buffers */
    PromptBuffer.Buffer = PromptString;
    PromptBuffer.Length = PromptLength;
    ResponseBuffer.Buffer = ResponseString;
    ResponseBuffer.Length = 0;
    ResponseBuffer.MaximumLength = MaximumResponseLength;

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

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

    /* Enter prompt loop */
    do
    {
        /* Send the prompt and receive the response */
        Resend = KdpPromptString(&PromptBuffer, &ResponseBuffer);

        /* Loop while we need to resend */
    } while (Resend);

    /* Exit the debugger */
    KdExitDebugger(Enable);

    /* Return the number of characters received */
    return ResponseBuffer.Length;
}
示例#2
0
文件: kdtrap.c 项目: conioh/os-design
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;
}
示例#3
0
文件: kdtrap.c 项目: conioh/os-design
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;
    }
}