Beispiel #1
0
static
void
handle_gdb_thread_alive(void)
{
    ULONG_PTR Pid, Tid;
    PETHREAD Thread;

#if MONOPROCESS
    Pid = 0;
    Tid = hex_to_tid(&gdb_input[1]);

    KDDBGPRINT("Checking if %p is alive.\n", Tid);

#else
    Pid = hex_to_pid(&gdb_input[2]);
    Tid = hex_to_tid(strstr(gdb_input, ".") + 1);

    /* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL.
     * So loop. */
    KDDBGPRINT("Checking if p%p.%p is alive.\n", Pid, Tid);
#endif

    Thread = find_thread(Pid, Tid);

    if (Thread != NULL)
        send_gdb_packet("OK");
    else
        send_gdb_packet("E03");
}
Beispiel #2
0
void
gdb_send_registers(void)
{
    CHAR Registers[16*8 + 1];
    UCHAR* RegisterPtr;
    unsigned i;
    unsigned short size;
    CHAR* ptr = Registers;

    KDDBGPRINT("Sending registers of thread %" PRIxPTR ".\n", gdb_dbg_tid);
    KDDBGPRINT("Current thread_id: %p.\n", PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread));
    if (((gdb_dbg_pid == 0) && (gdb_dbg_tid == 0)) ||
            gdb_tid_to_handle(gdb_dbg_tid) == PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))
    {
        for(i=0; i < 16; i++)
        {
            RegisterPtr = ctx_to_reg(&CurrentContext, i, &size);
            *ptr++ = hex_chars[RegisterPtr[0] >> 4];
            *ptr++ = hex_chars[RegisterPtr[0] & 0xF];
            *ptr++ = hex_chars[RegisterPtr[1] >> 4];
            *ptr++ = hex_chars[RegisterPtr[1] & 0xF];
            *ptr++ = hex_chars[RegisterPtr[2] >> 4];
            *ptr++ = hex_chars[RegisterPtr[2] & 0xF];
            *ptr++ = hex_chars[RegisterPtr[3] >> 4];
            *ptr++ = hex_chars[RegisterPtr[3] & 0xF];
        }
    }
    else
    {
Beispiel #3
0
KDSTATUS
gdb_receive_and_interpret_packet(
    _Out_ DBGKD_MANIPULATE_STATE64* State,
    _Out_ PSTRING MessageData,
    _Out_ PULONG MessageLength,
    _Inout_ PKD_CONTEXT KdContext)
{
    KDSTATUS Status;

    do
    {
        Status = gdb_receive_packet(KdContext);
        KDDBGPRINT("KDGBD: Packet received with status %u\n", Status);

        if (Status != KdPacketReceived)
            return Status;

        Status = (KDSTATUS)-1;

        switch (gdb_input[0])
        {
        case '?':
            /* Send the Status */
            gdb_send_exception(TRUE);
            break;
        case '!':
            send_gdb_packet("OK");
            break;
        case 'g':
            gdb_send_registers();
            break;
        case 'H':
            handle_gdb_set_thread();
            break;
        case 'm':
            Status = handle_gdb_read_mem(State, MessageData, MessageLength, KdContext);
            break;
        case 'p':
            gdb_send_register();
            break;
        case 'q':
            handle_gdb_query();
            break;
        case 'T':
            handle_gdb_thread_alive();
            break;
        case 'v':
            Status = handle_gdb_v(State, MessageData, MessageLength, KdContext);
            break;
        default:
            /* We don't know how to handle this request. Maybe this is something for KD */
            State->ReturnStatus = STATUS_NOT_SUPPORTED;
            KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input);
            return KdPacketReceived;
        }
    } while (Status == (KDSTATUS)-1);

    return Status;
}
Beispiel #4
0
/* H* packets */
static
void
handle_gdb_set_thread(void)
{
    switch (gdb_input[1])
    {
    case 'c':
        if (strcmp(&gdb_input[2], "-1") == 0)
            gdb_run_tid = (ULONG_PTR)-1;
        else
            gdb_run_tid = hex_to_tid(&gdb_input[2]);
        send_gdb_packet("OK");
        break;
    case 'g':
        KDDBGPRINT("Setting debug thread: %s.\n", gdb_input);
#if MONOPROCESS
        gdb_dbg_pid = 0;
        if (strncmp(&gdb_input[2], "-1", 2) == 0)
        {
            gdb_dbg_tid = (UINT_PTR)-1;
        }
        else
        {
            gdb_dbg_tid = hex_to_tid(&gdb_input[2]);
        }
#else
        if (strncmp(&gdb_input[2], "p-1", 3) == 0)
        {
            gdb_dbg_pid = (UINT_PTR)-1;
            gdb_dbg_tid = (UINT_PTR)-1;
        }
        else
        {
            char* ptr = strstr(gdb_input, ".") + 1;
            gdb_dbg_pid = hex_to_pid(&gdb_input[3]);
            if (strncmp(ptr, "-1", 2) == 0)
                gdb_dbg_tid = (UINT_PTR)-1;
            else
                gdb_dbg_tid = hex_to_tid(ptr);
        }
#endif
        send_gdb_packet("OK");
        break;
    default:
        KDDBGPRINT("KDGBD: Unknown 'H' command: %s\n", gdb_input);
        send_gdb_packet("");
    }
}
Beispiel #5
0
KDSTATUS
SetContextManipulateHandler(
    _Out_ DBGKD_MANIPULATE_STATE64* State,
    _Out_ PSTRING MessageData,
    _Out_ PULONG MessageLength,
    _Inout_ PKD_CONTEXT KdContext
)
{
    State->ApiNumber = DbgKdSetContextApi;
    State->Processor = CurrentStateChange.Processor;
    State->ReturnStatus = STATUS_SUCCESS;
    State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
    MessageData->Length = sizeof(CurrentContext);

    if (MessageData->MaximumLength < sizeof(CurrentContext))
    {
        KDDBGPRINT("Wrong message length %u.\n", MessageData->MaximumLength);
        while (1);
    }

    RtlCopyMemory(MessageData->Buffer, &CurrentContext, sizeof(CurrentContext));

    /* Update the send <-> receive loop handlers */
    KdpSendPacketHandler = SetContextSendHandler;
    KdpManipulateStateHandler = NULL;

    return KdPacketReceived;
}
Beispiel #6
0
static
VOID
GetVersionSendHandler(
    _In_ ULONG PacketType,
    _In_ PSTRING MessageHeader,
    _In_ PSTRING MessageData)
{
    DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
    LIST_ENTRY* DebuggerDataList;

    /* Confirm that all went well */
    if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
            || (State->ApiNumber != DbgKdGetVersionApi)
            || !NT_SUCCESS(State->ReturnStatus))
    {
        /* FIXME: should detach from KD and go along without debugging */
        KDDBGPRINT("Wrong packet received after asking for data.\n");
        while(1);
    }

    /* Copy the relevant data */
    RtlCopyMemory(&KdVersion, &State->u.GetVersion64, sizeof(KdVersion));
    DebuggerDataList = (LIST_ENTRY*)(ULONG_PTR)KdVersion.DebuggerDataList;
    KdDebuggerDataBlock = CONTAINING_RECORD(DebuggerDataList->Flink, KDDEBUGGER_DATA64, Header.List);
    ProcessListHead = (LIST_ENTRY*)KdDebuggerDataBlock->PsActiveProcessHead.Pointer;

    /* Now we can get the context for the current state */
    KdpSendPacketHandler = NULL;
    KdpManipulateStateHandler = GetContextManipulateHandler;
}
Beispiel #7
0
VOID
NTAPI
KdSendPacket(
    IN ULONG PacketType,
    IN PSTRING MessageHeader,
    IN PSTRING MessageData,
    IN OUT PKD_CONTEXT KdContext)
{
    /* Maybe we are in a send <-> receive loop that GDB doesn't need to know about */
    if (KdpSendPacketHandler)
    {
        KdpSendPacketHandler(PacketType, MessageHeader, MessageData);
        return;
    }

    switch (PacketType)
    {
    case PACKET_TYPE_KD_STATE_CHANGE64:
        send_kd_state_change((DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer);
        return;
    case PACKET_TYPE_KD_DEBUG_IO:
        send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData);
        break;
    case PACKET_TYPE_KD_STATE_MANIPULATE:
        send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer, MessageData);
        break;
    default:
        KDDBGPRINT("Unknown packet type %u.\n", PacketType);
        while (1);
    }
}
Beispiel #8
0
static
VOID
FirstSendHandler(
    _In_ ULONG PacketType,
    _In_ PSTRING MessageHeader,
    _In_ PSTRING MessageData)
{
    DBGKD_ANY_WAIT_STATE_CHANGE* StateChange = (DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer;
    PETHREAD Thread;

    if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
    {
        /* This is not the packet we are waiting for */
        send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData);
        return;
    }

    if (PacketType != PACKET_TYPE_KD_STATE_CHANGE64)
    {
        KDDBGPRINT("First KD packet is not a state change!\n");
        /* FIXME: What should we send back to KD ? */
        while(1);
    }

    KDDBGPRINT("KDGDB: START!\n");

    Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread;

    /* Set up the current state */
    CurrentStateChange = *StateChange;
    gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread));
#if MONOPROCESS
    gdb_dbg_pid = 0;
#else
    gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread));
#endif
    /* This is the idle process. Save it! */
    TheIdleThread = Thread;
    TheIdleProcess = (PEPROCESS)Thread->Tcb.ApcState.Process;

    KDDBGPRINT("Pid Tid of the first message: %" PRIxPTR", %" PRIxPTR ".\n", gdb_dbg_pid, gdb_dbg_tid);

    /* The next receive call will be asking for the version data */
    KdpSendPacketHandler = NULL;
    KdpManipulateStateHandler = GetVersionManipulateStateHandler;
}
Beispiel #9
0
static
void
send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE* StateChange)
{
    InException = TRUE;

    switch (StateChange->NewState)
    {
    case DbgKdLoadSymbolsStateChange:
    {
        /* We don't care about symbols loading */
        KdpManipulateStateHandler = ContinueManipulateStateHandler;
        break;
    }
    case DbgKdExceptionStateChange:
    {
        PETHREAD Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread;
        /* Save current state for later GDB queries */
        CurrentStateChange = *StateChange;
        KDDBGPRINT("Exception 0x%08x in thread p%p.%p.\n",
            StateChange->u.Exception.ExceptionRecord.ExceptionCode,
            PsGetThreadProcessId(Thread),
            PsGetThreadId(Thread));
        /* Set the current debugged process/thread accordingly */
        gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread));
#if MONOPROCESS
        gdb_dbg_pid = 0;
#else
        gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread));
#endif
        gdb_send_exception(FALSE);
        /* Next receive call will ask for the context */
        KdpManipulateStateHandler = GetContextManipulateHandler;
        break;
    }
    default:
        KDDBGPRINT("Unknown StateChange %u.\n", StateChange->NewState);
        while (1);
    }
}
Beispiel #10
0
static
void
ReadMemorySendHandler(
    _In_ ULONG PacketType,
    _In_ PSTRING MessageHeader,
    _In_ PSTRING MessageData)
{
    DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;

    if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
    {
        // KdAssert
        KDDBGPRINT("Wrong packet type (%lu) received after DbgKdReadVirtualMemoryApi request.\n", PacketType);
        while (1);
    }

    if (State->ApiNumber != DbgKdReadVirtualMemoryApi)
    {
        KDDBGPRINT("Wrong API number (%lu) after DbgKdReadVirtualMemoryApi request.\n", State->ApiNumber);
    }

    /* Check status */
    if (!NT_SUCCESS(State->ReturnStatus))
        send_gdb_ntstatus(State->ReturnStatus);
    else
        send_gdb_memory(MessageData->Buffer, MessageData->Length);
    KdpSendPacketHandler = NULL;
    KdpManipulateStateHandler = NULL;

#if !MONOPROCESS
    /* Reset the TLB */
    if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId())
    {
        __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
    }
#endif
}
Beispiel #11
0
static
KDSTATUS
handle_gdb_v(
    _Out_ DBGKD_MANIPULATE_STATE64* State,
    _Out_ PSTRING MessageData,
    _Out_ PULONG MessageLength,
    _Inout_ PKD_CONTEXT KdContext)
{
    if (strncmp(gdb_input, "vCont", 5) == 0)
    {
        if (gdb_input[5] == '?')
        {
            /* Report what we support */
            send_gdb_packet("vCont;c;C;s;S");
            return (KDSTATUS)-1;
        }

        if (strncmp(gdb_input, "vCont;c", 7) == 0)
        {
            DBGKM_EXCEPTION64* Exception = NULL;

            /* Tell GDB everything is fine, we will handle it */
            send_gdb_packet("OK");

            if (CurrentStateChange.NewState == DbgKdExceptionStateChange)
                Exception = &CurrentStateChange.u.Exception;

            /* See if we should update the program counter (unlike windbg, gdb doesn't do it for us) */
            if (Exception && (Exception->ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT)
                    && (Exception->ExceptionRecord.ExceptionInformation[0] == 0))
            {
                ULONG_PTR ProgramCounter;

                /* So we must get past the breakpoint instruction */
                ProgramCounter = KdpGetContextPc(&CurrentContext);
                KdpSetContextPc(&CurrentContext, ProgramCounter + KD_BREAKPOINT_SIZE);

                SetContextManipulateHandler(State, MessageData, MessageLength, KdContext);
                KdpManipulateStateHandler = ContinueManipulateStateHandler;
                return KdPacketReceived;
            }

            return ContinueManipulateStateHandler(State, MessageData, MessageLength, KdContext);
        }
    }

    KDDBGPRINT("Unhandled 'v' packet: %s\n", gdb_input);
    return KdPacketReceived;
}
Beispiel #12
0
static
void
send_kd_state_manipulate(
    _In_ DBGKD_MANIPULATE_STATE64* State,
    _In_ PSTRING MessageData)
{
    switch (State->ApiNumber)
    {
#if 0
    case DbgKdGetContextApi:
        /* This is an answer to a 'g' GDB request */
        gdb_send_registers((CONTEXT*)MessageData->Buffer);
        return;
#endif
    default:
        KDDBGPRINT("Unknown ApiNumber %u.\n", State->ApiNumber);
        while (1);
    }
}
Beispiel #13
0
static
void
send_kd_debug_io(
    _In_ DBGKD_DEBUG_IO* DebugIO,
    _In_ PSTRING String)
{
    if (InException)
        return;

    switch (DebugIO->ApiNumber)
    {
    case DbgKdPrintStringApi:
        gdb_send_debug_io(String, TRUE);
        break;
    default:
        KDDBGPRINT("Unknown ApiNumber %u.\n", DebugIO->ApiNumber);
        while (1);
    }
}
Beispiel #14
0
static
VOID
SetContextSendHandler(
    _In_ ULONG PacketType,
    _In_ PSTRING MessageHeader,
    _In_ PSTRING MessageData
)
{
    DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;

    /* We just confirm that all went well */
    if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
            || (State->ApiNumber != DbgKdSetContextApi)
            || (State->ReturnStatus != STATUS_SUCCESS))
    {
        /* Should we bugcheck ? */
        KDDBGPRINT("BAD BAD BAD not manipulating state for sending context.\n");
        while (1);
    }

    KdpSendPacketHandler = NULL;
}
Beispiel #15
0
NTSTATUS
NTAPI
KdpPortInitialize(IN ULONG ComPortNumber,
                  IN ULONG ComPortBaudRate)
{
    NTSTATUS Status;

    KDDBGPRINT("KdpPortInitialize, Port = COM%ld\n", ComPortNumber);

    Status = CpInitialize(&KdDebugComPort,
                          UlongToPtr(BaseArray[ComPortNumber]),
                          ComPortBaudRate);
    if (!NT_SUCCESS(Status))
    {
        return STATUS_INVALID_PARAMETER;
    }
    else
    {
        KdComPortInUse = KdDebugComPort.Address;
        return STATUS_SUCCESS;
    }
}
Beispiel #16
0
static
KDSTATUS
handle_gdb_read_mem(
    _Out_ DBGKD_MANIPULATE_STATE64* State,
    _Out_ PSTRING MessageData,
    _Out_ PULONG MessageLength,
    _Inout_ PKD_CONTEXT KdContext)
{
    State->ApiNumber = DbgKdReadVirtualMemoryApi;
    State->ReturnStatus = STATUS_SUCCESS; /* ? */
    State->Processor = CurrentStateChange.Processor;
    State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
    if (MessageData)
        MessageData->Length = 0;
    *MessageLength = 0;

#if !MONOPROCESS
    /* Set the TLB according to the process being read. Pid 0 means any process. */
    if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId())
    {
        PEPROCESS AttachedProcess = find_process(gdb_dbg_pid);
        if (AttachedProcess == NULL)
        {
            KDDBGPRINT("The current GDB debug thread is invalid!");
            send_gdb_packet("E03");
            return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext);
        }
        __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]);
    }
#endif

    State->u.ReadMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]);
    State->u.ReadMemory.TransferCount = hex_to_address(strstr(&gdb_input[1], ",") + 1);

    /* KD will reply with KdSendPacket. Catch it */
    KdpSendPacketHandler = ReadMemorySendHandler;

    return KdPacketReceived;
}
Beispiel #17
0
static
VOID
GetContextSendHandler(
    _In_ ULONG PacketType,
    _In_ PSTRING MessageHeader,
    _In_ PSTRING MessageData
)
{
    DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
    const CONTEXT* Context = (const CONTEXT*)MessageData->Buffer;

    if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
            || (State->ApiNumber != DbgKdGetContextApi)
            || (MessageData->Length < sizeof(*Context)))
    {
        /* Should we bugcheck ? */
        KDDBGPRINT("ERROR: Received wrong packet from KD.\n");
        while (1);
    }

    /* Just copy it */
    RtlCopyMemory(&CurrentContext, Context, sizeof(*Context));
    KdpSendPacketHandler = NULL;
}
Beispiel #18
0
static
void*
thread_to_reg(PETHREAD Thread, enum reg_name reg_name, unsigned short* size)
{
    /* See if the guy got a stack */
    if (Thread->Tcb.InitialStack == NULL)
    {
        static const void* NullValue = NULL;
        /* Terminated thread ? */
        switch (reg_name)
        {
            case ESP:
            case EBP:
            case EIP:
                KDDBGPRINT("Returning NULL for register %d.\n", reg_name);
                *size = 4;
                return &NullValue;
            default:
                return NULL;
        }
    }
    else if (Thread->Tcb.TrapFrame)
    {
        PKTRAP_FRAME TrapFrame = Thread->Tcb.TrapFrame;

        *size = 4;
        switch (reg_name)
        {
            case EAX: return &TrapFrame->Eax;
            case ECX: return &TrapFrame->Ecx;
            case EDX: return &TrapFrame->Edx;
            case EBX: return &TrapFrame->Ebx;
            case ESP: return (TrapFrame->PreviousPreviousMode == KernelMode) ?
                    &TrapFrame->TempEsp : &TrapFrame->HardwareEsp;
            case EBP: return &TrapFrame->Ebp;
            case ESI: return &TrapFrame->Esi;
            case EDI: return &TrapFrame->Edi;
            case EIP: return &TrapFrame->Eip;
            case EFLAGS: return &TrapFrame->EFlags;
            case CS: return &TrapFrame->SegCs;
            case SS: return &TrapFrame->HardwareSegSs;
            case DS: return &TrapFrame->SegDs;
            case ES: return &TrapFrame->SegEs;
            case FS: return &TrapFrame->SegFs;
            case GS: return &TrapFrame->SegGs;
            default:
                KDDBGPRINT("Unhandled regname: %d.\n", reg_name);
        }
    }
    else
    {
        /* The thread was not yet scheduled */
        *size = 4;
        switch(reg_name)
        {
            case ESP: return &Thread->Tcb.KernelStack;
            case EBP: return &((ULONG*)Thread->Tcb.KernelStack)[4];
            case EIP: return &Thread->StartAddress;
            default:
                return NULL;
        }
    }
    return NULL;
}
Beispiel #19
0
KDSTATUS
NTAPI
gdb_receive_packet(_Inout_ PKD_CONTEXT KdContext)
{
    UCHAR* ByteBuffer = (UCHAR*)gdb_input;
    UCHAR Byte;
    KDSTATUS Status;
    CHAR CheckSum = 0, ReceivedCheckSum;

    do
    {
        Status = KdpReceiveByte(&Byte);
        if (Status != KdPacketReceived)
            return Status;
        if (Byte == 0x03)
        {
            KDDBGPRINT("BREAK!");
            KdContext->KdpControlCPending = TRUE;
            return KdPacketNeedsResend;
        }
    } while (Byte != '$');

    while (TRUE)
    {
        /* Try to get a byte from the port */
        Status = KdpReceiveByte(&Byte);
        if (Status != KdPacketReceived)
            return Status;

        if (Byte == '#')
        {
            *ByteBuffer = '\0';
            break;
        }
        CheckSum += (CHAR)Byte;
        
        /* See if we should escape */
        if (Byte == 0x7d)
        {
            Status = KdpReceiveByte(&Byte);
            if (Status != KdPacketReceived)
                return Status;         
            CheckSum += (CHAR)Byte;
            Byte ^= 0x20;
        }
        *ByteBuffer++ = Byte;
    }

    /* Get Check sum (two bytes) */
    Status = KdpReceiveByte(&Byte);
    if (Status != KdPacketReceived)
        goto end;
    ReceivedCheckSum = hex_value(Byte) << 4;

    Status = KdpReceiveByte(&Byte);
    if (Status != KdPacketReceived)
        goto end;
    ReceivedCheckSum += hex_value(Byte);

end:
    if (ReceivedCheckSum != CheckSum)
    {
        /* Do not acknowledge to GDB */
        KDDBGPRINT("Check sums don't match!");
        KdpSendByte('-');
        return KdPacketNeedsResend;
    }

    /* Acknowledge */
    KdpSendByte('+');

    return KdPacketReceived;
}
Beispiel #20
0
/* q* packets */
static
void
handle_gdb_query(void)
{
    if (strncmp(gdb_input, "qSupported:", 11) == 0)
    {
#if MONOPROCESS
        send_gdb_packet("PacketSize=1000;");
#else
        send_gdb_packet("PacketSize=1000;multiprocess+;");
#endif
        return;
    }

    if (strncmp(gdb_input, "qAttached", 9) == 0)
    {
#if MONOPROCESS
        send_gdb_packet("1");
#else
        UINT_PTR queried_pid = hex_to_pid(&gdb_input[10]);
        /* Let's say we created system process */
        if (gdb_pid_to_handle(queried_pid) == NULL)
            send_gdb_packet("0");
        else
            send_gdb_packet("1");
#endif
        return;
    }

    if (strncmp(gdb_input, "qRcmd,", 6) == 0)
    {
        send_gdb_packet("OK");
        return;
    }

    if (strcmp(gdb_input, "qC") == 0)
    {
        char gdb_out[64];
#if MONOPROCESS
        sprintf(gdb_out, "QC:%"PRIxPTR";",
            handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)));
#else
        sprintf(gdb_out, "QC:p%"PRIxPTR".%"PRIxPTR";",
            handle_to_gdb_pid(PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)),
            handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)));
#endif
        send_gdb_packet(gdb_out);
        return;
    }

    if ((strncmp(gdb_input, "qfThreadInfo", 12) == 0)
            || (strncmp(gdb_input, "qsThreadInfo", 12) == 0))
    {
        BOOLEAN FirstThread = TRUE;
        PEPROCESS Process;
        PETHREAD Thread;
        char gdb_out[1024];
        char* ptr = gdb_out;
        BOOLEAN Resuming = strncmp(gdb_input, "qsThreadInfo", 12) == 0;
        /* Keep track of where we are. */
        static LIST_ENTRY* CurrentProcessEntry;
        static LIST_ENTRY* CurrentThreadEntry;

        ptr = gdb_out;

        *ptr++ = 'm';
        /* NULL terminate in case we got nothing more to iterate */
        *ptr  = '\0';

        if (!Resuming)
        {
            /* Initialize the entries */
            CurrentProcessEntry = ProcessListHead->Flink;
            CurrentThreadEntry = NULL;

            /* Start with idle thread */
#if MONOPROCESS
            ptr = gdb_out + sprintf(gdb_out, "m1");
#else
            ptr = gdb_out + sprintf(gdb_out, "mp1.1");
#endif
            FirstThread = FALSE;
        }

        if (CurrentProcessEntry == NULL) /* Ps is not initialized */
        {
            send_gdb_packet(Resuming ? "l" : gdb_out);
            return;
        }

        /* List all the processes */
        for ( ;
            CurrentProcessEntry != ProcessListHead;
            CurrentProcessEntry = CurrentProcessEntry->Flink)
        {

            Process = CONTAINING_RECORD(CurrentProcessEntry, EPROCESS, ActiveProcessLinks);

            if (CurrentThreadEntry != NULL)
                CurrentThreadEntry = CurrentThreadEntry->Flink;
            else
                CurrentThreadEntry = Process->ThreadListHead.Flink;

            /* List threads from this process */
            for ( ;
                 CurrentThreadEntry != &Process->ThreadListHead;
                 CurrentThreadEntry = CurrentThreadEntry->Flink)
            {
                Thread = CONTAINING_RECORD(CurrentThreadEntry, ETHREAD, ThreadListEntry);

                /* See if we should add a comma */
                if (FirstThread)
                {
                    FirstThread = FALSE;
                }
                else
                {
                    *ptr++ = ',';
                }

#if MONOPROCESS
                ptr += _snprintf(ptr, 1024 - (ptr - gdb_out),
                    "%p",
                    handle_to_gdb_tid(Thread->Cid.UniqueThread));
#else
                ptr += _snprintf(ptr, 1024 - (ptr - gdb_out),
                    "p%p.%p",
                    handle_to_gdb_pid(Process->UniqueProcessId),
                    handle_to_gdb_tid(Thread->Cid.UniqueThread));
#endif
                if (ptr > (gdb_out + 1024))
                {
                    /* send what we got */
                    send_gdb_packet(gdb_out);
                    /* GDB can ask anything at this point, it isn't necessarily a qsThreadInfo packet */
                    return;
                }
            }
            /* We're done for this process */
            CurrentThreadEntry = NULL;
        }

        if (gdb_out[1] == '\0')
        {
            /* We didn't iterate over anything, meaning we were already done */
            send_gdb_packet("l");
        }
        else
        {
            send_gdb_packet(gdb_out);
        }
        /* GDB can ask anything at this point, it isn't necessarily a qsThreadInfo packet */
        return;
    }

    if (strncmp(gdb_input, "qThreadExtraInfo,", 17) == 0)
    {
        ULONG_PTR Pid, Tid;
        PETHREAD Thread;
        PEPROCESS Process;
        char out_string[64];
        STRING String = {0, 64, out_string};

        KDDBGPRINT("Giving extra info for");

#if MONOPROCESS
        Pid = 0;
        Tid = hex_to_tid(&gdb_input[17]);

        KDDBGPRINT(" %p.\n", Tid);

        Thread = find_thread(Pid, Tid);
        Process = CONTAINING_RECORD(Thread->Tcb.Process, EPROCESS, Pcb);
#else
        Pid = hex_to_pid(&gdb_input[2]);
        Tid = hex_to_tid(strstr(gdb_input, ".") + 1);

        /* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL.
         * So loop. */
        KDDBGPRINT(" p%p.%p.\n", Pid, Tid);

        Process = find_process(Pid);
        Thread = find_thread(Pid, Tid);
#endif

        if (PsGetThreadProcessId(Thread) == 0)
        {
            String.Length = sprintf(out_string, "SYSTEM");
        }
        else
        {
            String.Length = sprintf(out_string, "%.*s", 16, Process->ImageFileName);
        }

        gdb_send_debug_io(&String, FALSE);
        return;
    }

    if (strncmp(gdb_input, "qOffsets", 8) == 0)
    {
        /* We load ntoskrnl at 0x80800000 while compiling it at 0x00800000 base adress */
        send_gdb_packet("TextSeg=80000000");
        return;
    }

    if (strcmp(gdb_input, "qTStatus") == 0)
    {
        /* No tracepoint support */
        send_gdb_packet("T0");
        return;
    }

    KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input);
    send_gdb_packet("");
    return;
}
Beispiel #21
0
/******************************************************************************
 * \name KdpReceivePacketLeader
 * \brief Recieves a packet leadr from the KD port.
 * \param PacketLeader Pointer to an ULONG that receives the packet leader.
 * \return KDP_PACKET_RECEIVED if successful. 
 *         KDP_PACKET_TIMEOUT if the receive timed out.
 *         KDP_PACKET_RESEND if a breakin byte was detected.
 */
KDP_STATUS
NTAPI
KdpReceivePacketLeader(
    OUT PULONG PacketLeader)
{
    UCHAR Index = 0, Byte, Buffer[4];
    KDP_STATUS KdStatus;

    /* Set first character to 0 */
    Buffer[0] = 0;

    do
    {
        /* Receive a single byte */
        KdStatus = KdpReceiveByte(&Byte);

        /* Check for timeout */
        if (KdStatus == KDP_PACKET_TIMEOUT)
        {
            /* Check if we already got a breakin byte */
            if (Buffer[0] == BREAKIN_PACKET_BYTE)
            {
                return KDP_PACKET_RESEND;
            }

            /* Report timeout */
            return KDP_PACKET_TIMEOUT;
        }

        /* Check if we received a byte */
        if (KdStatus == KDP_PACKET_RECEIVED)
        {
            /* Check if this is a valid packet leader byte */
            if (Byte == PACKET_LEADER_BYTE ||
                Byte == CONTROL_PACKET_LEADER_BYTE)
            {
                /* Check if we match the first byte */
                if (Byte != Buffer[0])
                {
                    /* No, this is the new byte 0! */
                    Index = 0;
                }

                /* Store the byte in the buffer */
                Buffer[Index] = Byte;

                /* Continue with next byte */
                Index++;
                continue;
            }

            /* Check for breakin byte */
            if (Byte == BREAKIN_PACKET_BYTE)
            {
                KDDBGPRINT("BREAKIN_PACKET_BYTE\n");
                Index = 0;
                Buffer[0] = Byte;
                continue;
            }
        }

        /* Restart */
        Index = 0;
        Buffer[0] = 0;
    }
    while (Index < 4);

    /* Enable the debugger */
    KdDebuggerNotPresent = FALSE;
    SharedUserData->KdDebuggerEnabled |= 0x00000002;

    /* Return the received packet leader */
    *PacketLeader = *(PULONG)Buffer;

    return KDP_PACKET_RECEIVED;
}
Beispiel #22
0
/******************************************************************************
 * \name KdDebuggerInitialize0
 * \brief Phase 0 initialization.
 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
 * \return Status
 */
NTSTATUS
NTAPI
KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
{
    ULONG ComPortNumber   = DEFAULT_DEBUG_PORT;
    ULONG ComPortBaudRate = DEFAULT_DEBUG_BAUD_RATE;

    PCHAR CommandLine, PortString, BaudString, IrqString;
    ULONG Value;

    /* Check if e have a LoaderBlock */
    if (LoaderBlock)
    {
        /* HACK */
        KdpDbgPrint = LoaderBlock->u.I386.CommonDataArea;
        KDDBGPRINT("KdDebuggerInitialize0\n");

        /* Get the Command Line */
        CommandLine = LoaderBlock->LoadOptions;

        /* Upcase it */
        _strupr(CommandLine);

        /* Get the port and baud rate */
        PortString = strstr(CommandLine, "DEBUGPORT");
        BaudString = strstr(CommandLine, "BAUDRATE");
        IrqString  = strstr(CommandLine, "IRQ");

        /* Check if we got the /DEBUGPORT parameter */
        if (PortString)
        {
            /* Move past the actual string, to reach the port*/
            PortString += strlen("DEBUGPORT");

            /* Now get past any spaces and skip the equal sign */
            while (*PortString == ' ') PortString++;
            PortString++;

            /* Do we have a serial port? */
            if (strncmp(PortString, "COM", 3) != 0)
            {
                return STATUS_INVALID_PARAMETER;
            }

            /* Check for a valid Serial Port */
            PortString += 3;
            Value = atol(PortString);
            if (Value >= sizeof(BaseArray) / sizeof(BaseArray[0]))
            {
                return STATUS_INVALID_PARAMETER;
            }

            /* Set the port to use */
            ComPortNumber = Value;
       }

        /* Check if we got a baud rate */
        if (BaudString)
        {
            /* Move past the actual string, to reach the rate */
            BaudString += strlen("BAUDRATE");

            /* Now get past any spaces */
            while (*BaudString == ' ') BaudString++;

            /* And make sure we have a rate */
            if (*BaudString)
            {
                /* Read and set it */
                Value = atol(BaudString + 1);
                if (Value) ComPortBaudRate = Value;
            }
        }

        /* Check Serial Port Settings [IRQ] */
        if (IrqString)
        {
            /* Move past the actual string, to reach the rate */
            IrqString += strlen("IRQ");

            /* Now get past any spaces */
            while (*IrqString == ' ') IrqString++;

            /* And make sure we have an IRQ */
            if (*IrqString)
            {
                /* Read and set it */
                Value = atol(IrqString + 1);
                if (Value) KdDebugComPortIrq = Value;
            }
        }
    }

    /* Initialize the port */
    return KdpPortInitialize(ComPortNumber, ComPortBaudRate);
}