ReactOS 0.4.15-dev-5664-g3bf4ef6
kdbreak.c
Go to the documentation of this file.
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 * Stefan Ginsberg (stefan.ginsberg@reactos.org)
8 */
9
10/* INCLUDES ******************************************************************/
11
12#include <ntoskrnl.h>
13#define NDEBUG
14#include <debug.h>
15
16/* FUNCTIONS *****************************************************************/
17
21{
22 KD_BREAKPOINT_TYPE Content;
23 ULONG i;
25
26 /* Check whether we are not setting a breakpoint twice */
27 for (i = 0; i < KD_BREAKPOINT_MAX; i++)
28 {
29 /* Check if the breakpoint is valid */
32 {
33 /* Were we not able to remove it earlier? */
35 {
36 /* Just re-use it! */
37 KdpBreakpointTable[i].Flags &= ~KD_BREAKPOINT_EXPIRED;
38 return i + 1;
39 }
40 else
41 {
42 /* Fail */
43 return 0;
44 }
45 }
46 }
47
48 /* Find a free entry */
49 for (i = 0; i < KD_BREAKPOINT_MAX; i++)
50 {
51 if (KdpBreakpointTable[i].Flags == 0)
52 break;
53 }
54
55 /* Fail if no free entry was found */
56 if (i == KD_BREAKPOINT_MAX) return 0;
57
58 /* Save the breakpoint */
60
61 /* If we are setting the breakpoint in user space, save the active process context */
63 KdpBreakpointTable[i].DirectoryTableBase = KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0];
64
65 /* Try to save the old instruction */
67 &Content,
69 0,
71 NULL);
72 if (NT_SUCCESS(Status))
73 {
74 /* Memory accessible, set the breakpoint */
75 KdpBreakpointTable[i].Content = Content;
77
78 /* Write the breakpoint */
82 0,
84 NULL);
85 if (!NT_SUCCESS(Status))
86 {
87 /* This should never happen */
88 KdpDprintf("Unable to write breakpoint to address 0x%p\n", Address);
89 }
90 }
91 else
92 {
93 /* Memory is inaccessible now, setting breakpoint is deferred */
94 KdpDprintf("Failed to set breakpoint at address 0x%p, adding deferred breakpoint.\n", Address);
97 }
98
99 /* Return the breakpoint handle */
100 return i + 1;
101}
102
103VOID
104NTAPI
106{
108 KD_BREAKPOINT_TYPE Content;
109 ULONG i;
111
112 /* If we don't owe any breakpoints, just return */
113 if (!KdpOweBreakpoint) return;
114
115 /* Enter the debugger */
117
118 /*
119 * Suppose we succeed in setting all the breakpoints.
120 * If we fail to do so, the flag will be set again.
121 */
123
124 /* Loop through current breakpoints and try to set or delete the pending ones */
125 for (i = 0; i < KD_BREAKPOINT_MAX; i++)
126 {
128 {
129 /*
130 * Set the breakpoint only if it is in kernel space, or if it is
131 * in user space and the active process context matches.
132 */
134 KdpBreakpointTable[i].DirectoryTableBase != KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0])
135 {
137 continue;
138 }
139
140 /* Try to save the old instruction */
142 &Content,
144 0,
146 NULL);
147 if (!NT_SUCCESS(Status))
148 {
149 /* Memory is still inaccessible, breakpoint setting will be deferred again */
150 // KdpDprintf("Failed to set deferred breakpoint at address 0x%p\n",
151 // KdpBreakpointTable[i].Address);
153 continue;
154 }
155
156 /* Check if we need to write the breakpoint */
158 {
159 /* Memory accessible, set the breakpoint */
160 KdpBreakpointTable[i].Content = Content;
161
162 /* Write the breakpoint */
166 0,
168 NULL);
169 if (!NT_SUCCESS(Status))
170 {
171 /* This should never happen */
172 KdpDprintf("Unable to write deferred breakpoint to address 0x%p\n",
175 }
176 else
177 {
179 }
180
181 continue;
182 }
183
184 /* Check if we need to restore the original instruction */
186 {
187 /* Write it back */
189 &KdpBreakpointTable[i].Content,
191 0,
193 NULL);
194 if (!NT_SUCCESS(Status))
195 {
196 /* This should never happen */
197 KdpDprintf("Unable to delete deferred breakpoint at address 0x%p\n",
200 }
201 else
202 {
203 /* Check if the breakpoint is suspended */
205 {
207 }
208 else
209 {
210 /* Invalidate it */
212 }
213 }
214
215 continue;
216 }
217 }
218 }
219
220 /* Exit the debugger */
222}
223
225NTAPI
227{
229
230 /* Make sure that the breakpoint is actually active */
232 {
233 /* So we have a valid breakpoint, but it hasn't been used yet... */
234 KdpBreakpointTable[BpIndex].Flags &= ~KD_BREAKPOINT_PENDING;
235 return TRUE;
236 }
237
238 /* Is the original instruction a breakpoint anyway? */
239 if (KdpBreakpointTable[BpIndex].Content == KdpBreakpointInstruction)
240 {
241 /* Then leave it that way... */
242 return TRUE;
243 }
244
245 /* We have an active breakpoint with an instruction to bring back. Do it. */
247 &KdpBreakpointTable[BpIndex].Content,
249 0,
251 NULL);
252 if (!NT_SUCCESS(Status))
253 {
254 /* Memory is inaccessible now, restoring original instruction is deferred */
255 // KdpDprintf("Failed to delete breakpoint at address 0x%p\n",
256 // KdpBreakpointTable[BpIndex].Address);
259 return FALSE;
260 }
261
262 /* Everything went fine, return */
263 return TRUE;
264}
265
267NTAPI
269{
271
272 /* Were we not able to remove it earlier? */
274 {
275 /* Just re-use it! */
276 KdpBreakpointTable[BpIndex].Flags &= ~KD_BREAKPOINT_EXPIRED;
277 return TRUE;
278 }
279
280 /* Are we merely writing a breakpoint on top of another breakpoint? */
281 if (KdpBreakpointTable[BpIndex].Content == KdpBreakpointInstruction)
282 {
283 /* Nothing to do */
284 return TRUE;
285 }
286
287 /* Ok, we actually have to overwrite the instruction now */
291 0,
293 NULL);
294 if (!NT_SUCCESS(Status))
295 {
296 /* Memory is inaccessible now, restoring breakpoint is deferred */
297 // KdpDprintf("Failed to restore breakpoint at address 0x%p\n",
298 // KdpBreakpointTable[BpIndex].Address);
301 return FALSE;
302 }
303
304 /* Clear any possible previous pending flag and return success */
305 KdpBreakpointTable[BpIndex].Flags &= ~KD_BREAKPOINT_PENDING;
306 return TRUE;
307}
308
310NTAPI
312{
313 ULONG BpIndex = BpEntry - 1;
314
315 /* Check for invalid breakpoint entry */
316 if (!BpEntry || (BpEntry > KD_BREAKPOINT_MAX)) return FALSE;
317
318 /* If the specified breakpoint table entry is not valid, then return FALSE. */
319 if (!KdpBreakpointTable[BpIndex].Flags) return FALSE;
320
321 /* Check if the breakpoint is suspended */
323 {
324 /* Check if breakpoint is not being deleted */
326 {
327 /* Invalidate it and return success */
328 KdpBreakpointTable[BpIndex].Flags = 0;
329 return TRUE;
330 }
331 }
332
333 /* Restore original data, then invalidate it and return success */
334 if (KdpLowWriteContent(BpIndex)) KdpBreakpointTable[BpIndex].Flags = 0;
335 return TRUE;
336}
337
339NTAPI
341 IN PVOID Limit)
342{
343 ULONG BpIndex;
344 BOOLEAN DeletedBreakpoints;
345
346 /* Assume no breakpoints will be deleted */
347 DeletedBreakpoints = FALSE;
348
349 /* Loop the breakpoint table */
350 for (BpIndex = 0; BpIndex < KD_BREAKPOINT_MAX; BpIndex++)
351 {
352 /* Make sure that the breakpoint is active and matches the range. */
354 ((KdpBreakpointTable[BpIndex].Address >= Base) &&
355 (KdpBreakpointTable[BpIndex].Address <= Limit)))
356 {
357 /* Delete it, and remember if we succeeded at least once */
358 if (KdpDeleteBreakpoint(BpIndex + 1)) DeletedBreakpoints = TRUE;
359 }
360 }
361
362 /* Return whether we deleted anything */
363 return DeletedBreakpoints;
364}
365
366VOID
367NTAPI
369{
370 ULONG BpIndex;
371
372 /* No more suspended Breakpoints */
374
375 /* Loop the breakpoints */
376 for (BpIndex = 0; BpIndex < KD_BREAKPOINT_MAX; BpIndex++)
377 {
378 /* Check if they are valid, suspended breakpoints */
381 {
382 /* Unsuspend them */
383 KdpBreakpointTable[BpIndex].Flags &= ~KD_BREAKPOINT_SUSPENDED;
385 }
386 }
387}
388
389VOID
390NTAPI
392{
393 ULONG BpIndex = BpEntry - 1;
394
395 /* Check if this is a valid, unsuspended breakpoint */
398 {
399 /* Suspend it */
401 KdpLowWriteContent(BpIndex);
402 }
403}
404
405VOID
406NTAPI
408{
409 ULONG BpEntry;
410
411 /* Breakpoints are suspended */
413
414 /* Loop every breakpoint */
415 for (BpEntry = 1; BpEntry <= KD_BREAKPOINT_MAX; BpEntry++)
416 {
417 /* Suspend it */
418 KdpSuspendBreakPoint(BpEntry);
419 }
420}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define KeGetCurrentThread
Definition: hal.h:55
#define KD_BREAKPOINT_MAX
Definition: kd64.h:28
BREAKPOINT_ENTRY KdpBreakpointTable[KD_BREAKPOINT_MAX]
Definition: kddata.c:96
#define KD_BREAKPOINT_EXPIRED
Definition: kd64.h:48
BOOLEAN BreakpointsSuspended
Definition: kddata.c:99
KD_BREAKPOINT_TYPE KdpBreakpointInstruction
Definition: kddata.c:97
#define KD_BREAKPOINT_ACTIVE
Definition: kd64.h:45
#define KD_BREAKPOINT_PENDING
Definition: kd64.h:46
NTSTATUS NTAPI KdpCopyMemoryChunks(_In_ ULONG64 Address, _In_ PVOID Buffer, _In_ ULONG TotalSize, _In_ ULONG ChunkSize, _In_ ULONG Flags, _Out_opt_ PULONG ActualSize)
Definition: kdapi.c:50
BOOLEAN NTAPI KdEnterDebugger(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdapi.c:1871
VOID NTAPI KdExitDebugger(IN BOOLEAN Enable)
Definition: kdapi.c:1924
#define KD_HIGHEST_USER_BREAKPOINT_ADDRESS
Definition: kd64.h:40
#define KD_BREAKPOINT_SUSPENDED
Definition: kd64.h:47
BOOLEAN KdpOweBreakpoint
Definition: kddata.c:98
VOID NTAPI KdpSuspendBreakPoint(IN ULONG BpEntry)
Definition: kdbreak.c:391
BOOLEAN NTAPI KdpLowWriteContent(IN ULONG BpIndex)
Definition: kdbreak.c:226
BOOLEAN NTAPI KdpDeleteBreakpointRange(IN PVOID Base, IN PVOID Limit)
Definition: kdbreak.c:340
BOOLEAN NTAPI KdpLowRestoreBreakpoint(IN ULONG BpIndex)
Definition: kdbreak.c:268
VOID NTAPI KdSetOwedBreakpoints(VOID)
Definition: kdbreak.c:105
VOID NTAPI KdpRestoreAllBreakpoints(VOID)
Definition: kdbreak.c:368
ULONG NTAPI KdpAddBreakpoint(IN PVOID Address)
Definition: kdbreak.c:20
BOOLEAN NTAPI KdpDeleteBreakpoint(IN ULONG BpEntry)
Definition: kdbreak.c:311
VOID NTAPI KdpSuspendAllBreakPoints(VOID)
Definition: kdbreak.c:407
unsigned int ULONG
Definition: retypes.h:1
#define KdpDprintf(...)
Definition: mmdbg.c:19
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2427
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
#define KD_BREAKPOINT_TYPE
Definition: ke.h:121
#define KD_BREAKPOINT_SIZE
Definition: ke.h:122
#define MMDBG_COPY_UNSAFE
Definition: mm.h:77
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1727
#define MMDBG_COPY_WRITE
Definition: mm.h:75
static WCHAR Address[46]
Definition: ping.c:68
KD_BREAKPOINT_TYPE Content
Definition: kd64.h:58
ULONG_PTR DirectoryTableBase
Definition: kd64.h:56
ULONG Flags
Definition: kd64.h:55
PVOID Address
Definition: kd64.h:57
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:318