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 (strcmp(gdb_input, "qTStatus") == 0) 305 { 306 /* No tracepoint support */ 307 return send_gdb_packet("T0"); 308 } 309 310 if (strcmp(gdb_input, "qSymbol::") == 0) 311 { 312 /* No need */ 313 return send_gdb_packet("OK"); 314 } 315 316 if (strncmp(gdb_input, "qXfer:libraries:read::", 22) == 0) 317 { 318 static LIST_ENTRY* CurrentEntry = NULL; 319 char str_helper[256]; 320 char name_helper[64]; 321 ULONG_PTR Offset = hex_to_address(&gdb_input[22]); 322 ULONG_PTR ToSend = hex_to_address(strstr(&gdb_input[22], ",") + 1); 323 ULONG Sent = 0; 324 static BOOLEAN allDone = FALSE; 325 326 KDDBGPRINT("KDGDB: qXfer:libraries:read !\n"); 327 328 /* Start the packet */ 329 start_gdb_packet(); 330 331 if (allDone) 332 { 333 send_gdb_partial_packet("l"); 334 allDone = FALSE; 335 return finish_gdb_packet(); 336 } 337 338 send_gdb_partial_packet("m"); 339 Sent++; 340 341 /* Are we starting ? */ 342 if (Offset == 0) 343 { 344 Sent += send_gdb_partial_binary("<?xml version=\"1.0\"?>", 21); 345 Sent += send_gdb_partial_binary("<library-list>", 14); 346 347 CurrentEntry = ModuleListHead->Flink; 348 349 if (!CurrentEntry) 350 { 351 /* Ps is not initialized. Send end of XML data or mark that we are finished. */ 352 Sent += send_gdb_partial_binary("</library-list>", 15); 353 allDone = TRUE; 354 return finish_gdb_packet(); 355 } 356 } 357 358 for ( ; 359 CurrentEntry != ModuleListHead; 360 CurrentEntry = CurrentEntry->Flink) 361 { 362 PLDR_DATA_TABLE_ENTRY TableEntry = CONTAINING_RECORD(CurrentEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 363 PVOID DllBase = (PVOID)((ULONG_PTR)TableEntry->DllBase + 0x1000); 364 LONG mem_length; 365 USHORT i; 366 367 /* Convert names to lower case. Yes this _is_ ugly */ 368 for (i = 0; i < (TableEntry->BaseDllName.Length / sizeof(WCHAR)); i++) 369 { 370 name_helper[i] = (char)TableEntry->BaseDllName.Buffer[i]; 371 if (name_helper[i] >= 'A' && name_helper[i] <= 'Z') 372 name_helper[i] += 'a' - 'A'; 373 } 374 name_helper[i] = 0; 375 376 /* GDB doesn't load the file if you don't prefix it with a drive letter... */ 377 mem_length = _snprintf(str_helper, 256, "<library name=\"C:\\%s\"><segment address=\"0x%p\"/></library>", &name_helper, DllBase); 378 379 /* DLL name must be too long. */ 380 if (mem_length < 0) 381 { 382 KDDBGPRINT("Failed to report %wZ\n", &TableEntry->BaseDllName); 383 continue; 384 } 385 386 if ((Sent + mem_length) > ToSend) 387 { 388 /* We're done for this pass */ 389 return finish_gdb_packet(); 390 } 391 392 Sent += send_gdb_partial_binary(str_helper, mem_length); 393 } 394 395 if ((ToSend - Sent) > 15) 396 { 397 Sent += send_gdb_partial_binary("</library-list>", 15); 398 allDone = TRUE; 399 } 400 401 return finish_gdb_packet(); 402 } 403 404 KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input); 405 return send_gdb_packet(""); 406 } 407 408 #if 0 409 static 410 KDSTATUS 411 handle_gdb_registers( 412 _Out_ DBGKD_MANIPULATE_STATE64* State, 413 _Out_ PSTRING MessageData, 414 _Out_ PULONG MessageLength) 415 { 416 /* 417 if (gdb_dbg_thread) 418 KDDBGPRINT("Should get registers from other thread!\n"); 419 */ 420 421 State->ApiNumber = DbgKdGetContextApi; 422 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 423 State->Processor = CurrentStateChange.Processor; 424 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 425 if (MessageData) 426 MessageData->Length = 0; 427 *MessageLength = 0; 428 return KdPacketReceived; 429 } 430 #endif 431 432 static 433 BOOLEAN 434 ReadMemorySendHandler( 435 _In_ ULONG PacketType, 436 _In_ PSTRING MessageHeader, 437 _In_ PSTRING MessageData) 438 { 439 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 440 441 if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 442 { 443 // KdAssert 444 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdReadVirtualMemoryApi request.\n", PacketType); 445 return FALSE; 446 } 447 448 if (State->ApiNumber != DbgKdReadVirtualMemoryApi) 449 { 450 KDDBGPRINT("Wrong API number (%lu) after DbgKdReadVirtualMemoryApi request.\n", State->ApiNumber); 451 return FALSE; 452 } 453 454 /* Check status. Allow to send partial data. */ 455 if (!MessageData->Length && !NT_SUCCESS(State->ReturnStatus)) 456 send_gdb_ntstatus(State->ReturnStatus); 457 else 458 send_gdb_memory(MessageData->Buffer, MessageData->Length); 459 KdpSendPacketHandler = NULL; 460 KdpManipulateStateHandler = NULL; 461 462 #if MONOPROCESS 463 if (gdb_dbg_tid != 0) 464 /* Reset the TLB */ 465 #else 466 if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) 467 #endif 468 { 469 /* Only do this if Ps is initialized */ 470 if (ProcessListHead->Flink) 471 __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]); 472 } 473 474 return TRUE; 475 } 476 477 static 478 KDSTATUS 479 handle_gdb_read_mem( 480 _Out_ DBGKD_MANIPULATE_STATE64* State, 481 _Out_ PSTRING MessageData, 482 _Out_ PULONG MessageLength, 483 _Inout_ PKD_CONTEXT KdContext) 484 { 485 State->ApiNumber = DbgKdReadVirtualMemoryApi; 486 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 487 State->Processor = CurrentStateChange.Processor; 488 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 489 if (MessageData) 490 MessageData->Length = 0; 491 *MessageLength = 0; 492 493 /* Set the TLB according to the process being read. Pid 0 means any process. */ 494 #if MONOPROCESS 495 if ((gdb_dbg_tid != 0) && gdb_tid_to_handle(gdb_dbg_tid) != PsGetCurrentThreadId()) 496 { 497 PETHREAD AttachedThread = find_thread(0, gdb_dbg_tid); 498 PKPROCESS AttachedProcess; 499 if (AttachedThread == NULL) 500 { 501 KDDBGPRINT("The current GDB debug thread is invalid!"); 502 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 503 } 504 505 AttachedProcess = AttachedThread->Tcb.Process; 506 if (AttachedProcess == NULL) 507 { 508 KDDBGPRINT("The current GDB debug thread is invalid!"); 509 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 510 } 511 __writecr3(AttachedProcess->DirectoryTableBase[0]); 512 } 513 #else 514 if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) 515 { 516 PEPROCESS AttachedProcess = find_process(gdb_dbg_pid); 517 if (AttachedProcess == NULL) 518 { 519 KDDBGPRINT("The current GDB debug thread is invalid!"); 520 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 521 } 522 /* Only do this if Ps is initialized */ 523 if (ProcessListHead->Flink) 524 __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]); 525 } 526 #endif 527 528 State->u.ReadMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]); 529 State->u.ReadMemory.TransferCount = hex_to_address(strstr(&gdb_input[1], ",") + 1); 530 531 /* KD will reply with KdSendPacket. Catch it */ 532 KdpSendPacketHandler = ReadMemorySendHandler; 533 return KdPacketReceived; 534 } 535 536 static 537 BOOLEAN 538 WriteMemorySendHandler( 539 _In_ ULONG PacketType, 540 _In_ PSTRING MessageHeader, 541 _In_ PSTRING MessageData) 542 { 543 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 544 545 if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 546 { 547 // KdAssert 548 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdWriteVirtualMemoryApi request.\n", PacketType); 549 return FALSE; 550 } 551 552 if (State->ApiNumber != DbgKdWriteVirtualMemoryApi) 553 { 554 KDDBGPRINT("Wrong API number (%lu) after DbgKdWriteVirtualMemoryApi request.\n", State->ApiNumber); 555 return FALSE; 556 } 557 558 /* Check status */ 559 if (!NT_SUCCESS(State->ReturnStatus)) 560 send_gdb_ntstatus(State->ReturnStatus); 561 else 562 send_gdb_packet("OK"); 563 KdpSendPacketHandler = NULL; 564 KdpManipulateStateHandler = NULL; 565 566 #if MONOPROCESS 567 if (gdb_dbg_tid != 0) 568 /* Reset the TLB */ 569 #else 570 if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) 571 #endif 572 { 573 /* Only do this if Ps is initialized */ 574 if (ProcessListHead->Flink) 575 __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]); 576 } 577 return TRUE; 578 } 579 580 static 581 KDSTATUS 582 handle_gdb_write_mem( 583 _Out_ DBGKD_MANIPULATE_STATE64* State, 584 _Out_ PSTRING MessageData, 585 _Out_ PULONG MessageLength, 586 _Inout_ PKD_CONTEXT KdContext) 587 { 588 /* Maximal input buffer is 0x1000. Each byte is encoded on two bytes by GDB */ 589 static UCHAR OutBuffer[0x800]; 590 ULONG BufferLength; 591 char* blob_ptr; 592 UCHAR* OutPtr; 593 594 State->ApiNumber = DbgKdWriteVirtualMemoryApi; 595 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 596 State->Processor = CurrentStateChange.Processor; 597 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 598 599 /* Set the TLB according to the process being read. Pid 0 means any process. */ 600 #if MONOPROCESS 601 if ((gdb_dbg_tid != 0) && gdb_tid_to_handle(gdb_dbg_tid) != PsGetCurrentThreadId()) 602 { 603 PETHREAD AttachedThread = find_thread(0, gdb_dbg_tid); 604 PKPROCESS AttachedProcess; 605 if (AttachedThread == NULL) 606 { 607 KDDBGPRINT("The current GDB debug thread is invalid!"); 608 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 609 } 610 611 AttachedProcess = AttachedThread->Tcb.Process; 612 if (AttachedProcess == NULL) 613 { 614 KDDBGPRINT("The current GDB debug thread is invalid!"); 615 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 616 } 617 __writecr3(AttachedProcess->DirectoryTableBase[0]); 618 } 619 #else 620 if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) 621 { 622 PEPROCESS AttachedProcess = find_process(gdb_dbg_pid); 623 if (AttachedProcess == NULL) 624 { 625 KDDBGPRINT("The current GDB debug thread is invalid!"); 626 return LOOP_IF_SUCCESS(send_gdb_packet("E03")); 627 } 628 /* Only do this if Ps is initialized */ 629 if (ProcessListHead->Flink) 630 __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]); 631 } 632 #endif 633 634 State->u.WriteMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]); 635 BufferLength = hex_to_address(strstr(&gdb_input[1], ",") + 1); 636 if (BufferLength == 0) 637 { 638 /* Nothing to do */ 639 return LOOP_IF_SUCCESS(send_gdb_packet("OK")); 640 } 641 642 State->u.WriteMemory.TransferCount = BufferLength; 643 MessageData->Length = BufferLength; 644 MessageData->Buffer = (CHAR*)OutBuffer; 645 646 OutPtr = OutBuffer; 647 blob_ptr = strstr(strstr(&gdb_input[1], ",") + 1, ":") + 1; 648 while (BufferLength) 649 { 650 if (BufferLength >= 4) 651 { 652 *((ULONG*)OutPtr) = *((ULONG*)blob_ptr); 653 OutPtr += 4; 654 blob_ptr += 4; 655 BufferLength -= 4; 656 } 657 else if (BufferLength >= 2) 658 { 659 *((USHORT*)OutPtr) = *((USHORT*)blob_ptr); 660 OutPtr += 2; 661 blob_ptr += 2; 662 BufferLength -= 2; 663 } 664 else 665 { 666 *OutPtr++ = *blob_ptr++; 667 BufferLength--; 668 } 669 } 670 671 /* KD will reply with KdSendPacket. Catch it */ 672 KdpSendPacketHandler = WriteMemorySendHandler; 673 return KdPacketReceived; 674 } 675 676 static 677 BOOLEAN 678 WriteBreakPointSendHandler( 679 _In_ ULONG PacketType, 680 _In_ PSTRING MessageHeader, 681 _In_ PSTRING MessageData) 682 { 683 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 684 685 if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 686 { 687 // KdAssert 688 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdWriteBreakPointApi request.\n", PacketType); 689 return FALSE; 690 } 691 692 if (State->ApiNumber != DbgKdWriteBreakPointApi) 693 { 694 KDDBGPRINT("Wrong API number (%lu) after DbgKdWriteBreakPointApi request.\n", State->ApiNumber); 695 return FALSE; 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 return TRUE; 722 } 723 724 static 725 KDSTATUS 726 handle_gdb_insert_breakpoint( 727 _Out_ DBGKD_MANIPULATE_STATE64* State, 728 _Out_ PSTRING MessageData, 729 _Out_ PULONG MessageLength, 730 _Inout_ PKD_CONTEXT KdContext) 731 { 732 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 733 State->Processor = CurrentStateChange.Processor; 734 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 735 if (MessageData) 736 MessageData->Length = 0; 737 *MessageLength = 0; 738 739 switch (gdb_input[1]) 740 { 741 case '0': 742 { 743 ULONG_PTR Address = hex_to_address(&gdb_input[3]); 744 ULONG i; 745 BOOLEAN HasFreeSlot = FALSE; 746 747 KDDBGPRINT("Inserting breakpoint at %p.\n", (void*)Address); 748 749 for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) 750 { 751 if (BreakPointHandles[i].Address == 0) 752 HasFreeSlot = TRUE; 753 } 754 755 if (!HasFreeSlot) 756 { 757 /* We don't have a way to keep track of this break point. Fail. */ 758 KDDBGPRINT("No breakpoint slot available!\n"); 759 return LOOP_IF_SUCCESS(send_gdb_packet("E01")); 760 } 761 762 State->ApiNumber = DbgKdWriteBreakPointApi; 763 State->u.WriteBreakPoint.BreakPointAddress = Address; 764 /* FIXME : ignoring all other Z0 arguments */ 765 766 /* KD will reply with KdSendPacket. Catch it */ 767 KdpSendPacketHandler = WriteBreakPointSendHandler; 768 return KdPacketReceived; 769 } 770 } 771 772 KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input); 773 return LOOP_IF_SUCCESS(send_gdb_packet("E01")); 774 } 775 776 static 777 BOOLEAN 778 RestoreBreakPointSendHandler( 779 _In_ ULONG PacketType, 780 _In_ PSTRING MessageHeader, 781 _In_ PSTRING MessageData) 782 { 783 DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer; 784 ULONG i; 785 786 if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE) 787 { 788 // KdAssert 789 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdRestoreBreakPointApi request.\n", PacketType); 790 return FALSE; 791 } 792 793 if (State->ApiNumber != DbgKdRestoreBreakPointApi) 794 { 795 KDDBGPRINT("Wrong API number (%lu) after DbgKdRestoreBreakPointApi request.\n", State->ApiNumber); 796 return FALSE; 797 } 798 799 /* We ignore failure here. If DbgKdRestoreBreakPointApi fails, 800 * this means that the breakpoint was already invalid for KD. So clean it up on our side. */ 801 for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) 802 { 803 if (BreakPointHandles[i].Handle == State->u.RestoreBreakPoint.BreakPointHandle) 804 { 805 BreakPointHandles[i].Address = 0; 806 BreakPointHandles[i].Handle = 0; 807 break; 808 } 809 } 810 811 send_gdb_packet("OK"); 812 813 KdpSendPacketHandler = NULL; 814 KdpManipulateStateHandler = NULL; 815 return TRUE; 816 } 817 818 static 819 KDSTATUS 820 handle_gdb_remove_breakpoint( 821 _Out_ DBGKD_MANIPULATE_STATE64* State, 822 _Out_ PSTRING MessageData, 823 _Out_ PULONG MessageLength, 824 _Inout_ PKD_CONTEXT KdContext) 825 { 826 State->ReturnStatus = STATUS_SUCCESS; /* ? */ 827 State->Processor = CurrentStateChange.Processor; 828 State->ProcessorLevel = CurrentStateChange.ProcessorLevel; 829 if (MessageData) 830 MessageData->Length = 0; 831 *MessageLength = 0; 832 833 switch (gdb_input[1]) 834 { 835 case '0': 836 { 837 ULONG_PTR Address = hex_to_address(&gdb_input[3]); 838 ULONG i, Handle = 0; 839 840 KDDBGPRINT("Removing breakpoint on %p.\n", (void*)Address); 841 842 for (i = 0; i < (sizeof(BreakPointHandles) / sizeof(BreakPointHandles[0])); i++) 843 { 844 if (BreakPointHandles[i].Address == Address) 845 { 846 Handle = BreakPointHandles[i].Handle; 847 break; 848 } 849 } 850 851 if (Handle == 0) 852 { 853 KDDBGPRINT("Received %s, but breakpoint was never inserted ?!\n", gdb_input); 854 return LOOP_IF_SUCCESS(send_gdb_packet("E01")); 855 } 856 857 State->ApiNumber = DbgKdRestoreBreakPointApi; 858 State->u.RestoreBreakPoint.BreakPointHandle = Handle; 859 /* FIXME : ignoring all other z0 arguments */ 860 861 /* KD will reply with KdSendPacket. Catch it */ 862 KdpSendPacketHandler = RestoreBreakPointSendHandler; 863 return KdPacketReceived; 864 } 865 } 866 867 KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input); 868 return LOOP_IF_SUCCESS(send_gdb_packet("E01")); 869 } 870 871 static 872 KDSTATUS 873 handle_gdb_c( 874 _Out_ DBGKD_MANIPULATE_STATE64* State, 875 _Out_ PSTRING MessageData, 876 _Out_ PULONG MessageLength, 877 _Inout_ PKD_CONTEXT KdContext) 878 { 879 KDSTATUS Status; 880 881 /* Tell GDB everything is fine, we will handle it */ 882 Status = send_gdb_packet("OK"); 883 if (Status != KdPacketReceived) 884 return Status; 885 886 887 if (CurrentStateChange.NewState == DbgKdExceptionStateChange) 888 { 889 DBGKM_EXCEPTION64* Exception = &CurrentStateChange.u.Exception; 890 ULONG_PTR ProgramCounter = KdpGetContextPc(&CurrentContext); 891 892 /* See if we should update the program counter */ 893 if (Exception && (Exception->ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT) 894 && ((*(KD_BREAKPOINT_TYPE*)ProgramCounter) == KD_BREAKPOINT_VALUE)) 895 { 896 /* We must get past the breakpoint instruction */ 897 KdpSetContextPc(&CurrentContext, ProgramCounter + KD_BREAKPOINT_SIZE); 898 899 SetContextManipulateHandler(State, MessageData, MessageLength, KdContext); 900 KdpManipulateStateHandler = ContinueManipulateStateHandler; 901 return KdPacketReceived; 902 } 903 } 904 905 return ContinueManipulateStateHandler(State, MessageData, MessageLength, KdContext); 906 } 907 908 static 909 KDSTATUS 910 handle_gdb_C( 911 _Out_ DBGKD_MANIPULATE_STATE64* State, 912 _Out_ PSTRING MessageData, 913 _Out_ PULONG MessageLength, 914 _Inout_ PKD_CONTEXT KdContext) 915 { 916 KDSTATUS Status; 917 918 /* Tell GDB everything is fine, we will handle it */ 919 Status = send_gdb_packet("OK"); 920 if (Status != KdPacketReceived) 921 return Status; 922 923 if (CurrentStateChange.NewState == DbgKdExceptionStateChange) 924 { 925 /* Debugger didn't handle the exception, report it back to the kernel */ 926 State->u.Continue2.ContinueStatus = CurrentStateChange.u.Exception.ExceptionRecord.ExceptionCode; 927 State->ApiNumber = DbgKdContinueApi2; 928 return KdPacketReceived; 929 } 930 /* We should never reach this ? */ 931 return ContinueManipulateStateHandler(State, MessageData, MessageLength, KdContext); 932 } 933 934 static 935 KDSTATUS 936 handle_gdb_s( 937 _Out_ DBGKD_MANIPULATE_STATE64* State, 938 _Out_ PSTRING MessageData, 939 _Out_ PULONG MessageLength, 940 _Inout_ PKD_CONTEXT KdContext) 941 { 942 KDDBGPRINT("Single stepping.\n"); 943 /* Set CPU single step mode and continue */ 944 KdpSetSingleStep(&CurrentContext); 945 SetContextManipulateHandler(State, MessageData, MessageLength, KdContext); 946 KdpManipulateStateHandler = ContinueManipulateStateHandler; 947 return KdPacketReceived; 948 } 949 950 static 951 KDSTATUS 952 handle_gdb_v( 953 _Out_ DBGKD_MANIPULATE_STATE64* State, 954 _Out_ PSTRING MessageData, 955 _Out_ PULONG MessageLength, 956 _Inout_ PKD_CONTEXT KdContext) 957 { 958 if (strncmp(gdb_input, "vCont", 5) == 0) 959 { 960 if (gdb_input[5] == '?') 961 { 962 /* Report what we support */ 963 return LOOP_IF_SUCCESS(send_gdb_packet("vCont;c;s")); 964 } 965 966 if (strncmp(gdb_input, "vCont;c", 7) == 0) 967 { 968 return handle_gdb_c(State, MessageData, MessageLength, KdContext); 969 } 970 971 if (strncmp(gdb_input, "vCont;s", 7) == 0) 972 { 973 974 return handle_gdb_s(State, MessageData, MessageLength, KdContext); 975 } 976 } 977 978 KDDBGPRINT("Unhandled 'v' packet: %s\n", gdb_input); 979 return LOOP_IF_SUCCESS(send_gdb_packet("")); 980 } 981 982 KDSTATUS 983 gdb_receive_and_interpret_packet( 984 _Out_ DBGKD_MANIPULATE_STATE64* State, 985 _Out_ PSTRING MessageData, 986 _Out_ PULONG MessageLength, 987 _Inout_ PKD_CONTEXT KdContext) 988 { 989 KDSTATUS Status; 990 991 do 992 { 993 KDDBGPRINT("KDGBD: Receiving packet.\n"); 994 Status = gdb_receive_packet(KdContext); 995 KDDBGPRINT("KDGBD: Packet \"%s\" received with status %u\n", gdb_input, Status); 996 997 if (Status != KdPacketReceived) 998 return Status; 999 1000 Status = (KDSTATUS)-1; 1001 1002 switch (gdb_input[0]) 1003 { 1004 case '?': 1005 /* Send the Status */ 1006 Status = LOOP_IF_SUCCESS(gdb_send_exception()); 1007 break; 1008 case '!': 1009 Status = LOOP_IF_SUCCESS(send_gdb_packet("OK")); 1010 break; 1011 case 'c': 1012 Status = handle_gdb_c(State, MessageData, MessageLength, KdContext); 1013 break; 1014 case 'C': 1015 Status = handle_gdb_C(State, MessageData, MessageLength, KdContext); 1016 break; 1017 case 'g': 1018 Status = LOOP_IF_SUCCESS(gdb_send_registers()); 1019 break; 1020 case 'H': 1021 Status = LOOP_IF_SUCCESS(handle_gdb_set_thread()); 1022 break; 1023 case 'm': 1024 Status = handle_gdb_read_mem(State, MessageData, MessageLength, KdContext); 1025 break; 1026 case 'p': 1027 Status = LOOP_IF_SUCCESS(gdb_send_register()); 1028 break; 1029 case 'q': 1030 Status = LOOP_IF_SUCCESS(handle_gdb_query()); 1031 break; 1032 case 's': 1033 Status = handle_gdb_s(State, MessageData, MessageLength, KdContext); 1034 break; 1035 case 'T': 1036 Status = LOOP_IF_SUCCESS(handle_gdb_thread_alive()); 1037 break; 1038 case 'v': 1039 Status = handle_gdb_v(State, MessageData, MessageLength, KdContext); 1040 break; 1041 case 'X': 1042 Status = handle_gdb_write_mem(State, MessageData, MessageLength, KdContext); 1043 break; 1044 case 'z': 1045 Status = handle_gdb_remove_breakpoint(State, MessageData, MessageLength, KdContext); 1046 break; 1047 case 'Z': 1048 Status = handle_gdb_insert_breakpoint(State, MessageData, MessageLength, KdContext); 1049 break; 1050 default: 1051 /* We don't know how to handle this request. */ 1052 KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input); 1053 Status = LOOP_IF_SUCCESS(send_gdb_packet("")); 1054 } 1055 } while (Status == (KDSTATUS)-1); 1056 1057 return Status; 1058 } 1059 1060