1 /* 2 * COPYRIGHT: GPL, see COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: drivers/base/kddll/gdb_input.c 5 * PURPOSE: Base functions for the kernel debugger. 6 */ 7 8 #include "kdgdb.h" 9 10 /* LOCALS *********************************************************************/ 11 static ULONG_PTR gdb_run_tid; 12 static struct 13 { 14 ULONG_PTR Address; 15 ULONG Handle; 16 } BreakPointHandles[32]; 17 18 19 /* GLOBALS ********************************************************************/ 20 UINT_PTR gdb_dbg_pid; 21 UINT_PTR gdb_dbg_tid; 22 23 static inline 24 KDSTATUS 25 LOOP_IF_SUCCESS(int x) 26 { 27 return (x == KdPacketReceived) ? (KDSTATUS)-1 : x; 28 } 29 30 /* PRIVATE FUNCTIONS **********************************************************/ 31 static 32 UINT_PTR 33 hex_to_tid(char* buffer) 34 { 35 ULONG_PTR ret = 0; 36 char hex; 37 while (*buffer) 38 { 39 hex = hex_value(*buffer++); 40 if (hex < 0) 41 return ret; 42 ret <<= 4; 43 ret += hex; 44 } 45 return ret; 46 } 47 #define hex_to_pid hex_to_tid 48 49 static 50 ULONG64 51 hex_to_address(char* buffer) 52 { 53 ULONG64 ret = 0; 54 char hex; 55 while (*buffer) 56 { 57 hex = hex_value(*buffer++); 58 if (hex < 0) 59 return ret; 60 ret <<= 4; 61 ret += hex; 62 } 63 return ret; 64 } 65 66 /* H* packets */ 67 static 68 KDSTATUS 69 handle_gdb_set_thread(void) 70 { 71 KDSTATUS Status; 72 73 switch (gdb_input[1]) 74 { 75 case 'c': 76 if (strcmp(&gdb_input[2], "-1") == 0) 77 gdb_run_tid = (ULONG_PTR)-1; 78 else 79 gdb_run_tid = hex_to_tid(&gdb_input[2]); 80 Status = send_gdb_packet("OK"); 81 break; 82 case 'g': 83 KDDBGPRINT("Setting debug thread: %s.\n", gdb_input); 84 #if MONOPROCESS 85 gdb_dbg_pid = 0; 86 if (strncmp(&gdb_input[2], "-1", 2) == 0) 87 { 88 gdb_dbg_tid = (UINT_PTR)-1; 89 } 90 else 91 { 92 gdb_dbg_tid = hex_to_tid(&gdb_input[2]); 93 } 94 #else 95 if (strncmp(&gdb_input[2], "p-1", 3) == 0) 96 { 97 gdb_dbg_pid = (UINT_PTR)-1; 98 gdb_dbg_tid = (UINT_PTR)-1; 99 } 100 else 101 { 102 char* ptr = strstr(gdb_input, ".") + 1; 103 gdb_dbg_pid = hex_to_pid(&gdb_input[3]); 104 if (strncmp(ptr, "-1", 2) == 0) 105 gdb_dbg_tid = (UINT_PTR)-1; 106 else 107 gdb_dbg_tid = hex_to_tid(ptr); 108 } 109 #endif 110 Status = send_gdb_packet("OK"); 111 break; 112 default: 113 KDDBGPRINT("KDGBD: Unknown 'H' command: %s\n", gdb_input); 114 Status = send_gdb_packet(""); 115 } 116 117 return Status; 118 } 119 120 static 121 KDSTATUS 122 handle_gdb_thread_alive(void) 123 { 124 ULONG_PTR Pid, Tid; 125 PETHREAD Thread; 126 KDSTATUS Status; 127 128 #if MONOPROCESS 129 Pid = 0; 130 Tid = hex_to_tid(&gdb_input[1]); 131 132 KDDBGPRINT("Checking if %p is alive.\n", Tid); 133 134 #else 135 Pid = hex_to_pid(&gdb_input[2]); 136 Tid = hex_to_tid(strstr(gdb_input, ".") + 1); 137 138 /* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL. 139 * So loop. */ 140 KDDBGPRINT("Checking if p%p.%p is alive.\n", Pid, Tid); 141 #endif 142 143 Thread = find_thread(Pid, Tid); 144 145 if (Thread != NULL) 146 Status = send_gdb_packet("OK"); 147 else 148 Status = send_gdb_packet("E03"); 149 150 return Status; 151 } 152 153 /* q* packets */ 154 static 155 KDSTATUS 156 handle_gdb_query(void) 157 { 158 if (strncmp(gdb_input, "qSupported:", 11) == 0) 159 { 160 #if MONOPROCESS 161 return send_gdb_packet("PacketSize=1000;qXfer:libraries:read+;"); 162 #else 163 return send_gdb_packet("PacketSize=1000;multiprocess+;qXfer:libraries:read+;"); 164 #endif 165 } 166 167 if (strncmp(gdb_input, "qAttached", 9) == 0) 168 { 169 #if MONOPROCESS 170 return send_gdb_packet("1"); 171 #else 172 UINT_PTR queried_pid = hex_to_pid(&gdb_input[10]); 173 /* Let's say we created system process */ 174 if (gdb_pid_to_handle(queried_pid) == NULL) 175 return send_gdb_packet("0"); 176 else 177 return send_gdb_packet("1"); 178 #endif 179 } 180 181 if (strncmp(gdb_input, "qRcmd,", 6) == 0) 182 { 183 return send_gdb_packet("OK"); 184 } 185 186 if (strcmp(gdb_input, "qC") == 0) 187 { 188 char gdb_out[64]; 189 #if MONOPROCESS 190 sprintf(gdb_out, "QC:%"PRIxPTR";", 191 handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))); 192 #else 193 sprintf(gdb_out, "QC:p%"PRIxPTR".%"PRIxPTR";", 194 handle_to_gdb_pid(PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)), 195 handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))); 196 #endif 197 return send_gdb_packet(gdb_out); 198 } 199 200 if (strncmp(gdb_input, "qfThreadInfo", 12) == 0) 201 { 202 PEPROCESS Process; 203 char gdb_out[40]; 204 LIST_ENTRY* CurrentProcessEntry; 205 206 CurrentProcessEntry = ProcessListHead->Flink; 207 if (CurrentProcessEntry == NULL) /* Ps is not initialized */ 208 { 209 #if MONOPROCESS 210 return send_gdb_packet("m1"); 211 #else 212 return send_gdb_packet("mp1.1"); 213 #endif 214 } 215 216 /* We will push threads as we find them */ 217 start_gdb_packet(); 218 219 /* Start with the system thread */ 220 #if MONOPROCESS 221 send_gdb_partial_packet("m1"); 222 #else 223 send_gdb_partial_packet("mp1.1"); 224 #endif 225 226 /* List all the processes */ 227 for ( ; 228 CurrentProcessEntry != ProcessListHead; 229 CurrentProcessEntry = CurrentProcessEntry->Flink) 230 { 231 LIST_ENTRY* CurrentThreadEntry; 232 233 Process = CONTAINING_RECORD(CurrentProcessEntry, EPROCESS, ActiveProcessLinks); 234 235 /* List threads from this process */ 236 for ( CurrentThreadEntry = Process->ThreadListHead.Flink; 237 CurrentThreadEntry != &Process->ThreadListHead; 238 CurrentThreadEntry = CurrentThreadEntry->Flink) 239 { 240 PETHREAD Thread = CONTAINING_RECORD(CurrentThreadEntry, ETHREAD, ThreadListEntry); 241 242 #if MONOPROCESS 243 _snprintf(gdb_out, 40, ",%p", handle_to_gdb_tid(Thread->Cid.UniqueThread)); 244 #else 245 _snprintf(gdb_out, 40, ",p%p.%p", 246 handle_to_gdb_pid(Process->UniqueProcessId), 247 handle_to_gdb_tid(Thread->Cid.UniqueThread)); 248 #endif 249 send_gdb_partial_packet(gdb_out); 250 } 251 } 252 253 return finish_gdb_packet(); 254 } 255 256 if (strncmp(gdb_input, "qsThreadInfo", 12) == 0) 257 { 258 /* We sent the whole thread list on first qfThreadInfo call */ 259 return send_gdb_packet("l"); 260 } 261 262 if (strncmp(gdb_input, "qThreadExtraInfo,", 17) == 0) 263 { 264 ULONG_PTR Pid, Tid; 265 PETHREAD Thread; 266 PEPROCESS Process; 267 char out_string[64]; 268 STRING String = {0, 64, out_string}; 269 270 KDDBGPRINT("Giving extra info for"); 271 272 #if MONOPROCESS 273 Pid = 0; 274 Tid = hex_to_tid(&gdb_input[17]); 275 276 KDDBGPRINT(" %p.\n", Tid); 277 278 Thread = find_thread(Pid, Tid); 279 Process = CONTAINING_RECORD(Thread->Tcb.Process, EPROCESS, Pcb); 280 #else 281 Pid = hex_to_pid(&gdb_input[18]); 282 Tid = hex_to_tid(strstr(&gdb_input[18], ".") + 1); 283 284 /* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL. 285 * So loop. */ 286 KDDBGPRINT(" p%p.%p.\n", Pid, Tid); 287 288 Process = find_process(Pid); 289 Thread = find_thread(Pid, Tid); 290 #endif 291 292 if (PsGetThreadProcessId(Thread) == 0) 293 { 294 String.Length = sprintf(out_string, "SYSTEM"); 295 } 296 else 297 { 298 String.Length = sprintf(out_string, "%.*s", 16, Process->ImageFileName); 299 } 300 301 return gdb_send_debug_io(&String, FALSE); 302 } 303 304 if (strncmp(gdb_input, "qOffsets", 8) == 0) 305 { 306 /* We load ntoskrnl at 0x80800000 while compiling it at 0x00800000 base address */ 307 return send_gdb_packet("TextSeg=80000000"); 308 } 309 310 if (strcmp(gdb_input, "qTStatus") == 0) 311 { 312 /* No tracepoint support */ 313 return send_gdb_packet("T0"); 314 } 315 316 if (strcmp(gdb_input, "qSymbol::") == 0) 317 { 318 /* No need */ 319 return send_gdb_packet("OK"); 320 } 321 322 if (strncmp(gdb_input, "qXfer:libraries:read::", 22) == 0) 323 { 324 static LIST_ENTRY* CurrentEntry = NULL; 325 char str_helper[256]; 326 char name_helper[64]; 327 ULONG_PTR Offset = hex_to_address(&gdb_input[22]); 328 ULONG_PTR ToSend = hex_to_address(strstr(&gdb_input[22], ",") + 1); 329 ULONG Sent = 0; 330 static BOOLEAN allDone = FALSE; 331 332 KDDBGPRINT("KDGDB: qXfer:libraries:read !\n"); 333 334 /* Start the packet */ 335 start_gdb_packet(); 336 337 if (allDone) 338 { 339 send_gdb_partial_packet("l"); 340 allDone = FALSE; 341 return finish_gdb_packet(); 342 } 343 344 send_gdb_partial_packet("m"); 345 Sent++; 346 347 /* Are we starting ? */ 348 if (Offset == 0) 349 { 350 Sent += send_gdb_partial_binary("<?xml version=\"1.0\"?>", 21); 351 Sent += send_gdb_partial_binary("<library-list>", 14); 352 353 CurrentEntry = ModuleListHead->Flink; 354 355 if (!CurrentEntry) 356 { 357 /* Ps is not initialized. Send end of XML data or mark that we are finished. */ 358 Sent += send_gdb_partial_binary("</library-list>", 15); 359 allDone = TRUE; 360 return finish_gdb_packet(); 361 } 362 } 363 364 for ( ; 365 CurrentEntry != ModuleListHead; 366 CurrentEntry = CurrentEntry->Flink) 367 { 368 PLDR_DATA_TABLE_ENTRY TableEntry = CONTAINING_RECORD(CurrentEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 369 PVOID DllBase = (PVOID)((ULONG_PTR)TableEntry->DllBase + 0x1000); 370 LONG mem_length; 371 USHORT i; 372 373 /* Convert names to lower case. Yes this _is_ ugly */ 374 for (i = 0; i < (TableEntry->BaseDllName.Length / sizeof(WCHAR)); i++) 375 { 376 name_helper[i] = (char)TableEntry->BaseDllName.Buffer[i]; 377 if (name_helper[i] >= 'A' && name_helper[i] <= 'Z') 378 name_helper[i] += 'a' - 'A'; 379 } 380 name_helper[i] = 0; 381 382 /* GDB doesn't load the file if you don't prefix it with a drive letter... */ 383 mem_length = _snprintf(str_helper, 256, "<library name=\"C:\\%s\"><segment address=\"0x%p\"/></library>", &name_helper, DllBase); 384 385 /* DLL name must be too long. */ 386 if (mem_length < 0) 387 { 388 KDDBGPRINT("Failed to report %wZ\n", &TableEntry->BaseDllName); 389 continue; 390 } 391 392 if ((Sent + mem_length) > ToSend) 393 { 394 /* We're done for this pass */ 395 return finish_gdb_packet(); 396 } 397 398 Sent += send_gdb_partial_binary(str_helper, mem_length); 399 } 400 401 if ((ToSend - Sent) > 15) 402 { 403 Sent += send_gdb_partial_binary("</library-list>", 15); 404 allDone = TRUE; 405 } 406 407 return finish_gdb_packet(); 408 } 409 410 KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input); 411 return send_gdb_packet(""); 412 } 413 414 #if 0 415 static 416 KDSTATUS 417 handle_gdb_registers( 418 _Out_ DBGKD_MANIPULATE_STATE64* State, 419 _Out_ PSTRING MessageData, 420 _Out_ PULONG MessageLength) 421 { 422 /* 423 if (gdb_dbg_thread) 424 KDDBGPRINT("Should get registers from other thread!\n"); 425 */ 426 427 State->ApiNumber = DbgKdGetContextApi; 428 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 429 State->Processor = CurrentStateChange.Processor; 430 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 431 if (MessageData) 432 MessageData->Length = 0; 433 *MessageLength = 0; 434 return KdPacketReceived; 435 } 436 #endif 437 438 static 439 void 440 ReadMemorySendHandler( 441 _In_ ULONG PacketType, 442 _In_ PSTRING MessageHeader, 443 _In_ PSTRING MessageData) 444 { 445 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 446 447 if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 448 { 449 // KdAssert 450 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdReadVirtualMemoryApi request.\n", PacketType); 451 while (1); 452 } 453 454 if (State->ApiNumber != DbgKdReadVirtualMemoryApi) 455 { 456 KDDBGPRINT("Wrong API number (%lu) after DbgKdReadVirtualMemoryApi request.\n", State->ApiNumber); 457 } 458 459 /* Check status. Allow to send partial data. */ 460 if (!MessageData->Length && !NT_SUCCESS(State->ReturnStatus)) 461 send_gdb_ntstatus(State->ReturnStatus); 462 else 463 send_gdb_memory(MessageData->Buffer, MessageData->Length); 464 KdpSendPacketHandler = NULL; 465 KdpManipulateStateHandler = NULL; 466 467 #if MONOPROCESS 468 if (gdb_dbg_tid != 0) 469 /* Reset the TLB */ 470 #else 471 if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) 472 #endif 473 { 474 /* Only do this if Ps is initialized */ 475 if (ProcessListHead->Flink) 476 __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]); 477 } 478 } 479 480 static 481 KDSTATUS 482 handle_gdb_read_mem( 483 _Out_ DBGKD_MANIPULATE_STATE64* State, 484 _Out_ PSTRING MessageData, 485 _Out_ PULONG MessageLength, 486 _Inout_ PKD_CONTEXT KdContext) 487 { 488 State->ApiNumber = DbgKdReadVirtualMemoryApi; 489 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 490 State->Processor = CurrentStateChange.Processor; 491 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 492 if (MessageData) 493 MessageData->Length = 0; 494 *MessageLength = 0; 495 496 /* Set the TLB according to the process being read. Pid 0 means any process. */ 497 #if MONOPROCESS 498 if ((gdb_dbg_tid != 0) && gdb_tid_to_handle(gdb_dbg_tid) != PsGetCurrentThreadId()) 499 { 500 PETHREAD AttachedThread = find_thread(0, gdb_dbg_tid); 501 PKPROCESS AttachedProcess; 502 if (AttachedThread == NULL) 503 { 504 KDDBGPRINT("The current GDB debug thread is invalid!"); 505 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 506 } 507 508 AttachedProcess = AttachedThread->Tcb.Process; 509 if (AttachedProcess == NULL) 510 { 511 KDDBGPRINT("The current GDB debug thread is invalid!"); 512 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 513 } 514 __writecr3(AttachedProcess->DirectoryTableBase[0]); 515 } 516 #else 517 if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) 518 { 519 PEPROCESS AttachedProcess = find_process(gdb_dbg_pid); 520 if (AttachedProcess == NULL) 521 { 522 KDDBGPRINT("The current GDB debug thread is invalid!"); 523 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 524 } 525 /* Only do this if Ps is initialized */ 526 if (ProcessListHead->Flink) 527 __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]); 528 } 529 #endif 530 531 State->u.ReadMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]); 532 State->u.ReadMemory.TransferCount = hex_to_address(strstr(&gdb_input[1], ",") + 1); 533 534 /* KD will reply with KdSendPacket. Catch it */ 535 KdpSendPacketHandler = ReadMemorySendHandler; 536 return KdPacketReceived; 537 } 538 539 static 540 void 541 WriteMemorySendHandler( 542 _In_ ULONG PacketType, 543 _In_ PSTRING MessageHeader, 544 _In_ PSTRING MessageData) 545 { 546 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 547 548 if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 549 { 550 // KdAssert 551 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdWriteVirtualMemoryApi request.\n", PacketType); 552 while (1); 553 } 554 555 if (State->ApiNumber != DbgKdWriteVirtualMemoryApi) 556 { 557 KDDBGPRINT("Wrong API number (%lu) after DbgKdWriteVirtualMemoryApi request.\n", State->ApiNumber); 558 } 559 560 /* Check status */ 561 if (!NT_SUCCESS(State->ReturnStatus)) 562 send_gdb_ntstatus(State->ReturnStatus); 563 else 564 send_gdb_packet("OK"); 565 KdpSendPacketHandler = NULL; 566 KdpManipulateStateHandler = NULL; 567 568 #if MONOPROCESS 569 if (gdb_dbg_tid != 0) 570 /* Reset the TLB */ 571 #else 572 if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) 573 #endif 574 { 575 /* Only do this if Ps is initialized */ 576 if (ProcessListHead->Flink) 577 __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]); 578 } 579 } 580 581 static 582 KDSTATUS 583 handle_gdb_write_mem( 584 _Out_ DBGKD_MANIPULATE_STATE64* State, 585 _Out_ PSTRING MessageData, 586 _Out_ PULONG MessageLength, 587 _Inout_ PKD_CONTEXT KdContext) 588 { 589 /* Maximal input buffer is 0x1000. Each byte is encoded on two bytes by GDB */ 590 static UCHAR OutBuffer[0x800]; 591 ULONG BufferLength; 592 char* blob_ptr; 593 UCHAR* OutPtr; 594 595 State->ApiNumber = DbgKdWriteVirtualMemoryApi; 596 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 597 State->Processor = CurrentStateChange.Processor; 598 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 599 600 /* Set the TLB according to the process being read. Pid 0 means any process. */ 601 #if MONOPROCESS 602 if ((gdb_dbg_tid != 0) && gdb_tid_to_handle(gdb_dbg_tid) != PsGetCurrentThreadId()) 603 { 604 PETHREAD AttachedThread = find_thread(0, gdb_dbg_tid); 605 PKPROCESS AttachedProcess; 606 if (AttachedThread == NULL) 607 { 608 KDDBGPRINT("The current GDB debug thread is invalid!"); 609 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 610 } 611 612 AttachedProcess = AttachedThread->Tcb.Process; 613 if (AttachedProcess == NULL) 614 { 615 KDDBGPRINT("The current GDB debug thread is invalid!"); 616 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 617 } 618 __writecr3(AttachedProcess->DirectoryTableBase[0]); 619 } 620 #else 621 if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) 622 { 623 PEPROCESS AttachedProcess = find_process(gdb_dbg_pid); 624 if (AttachedProcess == NULL) 625 { 626 KDDBGPRINT("The current GDB debug thread is invalid!"); 627 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 628 } 629 /* Only do this if Ps is initialized */ 630 if (ProcessListHead->Flink) 631 __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]); 632 } 633 #endif 634 635 State->u.WriteMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]); 636 BufferLength = hex_to_address(strstr(&gdb_input[1], ",") + 1); 637 if (BufferLength == 0) 638 { 639 /* Nothing to do */ 640 return LOOP_IF_SUCCESS(send_gdb_packet("OK")); 641 } 642 643 State->u.WriteMemory.TransferCount = BufferLength; 644 MessageData->Length = BufferLength; 645 MessageData->Buffer = (CHAR*)OutBuffer; 646 647 OutPtr = OutBuffer; 648 blob_ptr = strstr(strstr(&gdb_input[1], ",") + 1, ":") + 1; 649 while (BufferLength) 650 { 651 if (BufferLength >= 4) 652 { 653 *((ULONG*)OutPtr) = *((ULONG*)blob_ptr); 654 OutPtr += 4; 655 blob_ptr += 4; 656 BufferLength -= 4; 657 } 658 else if (BufferLength >= 2) 659 { 660 *((USHORT*)OutPtr) = *((USHORT*)blob_ptr); 661 OutPtr += 2; 662 blob_ptr += 2; 663 BufferLength -= 2; 664 } 665 else 666 { 667 *OutPtr++ = *blob_ptr++; 668 BufferLength--; 669 } 670 } 671 672 /* KD will reply with KdSendPacket. Catch it */ 673 KdpSendPacketHandler = WriteMemorySendHandler; 674 return KdPacketReceived; 675 } 676 677 static 678 void 679 WriteBreakPointSendHandler( 680 _In_ ULONG PacketType, 681 _In_ PSTRING MessageHeader, 682 _In_ PSTRING MessageData) 683 { 684 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 685 686 if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 687 { 688 // KdAssert 689 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdWriteBreakPointApi request.\n", PacketType); 690 while (1); 691 } 692 693 if (State->ApiNumber != DbgKdWriteBreakPointApi) 694 { 695 KDDBGPRINT("Wrong API number (%lu) after DbgKdWriteBreakPointApi request.\n", State->ApiNumber); 696 } 697 698 /* Check status */ 699 if (!NT_SUCCESS(State->ReturnStatus)) 700 { 701 KDDBGPRINT("Inserting breakpoint failed!\n"); 702 send_gdb_ntstatus(State->ReturnStatus); 703 } 704 else 705 { 706 /* Keep track of the address+handle couple */ 707 ULONG i; 708 for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) 709 { 710 if (BreakPointHandles[i].Address == 0) 711 { 712 BreakPointHandles[i].Address = (ULONG_PTR)State->u.WriteBreakPoint.BreakPointAddress; 713 BreakPointHandles[i].Handle = State->u.WriteBreakPoint.BreakPointHandle; 714 break; 715 } 716 } 717 send_gdb_packet("OK"); 718 } 719 KdpSendPacketHandler = NULL; 720 KdpManipulateStateHandler = NULL; 721 } 722 723 static 724 KDSTATUS 725 handle_gdb_insert_breakpoint( 726 _Out_ DBGKD_MANIPULATE_STATE64* State, 727 _Out_ PSTRING MessageData, 728 _Out_ PULONG MessageLength, 729 _Inout_ PKD_CONTEXT KdContext) 730 { 731 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 732 State->Processor = CurrentStateChange.Processor; 733 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 734 if (MessageData) 735 MessageData->Length = 0; 736 *MessageLength = 0; 737 738 switch (gdb_input[1]) 739 { 740 case '0': 741 { 742 ULONG_PTR Address = hex_to_address(&gdb_input[3]); 743 ULONG i; 744 BOOLEAN HasFreeSlot = FALSE; 745 746 KDDBGPRINT("Inserting breakpoint at %p.\n", (void*)Address); 747 748 for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) 749 { 750 if (BreakPointHandles[i].Address == 0) 751 HasFreeSlot = TRUE; 752 } 753 754 if (!HasFreeSlot) 755 { 756 /* We don't have a way to keep track of this break point. Fail. */ 757 KDDBGPRINT("No breakpoint slot available!\n"); 758 return LOOP_IF_SUCCESS(send_gdb_packet("E01")); 759 } 760 761 State->ApiNumber = DbgKdWriteBreakPointApi; 762 State->u.WriteBreakPoint.BreakPointAddress = Address; 763 /* FIXME : ignoring all other Z0 arguments */ 764 765 /* KD will reply with KdSendPacket. Catch it */ 766 KdpSendPacketHandler = WriteBreakPointSendHandler; 767 return KdPacketReceived; 768 } 769 } 770 771 KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input); 772 return LOOP_IF_SUCCESS(send_gdb_packet("E01")); 773 } 774 775 static 776 void 777 RestoreBreakPointSendHandler( 778 _In_ ULONG PacketType, 779 _In_ PSTRING MessageHeader, 780 _In_ PSTRING MessageData) 781 { 782 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 783 ULONG i; 784 785 if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 786 { 787 // KdAssert 788 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdRestoreBreakPointApi request.\n", PacketType); 789 while (1); 790 } 791 792 if (State->ApiNumber != DbgKdRestoreBreakPointApi) 793 { 794 KDDBGPRINT("Wrong API number (%lu) after DbgKdRestoreBreakPointApi request.\n", State->ApiNumber); 795 } 796 797 /* We ignore failure here. If DbgKdRestoreBreakPointApi fails, 798 * this means that the breakpoint was already invalid for KD. So clean it up on our side. */ 799 for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) 800 { 801 if (BreakPointHandles[i].Handle == State->u.RestoreBreakPoint.BreakPointHandle) 802 { 803 BreakPointHandles[i].Address = 0; 804 BreakPointHandles[i].Handle = 0; 805 break; 806 } 807 } 808 809 send_gdb_packet("OK"); 810 811 KdpSendPacketHandler = NULL; 812 KdpManipulateStateHandler = NULL; 813 } 814 815 static 816 KDSTATUS 817 handle_gdb_remove_breakpoint( 818 _Out_ DBGKD_MANIPULATE_STATE64* State, 819 _Out_ PSTRING MessageData, 820 _Out_ PULONG MessageLength, 821 _Inout_ PKD_CONTEXT KdContext) 822 { 823 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 824 State->Processor = CurrentStateChange.Processor; 825 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 826 if (MessageData) 827 MessageData->Length = 0; 828 *MessageLength = 0; 829 830 switch (gdb_input[1]) 831 { 832 case '0': 833 { 834 ULONG_PTR Address = hex_to_address(&gdb_input[3]); 835 ULONG i, Handle = 0; 836 837 KDDBGPRINT("Removing breakpoint on %p.\n", (void*)Address); 838 839 for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) 840 { 841 if (BreakPointHandles[i].Address == Address) 842 { 843 Handle = BreakPointHandles[i].Handle; 844 break; 845 } 846 } 847 848 if (Handle == 0) 849 { 850 KDDBGPRINT("Received %s, but breakpoint was never inserted ?!\n", gdb_input); 851 return LOOP_IF_SUCCESS(send_gdb_packet("E01")); 852 } 853 854 State->ApiNumber = DbgKdRestoreBreakPointApi; 855 State->u.RestoreBreakPoint.BreakPointHandle = Handle; 856 /* FIXME : ignoring all other z0 arguments */ 857 858 /* KD will reply with KdSendPacket. Catch it */ 859 KdpSendPacketHandler = RestoreBreakPointSendHandler; 860 return KdPacketReceived; 861 } 862 } 863 864 KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input); 865 return LOOP_IF_SUCCESS(send_gdb_packet("E01")); 866 } 867 868 static 869 KDSTATUS 870 handle_gdb_c( 871 _Out_ DBGKD_MANIPULATE_STATE64* State, 872 _Out_ PSTRING MessageData, 873 _Out_ PULONG MessageLength, 874 _Inout_ PKD_CONTEXT KdContext) 875 { 876 KDSTATUS Status; 877 878 /* Tell GDB everything is fine, we will handle it */ 879 Status = send_gdb_packet("OK"); 880 if (Status != KdPacketReceived) 881 return Status; 882 883 884 if (CurrentStateChange.NewState == DbgKdExceptionStateChange) 885 { 886 DBGKM_EXCEPTION64* Exception = &CurrentStateChange.u.Exception; 887 ULONG_PTR ProgramCounter = KdpGetContextPc(&CurrentContext); 888 889 /* See if we should update the program counter */ 890 if (Exception && (Exception->ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT) 891 && ((*(KD_BREAKPOINT_TYPE*)ProgramCounter) == KD_BREAKPOINT_VALUE)) 892 { 893 /* We must get past the breakpoint instruction */ 894 KdpSetContextPc(&CurrentContext, ProgramCounter + KD_BREAKPOINT_SIZE); 895 896 SetContextManipulateHandler(State, MessageData, MessageLength, KdContext); 897 KdpManipulateStateHandler = ContinueManipulateStateHandler; 898 return KdPacketReceived; 899 } 900 } 901 902 return ContinueManipulateStateHandler(State, MessageData, MessageLength, KdContext); 903 } 904 905 static 906 KDSTATUS 907 handle_gdb_C( 908 _Out_ DBGKD_MANIPULATE_STATE64* State, 909 _Out_ PSTRING MessageData, 910 _Out_ PULONG MessageLength, 911 _Inout_ PKD_CONTEXT KdContext) 912 { 913 KDSTATUS Status; 914 915 /* Tell GDB everything is fine, we will handle it */ 916 Status = send_gdb_packet("OK"); 917 if (Status != KdPacketReceived) 918 return Status; 919 920 if (CurrentStateChange.NewState == DbgKdExceptionStateChange) 921 { 922 /* Debugger didn't handle the exception, report it back to the kernel */ 923 State->u.Continue2.ContinueStatus = CurrentStateChange.u.Exception.ExceptionRecord.ExceptionCode; 924 State->ApiNumber = DbgKdContinueApi2; 925 return KdPacketReceived; 926 } 927 /* We should never reach this ? */ 928 return ContinueManipulateStateHandler(State, MessageData, MessageLength, KdContext); 929 } 930 931 static 932 KDSTATUS 933 handle_gdb_s( 934 _Out_ DBGKD_MANIPULATE_STATE64* State, 935 _Out_ PSTRING MessageData, 936 _Out_ PULONG MessageLength, 937 _Inout_ PKD_CONTEXT KdContext) 938 { 939 KDDBGPRINT("Single stepping.\n"); 940 /* Set CPU single step mode and continue */ 941 KdpSetSingleStep(&CurrentContext); 942 SetContextManipulateHandler(State, MessageData, MessageLength, KdContext); 943 KdpManipulateStateHandler = ContinueManipulateStateHandler; 944 return KdPacketReceived; 945 } 946 947 static 948 KDSTATUS 949 handle_gdb_v( 950 _Out_ DBGKD_MANIPULATE_STATE64* State, 951 _Out_ PSTRING MessageData, 952 _Out_ PULONG MessageLength, 953 _Inout_ PKD_CONTEXT KdContext) 954 { 955 if (strncmp(gdb_input, "vCont", 5) == 0) 956 { 957 if (gdb_input[5] == '?') 958 { 959 /* Report what we support */ 960 return LOOP_IF_SUCCESS(send_gdb_packet("vCont;c;s")); 961 } 962 963 if (strncmp(gdb_input, "vCont;c", 7) == 0) 964 { 965 return handle_gdb_c(State, MessageData, MessageLength, KdContext); 966 } 967 968 if (strncmp(gdb_input, "vCont;s", 7) == 0) 969 { 970 971 return handle_gdb_s(State, MessageData, MessageLength, KdContext); 972 } 973 } 974 975 KDDBGPRINT("Unhandled 'v' packet: %s\n", gdb_input); 976 return LOOP_IF_SUCCESS(send_gdb_packet("")); 977 } 978 979 KDSTATUS 980 gdb_receive_and_interpret_packet( 981 _Out_ DBGKD_MANIPULATE_STATE64* State, 982 _Out_ PSTRING MessageData, 983 _Out_ PULONG MessageLength, 984 _Inout_ PKD_CONTEXT KdContext) 985 { 986 KDSTATUS Status; 987 988 do 989 { 990 KDDBGPRINT("KDGBD: Receiving packet.\n"); 991 Status = gdb_receive_packet(KdContext); 992 KDDBGPRINT("KDGBD: Packet \"%s\" received with status %u\n", gdb_input, Status); 993 994 if (Status != KdPacketReceived) 995 return Status; 996 997 Status = (KDSTATUS)-1; 998 999 switch (gdb_input[0]) 1000 { 1001 case '?': 1002 /* Send the Status */ 1003 Status = LOOP_IF_SUCCESS(gdb_send_exception()); 1004 break; 1005 case '!': 1006 Status = LOOP_IF_SUCCESS(send_gdb_packet("OK")); 1007 break; 1008 case 'c': 1009 Status = handle_gdb_c(State, MessageData, MessageLength, KdContext); 1010 break; 1011 case 'C': 1012 Status = handle_gdb_C(State, MessageData, MessageLength, KdContext); 1013 break; 1014 case 'g': 1015 Status = LOOP_IF_SUCCESS(gdb_send_registers()); 1016 break; 1017 case 'H': 1018 Status = LOOP_IF_SUCCESS(handle_gdb_set_thread()); 1019 break; 1020 case 'm': 1021 Status = handle_gdb_read_mem(State, MessageData, MessageLength, KdContext); 1022 break; 1023 case 'p': 1024 Status = LOOP_IF_SUCCESS(gdb_send_register()); 1025 break; 1026 case 'q': 1027 Status = LOOP_IF_SUCCESS(handle_gdb_query()); 1028 break; 1029 case 's': 1030 Status = handle_gdb_s(State, MessageData, MessageLength, KdContext); 1031 break; 1032 case 'T': 1033 Status = LOOP_IF_SUCCESS(handle_gdb_thread_alive()); 1034 break; 1035 case 'v': 1036 Status = handle_gdb_v(State, MessageData, MessageLength, KdContext); 1037 break; 1038 case 'X': 1039 Status = handle_gdb_write_mem(State, MessageData, MessageLength, KdContext); 1040 break; 1041 case 'z': 1042 Status = handle_gdb_remove_breakpoint(State, MessageData, MessageLength, KdContext); 1043 break; 1044 case 'Z': 1045 Status = handle_gdb_insert_breakpoint(State, MessageData, MessageLength, KdContext); 1046 break; 1047 default: 1048 /* We don't know how to handle this request. */ 1049 KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input); 1050 Status = LOOP_IF_SUCCESS(send_gdb_packet("")); 1051 } 1052 } while (Status == (KDSTATUS)-1); 1053 1054 return Status; 1055 } 1056 1057