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.
10 /* LOCALS *********************************************************************/
11 static ULONG_PTR gdb_run_tid
;
16 } BreakPointHandles
[32];
19 /* GLOBALS ********************************************************************/
27 return (x
== KdPacketReceived
) ? (KDSTATUS
)-1 : x
;
30 /* PRIVATE FUNCTIONS **********************************************************/
33 hex_to_tid(char* buffer
)
39 hex
= hex_value(*buffer
++);
47 #define hex_to_pid hex_to_tid
51 hex_to_address(char* buffer
)
57 hex
= hex_value(*buffer
++);
69 handle_gdb_set_thread(void)
76 if (strcmp(&gdb_input
[2], "-1") == 0)
77 gdb_run_tid
= (ULONG_PTR
)-1;
79 gdb_run_tid
= hex_to_tid(&gdb_input
[2]);
80 Status
= send_gdb_packet("OK");
83 KDDBGPRINT("Setting debug thread: %s.\n", gdb_input
);
86 if (strncmp(&gdb_input
[2], "-1", 2) == 0)
88 gdb_dbg_tid
= (UINT_PTR
)-1;
92 gdb_dbg_tid
= hex_to_tid(&gdb_input
[2]);
95 if (strncmp(&gdb_input
[2], "p-1", 3) == 0)
97 gdb_dbg_pid
= (UINT_PTR
)-1;
98 gdb_dbg_tid
= (UINT_PTR
)-1;
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;
107 gdb_dbg_tid
= hex_to_tid(ptr
);
110 Status
= send_gdb_packet("OK");
113 KDDBGPRINT("KDGBD: Unknown 'H' command: %s\n", gdb_input
);
114 Status
= send_gdb_packet("");
122 handle_gdb_thread_alive(void)
130 Tid
= hex_to_tid(&gdb_input
[1]);
132 KDDBGPRINT("Checking if %p is alive.\n", Tid
);
135 Pid
= hex_to_pid(&gdb_input
[2]);
136 Tid
= hex_to_tid(strstr(gdb_input
, ".") + 1);
138 /* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL.
140 KDDBGPRINT("Checking if p%p.%p is alive.\n", Pid
, Tid
);
143 Thread
= find_thread(Pid
, Tid
);
146 Status
= send_gdb_packet("OK");
148 Status
= send_gdb_packet("E03");
156 handle_gdb_query(void)
158 if (strncmp(gdb_input
, "qSupported:", 11) == 0)
161 return send_gdb_packet("PacketSize=1000;qXfer:libraries:read+;");
163 return send_gdb_packet("PacketSize=1000;multiprocess+;qXfer:libraries:read+;");
167 if (strncmp(gdb_input
, "qAttached", 9) == 0)
170 return send_gdb_packet("1");
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");
177 return send_gdb_packet("1");
181 if (strncmp(gdb_input
, "qRcmd,", 6) == 0)
183 return send_gdb_packet("OK");
186 if (strcmp(gdb_input
, "qC") == 0)
190 sprintf(gdb_out
, "QC:%"PRIxPTR
";",
191 handle_to_gdb_tid(PsGetThreadId((PETHREAD
)(ULONG_PTR
)CurrentStateChange
.Thread
)));
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
)));
197 return send_gdb_packet(gdb_out
);
200 if (strncmp(gdb_input
, "qfThreadInfo", 12) == 0)
204 LIST_ENTRY
* CurrentProcessEntry
;
206 CurrentProcessEntry
= ProcessListHead
->Flink
;
207 if (CurrentProcessEntry
== NULL
) /* Ps is not initialized */
210 return send_gdb_packet("m1");
212 return send_gdb_packet("mp1.1");
216 /* We will push threads as we find them */
219 /* Start with the system thread */
221 send_gdb_partial_packet("m1");
223 send_gdb_partial_packet("mp1.1");
226 /* List all the processes */
228 CurrentProcessEntry
!= ProcessListHead
;
229 CurrentProcessEntry
= CurrentProcessEntry
->Flink
)
231 LIST_ENTRY
* CurrentThreadEntry
;
233 Process
= CONTAINING_RECORD(CurrentProcessEntry
, EPROCESS
, ActiveProcessLinks
);
235 /* List threads from this process */
236 for ( CurrentThreadEntry
= Process
->ThreadListHead
.Flink
;
237 CurrentThreadEntry
!= &Process
->ThreadListHead
;
238 CurrentThreadEntry
= CurrentThreadEntry
->Flink
)
240 PETHREAD Thread
= CONTAINING_RECORD(CurrentThreadEntry
, ETHREAD
, ThreadListEntry
);
243 _snprintf(gdb_out
, 40, ",%p", handle_to_gdb_tid(Thread
->Cid
.UniqueThread
));
245 _snprintf(gdb_out
, 40, ",p%p.%p",
246 handle_to_gdb_pid(Process
->UniqueProcessId
),
247 handle_to_gdb_tid(Thread
->Cid
.UniqueThread
));
249 send_gdb_partial_packet(gdb_out
);
253 return finish_gdb_packet();
256 if (strncmp(gdb_input
, "qsThreadInfo", 12) == 0)
258 /* We sent the whole thread list on first qfThreadInfo call */
259 return send_gdb_packet("l");
262 if (strncmp(gdb_input
, "qThreadExtraInfo,", 17) == 0)
268 STRING String
= {0, 64, out_string
};
270 KDDBGPRINT("Giving extra info for");
274 Tid
= hex_to_tid(&gdb_input
[17]);
276 KDDBGPRINT(" %p.\n", Tid
);
278 Thread
= find_thread(Pid
, Tid
);
279 Process
= CONTAINING_RECORD(Thread
->Tcb
.Process
, EPROCESS
, Pcb
);
281 Pid
= hex_to_pid(&gdb_input
[18]);
282 Tid
= hex_to_tid(strstr(&gdb_input
[18], ".") + 1);
284 /* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL.
286 KDDBGPRINT(" p%p.%p.\n", Pid
, Tid
);
288 Process
= find_process(Pid
);
289 Thread
= find_thread(Pid
, Tid
);
292 if (PsGetThreadProcessId(Thread
) == 0)
294 String
.Length
= sprintf(out_string
, "SYSTEM");
298 String
.Length
= sprintf(out_string
, "%.*s", 16, Process
->ImageFileName
);
301 return gdb_send_debug_io(&String
, FALSE
);
304 if (strncmp(gdb_input
, "qOffsets", 8) == 0)
306 /* We load ntoskrnl at 0x80800000 while compiling it at 0x00800000 base address */
307 return send_gdb_packet("TextSeg=80000000");
310 if (strcmp(gdb_input
, "qTStatus") == 0)
312 /* No tracepoint support */
313 return send_gdb_packet("T0");
316 if (strcmp(gdb_input
, "qSymbol::") == 0)
319 return send_gdb_packet("OK");
322 if (strncmp(gdb_input
, "qXfer:libraries:read::", 22) == 0)
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);
330 static BOOLEAN allDone
= FALSE
;
332 KDDBGPRINT("KDGDB: qXfer:libraries:read !\n");
334 /* Start the packet */
339 send_gdb_partial_packet("l");
341 return finish_gdb_packet();
344 send_gdb_partial_packet("m");
347 /* Are we starting ? */
350 Sent
+= send_gdb_partial_binary("<?xml version=\"1.0\"?>", 21);
351 Sent
+= send_gdb_partial_binary("<library-list>", 14);
353 CurrentEntry
= ModuleListHead
->Flink
;
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);
360 return finish_gdb_packet();
365 CurrentEntry
!= ModuleListHead
;
366 CurrentEntry
= CurrentEntry
->Flink
)
368 PLDR_DATA_TABLE_ENTRY TableEntry
= CONTAINING_RECORD(CurrentEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
369 PVOID DllBase
= (PVOID
)((ULONG_PTR
)TableEntry
->DllBase
+ 0x1000);
373 /* Convert names to lower case. Yes this _is_ ugly */
374 for (i
= 0; i
< (TableEntry
->BaseDllName
.Length
/ sizeof(WCHAR
)); i
++)
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';
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
);
385 /* DLL name must be too long. */
388 KDDBGPRINT("Failed to report %wZ\n", &TableEntry
->BaseDllName
);
392 if ((Sent
+ mem_length
) > ToSend
)
394 /* We're done for this pass */
395 return finish_gdb_packet();
398 Sent
+= send_gdb_partial_binary(str_helper
, mem_length
);
401 if ((ToSend
- Sent
) > 15)
403 Sent
+= send_gdb_partial_binary("</library-list>", 15);
407 return finish_gdb_packet();
410 KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input
);
411 return send_gdb_packet("");
417 handle_gdb_registers(
418 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
419 _Out_ PSTRING MessageData
,
420 _Out_ PULONG MessageLength
)
424 KDDBGPRINT("Should get registers from other thread!\n");
427 State
->ApiNumber
= DbgKdGetContextApi
;
428 State
->ReturnStatus
= STATUS_SUCCESS
; /* ? */
429 State
->Processor
= CurrentStateChange
.Processor
;
430 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
432 MessageData
->Length
= 0;
434 return KdPacketReceived
;
440 ReadMemorySendHandler(
441 _In_ ULONG PacketType
,
442 _In_ PSTRING MessageHeader
,
443 _In_ PSTRING MessageData
)
445 DBGKD_MANIPULATE_STATE64
* State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
447 if (PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
450 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdReadVirtualMemoryApi request.\n", PacketType
);
454 if (State
->ApiNumber
!= DbgKdReadVirtualMemoryApi
)
456 KDDBGPRINT("Wrong API number (%lu) after DbgKdReadVirtualMemoryApi request.\n", State
->ApiNumber
);
459 /* Check status. Allow to send partial data. */
460 if (!MessageData
->Length
&& !NT_SUCCESS(State
->ReturnStatus
))
461 send_gdb_ntstatus(State
->ReturnStatus
);
463 send_gdb_memory(MessageData
->Buffer
, MessageData
->Length
);
464 KdpSendPacketHandler
= NULL
;
465 KdpManipulateStateHandler
= NULL
;
468 if (gdb_dbg_tid
!= 0)
471 if ((gdb_dbg_pid
!= 0) && gdb_pid_to_handle(gdb_dbg_pid
) != PsGetCurrentProcessId())
474 /* Only do this if Ps is initialized */
475 if (ProcessListHead
->Flink
)
476 __writecr3(PsGetCurrentProcess()->Pcb
.DirectoryTableBase
[0]);
483 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
484 _Out_ PSTRING MessageData
,
485 _Out_ PULONG MessageLength
,
486 _Inout_ PKD_CONTEXT KdContext
)
488 State
->ApiNumber
= DbgKdReadVirtualMemoryApi
;
489 State
->ReturnStatus
= STATUS_SUCCESS
; /* ? */
490 State
->Processor
= CurrentStateChange
.Processor
;
491 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
493 MessageData
->Length
= 0;
496 /* Set the TLB according to the process being read. Pid 0 means any process. */
498 if ((gdb_dbg_tid
!= 0) && gdb_tid_to_handle(gdb_dbg_tid
) != PsGetCurrentThreadId())
500 PETHREAD AttachedThread
= find_thread(0, gdb_dbg_tid
);
501 PKPROCESS AttachedProcess
;
502 if (AttachedThread
== NULL
)
504 KDDBGPRINT("The current GDB debug thread is invalid!");
505 return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
508 AttachedProcess
= AttachedThread
->Tcb
.Process
;
509 if (AttachedProcess
== NULL
)
511 KDDBGPRINT("The current GDB debug thread is invalid!");
512 return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
514 __writecr3(AttachedProcess
->DirectoryTableBase
[0]);
517 if ((gdb_dbg_pid
!= 0) && gdb_pid_to_handle(gdb_dbg_pid
) != PsGetCurrentProcessId())
519 PEPROCESS AttachedProcess
= find_process(gdb_dbg_pid
);
520 if (AttachedProcess
== NULL
)
522 KDDBGPRINT("The current GDB debug thread is invalid!");
523 return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
525 /* Only do this if Ps is initialized */
526 if (ProcessListHead
->Flink
)
527 __writecr3(AttachedProcess
->Pcb
.DirectoryTableBase
[0]);
531 State
->u
.ReadMemory
.TargetBaseAddress
= hex_to_address(&gdb_input
[1]);
532 State
->u
.ReadMemory
.TransferCount
= hex_to_address(strstr(&gdb_input
[1], ",") + 1);
534 /* KD will reply with KdSendPacket. Catch it */
535 KdpSendPacketHandler
= ReadMemorySendHandler
;
536 return KdPacketReceived
;
541 WriteMemorySendHandler(
542 _In_ ULONG PacketType
,
543 _In_ PSTRING MessageHeader
,
544 _In_ PSTRING MessageData
)
546 DBGKD_MANIPULATE_STATE64
* State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
548 if (PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
551 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdWriteVirtualMemoryApi request.\n", PacketType
);
555 if (State
->ApiNumber
!= DbgKdWriteVirtualMemoryApi
)
557 KDDBGPRINT("Wrong API number (%lu) after DbgKdWriteVirtualMemoryApi request.\n", State
->ApiNumber
);
561 if (!NT_SUCCESS(State
->ReturnStatus
))
562 send_gdb_ntstatus(State
->ReturnStatus
);
564 send_gdb_packet("OK");
565 KdpSendPacketHandler
= NULL
;
566 KdpManipulateStateHandler
= NULL
;
569 if (gdb_dbg_tid
!= 0)
572 if ((gdb_dbg_pid
!= 0) && gdb_pid_to_handle(gdb_dbg_pid
) != PsGetCurrentProcessId())
575 /* Only do this if Ps is initialized */
576 if (ProcessListHead
->Flink
)
577 __writecr3(PsGetCurrentProcess()->Pcb
.DirectoryTableBase
[0]);
583 handle_gdb_write_mem(
584 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
585 _Out_ PSTRING MessageData
,
586 _Out_ PULONG MessageLength
,
587 _Inout_ PKD_CONTEXT KdContext
)
589 /* Maximal input buffer is 0x1000. Each byte is encoded on two bytes by GDB */
590 static UCHAR OutBuffer
[0x800];
595 State
->ApiNumber
= DbgKdWriteVirtualMemoryApi
;
596 State
->ReturnStatus
= STATUS_SUCCESS
; /* ? */
597 State
->Processor
= CurrentStateChange
.Processor
;
598 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
600 /* Set the TLB according to the process being read. Pid 0 means any process. */
602 if ((gdb_dbg_tid
!= 0) && gdb_tid_to_handle(gdb_dbg_tid
) != PsGetCurrentThreadId())
604 PETHREAD AttachedThread
= find_thread(0, gdb_dbg_tid
);
605 PKPROCESS AttachedProcess
;
606 if (AttachedThread
== NULL
)
608 KDDBGPRINT("The current GDB debug thread is invalid!");
609 return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
612 AttachedProcess
= AttachedThread
->Tcb
.Process
;
613 if (AttachedProcess
== NULL
)
615 KDDBGPRINT("The current GDB debug thread is invalid!");
616 return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
618 __writecr3(AttachedProcess
->DirectoryTableBase
[0]);
621 if ((gdb_dbg_pid
!= 0) && gdb_pid_to_handle(gdb_dbg_pid
) != PsGetCurrentProcessId())
623 PEPROCESS AttachedProcess
= find_process(gdb_dbg_pid
);
624 if (AttachedProcess
== NULL
)
626 KDDBGPRINT("The current GDB debug thread is invalid!");
627 return LOOP_IF_SUCCESS(send_gdb_packet("E03"));
629 /* Only do this if Ps is initialized */
630 if (ProcessListHead
->Flink
)
631 __writecr3(AttachedProcess
->Pcb
.DirectoryTableBase
[0]);
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)
640 return LOOP_IF_SUCCESS(send_gdb_packet("OK"));
643 State
->u
.WriteMemory
.TransferCount
= BufferLength
;
644 MessageData
->Length
= BufferLength
;
645 MessageData
->Buffer
= (CHAR
*)OutBuffer
;
648 blob_ptr
= strstr(strstr(&gdb_input
[1], ",") + 1, ":") + 1;
651 if (BufferLength
>= 4)
653 *((ULONG
*)OutPtr
) = *((ULONG
*)blob_ptr
);
658 else if (BufferLength
>= 2)
660 *((USHORT
*)OutPtr
) = *((USHORT
*)blob_ptr
);
667 *OutPtr
++ = *blob_ptr
++;
672 /* KD will reply with KdSendPacket. Catch it */
673 KdpSendPacketHandler
= WriteMemorySendHandler
;
674 return KdPacketReceived
;
679 WriteBreakPointSendHandler(
680 _In_ ULONG PacketType
,
681 _In_ PSTRING MessageHeader
,
682 _In_ PSTRING MessageData
)
684 DBGKD_MANIPULATE_STATE64
* State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
686 if (PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
689 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdWriteBreakPointApi request.\n", PacketType
);
693 if (State
->ApiNumber
!= DbgKdWriteBreakPointApi
)
695 KDDBGPRINT("Wrong API number (%lu) after DbgKdWriteBreakPointApi request.\n", State
->ApiNumber
);
699 if (!NT_SUCCESS(State
->ReturnStatus
))
701 KDDBGPRINT("Inserting breakpoint failed!\n");
702 send_gdb_ntstatus(State
->ReturnStatus
);
706 /* Keep track of the address+handle couple */
708 for (i
= 0; i
< (sizeof(BreakPointHandles
) / sizeof(BreakPointHandles
[0])); i
++)
710 if (BreakPointHandles
[i
].Address
== 0)
712 BreakPointHandles
[i
].Address
= (ULONG_PTR
)State
->u
.WriteBreakPoint
.BreakPointAddress
;
713 BreakPointHandles
[i
].Handle
= State
->u
.WriteBreakPoint
.BreakPointHandle
;
717 send_gdb_packet("OK");
719 KdpSendPacketHandler
= NULL
;
720 KdpManipulateStateHandler
= NULL
;
725 handle_gdb_insert_breakpoint(
726 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
727 _Out_ PSTRING MessageData
,
728 _Out_ PULONG MessageLength
,
729 _Inout_ PKD_CONTEXT KdContext
)
731 State
->ReturnStatus
= STATUS_SUCCESS
; /* ? */
732 State
->Processor
= CurrentStateChange
.Processor
;
733 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
735 MessageData
->Length
= 0;
738 switch (gdb_input
[1])
742 ULONG_PTR Address
= hex_to_address(&gdb_input
[3]);
744 BOOLEAN HasFreeSlot
= FALSE
;
746 KDDBGPRINT("Inserting breakpoint at %p.\n", (void*)Address
);
748 for (i
= 0; i
< (sizeof(BreakPointHandles
) / sizeof(BreakPointHandles
[0])); i
++)
750 if (BreakPointHandles
[i
].Address
== 0)
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"));
761 State
->ApiNumber
= DbgKdWriteBreakPointApi
;
762 State
->u
.WriteBreakPoint
.BreakPointAddress
= Address
;
763 /* FIXME : ignoring all other Z0 arguments */
765 /* KD will reply with KdSendPacket. Catch it */
766 KdpSendPacketHandler
= WriteBreakPointSendHandler
;
767 return KdPacketReceived
;
771 KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input
);
772 return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
777 RestoreBreakPointSendHandler(
778 _In_ ULONG PacketType
,
779 _In_ PSTRING MessageHeader
,
780 _In_ PSTRING MessageData
)
782 DBGKD_MANIPULATE_STATE64
* State
= (DBGKD_MANIPULATE_STATE64
*)MessageHeader
->Buffer
;
785 if (PacketType
!= PACKET_TYPE_KD_STATE_MANIPULATE
)
788 KDDBGPRINT("Wrong packet type (%lu) received after DbgKdRestoreBreakPointApi request.\n", PacketType
);
792 if (State
->ApiNumber
!= DbgKdRestoreBreakPointApi
)
794 KDDBGPRINT("Wrong API number (%lu) after DbgKdRestoreBreakPointApi request.\n", State
->ApiNumber
);
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
++)
801 if (BreakPointHandles
[i
].Handle
== State
->u
.RestoreBreakPoint
.BreakPointHandle
)
803 BreakPointHandles
[i
].Address
= 0;
804 BreakPointHandles
[i
].Handle
= 0;
809 send_gdb_packet("OK");
811 KdpSendPacketHandler
= NULL
;
812 KdpManipulateStateHandler
= NULL
;
817 handle_gdb_remove_breakpoint(
818 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
819 _Out_ PSTRING MessageData
,
820 _Out_ PULONG MessageLength
,
821 _Inout_ PKD_CONTEXT KdContext
)
823 State
->ReturnStatus
= STATUS_SUCCESS
; /* ? */
824 State
->Processor
= CurrentStateChange
.Processor
;
825 State
->ProcessorLevel
= CurrentStateChange
.ProcessorLevel
;
827 MessageData
->Length
= 0;
830 switch (gdb_input
[1])
834 ULONG_PTR Address
= hex_to_address(&gdb_input
[3]);
837 KDDBGPRINT("Removing breakpoint on %p.\n", (void*)Address
);
839 for (i
= 0; i
< (sizeof(BreakPointHandles
) / sizeof(BreakPointHandles
[0])); i
++)
841 if (BreakPointHandles
[i
].Address
== Address
)
843 Handle
= BreakPointHandles
[i
].Handle
;
850 KDDBGPRINT("Received %s, but breakpoint was never inserted ?!\n", gdb_input
);
851 return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
854 State
->ApiNumber
= DbgKdRestoreBreakPointApi
;
855 State
->u
.RestoreBreakPoint
.BreakPointHandle
= Handle
;
856 /* FIXME : ignoring all other z0 arguments */
858 /* KD will reply with KdSendPacket. Catch it */
859 KdpSendPacketHandler
= RestoreBreakPointSendHandler
;
860 return KdPacketReceived
;
864 KDDBGPRINT("Unhandled 'Z' packet: %s\n", gdb_input
);
865 return LOOP_IF_SUCCESS(send_gdb_packet("E01"));
871 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
872 _Out_ PSTRING MessageData
,
873 _Out_ PULONG MessageLength
,
874 _Inout_ PKD_CONTEXT KdContext
)
878 /* Tell GDB everything is fine, we will handle it */
879 Status
= send_gdb_packet("OK");
880 if (Status
!= KdPacketReceived
)
884 if (CurrentStateChange
.NewState
== DbgKdExceptionStateChange
)
886 DBGKM_EXCEPTION64
* Exception
= &CurrentStateChange
.u
.Exception
;
887 ULONG_PTR ProgramCounter
= KdpGetContextPc(&CurrentContext
);
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
))
893 /* We must get past the breakpoint instruction */
894 KdpSetContextPc(&CurrentContext
, ProgramCounter
+ KD_BREAKPOINT_SIZE
);
896 SetContextManipulateHandler(State
, MessageData
, MessageLength
, KdContext
);
897 KdpManipulateStateHandler
= ContinueManipulateStateHandler
;
898 return KdPacketReceived
;
902 return ContinueManipulateStateHandler(State
, MessageData
, MessageLength
, KdContext
);
908 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
909 _Out_ PSTRING MessageData
,
910 _Out_ PULONG MessageLength
,
911 _Inout_ PKD_CONTEXT KdContext
)
915 /* Tell GDB everything is fine, we will handle it */
916 Status
= send_gdb_packet("OK");
917 if (Status
!= KdPacketReceived
)
920 if (CurrentStateChange
.NewState
== DbgKdExceptionStateChange
)
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
;
927 /* We should never reach this ? */
928 return ContinueManipulateStateHandler(State
, MessageData
, MessageLength
, KdContext
);
934 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
935 _Out_ PSTRING MessageData
,
936 _Out_ PULONG MessageLength
,
937 _Inout_ PKD_CONTEXT KdContext
)
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
;
950 _Out_ DBGKD_MANIPULATE_STATE64
* State
,
951 _Out_ PSTRING MessageData
,
952 _Out_ PULONG MessageLength
,
953 _Inout_ PKD_CONTEXT KdContext
)
955 if (strncmp(gdb_input
, "vCont", 5) == 0)
957 if (gdb_input
[5] == '?')
959 /* Report what we support */
960 return LOOP_IF_SUCCESS(send_gdb_packet("vCont;c;s"));
963 if (strncmp(gdb_input
, "vCont;c", 7) == 0)
965 return handle_gdb_c(State
, MessageData
, MessageLength
, KdContext
);
968 if (strncmp(gdb_input
, "vCont;s", 7) == 0)
971 return handle_gdb_s(State
, MessageData
, MessageLength
, KdContext
);
975 KDDBGPRINT("Unhandled 'v' packet: %s\n", gdb_input
);
976 return LOOP_IF_SUCCESS(send_gdb_packet(""));
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
)
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
);
994 if (Status
!= KdPacketReceived
)
997 Status
= (KDSTATUS
)-1;
999 switch (gdb_input
[0])
1002 /* Send the Status */
1003 Status
= LOOP_IF_SUCCESS(gdb_send_exception());
1006 Status
= LOOP_IF_SUCCESS(send_gdb_packet("OK"));
1009 Status
= handle_gdb_c(State
, MessageData
, MessageLength
, KdContext
);
1012 Status
= handle_gdb_C(State
, MessageData
, MessageLength
, KdContext
);
1015 Status
= LOOP_IF_SUCCESS(gdb_send_registers());
1018 Status
= LOOP_IF_SUCCESS(handle_gdb_set_thread());
1021 Status
= handle_gdb_read_mem(State
, MessageData
, MessageLength
, KdContext
);
1024 Status
= LOOP_IF_SUCCESS(gdb_send_register());
1027 Status
= LOOP_IF_SUCCESS(handle_gdb_query());
1030 Status
= handle_gdb_s(State
, MessageData
, MessageLength
, KdContext
);
1033 Status
= LOOP_IF_SUCCESS(handle_gdb_thread_alive());
1036 Status
= handle_gdb_v(State
, MessageData
, MessageLength
, KdContext
);
1039 Status
= handle_gdb_write_mem(State
, MessageData
, MessageLength
, KdContext
);
1042 Status
= handle_gdb_remove_breakpoint(State
, MessageData
, MessageLength
, KdContext
);
1045 Status
= handle_gdb_insert_breakpoint(State
, MessageData
, MessageLength
, KdContext
);
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(""));
1052 } while (Status
== (KDSTATUS
)-1);