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 * Stefan Ginsberg (stefan.ginsberg@reactos.org)
10 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
20 KdpAddBreakpoint(IN PVOID Address
)
22 KD_BREAKPOINT_TYPE Content
;
26 /* Loop current breakpoints */
27 for (i
= 0; i
< KD_BREAKPOINT_MAX
; i
++)
29 /* Check if the breakpoint is valid */
30 if ((KdpBreakpointTable
[i
].Flags
& KdpBreakpointActive
) &&
31 (KdpBreakpointTable
[i
].Address
== Address
))
33 /* Check if it's pending */
34 if ((KdpBreakpointTable
[i
].Flags
& KdpBreakpointPending
))
36 /* It's not pending anymore now */
37 KdpBreakpointTable
[i
].Flags
&= ~KdpBreakpointPending
;
48 /* Find a free entry */
49 for (i
= 0; i
< KD_BREAKPOINT_MAX
; i
++) if (!(KdpBreakpointTable
[i
].Flags
)) break;
51 /* Fail if no free entry was found */
52 if (i
== KD_BREAKPOINT_MAX
) return 0;
54 /* Save the old instruction */
55 Status
= KdpCopyMemoryChunks((ULONG_PTR
)Address
,
62 if (!NT_SUCCESS(Status
))
64 /* TODO: Set it as a owed breakpoint */
65 KdpDprintf("Failed to set breakpoint at address 0x%p\n", Address
);
70 KdpBreakpointTable
[i
].Address
= Address
;
71 KdpBreakpointTable
[i
].Content
= Content
;
72 KdpBreakpointTable
[i
].Flags
= KdpBreakpointActive
;
74 /* Write the breakpoint */
75 Status
= KdpCopyMemoryChunks((ULONG_PTR
)Address
,
76 &KdpBreakpointInstruction
,
79 MMDBG_COPY_UNSAFE
| MMDBG_COPY_WRITE
,
81 if (!NT_SUCCESS(Status
))
83 /* This should never happen */
84 KdpDprintf("Unable to write breakpoint to address 0x%p\n", Address
);
87 /* Return the breakpoint handle */
93 KdpLowWriteContent(IN ULONG BpIndex
)
97 /* Make sure that the breakpoint is actually active */
98 if (KdpBreakpointTable
[BpIndex
].Flags
& KdpBreakpointPending
)
100 /* So we have a valid breakpoint, but it hasn't been used yet... */
101 KdpBreakpointTable
[BpIndex
].Flags
&= ~KdpBreakpointPending
;
105 /* Is the original instruction a breakpoint anyway? */
106 if (KdpBreakpointTable
[BpIndex
].Content
== KdpBreakpointInstruction
)
108 /* Then leave it that way... */
112 /* We have an active breakpoint with an instruction to bring back. Do it. */
113 Status
= KdpCopyMemoryChunks((ULONG_PTR
)KdpBreakpointTable
[BpIndex
].
115 &KdpBreakpointTable
[BpIndex
].Content
,
118 MMDBG_COPY_UNSAFE
| MMDBG_COPY_WRITE
,
120 if (!NT_SUCCESS(Status
))
122 /* TODO: Set it as a owed breakpoint */
123 KdpDprintf("Failed to delete breakpoint at address 0x%p\n",
124 KdpBreakpointTable
[BpIndex
].Address
);
128 /* Everything went fine, return */
134 KdpLowRestoreBreakpoint(IN ULONG BpIndex
)
138 /* Were we not able to remove it earlier? */
139 if (KdpBreakpointTable
[BpIndex
].Flags
& KdpBreakpointExpired
)
141 /* Well then, we'll just re-use it and return success! */
142 KdpBreakpointTable
[BpIndex
].Flags
&= ~KdpBreakpointExpired
;
146 /* Are we merely writing a breakpoint on top of another breakpoint? */
147 if (KdpBreakpointTable
[BpIndex
].Content
== KdpBreakpointInstruction
)
149 /* Nothing to do then... */
153 /* Ok, we actually have to overwrite the instruction now */
154 Status
= KdpCopyMemoryChunks((ULONG_PTR
)KdpBreakpointTable
[BpIndex
].
156 &KdpBreakpointInstruction
,
159 MMDBG_COPY_UNSAFE
| MMDBG_COPY_WRITE
,
161 if (!NT_SUCCESS(Status
))
163 /* FIXME: Set it as a owed breakpoint */
164 KdpDprintf("Failed to restore breakpoint at address 0x%p\n",
165 KdpBreakpointTable
[BpIndex
].Address
);
169 /* Clear any possible previous pending flag and return success */
170 KdpBreakpointTable
[BpIndex
].Flags
&= ~KdpBreakpointPending
;
176 KdpDeleteBreakpoint(IN ULONG BpEntry
)
178 ULONG BpIndex
= BpEntry
- 1;
180 /* Check for invalid breakpoint entry */
181 if (!(BpEntry
) || (BpEntry
> KD_BREAKPOINT_MAX
)) return FALSE
;
183 /* If the specified breakpoint table entry is not valid, then return FALSE. */
184 if (!KdpBreakpointTable
[BpIndex
].Flags
) return FALSE
;
186 /* Check if the breakpoint is suspended */
187 if (KdpBreakpointTable
[BpIndex
].Flags
& KdpBreakpointSuspended
)
189 /* Check if breakpoint is not ...? */
190 if (!(KdpBreakpointTable
[BpIndex
].Flags
& KdpBreakpointExpired
))
192 /* Invalidate it and return success */
193 KdpBreakpointTable
[BpIndex
].Flags
= 0;
198 /* Restore original data, then invalidate it and return success */
199 if (KdpLowWriteContent(BpIndex
)) KdpBreakpointTable
[BpIndex
].Flags
= 0;
205 KdpDeleteBreakpointRange(IN PVOID Base
,
209 BOOLEAN Return
= FALSE
;
211 /* Loop the breakpoint table */
212 for (BpIndex
= 0; BpIndex
< KD_BREAKPOINT_MAX
; BpIndex
++)
214 /* Make sure that the breakpoint is active and matches the range. */
215 if ((KdpBreakpointTable
[BpIndex
].Flags
& KdpBreakpointActive
) &&
216 ((KdpBreakpointTable
[BpIndex
].Address
>= Base
) &&
217 (KdpBreakpointTable
[BpIndex
].Address
<= Limit
)))
220 Return
= Return
|| KdpDeleteBreakpoint(BpIndex
+ 1);
224 /* Return to caller */
230 KdpRestoreAllBreakpoints(VOID
)
234 /* No more suspended Breakpoints */
235 BreakpointsSuspended
= FALSE
;
237 /* Loop the breakpoints */
238 for (BpIndex
= 0; BpIndex
< KD_BREAKPOINT_MAX
; BpIndex
++)
240 /* Check if they are valid, suspended breakpoints */
241 if ((KdpBreakpointTable
[BpIndex
].Flags
& KdpBreakpointActive
) &&
242 (KdpBreakpointTable
[BpIndex
].Flags
& KdpBreakpointSuspended
))
245 KdpBreakpointTable
[BpIndex
].Flags
&= ~KdpBreakpointSuspended
;
246 KdpLowRestoreBreakpoint(BpIndex
);
253 KdpSuspendBreakPoint(IN ULONG BpEntry
)
255 ULONG BpIndex
= BpEntry
- 1;
257 /* Check if this is a valid, unsuspended breakpoint */
258 if ((KdpBreakpointTable
[BpIndex
].Flags
& KdpBreakpointActive
) &&
259 !(KdpBreakpointTable
[BpIndex
].Flags
& KdpBreakpointSuspended
))
262 KdpBreakpointTable
[BpIndex
].Flags
|= KdpBreakpointSuspended
;
263 KdpLowWriteContent(BpIndex
);
269 KdpSuspendAllBreakPoints(VOID
)
273 /* Breakpoints are suspended */
274 BreakpointsSuspended
= TRUE
;
276 /* Loop every breakpoint */
277 for (BpEntry
= 1; BpEntry
<= KD_BREAKPOINT_MAX
; BpEntry
++)
280 KdpSuspendBreakPoint(BpEntry
);