+/*\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
+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