ReactOS  0.4.10-dev-34-g4db10a4
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 #define KDB_MAXIMUM_BREAKPOINT_COUNT 256
22 #define KDB_MAXIMUM_HW_BREAKPOINT_COUNT 4
23 #define KDB_MAXIMUM_SW_BREAKPOINT_COUNT 256
24 
25 #define __STRING(x) #x
26 #define _STRING(x) __STRING(x)
27 
28 /* GLOBALS *******************************************************************/
29 
30 static LONG KdbEntryCount = 0;
32 
33 static ULONG KdbBreakPointCount = 0; /* Number of used breakpoints in the array */
34 static KDB_BREAKPOINT KdbBreakPoints[KDB_MAXIMUM_BREAKPOINT_COUNT] = {{0}}; /* Breakpoint array */
35 static ULONG KdbSwBreakPointCount = 0; /* Number of enabled software breakpoints */
36 static ULONG KdbHwBreakPointCount = 0; /* Number of enabled hardware breakpoints */
37 static PKDB_BREAKPOINT KdbSwBreakPoints[KDB_MAXIMUM_SW_BREAKPOINT_COUNT]; /* Enabled software breakpoints, orderless */
38 static PKDB_BREAKPOINT KdbHwBreakPoints[KDB_MAXIMUM_HW_BREAKPOINT_COUNT]; /* Enabled hardware breakpoints, orderless */
39 static PKDB_BREAKPOINT KdbBreakPointToReenable = NULL; /* Set to a breakpoint struct when single stepping after
40  a software breakpoint was hit, to reenable it */
42 LONG KdbLastBreakPointNr = -1; /* Index of the breakpoint which cause KDB to be entered */
43 ULONG KdbNumSingleSteps = 0; /* How many single steps to do */
44 BOOLEAN KdbSingleStepOver = FALSE; /* Whether to step over calls/reps. */
45 ULONG KdbDebugState = 0; /* KDBG Settings (NOECHO, KDSERIAL) */
46 static BOOLEAN KdbEnteredOnSingleStep = FALSE; /* Set to true when KDB was entered because of single step */
47 PEPROCESS KdbCurrentProcess = NULL; /* The current process context in which KDB runs */
48 PEPROCESS KdbOriginalProcess = NULL; /* The process in whichs context KDB was intered */
49 PETHREAD KdbCurrentThread = NULL; /* The current thread context in which KDB runs */
50 PETHREAD KdbOriginalThread = NULL; /* The thread in whichs context KDB was entered */
51 PKDB_KTRAP_FRAME KdbCurrentTrapFrame = NULL; /* Pointer to the current trapframe */
52 static KDB_KTRAP_FRAME KdbTrapFrame = { { 0 } }; /* The trapframe which was passed to KdbEnterDebuggerException */
53 static KDB_KTRAP_FRAME KdbThreadTrapFrame = { { 0 } }; /* The trapframe of the current thread (KdbCurrentThread) */
56 
57 /* Array of conditions when to enter KDB */
59 {
60  /* First chance Last chance */
61  { KdbDoNotEnter, KdbEnterFromKmode }, /* 0: Zero divide */
62  { KdbEnterFromKmode, KdbDoNotEnter }, /* 1: Debug trap */
63  { KdbDoNotEnter, KdbEnterAlways }, /* 2: NMI */
64  { KdbEnterFromKmode, KdbDoNotEnter }, /* 3: INT3 */
65  { KdbDoNotEnter, KdbEnterFromKmode }, /* 4: Overflow */
66  { KdbDoNotEnter, KdbEnterFromKmode }, /* 5: BOUND range exceeded */
67  { KdbDoNotEnter, KdbEnterFromKmode }, /* 6: Invalid opcode */
68  { KdbDoNotEnter, KdbEnterFromKmode }, /* 7: No math coprocessor fault */
69  { KdbEnterAlways, KdbEnterAlways }, /* 8: Double Fault */
70  { KdbEnterAlways, KdbEnterAlways }, /* 9: Unknown(9) */
71  { KdbDoNotEnter, KdbEnterFromKmode }, /* 10: Invalid TSS */
72  { KdbDoNotEnter, KdbEnterFromKmode }, /* 11: Segment Not Present */
73  { KdbDoNotEnter, KdbEnterFromKmode }, /* 12: Stack fault */
74  { KdbDoNotEnter, KdbEnterFromKmode }, /* 13: General protection fault */
75  { KdbDoNotEnter, KdbEnterFromKmode }, /* 14: Page fault */
76  { KdbEnterAlways, KdbEnterAlways }, /* 15: Reserved (15) */
77  { KdbDoNotEnter, KdbEnterFromKmode }, /* 16: FPU fault */
78  { KdbDoNotEnter, KdbEnterFromKmode }, /* 17: Alignment Check */
79  { KdbDoNotEnter, KdbEnterFromKmode }, /* 18: Machine Check */
80  { KdbDoNotEnter, KdbEnterFromKmode }, /* 19: SIMD fault */
81  { KdbEnterFromKmode, KdbDoNotEnter }, /* 20: Assertion failure */
82  { KdbDoNotEnter, KdbEnterFromKmode } /* Last entry: used for unknown exceptions */
83 };
84 
85 /* Exception descriptions */
86 static const CHAR *ExceptionNrToString[] =
87 {
88  "Divide Error",
89  "Debug Trap",
90  "NMI",
91  "Breakpoint",
92  "Overflow",
93  "BOUND range exceeded",
94  "Invalid Opcode",
95  "No Math Coprocessor",
96  "Double Fault",
97  "Unknown(9)",
98  "Invalid TSS",
99  "Segment Not Present",
100  "Stack Segment Fault",
101  "General Protection",
102  "Page Fault",
103  "Reserved(15)",
104  "Math Fault",
105  "Alignment Check",
106  "Machine Check",
107  "SIMD Fault",
108  "Assertion Failure"
109 };
110 
111 ULONG
112 NTAPI
114  IN PKTRAP_FRAME TrapFrame);
115 
116 ULONG
117 NTAPI
119  IN PKTRAP_FRAME TrapFrame);
120 
121 VOID
122 NTAPI
124  IN PKTRAP_FRAME TrapFrame,
125  IN ULONG Ss);
126 
127 VOID
128 NTAPI
130  IN PKTRAP_FRAME TrapFrame,
131  IN ULONG Esp);
132 
133 /* FUNCTIONS *****************************************************************/
134 
135 static VOID
137  PKTRAP_FRAME TrapFrame,
138  PKDB_KTRAP_FRAME KdbTrapFrame)
139 {
140  /* Copy the TrapFrame only up to Eflags and zero the rest*/
141  RtlCopyMemory(&KdbTrapFrame->Tf, TrapFrame, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
142  RtlZeroMemory((PVOID)((ULONG_PTR)&KdbTrapFrame->Tf + FIELD_OFFSET(KTRAP_FRAME, HardwareEsp)),
143  sizeof(KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
144 
145  KdbTrapFrame->Cr0 = __readcr0();
146  KdbTrapFrame->Cr2 = __readcr2();
147  KdbTrapFrame->Cr3 = __readcr3();
148  KdbTrapFrame->Cr4 = __readcr4();
149 
150  KdbTrapFrame->Tf.HardwareEsp = KiEspFromTrapFrame(TrapFrame);
151  KdbTrapFrame->Tf.HardwareSegSs = (USHORT)(KiSsFromTrapFrame(TrapFrame) & 0xFFFF);
152 
153 
154  /* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
155 }
156 
157 static VOID
159  PKDB_KTRAP_FRAME KdbTrapFrame,
160  PKTRAP_FRAME TrapFrame)
161 {
162  /* Copy the TrapFrame only up to Eflags and zero the rest*/
163  RtlCopyMemory(TrapFrame, &KdbTrapFrame->Tf, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
164 
165  /* FIXME: write cr0, cr2, cr3 and cr4 (not needed atm) */
166 
167  KiSsToTrapFrame(TrapFrame, KdbTrapFrame->Tf.HardwareSegSs);
168  KiEspToTrapFrame(TrapFrame, KdbTrapFrame->Tf.HardwareEsp);
169 
170  /* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
171 }
172 
173 static VOID
175  PVOID KernelStack,
176  PKDB_KTRAP_FRAME KdbTrapFrame)
177 {
178  ULONG_PTR *StackPtr;
179 
180  RtlZeroMemory(KdbTrapFrame, sizeof(KDB_KTRAP_FRAME));
181  StackPtr = (ULONG_PTR *) KernelStack;
182 #ifdef _M_IX86
183  KdbTrapFrame->Tf.Ebp = StackPtr[3];
184  KdbTrapFrame->Tf.Edi = StackPtr[4];
185  KdbTrapFrame->Tf.Esi = StackPtr[5];
186  KdbTrapFrame->Tf.Ebx = StackPtr[6];
187  KdbTrapFrame->Tf.Eip = StackPtr[7];
188  KdbTrapFrame->Tf.HardwareEsp = (ULONG) (StackPtr + 8);
189  KdbTrapFrame->Tf.HardwareSegSs = KGDT_R0_DATA;
190  KdbTrapFrame->Tf.SegCs = KGDT_R0_CODE;
191  KdbTrapFrame->Tf.SegDs = KGDT_R0_DATA;
192  KdbTrapFrame->Tf.SegEs = KGDT_R0_DATA;
193  KdbTrapFrame->Tf.SegGs = KGDT_R0_DATA;
194 #endif
195 
196  /* FIXME: what about the other registers??? */
197 }
198 
209 static NTSTATUS
213  IN UCHAR NewInst,
214  OUT PUCHAR OldInst OPTIONAL)
215 {
217  ULONG Protect;
220 
221  /* Get the protection for the address. */
222  Protect = MmGetPageProtect(Process, (PVOID)PAGE_ROUND_DOWN(Address));
223 
224  /* Return if that page isn't present. */
225  if (Protect & PAGE_NOACCESS)
226  {
228  }
229 
230  /* Attach to the process */
231  if (CurrentProcess != Process)
232  {
233  KeStackAttachProcess(&Process->Pcb, &ApcState);
234  }
235 
236  /* Make the page writeable if it is read only. */
238  {
239  MmSetPageProtect(Process, (PVOID)PAGE_ROUND_DOWN(Address),
241  }
242 
243  /* Copy the old instruction back to the caller. */
244  if (OldInst)
245  {
246  Status = KdbpSafeReadMemory(OldInst, (PUCHAR)Address, 1);
247  if (!NT_SUCCESS(Status))
248  {
250  {
251  MmSetPageProtect(Process, (PVOID)PAGE_ROUND_DOWN(Address), Protect);
252  }
253 
254  /* Detach from process */
255  if (CurrentProcess != Process)
256  {
257  KeDetachProcess();
258  }
259 
260  return Status;
261  }
262  }
263 
264  /* Copy the new instruction in its place. */
265  Status = KdbpSafeWriteMemory((PUCHAR)Address, &NewInst, 1);
266 
267  /* Restore the page protection. */
269  {
270  MmSetPageProtect(Process, (PVOID)PAGE_ROUND_DOWN(Address), Protect);
271  }
272 
273  /* Detach from process */
274  if (CurrentProcess != Process)
275  {
276  KeUnstackDetachProcess(&ApcState);
277  }
278 
279  return Status;
280 }
281 
288 BOOLEAN
290  ULONG_PTR Eip)
291 {
292  UCHAR Mem[3];
293  ULONG i = 0;
294 
295  if (!NT_SUCCESS(KdbpSafeReadMemory(Mem, (PVOID)Eip, sizeof (Mem))))
296  {
297  KdbpPrint("Couldn't access memory at 0x%p\n", Eip);
298  return FALSE;
299  }
300 
301  /* Check if the current instruction is a call. */
302  while ((i < sizeof (Mem)) && (Mem[i] == 0x66 || Mem[i] == 0x67))
303  i++;
304 
305  if (i == sizeof (Mem))
306  return FALSE;
307 
308  if (Mem[i] == 0xE8 || Mem[i] == 0x9A || Mem[i] == 0xF2 || Mem[i] == 0xF3 ||
309  (((i + 1) < sizeof (Mem)) && Mem[i] == 0xFF && (Mem[i+1] & 0x38) == 0x10))
310  {
311  return TRUE;
312  }
313 
314  return FALSE;
315 }
316 
326 BOOLEAN
328  ULONG_PTR Eip)
329 {
330  LONG InstLen;
331 
333  return FALSE;
334 
335  InstLen = KdbpGetInstLength(Eip);
336  if (InstLen < 1)
337  return FALSE;
338 
339  if (!NT_SUCCESS(KdbpInsertBreakPoint(Eip + InstLen, KdbBreakPointTemporary, 0, 0, NULL, FALSE, NULL)))
340  return FALSE;
341 
342  return TRUE;
343 }
344 
354 BOOLEAN
356  ULONG_PTR Eip)
357 {
358  KDESCRIPTOR Idtr = {0};
359  UCHAR Mem[2];
360  INT IntVect;
361  ULONG IntDesc[2];
362  ULONG_PTR TargetEip;
363 
364  /* Read memory */
365  if (!NT_SUCCESS(KdbpSafeReadMemory(Mem, (PVOID)Eip, sizeof (Mem))))
366  {
367  /*KdbpPrint("Couldn't access memory at 0x%p\n", Eip);*/
368  return FALSE;
369  }
370 
371  /* Check for INT instruction */
372  /* FIXME: Check for iret */
373  if (Mem[0] == 0xcc)
374  IntVect = 3;
375  else if (Mem[0] == 0xcd)
376  IntVect = Mem[1];
377  else if (Mem[0] == 0xce && KdbCurrentTrapFrame->Tf.EFlags & (1<<11)) /* 1 << 11 is the overflow flag */
378  IntVect = 4;
379  else
380  return FALSE;
381 
382  if (IntVect < 32) /* We should be informed about interrupts < 32 by the kernel, no need to breakpoint them */
383  {
384  return FALSE;
385  }
386 
387  /* Read the interrupt descriptor table register */
388  __sidt(&Idtr.Limit);
389  if (IntVect >= (Idtr.Limit + 1) / 8)
390  {
391  /*KdbpPrint("IDT does not contain interrupt vector %d\n.", IntVect);*/
392  return TRUE;
393  }
394 
395  /* Get the interrupt descriptor */
396  if (!NT_SUCCESS(KdbpSafeReadMemory(IntDesc, (PVOID)(ULONG_PTR)(Idtr.Base + (IntVect * 8)), sizeof (IntDesc))))
397  {
398  /*KdbpPrint("Couldn't access memory at 0x%p\n", (ULONG_PTR)Idtr.Base + (IntVect * 8));*/
399  return FALSE;
400  }
401 
402  /* Check descriptor and get target eip (16 bit interrupt/trap gates not supported) */
403  if ((IntDesc[1] & (1 << 15)) == 0) /* not present */
404  {
405  return FALSE;
406  }
407  if ((IntDesc[1] & 0x1f00) == 0x0500) /* Task gate */
408  {
409  /* FIXME: Task gates not supported */
410  return FALSE;
411  }
412  else if (((IntDesc[1] & 0x1fe0) == 0x0e00) || /* 32 bit Interrupt gate */
413  ((IntDesc[1] & 0x1fe0) == 0x0f00)) /* 32 bit Trap gate */
414  {
415  /* FIXME: Should the segment selector of the interrupt gate be checked? */
416  TargetEip = (IntDesc[1] & 0xffff0000) | (IntDesc[0] & 0x0000ffff);
417  }
418  else
419  {
420  return FALSE;
421  }
422 
423  /* Insert breakpoint */
425  return FALSE;
426 
427  return TRUE;
428 }
429 
436 LONG
439 {
440  for (; Start < RTL_NUMBER_OF(KdbBreakPoints); Start++)
441  {
442  if (KdbBreakPoints[Start].Type != KdbBreakPointNone)
443  return Start;
444  }
445 
446  return -1;
447 }
448 
463 BOOLEAN
465  IN ULONG BreakPointNr,
467  OUT KDB_BREAKPOINT_TYPE *Type OPTIONAL,
468  OUT UCHAR *Size OPTIONAL,
469  OUT KDB_ACCESS_TYPE *AccessType OPTIONAL,
470  OUT UCHAR *DebugReg OPTIONAL,
471  OUT BOOLEAN *Enabled OPTIONAL,
472  OUT BOOLEAN *Global OPTIONAL,
473  OUT PEPROCESS *Process OPTIONAL,
474  OUT PCHAR *ConditionExpression OPTIONAL)
475 {
476  PKDB_BREAKPOINT bp;
477 
478  if (BreakPointNr >= RTL_NUMBER_OF(KdbBreakPoints) ||
479  KdbBreakPoints[BreakPointNr].Type == KdbBreakPointNone)
480  {
481  return FALSE;
482  }
483 
484  bp = KdbBreakPoints + BreakPointNr;
485  if (Address)
486  *Address = bp->Address;
487 
488  if (Type)
489  *Type = bp->Type;
490 
491  if (bp->Type == KdbBreakPointHardware)
492  {
493  if (Size)
494  *Size = bp->Data.Hw.Size;
495 
496  if (AccessType)
497  *AccessType = bp->Data.Hw.AccessType;
498 
499  if (DebugReg && bp->Enabled)
500  *DebugReg = bp->Data.Hw.DebugReg;
501  }
502 
503  if (Enabled)
504  *Enabled = bp->Enabled;
505 
506  if (Global)
507  *Global = bp->Global;
508 
509  if (Process)
510  *Process = bp->Process;
511 
512  if (ConditionExpression)
513  *ConditionExpression = bp->ConditionExpression;
514 
515  return TRUE;
516 }
517 
532 NTSTATUS
537  IN KDB_ACCESS_TYPE AccessType OPTIONAL,
538  IN PCHAR ConditionExpression OPTIONAL,
539  IN BOOLEAN Global,
540  OUT PLONG BreakPointNr OPTIONAL)
541 {
542  LONG i;
544  PCHAR ConditionExpressionDup;
545  LONG ErrOffset;
546  CHAR ErrMsg[128];
547 
548  ASSERT(Type != KdbBreakPointNone);
549 
550  if (Type == KdbBreakPointHardware)
551  {
552  if ((Address % Size) != 0)
553  {
554  KdbpPrint("Address (0x%p) must be aligned to a multiple of the size (%d)\n", Address, Size);
555  return STATUS_UNSUCCESSFUL;
556  }
557 
558  if (AccessType == KdbAccessExec && Size != 1)
559  {
560  KdbpPrint("Size must be 1 for execution breakpoints.\n");
561  return STATUS_UNSUCCESSFUL;
562  }
563  }
564 
566  {
567  return STATUS_UNSUCCESSFUL;
568  }
569 
570  /* Parse conditon expression string and duplicate it */
571  if (ConditionExpression)
572  {
573  Condition = KdbpRpnParseExpression(ConditionExpression, &ErrOffset, ErrMsg);
574  if (!Condition)
575  {
576  if (ErrOffset >= 0)
577  KdbpPrint("Couldn't parse expression: %s at character %d\n", ErrMsg, ErrOffset);
578  else
579  KdbpPrint("Couldn't parse expression: %s", ErrMsg);
580 
581  return STATUS_UNSUCCESSFUL;
582  }
583 
584  i = strlen(ConditionExpression) + 1;
585  ConditionExpressionDup = ExAllocatePoolWithTag(NonPagedPool, i, TAG_KDBG);
586  RtlCopyMemory(ConditionExpressionDup, ConditionExpression, i);
587  }
588  else
589  {
590  Condition = NULL;
591  ConditionExpressionDup = NULL;
592  }
593 
594  /* Find unused breakpoint */
595  if (Type == KdbBreakPointTemporary)
596  {
597  for (i = RTL_NUMBER_OF(KdbBreakPoints) - 1; i >= 0; i--)
598  {
599  if (KdbBreakPoints[i].Type == KdbBreakPointNone)
600  break;
601  }
602  }
603  else
604  {
605  for (i = 0; i < (LONG)RTL_NUMBER_OF(KdbBreakPoints); i++)
606  {
607  if (KdbBreakPoints[i].Type == KdbBreakPointNone)
608  break;
609  }
610  }
611 
612  ASSERT(i < (LONG)RTL_NUMBER_OF(KdbBreakPoints));
613 
614  /* Set the breakpoint */
615  ASSERT(KdbCurrentProcess);
616  KdbBreakPoints[i].Type = Type;
617  KdbBreakPoints[i].Address = Address;
618  KdbBreakPoints[i].Enabled = FALSE;
619  KdbBreakPoints[i].Global = Global;
620  KdbBreakPoints[i].Process = KdbCurrentProcess;
621  KdbBreakPoints[i].ConditionExpression = ConditionExpressionDup;
622  KdbBreakPoints[i].Condition = Condition;
623 
624  if (Type == KdbBreakPointHardware)
625  {
626  KdbBreakPoints[i].Data.Hw.Size = Size;
627  KdbBreakPoints[i].Data.Hw.AccessType = AccessType;
628  }
629 
631 
632  if (Type != KdbBreakPointTemporary)
633  KdbpPrint("Breakpoint %d inserted.\n", i);
634 
635  /* Try to enable the breakpoint */
637 
638  /* Return the breakpoint number */
639  if (BreakPointNr)
640  *BreakPointNr = i;
641 
642  return STATUS_SUCCESS;
643 }
644 
653 BOOLEAN
655  IN LONG BreakPointNr OPTIONAL,
656  IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
657 {
658  if (BreakPointNr < 0)
659  {
660  ASSERT(BreakPoint);
661  BreakPointNr = BreakPoint - KdbBreakPoints;
662  }
663 
664  if (BreakPointNr < 0 || BreakPointNr >= KDB_MAXIMUM_BREAKPOINT_COUNT)
665  {
666  KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
667  return FALSE;
668  }
669 
670  if (!BreakPoint)
671  {
672  BreakPoint = KdbBreakPoints + BreakPointNr;
673  }
674 
675  if (BreakPoint->Type == KdbBreakPointNone)
676  {
677  KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
678  return FALSE;
679  }
680 
681  if (BreakPoint->Enabled && !KdbpDisableBreakPoint(-1, BreakPoint))
682  return FALSE;
683 
684  if (BreakPoint->Type != KdbBreakPointTemporary)
685  KdbpPrint("Breakpoint %d deleted.\n", BreakPointNr);
686 
687  BreakPoint->Type = KdbBreakPointNone;
689 
690  return TRUE;
691 }
692 
703 static LONG
706  IN PKTRAP_FRAME TrapFrame)
707 {
708  ULONG i;
709  ASSERT(ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT);
710 
711  if (ExceptionCode == STATUS_BREAKPOINT) /* Software interrupt */
712  {
713  ULONG_PTR BpEip = (ULONG_PTR)TrapFrame->Eip - 1; /* Get EIP of INT3 instruction */
714  for (i = 0; i < KdbSwBreakPointCount; i++)
715  {
716  ASSERT((KdbSwBreakPoints[i]->Type == KdbBreakPointSoftware ||
717  KdbSwBreakPoints[i]->Type == KdbBreakPointTemporary));
718  ASSERT(KdbSwBreakPoints[i]->Enabled);
719 
720  if (KdbSwBreakPoints[i]->Address == BpEip)
721  {
722  return KdbSwBreakPoints[i] - KdbBreakPoints;
723  }
724  }
725  }
726  else if (ExceptionCode == STATUS_SINGLE_STEP) /* Hardware interrupt */
727  {
728  UCHAR DebugReg;
729 
730  for (i = 0; i < KdbHwBreakPointCount; i++)
731  {
732  ASSERT(KdbHwBreakPoints[i]->Type == KdbBreakPointHardware &&
733  KdbHwBreakPoints[i]->Enabled);
734  DebugReg = KdbHwBreakPoints[i]->Data.Hw.DebugReg;
735 
736  if ((TrapFrame->Dr6 & (1 << DebugReg)) != 0)
737  {
738  return KdbHwBreakPoints[i] - KdbBreakPoints;
739  }
740  }
741  }
742 
743  return -1;
744 }
745 
756 BOOLEAN
758  IN LONG BreakPointNr OPTIONAL,
759  IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
760 {
762  INT i;
763  ULONG ul;
764 
765  if (BreakPointNr < 0)
766  {
767  ASSERT(BreakPoint);
768  BreakPointNr = BreakPoint - KdbBreakPoints;
769  }
770 
771  if (BreakPointNr < 0 || BreakPointNr >= KDB_MAXIMUM_BREAKPOINT_COUNT)
772  {
773  KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
774  return FALSE;
775  }
776 
777  if (!BreakPoint)
778  {
779  BreakPoint = KdbBreakPoints + BreakPointNr;
780  }
781 
782  if (BreakPoint->Type == KdbBreakPointNone)
783  {
784  KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
785  return FALSE;
786  }
787 
788  if (BreakPoint->Enabled)
789  {
790  KdbpPrint("Breakpoint %d is already enabled.\n", BreakPointNr);
791  return TRUE;
792  }
793 
794  if (BreakPoint->Type == KdbBreakPointSoftware ||
795  BreakPoint->Type == KdbBreakPointTemporary)
796  {
798  {
799  KdbpPrint("Maximum number of SW breakpoints (%d) used. "
800  "Disable another breakpoint in order to enable this one.\n",
802  return FALSE;
803  }
804 
805  Status = KdbpOverwriteInstruction(BreakPoint->Process, BreakPoint->Address,
806  0xCC, &BreakPoint->Data.SavedInstruction);
807  if (!NT_SUCCESS(Status))
808  {
809  KdbpPrint("Couldn't access memory at 0x%p\n", BreakPoint->Address);
810  return FALSE;
811  }
812 
813  KdbSwBreakPoints[KdbSwBreakPointCount++] = BreakPoint;
814  }
815  else
816  {
817  if (BreakPoint->Data.Hw.AccessType == KdbAccessExec)
818  ASSERT(BreakPoint->Data.Hw.Size == 1);
819 
820  ASSERT((BreakPoint->Address % BreakPoint->Data.Hw.Size) == 0);
821 
823  {
824  KdbpPrint("Maximum number of HW breakpoints (%d) already used. "
825  "Disable another breakpoint in order to enable this one.\n",
827 
828  return FALSE;
829  }
830 
831  /* Find unused hw breakpoint */
833  for (i = 0; i < KDB_MAXIMUM_HW_BREAKPOINT_COUNT; i++)
834  {
835  if ((KdbTrapFrame.Tf.Dr7 & (0x3 << (i * 2))) == 0)
836  break;
837  }
838 
839  ASSERT(i < KDB_MAXIMUM_HW_BREAKPOINT_COUNT);
840 
841  /* Set the breakpoint address. */
842  switch (i)
843  {
844  case 0:
845  KdbTrapFrame.Tf.Dr0 = BreakPoint->Address;
846  break;
847  case 1:
848  KdbTrapFrame.Tf.Dr1 = BreakPoint->Address;
849  break;
850  case 2:
851  KdbTrapFrame.Tf.Dr2 = BreakPoint->Address;
852  break;
853  case 3:
854  KdbTrapFrame.Tf.Dr3 = BreakPoint->Address;
855  break;
856  }
857 
858  /* Enable the global breakpoint */
859  KdbTrapFrame.Tf.Dr7 |= (0x2 << (i * 2));
860 
861  /* Enable the exact match bits. */
862  KdbTrapFrame.Tf.Dr7 |= 0x00000300;
863 
864  /* Clear existing state. */
865  KdbTrapFrame.Tf.Dr7 &= ~(0xF << (16 + (i * 4)));
866 
867  /* Set the breakpoint type. */
868  switch (BreakPoint->Data.Hw.AccessType)
869  {
870  case KdbAccessExec:
871  ul = 0;
872  break;
873  case KdbAccessWrite:
874  ul = 1;
875  break;
876  case KdbAccessRead:
877  case KdbAccessReadWrite:
878  ul = 3;
879  break;
880  default:
881  ASSERT(0);
882  return TRUE;
883  break;
884  }
885 
886  KdbTrapFrame.Tf.Dr7 |= (ul << (16 + (i * 4)));
887 
888  /* Set the breakpoint length. */
889  KdbTrapFrame.Tf.Dr7 |= ((BreakPoint->Data.Hw.Size - 1) << (18 + (i * 4)));
890 
891  /* Update KdbCurrentTrapFrame - values are taken from there by the CLI */
892  if (&KdbTrapFrame != KdbCurrentTrapFrame)
893  {
894  KdbCurrentTrapFrame->Tf.Dr0 = KdbTrapFrame.Tf.Dr0;
895  KdbCurrentTrapFrame->Tf.Dr1 = KdbTrapFrame.Tf.Dr1;
896  KdbCurrentTrapFrame->Tf.Dr2 = KdbTrapFrame.Tf.Dr2;
897  KdbCurrentTrapFrame->Tf.Dr3 = KdbTrapFrame.Tf.Dr3;
898  KdbCurrentTrapFrame->Tf.Dr6 = KdbTrapFrame.Tf.Dr6;
899  KdbCurrentTrapFrame->Tf.Dr7 = KdbTrapFrame.Tf.Dr7;
900  }
901 
902  BreakPoint->Data.Hw.DebugReg = i;
903  KdbHwBreakPoints[KdbHwBreakPointCount++] = BreakPoint;
904  }
905 
906  BreakPoint->Enabled = TRUE;
907  if (BreakPoint->Type != KdbBreakPointTemporary)
908  KdbpPrint("Breakpoint %d enabled.\n", BreakPointNr);
909 
910  return TRUE;
911 }
912 
923 BOOLEAN
925  IN LONG BreakPointNr OPTIONAL,
926  IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
927 {
928  ULONG i;
930 
931  if (BreakPointNr < 0)
932  {
933  ASSERT(BreakPoint);
934  BreakPointNr = BreakPoint - KdbBreakPoints;
935  }
936 
937  if (BreakPointNr < 0 || BreakPointNr >= KDB_MAXIMUM_BREAKPOINT_COUNT)
938  {
939  KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
940  return FALSE;
941  }
942 
943  if (!BreakPoint)
944  {
945  BreakPoint = KdbBreakPoints + BreakPointNr;
946  }
947 
948  if (BreakPoint->Type == KdbBreakPointNone)
949  {
950  KdbpPrint("Invalid breakpoint: %d\n", BreakPointNr);
951  return FALSE;
952  }
953 
954  if (BreakPoint->Enabled == FALSE)
955  {
956  KdbpPrint("Breakpoint %d is not enabled.\n", BreakPointNr);
957  return TRUE;
958  }
959 
960  if (BreakPoint->Type == KdbBreakPointSoftware ||
961  BreakPoint->Type == KdbBreakPointTemporary)
962  {
964  Status = KdbpOverwriteInstruction(BreakPoint->Process, BreakPoint->Address,
965  BreakPoint->Data.SavedInstruction, NULL);
966 
967  if (!NT_SUCCESS(Status))
968  {
969  KdbpPrint("Couldn't restore original instruction.\n");
970  return FALSE;
971  }
972 
973  for (i = 0; i < KdbSwBreakPointCount; i++)
974  {
975  if (KdbSwBreakPoints[i] == BreakPoint)
976  {
977  KdbSwBreakPoints[i] = KdbSwBreakPoints[--KdbSwBreakPointCount];
978  i = -1; /* if the last breakpoint is disabled dont break with i >= KdbSwBreakPointCount */
979  break;
980  }
981  }
982 
983  if (i != MAXULONG) /* not found */
984  ASSERT(0);
985  }
986  else
987  {
988  ASSERT(BreakPoint->Type == KdbBreakPointHardware);
989 
990  /* Clear the breakpoint. */
991  KdbTrapFrame.Tf.Dr7 &= ~(0x3 << (BreakPoint->Data.Hw.DebugReg * 2));
992  if ((KdbTrapFrame.Tf.Dr7 & 0xFF) == 0)
993  {
994  /* If no breakpoints are enabled then clear the exact match flags. */
995  KdbTrapFrame.Tf.Dr7 &= 0xFFFFFCFF;
996  }
997 
998  for (i = 0; i < KdbHwBreakPointCount; i++)
999  {
1000  if (KdbHwBreakPoints[i] == BreakPoint)
1001  {
1002  KdbHwBreakPoints[i] = KdbHwBreakPoints[--KdbHwBreakPointCount];
1003  i = -1; /* if the last breakpoint is disabled dont break with i >= KdbHwBreakPointCount */
1004  break;
1005  }
1006  }
1007 
1008  if (i != MAXULONG) /* not found */
1009  ASSERT(0);
1010  }
1011 
1012  BreakPoint->Enabled = FALSE;
1013  if (BreakPoint->Type != KdbBreakPointTemporary)
1014  KdbpPrint("Breakpoint %d disabled.\n", BreakPointNr);
1015 
1016  return TRUE;
1017 }
1018 
1028 BOOLEAN
1030  IN LONG ExceptionNr,
1031  IN BOOLEAN FirstChance,
1033 {
1034  if (ExceptionNr >= (LONG)RTL_NUMBER_OF(KdbEnterConditions))
1035  return FALSE;
1036 
1037  *Condition = KdbEnterConditions[ExceptionNr][FirstChance ? 0 : 1];
1038  return TRUE;
1039 }
1040 
1050 BOOLEAN
1052  IN LONG ExceptionNr,
1053  IN BOOLEAN FirstChance,
1055 {
1056  if (ExceptionNr < 0)
1057  {
1058  for (ExceptionNr = 0; ExceptionNr < (LONG)RTL_NUMBER_OF(KdbEnterConditions); ExceptionNr++)
1059  {
1060  if (ExceptionNr == 1 || ExceptionNr == 8 ||
1061  ExceptionNr == 9 || ExceptionNr == 15) /* Reserved exceptions */
1062  {
1063  continue;
1064  }
1065 
1066  KdbEnterConditions[ExceptionNr][FirstChance ? 0 : 1] = Condition;
1067  }
1068  }
1069  else
1070  {
1071  if (ExceptionNr >= (LONG)RTL_NUMBER_OF(KdbEnterConditions) ||
1072  ExceptionNr == 1 || ExceptionNr == 8 || /* Do not allow changing of the debug */
1073  ExceptionNr == 9 || ExceptionNr == 15) /* trap or reserved exceptions */
1074  {
1075  return FALSE;
1076  }
1077 
1078  KdbEnterConditions[ExceptionNr][FirstChance ? 0 : 1] = Condition;
1079  }
1080 
1081  return TRUE;
1082 }
1083 
1091 BOOLEAN
1093  PVOID ThreadId)
1094 {
1095  PETHREAD Thread = NULL;
1097 
1098  /* Get a pointer to the thread */
1099  if (!NT_SUCCESS(PsLookupThreadByThreadId(ThreadId, &Thread)))
1100  {
1101  KdbpPrint("Invalid thread id: 0x%08x\n", (ULONG_PTR)ThreadId);
1102  return FALSE;
1103  }
1104  Process = Thread->ThreadsProcess;
1105 
1106  if (KeIsExecutingDpc() && Process != KdbCurrentProcess)
1107  {
1108  KdbpPrint("Cannot attach to thread within another process while executing a DPC.\n");
1109  ObDereferenceObject(Thread);
1110  return FALSE;
1111  }
1112 
1113  /* Save the current thread's context (if we previously attached to a thread) */
1114  if (KdbCurrentThread != KdbOriginalThread)
1115  {
1116  ASSERT(KdbCurrentTrapFrame == &KdbThreadTrapFrame);
1117  /* Actually, we can't save the context, there's no guarantee that there was a trap frame */
1118  }
1119  else
1120  {
1121  ASSERT(KdbCurrentTrapFrame == &KdbTrapFrame);
1122  }
1123 
1124  /* Switch to the thread's context */
1125  if (Thread != KdbOriginalThread)
1126  {
1127  /* The thread we're attaching to isn't the thread on which we entered
1128  * kdb and so the thread we're attaching to is not running. There
1129  * is no guarantee that it actually has a trap frame. So we have to
1130  * peek directly at the registers which were saved on the stack when the
1131  * thread was preempted in the scheduler */
1133  &KdbThreadTrapFrame);
1134  KdbCurrentTrapFrame = &KdbThreadTrapFrame;
1135  }
1136  else /* Switching back to original thread */
1137  {
1138  KdbCurrentTrapFrame = &KdbTrapFrame;
1139  }
1140  KdbCurrentThread = Thread;
1141 
1142  /* Attach to the thread's process */
1143  ASSERT(KdbCurrentProcess == PsGetCurrentProcess());
1144  if (KdbCurrentProcess != Process)
1145  {
1146  if (KdbCurrentProcess != KdbOriginalProcess) /* detach from previously attached process */
1147  {
1149  }
1150 
1151  if (KdbOriginalProcess != Process)
1152  {
1153  KeStackAttachProcess(&Process->Pcb, &KdbApcState);
1154  }
1155 
1156  KdbCurrentProcess = Process;
1157  }
1158 
1159  ObDereferenceObject(Thread);
1160  return TRUE;
1161 }
1162 
1172 BOOLEAN
1174  PVOID ProcessId)
1175 {
1177  PETHREAD Thread;
1179 
1180  /* Get a pointer to the process */
1181  if (!NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &Process)))
1182  {
1183  KdbpPrint("Invalid process id: 0x%08x\n", (ULONG_PTR)ProcessId);
1184  return FALSE;
1185  }
1186 
1187  Entry = Process->ThreadListHead.Flink;
1188  ObDereferenceObject(Process);
1189  if (Entry == &KdbCurrentProcess->ThreadListHead)
1190  {
1191  KdbpPrint("No threads in process 0x%p, cannot attach to process!\n", ProcessId);
1192  return FALSE;
1193  }
1194 
1195  Thread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry);
1196 
1197  return KdbpAttachToThread(Thread->Cid.UniqueThread);
1198 }
1199 
1202 static VOID
1204 {
1206 }
1207 
1212 static VOID
1214 {
1215  PETHREAD Thread;
1216  PVOID SavedInitialStack, SavedStackBase, SavedKernelStack;
1217  ULONG SavedStackLimit;
1218 
1219  KbdDisableMouse();
1220 
1221  if (KdpDebugMode.Screen &&
1224  {
1225  /* Acquire ownership and reset the display */
1227  InbvResetDisplay();
1228 
1229  /* Display debugger prompt */
1230  InbvSolidColorFill(0, 0, 639, 479, 0);
1231  InbvSetTextColor(15);
1234  InbvSetScrollRegion(0, 0, 639, 479);
1235  }
1236 
1237  /* Call the interface's main loop on a different stack */
1238  Thread = PsGetCurrentThread();
1239  SavedInitialStack = Thread->Tcb.InitialStack;
1240  SavedStackBase = Thread->Tcb.StackBase;
1241  SavedStackLimit = Thread->Tcb.StackLimit;
1242  SavedKernelStack = Thread->Tcb.KernelStack;
1243  Thread->Tcb.InitialStack = Thread->Tcb.StackBase = (char*)KdbStack + KDB_STACK_SIZE;
1244  Thread->Tcb.StackLimit = (ULONG_PTR)KdbStack;
1245  Thread->Tcb.KernelStack = (char*)KdbStack + KDB_STACK_SIZE;
1246 
1247  /*KdbpPrint("Switching to KDB stack 0x%08x-0x%08x (Current Stack is 0x%08x)\n", Thread->Tcb.StackLimit, Thread->Tcb.StackBase, Esp);*/
1248 
1250 
1251  Thread->Tcb.InitialStack = SavedInitialStack;
1252  Thread->Tcb.StackBase = SavedStackBase;
1253  Thread->Tcb.StackLimit = SavedStackLimit;
1254  Thread->Tcb.KernelStack = SavedKernelStack;
1255  KbdEnableMouse();
1256 }
1257 
1258 static ULONG
1261 {
1262  ULONG Ret;
1263 
1264  switch (ExceptionCode)
1265  {
1267  Ret = 0;
1268  break;
1269  case STATUS_SINGLE_STEP:
1270  Ret = 1;
1271  break;
1272  case STATUS_BREAKPOINT:
1273  Ret = 3;
1274  break;
1276  Ret = 4;
1277  break;
1279  Ret = 5;
1280  break;
1282  Ret = 6;
1283  break;
1285  Ret = 7;
1286  break;
1287  case STATUS_STACK_OVERFLOW:
1288  Ret = 12;
1289  break;
1291  Ret = 14;
1292  break;
1294  Ret = 17;
1295  break;
1297  Ret = 18;
1298  break;
1300  Ret = 20;
1301  break;
1302 
1303  default:
1304  Ret = RTL_NUMBER_OF(KdbEnterConditions) - 1;
1305  break;
1306  }
1307 
1308  return Ret;
1309 }
1310 
1324 KD_CONTINUE_TYPE
1326  IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
1329  IN OUT PKTRAP_FRAME TrapFrame,
1330  IN BOOLEAN FirstChance)
1331 {
1332  KDB_ENTER_CONDITION EnterCondition;
1333  KD_CONTINUE_TYPE ContinueType = kdHandleException;
1334  PKDB_BREAKPOINT BreakPoint;
1335  ULONG ExpNr;
1336  ULONGLONG ull;
1337  BOOLEAN Resume = FALSE;
1338  BOOLEAN EnterConditionMet = TRUE;
1339  ULONG OldEflags;
1340  KIRQL OldIrql;
1342 
1343  ExceptionCode = (ExceptionRecord ? ExceptionRecord->ExceptionCode : STATUS_BREAKPOINT);
1344 
1345  KdbCurrentProcess = PsGetCurrentProcess();
1346 
1347  /* Set continue type to kdContinue for single steps and breakpoints */
1348  if (ExceptionCode == STATUS_SINGLE_STEP ||
1349  ExceptionCode == STATUS_BREAKPOINT ||
1350  ExceptionCode == STATUS_ASSERTION_FAILURE)
1351  {
1352  ContinueType = kdContinue;
1353  }
1354 
1355  /* Check if we should handle the exception. */
1356  /* FIXME - won't get all exceptions here :( */
1357  ExpNr = KdbpGetExceptionNumberFromStatus(ExceptionCode);
1358  EnterCondition = KdbEnterConditions[ExpNr][FirstChance ? 0 : 1];
1359  if (EnterCondition == KdbDoNotEnter ||
1360  (EnterCondition == KdbEnterFromUmode && PreviousMode == KernelMode) ||
1361  (EnterCondition == KdbEnterFromKmode && PreviousMode != KernelMode))
1362  {
1363  EnterConditionMet = FALSE;
1364  }
1365 
1366  /* If we stopped on one of our breakpoints then let the user know. */
1367  KdbLastBreakPointNr = -1;
1369 
1370  if (FirstChance && (ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT) &&
1371  (KdbLastBreakPointNr = KdbpIsBreakPointOurs(ExceptionCode, TrapFrame)) >= 0)
1372  {
1373  BreakPoint = KdbBreakPoints + KdbLastBreakPointNr;
1374 
1375  if (ExceptionCode == STATUS_BREAKPOINT)
1376  {
1377  /* ... and restore the original instruction. */
1378  if (!NT_SUCCESS(KdbpOverwriteInstruction(KdbCurrentProcess, BreakPoint->Address,
1379  BreakPoint->Data.SavedInstruction, NULL)))
1380  {
1381  KdbpPrint("Couldn't restore original instruction after INT3! Cannot continue execution.\n");
1382  KeBugCheck(0); // FIXME: Proper bugcode!
1383  }
1384 
1385  /* Also since we are past the int3 now, decrement EIP in the
1386  TrapFrame. This is only needed because KDBG insists on working
1387  with the TrapFrame instead of with the Context, as it is supposed
1388  to do. The context has already EIP point to the int3, since
1389  KiDispatchException accounts for that. Whatever we do here with
1390  the TrapFrame does not matter anyway, since KiDispatchException
1391  will overwrite it with the values from the Context! */
1392  TrapFrame->Eip--;
1393  }
1394 
1395  if ((BreakPoint->Type == KdbBreakPointHardware) &&
1396  (BreakPoint->Data.Hw.AccessType == KdbAccessExec))
1397  {
1398  Resume = TRUE; /* Set the resume flag when continuing execution */
1399  }
1400 
1401  /*
1402  * When a temporary breakpoint is hit we have to make sure that we are
1403  * in the same context in which it was set, otherwise it could happen
1404  * that another process/thread hits it before and it gets deleted.
1405  */
1406  else if (BreakPoint->Type == KdbBreakPointTemporary &&
1407  BreakPoint->Process == KdbCurrentProcess)
1408  {
1409  ASSERT((TrapFrame->EFlags & EFLAGS_TF) == 0);
1410 
1411  /* Delete the temporary breakpoint which was used to step over or into the instruction. */
1412  KdbpDeleteBreakPoint(-1, BreakPoint);
1413 
1414  if (--KdbNumSingleSteps > 0)
1415  {
1416  if ((KdbSingleStepOver && !KdbpStepOverInstruction(TrapFrame->Eip)) ||
1417  (!KdbSingleStepOver && !KdbpStepIntoInstruction(TrapFrame->Eip)))
1418  {
1419  Context->EFlags |= EFLAGS_TF;
1420  }
1421 
1422  goto continue_execution; /* return */
1423  }
1424 
1426  }
1427 
1428  /*
1429  * If we hit a breakpoint set by the debugger we set the single step flag,
1430  * ignore the next single step and reenable the breakpoint.
1431  */
1432  else if (BreakPoint->Type == KdbBreakPointSoftware ||
1433  BreakPoint->Type == KdbBreakPointTemporary)
1434  {
1435  ASSERT(ExceptionCode == STATUS_BREAKPOINT);
1436  Context->EFlags |= EFLAGS_TF;
1437  KdbBreakPointToReenable = BreakPoint;
1438  }
1439 
1440  /* Make sure that the breakpoint should be triggered in this context */
1441  if (!BreakPoint->Global && BreakPoint->Process != KdbCurrentProcess)
1442  {
1443  goto continue_execution; /* return */
1444  }
1445 
1446  /* Check if the condition for the breakpoint is met. */
1447  if (BreakPoint->Condition)
1448  {
1449  /* Setup the KDB trap frame */
1450  KdbpTrapFrameToKdbTrapFrame(TrapFrame, &KdbTrapFrame);
1451 
1452  ull = 0;
1453  if (!KdbpRpnEvaluateParsedExpression(BreakPoint->Condition, &KdbTrapFrame, &ull, NULL, NULL))
1454  {
1455  /* FIXME: Print warning? */
1456  }
1457  else if (ull == 0) /* condition is not met */
1458  {
1459  goto continue_execution; /* return */
1460  }
1461  }
1462 
1463  if (BreakPoint->Type == KdbBreakPointSoftware)
1464  {
1465  KdbpPrint("\nEntered debugger on breakpoint #%d: EXEC 0x%04x:0x%08x\n",
1466  KdbLastBreakPointNr, TrapFrame->SegCs & 0xffff, TrapFrame->Eip);
1467  }
1468  else if (BreakPoint->Type == KdbBreakPointHardware)
1469  {
1470  KdbpPrint("\nEntered debugger on breakpoint #%d: %s 0x%08x\n",
1471  KdbLastBreakPointNr,
1472  (BreakPoint->Data.Hw.AccessType == KdbAccessRead) ? "READ" :
1473  ((BreakPoint->Data.Hw.AccessType == KdbAccessWrite) ? "WRITE" :
1474  ((BreakPoint->Data.Hw.AccessType == KdbAccessReadWrite) ? "RDWR" : "EXEC")),
1475  BreakPoint->Address);
1476  }
1477  }
1478  else if (ExceptionCode == STATUS_SINGLE_STEP)
1479  {
1480  /* Silently ignore a debugger initiated single step. */
1481  if ((TrapFrame->Dr6 & 0xf) == 0 && KdbBreakPointToReenable)
1482  {
1483  /* FIXME: Make sure that the breakpoint was really hit (check bp->Address vs. tf->Eip) */
1484  BreakPoint = KdbBreakPointToReenable;
1485  KdbBreakPointToReenable = NULL;
1486  ASSERT(BreakPoint->Type == KdbBreakPointSoftware ||
1487  BreakPoint->Type == KdbBreakPointTemporary);
1488 
1489  /*
1490  * Reenable the breakpoint we disabled to execute the breakpointed
1491  * instruction.
1492  */
1493  if (!NT_SUCCESS(KdbpOverwriteInstruction(KdbCurrentProcess, BreakPoint->Address, 0xCC,
1494  &BreakPoint->Data.SavedInstruction)))
1495  {
1496  KdbpPrint("Warning: Couldn't reenable breakpoint %d\n",
1497  BreakPoint - KdbBreakPoints);
1498  }
1499 
1500  /* Unset TF if we are no longer single stepping. */
1501  if (KdbNumSingleSteps == 0)
1502  Context->EFlags &= ~EFLAGS_TF;
1503 
1505  {
1506  goto continue_execution; /* return */
1507  }
1508  }
1509 
1510  /* Quoth the raven, 'Nevermore!' */
1512 
1513  /* Check if we expect a single step */
1514  if ((TrapFrame->Dr6 & 0xf) == 0 && KdbNumSingleSteps > 0)
1515  {
1516  /*ASSERT((Context->Eflags & EFLAGS_TF) != 0);*/
1517  if (--KdbNumSingleSteps > 0)
1518  {
1519  if ((KdbSingleStepOver && KdbpStepOverInstruction(TrapFrame->Eip)) ||
1520  (!KdbSingleStepOver && KdbpStepIntoInstruction(TrapFrame->Eip)))
1521  {
1522  Context->EFlags &= ~EFLAGS_TF;
1523  }
1524  else
1525  {
1526  Context->EFlags |= EFLAGS_TF;
1527  }
1528 
1529  goto continue_execution; /* return */
1530  }
1531  else
1532  {
1533  Context->EFlags &= ~EFLAGS_TF;
1535  }
1536  }
1537  else
1538  {
1539  if (!EnterConditionMet)
1540  {
1541  return kdHandleException;
1542  }
1543 
1544  KdbpPrint("\nEntered debugger on unexpected debug trap!\n");
1545  }
1546  }
1547  else if (ExceptionCode == STATUS_BREAKPOINT)
1548  {
1549  if (KdbInitFileBuffer)
1550  {
1552  EnterConditionMet = FALSE;
1553  }
1554  if (!EnterConditionMet)
1555  {
1556  return kdHandleException;
1557  }
1558 
1559  KdbpPrint("\nEntered debugger on embedded INT3 at 0x%04x:0x%08x.\n",
1560  TrapFrame->SegCs & 0xffff, TrapFrame->Eip - 1);
1561  }
1562  else
1563  {
1564  const CHAR *ExceptionString = (ExpNr < RTL_NUMBER_OF(ExceptionNrToString)) ?
1565  (ExceptionNrToString[ExpNr]) :
1566  ("Unknown/User defined exception");
1567 
1568  if (!EnterConditionMet)
1569  {
1570  return ContinueType;
1571  }
1572 
1573  KdbpPrint("\nEntered debugger on %s-chance exception (Exception Code: 0x%x) (%s)\n",
1574  FirstChance ? "first" : "last", ExceptionCode, ExceptionString);
1575 
1576  if (ExceptionCode == STATUS_ACCESS_VIOLATION &&
1577  ExceptionRecord && ExceptionRecord->NumberParameters != 0)
1578  {
1579  /* FIXME: Add noexec memory stuff */
1580  ULONG_PTR TrapCr2;
1581  ULONG Err;
1582 
1583  TrapCr2 = __readcr2();
1584 
1585  Err = TrapFrame->ErrCode;
1586  KdbpPrint("Memory at 0x%p could not be %s: ", TrapCr2, (Err & (1 << 1)) ? "written" : "read");
1587 
1588  if ((Err & (1 << 0)) == 0)
1589  {
1590  KdbpPrint("Page not present.\n");
1591  }
1592  else
1593  {
1594  if ((Err & (1 << 3)) != 0)
1595  KdbpPrint("Reserved bits in page directory set.\n");
1596  else
1597  KdbpPrint("Page protection violation.\n");
1598  }
1599  }
1600  }
1601 
1602  /* Once we enter the debugger we do not expect any more single steps to happen */
1603  KdbNumSingleSteps = 0;
1604 
1605  /* Update the current process pointer */
1606  KdbCurrentProcess = KdbOriginalProcess = PsGetCurrentProcess();
1607  KdbCurrentThread = KdbOriginalThread = PsGetCurrentThread();
1608  KdbCurrentTrapFrame = &KdbTrapFrame;
1609 
1610  /* Setup the KDB trap frame */
1611  KdbpTrapFrameToKdbTrapFrame(TrapFrame, &KdbTrapFrame);
1612 
1613  /* Enter critical section */
1614  OldEflags = __readeflags();
1615  _disable();
1616 
1617  /* HACK: Save the current IRQL and pretend we are at passive level,
1618  * although interrupts are off. Needed because KDBG calls pageable code. */
1619  OldIrql = KeGetCurrentIrql();
1621 
1622  /* Exception inside the debugger? Game over. */
1624  {
1625  __writeeflags(OldEflags);
1626  return kdHandleException;
1627  }
1628 
1629  /* Call the main loop. */
1631 
1632  /* Check if we should single step */
1633  if (KdbNumSingleSteps > 0)
1634  {
1635  /* Variable explains itself! */
1637 
1638  if ((KdbSingleStepOver && KdbpStepOverInstruction(KdbCurrentTrapFrame->Tf.Eip)) ||
1639  (!KdbSingleStepOver && KdbpStepIntoInstruction(KdbCurrentTrapFrame->Tf.Eip)))
1640  {
1641  ASSERT((KdbCurrentTrapFrame->Tf.EFlags & EFLAGS_TF) == 0);
1642  /*KdbCurrentTrapFrame->Tf.EFlags &= ~EFLAGS_TF;*/
1643  }
1644  else
1645  {
1646  Context->EFlags |= EFLAGS_TF;
1647  }
1648  }
1649 
1650  /* We can't update the current thread's trapframe 'cause it might not have one */
1651 
1652  /* Detach from attached process */
1653  if (KdbCurrentProcess != KdbOriginalProcess)
1654  {
1656  }
1657 
1658  /* Update the exception TrapFrame */
1659  KdbpKdbTrapFrameToTrapFrame(&KdbTrapFrame, TrapFrame);
1660 
1661  /* Decrement the entry count */
1663 
1664  /* HACK: Raise back to old IRQL */
1665  KeRaiseIrql(OldIrql, &OldIrql);
1666 
1667  /* Leave critical section */
1668  __writeeflags(OldEflags);
1669 
1670  /* Check if user requested a bugcheck */
1672  {
1673  /* Clear the flag and bugcheck the system */
1675  KeBugCheck(MANUALLY_INITIATED_CRASH);
1676  }
1677 
1678 continue_execution:
1679  /* Clear debug status */
1680  if (ExceptionCode == STATUS_BREAKPOINT) /* FIXME: Why clear DR6 on INT3? */
1681  {
1682  /* Set the RF flag so we don't trigger the same breakpoint again. */
1683  if (Resume)
1684  {
1685  TrapFrame->EFlags |= EFLAGS_RF;
1686  }
1687 
1688  /* Clear dr6 status flags. */
1689  TrapFrame->Dr6 &= ~0x0000e00f;
1690 
1692  {
1693  /* Skip the current instruction */
1694  Context->Eip++;
1695  }
1696  }
1697 
1698  return ContinueType;
1699 }
1700 
1701 VOID
1702 NTAPI
1705  PCHAR p1)
1706 {
1707 #define CONST_STR_LEN(x) (sizeof(x)/sizeof(x[0]) - 1)
1708 
1709  while (p1 && (p1 = strchr(p1, ' ')))
1710  {
1711  /* Skip other spaces */
1712  while (*p1 == ' ') ++p1;
1713 
1714  if (!_strnicmp(p1, "KDSERIAL", CONST_STR_LEN("KDSERIAL")))
1715  {
1716  p1 += CONST_STR_LEN("KDSERIAL");
1718  KdpDebugMode.Serial = TRUE;
1719  }
1720  else if (!_strnicmp(p1, "KDNOECHO", CONST_STR_LEN("KDNOECHO")))
1721  {
1722  p1 += CONST_STR_LEN("KDNOECHO");
1724  }
1725  else if (!_strnicmp(p1, "FIRSTCHANCE", CONST_STR_LEN("FIRSTCHANCE")))
1726  {
1727  p1 += CONST_STR_LEN("FIRSTCHANCE");
1729  }
1730  }
1731 }
1732 
1733 NTSTATUS
1735  OUT PVOID Dest,
1736  IN PVOID Src,
1737  IN ULONG Bytes)
1738 {
1739  BOOLEAN Result = TRUE;
1740 
1741  switch (Bytes)
1742  {
1743  case 1:
1744  case 2:
1745  case 4:
1746  case 8:
1747  Result = KdpSafeReadMemory((ULONG_PTR)Src, Bytes, Dest);
1748  break;
1749 
1750  default:
1751  {
1752  ULONG_PTR Start, End, Write;
1753 
1754  for (Start = (ULONG_PTR)Src,
1755  End = Start + Bytes,
1756  Write = (ULONG_PTR)Dest;
1757  Result && (Start < End);
1758  Start++, Write++)
1759  if (!KdpSafeReadMemory(Start, 1, (PVOID)Write))
1760  Result = FALSE;
1761 
1762  break;
1763  }
1764  }
1765 
1766  return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
1767 }
1768 
1769 NTSTATUS
1771  OUT PVOID Dest,
1772  IN PVOID Src,
1773  IN ULONG Bytes)
1774 {
1775  BOOLEAN Result = TRUE;
1776  ULONG_PTR Start, End, Write;
1777 
1778  for (Start = (ULONG_PTR)Src,
1779  End = Start + Bytes,
1780  Write = (ULONG_PTR)Dest;
1781  Result && (Start < End);
1782  Start++, Write++)
1783  if (!KdpSafeWriteMemory(Write, 1, *((PCHAR)Start)))
1784  Result = FALSE;
1785 
1786  return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
1787 }
ULONG NTAPI KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
Definition: kdb.c:18
DWORD *typedef PVOID
Definition: winlogon.h:52
#define TAG_KDBG
Definition: kdb.h:7
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
BOOLEAN KdbpDeleteBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Deletes a breakpoint.
Definition: kdb.c:654
signed char * PCHAR
Definition: retypes.h:7
ULONG Cr3
Definition: kdb.h:18
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1782
#define KDB_MAXIMUM_SW_BREAKPOINT_COUNT
Definition: kdb.c:23
#define IN
Definition: typedefs.h:38
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:1051
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2697
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
KAPC_STATE
Definition: ketypes.h:1273
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:1131
PVOID ULONG Address
Definition: oprghdlr.h:14
#define STATUS_ILLEGAL_INSTRUCTION
Definition: ntstatus.h:252
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
KDP_DEBUG_MODE KdpDebugMode
Definition: kdinit.c:25
static PKDB_BREAKPOINT KdbBreakPointToReenable
Definition: kdb.c:39
Type
Definition: Type.h:6
__INTRIN_INLINE unsigned long __readcr2(void)
Definition: intrin_x86.h:1704
struct _Entry Entry
Definition: kefuncs.h:640
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
ULONG KdbDebugState
Definition: kdb.c:45
BOOLEAN Global
Definition: kdb.h:43
static VOID KdbpInternalEnter(VOID)
Internal function to enter KDB.
Definition: kdb.c:1213
static ULONG KdbBreakPointCount
Definition: kdb.c:33
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
_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:214
BOOLEAN KdbpStepIntoInstruction(ULONG_PTR Eip)
Steps into an instruction (interrupts)
Definition: kdb.c:355
#define KDB_MAXIMUM_BREAKPOINT_COUNT
Definition: kdb.c:21
ULONG NTAPI MmGetPageProtect(struct _EPROCESS *Process, PVOID Address)
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
static ULONG KdbSwBreakPointCount
Definition: kdb.c:35
BOOLEAN KdbpAttachToThread(PVOID ThreadId)
Switches to another thread context.
Definition: kdb.c:1092
PETHREAD KdbOriginalThread
Definition: kdb.c:50
return STATUS_SUCCESS
Definition: btrfs.c:2690
PEPROCESS KdbCurrentProcess
Definition: kdb.c:47
VOID NTAPI INIT_FUNCTION KdbpGetCommandLineSettings(PCHAR p1)
Definition: kdb.c:1704
ULONG Cr4
Definition: kdb.h:19
unsigned char * PUCHAR
Definition: retypes.h:3
NTSTATUS NTAPI PsLookupThreadByThreadId(IN HANDLE ThreadId, OUT PETHREAD *Thread)
Definition: thread.c:643
char CHAR
Definition: xmlstorage.h:175
union _KDB_BREAKPOINT::@1678 Data
PCHAR ConditionExpression
Definition: kdb.h:45
#define STATUS_SINGLE_STEP
Definition: ntstatus.h:173
KTHREAD Tcb
Definition: pstypes.h:1034
_In_ UINT Bytes
Definition: mmcopy.h:9
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
#define KGDT_R0_CODE
Definition: ketypes.h:74
BOOLEAN KdbpStepOverInstruction(ULONG_PTR Eip)
Steps over an instruction.
Definition: kdb.c:327
BOOLEAN NTAPI KdpSafeWriteMemory(ULONG_PTR Addr, LONG Len, ULONGLONG Value)
Definition: kdmemsup.c:193
VOID NTAPI InbvSolidColorFill(IN ULONG Left, IN ULONG Top, IN ULONG Right, IN ULONG Bottom, IN ULONG Color)
Definition: inbv.c:578
ULONG HardwareSegSs
Definition: ketypes.h:269
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
static VOID KdbpKdbTrapFrameFromKernelStack(PVOID KernelStack, PKDB_KTRAP_FRAME KdbTrapFrame)
Definition: kdb.c:174
__INTRIN_INLINE unsigned long __readcr3(void)
Definition: intrin_x86.h:1711
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
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:533
VOID KdbpCliInterpretInitFile(VOID)
This function is called by KdbEnterDebuggerException...
Definition: kdb_cli.c:3534
ULONG Esi
Definition: ketypes.h:261
static BOOL Write(PBYTE Address, PBYTE Data, SIZE_T Size)
Definition: vmhorizon.c:15
BOOLEAN NTAPI KeIsExecutingDpc(VOID)
Definition: dpc.c:946
UNICODE_STRING Global
Definition: symlink.c:37
int32_t INT
Definition: typedefs.h:56
PVOID Base
Definition: ketypes.h:486
static CHAR KdbStack[KDB_STACK_SIZE]
Definition: kdb.c:31
static KDB_KTRAP_FRAME KdbThreadTrapFrame
Definition: kdb.c:53
ULONG Edi
Definition: ketypes.h:260
USHORT Limit
Definition: ketypes.h:485
PEPROCESS KdbOriginalProcess
Definition: kdb.c:48
uint32_t ULONG_PTR
Definition: typedefs.h:63
static ULONG KdbpGetExceptionNumberFromStatus(IN NTSTATUS ExceptionCode)
Definition: kdb.c:1259
BOOLEAN KdbpDisableBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Disables a breakpoint.
Definition: kdb.c:924
LONG KdbpGetInstLength(IN ULONG_PTR Address)
Definition: i386-dis.c:97
VOID NTAPI KdbpStackSwitchAndCall(IN PVOID NewStack, IN VOID(*Function)(VOID))
UCHAR KIRQL
Definition: env_spec_w32.h:591
static LONG KdbpIsBreakPointOurs(IN NTSTATUS ExceptionCode, IN PKTRAP_FRAME TrapFrame)
Checks if the breakpoint was set by the debugger.
Definition: kdb.c:704
static PKDB_BREAKPOINT KdbHwBreakPoints[KDB_MAXIMUM_HW_BREAKPOINT_COUNT]
Definition: kdb.c:38
BOOLEAN NTAPI KdpSafeReadMemory(ULONG_PTR Addr, LONG Len, PVOID Value)
Definition: kdmemsup.c:157
GLenum GLclampf GLint i
Definition: glfuncs.h:14
static LONG KdbEntryCount
Definition: kdb.c:30
UINT64 Dr2
Definition: ketypes.h:344
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1560
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
USHORT SegGs
Definition: ketypes.h:367
#define FALSE
Definition: types.h:117
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:701
#define STATUS_INTEGER_OVERFLOW
Definition: ntstatus.h:371
static KDB_ENTER_CONDITION KdbEnterConditions[][2]
Definition: kdb.c:58
long LONG
Definition: pedump.c:60
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:1925
static VOID KdbpKdbTrapFrameToTrapFrame(PKDB_KTRAP_FRAME KdbTrapFrame, PKTRAP_FRAME TrapFrame)
Definition: kdb.c:158
static const CHAR * ExceptionNrToString[]
Definition: kdb.c:86
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:210
_Check_return_ _CRTIMP int __cdecl _strnicmp(_In_reads_or_z_(_MaxCount) const char *_Str1, _In_reads_or_z_(_MaxCount) const char *_Str2, _In_ size_t _MaxCount)
static BOOLEAN KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep
Definition: kdb.c:41
USHORT SegEs
Definition: ketypes.h:365
#define STATUS_INTEGER_DIVIDE_BY_ZERO
Definition: ntstatus.h:370
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define PAGE_NOACCESS
Definition: nt_native.h:1302
smooth NULL
Definition: ftsmooth.c:416
#define STATUS_BREAKPOINT
Definition: ntstatus.h:172
struct _KDB_BREAKPOINT::@1678::@1679 Hw
USHORT SegCs
Definition: ketypes.h:380
VOID KbdEnableMouse(VOID)
#define PAGE_EXECUTE
Definition: nt_native.h:1306
ULONG_PTR Address
Definition: kdb.h:42
VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1469
PVOID Condition
Definition: kdb.h:46
PVOID KernelStack
Definition: ketypes.h:1565
#define CONST_STR_LEN(x)
IN ULONG IN UCHAR Condition
LIST_ENTRY ThreadListHead
Definition: pstypes.h:1260
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
VOID NTAPI InbvSetTextColor(IN ULONG Color)
Definition: inbv.c:554
static VOID KdbpTrapFrameToKdbTrapFrame(PKTRAP_FRAME TrapFrame, PKDB_KTRAP_FRAME KdbTrapFrame)
Definition: kdb.c:136
VOID KdbpCliMainLoop(IN BOOLEAN EnteredOnSingleStep)
KDB Main Loop.
Definition: kdb_cli.c:3456
UINTN Size
Definition: acefiex.h:555
PKDB_KTRAP_FRAME KdbCurrentTrapFrame
Definition: kdb.c:51
BOOLEAN KdbpEnableBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Enables a breakpoint.
Definition: kdb.c:757
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define KDB_STACK_SIZE
Definition: kdb.c:20
#define STATUS_ASSERTION_FAILURE
Definition: ntstatus.h:946
unsigned char BOOLEAN
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
ULONG CurrentProcess
Definition: shell.c:125
LONG NTSTATUS
Definition: precomp.h:26
#define KGDT_R0_DATA
Definition: ketypes.h:75
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
uint64_t ULONGLONG
Definition: typedefs.h:65
CLIENT_ID Cid
Definition: pstypes.h:1059
NTSTATUS KdbpSafeWriteMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1770
LONG KdbpGetNextBreakPointNr(IN ULONG Start OPTIONAL)
Gets the number of the next breakpoint >= Start.
Definition: kdb.c:437
ULONG NTAPI KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
Definition: kdb.c:80
static PKDB_BREAKPOINT KdbSwBreakPoints[KDB_MAXIMUM_SW_BREAKPOINT_COUNT]
Definition: kdb.c:37
ULONG HardwareEsp
Definition: ketypes.h:268
volatile VOID * StackLimit
Definition: ketypes.h:1555
VOID KbdDisableMouse(VOID)
UINT64 Dr6
Definition: ketypes.h:346
#define for
Definition: utility.h:88
static VOID KdbpCallMainLoop(VOID)
Calls the main loop ...
Definition: kdb.c:1203
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define LONG
Definition: msvc.h:36
UINT64 Dr3
Definition: ketypes.h:345
HANDLE UniqueThread
Definition: compat.h:475
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
enum _KDB_ACCESS_TYPE KDB_ACCESS_TYPE
VOID NTAPI InbvAcquireDisplayOwnership(VOID)
Definition: inbv.c:390
VOID NTAPI KeDetachProcess(VOID)
Definition: procobj.c:618
NTSTATUS NTAPI PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process)
Definition: process.c:919
unsigned char UCHAR
Definition: xmlstorage.h:181
ULONG KdbNumSingleSteps
Definition: kdb.c:43
UINT64 Dr1
Definition: ketypes.h:343
VOID KdbpPrint(IN PCHAR Format, IN...OPTIONAL)
Prints the given string with printf-like formatting.
Definition: kdb_cli.c:2468
#define InterlockedDecrement
Definition: armddk.h:52
enum _KDB_ENTER_CONDITION KDB_ENTER_CONDITION
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1555
#define EFLAGS_RF
Definition: cpu.c:19
USHORT SegDs
Definition: ketypes.h:364
__INTRIN_INLINE unsigned long __readcr0(void)
Definition: intrin_x86.h:1697
BOOLEAN KdbSingleStepOver
Definition: kdb.c:44
Definition: typedefs.h:117
#define EFLAGS_TF
Definition: ketypes.h:125
KPROCESS Pcb
Definition: pstypes.h:1193
#define STATUS_FLOAT_MULTIPLE_TRAPS
Definition: ntstatus.h:794
BOOLEAN KdbpBugCheckRequested
Definition: kdb_cli.c:122
enum _KDB_BREAKPOINT_TYPE KDB_BREAKPOINT_TYPE
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
__INTRIN_INLINE unsigned long __readcr4(void)
Definition: intrin_x86.h:1718
BOOLEAN KdbpAttachToProcess(PVOID ProcessId)
Switches to another process/thread context.
Definition: kdb.c:1173
ULONG Eip
Definition: ketypes.h:265
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:1185
UINT64 Dr0
Definition: ketypes.h:342
#define KDB_MAXIMUM_HW_BREAKPOINT_COUNT
Definition: kdb.c:22
VOID NTAPI KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame, IN ULONG_PTR Esp)
Definition: kdb.c:25
Status
Definition: gdiplustypes.h:24
#define MAXULONG
Definition: typedefs.h:250
BOOLEAN NTAPI InbvEnableDisplayString(IN BOOLEAN Enable)
Definition: inbv.c:468
PEPROCESS Process
Definition: kdb.h:44
PVOID StackBase
Definition: ketypes.h:1556
BOOLEAN NTAPI InbvIsBootDriverInstalled(VOID)
Definition: inbv.c:492
ULONG Cr0
Definition: kdb.h:15
UCHAR SavedInstruction
Definition: kdb.h:49
NTSTATUS KdbpSafeReadMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1734
BOOLEAN NTAPI InbvResetDisplay(VOID)
Definition: inbv.c:526
ULONG Ebx
Definition: ketypes.h:262
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:464
#define InterlockedIncrement
Definition: armddk.h:53
#define STATUS_MEMORY_NOT_ALLOCATED
Definition: ntstatus.h:382
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
unsigned short USHORT
Definition: pedump.c:61
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
KTRAP_FRAME Tf
Definition: kdb.h:14
LONG KdbLastBreakPointNr
Definition: kdb.c:42
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:753
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1452
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
static KAPC_STATE KdbApcState
Definition: kdb.c:54
#define PAGE_READONLY
Definition: compat.h:127
#define STATUS_STACK_OVERFLOW
Definition: ntstatus.h:475
static KDB_KTRAP_FRAME KdbTrapFrame
Definition: kdb.c:52
VOID NTAPI InbvInstallDisplayStringFilter(IN INBV_DISPLAY_STRING_FILTER Filter)
Definition: inbv.c:484
char * strchr(const char *String, int ch)
Definition: utclib.c:501
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
PETHREAD KdbCurrentThread
Definition: kdb.c:49
#define OUT
Definition: typedefs.h:39
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:289
#define STATUS_DATATYPE_MISALIGNMENT
Definition: ntstatus.h:171
void __cdecl _disable(void)
Definition: intrin_arm.h:365
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
BOOLEAN Enabled
Definition: kdb.h:41
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1307
KD_CONTINUE_TYPE KdbEnterDebuggerException(IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT Context, IN OUT PKTRAP_FRAME TrapFrame, IN BOOLEAN FirstChance)
KDB Exception filter.
Definition: kdb.c:1325
UINT64 Dr7
Definition: ketypes.h:347
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:1029
static KDB_BREAKPOINT KdbBreakPoints[KDB_MAXIMUM_BREAKPOINT_COUNT]
Definition: kdb.c:34
#define STATUS_FLOAT_INVALID_OPERATION
Definition: ntstatus.h:366
VOID NTAPI InbvSetScrollRegion(IN ULONG Left, IN ULONG Top, IN ULONG Right, IN ULONG Bottom)
Definition: inbv.c:543
BOOLEAN NTAPI InbvCheckDisplayOwnership(VOID)
Definition: inbv.c:415
const GLfloat * p1
Definition: s_aatritemp.h:43
ULONG Cr2
Definition: kdb.h:17
VOID NTAPI KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame, IN ULONG Ss)
Definition: kdb.c:96
KDB_BREAKPOINT_TYPE Type
Definition: kdb.h:40
static BOOLEAN KdbEnteredOnSingleStep
Definition: kdb.c:46
signed int * PLONG
Definition: retypes.h:5
PVOID InitialStack
Definition: ketypes.h:1554
#define STATUS_ARRAY_BOUNDS_EXCEEDED
Definition: ntstatus.h:362
ULONG EFlags
Definition: ketypes.h:384
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
Definition: partlist.h:39
ULONG Ebp
Definition: ketypes.h:263
#define INIT_FUNCTION
Definition: ntoskrnl.h:11
PCHAR KdbInitFileBuffer
Definition: kdb_cli.c:121
#define PAGE_READWRITE
Definition: nt_native.h:1304
static ULONG KdbHwBreakPointCount
Definition: kdb.c:36