X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fdrivers%2Fbase%2Fkdgdb%2Fkdpacket.c;h=7f86b372a94f6673b1a1dacf27fca6a69e0910b1;hp=9d2982610d6f74df6a8ae89095b03a711cb0fc47;hb=31965e9804622cc653d51980092e3418a93f42e6;hpb=fe8e1d19fb089609c6a8d1877a57db65e71f6e6a diff --git a/reactos/drivers/base/kdgdb/kdpacket.c b/reactos/drivers/base/kdgdb/kdpacket.c index 9d2982610d6..7f86b372a94 100644 --- a/reactos/drivers/base/kdgdb/kdpacket.c +++ b/reactos/drivers/base/kdgdb/kdpacket.c @@ -7,61 +7,145 @@ #include "kdgdb.h" -/* GLOBALS ********************************************************************/ +/* LOCALS *********************************************************************/ +static +VOID +FirstSendHandler( + _In_ ULONG PacketType, + _In_ PSTRING MessageHeader, + _In_ PSTRING MessageData); -DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange; +/* GLOBALS ********************************************************************/ DBGKD_GET_VERSION64 KdVersion; KDDEBUGGER_DATA64* KdDebuggerDataBlock; +BOOLEAN InException = FALSE; /* Callbacks used to communicate with KD aside from GDB */ -KDP_SEND_HANDLER KdpSendPacketHandler = NULL; +KDP_SEND_HANDLER KdpSendPacketHandler = FirstSendHandler; KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler = NULL; - -/* LOCALS *********************************************************************/ -static BOOLEAN FakeNextManipulatePacket = FALSE; -static DBGKD_MANIPULATE_STATE64 FakeManipulateState = {0}; +/* Data describing the current exception */ +DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange; +CONTEXT CurrentContext; /* PRIVATE FUNCTIONS **********************************************************/ + static -void -send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE* StateChange) +VOID +GetContextSendHandler( + _In_ ULONG PacketType, + _In_ PSTRING MessageHeader, + _In_ PSTRING MessageData +) { - static BOOLEAN first = TRUE; + DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; + const CONTEXT* Context = (const CONTEXT*)MessageData->Buffer; - /* Save current state for later GDB queries */ - CurrentStateChange = *StateChange; + 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; +} + +static +KDSTATUS +GetContextManipulateHandler( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext +) +{ + State->ApiNumber = DbgKdGetContextApi; + State->Processor = CurrentStateChange.Processor; + State->ReturnStatus = STATUS_SUCCESS; + State->ProcessorLevel = CurrentStateChange.ProcessorLevel; + MessageData->Length = 0; + + /* Update the send <-> receive loop handler */ + KdpSendPacketHandler = GetContextSendHandler; + KdpManipulateStateHandler = NULL; - if (first) + return KdPacketReceived; +} + +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)) { - /* - * This is the first packet we receive. - * We take this as an opportunity to connect with GDB and to - * get the KD version block - */ - FakeNextManipulatePacket = TRUE; - FakeManipulateState.ApiNumber = DbgKdGetVersionApi; - FakeManipulateState.Processor = StateChange->Processor; - FakeManipulateState.ProcessorLevel = StateChange->ProcessorLevel; - FakeManipulateState.ReturnStatus = STATUS_SUCCESS; - - first = FALSE; - return; + /* Should we bugcheck ? */ + while (1); + } + + KdpSendPacketHandler = NULL; +} + +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)) + { + while (1); } + RtlCopyMemory(MessageData->Buffer, &CurrentContext, sizeof(CurrentContext)); + + /* Update the send <-> receive loop handlers */ + KdpSendPacketHandler = SetContextSendHandler; + KdpManipulateStateHandler = NULL; + + return KdPacketReceived; +} + +static +void +send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE* StateChange) +{ switch (StateChange->NewState) { case DbgKdLoadSymbolsStateChange: { /* We don't care about symbols loading */ - FakeNextManipulatePacket = TRUE; - FakeManipulateState.ApiNumber = DbgKdContinueApi; - FakeManipulateState.Processor = StateChange->Processor; - FakeManipulateState.ProcessorLevel = StateChange->ProcessorLevel; - FakeManipulateState.ReturnStatus = STATUS_SUCCESS; - FakeManipulateState.u.Continue.ContinueStatus = STATUS_SUCCESS; + KdpManipulateStateHandler = ContinueManipulateStateHandler; break; } case DbgKdExceptionStateChange: + /* Save current state for later GDB queries */ + CurrentStateChange = *StateChange; + /* Unless GDB tells us otherwise, those are what we should have */ + gdb_dbg_thread = PsGetThreadId((PETHREAD)StateChange->Thread); + gdb_dbg_process = PsGetThreadProcessId((PETHREAD)StateChange->Thread); gdb_send_exception(); + /* Next receive call will ask for the context */ + KdpManipulateStateHandler = GetContextManipulateHandler; break; default: /* FIXME */ @@ -100,21 +184,119 @@ send_kd_state_manipulate( gdb_send_registers((CONTEXT*)MessageData->Buffer); return; #endif - case DbgKdGetVersionApi: - { - LIST_ENTRY* DebuggerDataList; - /* Simply get a copy */ - RtlCopyMemory(&KdVersion, &State->u.GetVersion64, sizeof(KdVersion)); - DebuggerDataList = (LIST_ENTRY*)(ULONG_PTR)KdVersion.DebuggerDataList; - KdDebuggerDataBlock = CONTAINING_RECORD(DebuggerDataList->Flink, KDDEBUGGER_DATA64, Header.List); - return; - } default: /* FIXME */ while (1); } } +KDSTATUS +ContinueManipulateStateHandler( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext +) +{ + /* Let's go on */ + State->ApiNumber = DbgKdContinueApi; + State->ReturnStatus = STATUS_SUCCESS; /* ? */ + State->Processor = CurrentStateChange.Processor; + State->ProcessorLevel = CurrentStateChange.ProcessorLevel; + if (MessageData) + MessageData->Length = 0; + *MessageLength = 0; + State->u.Continue.ContinueStatus = STATUS_SUCCESS; + + /* We definitely are at the end of the send <-> receive loop, if any */ + KdpSendPacketHandler = NULL; + KdpManipulateStateHandler = NULL; + return KdPacketReceived; +} + +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); + + /* We can tell KD to continue */ + KdpSendPacketHandler = NULL; + KdpManipulateStateHandler = ContinueManipulateStateHandler; +} + +static +KDSTATUS +GetVersionManipulateStateHandler( + _Out_ DBGKD_MANIPULATE_STATE64* State, + _Out_ PSTRING MessageData, + _Out_ PULONG MessageLength, + _Inout_ PKD_CONTEXT KdContext) +{ + /* Ask for the version data */ + State->ApiNumber = DbgKdGetVersionApi; + State->Processor = CurrentStateChange.Processor; + State->ProcessorLevel = CurrentStateChange.ProcessorLevel; + + /* The next send call will serve this query */ + KdpSendPacketHandler = GetVersionSendHandler; + KdpManipulateStateHandler = NULL; + + /* This will make KD breakin and we will be able to properly attach to GDB */ + KdContext->KdpControlCPending = TRUE; + + return KdPacketReceived; +} + +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; + + 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); + } + + CurrentStateChange = *StateChange; + + /* The next receive call will be asking for the version data */ + KdpSendPacketHandler = NULL; + KdpManipulateStateHandler = GetVersionManipulateStateHandler; +} + /* PUBLIC FUNCTIONS ***********************************************************/ /****************************************************************************** @@ -162,13 +344,6 @@ KdReceivePacket( if (KdpManipulateStateHandler != NULL) return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext); - if (FakeNextManipulatePacket) - { - FakeNextManipulatePacket = FALSE; - *State = FakeManipulateState; - return KdPacketReceived; - } - /* Receive data from GDB */ Status = gdb_receive_packet(KdContext); if (Status != KdPacketReceived)