Merge with blight's rewrite Modified: branches/alex_devel_branch/reactos/Makefile Modified: branches/alex_devel_branch/reactos/drivers/input/keyboard/keyboard.c Added: branches/alex_devel_branch/reactos/media/drivers/etc/KDB.init Modified: branches/alex_devel_branch/reactos/ntoskrnl/Makefile Modified: branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/i386-dis.c Modified: branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/kdb_help.S Added: branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/longjmp.S Added: branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/setjmp.S Modified: branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb.c Modified: branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb.h Added: branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb_cli.c Added: branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb_expr.c Modified: branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb_keyboard.c Modified: branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb_serial.c Added: branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb_string.c Modified: branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb_symbols.c Modified: branches/alex_devel_branch/reactos/ntoskrnl/include/internal/i386/ke.h Modified: branches/alex_devel_branch/reactos/ntoskrnl/include/internal/kd.h Modified: branches/alex_devel_branch/reactos/ntoskrnl/io/iomgr.c Modified: branches/alex_devel_branch/reactos/ntoskrnl/ke/catch.c Modified: branches/alex_devel_branch/reactos/ntoskrnl/ke/i386/trap.s Modified: branches/alex_devel_branch/reactos/ntoskrnl/ke/i386/tskswitch.S Modified: branches/alex_devel_branch/reactos/ntoskrnl/ke/kthread.c Modified: branches/alex_devel_branch/reactos/ntoskrnl/ke/main.c Modified: branches/alex_devel_branch/reactos/ntoskrnl/ps/w32call.c _____
Modified: branches/alex_devel_branch/reactos/Makefile --- branches/alex_devel_branch/reactos/Makefile 2005-03-05 23:35:08 UTC (rev 13841) +++ branches/alex_devel_branch/reactos/Makefile 2005-03-05 23:58:25 UTC (rev 13842) @@ -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: branches/alex_devel_branch/reactos/drivers/input/keyboard/keyboard.c --- branches/alex_devel_branch/reactos/drivers/input/keyboard/keyboard.c 2005-03-05 23:35:08 UTC (rev 13841) +++ branches/alex_devel_branch/reactos/drivers/input/keyboard/keyboard.c 2005-03-05 23:58:25 UTC (rev 13842) @@ -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; }
_____
Copied: branches/alex_devel_branch/reactos/media/drivers/etc/KDB.init (from rev 13841, trunk/reactos/media/drivers/etc/KDB.init) _____
Modified: branches/alex_devel_branch/reactos/ntoskrnl/Makefile --- branches/alex_devel_branch/reactos/ntoskrnl/Makefile 2005-03-05 23:35:08 UTC (rev 13841) +++ branches/alex_devel_branch/reactos/ntoskrnl/Makefile 2005-03-05 23:58:25 UTC (rev 13842) @@ -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: branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/i386-dis.c --- branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/i386-dis.c 2005-03-05 23:35:08 UTC (rev 13841) +++ branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/i386-dis.c 2005-03-05 23:58:25 UTC (rev 13842) @@ -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: branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/kdb_help.S --- branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/kdb_help.S 2005-03-05 23:35:08 UTC (rev 13841) +++ branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/kdb_help.S 2005-03-05 23:58:25 UTC (rev 13842) @@ -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 + _____
Copied: branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/longjmp.S (from rev 13841, trunk/reactos/ntoskrnl/dbg/i386/longjmp.S) _____
Copied: branches/alex_devel_branch/reactos/ntoskrnl/dbg/i386/setjmp.S (from rev 13841, trunk/reactos/ntoskrnl/dbg/i386/setjmp.S) _____
Modified: branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb.c --- branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb.c 2005-03-05 23:35:08 UTC (rev 13841) +++ branches/alex_devel_branch/reactos/ntoskrnl/dbg/kdb.c 2005-03-05 23:58:25 UTC (rev 13842) @@ -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. + * + * \retval TRUE Instruction is a call. + * \retval FALSE Instruction is not a call. + */ +BOOLEAN +KdbpShouldStepOverInstruction(ULONG_PTR Eip) { - INT page, page_end; - - /* check source */ - page_end = (((ULONG_PTR)src + size) / PAGE_SIZE); - for (page = ((ULONG_PTR)src / PAGE_SIZE); page <= page_end; page++) - { - if (!MmIsPagePresent(NULL, (PVOID)(page * PAGE_SIZE))) - return STATUS_UNSUCCESSFUL; - } + UCHAR Mem[3]; + INT i = 0;
- /* copy memory */ - RtlCopyMemory(dst, src, size); - return STATUS_SUCCESS; + if (!NT_SUCCESS(KdbpSafeReadMemory(Mem, (PVOID)Eip, sizeof (Mem)))) + { + KdbpPrint("Couldn't access memory at 0x%x\n", (UINT)Eip); + return FALSE; + } + + /* Check if the current instruction is a call. */ + while ((i < sizeof (Mem)) && (Mem[i] == 0x66 || Mem[i] == 0x67)) + i++; + if (i == sizeof (Mem)) + return FALSE; + if (Mem[i] == 0xE8 || Mem[i] == 0x9A || Mem[i] == 0xF2 || Mem[i] == 0xF3 || + (((i + 1) < sizeof (Mem)) && Mem[i] == 0xFF && (Mem[i+1] & 0x38) == 0x10)) + { + return TRUE; + } + return FALSE; }
- -NTSTATUS -KdbpSafeWriteMemory(PVOID dst, PVOID src, INT size) +/*!\brief Steps over an instruction + * + * If the given instruction should be stepped over, this function inserts a + * temporary breakpoint after the instruction and returns TRUE, otherwise it + * returns FALSE. + * + * \retval TRUE Temporary breakpoint set after instruction. + * \retval FALSE No breakpoint was set. + */ +BOOLEAN +KdbpStepOverInstruction(ULONG_PTR Eip) { - return KdbpSafeWriteMemory(dst, src, size); - INT page, page_end; + LONG InstLen;
- /* check destination */ - page_end = (((ULONG_PTR)dst + size) / PAGE_SIZE); - for (page = ((ULONG_PTR)dst / PAGE_SIZE); page <= page_end; page++) - { - if (!MmIsPagePresent(NULL, (PVOID)(page * PAGE_SIZE))) - return STATUS_UNSUCCESSFUL; - } + if (!KdbpShouldStepOverInstruction(Eip)) + return FALSE;
- /* copy memory */ - RtlCopyMemory(dst, src, size); - return STATUS_SUCCESS; -} -#endif /* unused */ + InstLen = KdbpGetInstLength(Eip); + if (InstLen < 1) + return FALSE;
+ if (!NT_SUCCESS(KdbpInsertBreakPoint(Eip + InstLen, KdbBreakPointTemporary, 0, 0, NULL, FALSE, NULL))) + return FALSE;
-VOID -KdbGetCommand(PCH Buffer) -{ - CHAR Key; - PCH Orig = Buffer; - static CHAR LastCommand[256] = ""; - ULONG ScanCode = 0; - static CHAR LastKey = '\0'; - - KbdEchoOn = !((KdDebugState & KD_DEBUG_KDNOECHO) != 0); - - for (;;) - { - if (KdDebugState & KD_DEBUG_KDSERIAL) - while ((Key = KdbTryGetCharSerial()) == -1); - else - while ((Key = KdbTryGetCharKeyboard(&ScanCode)) == -1); - - if (Key == '\n' && LastKey == '\r') - { - /* Ignore this key... */ - } - else if (Key == '\r' || Key == '\n') - { - DbgPrint("\n"); - /* - Repeat the last command if the user presses enter. Reduces the - risk of RSI when single-stepping. - */ - if (Buffer == Orig) - { - strcpy(Buffer, LastCommand); - } - else - { - *Buffer = 0; - strcpy(LastCommand, Orig); - } - LastKey = Key; - return; - } - else if (Key == BS || Key == DEL) - { - if (Buffer > Orig) - { - Buffer--; - *Buffer = 0; - if (KbdEchoOn) - DbgPrint("%c %c", BS, BS); - else - DbgPrint(" %c", BS); - } - } - else if (ScanCode == 72) - { - ULONG i; - while (Buffer > Orig) - { - Buffer--; - *Buffer = 0; - if (KbdEchoOn) - DbgPrint("%c %c", BS, BS); - else - DbgPrint(" %c", BS); - } - for (i = 0; LastCommand[i] != 0; i++) - { - if (KbdEchoOn) - DbgPrint("%c", LastCommand[i]); - *Buffer = LastCommand[i]; - Buffer++; - } - } - else - { [truncated at 1000 lines; 3359 more skipped]