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
;
16 /* LOCALS *********************************************************************/
17 static BOOLEAN FakeNextManipulatePacket
= FALSE
;
18 static DBGKD_MANIPULATE_STATE64 FakeManipulateState
= {0};
20 /* PRIVATE FUNCTIONS **********************************************************/
23 send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE
* StateChange
)
25 static BOOLEAN first
= TRUE
;
27 /* Save current state for later GDB queries */
28 CurrentStateChange
= *StateChange
;
33 * This is the first packet we receive.
34 * We take this as an opportunity to connect with GDB and to
35 * get the KD version block
37 FakeNextManipulatePacket
= TRUE
;
38 FakeManipulateState
.ApiNumber
= DbgKdGetVersionApi
;
39 FakeManipulateState
.Processor
= StateChange
->Processor
;
40 FakeManipulateState
.ProcessorLevel
= StateChange
->ProcessorLevel
;
41 FakeManipulateState
.ReturnStatus
= STATUS_SUCCESS
;
47 switch (StateChange
->NewState
)
49 case DbgKdLoadSymbolsStateChange
:
51 /* We don't care about symbols loading */
52 FakeNextManipulatePacket
= TRUE
;
53 FakeManipulateState
.ApiNumber
= DbgKdContinueApi
;
54 FakeManipulateState
.Processor
= StateChange
->Processor
;
55 FakeManipulateState
.ProcessorLevel
= StateChange
->ProcessorLevel
;
56 FakeManipulateState
.ReturnStatus
= STATUS_SUCCESS
;
57 FakeManipulateState
.u
.Continue
.ContinueStatus
= STATUS_SUCCESS
;
60 case DbgKdExceptionStateChange
:
72 _In_ DBGKD_DEBUG_IO
* DebugIO
,
75 switch (DebugIO
->ApiNumber
)
77 case DbgKdPrintStringApi
:
78 gdb_send_debug_io(String
);
88 send_kd_state_manipulate(
89 _In_ DBGKD_MANIPULATE_STATE64
* State
,
90 _In_ PSTRING MessageData
)
92 switch (State
->ApiNumber
)
95 case DbgKdGetContextApi
:
96 /* This is an answer to a 'g' GDB request */
97 gdb_send_registers((CONTEXT
*)MessageData
->Buffer
);
100 case DbgKdReadVirtualMemoryApi
:
101 /* Answer to 'm' GDB request */
102 send_gdb_memory(MessageData
->Buffer
, State
->u
.ReadMemory
.ActualBytesRead
);
104 case DbgKdGetVersionApi
:
106 LIST_ENTRY
* DebuggerDataList
;
107 /* Simply get a copy */
108 RtlCopyMemory(&KdVersion
, &State
->u
.GetVersion64
, sizeof(KdVersion
));
109 DebuggerDataList
= (LIST_ENTRY
*)(ULONG_PTR
)KdVersion
.DebuggerDataList
;
110 KdDebuggerDataBlock
= CONTAINING_RECORD(DebuggerDataList
->Flink
, KDDEBUGGER_DATA64
, Header
.List
);
119 /* PUBLIC FUNCTIONS ***********************************************************/
121 /******************************************************************************
122 * \name KdReceivePacket
123 * \brief Receive a packet from the KD port.
124 * \param [in] PacketType Describes the type of the packet to receive.
125 * This can be one of the PACKET_TYPE_ constants.
126 * \param [out] MessageHeader Pointer to a STRING structure for the header.
127 * \param [out] MessageData Pointer to a STRING structure for the data.
128 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
129 * timed out, KdPacketNeedsResend to signal that the last packet needs
131 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
132 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
133 * packet byte is received.
134 * \sa http://www.nynaeve.net/?p=169
139 _In_ ULONG PacketType
,
140 _Out_ PSTRING MessageHeader
,
141 _Out_ PSTRING MessageData
,
142 _Out_ PULONG DataLength
,
143 _Inout_ PKD_CONTEXT KdContext
)
146 DBGKD_MANIPULATE_STATE64
* State
;
148 /* Special handling for breakin packet */
149 if (PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
151 return KdpPollBreakIn();
154 if (PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
156 /* What should we do ? */
160 State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
162 if (FakeNextManipulatePacket
)
164 FakeNextManipulatePacket
= FALSE
;
165 *State
= FakeManipulateState
;
166 return KdPacketReceived
;
169 /* Receive data from GDB */
170 Status
= gdb_receive_packet(KdContext
);
171 if (Status
!= KdPacketReceived
)
175 return gdb_interpret_input(State
, MessageData
, DataLength
, KdContext
);
182 IN PSTRING MessageHeader
,
183 IN PSTRING MessageData
,
184 IN OUT PKD_CONTEXT KdContext
)
188 case PACKET_TYPE_KD_STATE_CHANGE64
:
189 send_kd_state_change((DBGKD_ANY_WAIT_STATE_CHANGE
*)MessageHeader
->Buffer
);
191 case PACKET_TYPE_KD_DEBUG_IO
:
192 send_kd_debug_io((DBGKD_DEBUG_IO
*)MessageHeader
->Buffer
, MessageData
);
194 case PACKET_TYPE_KD_STATE_MANIPULATE
:
195 send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
, MessageData
);