ReactOS 0.4.15-dev-7918-g2a2556c
gdb_input.c
Go to the documentation of this file.
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 *********************************************************************/
12static struct
13{
17
18
19/* GLOBALS ********************************************************************/
22
23static inline
26{
27 return (x == KdPacketReceived) ? (KDSTATUS)-1 : x;
28}
29
30/* PRIVATE FUNCTIONS **********************************************************/
31static
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
49static
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 */
67static
70{
72
73 switch (gdb_input[1])
74 {
75 case 'c':
76 if (strcmp(&gdb_input[2], "-1") == 0)
78 else
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 {
89 }
90 else
91 {
93 }
94#else
95 if (strncmp(&gdb_input[2], "p-1", 3) == 0)
96 {
99 }
100 else
101 {
102 char* ptr = strstr(gdb_input, ".") + 1;
104 if (strncmp(ptr, "-1", 2) == 0)
105 gdb_dbg_tid = (UINT_PTR)-1;
106 else
108 }
109#endif
110 Status = send_gdb_packet("OK");
111 break;
112 default:
113 KDDBGPRINT("KDGBD: Unknown 'H' command: %s\n", gdb_input);
115 }
116
117 return Status;
118}
119
120static
123{
124 ULONG_PTR Pid, Tid;
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 */
154static
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";",
192#else
193 sprintf(gdb_out, "QC:p%"PRIxPTR".%"PRIxPTR";",
196#endif
197 return send_gdb_packet(gdb_out);
198 }
199
200 if (strncmp(gdb_input, "qfThreadInfo", 12) == 0)
201 {
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 */
218
219 /* Start with the system thread */
220#if MONOPROCESS
222#else
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),
248#endif
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;
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;
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);
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
317 {
318 String.Length = sprintf(out_string, "SYSTEM");
319 }
320 else
321 {
322 String.Length = sprintf(out_string, "%.*s", 16, Process->ImageFileName);
323 }
324
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];
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 */
354
355 if (allDone)
356 {
358 allDone = FALSE;
359 return finish_gdb_packet();
360 }
361
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 {
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
433static
435handle_gdb_registers(
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; /* ? */
448 State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
449 if (MessageData)
450 MessageData->Length = 0;
451 *MessageLength = 0;
452 return KdPacketReceived;
453}
454#endif
455
456static
459 _In_ ULONG PacketType,
460 _In_ PSTRING MessageHeader,
461 _In_ PSTRING MessageData)
462{
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);
485
486#if MONOPROCESS
487 if (gdb_dbg_tid != 0)
488 /* Reset the TLB */
489#else
491#endif
492 {
493 /* Only do this if Ps is initialized */
495 __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
496 }
497
498 return TRUE;
499}
500
501static
505 _Out_ PSTRING MessageData,
506 _Out_ PULONG MessageLength,
507 _Inout_ PKD_CONTEXT KdContext)
508{
509 State->ApiNumber = DbgKdReadVirtualMemoryApi;
510 State->ReturnStatus = STATUS_SUCCESS; /* ? */
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
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
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 */
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 */
557 return KdPacketReceived;
558}
559
560static
563 _In_ ULONG PacketType,
564 _In_ PSTRING MessageHeader,
565 _In_ PSTRING MessageData)
566{
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");
589
590#if MONOPROCESS
591 if (gdb_dbg_tid != 0)
592 /* Reset the TLB */
593#else
595#endif
596 {
597 /* Only do this if Ps is initialized */
599 __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
600 }
601 return TRUE;
602}
603
604static
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];
615 char* blob_ptr;
616 UCHAR* OutPtr;
617
619 State->ReturnStatus = STATUS_SUCCESS; /* ? */
621 State->ProcessorLevel = CurrentStateChange.ProcessorLevel;
622
623 /* Set the TLB according to the process being read. Pid 0 means any process. */
624#if MONOPROCESS
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
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 */
654 __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]);
655 }
656#endif
657
658 State->u.WriteMemory.TargetBaseAddress = hex_to_address(&gdb_input[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 */
697 return KdPacketReceived;
698}
699
700static
703 _In_ ULONG PacketType,
704 _In_ PSTRING MessageHeader,
705 _In_ PSTRING MessageData)
706{
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 }
745 return TRUE;
746}
747
748static
752 _Out_ PSTRING MessageData,
753 _Out_ PULONG MessageLength,
754 _Inout_ PKD_CONTEXT KdContext)
755{
756 State->ReturnStatus = STATUS_SUCCESS; /* ? */
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 {
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 */
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
800static
803 _In_ ULONG PacketType,
804 _In_ PSTRING MessageHeader,
805 _In_ PSTRING MessageData)
806{
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
839 return TRUE;
840}
841
842static
846 _Out_ PSTRING MessageData,
847 _Out_ PULONG MessageLength,
848 _Inout_ PKD_CONTEXT KdContext)
849{
850 State->ReturnStatus = STATUS_SUCCESS; /* ? */
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 {
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 {
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 */
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
895static
899 _Out_ PSTRING MessageData,
900 _Out_ PULONG MessageLength,
901 _Inout_ PKD_CONTEXT KdContext)
902{
904
905 /* Tell GDB everything is fine, we will handle it */
906 Status = send_gdb_packet("OK");
908 return Status;
909
910
912 {
914 ULONG_PTR ProgramCounter = KdpGetContextPc(&CurrentContext);
915
916 /* See if we should update the program counter */
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);
925 return KdPacketReceived;
926 }
927#if defined(_M_IX86) || defined(_M_AMD64)
929 && ((*(KD_BREAKPOINT_TYPE*)ProgramCounter) == 0xCD)
930 && (*((KD_BREAKPOINT_TYPE*)ProgramCounter + 1) == 0x2C))
931 {
932 /* INT 2C (a.k.a. runtime check failure) */
933 KdpSetContextPc(&CurrentContext, ProgramCounter + 2);
934
935 SetContextManipulateHandler(State, MessageData, MessageLength, KdContext);
937 return KdPacketReceived;
938 }
939#endif
940 }
941
942 return ContinueManipulateStateHandler(State, MessageData, MessageLength, KdContext);
943}
944
945static
949 _Out_ PSTRING MessageData,
950 _Out_ PULONG MessageLength,
951 _Inout_ PKD_CONTEXT KdContext)
952{
953 KDDBGPRINT("Single stepping.\n");
954 /* Set CPU single step mode and continue */
955 KdpSetSingleStep(&CurrentContext);
956 SetContextManipulateHandler(State, MessageData, MessageLength, KdContext);
958 return KdPacketReceived;
959}
960
961static
965 _Out_ PSTRING MessageData,
966 _Out_ PULONG MessageLength,
967 _Inout_ PKD_CONTEXT KdContext)
968{
969 if (strncmp(gdb_input, "vCont", 5) == 0)
970 {
971 if (gdb_input[5] == '?')
972 {
973 /* Report what we support */
974 return LOOP_IF_SUCCESS(send_gdb_packet("vCont;c;s"));
975 }
976
977 if (strncmp(gdb_input, "vCont;c", 7) == 0)
978 {
979 return handle_gdb_c(State, MessageData, MessageLength, KdContext);
980 }
981
982 if (strncmp(gdb_input, "vCont;s", 7) == 0)
983 {
984
985 return handle_gdb_s(State, MessageData, MessageLength, KdContext);
986 }
987 }
988
989 KDDBGPRINT("Unhandled 'v' packet: %s\n", gdb_input);
991}
992
996 _Out_ PSTRING MessageData,
997 _Out_ PULONG MessageLength,
998 _Inout_ PKD_CONTEXT KdContext)
999{
1001
1002 do
1003 {
1004 KDDBGPRINT("KDGBD: Receiving packet.\n");
1005 Status = gdb_receive_packet(KdContext);
1006 KDDBGPRINT("KDGBD: Packet \"%s\" received with status %u\n", gdb_input, Status);
1007
1008 if (Status != KdPacketReceived)
1009 return Status;
1010
1011 Status = (KDSTATUS)-1;
1012
1013 switch (gdb_input[0])
1014 {
1015 case '?':
1016 /* Send the Status */
1018 break;
1019 case '!':
1021 break;
1022 case 'c':
1023 case 'C':
1024 Status = handle_gdb_c(State, MessageData, MessageLength, KdContext);
1025 break;
1026 case 'g':
1028 break;
1029 case 'H':
1031 break;
1032 case 'm':
1033 Status = handle_gdb_read_mem(State, MessageData, MessageLength, KdContext);
1034 break;
1035 case 'p':
1037 break;
1038 case 'q':
1040 break;
1041 case 's':
1042 Status = handle_gdb_s(State, MessageData, MessageLength, KdContext);
1043 break;
1044 case 'T':
1046 break;
1047 case 'v':
1048 Status = handle_gdb_v(State, MessageData, MessageLength, KdContext);
1049 break;
1050 case 'X':
1051 Status = handle_gdb_write_mem(State, MessageData, MessageLength, KdContext);
1052 break;
1053 case 'z':
1054 Status = handle_gdb_remove_breakpoint(State, MessageData, MessageLength, KdContext);
1055 break;
1056 case 'Z':
1057 Status = handle_gdb_insert_breakpoint(State, MessageData, MessageLength, KdContext);
1058 break;
1059 default:
1060 /* We don't know how to handle this request. */
1061 KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input);
1063 }
1064 } while (Status == (KDSTATUS)-1);
1065
1066 return Status;
1067}
1068
unsigned char BOOLEAN
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
KDSTATUS gdb_send_registers(void)
Definition: amd64_sup.c:144
KDSTATUS gdb_send_register(void)
Definition: amd64_sup.c:219
UINT Sent
Definition: arping.c:39
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
unsigned char
Definition: typeof.h:29
#define KDDBGPRINT(...)
Definition: kddll.h:19
#define ULONG_PTR
Definition: config.h:101
PsGetCurrentThreadId
Definition: CrNtStubs.h:8
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
std::wstring STRING
Definition: fontsub.cpp:33
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
static KDSTATUS handle_gdb_set_thread(void)
Definition: gdb_input.c:69
static KDSTATUS handle_gdb_insert_breakpoint(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:750
static KDSTATUS LOOP_IF_SUCCESS(int x)
Definition: gdb_input.c:25
static KDSTATUS handle_gdb_s(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:947
static UINT_PTR hex_to_tid(char *buffer)
Definition: gdb_input.c:33
static ULONG64 hex_to_address(char *buffer)
Definition: gdb_input.c:51
ULONG_PTR Address
Definition: gdb_input.c:14
static KDSTATUS handle_gdb_c(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:897
static BOOLEAN ReadMemorySendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: gdb_input.c:458
static struct @607 BreakPointHandles[32]
#define hex_to_pid
Definition: gdb_input.c:47
static KDSTATUS handle_gdb_write_mem(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:606
static ULONG_PTR gdb_run_tid
Definition: gdb_input.c:11
static BOOLEAN WriteMemorySendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: gdb_input.c:562
static KDSTATUS handle_gdb_read_mem(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:503
KDSTATUS gdb_receive_and_interpret_packet(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:994
ULONG Handle
Definition: gdb_input.c:15
static KDSTATUS handle_gdb_thread_alive(void)
Definition: gdb_input.c:122
static KDSTATUS handle_gdb_v(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:963
UINT_PTR gdb_dbg_tid
Definition: gdb_input.c:21
static BOOLEAN RestoreBreakPointSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: gdb_input.c:802
static KDSTATUS handle_gdb_query(void)
Definition: gdb_input.c:156
UINT_PTR gdb_dbg_pid
Definition: gdb_input.c:20
static BOOLEAN WriteBreakPointSendHandler(_In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData)
Definition: gdb_input.c:702
static KDSTATUS handle_gdb_remove_breakpoint(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: gdb_input.c:844
KDSTATUS NTAPI gdb_receive_packet(_Inout_ PKD_CONTEXT KdContext)
Definition: gdb_receive.c:31
CHAR gdb_input[0x1000]
Definition: gdb_receive.c:11
char hex_value(char ch)
Definition: gdb_receive.c:15
KDSTATUS gdb_send_debug_io(_In_ PSTRING String, _In_ BOOLEAN WithPrefix)
Definition: gdb_send.c:168
void send_gdb_ntstatus(_In_ NTSTATUS Status)
Definition: gdb_send.c:231
KDSTATUS send_gdb_memory(_In_ const VOID *Buffer, _In_ size_t Length)
Definition: gdb_send.c:158
void send_gdb_partial_packet(_In_ const CHAR *Buffer)
Definition: gdb_send.c:60
void start_gdb_packet(void)
Definition: gdb_send.c:52
KDSTATUS gdb_send_exception()
Definition: gdb_send.c:197
KDSTATUS finish_gdb_packet(void)
Definition: gdb_send.c:74
ULONG send_gdb_partial_binary(_In_ const VOID *Buffer, _In_ size_t Length)
Definition: gdb_send.c:108
KDSTATUS send_gdb_packet(_In_ const CHAR *Buffer)
Definition: gdb_send.c:100
Status
Definition: gdiplustypes.h:25
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint buffer
Definition: glext.h:5915
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int hex(char ch)
#define PRIxPTR
Definition: inttypes.h:236
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1794
#define gdb_pid_to_handle
Definition: kdgdb.h:39
CONTEXT CurrentContext
Definition: kdpacket.c:29
KDP_SEND_HANDLER KdpSendPacketHandler
Definition: kdpacket.c:25
KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler
Definition: kdpacket.c:26
KDSTATUS SetContextManipulateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:107
PEPROCESS find_process(_In_ UINT_PTR Pid)
Definition: utils.c:16
DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange
Definition: kdpacket.c:28
#define handle_to_gdb_pid
Definition: kdgdb.h:45
FORCEINLINE HANDLE gdb_tid_to_handle(UINT_PTR Tid)
Definition: kdgdb.h:35
FORCEINLINE UINT_PTR handle_to_gdb_tid(HANDLE Handle)
Definition: kdgdb.h:41
KDSTATUS ContinueManipulateStateHandler(_Out_ DBGKD_MANIPULATE_STATE64 *State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext)
Definition: kdpacket.c:213
LIST_ENTRY * ModuleListHead
Definition: kdpacket.c:23
LIST_ENTRY * ProcessListHead
Definition: kdpacket.c:22
PETHREAD find_thread(_In_ UINT_PTR Pid, _In_ UINT_PTR Tid)
Definition: utils.c:41
if(dx< 0)
Definition: linetemp.h:194
unsigned __int64 ULONG64
Definition: imports.h:198
static PVOID ptr
Definition: dispmode.c:27
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define _Inout_
Definition: ms_sal.h:378
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define KD_BREAKPOINT_TYPE
Definition: ke.h:121
#define KD_BREAKPOINT_VALUE
Definition: ke.h:123
#define KD_BREAKPOINT_SIZE
Definition: ke.h:122
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
HANDLE NTAPI PsGetThreadId(IN PETHREAD Thread)
Definition: thread.c:705
HANDLE NTAPI PsGetThreadProcessId(IN PETHREAD Thread)
Definition: thread.c:745
#define STATUS_ASSERTION_FAILURE
Definition: ntstatus.h:960
#define STATUS_BREAKPOINT
Definition: ntstatus.h:184
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
_In_ UCHAR _In_ ULONG _Out_ PUCHAR _Outptr_result_bytebuffer_ OutBufferLength PVOID * OutBuffer
Definition: scsi.h:4071
#define KdPacketReceived
Definition: kddll.h:5
ULONG KDSTATUS
Definition: kddll.h:4
#define STATUS_SUCCESS
Definition: shellext.h:65
HANDLE UniqueThread
Definition: compat.h:826
DBGKM_EXCEPTION64 Exception
Definition: windbgkd.h:508
union _DBGKD_ANY_WAIT_STATE_CHANGE::@3549 u
EXCEPTION_RECORD64 ExceptionRecord
Definition: windbgkd.h:312
KPROCESS Pcb
Definition: pstypes.h:1262
KTHREAD Tcb
Definition: pstypes.h:1103
CLIENT_ID Cid
Definition: pstypes.h:1128
NTSTATUS ExceptionCode
Definition: rtltypes.h:190
ULONG_PTR DirectoryTableBase
Definition: ketypes.h:2087
PVOID Teb
Definition: ketypes.h:1807
PKPROCESS Process
Definition: ketypes.h:1908
Definition: btrfs_drv.h:1876
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
uint32_t * PULONG
Definition: typedefs.h:59
void * PVOID
Definition: typedefs.h:50
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
int ret
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433
#define DbgKdGetContextApi
Definition: windbgkd.h:76
#define DbgKdWriteVirtualMemoryApi
Definition: windbgkd.h:75
#define PACKET_TYPE_KD_STATE_MANIPULATE
Definition: windbgkd.h:43
#define DbgKdReadVirtualMemoryApi
Definition: windbgkd.h:74
#define DbgKdWriteBreakPointApi
Definition: windbgkd.h:78
#define DbgKdExceptionStateChange
Definition: windbgkd.h:59
#define DbgKdRestoreBreakPointApi
Definition: windbgkd.h:79
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:4303
#define PsGetCurrentProcess
Definition: psfuncs.h:17
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define _snprintf
Definition: xmlstorage.h:200
char CHAR
Definition: xmlstorage.h:175