+typedef struct _BREAKPOINT_ENTRY
+{
+ ULONG Flags;
+ PKPROCESS Process;
+ PVOID Address;
+ UCHAR Content;
+} BREAKPOINT_ENTRY, *PBREAKPOINT_ENTRY;
+
+typedef enum _KDP_BREAKPOINT_FLAGS
+{
+ KdpBreakpointActive = 1,
+ KdpBreakpointPending = 2,
+ KdpBreakpointSuspended = 4,
+ KdpBreakpointExpired = 8
+} KDP_BREAKPOINT_FLAGS;
+
typedef
BOOLEAN
(NTAPI *PKDEBUG_ROUTINE)(
IN OUT PCONTEXT Context
);
+VOID
+NTAPI
+KdpRestoreAllBreakpoints(
+ VOID
+);
+
+BOOLEAN
+NTAPI
+KdpDeleteBreakpoint(
+ IN ULONG BpEntry
+);
+
extern DBGKD_GET_VERSION64 KdVersionBlock;
extern KDDEBUGGER_DATA64 KdDebuggerDataBlock;
extern LIST_ENTRY KdpDebuggerDataListHead;
extern ULONG Kd_WIN2000_Mask;
extern PULONG KdComponentTable[104];
extern CHAR KdpMessageBuffer[4096], KdpPathBuffer[4096];
+extern BREAKPOINT_ENTRY KdpBreakpointTable[20];
+extern ULONG KdpBreakpointInstruction;
+extern BOOLEAN KdpOweBreakpoint;
+extern BOOLEAN BreakpointsSuspended;
&KdpContext);\r
}\r
\r
+VOID\r
+NTAPI\r
+KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,\r
+ IN PSTRING Data,\r
+ IN PCONTEXT Context)\r
+{\r
+ PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;\r
+ STRING Header;\r
+\r
+ /* Fill out the header */\r
+ Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);\r
+ Header.Buffer = (PCHAR)State;\r
+ ASSERT(Data->Length == 0);\r
+\r
+ /* Get the version block */\r
+ if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))\r
+ {\r
+ /* We're all good */\r
+ State->ReturnStatus = STATUS_SUCCESS;\r
+ }\r
+ else\r
+ {\r
+ /* We failed */\r
+ State->ReturnStatus = STATUS_UNSUCCESSFUL;\r
+ }\r
+\r
+ /* Send the packet */\r
+ KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
+ &Header,\r
+ NULL,\r
+ &KdpContext);\r
+}\r
+\r
KCONTINUE_STATUS\r
NTAPI\r
KdpSendWaitContinue(IN ULONG PacketType,\r
case DbgKdRestoreBreakPointApi:\r
\r
/* FIXME: TODO */\r
- Ke386SetCr2(DbgKdRestoreBreakPointApi);\r
- while (TRUE);\r
+ KdpRestoreBreakpoint(&ManipulateState, &Data, Context);\r
break;\r
\r
case DbgKdContinueApi:\r
{\r
/* Reinitialize the Debugger */\r
KdInitSystem(0, NULL) ;\r
- //KdpRestoreAllBreakpoints();\r
+ KdpRestoreAllBreakpoints();\r
}\r
}\r
\r
--- /dev/null
+/*\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