- Add kdbreak.c with the following APIs: KdpLowWriteContent, KdpLowRestoreBreakpoint...
authorAlex Ionescu <aionescu@gmail.com>
Tue, 20 Feb 2007 02:00:01 +0000 (02:00 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Tue, 20 Feb 2007 02:00:01 +0000 (02:00 +0000)
- Enable kdinit.c call to KdpRestoreAllBreakpoints.
- Add breakpoint table and data.
- Support DbgKdRestoreBreakpointApi. Now we get DbgKdClearAllInternalBreakpointsApi.

svn path=/branches/alex-kd-branch/; revision=25850

reactos/ntoskrnl/include/internal/kd.h
reactos/ntoskrnl/kd64/kdapi.c
reactos/ntoskrnl/kd64/kdbreak.c [new file with mode: 0644]
reactos/ntoskrnl/kd64/kddata.c
reactos/ntoskrnl/ntoskrnl.rbuild

index 856ed50..2726a51 100644 (file)
@@ -1,3 +1,19 @@
+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)(
@@ -144,6 +160,18 @@ KdpReportLoadSymbolsStateChange(
     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;
@@ -177,3 +205,7 @@ extern ULONG KdComponentTableSize;
 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;
index 92a943c..99546b8 100644 (file)
@@ -243,6 +243,39 @@ KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
                  &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
@@ -327,8 +360,7 @@ SendPacket:
             case DbgKdRestoreBreakPointApi:\r
 \r
                 /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdRestoreBreakPointApi);\r
-                while (TRUE);\r
+                KdpRestoreBreakpoint(&ManipulateState, &Data, Context);\r
                 break;\r
 \r
             case DbgKdContinueApi:\r
@@ -862,7 +894,7 @@ KdEnableDebuggerWithLock(BOOLEAN NeedLock)
         {\r
             /* Reinitialize the Debugger */\r
             KdInitSystem(0, NULL) ;\r
-            //KdpRestoreAllBreakpoints();\r
+            KdpRestoreAllBreakpoints();\r
         }\r
     }\r
 \r
diff --git a/reactos/ntoskrnl/kd64/kdbreak.c b/reactos/ntoskrnl/kd64/kdbreak.c
new file mode 100644 (file)
index 0000000..4b9b9af
--- /dev/null
@@ -0,0 +1,149 @@
+/*\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
index 1cdaf12..709b238 100644 (file)
@@ -45,6 +45,14 @@ BOOLEAN KdEnteredDebugger;
 ULONG KdDisableCount;\r
 LARGE_INTEGER KdPerformanceCounterRate;\r
 \r
+//\r
+// Breakpoint Data\r
+//\r
+BREAKPOINT_ENTRY KdpBreakpointTable[20];\r
+ULONG KdpBreakpointInstruction = 0xCC;\r
+BOOLEAN KdpOweBreakpoint;\r
+BOOLEAN BreakpointsSuspended;\r
+\r
 //\r
 // Time Slip Support\r
 //\r
index 7985971..66487e0 100644 (file)
     </directory>
     <directory name="kd64">
         <file>kdapi.c</file>
+        <file>kdbreak.c</file>
         <file>kddata.c</file>
         <file>kdinit.c</file>
         <file>kdlock.c</file>