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