-/*\r
- * PROJECT: ReactOS Kernel\r
- * LICENSE: GPL - See COPYING in the top level directory\r
- * FILE: ntoskrnl/kd64/kdbreak.c\r
- * PURPOSE: KD64 Breakpoint Support\r
- * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#include <ntoskrnl.h>\r
-#define NDEBUG\r
-#include <debug.h>\r
-\r
-/* FUNCTIONS *****************************************************************/\r
-\r
-ULONG\r
-NTAPI\r
-KdpAddBreakpoint(IN PVOID Address)\r
-{\r
- UCHAR Content;\r
- ULONG i;\r
-\r
- /* Loop current breakpoints */\r
- for (i = 0; i < 20; i++)\r
- {\r
- /* Check if the breakpoint is valid */\r
- if ((KdpBreakpointTable[i].Flags & KdpBreakpointActive) &&\r
- (KdpBreakpointTable[i].Address == Address))\r
- {\r
- /* Check if it's pending */\r
- if ((KdpBreakpointTable[i].Flags & KdpBreakpointPending))\r
- {\r
- /* It's not pending anymore now */\r
- KdpBreakpointTable[i].Flags &= ~KdpBreakpointPending;\r
- return i + 1;\r
- }\r
- else\r
- {\r
- /* Fail */\r
- return 0;\r
- }\r
- }\r
- }\r
-\r
- /* Find a free entry */\r
- for (i = 0; i < 20; i++) if (!(KdpBreakpointTable[i].Flags)) break;\r
-\r
- /* Fail if no free entry was found */\r
- if (i == 20) return 0;\r
-\r
- /* Save the old instruction */\r
- RtlCopyMemory(&Content, Address, sizeof(UCHAR));\r
-\r
- /* Write the entry */\r
- KdpBreakpointTable[i].Address = Address;\r
- KdpBreakpointTable[i].Content = Content;\r
- KdpBreakpointTable[i].Flags = KdpBreakpointActive;\r
-\r
- /* Write the INT3 and return the handle */\r
- RtlCopyMemory(Address, &KdpBreakpointInstruction, sizeof(UCHAR));\r
- return i + 1;\r
-}\r
-\r
-BOOLEAN\r
-NTAPI\r
-KdpLowWriteContent(IN ULONG BpIndex)\r
-{\r
- /* Make sure that the breakpoint is actually active */\r
- if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointPending)\r
- {\r
- /* So we have a valid breakpoint, but it hasn't been used yet... */\r
- KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointPending;\r
- return TRUE;\r
- }\r
-\r
- /* Is the original instruction an INT3 anyway? */\r
- if (KdpBreakpointTable[BpIndex].Content == KdpBreakpointInstruction)\r
- {\r
- /* Then leave it that way... */\r
- return TRUE;\r
- }\r
-\r
- /* We have an active breakpoint with an instruction to bring back. Do it. */\r
- RtlCopyMemory(KdpBreakpointTable[BpIndex].Address,\r
- &KdpBreakpointTable[BpIndex].Content,\r
- sizeof(UCHAR));\r
-\r
- /* Everything went fine, return */\r
- return TRUE;\r
-}\r
-\r
-BOOLEAN\r
-NTAPI\r
-KdpLowRestoreBreakpoint(IN ULONG BpIndex)\r
-{\r
- /* Were we not able to remove it earlier? */\r
- if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointExpired)\r
- {\r
- /* Well then, we'll just re-use it and return success! */\r
- KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointExpired;\r
- return TRUE;\r
- }\r
-\r
- /* Are we merely writing an INT3 on top of another INT3? */\r
- if (KdpBreakpointTable[BpIndex].Content == KdpBreakpointInstruction)\r
- {\r
- /* Nothing to do then... */\r
- return TRUE;\r
- }\r
-\r
- /* Ok, we actually have to overwrite the instruction now */\r
- RtlCopyMemory(KdpBreakpointTable[BpIndex].Address,\r
- &KdpBreakpointInstruction,\r
- sizeof(UCHAR));\r
-\r
- /* Clear any possible previous pending flag and return success */\r
- KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointPending;\r
- return TRUE;\r
-}\r
-\r
-BOOLEAN\r
-NTAPI\r
-KdpDeleteBreakpoint(IN ULONG BpEntry)\r
-{\r
- ULONG BpIndex = BpEntry - 1;\r
-\r
- /* Check for invalid breakpoint entry */\r
- if (!(BpEntry) || (BpEntry > 20)) return FALSE;\r
-\r
- /* If the specified breakpoint table entry is not valid, then return FALSE. */\r
- if (!KdpBreakpointTable[BpIndex].Flags) return FALSE;\r
-\r
- /* Check if the breakpoint is suspended */\r
- if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointSuspended)\r
- {\r
- /* Check if breakpoint is not ...? */\r
- if (!(KdpBreakpointTable[BpIndex].Flags & KdpBreakpointExpired))\r
- {\r
- /* Invalidate it and return success */\r
- KdpBreakpointTable[BpIndex].Flags = 0;\r
- return TRUE;\r
- }\r
- }\r
-\r
- /* Restore original data, then invalidate it and return success */\r
- if (KdpLowWriteContent(BpIndex)) KdpBreakpointTable[BpIndex].Flags = 0;\r
- return TRUE;\r
-}\r
-\r
-BOOLEAN\r
-NTAPI\r
-KdpDeleteBreakpointRange(IN PVOID Base,\r
- IN PVOID Limit)\r
-{\r
- ULONG BpIndex;\r
- BOOLEAN Return = FALSE;\r
-\r
- /* Loop the breakpoint table */\r
- for (BpIndex = 0; BpIndex < 20; BpIndex++)\r
- {\r
- /* Make sure that the breakpoint is active and matches the range. */\r
- if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) &&\r
- ((KdpBreakpointTable[BpIndex].Address >= Base) &&\r
- (KdpBreakpointTable[BpIndex].Address <= Limit)))\r
- {\r
- /* Delete it */\r
- Return = Return || KdpDeleteBreakpoint(BpIndex + 1);\r
- }\r
- }\r
-\r
- /* Return to caller */\r
- return Return;\r
-}\r
-\r
-VOID\r
-NTAPI\r
-KdpRestoreAllBreakpoints(VOID)\r
-{\r
- ULONG BpIndex;\r
-\r
- /* No more suspended Breakpoints */\r
- BreakpointsSuspended = FALSE;\r
-\r
- /* Loop the breakpoints */\r
- for (BpIndex = 0; BpIndex < 20; BpIndex++ )\r
- {\r
- /* Check if they are valid, suspended breakpoints */\r
- if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) &&\r
- (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointSuspended))\r
- {\r
- /* Unsuspend them */\r
- KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointSuspended;\r
- KdpLowRestoreBreakpoint(BpIndex);\r
- }\r
- }\r
-}\r
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/kd64/kdbreak.c
+ * PURPOSE: KD64 Breakpoint Support
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS *****************************************************************/
+
+ULONG
+NTAPI
+KdpAddBreakpoint(IN PVOID Address)
+{
+ KD_BREAKPOINT_TYPE Content;
+ ULONG i;
+
+ /* Loop current breakpoints */
+ for (i = 0; i < KD_BREAKPOINT_MAX; i++)
+ {
+ /* Check if the breakpoint is valid */
+ if ((KdpBreakpointTable[i].Flags & KdpBreakpointActive) &&
+ (KdpBreakpointTable[i].Address == Address))
+ {
+ /* Check if it's pending */
+ if ((KdpBreakpointTable[i].Flags & KdpBreakpointPending))
+ {
+ /* It's not pending anymore now */
+ KdpBreakpointTable[i].Flags &= ~KdpBreakpointPending;
+ return i + 1;
+ }
+ else
+ {
+ /* Fail */
+ return 0;
+ }
+ }
+ }
+
+ /* Find a free entry */
+ for (i = 0; i < KD_BREAKPOINT_MAX; i++) if (!(KdpBreakpointTable[i].Flags)) break;
+
+ /* Fail if no free entry was found */
+ if (i == KD_BREAKPOINT_MAX) return 0;
+
+ /* Save the old instruction */
+ RtlCopyMemory(&Content, Address, KD_BREAKPOINT_SIZE);
+
+ /* Write the entry */
+ KdpBreakpointTable[i].Address = Address;
+ KdpBreakpointTable[i].Content = Content;
+ KdpBreakpointTable[i].Flags = KdpBreakpointActive;
+
+ /* Write the breakpoint and return the handle */
+ RtlCopyMemory(Address, &KdpBreakpointInstruction, KD_BREAKPOINT_SIZE);
+ return i + 1;
+}
+
+BOOLEAN
+NTAPI
+KdpLowWriteContent(IN ULONG BpIndex)
+{
+ /* Make sure that the breakpoint is actually active */
+ if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointPending)
+ {
+ /* So we have a valid breakpoint, but it hasn't been used yet... */
+ KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointPending;
+ return TRUE;
+ }
+
+ /* Is the original instruction a breakpoint anyway? */
+ if (KdpBreakpointTable[BpIndex].Content == KdpBreakpointInstruction)
+ {
+ /* Then leave it that way... */
+ return TRUE;
+ }
+
+ /* We have an active breakpoint with an instruction to bring back. Do it. */
+ RtlCopyMemory(KdpBreakpointTable[BpIndex].Address,
+ &KdpBreakpointTable[BpIndex].Content,
+ KD_BREAKPOINT_SIZE);
+
+ /* Everything went fine, return */
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+KdpLowRestoreBreakpoint(IN ULONG BpIndex)
+{
+ /* Were we not able to remove it earlier? */
+ if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointExpired)
+ {
+ /* Well then, we'll just re-use it and return success! */
+ KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointExpired;
+ return TRUE;
+ }
+
+ /* Are we merely writing a breakpoint on top of another breakpoint? */
+ if (KdpBreakpointTable[BpIndex].Content == KdpBreakpointInstruction)
+ {
+ /* Nothing to do then... */
+ return TRUE;
+ }
+
+ /* Ok, we actually have to overwrite the instruction now */
+ RtlCopyMemory(KdpBreakpointTable[BpIndex].Address,
+ &KdpBreakpointInstruction,
+ KD_BREAKPOINT_SIZE);
+
+ /* Clear any possible previous pending flag and return success */
+ KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointPending;
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+KdpDeleteBreakpoint(IN ULONG BpEntry)
+{
+ ULONG BpIndex = BpEntry - 1;
+
+ /* Check for invalid breakpoint entry */
+ if (!(BpEntry) || (BpEntry > KD_BREAKPOINT_MAX)) return FALSE;
+
+ /* If the specified breakpoint table entry is not valid, then return FALSE. */
+ if (!KdpBreakpointTable[BpIndex].Flags) return FALSE;
+
+ /* Check if the breakpoint is suspended */
+ if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointSuspended)
+ {
+ /* Check if breakpoint is not ...? */
+ if (!(KdpBreakpointTable[BpIndex].Flags & KdpBreakpointExpired))
+ {
+ /* Invalidate it and return success */
+ KdpBreakpointTable[BpIndex].Flags = 0;
+ return TRUE;
+ }
+ }
+
+ /* Restore original data, then invalidate it and return success */
+ if (KdpLowWriteContent(BpIndex)) KdpBreakpointTable[BpIndex].Flags = 0;
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+KdpDeleteBreakpointRange(IN PVOID Base,
+ IN PVOID Limit)
+{
+ ULONG BpIndex;
+ BOOLEAN Return = FALSE;
+
+ /* Loop the breakpoint table */
+ for (BpIndex = 0; BpIndex < KD_BREAKPOINT_MAX; BpIndex++)
+ {
+ /* Make sure that the breakpoint is active and matches the range. */
+ if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) &&
+ ((KdpBreakpointTable[BpIndex].Address >= Base) &&
+ (KdpBreakpointTable[BpIndex].Address <= Limit)))
+ {
+ /* Delete it */
+ Return = Return || KdpDeleteBreakpoint(BpIndex + 1);
+ }
+ }
+
+ /* Return to caller */
+ return Return;
+}
+
+VOID
+NTAPI
+KdpRestoreAllBreakpoints(VOID)
+{
+ ULONG BpIndex;
+
+ /* No more suspended Breakpoints */
+ BreakpointsSuspended = FALSE;
+
+ /* Loop the breakpoints */
+ for (BpIndex = 0; BpIndex < KD_BREAKPOINT_MAX; BpIndex++ )
+ {
+ /* Check if they are valid, suspended breakpoints */
+ if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) &&
+ (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointSuspended))
+ {
+ /* Unsuspend them */
+ KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointSuspended;
+ KdpLowRestoreBreakpoint(BpIndex);
+ }
+ }
+}