Little KDB update ;-) If you have any problems and/or questions let me know. I hope it was tested enough and works well enough for everybody.
Modified: trunk/reactos/Makefile
Modified: trunk/reactos/drivers/input/keyboard/keyboard.c
Added: trunk/reactos/media/drivers/etc/KDB.init
Modified: trunk/reactos/ntoskrnl/Makefile
Modified: trunk/reactos/ntoskrnl/dbg/i386/i386-dis.c
Modified: trunk/reactos/ntoskrnl/dbg/i386/kdb_help.S
Added: trunk/reactos/ntoskrnl/dbg/i386/longjmp.S
Added: trunk/reactos/ntoskrnl/dbg/i386/setjmp.S
Modified: trunk/reactos/ntoskrnl/dbg/kdb.c
Modified: trunk/reactos/ntoskrnl/dbg/kdb.h
Added: trunk/reactos/ntoskrnl/dbg/kdb_cli.c
Added: trunk/reactos/ntoskrnl/dbg/kdb_expr.c
Modified: trunk/reactos/ntoskrnl/dbg/kdb_keyboard.c
Modified: trunk/reactos/ntoskrnl/dbg/kdb_serial.c
Added: trunk/reactos/ntoskrnl/dbg/kdb_string.c
Modified: trunk/reactos/ntoskrnl/dbg/kdb_symbols.c
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
Modified: trunk/reactos/ntoskrnl/include/internal/kd.h
Modified: trunk/reactos/ntoskrnl/ke/catch.c
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
Modified: trunk/reactos/ntoskrnl/ke/i386/tskswitch.S
Modified: trunk/reactos/ntoskrnl/ke/kthread.c
Modified: trunk/reactos/ntoskrnl/ke/main.c
Modified: trunk/reactos/ntoskrnl/ps/w32call.c

Modified: trunk/reactos/Makefile
--- trunk/reactos/Makefile	2005-03-05 23:22:44 UTC (rev 13840)
+++ trunk/reactos/Makefile	2005-03-05 23:35:08 UTC (rev 13841)
@@ -216,6 +216,8 @@
 	$(CP) media/nls/l_intl.nls $(BOOTCD_DIR)/reactos/l_intl.nls
 	$(HALFVERBOSEECHO) [COPY]    media/drivers/etc/services to $(BOOTCD_DIR)/reactos/services
 	$(CP) media/drivers/etc/services $(BOOTCD_DIR)/reactos/services
+	$(HALFVERBOSEECHO) [COPY]    media/drivers/etc/KDB.init to $(BOOTCD_DIR)/reactos/KDB.init
+	$(CP) media/drivers/etc/KDB.init $(BOOTCD_DIR)/reactos/KDB.init
 
 bootcd_basic: bootcd_directory_layout bootcd_bootstrap_files bootcd_install_before
 
@@ -1043,6 +1045,8 @@
 	$(CP) media/nls/l_intl.nls $(INSTALL_DIR)/system32/casemap.nls
 	$(HALFVERBOSEECHO) [INSTALL] media/drivers/etc/services to $(INSTALL_DIR)/system32/drivers/etc/services
 	$(CP) media/drivers/etc/services $(INSTALL_DIR)/system32/drivers/etc/services
+	$(HALFVERBOSEECHO) [INSTALL] media/drivers/etc/KDB.init to $(INSTALL_DIR)/system32/drivers/etc/KDB.init
+	$(CP) media/drivers/etc/KDB.init $(INSTALL_DIR)/system32/drivers/etc/KDB.init
 
 .PHONY: install_clean install_dirs install_before
 

Modified: trunk/reactos/drivers/input/keyboard/keyboard.c
--- trunk/reactos/drivers/input/keyboard/keyboard.c	2005-03-05 23:22:44 UTC (rev 13840)
+++ trunk/reactos/drivers/input/keyboard/keyboard.c	2005-03-05 23:35:08 UTC (rev 13841)
@@ -38,6 +38,7 @@
 static DWORD ctrlKeyState;
 static PKINTERRUPT KbdInterrupt;
 static KDPC KbdDpc;
+static PIO_WORKITEM KbdWorkItem = NULL;
 static BOOLEAN AlreadyOpened = FALSE;
 
 /*
@@ -408,6 +409,24 @@
 
 
 /*
+ * Debug request handler
+ */
+
+static VOID STDCALL
+KbdWorkItemRoutine(IN PDEVICE_OBJECT DeviceObject,
+                   IN PVOID Context)
+{
+   LONG Debug;
+
+   Debug = InterlockedExchange(&DoSystemDebug, -1);
+   if (Debug != -1)
+     {
+       KdSystemDebugControl(Debug);
+     }
+}
+
+
+/*
  * Keyboard IRQ handler
  */
 
@@ -419,14 +438,21 @@
 {
    PIRP Irp = (PIRP)SystemArgument2;
    PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)SystemArgument1;
-   
+
    if (SystemArgument1 == NULL && DoSystemDebug != -1)
      {
-       KdSystemDebugControl(DoSystemDebug);
-       DoSystemDebug = -1;
+       if (KbdWorkItem != NULL)
+         {
+           IoQueueWorkItem(KbdWorkItem, (PIO_WORKITEM_ROUTINE)KbdWorkItemRoutine, DelayedWorkQueue, NULL);
+         }
+       else
+         {
+           KdSystemDebugControl(DoSystemDebug);
+           DoSystemDebug = -1;
+         }
        return;
      }
-
+     
    CHECKPOINT;
    DPRINT("KbdDpcRoutine(DeviceObject %x, Irp %x)\n",
 	    DeviceObject,Irp);
@@ -436,6 +462,7 @@
    IoStartNextPacket(DeviceObject,FALSE);
 }
 
+
 static BOOLEAN STDCALL
 KeyboardHandler(PKINTERRUPT Interrupt,
 		PVOID Context)
@@ -538,7 +565,7 @@
    else if (InSysRq == TRUE && ScanToVirtual(thisKey) >= VK_A &&
 	    ScanToVirtual(thisKey) <= VK_Z && isDown)
      {
-       DoSystemDebug = ScanToVirtual(thisKey) - VK_A;
+       InterlockedExchange(&DoSystemDebug, ScanToVirtual(thisKey) - VK_A);
        KeInsertQueueDpc(&KbdDpc, NULL, NULL);
        return(TRUE);
      }
@@ -659,6 +686,11 @@
    KbdClearInput();
    KeyboardConnectInterrupt(DeviceObject);
    KeInitializeDpc(&KbdDpc,KbdDpcRoutine,NULL);
+   KbdWorkItem = IoAllocateWorkItem(DeviceObject);
+   if (KbdWorkItem == NULL)
+     {
+        DPRINT("Warning: Couldn't allocate work item!\n");
+     }
    return 0;
 }
 

Added: trunk/reactos/media/drivers/etc/KDB.init
--- trunk/reactos/media/drivers/etc/KDB.init	2005-03-05 23:22:44 UTC (rev 13840)
+++ trunk/reactos/media/drivers/etc/KDB.init	2005-03-05 23:35:08 UTC (rev 13841)
@@ -0,0 +1,15 @@
+# Example KDB.init file
+#
+# The disassembly flavor is set to "intel" (default is "at&t") and the
+#
+
+# Set the disassembly flavor to "intel" (default is "at&t")
+set syntax intel
+
+# Change the condition to enter KDB on INT3 to "always" (default is "kmode")
+set condition INT3 first always
+
+# This is a special command available only in the KDB.init file - it breaks into
+# KDB when it is interpreting the init file at startup.
+#break
+

Modified: trunk/reactos/ntoskrnl/Makefile
--- trunk/reactos/ntoskrnl/Makefile	2005-03-05 23:22:44 UTC (rev 13840)
+++ trunk/reactos/ntoskrnl/Makefile	2005-03-05 23:35:08 UTC (rev 13841)
@@ -25,14 +25,10 @@
 STRIP_FLAGS := -Wl,-s
 
 ifeq ($(KDBG), 1)
-OBJECTS_KDBG := dbg/kdb.o dbg/kdb_serial.o dbg/kdb_keyboard.o dbg/rdebug.o \
-                dbg/i386/kdb_help.o \
-		../dk/w32/lib/libkjs.a dbg/i386/i386-dis.o
-CFLAGS_KDBG := -I../lib/kjs/include
+OBJECTS_KDBG := dbg/kdb.o dbg/kdb_cli.o dbg/kdb_expr.o dbg/kdb_keyboard.o \
+                dbg/kdb_serial.o dbg/kdb_string.o dbg/rdebug.o dbg/i386/kdb_help.o \
+                dbg/i386/i386-dis.o dbg/i386/longjmp.o dbg/i386/setjmp.o
 preall: all
-
-../dk/w32/lib/libkjs.a:
-	$(MAKE) -C ../lib/kjs
 else
 OBJECTS_KDBG :=
 endif

Modified: trunk/reactos/ntoskrnl/dbg/i386/i386-dis.c
--- trunk/reactos/ntoskrnl/dbg/i386/i386-dis.c	2005-03-05 23:22:44 UTC (rev 13840)
+++ trunk/reactos/ntoskrnl/dbg/i386/i386-dis.c	2005-03-05 23:35:08 UTC (rev 13841)
@@ -1,4 +1,4 @@
-/* $Id:$
+/* $Id$
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -52,10 +52,10 @@
 
 
 int
-print_insn_i386_att (bfd_vma pc, struct disassemble_info *info);
+print_insn_i386 (bfd_vma pc, struct disassemble_info *info);
 
 int
-KdbPrintDisasm(void* Ignored, const char* fmt, ...)
+KdbpPrintDisasm(void* Ignored, const char* fmt, ...)
 {
   va_list ap;
   static char buffer[256];
@@ -69,46 +69,46 @@
 }
 
 int
-KdbNopPrintDisasm(void* Ignored, const char* fmt, ...)
+KdbpNopPrintDisasm(void* Ignored, const char* fmt, ...)
 {
   return(0);
 }
 
 int static
-KdbReadMemory(unsigned int Addr, unsigned char* Data, unsigned int Length, 
-	      struct disassemble_info * Ignored)
+KdbpReadMemory(unsigned int Addr, unsigned char* Data, unsigned int Length,
+	       struct disassemble_info * Ignored)
 {
   return KdbpSafeReadMemory(Data, (void *)Addr, Length); /* 0 means no error */
 }
 
 void static
-KdbMemoryError(int Status, unsigned int Addr, 
-	       struct disassemble_info * Ignored)
+KdbpMemoryError(int Status, unsigned int Addr,
+	        struct disassemble_info * Ignored)
 {
 }
 
 void static
-KdbPrintAddressInCode(unsigned int Addr, struct disassemble_info * Ignored)
+KdbpPrintAddressInCode(unsigned int Addr, struct disassemble_info * Ignored)
 {
   if (!KdbSymPrintAddress((void*)Addr))
     {
-      DbgPrint("<0x%X>", Addr);
+      DbgPrint("<%08x>", Addr);
     }
 }
 
 void static
-KdbNopPrintAddress(unsigned int Addr, struct disassemble_info * Ignored)
+KdbpNopPrintAddress(unsigned int Addr, struct disassemble_info * Ignored)
 {
 }
 
 #include "dis-asm.h"
 
 long
-KdbGetInstLength(unsigned int Address)
+KdbpGetInstLength(unsigned int Address)
 {
   disassemble_info info;
 
-  info.fprintf_func = KdbNopPrintDisasm;
+  info.fprintf_func = KdbpNopPrintDisasm;
   info.stream = NULL;
   info.application_data = NULL;
   info.flavour = bfd_target_unknown_flavour;
@@ -116,9 +116,9 @@
   info.mach = bfd_mach_i386_i386;
   info.insn_sets = 0;
   info.flags = 0;
-  info.read_memory_func = KdbReadMemory;
-  info.memory_error_func = KdbMemoryError;
-  info.print_address_func = KdbNopPrintAddress;
+  info.read_memory_func = KdbpReadMemory;
+  info.memory_error_func = KdbpMemoryError;
+  info.print_address_func = KdbpNopPrintAddress;
   info.symbol_at_address_func = NULL;
   info.buffer = NULL;
   info.buffer_vma = info.buffer_length = 0;
@@ -126,25 +126,25 @@
   info.display_endian = BIG_ENDIAN_LITTLE;
   info.disassembler_options = NULL;
 
-  return(print_insn_i386_att(Address, &info));
+  return(print_insn_i386(Address, &info));
 }
 
 long
-KdbDisassemble(unsigned int Address)
+KdbpDisassemble(unsigned int Address, unsigned long IntelSyntax)
 {
   disassemble_info info;
 
-  info.fprintf_func = KdbPrintDisasm;
+  info.fprintf_func = KdbpPrintDisasm;
   info.stream = NULL;
   info.application_data = NULL;
   info.flavour = bfd_target_unknown_flavour;
   info.arch = bfd_arch_i386;
-  info.mach = bfd_mach_i386_i386;
+  info.mach = IntelSyntax ? bfd_mach_i386_i386_intel_syntax : bfd_mach_i386_i386;
   info.insn_sets = 0;
   info.flags = 0;
-  info.read_memory_func = KdbReadMemory;
-  info.memory_error_func = KdbMemoryError;
-  info.print_address_func = KdbPrintAddressInCode;
+  info.read_memory_func = KdbpReadMemory;
+  info.memory_error_func = KdbpMemoryError;
+  info.print_address_func = KdbpPrintAddressInCode;
   info.symbol_at_address_func = NULL;
   info.buffer = NULL;
   info.buffer_vma = info.buffer_length = 0;
@@ -152,7 +152,7 @@
   info.display_endian = BIG_ENDIAN_LITTLE;
   info.disassembler_options = NULL;
 
-  return(print_insn_i386_att(Address, &info));
+  return(print_insn_i386(Address, &info));
 }
 
 /* Print i386 instructions for GDB, the GNU debugger.
@@ -2113,7 +2113,7 @@
 #else
   mode_64bit = 0;
   priv.orig_sizeflag = AFLAG | DFLAG;
-  intel_syntax = 0;
+  /*intel_syntax = 0;*/
 #endif
 
   if (intel_syntax)

Modified: trunk/reactos/ntoskrnl/dbg/i386/kdb_help.S
--- trunk/reactos/ntoskrnl/dbg/i386/kdb_help.S	2005-03-05 23:22:44 UTC (rev 13840)
+++ trunk/reactos/ntoskrnl/dbg/i386/kdb_help.S	2005-03-05 23:35:08 UTC (rev 13841)
@@ -1,29 +1,19 @@
 #include <internal/ke.h>
 #include <internal/i386/segment.h>
 
-	.data
-_KdbEipTemp:
-	.int	0
+.text
 
-	.text
-.globl _KdbEnter	
+.globl _KdbEnter
 _KdbEnter:
 	/*
-	 * Record when we are inside the debugger.
-	 */
-	incl	_KdbEntryCount
-
-	/*
-	 * Save the callers eip.
-	 */
-	popl	_KdbEipTemp
-		
-	/*
 	 * Set up a trap frame
 	 */
+                                /* Ss - space already reserved by return EIP */
+        pushl   %esp            /* Esp */
 	pushfl			/* Eflags */
 	pushl	%cs		/* Cs */
-	pushl	_KdbEipTemp	/* Eip */
+	pushl	12(%esp)	/* Eip */
+	movl    %ss, 16(%esp)   /* Save Ss */
 	pushl	$0		/* ErrorCode */
 	pushl	%ebp		/* Ebp */
 	pushl	%ebx		/* Ebx */
@@ -56,34 +46,35 @@
 	pushl	$0		/* TempEip */
 	pushl	$0		/* TempCs */
 	pushl	$0		/* DebugPointer */
-	pushl	$0		/* DebugArgMark */
-	pushl	_KdbEipTemp	/* DebugEip */
+	pushl	$3       	/* DebugArgMark (Exception number) */
+	pushl	0x60(%esp)	/* DebugEip */
 	pushl	%ebp		/* DebugEbp */
 
 	/*
-	 * Push a pointer to the trap frame
-	 */
-	pushl	%esp
-
-	/*
 	 * Call KDB
 	 */
-	call	_KdbInternalEnter
+	movl	%esp, %eax
+	pushl	$1		/* FirstChance */
+	pushl	%eax		/* Push a pointer to the trap frame */
+	pushl	$0		/* Context */
+	pushl	$0		/* PreviousMode (KernelMode) */
+	pushl	$0		/* ExceptionRecord */
+	call	_KdbEnterDebuggerException
 
 	/*
-	 * Pop the argument
+	 * Pop the arguments and unused portions of the trap frame:
+	 *   DebugEbp
+	 *   DebugEip
+	 *   DebugArgMark
+	 *   DebugPointer
+	 *   TempCs
+	 *   TempEip
 	 */
-	popl	%eax	
+	addl	$(11*4), %esp
 
 	/*
-	 * Ignore unused portions of the trap frame.
+	 * Restore/update debugging registers.
 	 */
-	popl	%eax		/* DebugEbp */
-	popl	%eax		/* DebugEip */
-	popl	%eax		/* DebugArgMark */
-	popl	%eax		/* DebugPointer */
-	popl	%eax		/* TempCs */
-	popl	%eax		/* TempEip */
 	popl	%eax		/* Dr0 */
 	movl	%eax, %dr0
 	popl	%eax		/* Dr1 */
@@ -113,19 +104,44 @@
 	popl	%edi		/* Edi */
 	popl	%esi		/* Esi */
 	popl	%ebx		/* Ebx */
+
+        /* Remove SS:ESP from the stack */
+        movl    16(%esp), %ebp
+        movl    %ebp, 24(%esp)
+        movl    12(%esp), %ebp
+        movl    %ebp, 20(%esp)
+        movl    8(%esp), %ebp
+        movl    %ebp, 16(%esp)
+        
 	popl	%ebp		/* Ebp */
-	addl	$4, %esp	/* ErrorCode */
+	addl	$12, %esp	/* ErrorCode and SS:ESP */
 
 	/*
-	 * Record when we are in the debugger.
-	 */
-	decl	_KdbEntryCount
-
-	/*
 	 * Return to the caller.
 	 */
 	iret
 
 
+.globl _KdbpStackSwitchAndCall@8
+_KdbpStackSwitchAndCall@8:
+        pushl   %ebp
+        movl    %esp, %ebp
+        
+        movl    0x8(%esp), %eax         /* New stack */
+        movl    0xC(%esp), %ecx         /* Function to call */
+        movl    %esp, %edx              /* Old stack */
 
-	
+        /* Switch stack */
+        movl    %eax, %esp
+        pushl   %edx
+
+        /* Call function */
+        call    *%ecx
+
+        /* Switch back to old stack */
+        popl    %esp
+
+        /* Return */
+        popl    %ebp
+        ret     $8
+

Added: trunk/reactos/ntoskrnl/dbg/i386/longjmp.S
--- trunk/reactos/ntoskrnl/dbg/i386/longjmp.S	2005-03-05 23:22:44 UTC (rev 13840)
+++ trunk/reactos/ntoskrnl/dbg/i386/longjmp.S	2005-03-05 23:35:08 UTC (rev 13841)
@@ -0,0 +1,70 @@
+        .file   "longjmp.S"
+/*
+ * Copyright (C) 1998, 1999, Jonathan S. Shapiro.
+ *
+ * This file is part of the EROS Operating System.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+        /*
+         * typedef struct {
+         *  unsigned long ebx, esi, edi;
+         *  unsigned long ebp;
+         *  unsigned long sp;
+         *  unsigned long pc;
+         * } jmp_buf[1];
+         */
+        
+        /*
+         * On entry, the stack to longjmp looks like:
+         *
+         *     value
+         *     ptr to jmp_buf
+         *     return PC
+         */
+
+.globl _longjmp
+_longjmp:
+        pushl   %ebp
+        movl    %esp,%ebp
+
+        movl    8(%ebp),%ecx            /* address of jmp_buf to ecx */
+        movl    12(%ebp),%eax           /* return value to %eax */
+        testl   %eax,%eax
+        jne     1f
+        incl    %eax                    /* return 1 if handed 0 */
+
+1:      
+        movl    (%ecx),%ebx             /* restore %ebx */
+        movl    4(%ecx),%esi            /* restore %esi */
+        movl    8(%ecx),%edi            /* restore %edi */
+        
+        /*
+         * From this instant on we are not running in a valid frame
+         */
+        
+        movl    12(%ecx),%ebp           /* restore %ebp */
+        movl    16(%ecx),%esp           /* restore %esp */
+        /* movl 20(%ecx),%eax           return PC */
+
+        /*
+         * Since we are abandoning the stack in any case, 
+         * there isn't much point in doing the usual return 
+         * discipline.
+         */
+        
+        jmpl    *20(%ecx)
+	

Added: trunk/reactos/ntoskrnl/dbg/i386/setjmp.S
--- trunk/reactos/ntoskrnl/dbg/i386/setjmp.S	2005-03-05 23:22:44 UTC (rev 13840)
+++ trunk/reactos/ntoskrnl/dbg/i386/setjmp.S	2005-03-05 23:35:08 UTC (rev 13841)
@@ -0,0 +1,59 @@
+        .file   "setjmp.S"
+/*
+ * Copyright (C) 1998, 1999, Jonathan S. Shapiro.
+ *
+ * This file is part of the EROS Operating System.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* #include <eros/i486/asm.h> */
+        
+        
+        /*
+         * typedef struct {
+         *  unsigned long ebx, esi, edi;
+         *  unsigned long ebp;
+         *  unsigned long sp;
+         *  unsigned long pc;
+         * } jmp_buf[1];
+         */
+        
+        /*
+         * On entry, the stack to setjmp looks like:
+         *
+         *     ptr to jmp_buf
+         *     return PC
+         */
+.globl _setjmp
+_setjmp:	
+        pushl   %ebp
+        movl    %esp,%ebp
+        
+        movl    0x8(%ebp),%eax          /* address of jmp_buf to eax */
+        movl    %ebx,(%eax)             /* save %ebx */
+        movl    %esi,4(%eax)            /* save %esi */
+        movl    %edi,8(%eax)            /* save %edi */
+        leal    8(%ebp),%edx            /* calling proc's esp, not ours! */
+        movl    %edx,16(%eax)
+        movl    4(%ebp), %edx           /* save return PC */
+        movl    %edx,20(%eax)
+        movl    0(%ebp),%edx            /* calling proc's ebp, not ours! */
+        movl    %edx,12(%eax)
+
+        xorl    %eax,%eax               /* return 0 the first time */
+        leave
+        ret	$4
+

Modified: trunk/reactos/ntoskrnl/dbg/kdb.c
--- trunk/reactos/ntoskrnl/dbg/kdb.c	2005-03-05 23:22:44 UTC (rev 13840)
+++ trunk/reactos/ntoskrnl/dbg/kdb.c	2005-03-05 23:35:08 UTC (rev 13841)
@@ -12,1786 +12,1495 @@
 
 #include <ntoskrnl.h>
 #include "kdb.h"
-#include "kjs.h"
 #define NDEBUG
 #include <internal/debug.h>
 
 /* TYPES *********************************************************************/
 
-/* GLOBALS *******************************************************************/
+/* DEFINES *******************************************************************/
 
-#define BS 8
-#define DEL 127
+#define KDB_STACK_SIZE                   (4096*3)
+#define KDB_MAXIMUM_BREAKPOINT_COUNT     256
+#define KDB_MAXIMUM_HW_BREAKPOINT_COUNT  4
+#define KDB_MAXIMUM_SW_BREAKPOINT_COUNT  256
 
-BOOL KbdEchoOn = TRUE;
+#define __STRING(x) #x
+#define _STRING(x) __STRING(x)
 
-typedef struct
-{
-  BOOLEAN Enabled;
-  BOOLEAN Temporary;
-  BOOLEAN Assigned;
-  ULONG Address;
-  UCHAR SavedInst;
-} KDB_ACTIVE_BREAKPOINT;
+/* GLOBALS *******************************************************************/
 
-#define KDB_MAXIMUM_BREAKPOINT_COUNT (255)
+STATIC LONG KdbEntryCount = 0;
+STATIC CHAR KdbStack[KDB_STACK_SIZE];
 
-static ULONG KdbBreakPointCount = 0;
-static KDB_ACTIVE_BREAKPOINT 
- KdbActiveBreakPoints[KDB_MAXIMUM_BREAKPOINT_COUNT];
+STATIC ULONG KdbBreakPointCount = 0;  /* Number of used breakpoints in the array */
+STATIC KDB_BREAKPOINT KdbBreakPoints[KDB_MAXIMUM_BREAKPOINT_COUNT] = {{0}};  /* Breakpoint array */
+STATIC ULONG KdbSwBreakPointCount = 0;  /* Number of enabled software breakpoints */
+STATIC ULONG KdbHwBreakPointCount = 0;  /* Number of enabled hardware breakpoints */
+STATIC PKDB_BREAKPOINT KdbSwBreakPoints[KDB_MAXIMUM_SW_BREAKPOINT_COUNT]; /* Enabled software breakpoints, orderless */
+STATIC PKDB_BREAKPOINT KdbHwBreakPoints[KDB_MAXIMUM_HW_BREAKPOINT_COUNT]; /* Enabled hardware breakpoints, orderless */
+STATIC PKDB_BREAKPOINT KdbBreakPointToReenable = NULL; /* Set to a breakpoint struct when single stepping after
+                                                          a software breakpoint was hit, to reenable it */
+LONG KdbLastBreakPointNr = -1;  /* Index of the breakpoint which cause KDB to be entered */
+ULONG KdbNumSingleSteps = 0; /* How many single steps to do */
+BOOLEAN KdbSingleStepOver = FALSE; /* Whether to step over calls/reps. */
 
-static BOOLEAN KdbHandleUmode = FALSE;
-static BOOLEAN KdbHandleHandled = FALSE;
-static BOOLEAN KdbBreakOnModuleLoad = FALSE;
+STATIC BOOLEAN KdbEnteredOnSingleStep = FALSE; /* Set to true when KDB was entered because of single step */
+PEPROCESS KdbCurrentProcess = NULL;  /* The current process context in which KDB runs */
+PEPROCESS KdbOriginalProcess = NULL; /* The process in whichs context KDB was intered */
+PETHREAD KdbCurrentThread = NULL;  /* The current thread context in which KDB runs */
+PETHREAD KdbOriginalThread = NULL; /* The thread in whichs context KDB was entered */
+PKDB_KTRAP_FRAME KdbCurrentTrapFrame = NULL; /* Pointer to the current trapframe */
+STATIC KDB_KTRAP_FRAME KdbTrapFrame = { { 0 } };  /* The trapframe which was passed to KdbEnterDebuggerException */
+STATIC KDB_KTRAP_FRAME KdbThreadTrapFrame = { { 0 } }; /* The trapframe of the current thread (KdbCurrentThread) */
+STATIC KAPC_STATE KdbApcState;
 
-static BOOLEAN KdbIgnoreNextSingleStep = FALSE;
-static ULONG KdbLastSingleStepFrom = 0xFFFFFFFF;
-static BOOLEAN KdbEnteredOnSingleStep = FALSE;
-
-ULONG KdbEntryCount = 0;
-
-int isalpha( int );
-VOID
-PsDumpThreads(BOOLEAN System);
-ULONG 
-DbgContCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG 
-DbgStopCondition(ULONG Aargc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgModuleLoadedAction(ULONG Aargc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgEchoToggle(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG 
-DbgRegsCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG 
-DbgDRegsCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG 
-DbgCRegsCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG 
-DbgBugCheckCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgBackTraceCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgAddrCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgXCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgScriptCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgThreadListCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgProcessListCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgProcessHelpCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgShowFilesCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgEnableFileCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgDisableFileCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgDisassemble(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgSetBreakPoint(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgDeleteBreakPoint(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgSetMemoryBreakPoint(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgStep(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgStepOver(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-ULONG
-DbgFinish(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-
-struct
+/* Array of conditions when to enter KDB */
+STATIC KDB_ENTER_CONDITION KdbEnterConditions[][2] =
 {
-  PCH Name;
-  PCH Syntax;
-  PCH Help;
-  ULONG (*Fn)(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf);
-} DebuggerCommands[] = {
-  {"cont", "cont", "Exit the debugger", DbgContCommand},
-  {"echo", "echo", "Toggle serial echo", DbgEchoToggle},
-  {"condition", "condition [all|umode|kmode]", "Kdbg enter condition", DbgStopCondition},
-  {"module-loaded", "module-loaded [break|continue]", "Module-loaded action", DbgModuleLoadedAction},
+   /* First chance       Last chance */
+   { KdbDoNotEnter,      KdbEnterFromKmode },   /* Zero devide */
+   { KdbEnterAlways,     KdbDoNotEnter },       /* Debug trap */
+   { KdbDoNotEnter,      KdbEnterAlways },      /* NMI */
+   { KdbEnterFromKmode,  KdbDoNotEnter },       /* INT3 */
+   { KdbDoNotEnter,      KdbEnterFromKmode },   /* Overflow */
+   { KdbDoNotEnter,      KdbEnterFromKmode },
+   { KdbDoNotEnter,      KdbEnterFromKmode },   /* Invalid opcode */
+   { KdbDoNotEnter,      KdbEnterFromKmode },   /* No math coprocessor fault */
+   { KdbEnterAlways,     KdbEnterAlways },
+   { KdbEnterAlways,     KdbEnterAlways },
+   { KdbDoNotEnter,      KdbEnterFromKmode },
+   { KdbDoNotEnter,      KdbEnterFromKmode },
+   { KdbDoNotEnter,      KdbEnterFromKmode },   /* Stack fault */
+   { KdbDoNotEnter,      KdbEnterFromKmode },   /* General protection fault */
+   { KdbDoNotEnter,      KdbEnterFromKmode },   /* Page fault */
+   { KdbEnterAlways,     KdbEnterAlways },      /* Reserved (15) */
+   { KdbDoNotEnter,      KdbEnterFromKmode },   /* FPU fault */
+   { KdbDoNotEnter,      KdbEnterFromKmode },
+   { KdbDoNotEnter,      KdbEnterFromKmode },
+   { KdbDoNotEnter,      KdbEnterFromKmode },   /* SIMD fault */
+   { KdbDoNotEnter,      KdbEnterFromKmode }    /* Last entry: used for unknown exceptions */
+};
 
-  {"regs", "regs", "Display general purpose registers", DbgRegsCommand},
-  {"dregs", "dregs", "Display debug registers", DbgDRegsCommand},
-  {"cregs", "cregs", "Display control registers", DbgCRegsCommand},
-  {"bugcheck", "bugcheck", "Bugcheck the system", DbgBugCheckCommand},
-  {"bt", "bt [*frame-address]|[thread-id]","Do a backtrace", DbgBackTraceCommand},
-  {"addr", "addr <address>", "Displays symbol info", DbgAddrCommand},
-  {"x", "x <addr> <words>", "Displays <addr> for <words>", DbgXCommand},
-  {"plist", "plist", "Display processes in the system", DbgProcessListCommand},
-  {"tlist", "tlist [sys]", "Display threads in the system", DbgThreadListCommand},
-  {"sfiles", "sfiles", "Show files that print debug prints", DbgShowFilesCommand},
-  {"efile", "efile <filename>", "Enable debug prints from file", DbgEnableFileCommand},
-  {"dfile", "dfile <filename>", "Disable debug prints from file", DbgDisableFileCommand},
-  {"js", "js", "Script mode", DbgScriptCommand},
-  {"disasm", "disasm <address>", "Disables 10 instructions at <address> or "
-   "eip", DbgDisassemble},
-  {"bp", "bp <address>", "Sets an int3 breakpoint at a given address",
-   DbgSetBreakPoint},
-  {"bc", "bc <breakpoint number>", "Deletes a breakpoint",
-   DbgDeleteBreakPoint},
-  {"ba", "ba <debug register> <access type> <length> <address>", 
-   "Sets a breakpoint using a debug register", DbgSetMemoryBreakPoint},
-  {"t", "t", "Steps forward a single instructions", DbgStep},
-  {"p", "p", "Steps forward a single instructions skipping calls", 
-   DbgStepOver},
-  {"finish", "finish", "Runs until the current function exits", DbgFinish},
-  {"help", "help", "Display help screen", DbgProcessHelpCommand},
-  {NULL, NULL, NULL}
+/* Exception descriptions */
+STATIC CONST PCHAR ExceptionNrToString[] =
+{
+   "Divide Error",
+   "Debug Trap",
+   "NMI",
+   "Breakpoint",
+   "Overflow",
+   "BOUND range exceeded",
+   "Invalid Opcode",
+   "No Math Coprocessor",
+   "Double Fault",
+   "Unknown(9)",
+   "Invalid TSS",
+   "Segment Not Present",
+   "Stack Segment Fault",
+   "General Protection",
+   "Page Fault",
+   "Reserved(15)",
+   "Math Fault",
+   "Alignment Check",
+   "Machine Check",
+   "SIMD Fault"
 };
 
-static const char *ExceptionTypeStrings[] =
-  {
-    "Divide Error",
-    "Debug Trap",
-    "NMI",
-    "Breakpoint",
-    "Overflow",
-    "BOUND range exceeded",
-    "Invalid Opcode",
-    "No Math Coprocessor",
-    "Double Fault",
-    "Unknown(9)",
-    "Invalid TSS",
-    "Segment Not Present",
-    "Stack Segment Fault",
-    "General Protection",
-    "Page Fault",
-    "Reserved(15)",
-    "Math Fault",
-    "Alignment Check",
-    "Machine Check",
-    "SIMD Fault"
-  };
-
-volatile DWORD x_dr0 = 0, x_dr1 = 0, x_dr2 = 0, x_dr3 = 0, x_dr7 = 0;
-
-extern LONG KdbDisassemble(ULONG Address);
-extern LONG KdbGetInstLength(ULONG Address);
-
 /* FUNCTIONS *****************************************************************/
 
-/*
- * Convert a string to an unsigned long integer.
+/*!\brief Overwrites the instruction at \a Address with \a NewInst and stores
+ *        the old instruction in *OldInst.
  *
- * Ignores `locale' stuff.  Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
+ * \param Process  Process in which's context to overwrite the instruction.
+ * \param Address  Address at which to overwrite the instruction.
+ * \param NewInst  New instruction (written to \a Address)
+ * \param OldInst  Old instruction (read from \a Address)
+ *
+ * \returns NTSTATUS
  */
-unsigned long
-strtoul(const char *nptr, char **endptr, int base)
+STATIC NTSTATUS
+KdbpOverwriteInstruction(
+   IN  PEPROCESS Process,
+   IN  ULONG_PTR Address,
+   IN  UCHAR NewInst,
+   OUT PUCHAR OldInst  OPTIONAL)
 {
-  const char *s = nptr;
-  unsigned long acc;
-  int c;
-  unsigned long cutoff;
-  int neg = 0, any, cutlim;
+   NTSTATUS Status;
+   ULONG Protect;
+   PEPROCESS CurrentProcess = PsGetCurrentProcess();
+   KAPC_STATE ApcState;
 
-  /*
-   * See strtol for comments as to the logic used.
-   */
-  do {
-    c = *s++;
-  } while (isspace(c));
-  if (c == '-')
-  {
-    neg = 1;
-    c = *s++;
-  }
-  else if (c == '+')
-    c = *s++;
-  if ((base == 0 || base == 16) &&
-      c == '0' && (*s == 'x' || *s == 'X'))
-  {
-    c = s[1];
-    s += 2;
-    base = 16;
-  }
-  if (base == 0)
-    base = c == '0' ? 8 : 10;
-  cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
-  cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
-  for (acc = 0, any = 0;; c = *s++)
-  {
-    if (isdigit(c))
-      c -= '0';
-    else if (isalpha(c))
-      c -= isupper(c) ? 'A' - 10 : 'a' - 10;
-    else
-      break;
-    if (c >= base)
-      break;
-    if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
-      any = -1;
-    else {
-      any = 1;
-      acc *= base;
-      acc += c;
-    }
-  }
-  if (any < 0)
-  {
-    acc = ULONG_MAX;
-  }
-  else if (neg)
-    acc = -acc;
-  if (endptr != 0)
-    *endptr = any ? (char *)s - 1 : (char *)nptr;
-  return acc;
-}
+   /* Get the protection for the address. */
+   Protect = MmGetPageProtect(Process, (PVOID)PAGE_ROUND_DOWN(Address));
+   
+   /* Return if that page isn't present. */
+   if (Protect & PAGE_NOACCESS)
+   {
+      return STATUS_MEMORY_NOT_ALLOCATED;
+   }
+   
+   /* Attach to the process */
+   if (CurrentProcess != Process)
+   {
+      KeStackAttachProcess(EPROCESS_TO_KPROCESS(Process), &ApcState);
+   }
 
+   /* Make the page writeable if it is read only. */
+   if (Protect & (PAGE_READONLY|PAGE_EXECUTE|PAGE_EXECUTE_READ))
+   {
+      MmSetPageProtect(Process, (PVOID)PAGE_ROUND_DOWN(Address),
+	               (Protect & ~(PAGE_READONLY|PAGE_EXECUTE|PAGE_EXECUTE_READ)) | PAGE_READWRITE);
+   }
+   
+   /* Copy the old instruction back to the caller. */
+   if (OldInst != NULL)
+   {
+      Status = KdbpSafeReadMemory(OldInst, (PUCHAR)Address, 1);
+      if (!NT_SUCCESS(Status))
+      {
+         if (Protect & (PAGE_READONLY|PAGE_EXECUTE|PAGE_EXECUTE_READ))
+         {
+            MmSetPageProtect(Process, (PVOID)PAGE_ROUND_DOWN(Address), Protect);
+         }
+         /* Detach from process */
+         if (CurrentProcess != Process)
+         {
+            KeDetachProcess();
+         }
+	 return Status;
+      }
+   }
+   
+   /* Copy the new instruction in its place. */
+   Status = KdbpSafeWriteMemory((PUCHAR)Address, &NewInst, 1);
+   
+   /* Restore the page protection. */
+   if (Protect & (PAGE_READONLY|PAGE_EXECUTE|PAGE_EXECUTE_READ))
+   {
+      MmSetPageProtect(Process, (PVOID)PAGE_ROUND_DOWN(Address), Protect);
+   }
+   
+   /* Detach from process */
+   if (CurrentProcess != Process)
+   {
+      KeUnstackDetachProcess(&ApcState);
+   }
 
-char*
-strpbrk(const char* s, const char* accept)
-{
-  int i;
-  for (; (*s) != 0; s++)
-    {
-      for (i = 0; accept[i] != 0; i++)
-	{
-	  if (accept[i] == (*s))
-	    {
-	      return((char *)s);
-	    }
-	}
-    }
-  return(NULL);
+   return Status;
 }
 
-
-#if 0
-NTSTATUS
-KdbpSafeReadMemory(PVOID dst, PVOID src, INT size)
+/*!\brief Checks whether the given instruction can be single stepped or has to be
+ *        stepped over using a temporary breakpoint.
+ *
[truncated at 1000 lines; 7037 more skipped]