2 * COPYRIGHT: GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/base/kddll/kdpacket.c
5 * PURPOSE: Base functions for the kernel debugger.
10 /* GLOBALS ********************************************************************/
12 DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange
;
13 DBGKD_GET_VERSION64 KdVersion
;
14 KDDEBUGGER_DATA64
* KdDebuggerDataBlock
;
15 /* Callbacks used to communicate with KD aside from GDB */
16 KDP_SEND_HANDLER KdpSendPacketHandler
= NULL
;
17 KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler
= NULL
;
19 /* LOCALS *********************************************************************/
20 static BOOLEAN FakeNextManipulatePacket
= FALSE
;
21 static DBGKD_MANIPULATE_STATE64 FakeManipulateState
= {0};
23 /* PRIVATE FUNCTIONS **********************************************************/
26 send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE
* StateChange
)
28 static BOOLEAN first
= TRUE
;
30 /* Save current state for later GDB queries */
31 CurrentStateChange
= *StateChange
;
36 * This is the first packet we receive.
37 * We take this as an opportunity to connect with GDB and to
38 * get the KD version block
40 FakeNextManipulatePacket
= TRUE
;
41 FakeManipulateState
.ApiNumber
= DbgKdGetVersionApi
;
42 FakeManipulateState
.Processor
= StateChange
->Processor
;
43 FakeManipulateState
.ProcessorLevel
= StateChange
->ProcessorLevel
;
44 FakeManipulateState
.ReturnStatus
= STATUS_SUCCESS
;
50 switch (StateChange
->NewState
)
52 case DbgKdLoadSymbolsStateChange
:
54 /* We don't care about symbols loading */
55 FakeNextManipulatePacket
= TRUE
;
56 FakeManipulateState
.ApiNumber
= DbgKdContinueApi
;
57 FakeManipulateState
.Processor
= StateChange
->Processor
;
58 FakeManipulateState
.ProcessorLevel
= StateChange
->ProcessorLevel
;
59 FakeManipulateState
.ReturnStatus
= STATUS_SUCCESS
;
60 FakeManipulateState
.u
.Continue
.ContinueStatus
= STATUS_SUCCESS
;
63 case DbgKdExceptionStateChange
:
75 _In_ DBGKD_DEBUG_IO
* DebugIO
,
78 switch (DebugIO
->ApiNumber
)
80 case DbgKdPrintStringApi
:
81 gdb_send_debug_io(String
);
91 send_kd_state_manipulate(
92 _In_ DBGKD_MANIPULATE_STATE64
* State
,
93 _In_ PSTRING MessageData
)
95 switch (State
->ApiNumber
)
98 case DbgKdGetContextApi
:
99 /* This is an answer to a 'g' GDB request */
100 gdb_send_registers((CONTEXT
*)MessageData
->Buffer
);
103 case DbgKdGetVersionApi
:
105 LIST_ENTRY
* DebuggerDataList
;
106 /* Simply get a copy */
107 RtlCopyMemory(&KdVersion
, &State
->u
.GetVersion64
, sizeof(KdVersion
));
108 DebuggerDataList
= (LIST_ENTRY
*)(ULONG_PTR
)KdVersion
.DebuggerDataList
;
109 KdDebuggerDataBlock
= CONTAINING_RECORD(DebuggerDataList
->Flink
, KDDEBUGGER_DATA64
, Header
.List
);
118 /* PUBLIC FUNCTIONS ***********************************************************/
120 /******************************************************************************
121 * \name KdReceivePacket
122 * \brief Receive a packet from the KD port.
123 * \param [in] PacketType Describes the type of the packet to receive.
124 * This can be one of the PACKET_TYPE_ constants.
125 * \param [out] MessageHeader Pointer to a STRING structure for the header.
126 * \param [out] MessageData Pointer to a STRING structure for the data.
127 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
128 * timed out, KdPacketNeedsResend to signal that the last packet needs
130 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
131 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
132 * packet byte is received.
133 * \sa http://www.nynaeve.net/?p=169
138 _In_ ULONG PacketType
,
139 _Out_ PSTRING MessageHeader
,
140 _Out_ PSTRING MessageData
,
141 _Out_ PULONG DataLength
,
142 _Inout_ PKD_CONTEXT KdContext
)
145 DBGKD_MANIPULATE_STATE64
* State
;
147 /* Special handling for breakin packet */
148 if (PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
150 return KdpPollBreakIn();
153 if (PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
155 /* What should we do ? */
159 State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
161 /* Maybe we are in a send<->receive loop that GDB doesn't need to know about */
162 if (KdpManipulateStateHandler
!= NULL
)
163 return KdpManipulateStateHandler(State
, MessageData
, DataLength
, KdContext
);
165 if (FakeNextManipulatePacket
)
167 FakeNextManipulatePacket
= FALSE
;
168 *State
= FakeManipulateState
;
169 return KdPacketReceived
;
172 /* Receive data from GDB */
173 Status
= gdb_receive_packet(KdContext
);
174 if (Status
!= KdPacketReceived
)
178 return gdb_interpret_input(State
, MessageData
, DataLength
, KdContext
);
185 IN PSTRING MessageHeader
,
186 IN PSTRING MessageData
,
187 IN OUT PKD_CONTEXT KdContext
)
189 /* Maybe we are in a send <-> receive loop that GDB doesn't need to know about */
190 if (KdpSendPacketHandler
)
192 KdpSendPacketHandler(PacketType
, MessageHeader
, MessageData
);
198 case PACKET_TYPE_KD_STATE_CHANGE64
:
199 send_kd_state_change((DBGKD_ANY_WAIT_STATE_CHANGE
*)MessageHeader
->Buffer
);
201 case PACKET_TYPE_KD_DEBUG_IO
:
202 send_kd_debug_io((DBGKD_DEBUG_IO
*)MessageHeader
->Buffer
, MessageData
);
204 case PACKET_TYPE_KD_STATE_MANIPULATE
:
205 send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
, MessageData
);