ReactOS 0.4.15-dev-5863-g1fe3ab7
kdb.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/kdbg/kdb.c
5 * PURPOSE: Kernel Debugger
6 *
7 * PROGRAMMERS: Gregor Anich
8 */
9
10/* INCLUDES ******************************************************************/
11
12#include <ntoskrnl.h>
13#define NDEBUG
14#include <debug.h>
15
16/* TYPES *********************************************************************/
17
18/* DEFINES *******************************************************************/
19
20#define KDB_STACK_SIZE (4096*3)
21#ifdef _M_AMD64
22#define KDB_STACK_ALIGN 16
23#define KDB_STACK_RESERVE (5 * sizeof(PVOID)) /* Home space + return address */
24#else
25#define KDB_STACK_ALIGN 4
26#define KDB_STACK_RESERVE sizeof(ULONG) /* Return address */
27#endif
28#define KDB_MAXIMUM_BREAKPOINT_COUNT 256
29#define KDB_MAXIMUM_HW_BREAKPOINT_COUNT 4
30#define KDB_MAXIMUM_SW_BREAKPOINT_COUNT 256
31
32#define __STRING(x) #x
33#define _STRING(x) __STRING(x)
34
35/* GLOBALS *******************************************************************/
36
39
40static ULONG KdbBreakPointCount = 0; /* Number of used breakpoints in the array */
41static KDB_BREAKPOINT KdbBreakPoints[KDB_MAXIMUM_BREAKPOINT_COUNT] = {{0}}; /* Breakpoint array */
42static ULONG KdbSwBreakPointCount = 0; /* Number of enabled software breakpoints */
43static ULONG KdbHwBreakPointCount = 0; /* Number of enabled hardware breakpoints */
44static PKDB_BREAKPOINT KdbSwBreakPoints[KDB_MAXIMUM_SW_BREAKPOINT_COUNT]; /* Enabled software breakpoints, orderless */
45static PKDB_BREAKPOINT KdbHwBreakPoints[KDB_MAXIMUM_HW_BREAKPOINT_COUNT]; /* Enabled hardware breakpoints, orderless */
46static PKDB_BREAKPOINT KdbBreakPointToReenable = NULL; /* Set to a breakpoint struct when single stepping after
47 a software breakpoint was hit, to reenable it */
49LONG KdbLastBreakPointNr = -1; /* Index of the breakpoint which cause KDB to be entered */
50ULONG KdbNumSingleSteps = 0; /* How many single steps to do */
51BOOLEAN KdbSingleStepOver = FALSE; /* Whether to step over calls/reps. */
52ULONG KdbDebugState = 0; /* KDBG Settings (NOECHO, KDSERIAL) */
53static BOOLEAN KdbEnteredOnSingleStep = FALSE; /* Set to true when KDB was entered because of single step */
54PEPROCESS KdbCurrentProcess = NULL; /* The current process context in which KDB runs */
55PEPROCESS KdbOriginalProcess = NULL; /* The process in whichs context KDB was intered */
56PETHREAD KdbCurrentThread = NULL; /* The current thread context in which KDB runs */
57PETHREAD KdbOriginalThread = NULL; /* The thread in whichs context KDB was entered */
58PKDB_KTRAP_FRAME KdbCurrentTrapFrame = NULL; /* Pointer to the current trapframe */
59static KDB_KTRAP_FRAME KdbTrapFrame = { 0 }; /* The trapframe which was passed to KdbEnterDebuggerException */
60static KDB_KTRAP_FRAME KdbThreadTrapFrame = { 0 }; /* The trapframe of the current thread (KdbCurrentThread) */
63
64/* Array of conditions when to enter KDB */
66{
67 /* First chance Last chance */
68 { KdbDoNotEnter, KdbEnterFromKmode }, /* 0: Zero divide */
69 { KdbEnterFromKmode, KdbDoNotEnter }, /* 1: Debug trap */
70 { KdbDoNotEnter, KdbEnterAlways }, /* 2: NMI */
71 { KdbEnterFromKmode, KdbDoNotEnter }, /* 3: INT3 */
72 { KdbDoNotEnter, KdbEnterFromKmode }, /* 4: Overflow */
73 { KdbDoNotEnter, KdbEnterFromKmode }, /* 5: BOUND range exceeded */
74 { KdbDoNotEnter, KdbEnterFromKmode }, /* 6: Invalid opcode */
75 { KdbDoNotEnter, KdbEnterFromKmode }, /* 7: No math coprocessor fault */
76 { KdbEnterAlways, KdbEnterAlways }, /* 8: Double Fault */
77 { KdbEnterAlways, KdbEnterAlways }, /* 9: Unknown(9) */
78 { KdbDoNotEnter, KdbEnterFromKmode }, /* 10: Invalid TSS */
79 { KdbDoNotEnter, KdbEnterFromKmode }, /* 11: Segment Not Present */
80 { KdbDoNotEnter, KdbEnterFromKmode }, /* 12: Stack fault */
81 { KdbDoNotEnter, KdbEnterFromKmode }, /* 13: General protection fault */
82 { KdbDoNotEnter, KdbEnterFromKmode }, /* 14: Page fault */
83 { KdbEnterAlways, KdbEnterAlways }, /* 15: Reserved (15) */
84 { KdbDoNotEnter, KdbEnterFromKmode }, /* 16: FPU fault */
85 { KdbDoNotEnter, KdbEnterFromKmode }, /* 17: Alignment Check */
86 { KdbDoNotEnter, KdbEnterFromKmode }, /* 18: Machine Check */
87 { KdbDoNotEnter, KdbEnterFromKmode }, /* 19: SIMD fault */
88 { KdbEnterFromKmode, KdbDoNotEnter }, /* 20: Assertion failure */
89 { KdbDoNotEnter, KdbEnterFromKmode } /* Last entry: used for unknown exceptions */
90};
91
92/* Exception descriptions */
93static const CHAR *ExceptionNrToString[] =
94{
95 "Divide Error",
96 "Debug Trap",
97 "NMI",
98 "Breakpoint",
99 "Overflow",
100 "BOUND range exceeded",
101 "Invalid Opcode",
102 "No Math Coprocessor",
103 "Double Fault",
104 "Unknown(9)",
105 "Invalid TSS",
106 "Segment Not Present",
107 "Stack Segment Fault",
108 "General Protection",
109 "Page Fault",
110 "Reserved(15)",
111 "Math Fault",
112 "Alignment Check",
113 "Machine Check",
114 "SIMD Fault",
115 "Assertion Failure"
116};
117
118/* FUNCTIONS *****************************************************************/
119
120static VOID
122 PVOID KernelStack,
124{
125 ULONG_PTR *StackPtr;
126
128 StackPtr = (ULONG_PTR *) KernelStack;
129#ifdef _M_IX86
130 KdbTrapFrame->Ebp = StackPtr[3];
131 KdbTrapFrame->Edi = StackPtr[4];
132 KdbTrapFrame->Esi = StackPtr[5];
133 KdbTrapFrame->Ebx = StackPtr[6];
134 KdbTrapFrame->Eip = StackPtr[7];
135 KdbTrapFrame->Esp = (ULONG) (StackPtr + 8);
141#endif
142
143 /* FIXME: what about the other registers??? */
144}
145
156static NTSTATUS
160 IN UCHAR NewInst,
161 OUT PUCHAR OldInst OPTIONAL)
162{
165 PEPROCESS CurrentProcess = PsGetCurrentProcess();
167
168 /* Get the protection for the address. */
170
171 /* Return if that page isn't present. */
173 {
175 }
176
177 /* Attach to the process */
178 if (CurrentProcess != Process)
179 {
181 }
182
183 /* Make the page writeable if it is read only. */
185 {
188 }
189
190 /* Copy the old instruction back to the caller. */
191 if (OldInst)
192 {
193 Status = KdbpSafeReadMemory(OldInst, (PUCHAR)Address, 1);
194 if (!NT_SUCCESS(Status))
195 {
197 {
199 }
200
201 /* Detach from process */
202 if (CurrentProcess != Process)
203 {
205 }
206
207 return Status;
208 }
209 }
210
211 /* Copy the new instruction in its place. */
212 Status = KdbpSafeWriteMemory((PUCHAR)Address, &NewInst, 1);
213
214 /* Restore the page protection. */
216 {
218 }
219
220 /* Detach from process */
221 if (CurrentProcess != Process)
222 {
224 }
225
226 return Status;
227}
228
237 ULONG_PTR Eip)
238{
239 UCHAR Mem[3];
240 ULONG i = 0;
241
242 if (!NT_SUCCESS(KdbpSafeReadMemory(Mem, (PVOID)Eip, sizeof (Mem))))
243 {
244 KdbpPrint("Couldn't access memory at 0x%p\n", Eip);
245 return FALSE;
246 }
247
248 /* Check if the current instruction is a call. */
249 while ((i < sizeof (Mem)) && (Mem[i] == 0x66 || Mem[i] == 0x67))
250 i++;
251
252 if (i == sizeof (Mem))
253 return FALSE;
254
255 if (Mem[i] == 0xE8 || Mem[i] == 0x9A || Mem[i] == 0xF2 || Mem[i] == 0xF3 ||
256 (((i + 1) < sizeof (Mem)) && Mem[i] == 0xFF && (Mem[i+1] & 0x38) == 0x10))
257 {
258 return TRUE;
259 }
260
261 return FALSE;
262}
263
275 ULONG_PTR Eip)
276{
277 LONG InstLen;
278
280 return FALSE;
281
282 InstLen = KdbpGetInstLength(Eip);
283 if (InstLen < 1)
284 return FALSE;
285
287 return FALSE;
288
289 return TRUE;
290}
291
303 ULONG_PTR Eip)
304{
305 KDESCRIPTOR Idtr = {0};
306 UCHAR Mem[2];
307 INT IntVect;
308 ULONG IntDesc[2];
309 ULONG_PTR TargetEip;
310
311 /* Read memory */
312 if (!NT_SUCCESS(KdbpSafeReadMemory(Mem, (PVOID)Eip, sizeof (Mem))))
313 {
314 /*KdbpPrint("Couldn't access memory at 0x%p\n", Eip);*/
315 return FALSE;
316 }
317
318 /* Check for INT instruction */
319 /* FIXME: Check for iret */
320 if (Mem[0] == 0xcc)
321 IntVect = 3;
322 else if (Mem[0] == 0xcd)
323 IntVect = Mem[1];
324 else if (Mem[0] == 0xce && KdbCurrentTrapFrame->EFlags & (1<<11)) /* 1 << 11 is the overflow flag */
325 IntVect = 4;
326 else
327 return FALSE;
328
329 if (IntVect < 32) /* We should be informed about interrupts < 32 by the kernel, no need to breakpoint them */
330 {
331 return FALSE;
332 }
333
334 /* Read the interrupt descriptor table register */
335 __sidt(&Idtr.Limit);
336 if (IntVect >= (Idtr.Limit + 1) / 8)
337 {
338 /*KdbpPrint("IDT does not contain interrupt vector %d.\n", IntVect);*/
339 return TRUE;
340 }
341
342 /* Get the interrupt descriptor */
343 if (!NT_SUCCESS(KdbpSafeReadMemory(IntDesc, (PVOID)((ULONG_PTR)Idtr.Base + (IntVect * 8)), sizeof(IntDesc))))
344 {
345 /*KdbpPrint("Couldn't access memory at 0x%p\n", (ULONG_PTR)Idtr.Base + (IntVect * 8));*/
346 return FALSE;
347 }
348
349 /* Check descriptor and get target eip (16 bit interrupt/trap gates not supported) */
350 if ((IntDesc[1] & (1 << 15)) == 0) /* not present */
351 {
352 return FALSE;
353 }
354 if ((IntDesc[1] & 0x1f00) == 0x0500) /* Task gate */
355 {
356 /* FIXME: Task gates not supported */
357 return FALSE;
358 }
359 else if (((IntDesc[1] & 0x1fe0) == 0x0e00) || /* 32 bit Interrupt gate */
360 ((IntDesc[1] & 0x1fe0) == 0x0f00)) /* 32 bit Trap gate */
361 {
362 /* FIXME: Should the segment selector of the interrupt gate be checked? */
363 TargetEip = (IntDesc[1] & 0xffff0000) | (IntDesc[0] & 0x0000ffff);
364 }
365 else
366 {
367 return FALSE;
368 }
369
370 /* Insert breakpoint */
372 return FALSE;
373
374 return TRUE;
375}
376
383LONG
386{
387 for (; Start < RTL_NUMBER_OF(KdbBreakPoints); Start++)
388 {
389 if (KdbBreakPoints[Start].Type != KdbBreakPointNone)
390 return Start;
391 }
392
393 return -1;
394}
395
412 IN ULONG BreakPointNr,
416 OUT KDB_ACCESS_TYPE *AccessType OPTIONAL,
417 OUT UCHAR *DebugReg OPTIONAL,
421 OUT PCHAR *ConditionExpression OPTIONAL)
422{
424
425 if (BreakPointNr >= RTL_NUMBER_OF(KdbBreakPoints) ||
426 KdbBreakPoints[BreakPointNr].Type == KdbBreakPointNone)
427 {
428 return FALSE;
429 }
430
431 bp = KdbBreakPoints + BreakPointNr;
432 if (Address)
433 *Address = bp->Address;
434
435 if (Type)
436 *Type = bp->Type;
437
438 if (bp->Type == KdbBreakPointHardware)
439 {
440 if (Size)
441 *Size = bp->Data.Hw.Size;
442
443 if (AccessType)
444 *AccessType = bp->Data.Hw.AccessType;
445
446 if (DebugReg && bp->Enabled)
447 *DebugReg = bp->Data.Hw.DebugReg;
448 }
449
450 if (Enabled)
451 *Enabled = bp->Enabled;
452
453 if (Global)
454 *Global = bp->Global;
455
456 if (Process)
457 *Process = bp->Process;
458
459 if (ConditionExpression)
460 *ConditionExpression = bp->ConditionExpression;
461
462 return TRUE;
463}
464
484 IN KDB_ACCESS_TYPE AccessType OPTIONAL,
485 IN PCHAR ConditionExpression OPTIONAL,
487 OUT PLONG BreakPointNr OPTIONAL)
488{
489 LONG_PTR i;
491 PCHAR ConditionExpressionDup;
492 LONG ErrOffset;
493 CHAR ErrMsg[128];
494
496
498 {
499 if ((Address % Size) != 0)
500 {
501 KdbpPrint("Address (0x%p) must be aligned to a multiple of the size (%d)\n", Address, Size);
502 return STATUS_UNSUCCESSFUL;
503 }
504
505 if (AccessType == KdbAccessExec && Size != 1)
506 {
507 KdbpPrint("Size must be 1 for execution breakpoints.\n");
508 return STATUS_UNSUCCESSFUL;
509 }
510 }
511
512 if (KdbBreakPointCount == KDB_MAXIMUM_BREAKPOINT_COUNT)
513 {
514 return STATUS_UNSUCCESSFUL;
515 }
516
517 /* Parse conditon expression string and duplicate it */
518 if (ConditionExpression)
519 {
520 Condition = KdbpRpnParseExpression(ConditionExpression, &ErrOffset, ErrMsg);
521 if (!Condition)
522 {
523 if (ErrOffset >= 0)
524 KdbpPrint("Couldn't parse expression: %s at character %d\n", ErrMsg, ErrOffset);
525 else
526 KdbpPrint("Couldn't parse expression: %s", ErrMsg);
527
528 return STATUS_UNSUCCESSFUL;
529 }
530
531 i = strlen(ConditionExpression) + 1;
532 ConditionExpressionDup = ExAllocatePoolWithTag(NonPagedPool, i, TAG_KDBG);
533 RtlCopyMemory(ConditionExpressionDup, ConditionExpression, i);
534 }
535 else
536 {
537 Condition = NULL;
538 ConditionExpressionDup = NULL;
539 }
540
541 /* Find unused breakpoint */
543 {
544 for (i = RTL_NUMBER_OF(KdbBreakPoints) - 1; i >= 0; i--)
545 {
546 if (KdbBreakPoints[i].Type == KdbBreakPointNone)
547 break;
548 }
549 }
550 else
551 {
552 for (i = 0; i < (LONG)RTL_NUMBER_OF(KdbBreakPoints); i++)
553 {
554 if (KdbBreakPoints[i].Type == KdbBreakPointNone)
555 break;
556 }
557 }
558
559 ASSERT(i < (LONG)RTL_NUMBER_OF(KdbBreakPoints));
560
561 /* Set the breakpoint */
563 KdbBreakPoints[i].Type = Type;
564 KdbBreakPoints[i].Address = Address;
565 KdbBreakPoints[i].Enabled = FALSE;
566 KdbBreakPoints[i].Global = Global;
567 KdbBreakPoints[i].Process = KdbCurrentProcess;
568 KdbBreakPoints[i].ConditionExpression = ConditionExpressionDup;
569 KdbBreakPoints[i].Condition = Condition;
570
572 {
573 KdbBreakPoints[i].Data.Hw.Size = Size;
574 KdbBreakPoints[i].Data.Hw.AccessType = AccessType;
575 }
576
577 KdbBreakPointCount++;
578
580 KdbpPrint("Breakpoint %d inserted.\n", i);
581
582 /* Try to enable the breakpoint */
584
585 /* Return the breakpoint number */
586 if (BreakPointNr)
587 *BreakPointNr = i;
588
589 return STATUS_SUCCESS;
590}
591
602 IN LONG BreakPointNr OPTIONAL,
603 IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
604{
605 if (BreakPointNr < 0)
606 {
607 ASSERT(BreakPoint);
608 BreakPointNr = BreakPoint - KdbBreakPoints;
609 }
610
611 if (BreakPointNr < 0 || BreakPointNr >= KDB_MAXIMUM_BREAKPOINT_COUNT)
612 {
613 KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
614 return FALSE;
615 }
616
617 if (!BreakPoint)
618 {
619 BreakPoint = KdbBreakPoints + BreakPointNr;
620 }
621
622 if (BreakPoint->Type == KdbBreakPointNone)
623 {
624 KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
625 return FALSE;
626 }
627
628 if (BreakPoint->Enabled && !KdbpDisableBreakPoint(-1, BreakPoint))
629 return FALSE;
630
631 if (BreakPoint->Type != KdbBreakPointTemporary)
632 KdbpPrint("Breakpoint %d deleted.\n", BreakPointNr);
633
634 BreakPoint->Type = KdbBreakPointNone;
635 KdbBreakPointCount--;
636
637 return TRUE;
638}
639
650static LONG
654{
655 ULONG i;
657
658 if (ExceptionCode == STATUS_BREAKPOINT) /* Software interrupt */
659 {
660 ULONG_PTR BpPc = KeGetContextPc(Context) - 1; /* Get EIP of INT3 instruction */
661 for (i = 0; i < KdbSwBreakPointCount; i++)
662 {
666
667 if (KdbSwBreakPoints[i]->Address == BpPc)
668 {
669 return KdbSwBreakPoints[i] - KdbBreakPoints;
670 }
671 }
672 }
673 else if (ExceptionCode == STATUS_SINGLE_STEP) /* Hardware interrupt */
674 {
675 UCHAR DebugReg;
676
677 for (i = 0; i < KdbHwBreakPointCount; i++)
678 {
681 DebugReg = KdbHwBreakPoints[i]->Data.Hw.DebugReg;
682
683 if ((Context->Dr6 & ((ULONG_PTR)1 << DebugReg)) != 0)
684 {
685 return KdbHwBreakPoints[i] - KdbBreakPoints;
686 }
687 }
688 }
689
690 return -1;
691}
692
705 IN LONG BreakPointNr OPTIONAL,
706 IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
707{
709 INT i;
710 ULONG ul;
711
712 if (BreakPointNr < 0)
713 {
714 ASSERT(BreakPoint);
715 BreakPointNr = BreakPoint - KdbBreakPoints;
716 }
717
718 if (BreakPointNr < 0 || BreakPointNr >= KDB_MAXIMUM_BREAKPOINT_COUNT)
719 {
720 KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
721 return FALSE;
722 }
723
724 if (!BreakPoint)
725 {
726 BreakPoint = KdbBreakPoints + BreakPointNr;
727 }
728
729 if (BreakPoint->Type == KdbBreakPointNone)
730 {
731 KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
732 return FALSE;
733 }
734
735 if (BreakPoint->Enabled)
736 {
737 KdbpPrint("Breakpoint %d is already enabled.\n", BreakPointNr);
738 return TRUE;
739 }
740
741 if (BreakPoint->Type == KdbBreakPointSoftware ||
742 BreakPoint->Type == KdbBreakPointTemporary)
743 {
745 {
746 KdbpPrint("Maximum number of SW breakpoints (%d) used. "
747 "Disable another breakpoint in order to enable this one.\n",
749 return FALSE;
750 }
751
752 Status = KdbpOverwriteInstruction(BreakPoint->Process, BreakPoint->Address,
753 0xCC, &BreakPoint->Data.SavedInstruction);
754 if (!NT_SUCCESS(Status))
755 {
756 KdbpPrint("Couldn't access memory at 0x%p\n", BreakPoint->Address);
757 return FALSE;
758 }
759
761 }
762 else
763 {
764 if (BreakPoint->Data.Hw.AccessType == KdbAccessExec)
765 ASSERT(BreakPoint->Data.Hw.Size == 1);
766
767 ASSERT((BreakPoint->Address % BreakPoint->Data.Hw.Size) == 0);
768
770 {
771 KdbpPrint("Maximum number of HW breakpoints (%d) already used. "
772 "Disable another breakpoint in order to enable this one.\n",
774
775 return FALSE;
776 }
777
778 /* Find unused hw breakpoint */
780 for (i = 0; i < KDB_MAXIMUM_HW_BREAKPOINT_COUNT; i++)
781 {
782 if ((KdbTrapFrame.Dr7 & (0x3 << (i * 2))) == 0)
783 break;
784 }
785
787
788 /* Set the breakpoint address. */
789 switch (i)
790 {
791 case 0:
792 KdbTrapFrame.Dr0 = BreakPoint->Address;
793 break;
794 case 1:
795 KdbTrapFrame.Dr1 = BreakPoint->Address;
796 break;
797 case 2:
798 KdbTrapFrame.Dr2 = BreakPoint->Address;
799 break;
800 case 3:
801 KdbTrapFrame.Dr3 = BreakPoint->Address;
802 break;
803 }
804
805 /* Enable the global breakpoint */
806 KdbTrapFrame.Dr7 |= (0x2 << (i * 2));
807
808 /* Enable the exact match bits. */
809 KdbTrapFrame.Dr7 |= 0x00000300;
810
811 /* Clear existing state. */
812 KdbTrapFrame.Dr7 &= ~(0xF << (16 + (i * 4)));
813
814 /* Set the breakpoint type. */
815 switch (BreakPoint->Data.Hw.AccessType)
816 {
817 case KdbAccessExec:
818 ul = 0;
819 break;
820 case KdbAccessWrite:
821 ul = 1;
822 break;
823 case KdbAccessRead:
825 ul = 3;
826 break;
827 default:
828 ASSERT(0);
829 return TRUE;
830 break;
831 }
832
833 KdbTrapFrame.Dr7 |= (ul << (16 + (i * 4)));
834
835 /* Set the breakpoint length. */
836 KdbTrapFrame.Dr7 |= ((BreakPoint->Data.Hw.Size - 1) << (18 + (i * 4)));
837
838 /* Update KdbCurrentTrapFrame - values are taken from there by the CLI */
840 {
847 }
848
849 BreakPoint->Data.Hw.DebugReg = i;
851 }
852
853 BreakPoint->Enabled = TRUE;
854 if (BreakPoint->Type != KdbBreakPointTemporary)
855 KdbpPrint("Breakpoint %d enabled.\n", BreakPointNr);
856
857 return TRUE;
858}
859
872 IN LONG BreakPointNr OPTIONAL,
873 IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
874{
875 ULONG i;
877
878 if (BreakPointNr < 0)
879 {
880 ASSERT(BreakPoint);
881 BreakPointNr = BreakPoint - KdbBreakPoints;
882 }
883
884 if (BreakPointNr < 0 || BreakPointNr >= KDB_MAXIMUM_BREAKPOINT_COUNT)
885 {
886 KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
887 return FALSE;
888 }
889
890 if (!BreakPoint)
891 {
892 BreakPoint = KdbBreakPoints + BreakPointNr;
893 }
894
895 if (BreakPoint->Type == KdbBreakPointNone)
896 {
897 KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
898 return FALSE;
899 }
900
901 if (BreakPoint->Enabled == FALSE)
902 {
903 KdbpPrint("Breakpoint %d is not enabled.\n", BreakPointNr);
904 return TRUE;
905 }
906
907 if (BreakPoint->Type == KdbBreakPointSoftware ||
908 BreakPoint->Type == KdbBreakPointTemporary)
909 {
911 Status = KdbpOverwriteInstruction(BreakPoint->Process, BreakPoint->Address,
912 BreakPoint->Data.SavedInstruction, NULL);
913
914 if (!NT_SUCCESS(Status))
915 {
916 KdbpPrint("Couldn't restore original instruction.\n");
917 return FALSE;
918 }
919
920 for (i = 0; i < KdbSwBreakPointCount; i++)
921 {
922 if (KdbSwBreakPoints[i] == BreakPoint)
923 {
925 i = -1; /* if the last breakpoint is disabled dont break with i >= KdbSwBreakPointCount */
926 break;
927 }
928 }
929
930 if (i != MAXULONG) /* not found */
931 ASSERT(0);
932 }
933 else
934 {
935 ASSERT(BreakPoint->Type == KdbBreakPointHardware);
936
937 /* Clear the breakpoint. */
938 KdbTrapFrame.Dr7 &= ~(0x3 << (BreakPoint->Data.Hw.DebugReg * 2));
939 if ((KdbTrapFrame.Dr7 & 0xFF) == 0)
940 {
941 /* If no breakpoints are enabled then clear the exact match flags. */
942 KdbTrapFrame.Dr7 &= 0xFFFFFCFF;
943 }
944
945 for (i = 0; i < KdbHwBreakPointCount; i++)
946 {
947 if (KdbHwBreakPoints[i] == BreakPoint)
948 {
950 i = -1; /* if the last breakpoint is disabled dont break with i >= KdbHwBreakPointCount */
951 break;
952 }
953 }
954
955 if (i != MAXULONG) /* not found */
956 ASSERT(0);
957 }
958
959 BreakPoint->Enabled = FALSE;
960 if (BreakPoint->Type != KdbBreakPointTemporary)
961 KdbpPrint("Breakpoint %d disabled.\n", BreakPointNr);
962
963 return TRUE;
964}
965
977 IN LONG ExceptionNr,
978 IN BOOLEAN FirstChance,
980{
981 if (ExceptionNr >= (LONG)RTL_NUMBER_OF(KdbEnterConditions))
982 return FALSE;
983
984 *Condition = KdbEnterConditions[ExceptionNr][FirstChance ? 0 : 1];
985 return TRUE;
986}
987
999 IN LONG ExceptionNr,
1000 IN BOOLEAN FirstChance,
1002{
1003 if (ExceptionNr < 0)
1004 {
1005 for (ExceptionNr = 0; ExceptionNr < (LONG)RTL_NUMBER_OF(KdbEnterConditions); ExceptionNr++)
1006 {
1007 if (ExceptionNr == 1 || ExceptionNr == 8 ||
1008 ExceptionNr == 9 || ExceptionNr == 15) /* Reserved exceptions */
1009 {
1010 continue;
1011 }
1012
1013 KdbEnterConditions[ExceptionNr][FirstChance ? 0 : 1] = Condition;
1014 }
1015 }
1016 else
1017 {
1018 if (ExceptionNr >= (LONG)RTL_NUMBER_OF(KdbEnterConditions) ||
1019 ExceptionNr == 1 || ExceptionNr == 8 || /* Do not allow changing of the debug */
1020 ExceptionNr == 9 || ExceptionNr == 15) /* trap or reserved exceptions */
1021 {
1022 return FALSE;
1023 }
1024
1025 KdbEnterConditions[ExceptionNr][FirstChance ? 0 : 1] = Condition;
1026 }
1027
1028 return TRUE;
1029}
1030
1038BOOLEAN
1040 PVOID ThreadId)
1041{
1044
1045 /* Get a pointer to the thread */
1046 if (!NT_SUCCESS(PsLookupThreadByThreadId(ThreadId, &Thread)))
1047 {
1048 KdbpPrint("Invalid thread id: 0x%08x\n", (ULONG_PTR)ThreadId);
1049 return FALSE;
1050 }
1051 Process = Thread->ThreadsProcess;
1052
1054 {
1055 KdbpPrint("Cannot attach to thread within another process while executing a DPC.\n");
1057 return FALSE;
1058 }
1059
1060 /* Save the current thread's context (if we previously attached to a thread) */
1062 {
1064 /* Actually, we can't save the context, there's no guarantee that there was a trap frame */
1065 }
1066 else
1067 {
1069 }
1070
1071 /* Switch to the thread's context */
1073 {
1074 /* The thread we're attaching to isn't the thread on which we entered
1075 * kdb and so the thread we're attaching to is not running. There
1076 * is no guarantee that it actually has a trap frame. So we have to
1077 * peek directly at the registers which were saved on the stack when the
1078 * thread was preempted in the scheduler */
1082 }
1083 else /* Switching back to original thread */
1084 {
1086 }
1088
1089 /* Attach to the thread's process */
1092 {
1093 if (KdbCurrentProcess != KdbOriginalProcess) /* detach from previously attached process */
1094 {
1096 }
1097
1099 {
1101 }
1102
1104 }
1105
1107 return TRUE;
1108}
1109
1119BOOLEAN
1122{
1126
1127 /* Get a pointer to the process */
1129 {
1130 KdbpPrint("Invalid process id: 0x%08x\n", (ULONG_PTR)ProcessId);
1131 return FALSE;
1132 }
1133
1134 Entry = Process->ThreadListHead.Flink;
1137 {
1138 KdbpPrint("No threads in process 0x%p, cannot attach to process!\n", ProcessId);
1139 return FALSE;
1140 }
1141
1142 Thread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry);
1143
1145}
1146
1149static VOID
1151{
1153}
1154
1159static VOID
1161{
1163 PVOID SavedInitialStack, SavedStackBase, SavedKernelStack;
1164 ULONG SavedStackLimit;
1165
1167
1168 /* Take control of the display */
1169 if (KdpDebugMode.Screen)
1171
1172 /* Call the interface's main loop on a different stack */
1174 SavedInitialStack = Thread->Tcb.InitialStack;
1175 SavedStackBase = Thread->Tcb.StackBase;
1176 SavedStackLimit = Thread->Tcb.StackLimit;
1177 SavedKernelStack = Thread->Tcb.KernelStack;
1178 Thread->Tcb.InitialStack = Thread->Tcb.StackBase = (char*)KdbStack + KDB_STACK_SIZE;
1179 Thread->Tcb.StackLimit = (ULONG_PTR)KdbStack;
1180 Thread->Tcb.KernelStack = (char*)KdbStack + KDB_STACK_SIZE;
1181
1182 // KdbpPrint("Switching to KDB stack 0x%08x-0x%08x (Current Stack is 0x%08x)\n", Thread->Tcb.StackLimit, Thread->Tcb.StackBase, Esp);
1183
1185
1186 Thread->Tcb.InitialStack = SavedInitialStack;
1187 Thread->Tcb.StackBase = SavedStackBase;
1188 Thread->Tcb.StackLimit = SavedStackLimit;
1189 Thread->Tcb.KernelStack = SavedKernelStack;
1190
1191 /* Release the display */
1192 if (KdpDebugMode.Screen)
1194
1196}
1197
1198static ULONG
1201{
1202 ULONG Ret;
1203
1204 switch (ExceptionCode)
1205 {
1207 Ret = 0;
1208 break;
1209 case STATUS_SINGLE_STEP:
1210 Ret = 1;
1211 break;
1212 case STATUS_BREAKPOINT:
1213 Ret = 3;
1214 break;
1216 Ret = 4;
1217 break;
1219 Ret = 5;
1220 break;
1222 Ret = 6;
1223 break;
1225 Ret = 7;
1226 break;
1228 Ret = 12;
1229 break;
1231 Ret = 14;
1232 break;
1234 Ret = 17;
1235 break;
1237 Ret = 18;
1238 break;
1240 Ret = 20;
1241 break;
1242
1243 default:
1245 break;
1246 }
1247
1248 return Ret;
1249}
1250
1264KD_CONTINUE_TYPE
1266 IN PEXCEPTION_RECORD64 ExceptionRecord,
1269 IN BOOLEAN FirstChance)
1270{
1271 KDB_ENTER_CONDITION EnterCondition;
1272 KD_CONTINUE_TYPE ContinueType = kdHandleException;
1273 PKDB_BREAKPOINT BreakPoint;
1274 ULONG ExpNr;
1275 ULONGLONG ull;
1276 BOOLEAN Resume = FALSE;
1277 BOOLEAN EnterConditionMet = TRUE;
1278 ULONG OldEflags;
1279 KIRQL OldIrql;
1281
1282 ExceptionCode = (ExceptionRecord ? ExceptionRecord->ExceptionCode : STATUS_BREAKPOINT);
1283
1285
1286 /* Set continue type to kdContinue for single steps and breakpoints */
1290 {
1291 ContinueType = kdContinue;
1292 }
1293
1294 /* Check if we should handle the exception. */
1295 /* FIXME - won't get all exceptions here :( */
1297 EnterCondition = KdbEnterConditions[ExpNr][FirstChance ? 0 : 1];
1298 if (EnterCondition == KdbDoNotEnter ||
1299 (EnterCondition == KdbEnterFromUmode && PreviousMode == KernelMode) ||
1300 (EnterCondition == KdbEnterFromKmode && PreviousMode != KernelMode))
1301 {
1302 EnterConditionMet = FALSE;
1303 }
1304
1305 /* If we stopped on one of our breakpoints then let the user know */
1308
1309 if (FirstChance && (ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT) &&
1311 {
1312 BreakPoint = KdbBreakPoints + KdbLastBreakPointNr;
1313
1315 {
1316 /* ... and restore the original instruction */
1318 BreakPoint->Data.SavedInstruction, NULL)))
1319 {
1320 KdbpPrint("Couldn't restore original instruction after INT3! Cannot continue execution.\n");
1321 KeBugCheck(0); // FIXME: Proper bugcode!
1322 }
1323
1324 /* Also since we are past the int3 now, decrement EIP in the
1325 TrapFrame. This is only needed because KDBG insists on working
1326 with the TrapFrame instead of with the Context, as it is supposed
1327 to do. The context has already EIP point to the int3, since
1328 KiDispatchException accounts for that. Whatever we do here with
1329 the TrapFrame does not matter anyway, since KiDispatchException
1330 will overwrite it with the values from the Context! */
1332 }
1333
1334 if ((BreakPoint->Type == KdbBreakPointHardware) &&
1335 (BreakPoint->Data.Hw.AccessType == KdbAccessExec))
1336 {
1337 Resume = TRUE; /* Set the resume flag when continuing execution */
1338 }
1339
1340 /*
1341 * When a temporary breakpoint is hit we have to make sure that we are
1342 * in the same context in which it was set, otherwise it could happen
1343 * that another process/thread hits it before and it gets deleted.
1344 */
1345 else if (BreakPoint->Type == KdbBreakPointTemporary &&
1346 BreakPoint->Process == KdbCurrentProcess)
1347 {
1348 ASSERT((Context->EFlags & EFLAGS_TF) == 0);
1349
1350 /* Delete the temporary breakpoint which was used to step over or into the instruction */
1351 KdbpDeleteBreakPoint(-1, BreakPoint);
1352
1353 if (--KdbNumSingleSteps > 0)
1354 {
1357 {
1358 Context->EFlags |= EFLAGS_TF;
1359 }
1360
1361 goto continue_execution; /* return */
1362 }
1363
1365 }
1366
1367 /*
1368 * If we hit a breakpoint set by the debugger we set the single step flag,
1369 * ignore the next single step and reenable the breakpoint.
1370 */
1371 else if (BreakPoint->Type == KdbBreakPointSoftware ||
1372 BreakPoint->Type == KdbBreakPointTemporary)
1373 {
1375 Context->EFlags |= EFLAGS_TF;
1376 KdbBreakPointToReenable = BreakPoint;
1377 }
1378
1379 /* Make sure that the breakpoint should be triggered in this context */
1380 if (!BreakPoint->Global && BreakPoint->Process != KdbCurrentProcess)
1381 {
1382 goto continue_execution; /* return */
1383 }
1384
1385 /* Check if the condition for the breakpoint is met. */
1386 if (BreakPoint->Condition)
1387 {
1388 /* Setup the KDB trap frame */
1390
1391 ull = 0;
1393 {
1394 /* FIXME: Print warning? */
1395 }
1396 else if (ull == 0) /* condition is not met */
1397 {
1398 goto continue_execution; /* return */
1399 }
1400 }
1401
1402 if (BreakPoint->Type == KdbBreakPointSoftware)
1403 {
1404 KdbpPrint("\nEntered debugger on breakpoint #%d: EXEC 0x%04x:0x%p\n",
1406 }
1407 else if (BreakPoint->Type == KdbBreakPointHardware)
1408 {
1409 KdbpPrint("\nEntered debugger on breakpoint #%d: %s 0x%08x\n",
1411 (BreakPoint->Data.Hw.AccessType == KdbAccessRead) ? "READ" :
1412 ((BreakPoint->Data.Hw.AccessType == KdbAccessWrite) ? "WRITE" :
1413 ((BreakPoint->Data.Hw.AccessType == KdbAccessReadWrite) ? "RDWR" : "EXEC")),
1414 BreakPoint->Address);
1415 }
1416 }
1418 {
1419 /* Silently ignore a debugger initiated single step. */
1420 if ((Context->Dr6 & 0xf) == 0 && KdbBreakPointToReenable)
1421 {
1422 /* FIXME: Make sure that the breakpoint was really hit (check bp->Address vs. tf->Eip) */
1423 BreakPoint = KdbBreakPointToReenable;
1425 ASSERT(BreakPoint->Type == KdbBreakPointSoftware ||
1426 BreakPoint->Type == KdbBreakPointTemporary);
1427
1428 /*
1429 * Reenable the breakpoint we disabled to execute the breakpointed
1430 * instruction.
1431 */
1433 &BreakPoint->Data.SavedInstruction)))
1434 {
1435 KdbpPrint("Warning: Couldn't reenable breakpoint %d\n",
1436 BreakPoint - KdbBreakPoints);
1437 }
1438
1439 /* Unset TF if we are no longer single stepping. */
1440 if (KdbNumSingleSteps == 0)
1441 Context->EFlags &= ~EFLAGS_TF;
1442
1444 {
1445 goto continue_execution; /* return */
1446 }
1447 }
1448
1449 /* Quoth the raven, 'Nevermore!' */
1451
1452 /* Check if we expect a single step */
1453 if ((Context->Dr6 & 0xf) == 0 && KdbNumSingleSteps > 0)
1454 {
1455 /*ASSERT((Context->Eflags & EFLAGS_TF) != 0);*/
1456 if (--KdbNumSingleSteps > 0)
1457 {
1460 {
1461 Context->EFlags &= ~EFLAGS_TF;
1462 }
1463 else
1464 {
1465 Context->EFlags |= EFLAGS_TF;
1466 }
1467
1468 goto continue_execution; /* return */
1469 }
1470 else
1471 {
1472 Context->EFlags &= ~EFLAGS_TF;
1474 }
1475 }
1476 else
1477 {
1478 if (!EnterConditionMet)
1479 {
1480 return kdHandleException;
1481 }
1482
1483 KdbpPrint("\nEntered debugger on unexpected debug trap!\n");
1484 }
1485 }
1486 else if (ExceptionCode == STATUS_BREAKPOINT)
1487 {
1489 {
1491 EnterConditionMet = FALSE;
1492 }
1493 if (!EnterConditionMet)
1494 {
1495 return kdHandleException;
1496 }
1497
1498 KdbpPrint("\nEntered debugger on embedded INT3 at 0x%04x:0x%p.\n",
1499 Context->SegCs & 0xffff, KeGetContextPc(Context));
1500 }
1501 else
1502 {
1503 const CHAR *ExceptionString = (ExpNr < RTL_NUMBER_OF(ExceptionNrToString)) ?
1504 (ExceptionNrToString[ExpNr]) :
1505 ("Unknown/User defined exception");
1506
1507 if (!EnterConditionMet)
1508 {
1509 return ContinueType;
1510 }
1511
1512 KdbpPrint("\nEntered debugger on %s-chance exception (Exception Code: 0x%x) (%s)\n",
1513 FirstChance ? "first" : "last", ExceptionCode, ExceptionString);
1514
1516 ExceptionRecord && ExceptionRecord->NumberParameters != 0)
1517 {
1518 ULONG_PTR TrapCr2;
1519
1520 TrapCr2 = __readcr2();
1521
1522 KdbpPrint("Memory at 0x%p could not be accessed\n", TrapCr2);
1523 }
1524 }
1525
1526 /* Once we enter the debugger we do not expect any more single steps to happen */
1528
1529 /* Update the current process pointer */
1533
1534 /* Setup the KDB trap frame */
1536
1537 /* Enter critical section */
1538 OldEflags = __readeflags();
1539 _disable();
1540
1541 /* HACK: Save the current IRQL and pretend we are at dispatch level */
1543 if (OldIrql > DISPATCH_LEVEL)
1545
1546 /* Exception inside the debugger? Game over. */
1548 {
1549 __writeeflags(OldEflags);
1550 return kdHandleException;
1551 }
1552
1553 /* Call the main loop */
1555
1556 /* Check if we should single step */
1557 if (KdbNumSingleSteps > 0)
1558 {
1559 /* Variable explains itself! */
1561
1564 {
1566 /*KdbCurrentTrapFrame->EFlags &= ~EFLAGS_TF;*/
1567 }
1568 else
1569 {
1571 }
1572 }
1573
1574 /* We can't update the current thread's trapframe 'cause it might not have one */
1575
1576 /* Detach from attached process */
1578 {
1580 }
1581
1582 /* Update the exception Context */
1584
1585 /* Decrement the entry count */
1587
1588 /* HACK: Raise back to old IRQL */
1589 if (OldIrql > DISPATCH_LEVEL)
1591
1592 /* Leave critical section */
1593 __writeeflags(OldEflags);
1594
1595 /* Check if user requested a bugcheck */
1597 {
1598 /* Clear the flag and bugcheck the system */
1600 KeBugCheck(MANUALLY_INITIATED_CRASH);
1601 }
1602
1603continue_execution:
1604 /* Clear debug status */
1605 if (ExceptionCode == STATUS_BREAKPOINT) /* FIXME: Why clear DR6 on INT3? */
1606 {
1607 /* Set the RF flag so we don't trigger the same breakpoint again. */
1608 if (Resume)
1609 {
1610 Context->EFlags |= EFLAGS_RF;
1611 }
1612
1613 /* Clear dr6 status flags. */
1614 Context->Dr6 &= ~0x0000e00f;
1615
1617 {
1618 /* Skip the current instruction */
1620 }
1621 }
1622
1623 return ContinueType;
1624}
1625
1626VOID
1627NTAPI
1629 PCHAR p1)
1630{
1631#define CONST_STR_LEN(x) (sizeof(x)/sizeof(x[0]) - 1)
1632
1633 while (p1 && (p1 = strchr(p1, ' ')))
1634 {
1635 /* Skip other spaces */
1636 while (*p1 == ' ') ++p1;
1637
1638 if (!_strnicmp(p1, "KDSERIAL", CONST_STR_LEN("KDSERIAL")))
1639 {
1640 p1 += CONST_STR_LEN("KDSERIAL");
1642 KdpDebugMode.Serial = TRUE;
1643 }
1644 else if (!_strnicmp(p1, "KDNOECHO", CONST_STR_LEN("KDNOECHO")))
1645 {
1646 p1 += CONST_STR_LEN("KDNOECHO");
1648 }
1649 else if (!_strnicmp(p1, "FIRSTCHANCE", CONST_STR_LEN("FIRSTCHANCE")))
1650 {
1651 p1 += CONST_STR_LEN("FIRSTCHANCE");
1653 }
1654 }
1655}
1656
1659 OUT PVOID Dest,
1660 IN PVOID Src,
1661 IN ULONG Bytes)
1662{
1664 Dest,
1665 Bytes,
1666 0,
1668 NULL);
1669}
1670
1673 OUT PVOID Dest,
1674 IN PVOID Src,
1675 IN ULONG Bytes)
1676{
1678 Src,
1679 Bytes,
1680 0,
1682 NULL);
1683}
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
Type
Definition: Type.h:7
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1427
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1774
#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
#define PAGE_READONLY
Definition: compat.h:138
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
BOOLEAN NTAPI KeIsExecutingDpc(VOID)
Definition: dpc.c:947
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define NonPagedPool
Definition: env_spec_w32.h:307
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2711
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
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
LONG KdbpGetInstLength(IN ULONG_PTR Address)
Definition: i386-dis.c:95
void __cdecl _disable(void)
Definition: intrin_arm.h:365
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1669
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1674
__INTRIN_INLINE unsigned long __readcr2(void)
Definition: intrin_x86.h:1811
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:2023
NTSTATUS NTAPI KdpCopyMemoryChunks(_In_ ULONG64 Address, _In_ PVOID Buffer, _In_ ULONG TotalSize, _In_ ULONG ChunkSize, _In_ ULONG Flags, _Out_opt_ PULONG ActualSize)
Definition: kdapi.c:50
PEPROCESS KdbCurrentProcess
Definition: kdb.c:54
LONG KdbpGetNextBreakPointNr(IN ULONG Start OPTIONAL)
Gets the number of the next breakpoint >= Start.
Definition: kdb.c:384
static PKDB_BREAKPOINT KdbHwBreakPoints[KDB_MAXIMUM_HW_BREAKPOINT_COUNT]
Definition: kdb.c:45
PETHREAD KdbCurrentThread
Definition: kdb.c:56
KD_CONTINUE_TYPE KdbEnterDebuggerException(IN PEXCEPTION_RECORD64 ExceptionRecord, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT Context, IN BOOLEAN FirstChance)
KDB Exception filter.
Definition: kdb.c:1265
PETHREAD KdbOriginalThread
Definition: kdb.c:57
static PKDB_BREAKPOINT KdbBreakPointToReenable
Definition: kdb.c:46
PKDB_KTRAP_FRAME KdbCurrentTrapFrame
Definition: kdb.c:58
static LONG KdbpIsBreakPointOurs(IN NTSTATUS ExceptionCode, IN PCONTEXT Context)
Checks if the breakpoint was set by the debugger.
Definition: kdb.c:651
static KDB_KTRAP_FRAME KdbThreadTrapFrame
Definition: kdb.c:60
static KDB_KTRAP_FRAME KdbTrapFrame
Definition: kdb.c:59
static BOOLEAN KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep
Definition: kdb.c:48
BOOLEAN KdbpSetEnterCondition(IN LONG ExceptionNr, IN BOOLEAN FirstChance, IN KDB_ENTER_CONDITION Condition)
Sets the first or last chance enter-condition for exception nr. ExceptionNr.
Definition: kdb.c:998
PEPROCESS KdbOriginalProcess
Definition: kdb.c:55
BOOLEAN KdbpDisableBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Disables a breakpoint.
Definition: kdb.c:871
VOID NTAPI KdbpGetCommandLineSettings(PCHAR p1)
Definition: kdb.c:1628
#define KDB_MAXIMUM_HW_BREAKPOINT_COUNT
Definition: kdb.c:29
#define CONST_STR_LEN(x)
BOOLEAN KdbpBugCheckRequested
Definition: kdb_cli.c:156
BOOLEAN KdbpStepIntoInstruction(ULONG_PTR Eip)
Steps into an instruction (interrupts)
Definition: kdb.c:302
static NTSTATUS KdbpOverwriteInstruction(IN PEPROCESS Process, IN ULONG_PTR Address, IN UCHAR NewInst, OUT PUCHAR OldInst OPTIONAL)
Overwrites the instruction at Address with NewInst and stores the old instruction in *OldInst.
Definition: kdb.c:157
BOOLEAN KdbpGetEnterCondition(IN LONG ExceptionNr, IN BOOLEAN FirstChance, OUT KDB_ENTER_CONDITION *Condition)
Gets the first or last chance enter-condition for exception nr. ExceptionNr.
Definition: kdb.c:976
static KDB_ENTER_CONDITION KdbEnterConditions[][2]
Definition: kdb.c:65
static VOID KdbpKdbTrapFrameFromKernelStack(PVOID KernelStack, PKDB_KTRAP_FRAME KdbTrapFrame)
Definition: kdb.c:121
BOOLEAN KdbpAttachToProcess(PVOID ProcessId)
Switches to another process/thread context.
Definition: kdb.c:1120
ULONG KdbDebugState
Definition: kdb.c:52
BOOLEAN KdbpAttachToThread(PVOID ThreadId)
Switches to another thread context.
Definition: kdb.c:1039
#define KDB_MAXIMUM_SW_BREAKPOINT_COUNT
Definition: kdb.c:30
static BOOLEAN KdbEnteredOnSingleStep
Definition: kdb.c:53
#define KDB_STACK_ALIGN
Definition: kdb.c:25
BOOLEAN KdbpEnableBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Enables a breakpoint.
Definition: kdb.c:704
#define KDB_STACK_RESERVE
Definition: kdb.c:26
static VOID KdbpInternalEnter(VOID)
Internal function to enter KDB.
Definition: kdb.c:1160
LONG KdbLastBreakPointNr
Definition: kdb.c:49
static PKDB_BREAKPOINT KdbSwBreakPoints[KDB_MAXIMUM_SW_BREAKPOINT_COUNT]
Definition: kdb.c:44
NTSTATUS KdbpSafeWriteMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1672
#define KDB_MAXIMUM_BREAKPOINT_COUNT
Definition: kdb.c:28
BOOLEAN KdbpShouldStepOverInstruction(ULONG_PTR Eip)
Checks whether the given instruction can be single stepped or has to be stepped over using a temporar...
Definition: kdb.c:236
static LONG KdbEntryCount
Definition: kdb.c:37
BOOLEAN KdbSingleStepOver
Definition: kdb.c:51
BOOLEAN KdbpDeleteBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Deletes a breakpoint.
Definition: kdb.c:601
ULONG KdbNumSingleSteps
Definition: kdb.c:50
NTSTATUS KdbpInsertBreakPoint(IN ULONG_PTR Address, IN KDB_BREAKPOINT_TYPE Type, IN UCHAR Size OPTIONAL, IN KDB_ACCESS_TYPE AccessType OPTIONAL, IN PCHAR ConditionExpression OPTIONAL, IN BOOLEAN Global, OUT PLONG BreakPointNr OPTIONAL)
Inserts a breakpoint into the breakpoint array.
Definition: kdb.c:480
static const CHAR * ExceptionNrToString[]
Definition: kdb.c:93
NTSTATUS KdbpSafeReadMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1658
BOOLEAN KdbpStepOverInstruction(ULONG_PTR Eip)
Steps over an instruction.
Definition: kdb.c:274
static VOID KdbpCallMainLoop(VOID)
Calls the main loop ...
Definition: kdb.c:1150
static ULONG KdbSwBreakPointCount
Definition: kdb.c:42
static ULONG KdbpGetExceptionNumberFromStatus(IN NTSTATUS ExceptionCode)
Definition: kdb.c:1199
static KAPC_STATE KdbApcState
Definition: kdb.c:61
#define KDB_STACK_SIZE
Definition: kdb.c:20
BOOLEAN KdbpGetBreakPointInfo(IN ULONG BreakPointNr, OUT ULONG_PTR *Address OPTIONAL, OUT KDB_BREAKPOINT_TYPE *Type OPTIONAL, OUT UCHAR *Size OPTIONAL, OUT KDB_ACCESS_TYPE *AccessType OPTIONAL, OUT UCHAR *DebugReg OPTIONAL, OUT BOOLEAN *Enabled OPTIONAL, OUT BOOLEAN *Global OPTIONAL, OUT PEPROCESS *Process OPTIONAL, OUT PCHAR *ConditionExpression OPTIONAL)
Returns information of the specified breakpoint.
Definition: kdb.c:411
static ULONG KdbHwBreakPointCount
Definition: kdb.c:43
@ KD_DEBUG_KDSERIAL
Definition: kdb.h:57
@ KD_DEBUG_KDNOECHO
Definition: kdb.h:58
enum _KDB_ENTER_CONDITION KDB_ENTER_CONDITION
@ KdbBreakPointSoftware
Definition: kdb.h:12
@ KdbBreakPointNone
Definition: kdb.h:11
@ KdbBreakPointTemporary
Definition: kdb.h:14
@ KdbBreakPointHardware
Definition: kdb.h:13
VOID KdbpCliInterpretInitFile(VOID)
This function is called by KdbEnterDebuggerException...
Definition: kdb_cli.c:3754
PVOID KdbpRpnParseExpression(IN PCHAR Expression, OUT PLONG ErrOffset OPTIONAL, OUT PCHAR ErrMsg OPTIONAL)
Parses the given expression and returns a "handle" to it.
Definition: kdb_expr.c:1142
BOOLEAN KdbpRpnEvaluateParsedExpression(IN PVOID Expression, IN PKDB_KTRAP_FRAME TrapFrame, OUT PULONGLONG Result, OUT PLONG ErrOffset OPTIONAL, OUT PCHAR ErrMsg OPTIONAL)
Evaluates the given expression and returns the result.
Definition: kdb_expr.c:1196
VOID NTAPI KdbpStackSwitchAndCall(IN PVOID NewStack, IN VOID(*Function)(VOID))
@ KdbAccessExec
Definition: kdb.h:22
@ KdbAccessRead
Definition: kdb.h:19
@ KdbAccessReadWrite
Definition: kdb.h:21
@ KdbAccessWrite
Definition: kdb.h:20
VOID KdbpPrint(_In_ PSTR Format, _In_ ...)
Prints the given string with printf-like formatting.
Definition: kdb_cli.c:3224
VOID KbdDisableMouse(VOID)
Definition: kdb_keyboard.c:98
@ KdbDoNotEnter
Definition: kdb.h:48
@ KdbEnterFromUmode
Definition: kdb.h:51
@ KdbEnterAlways
Definition: kdb.h:49
@ KdbEnterFromKmode
Definition: kdb.h:50
VOID KbdEnableMouse(VOID)
Definition: kdb_keyboard.c:93
PCHAR KdbInitFileBuffer
Definition: kdb_cli.c:155
enum _KDB_ACCESS_TYPE KDB_ACCESS_TYPE
VOID KdbpCliMainLoop(IN BOOLEAN EnteredOnSingleStep)
KDB Main Loop.
Definition: kdb_cli.c:3691
enum _KDB_BREAKPOINT_TYPE KDB_BREAKPOINT_TYPE
KDP_DEBUG_MODE KdpDebugMode
Definition: kdio.c:38
VOID KdpScreenRelease(VOID)
Definition: kdio.c:446
VOID KdpScreenAcquire(VOID)
Definition: kdio.c:427
_In_ UINT Bytes
Definition: mmcopy.h:9
UNICODE_STRING Global
Definition: symlink.c:37
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
@ Enabled
Definition: mountmgr.h:159
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define KernelMode
Definition: asm.h:34
#define EFLAGS_TF
Definition: ketypes.h:125
#define EFLAGS_RF
Definition: ketypes.h:131
#define KGDT_R0_CODE
Definition: ketypes.h:75
#define KGDT_R0_DATA
Definition: ketypes.h:76
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1307
#define PAGE_EXECUTE
Definition: nt_native.h:1306
#define PAGE_NOACCESS
Definition: nt_native.h:1302
#define DECLSPEC_ALIGN(x)
Definition: ntbasedef.h:251
IN ULONG IN UCHAR Condition
#define KD_BREAKPOINT_SIZE
Definition: ke.h:122
#define KeSetContextPc(Context, ProgramCounter)
Definition: ke.h:34
#define KeGetContextPc(Context)
Definition: ke.h:31
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
#define MMDBG_COPY_UNSAFE
Definition: mm.h:77
ULONG NTAPI MmGetPageProtect(struct _EPROCESS *Process, PVOID Address)
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1727
#define MMDBG_COPY_WRITE
Definition: mm.h:75
NTSTATUS NTAPI PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process)
Definition: process.c:919
NTSTATUS NTAPI PsLookupThreadByThreadId(IN HANDLE ThreadId, OUT PETHREAD *Thread)
Definition: thread.c:643
#define STATUS_ILLEGAL_INSTRUCTION
Definition: ntstatus.h:266
#define STATUS_ARRAY_BOUNDS_EXCEEDED
Definition: ntstatus.h:376
#define STATUS_ASSERTION_FAILURE
Definition: ntstatus.h:960
#define STATUS_MEMORY_NOT_ALLOCATED
Definition: ntstatus.h:396
#define STATUS_STACK_OVERFLOW
Definition: ntstatus.h:489
#define STATUS_SINGLE_STEP
Definition: ntstatus.h:185
#define STATUS_BREAKPOINT
Definition: ntstatus.h:184
#define STATUS_FLOAT_MULTIPLE_TRAPS
Definition: ntstatus.h:808
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define STATUS_FLOAT_INVALID_OPERATION
Definition: ntstatus.h:380
#define STATUS_DATATYPE_MISALIGNMENT
Definition: ntstatus.h:183
#define STATUS_INTEGER_OVERFLOW
Definition: ntstatus.h:385
#define STATUS_INTEGER_DIVIDE_BY_ZERO
Definition: ntstatus.h:384
long LONG
Definition: pedump.c:60
static WCHAR Address[46]
Definition: ping.c:68
VOID NTAPI KeDetachProcess(VOID)
Definition: procobj.c:621
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
#define STATUS_SUCCESS
Definition: shellext.h:65
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
base of all file and directory entries
Definition: entries.h:83
HANDLE UniqueThread
Definition: compat.h:826
ULONG Esp
Definition: nt_native.h:1479
ULONG Dr3
Definition: nt_native.h:1437
ULONG Dr1
Definition: nt_native.h:1435
ULONG Esi
Definition: nt_native.h:1464
ULONG Ebp
Definition: nt_native.h:1475
ULONG Dr6
Definition: nt_native.h:1438
ULONG SegSs
Definition: nt_native.h:1480
ULONG Dr0
Definition: nt_native.h:1434
ULONG Eip
Definition: nt_native.h:1476
ULONG SegCs
Definition: nt_native.h:1477
ULONG SegDs
Definition: nt_native.h:1456
ULONG EFlags
Definition: nt_native.h:1478
ULONG SegGs
Definition: nt_native.h:1453
ULONG Dr2
Definition: nt_native.h:1436
ULONG SegEs
Definition: nt_native.h:1455
ULONG Ebx
Definition: nt_native.h:1465
ULONG Edi
Definition: nt_native.h:1463
ULONG Dr7
Definition: nt_native.h:1439
LIST_ENTRY ThreadListHead
Definition: pstypes.h:1329
KTHREAD Tcb
Definition: pstypes.h:1103
CLIENT_ID Cid
Definition: pstypes.h:1128
PVOID Condition
Definition: kdb.h:33
UCHAR SavedInstruction
Definition: kdb.h:36
BOOLEAN Enabled
Definition: kdb.h:28
union _KDB_BREAKPOINT::@1786 Data
PCHAR ConditionExpression
Definition: kdb.h:32
struct _KDB_BREAKPOINT::@1786::@1787 Hw
ULONG_PTR Address
Definition: kdb.h:29
PEPROCESS Process
Definition: kdb.h:31
KDB_BREAKPOINT_TYPE Type
Definition: kdb.h:27
BOOLEAN Global
Definition: kdb.h:30
PVOID Base
Definition: ketypes.h:491
USHORT Limit
Definition: ketypes.h:490
PVOID InitialStack
Definition: ketypes.h:1604
PVOID KernelStack
Definition: ketypes.h:1615
PVOID StackBase
Definition: ketypes.h:1606
volatile VOID * StackLimit
Definition: ketypes.h:1605
Definition: typedefs.h:120
#define TAG_KDBG
Definition: tag.h:38
#define MAXULONG
Definition: typedefs.h:251
#define NTAPI
Definition: typedefs.h:36
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
@ Start
Definition: partlist.h:33
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
KAPC_STATE
Definition: ketypes.h:1285
#define ObDereferenceObject
Definition: obfuncs.h:203
#define PsGetCurrentProcess
Definition: psfuncs.h:17
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:221