Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenkdbreak.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/kd64/kdbreak.c 00005 * PURPOSE: KD64 Breakpoint Support 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Stefan Ginsberg (stefan.ginsberg@reactos.org) 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* FUNCTIONS *****************************************************************/ 00017 00018 ULONG 00019 NTAPI 00020 KdpAddBreakpoint(IN PVOID Address) 00021 { 00022 KD_BREAKPOINT_TYPE Content; 00023 ULONG i; 00024 NTSTATUS Status; 00025 00026 /* Loop current breakpoints */ 00027 for (i = 0; i < KD_BREAKPOINT_MAX; i++) 00028 { 00029 /* Check if the breakpoint is valid */ 00030 if ((KdpBreakpointTable[i].Flags & KdpBreakpointActive) && 00031 (KdpBreakpointTable[i].Address == Address)) 00032 { 00033 /* Check if it's pending */ 00034 if ((KdpBreakpointTable[i].Flags & KdpBreakpointPending)) 00035 { 00036 /* It's not pending anymore now */ 00037 KdpBreakpointTable[i].Flags &= ~KdpBreakpointPending; 00038 return i + 1; 00039 } 00040 else 00041 { 00042 /* Fail */ 00043 return 0; 00044 } 00045 } 00046 } 00047 00048 /* Find a free entry */ 00049 for (i = 0; i < KD_BREAKPOINT_MAX; i++) if (!(KdpBreakpointTable[i].Flags)) break; 00050 00051 /* Fail if no free entry was found */ 00052 if (i == KD_BREAKPOINT_MAX) return 0; 00053 00054 /* Save the old instruction */ 00055 Status = KdpCopyMemoryChunks((ULONG_PTR)Address, 00056 &Content, 00057 KD_BREAKPOINT_SIZE, 00058 0, 00059 MMDBG_COPY_UNSAFE, 00060 NULL); 00061 00062 if (!NT_SUCCESS(Status)) 00063 { 00064 /* TODO: Set it as a owed breakpoint */ 00065 KdpDprintf("Failed to set breakpoint at address 0x%p\n", Address); 00066 return 0; 00067 } 00068 00069 /* Write the entry */ 00070 KdpBreakpointTable[i].Address = Address; 00071 KdpBreakpointTable[i].Content = Content; 00072 KdpBreakpointTable[i].Flags = KdpBreakpointActive; 00073 00074 /* Write the breakpoint */ 00075 Status = KdpCopyMemoryChunks((ULONG_PTR)Address, 00076 &KdpBreakpointInstruction, 00077 KD_BREAKPOINT_SIZE, 00078 0, 00079 MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE, 00080 NULL); 00081 if (!NT_SUCCESS(Status)) 00082 { 00083 /* This should never happen */ 00084 KdpDprintf("Unable to write breakpoint to address 0x%p\n", Address); 00085 } 00086 00087 /* Return the breakpoint handle */ 00088 return i + 1; 00089 } 00090 00091 BOOLEAN 00092 NTAPI 00093 KdpLowWriteContent(IN ULONG BpIndex) 00094 { 00095 NTSTATUS Status; 00096 00097 /* Make sure that the breakpoint is actually active */ 00098 if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointPending) 00099 { 00100 /* So we have a valid breakpoint, but it hasn't been used yet... */ 00101 KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointPending; 00102 return TRUE; 00103 } 00104 00105 /* Is the original instruction a breakpoint anyway? */ 00106 if (KdpBreakpointTable[BpIndex].Content == KdpBreakpointInstruction) 00107 { 00108 /* Then leave it that way... */ 00109 return TRUE; 00110 } 00111 00112 /* We have an active breakpoint with an instruction to bring back. Do it. */ 00113 Status = KdpCopyMemoryChunks((ULONG_PTR)KdpBreakpointTable[BpIndex]. 00114 Address, 00115 &KdpBreakpointTable[BpIndex].Content, 00116 KD_BREAKPOINT_SIZE, 00117 0, 00118 MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE, 00119 NULL); 00120 if (!NT_SUCCESS(Status)) 00121 { 00122 /* TODO: Set it as a owed breakpoint */ 00123 KdpDprintf("Failed to delete breakpoint at address 0x%p\n", 00124 KdpBreakpointTable[BpIndex].Address); 00125 return FALSE; 00126 } 00127 00128 /* Everything went fine, return */ 00129 return TRUE; 00130 } 00131 00132 BOOLEAN 00133 NTAPI 00134 KdpLowRestoreBreakpoint(IN ULONG BpIndex) 00135 { 00136 NTSTATUS Status; 00137 00138 /* Were we not able to remove it earlier? */ 00139 if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointExpired) 00140 { 00141 /* Well then, we'll just re-use it and return success! */ 00142 KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointExpired; 00143 return TRUE; 00144 } 00145 00146 /* Are we merely writing a breakpoint on top of another breakpoint? */ 00147 if (KdpBreakpointTable[BpIndex].Content == KdpBreakpointInstruction) 00148 { 00149 /* Nothing to do then... */ 00150 return TRUE; 00151 } 00152 00153 /* Ok, we actually have to overwrite the instruction now */ 00154 Status = KdpCopyMemoryChunks((ULONG_PTR)KdpBreakpointTable[BpIndex]. 00155 Address, 00156 &KdpBreakpointInstruction, 00157 KD_BREAKPOINT_SIZE, 00158 0, 00159 MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE, 00160 NULL); 00161 if (!NT_SUCCESS(Status)) 00162 { 00163 /* FIXME: Set it as a owed breakpoint */ 00164 KdpDprintf("Failed to restore breakpoint at address 0x%p\n", 00165 KdpBreakpointTable[BpIndex].Address); 00166 return FALSE; 00167 } 00168 00169 /* Clear any possible previous pending flag and return success */ 00170 KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointPending; 00171 return TRUE; 00172 } 00173 00174 BOOLEAN 00175 NTAPI 00176 KdpDeleteBreakpoint(IN ULONG BpEntry) 00177 { 00178 ULONG BpIndex = BpEntry - 1; 00179 00180 /* Check for invalid breakpoint entry */ 00181 if (!(BpEntry) || (BpEntry > KD_BREAKPOINT_MAX)) return FALSE; 00182 00183 /* If the specified breakpoint table entry is not valid, then return FALSE. */ 00184 if (!KdpBreakpointTable[BpIndex].Flags) return FALSE; 00185 00186 /* Check if the breakpoint is suspended */ 00187 if (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointSuspended) 00188 { 00189 /* Check if breakpoint is not ...? */ 00190 if (!(KdpBreakpointTable[BpIndex].Flags & KdpBreakpointExpired)) 00191 { 00192 /* Invalidate it and return success */ 00193 KdpBreakpointTable[BpIndex].Flags = 0; 00194 return TRUE; 00195 } 00196 } 00197 00198 /* Restore original data, then invalidate it and return success */ 00199 if (KdpLowWriteContent(BpIndex)) KdpBreakpointTable[BpIndex].Flags = 0; 00200 return TRUE; 00201 } 00202 00203 BOOLEAN 00204 NTAPI 00205 KdpDeleteBreakpointRange(IN PVOID Base, 00206 IN PVOID Limit) 00207 { 00208 ULONG BpIndex; 00209 BOOLEAN Return = FALSE; 00210 00211 /* Loop the breakpoint table */ 00212 for (BpIndex = 0; BpIndex < KD_BREAKPOINT_MAX; BpIndex++) 00213 { 00214 /* Make sure that the breakpoint is active and matches the range. */ 00215 if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) && 00216 ((KdpBreakpointTable[BpIndex].Address >= Base) && 00217 (KdpBreakpointTable[BpIndex].Address <= Limit))) 00218 { 00219 /* Delete it */ 00220 Return = Return || KdpDeleteBreakpoint(BpIndex + 1); 00221 } 00222 } 00223 00224 /* Return to caller */ 00225 return Return; 00226 } 00227 00228 VOID 00229 NTAPI 00230 KdpRestoreAllBreakpoints(VOID) 00231 { 00232 ULONG BpIndex; 00233 00234 /* No more suspended Breakpoints */ 00235 BreakpointsSuspended = FALSE; 00236 00237 /* Loop the breakpoints */ 00238 for (BpIndex = 0; BpIndex < KD_BREAKPOINT_MAX; BpIndex++) 00239 { 00240 /* Check if they are valid, suspended breakpoints */ 00241 if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) && 00242 (KdpBreakpointTable[BpIndex].Flags & KdpBreakpointSuspended)) 00243 { 00244 /* Unsuspend them */ 00245 KdpBreakpointTable[BpIndex].Flags &= ~KdpBreakpointSuspended; 00246 KdpLowRestoreBreakpoint(BpIndex); 00247 } 00248 } 00249 } 00250 00251 VOID 00252 NTAPI 00253 KdpSuspendBreakPoint(IN ULONG BpEntry) 00254 { 00255 ULONG BpIndex = BpEntry - 1; 00256 00257 /* Check if this is a valid, unsuspended breakpoint */ 00258 if ((KdpBreakpointTable[BpIndex].Flags & KdpBreakpointActive) && 00259 !(KdpBreakpointTable[BpIndex].Flags & KdpBreakpointSuspended)) 00260 { 00261 /* Suspend it */ 00262 KdpBreakpointTable[BpIndex].Flags |= KdpBreakpointSuspended; 00263 KdpLowWriteContent(BpIndex); 00264 } 00265 } 00266 00267 VOID 00268 NTAPI 00269 KdpSuspendAllBreakPoints(VOID) 00270 { 00271 ULONG BpEntry; 00272 00273 /* Breakpoints are suspended */ 00274 BreakpointsSuspended = TRUE; 00275 00276 /* Loop every breakpoint */ 00277 for (BpEntry = 1; BpEntry <= KD_BREAKPOINT_MAX; BpEntry++) 00278 { 00279 /* Suspend it */ 00280 KdpSuspendBreakPoint(BpEntry); 00281 } 00282 } Generated on Sat May 26 2012 04:36:15 for ReactOS by
1.7.6.1
|