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