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