4b9b9af12f760e9eec0d349a555ae52e49827968
[reactos.git] / reactos / ntoskrnl / kd64 / kdbreak.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/kd64/kdbreak.c
5 * PURPOSE: KD64 Breakpoint Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS *****************************************************************/
16
17 BOOLEAN
18 NTAPI
19 KdpLowWriteContent(IN ULONG BpIndex)
20 {
21 /* Make sure that the breakpoint is actually active */
22 if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointPending)
23 {
24 /* So we have a valid breakpoint, but it hasn't been used yet... */
25 KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointPending;
26 return TRUE;
27 }
28
29 /* Is the original instruction an INT3 anyway? */
30 if (KdpBreakpointTable[BpIndex].Content == KdpBreakpointInstruction)
31 {
32 /* Then leave it that way... */
33 return TRUE;
34 }
35
36 /* We have an active breakpoint with an instruction to bring back. Do it. */
37 RtlCopyMemory(KdpBreakpointTable[BpIndex].Address,
38 &KdpBreakpointTable[BpIndex].Content,
39 sizeof(UCHAR));
40
41 /* Everything went fine, return */
42 return TRUE;
43 }
44
45 BOOLEAN
46 NTAPI
47 KdpLowRestoreBreakpoint(IN ULONG BpIndex)
48 {
49 /* Were we not able to remove it earlier? */
50 if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointExpired)
51 {
52 /* Well then, we'll just re-use it and return success! */
53 KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointExpired;
54 return TRUE;
55 }
56
57 /* Are we merely writing an INT3 on top of another INT3? */
58 if (KdpBreakpointTable[BpIndex].Content == KdpBreakpointInstruction)
59 {
60 /* Nothing to do then... */
61 return TRUE;
62 }
63
64 /* Ok, we actually have to overwrite the instruction now */
65 RtlCopyMemory(KdpBreakpointTable[BpIndex].Address,
66 &KdpBreakpointInstruction,
67 sizeof(UCHAR));
68
69 /* Clear any possible previous pending flag and return success */
70 KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointPending;
71 return TRUE;
72 }
73
74 BOOLEAN
75 NTAPI
76 KdpDeleteBreakpoint(IN ULONG BpEntry)
77 {
78 ULONG BpIndex = BpEntry - 1;
79
80 /* Check for invalid breakpoint entry */
81 if (!(BpEntry) || (BpEntry > 20)) return FALSE;
82
83 /* If the specified breakpoint table entry is not valid, then return FALSE. */
84 if (!KdpBreakpointTable[BpIndex].Flags) return FALSE;
85
86 /* Check if the breakpoint is suspended */
87 if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointSuspended)
88 {
89 /* Check if breakpoint is not ...? */
90 if (!(KdpBreakpointTable[BpIndex].Flags & KdpBreakpointExpired))
91 {
92 /* Invalidate it and return success */
93 KdpBreakpointTable[BpIndex].Flags = 0;
94 return TRUE;
95 }
96 }
97
98 /* Restore original data, then invalidate it and return success */
99 if (KdpLowWriteContent(BpIndex)) KdpBreakpointTable[BpIndex].Flags = 0;
100 return TRUE;
101 }
102
103 BOOLEAN
104 NTAPI
105 KdpDeleteBreakpointRange(IN PVOID Base,
106 IN PVOID Limit)
107 {
108 ULONG BpIndex;
109 BOOLEAN Return = FALSE;
110
111 /* Loop the breakpoint table */
112 for (BpIndex = 0; BpIndex < 20; BpIndex++)
113 {
114 /* Make sure that the breakpoint is active and matches the range. */
115 if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) &&
116 ((KdpBreakpointTable[BpIndex].Address >= Base) &&
117 (KdpBreakpointTable[BpIndex].Address <= Limit)))
118 {
119 /* Delete it */
120 Return = Return || KdpDeleteBreakpoint(BpIndex + 1);
121 }
122 }
123
124 /* Return to caller */
125 return Return;
126 }
127
128 VOID
129 NTAPI
130 KdpRestoreAllBreakpoints(VOID)
131 {
132 ULONG BpIndex;
133
134 /* No more suspended Breakpoints */
135 BreakpointsSuspended = FALSE;
136
137 /* Loop the breakpoints */
138 for (BpIndex = 0; BpIndex < 20; BpIndex++ )
139 {
140 /* Check if they are valid, suspended breakpoints */
141 if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) &&
142 (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointSuspended))
143 {
144 /* Unsuspend them */
145 KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointSuspended;
146 KdpLowRestoreBreakpoint(BpIndex);
147 }
148 }
149 }