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]