1 /* 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. 6 */ 7 8 #include "kdgdb.h" 9 10 /* LOCALS *********************************************************************/ 11 static 12 BOOLEAN 13 FirstSendHandler( 14 _In_ ULONG PacketType, 15 _In_ PSTRING MessageHeader, 16 _In_ PSTRING MessageData); 17 static BOOLEAN InException = FALSE; 18 19 /* GLOBALS ********************************************************************/ 20 DBGKD_GET_VERSION64 KdVersion; 21 KDDEBUGGER_DATA64* KdDebuggerDataBlock; 22 LIST_ENTRY* ProcessListHead; 23 LIST_ENTRY* ModuleListHead; 24 /* Callbacks used to communicate with KD aside from GDB */ 25 KDP_SEND_HANDLER KdpSendPacketHandler = FirstSendHandler; 26 KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler = NULL; 27 /* Data describing the current exception */ 28 DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange; 29 CONTEXT CurrentContext; 30 PEPROCESS TheIdleProcess; 31 PETHREAD TheIdleThread; 32 33 /* PRIVATE FUNCTIONS **********************************************************/ 34 35 static 36 BOOLEAN 37 GetContextSendHandler( 38 _In_ ULONG PacketType, 39 _In_ PSTRING MessageHeader, 40 _In_ PSTRING MessageData 41 ) 42 { 43 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 44 const CONTEXT* Context = (const CONTEXT*)MessageData->Buffer; 45 46 if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 47 || (State->ApiNumber != DbgKdGetContextApi) 48 || (MessageData->Length < sizeof(*Context))) 49 { 50 KDDBGPRINT("ERROR: Received wrong packet from KD.\n"); 51 return FALSE; 52 } 53 54 /* Just copy it */ 55 RtlCopyMemory(&CurrentContext, Context, sizeof(*Context)); 56 KdpSendPacketHandler = NULL; 57 return TRUE; 58 } 59 60 static 61 KDSTATUS 62 GetContextManipulateHandler( 63 _Out_ DBGKD_MANIPULATE_STATE64* State, 64 _Out_ PSTRING MessageData, 65 _Out_ PULONG MessageLength, 66 _Inout_ PKD_CONTEXT KdContext 67 ) 68 { 69 State->ApiNumber = DbgKdGetContextApi; 70 State->Processor = CurrentStateChange.Processor; 71 State->ReturnStatus = STATUS_SUCCESS; 72 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 73 MessageData->Length = 0; 74 75 /* Update the send <-> receive loop handler */ 76 KdpSendPacketHandler = GetContextSendHandler; 77 KdpManipulateStateHandler = NULL; 78 79 return KdPacketReceived; 80 } 81 82 static 83 BOOLEAN 84 SetContextSendHandler( 85 _In_ ULONG PacketType, 86 _In_ PSTRING MessageHeader, 87 _In_ PSTRING MessageData 88 ) 89 { 90 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 91 92 /* We just confirm that all went well */ 93 if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 94 || (State->ApiNumber != DbgKdSetContextApi) 95 || (State->ReturnStatus != STATUS_SUCCESS)) 96 { 97 /* Should we bugcheck ? */ 98 KDDBGPRINT("BAD BAD BAD not manipulating state for sending context.\n"); 99 return FALSE; 100 } 101 102 KdpSendPacketHandler = NULL; 103 return TRUE; 104 } 105 106 KDSTATUS 107 SetContextManipulateHandler( 108 _Out_ DBGKD_MANIPULATE_STATE64* State, 109 _Out_ PSTRING MessageData, 110 _Out_ PULONG MessageLength, 111 _Inout_ PKD_CONTEXT KdContext 112 ) 113 { 114 State->ApiNumber = DbgKdSetContextApi; 115 State->Processor = CurrentStateChange.Processor; 116 State->ReturnStatus = STATUS_SUCCESS; 117 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 118 MessageData->Length = sizeof(CurrentContext); 119 120 if (MessageData->MaximumLength < sizeof(CurrentContext)) 121 { 122 KDDBGPRINT("Wrong message length %u.\n", MessageData->MaximumLength); 123 while (1); 124 } 125 126 RtlCopyMemory(MessageData->Buffer, &CurrentContext, sizeof(CurrentContext)); 127 128 /* Update the send <-> receive loop handlers */ 129 KdpSendPacketHandler = SetContextSendHandler; 130 KdpManipulateStateHandler = NULL; 131 132 return KdPacketReceived; 133 } 134 135 static 136 void 137 send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE* StateChange) 138 { 139 InException = TRUE; 140 141 switch (StateChange->NewState) 142 { 143 case DbgKdLoadSymbolsStateChange: 144 case DbgKdExceptionStateChange: 145 { 146 PETHREAD Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread; 147 /* Save current state for later GDB queries */ 148 CurrentStateChange = *StateChange; 149 KDDBGPRINT("Exception 0x%08x in thread p%p.%p.\n", 150 StateChange->u.Exception.ExceptionRecord.ExceptionCode, 151 PsGetThreadProcessId(Thread), 152 PsGetThreadId(Thread)); 153 /* Set the current debugged process/thread accordingly */ 154 gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread)); 155 #if MONOPROCESS 156 gdb_dbg_pid = 0; 157 #else 158 gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread)); 159 #endif 160 gdb_send_exception(); 161 /* Next receive call will ask for the context */ 162 KdpManipulateStateHandler = GetContextManipulateHandler; 163 break; 164 } 165 default: 166 KDDBGPRINT("Unknown StateChange %u.\n", StateChange->NewState); 167 while (1); 168 } 169 } 170 171 static 172 void 173 send_kd_debug_io( 174 _In_ DBGKD_DEBUG_IO* DebugIO, 175 _In_ PSTRING String) 176 { 177 if (InException) 178 return; 179 180 switch (DebugIO->ApiNumber) 181 { 182 case DbgKdPrintStringApi: 183 case DbgKdGetStringApi: 184 gdb_send_debug_io(String, TRUE); 185 break; 186 default: 187 KDDBGPRINT("Unknown ApiNumber %u.\n", DebugIO->ApiNumber); 188 while (1); 189 } 190 } 191 192 static 193 void 194 send_kd_state_manipulate( 195 _In_ DBGKD_MANIPULATE_STATE64* State, 196 _In_ PSTRING MessageData) 197 { 198 switch (State->ApiNumber) 199 { 200 #if 0 201 case DbgKdGetContextApi: 202 /* This is an answer to a 'g' GDB request */ 203 gdb_send_registers((CONTEXT*)MessageData->Buffer); 204 return; 205 #endif 206 default: 207 KDDBGPRINT("Unknown ApiNumber %u.\n", State->ApiNumber); 208 while (1); 209 } 210 } 211 212 KDSTATUS 213 ContinueManipulateStateHandler( 214 _Out_ DBGKD_MANIPULATE_STATE64* State, 215 _Out_ PSTRING MessageData, 216 _Out_ PULONG MessageLength, 217 _Inout_ PKD_CONTEXT KdContext 218 ) 219 { 220 /* Let's go on */ 221 State->ApiNumber = DbgKdContinueApi; 222 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 223 State->Processor = CurrentStateChange.Processor; 224 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 225 if (MessageData) 226 MessageData->Length = 0; 227 *MessageLength = 0; 228 State->u.Continue.ContinueStatus = STATUS_SUCCESS; 229 230 /* We definitely are at the end of the send <-> receive loop, if any */ 231 KdpSendPacketHandler = NULL; 232 KdpManipulateStateHandler = NULL; 233 /* We're not handling an exception anymore */ 234 InException = FALSE; 235 236 return KdPacketReceived; 237 } 238 239 static 240 BOOLEAN 241 GetVersionSendHandler( 242 _In_ ULONG PacketType, 243 _In_ PSTRING MessageHeader, 244 _In_ PSTRING MessageData) 245 { 246 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 247 PLIST_ENTRY DebuggerDataList; 248 249 /* Confirm that all went well */ 250 if ((PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 251 || (State->ApiNumber != DbgKdGetVersionApi) 252 || !NT_SUCCESS(State->ReturnStatus)) 253 { 254 KDDBGPRINT("Wrong packet received after asking for data.\n"); 255 return FALSE; 256 } 257 258 /* Copy the relevant data */ 259 RtlCopyMemory(&KdVersion, &State->u.GetVersion64, sizeof(KdVersion)); 260 DebuggerDataList = *(PLIST_ENTRY*)&KdVersion.DebuggerDataList; 261 KdDebuggerDataBlock = CONTAINING_RECORD(DebuggerDataList->Flink, KDDEBUGGER_DATA64, Header.List); 262 ProcessListHead = *(PLIST_ENTRY*)&KdDebuggerDataBlock->PsActiveProcessHead; 263 ModuleListHead = *(PLIST_ENTRY*)&KdDebuggerDataBlock->PsLoadedModuleList; 264 265 /* Now we can get the context for the current state */ 266 KdpSendPacketHandler = NULL; 267 KdpManipulateStateHandler = GetContextManipulateHandler; 268 return TRUE; 269 } 270 271 static 272 KDSTATUS 273 GetVersionManipulateStateHandler( 274 _Out_ DBGKD_MANIPULATE_STATE64* State, 275 _Out_ PSTRING MessageData, 276 _Out_ PULONG MessageLength, 277 _Inout_ PKD_CONTEXT KdContext) 278 { 279 /* Ask for the version data */ 280 State->ApiNumber = DbgKdGetVersionApi; 281 State->Processor = CurrentStateChange.Processor; 282 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 283 284 /* The next send call will serve this query */ 285 KdpSendPacketHandler = GetVersionSendHandler; 286 KdpManipulateStateHandler = NULL; 287 288 return KdPacketReceived; 289 } 290 291 static 292 BOOLEAN 293 FirstSendHandler( 294 _In_ ULONG PacketType, 295 _In_ PSTRING MessageHeader, 296 _In_ PSTRING MessageData) 297 { 298 DBGKD_ANY_WAIT_STATE_CHANGE* StateChange = (DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer; 299 PETHREAD Thread; 300 301 if (PacketType != PACKET_TYPE_KD_STATE_CHANGE64) 302 { 303 KDDBGPRINT("First KD packet is not a state change!\n"); 304 return FALSE; 305 } 306 307 KDDBGPRINT("KDGDB: START!\n"); 308 309 Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread; 310 311 /* Set up the current state */ 312 CurrentStateChange = *StateChange; 313 gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread)); 314 #if MONOPROCESS 315 gdb_dbg_pid = 0; 316 #else 317 gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread)); 318 #endif 319 /* This is the idle process. Save it! */ 320 TheIdleThread = Thread; 321 TheIdleProcess = (PEPROCESS)Thread->Tcb.ApcState.Process; 322 323 KDDBGPRINT("Pid Tid of the first message: %" PRIxPTR", %" PRIxPTR ".\n", gdb_dbg_pid, gdb_dbg_tid); 324 325 /* The next receive call will be asking for the version data */ 326 KdpSendPacketHandler = NULL; 327 KdpManipulateStateHandler = GetVersionManipulateStateHandler; 328 return TRUE; 329 } 330 331 /* PUBLIC FUNCTIONS ***********************************************************/ 332 333 /****************************************************************************** 334 * \name KdReceivePacket 335 * \brief Receive a packet from the KD port. 336 * \param [in] PacketType Describes the type of the packet to receive. 337 * This can be one of the PACKET_TYPE_ constants. 338 * \param [out] MessageHeader Pointer to a STRING structure for the header. 339 * \param [out] MessageData Pointer to a STRING structure for the data. 340 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive 341 * timed out, KdPacketNeedsResend to signal that the last packet needs 342 * to be sent again. 343 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't 344 * wait for any data, but returns KdPacketTimedOut instantly if no breakin 345 * packet byte is received. 346 * \sa http://www.nynaeve.net/?p=169 347 */ 348 KDSTATUS 349 NTAPI 350 KdReceivePacket( 351 _In_ ULONG PacketType, 352 _Out_ PSTRING MessageHeader, 353 _Out_ PSTRING MessageData, 354 _Out_ PULONG DataLength, 355 _Inout_ PKD_CONTEXT KdContext) 356 { 357 KDDBGPRINT("KdReceivePacket --> "); 358 359 if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN) 360 { 361 static BOOLEAN firstTime = TRUE; 362 KDDBGPRINT("Polling break in.\n"); 363 if (firstTime) 364 { 365 /* Force debug break on init */ 366 firstTime = FALSE; 367 return KdPacketReceived; 368 } 369 370 return KdpPollBreakIn(); 371 } 372 373 if (PacketType == PACKET_TYPE_KD_DEBUG_IO) 374 { 375 static BOOLEAN ignore = 0; 376 KDDBGPRINT("Debug prompt.\n"); 377 /* HACK ! Debug prompt asks for break or ignore. First break, then ignore. */ 378 MessageData->Length = 1; 379 MessageData->Buffer[0] = ignore ? 'i' : 'b'; 380 ignore = !ignore; 381 return KdPacketReceived; 382 } 383 384 if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE) 385 { 386 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 387 388 KDDBGPRINT("State manipulation: "); 389 390 /* Maybe we are in a send<->receive loop that GDB doesn't need to know about */ 391 if (KdpManipulateStateHandler != NULL) 392 { 393 KDDBGPRINT("We have a manipulate state handler.\n"); 394 return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext); 395 } 396 397 /* Receive data from GDB and interpret it */ 398 KDDBGPRINT("Receiving data from GDB.\n"); 399 return gdb_receive_and_interpret_packet(State, MessageData, DataLength, KdContext); 400 } 401 402 /* What should we do ? */ 403 while (1); 404 return KdPacketNeedsResend; 405 } 406 407 VOID 408 NTAPI 409 KdSendPacket( 410 IN ULONG PacketType, 411 IN PSTRING MessageHeader, 412 IN PSTRING MessageData, 413 IN OUT PKD_CONTEXT KdContext) 414 { 415 /* Override if we have some debug print from KD. */ 416 if (PacketType == PACKET_TYPE_KD_DEBUG_IO) 417 { 418 send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData); 419 return; 420 } 421 422 /* Maybe we are in a send <-> receive loop that GDB doesn't need to know about */ 423 if (KdpSendPacketHandler 424 && KdpSendPacketHandler(PacketType, MessageHeader, MessageData)) 425 { 426 return; 427 } 428 429 switch (PacketType) 430 { 431 case PACKET_TYPE_KD_STATE_CHANGE64: 432 send_kd_state_change((DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer); 433 return; 434 case PACKET_TYPE_KD_DEBUG_IO: 435 send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData); 436 break; 437 case PACKET_TYPE_KD_STATE_MANIPULATE: 438 send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer, MessageData); 439 break; 440 default: 441 KDDBGPRINT("Unknown packet type %u.\n", PacketType); 442 while (1); 443 } 444 } 445 446 /* EOF */ 447