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
--- 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
--- 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;
}
--- 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
+
--- 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
--- 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)
--- 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
+
--- 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)
+
--- 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
+
--- 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]