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 DbgKdReadVirtualMemoryApi
:
104 /* Answer to 'm' GDB request */
105 send_gdb_memory(MessageData
->Buffer
, State
->u
.ReadMemory
.ActualBytesRead
);
107 case DbgKdGetVersionApi
:
109 LIST_ENTRY
* DebuggerDataList
;
110 /* Simply get a copy */
111 RtlCopyMemory(&KdVersion
, &State
->u
.GetVersion64
, sizeof(KdVersion
));
112 DebuggerDataList
= (LIST_ENTRY
*)(ULONG_PTR
)KdVersion
.DebuggerDataList
;
113 KdDebuggerDataBlock
= CONTAINING_RECORD(DebuggerDataList
->Flink
, KDDEBUGGER_DATA64
, Header
.List
);
122 /* PUBLIC FUNCTIONS ***********************************************************/
124 /******************************************************************************
125 * \name KdReceivePacket
126 * \brief Receive a packet from the KD port.
127 * \param [in] PacketType Describes the type of the packet to receive.
128 * This can be one of the PACKET_TYPE_ constants.
129 * \param [out] MessageHeader Pointer to a STRING structure for the header.
130 * \param [out] MessageData Pointer to a STRING structure for the data.
131 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
132 * timed out, KdPacketNeedsResend to signal that the last packet needs
134 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
135 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
136 * packet byte is received.
137 * \sa http://www.nynaeve.net/?p=169
142 _In_ ULONG PacketType
,
143 _Out_ PSTRING MessageHeader
,
144 _Out_ PSTRING MessageData
,
145 _Out_ PULONG DataLength
,
146 _Inout_ PKD_CONTEXT KdContext
)
149 DBGKD_MANIPULATE_STATE64
* State
;
151 /* Special handling for breakin packet */
152 if (PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
154 return KdpPollBreakIn();
157 if (PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
159 /* What should we do ? */
163 State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
165 /* Maybe we are in a send<->receive loop that GDB doesn't need to know about */
166 if (KdpManipulateStateHandler
!= NULL
)
167 return KdpManipulateStateHandler(State
, MessageData
, DataLength
, KdContext
);
169 if (FakeNextManipulatePacket
)
171 FakeNextManipulatePacket
= FALSE
;
172 *State
= FakeManipulateState
;
173 return KdPacketReceived
;
176 /* Receive data from GDB */
177 Status
= gdb_receive_packet(KdContext
);
178 if (Status
!= KdPacketReceived
)
182 return gdb_interpret_input(State
, MessageData
, DataLength
, KdContext
);
189 IN PSTRING MessageHeader
,
190 IN PSTRING MessageData
,
191 IN OUT PKD_CONTEXT KdContext
)
193 /* Maybe we are in a send <-> receive loop that GDB doesn't need to know about */
194 if (KdpSendPacketHandler
)
196 KdpSendPacketHandler(PacketType
, MessageHeader
, MessageData
);
202 case PACKET_TYPE_KD_STATE_CHANGE64
:
203 send_kd_state_change((DBGKD_ANY_WAIT_STATE_CHANGE
*)MessageHeader
->Buffer
);
205 case PACKET_TYPE_KD_DEBUG_IO
:
206 send_kd_debug_io((DBGKD_DEBUG_IO
*)MessageHeader
->Buffer
, MessageData
);
208 case PACKET_TYPE_KD_STATE_MANIPULATE
:
209 send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
, MessageData
);