Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

kdbreak.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 kdbreak.c 00008 00009 Abstract: 00010 00011 This module implements machine dependent functions to add and delete 00012 breakpoints from the kernel debugger breakpoint table. 00013 00014 Author: 00015 00016 David N. Cutler 2-Aug-1990 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "kdp.h" 00023 00024 // 00025 // Define external references. 00026 // 00027 00028 VOID 00029 KdSetOwedBreakpoints( 00030 VOID 00031 ); 00032 00033 BOOLEAN 00034 KdpLowWriteContent( 00035 ULONG Index 00036 ); 00037 00038 BOOLEAN 00039 KdpLowRestoreBreakpoint( 00040 ULONG Index 00041 ); 00042 00043 #ifdef ALLOC_PRAGMA 00044 #pragma alloc_text(PAGEKD, KdpAddBreakpoint) 00045 #pragma alloc_text(PAGEKD, KdpDeleteBreakpoint) 00046 #pragma alloc_text(PAGEKD, KdpDeleteBreakpointRange) 00047 #pragma alloc_text(PAGEKD, KdpSuspendBreakpoint) 00048 #pragma alloc_text(PAGEKD, KdpSuspendAllBreakpoints) 00049 #pragma alloc_text(PAGEKD, KdpRestoreAllBreakpoints) 00050 #pragma alloc_text(PAGEKD, KdpLowWriteContent) 00051 #pragma alloc_text(PAGEKD, KdpLowRestoreBreakpoint) 00052 #if defined(_IA64_) 00053 #pragma alloc_text(PAGEKD, KdpSuspendBreakpointRange) 00054 #pragma alloc_text(PAGEKD, KdpRestoreBreakpointRange) 00055 #endif 00056 #endif 00057 00058 00059 ULONG 00060 KdpAddBreakpoint ( 00061 IN PVOID Address 00062 ) 00063 00064 /*++ 00065 00066 Routine Description: 00067 00068 This routine adds an entry to the breakpoint table and returns a handle 00069 to the breakpoint table entry. 00070 00071 Arguments: 00072 00073 Address - Supplies the address where to set the breakpoint. 00074 00075 Return Value: 00076 00077 A value of zero is returned if the specified address is already in the 00078 breakpoint table, there are no free entries in the breakpoint table, the 00079 specified address is not correctly aligned, or the specified address is 00080 not valid. Otherwise, the index of the assigned breakpoint table entry 00081 plus one is returned as the function value. 00082 00083 --*/ 00084 00085 { 00086 00087 KDP_BREAKPOINT_TYPE Content; 00088 ULONG Index; 00089 BOOLEAN Accessible; 00090 ULONG_PTR Opaque; 00091 00092 //DPRINT(("KD: Setting breakpoint at 0x%08x\n", Address)); 00093 00094 // 00095 // If the specified address is not properly aligned, then return zero. 00096 // 00097 00098 if (((ULONG_PTR)Address & KDP_BREAKPOINT_ALIGN) != 0) { 00099 return 0; 00100 } 00101 00102 00103 // 00104 // Don't allow setting the same breakpoint twice. 00105 // 00106 00107 for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index += 1) { 00108 if ((KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) != 0 && 00109 KdpBreakpointTable[Index].Address == Address) { 00110 00111 if ((KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_REPLACE) != 0) { 00112 00113 // 00114 // Breakpoint was set, the page was written out and was not 00115 // accessible when the breakpoint was cleared. Now the breakpoint 00116 // is being set again. Just clear the defer flag: 00117 // 00118 KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_NEEDS_REPLACE; 00119 return Index + 1; 00120 00121 } else { 00122 00123 DPRINT(("KD: Attempt to set breakpoint %08x twice!\n", Address)); 00124 return 0; 00125 00126 } 00127 } 00128 } 00129 00130 // 00131 // Search the breakpoint table for a free entry. 00132 // 00133 00134 for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index += 1) { 00135 if (KdpBreakpointTable[Index].Flags == 0) { 00136 break; 00137 } 00138 } 00139 00140 // 00141 // If a free entry was found, then write breakpoint and return the handle 00142 // value plus one. Otherwise, return zero. 00143 // 00144 00145 if (Index == BREAKPOINT_TABLE_SIZE) { 00146 DPRINT(("KD: ran out of breakpoints!\n")); 00147 return 0; 00148 } 00149 00150 00151 //DPRINT(("KD: using Index %d\n", Index)); 00152 00153 // 00154 // Get the instruction to be replaced. If the instruction cannot be read, 00155 // then mark breakpoint as not accessible. 00156 // 00157 00158 if (KdpMoveMemory( 00159 (PCHAR)&Content, 00160 (PCHAR)Address, 00161 sizeof(KDP_BREAKPOINT_TYPE) ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00162 Accessible = FALSE; 00163 //DPRINT(("KD: memory inaccessible\n")); 00164 } else { 00165 //DPRINT(("KD: memory readable...\n")); 00166 Accessible = TRUE; 00167 } 00168 00169 // 00170 // If the specified address is not write accessible, then return zero. 00171 // 00172 00173 if (Accessible) { 00174 if (MmDbgWriteCheck((PVOID)Address, &Opaque) != NULL) { 00175 MmDbgReleaseAddress((PVOID)Address, Opaque); 00176 } else { 00177 DPRINT(("KD: memory not writable!\n")); 00178 return 0; 00179 } 00180 } 00181 00182 #if defined(_IA64_) 00183 if ( Accessible ) { 00184 KDP_BREAKPOINT_TYPE mBuf; 00185 PVOID BundleAddress; 00186 00187 // change template to type 0 if current instruction is MLI 00188 00189 // read in intruction template if current instruction is NOT slot 0. 00190 // check for two-slot MOVL instruction. Reject request if attempt to 00191 // set break in slot 2 of MLI template. 00192 00193 if (((ULONG_PTR)Address & 0xf) != 0) { 00194 (ULONG_PTR)BundleAddress = (ULONG_PTR)Address & ~(0xf); 00195 if (KdpMoveMemory( 00196 (PCHAR)&mBuf, 00197 (PCHAR)BundleAddress, 00198 sizeof(KDP_BREAKPOINT_TYPE) 00199 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00200 DPRINT(("KD: read 0x%08x template failed\n", BundleAddress)); 00201 return 0; 00202 } else { 00203 if (((mBuf & INST_TEMPL_MASK) >> 1) == 0x2) { 00204 if (((ULONG_PTR)Address & 0xf) == 4) { 00205 // if template= type 2 MLI, change to type 0 00206 mBuf &= ~((INST_TEMPL_MASK >> 1) << 1); 00207 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IA64_MOVL; 00208 if (KdpMoveMemory( 00209 (PCHAR)BundleAddress, 00210 (PCHAR)&mBuf, 00211 sizeof(KDP_BREAKPOINT_TYPE) 00212 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00213 DPRINT(("KD: write to 0x%08x template failed\n", BundleAddress)); 00214 return 0; 00215 } 00216 else { 00217 //DPRINT(("KD: change MLI template to type 0 at 0x%08x set\n", Address)); 00218 } 00219 } else { 00220 // set breakpoint at slot 2 of MOVL is illegal 00221 DPRINT(("KD: illegal to set BP at slot 2 of MOVL at 0x%08x\n", BundleAddress)); 00222 return 0; 00223 } 00224 } 00225 } 00226 } 00227 00228 // insert break instruction 00229 00230 KdpBreakpointTable[Index].Address = Address; 00231 KdpBreakpointTable[Index].Content = Content; 00232 KdpBreakpointTable[Index].Flags &= ~(KD_BREAKPOINT_STATE_MASK); 00233 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IN_USE; 00234 if (Address < (PVOID)GLOBAL_BREAKPOINT_LIMIT) { 00235 KdpBreakpointTable[Index].DirectoryTableBase = 00236 KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0]; 00237 } 00238 switch ((ULONG_PTR)Address & 0xf) { 00239 case 0: 00240 Content = (Content & ~(INST_SLOT0_MASK)) | (KdpBreakpointInstruction << 5); 00241 break; 00242 00243 case 4: 00244 Content = (Content & ~(INST_SLOT1_MASK)) | (KdpBreakpointInstruction << 14); 00245 break; 00246 00247 case 8: 00248 Content = (Content & ~(INST_SLOT2_MASK)) | (KdpBreakpointInstruction << 23); 00249 break; 00250 00251 default: 00252 DPRINT(("KD: KdpAddBreakpoint bad instruction slot#\n")); 00253 return 0; 00254 } 00255 if (KdpMoveMemory( 00256 (PCHAR)Address, 00257 (PCHAR)&Content, 00258 sizeof(KDP_BREAKPOINT_TYPE) 00259 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00260 00261 DPRINT(("KD: KdpMoveMemory failed writing BP!\n")); 00262 return 0; 00263 } 00264 else { 00265 //DPRINT(("KD: breakpoint at 0x%08x set\n", Address)); 00266 } 00267 00268 } else { // memory not accessible 00269 KdpBreakpointTable[Index].Address = Address; 00270 KdpBreakpointTable[Index].Flags &= ~(KD_BREAKPOINT_STATE_MASK); 00271 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IN_USE; 00272 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE; 00273 KdpOweBreakpoint = TRUE; 00274 //DPRINT(("KD: breakpoint write deferred\n")); 00275 if (Address < (PVOID)GLOBAL_BREAKPOINT_LIMIT) { 00276 KdpBreakpointTable[Index].DirectoryTableBase = 00277 KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0]; 00278 } 00279 } 00280 #else 00281 if ( Accessible ) { 00282 KdpBreakpointTable[Index].Address = Address; 00283 KdpBreakpointTable[Index].Content = Content; 00284 KdpBreakpointTable[Index].Flags = KD_BREAKPOINT_IN_USE; 00285 if (Address < (PVOID)GLOBAL_BREAKPOINT_LIMIT) { 00286 KdpBreakpointTable[Index].DirectoryTableBase = 00287 KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0]; 00288 } 00289 if (KdpMoveMemory( 00290 (PCHAR)Address, 00291 (PCHAR)&KdpBreakpointInstruction, 00292 sizeof(KDP_BREAKPOINT_TYPE) 00293 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00294 00295 DPRINT(("KD: KdpMoveMemory failed writing BP!\n")); 00296 } 00297 } else { 00298 KdpBreakpointTable[Index].Address = Address; 00299 KdpBreakpointTable[Index].Flags = KD_BREAKPOINT_IN_USE | KD_BREAKPOINT_NEEDS_WRITE; 00300 KdpOweBreakpoint = TRUE; 00301 //DPRINT(("KD: breakpoint write deferred\n")); 00302 if (Address < (PVOID)GLOBAL_BREAKPOINT_LIMIT) { 00303 KdpBreakpointTable[Index].DirectoryTableBase = 00304 KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0]; 00305 } 00306 } 00307 #endif // IA64 00308 00309 return Index + 1; 00310 00311 } 00312 00313 00314 00315 VOID 00316 KdSetOwedBreakpoints( 00317 VOID 00318 ) 00319 00320 /*++ 00321 00322 Routine Description: 00323 00324 This function is called after returning from memory management calls 00325 that may cause an inpage. Its purpose is to store pending 00326 breakpoints in pages just made valid. 00327 00328 Arguments: 00329 00330 None. 00331 00332 Return Value: 00333 00334 None. 00335 00336 --*/ 00337 00338 { 00339 00340 KDP_BREAKPOINT_TYPE Content; 00341 BOOLEAN Enable; 00342 LONG Index; 00343 ULONG_PTR Opaque; 00344 00345 // 00346 // If we don't owe any breakpoints then return 00347 // 00348 00349 if ( !KdpOweBreakpoint ) { 00350 return; 00351 } 00352 00353 00354 // 00355 // Freeze all other processors, disable interrupts, and save debug 00356 // port state. 00357 // 00358 00359 Enable = KdEnterDebugger(NULL, NULL); 00360 KdpOweBreakpoint = FALSE; 00361 00362 // 00363 // Search the breakpoint table for breakpoints that need to be 00364 // written or replaced. 00365 // 00366 00367 for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index += 1) { 00368 if (KdpBreakpointTable[Index].Flags & 00369 (KD_BREAKPOINT_NEEDS_WRITE | KD_BREAKPOINT_NEEDS_REPLACE) ) { 00370 00371 // 00372 // Breakpoint needs to be written 00373 // 00374 //DPRINT(("KD: Breakpoint %d at 0x%08x: trying to %s after page in.\n", 00375 // Index, 00376 // KdpBreakpointTable[Index].Address, 00377 // (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_WRITE) ? 00378 // "set" : "clear")); 00379 00380 if ((KdpBreakpointTable[Index].Address >= (PVOID)GLOBAL_BREAKPOINT_LIMIT) || 00381 (KdpBreakpointTable[Index].DirectoryTableBase == 00382 KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0])) { 00383 00384 // 00385 // Check to see if we have write access to the memory 00386 // 00387 if (MmDbgWriteCheck((PVOID)KdpBreakpointTable[Index].Address, &Opaque) == NULL) { 00388 KdpOweBreakpoint = TRUE; 00389 //DPRINT(("KD: address not writeable.\n")); 00390 break; 00391 } 00392 00393 MmDbgReleaseAddress( 00394 (PVOID)KdpBreakpointTable[Index].Address, 00395 Opaque 00396 ); 00397 00398 // 00399 // Breakpoint is global, or its directory base matches 00400 // 00401 00402 if (KdpMoveMemory( 00403 (PCHAR)&Content, 00404 (PCHAR)KdpBreakpointTable[Index].Address, 00405 sizeof(KDP_BREAKPOINT_TYPE) 00406 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00407 00408 // 00409 // Memory is still inaccessible (is this possible after 00410 // the call above to MmDbgWriteCheck?) 00411 // 00412 00413 DPRINT(("KD: read from 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00414 00415 KdpOweBreakpoint = TRUE; 00416 00417 } else { 00418 if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_WRITE) { 00419 KdpBreakpointTable[Index].Content = Content; 00420 #if defined(_IA64_) 00421 switch ((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) { 00422 case 0: 00423 Content = (Content & ~(INST_SLOT0_MASK)) | (KdpBreakpointInstruction << 5); 00424 break; 00425 00426 case 4: 00427 Content = (Content & ~(INST_SLOT1_MASK)) | (KdpBreakpointInstruction << 14); 00428 break; 00429 00430 case 8: 00431 Content = (Content & ~(INST_SLOT2_MASK)) | (KdpBreakpointInstruction << 23); 00432 break; 00433 00434 default: 00435 DPRINT(("KD: illegal instruction address 0x%08x\n", KdpBreakpointTable[Index].Address)); 00436 return; 00437 } 00438 if (KdpMoveMemory( 00439 (PCHAR)KdpBreakpointTable[Index].Address, 00440 (PCHAR)&Content, 00441 sizeof(KDP_BREAKPOINT_TYPE) 00442 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00443 KdpOweBreakpoint = TRUE; 00444 DPRINT(("KD: write to 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00445 } 00446 00447 // read in intruction template if current instruction is NOT slot 0. 00448 // check for two-slot MOVL instruction. Reject request if attempt to 00449 // set break in slot 2 of MLI template. 00450 00451 else if (((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) != 0) { 00452 KDP_BREAKPOINT_TYPE mBuf; 00453 PVOID BundleAddress; 00454 00455 (ULONG_PTR)BundleAddress = (ULONG_PTR)KdpBreakpointTable[Index].Address & ~(0xf); 00456 if (KdpMoveMemory( 00457 (PCHAR)&mBuf, 00458 (PCHAR)BundleAddress, 00459 sizeof(KDP_BREAKPOINT_TYPE) 00460 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00461 KdpOweBreakpoint = TRUE; 00462 DPRINT(("KD: read 0x%08x template failed\n", KdpBreakpointTable[Index].Address)); 00463 } else { 00464 if (((mBuf & INST_TEMPL_MASK) >> 1) == 0x2) { 00465 if (((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) == 4) { 00466 // if template= type 2 MLI, change to type 0 00467 mBuf &= ~((INST_TEMPL_MASK >> 1) << 1); 00468 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IA64_MOVL; 00469 if (KdpMoveMemory( 00470 (PCHAR)BundleAddress, 00471 (PCHAR)&mBuf, 00472 sizeof(KDP_BREAKPOINT_TYPE) 00473 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00474 KdpOweBreakpoint = TRUE; 00475 DPRINT(("KD: write to 0x%08x template failed\n", KdpBreakpointTable[Index].Address)); 00476 } 00477 else { 00478 KdpBreakpointTable[Index].Flags &= ~(KD_BREAKPOINT_STATE_MASK); 00479 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IN_USE; 00480 //DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address)); 00481 } 00482 } else { 00483 // set breakpoint at slot 2 of MOVL is illegal 00484 KdpOweBreakpoint = TRUE; 00485 DPRINT(("KD: illegal attempt to set BP at slot 2 of 0x%08x\n", KdpBreakpointTable[Index].Address)); 00486 } 00487 } 00488 else { 00489 KdpBreakpointTable[Index].Flags &= ~(KD_BREAKPOINT_STATE_MASK); 00490 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IN_USE; 00491 //DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address)); 00492 } 00493 } 00494 } 00495 #else 00496 if (KdpMoveMemory( 00497 (PCHAR)KdpBreakpointTable[Index].Address, 00498 (PCHAR)&KdpBreakpointInstruction, 00499 sizeof(KDP_BREAKPOINT_TYPE) 00500 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00501 KdpOweBreakpoint = TRUE; 00502 DPRINT(("KD: write to 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00503 } else { 00504 KdpBreakpointTable[Index].Flags = KD_BREAKPOINT_IN_USE; 00505 DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address)); 00506 } 00507 #endif 00508 } else { 00509 #if defined(_IA64_) 00510 00511 KDP_BREAKPOINT_TYPE mBuf; 00512 PVOID BundleAddress; 00513 00514 // restore original instruction content 00515 00516 // Read in memory since adjancent instructions in the same bundle may have 00517 // been modified after we save them. 00518 if (KdpMoveMemory( 00519 (PCHAR)&mBuf, 00520 (PCHAR)KdpBreakpointTable[Index].Address, 00521 sizeof(KDP_BREAKPOINT_TYPE)) != sizeof(KDP_BREAKPOINT_TYPE)) { 00522 KdpOweBreakpoint = TRUE; 00523 DPRINT(("KD: read 0x%08x template failed\n", KdpBreakpointTable[Index].Address)); 00524 } 00525 else { 00526 switch ((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) { 00527 case 0: 00528 mBuf = (mBuf & ~(INST_SLOT0_MASK)) 00529 | (KdpBreakpointTable[Index].Content & INST_SLOT0_MASK); 00530 break; 00531 00532 case 4: 00533 mBuf = (mBuf & ~(INST_SLOT1_MASK)) 00534 | (KdpBreakpointTable[Index].Content & INST_SLOT1_MASK); 00535 break; 00536 00537 case 8: 00538 mBuf = (mBuf & ~(INST_SLOT2_MASK)) 00539 | (KdpBreakpointTable[Index].Content & INST_SLOT2_MASK); 00540 break; 00541 00542 default: 00543 KdpOweBreakpoint = TRUE; 00544 DPRINT(("KD: illegal instruction address 0x%08x\n", KdpBreakpointTable[Index].Address)); 00545 } 00546 00547 if (KdpMoveMemory( 00548 (PCHAR)KdpBreakpointTable[Index].Address, 00549 (PCHAR)&mBuf, 00550 sizeof(KDP_BREAKPOINT_TYPE)) != sizeof(KDP_BREAKPOINT_TYPE)) { 00551 KdpOweBreakpoint = TRUE; 00552 DPRINT(("KD: write to 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00553 } 00554 else { 00555 // restore template to MLI if displaced instruction was MOVL 00556 00557 if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IA64_MOVL) { 00558 (ULONG_PTR)BundleAddress = (ULONG_PTR)KdpBreakpointTable[Index].Address & ~(0xf); 00559 if (KdpMoveMemory( 00560 (PCHAR)&mBuf, 00561 (PCHAR)BundleAddress, 00562 sizeof(KDP_BREAKPOINT_TYPE) 00563 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00564 KdpOweBreakpoint = TRUE; 00565 DPRINT(("KD: read template 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00566 } 00567 else { 00568 mBuf &= ~((INST_TEMPL_MASK >> 1) << 1); // set template to MLI 00569 mBuf |= 0x4; 00570 00571 if (KdpMoveMemory( 00572 (PCHAR)BundleAddress, 00573 (PCHAR)&mBuf, 00574 sizeof(KDP_BREAKPOINT_TYPE) 00575 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00576 KdpOweBreakpoint = TRUE; 00577 DPRINT(("KD: write template to 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00578 } else { 00579 //DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address)); 00580 if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) { 00581 KdpBreakpointTable[Index].Flags |= (KD_BREAKPOINT_SUSPENDED | KD_BREAKPOINT_IN_USE); 00582 } else { 00583 KdpBreakpointTable[Index].Flags = 0; 00584 } 00585 } 00586 } 00587 } else { 00588 //DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address)); 00589 if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) { 00590 KdpBreakpointTable[Index].Flags |= (KD_BREAKPOINT_SUSPENDED | KD_BREAKPOINT_IN_USE); 00591 } else { 00592 KdpBreakpointTable[Index].Flags = 0; 00593 } 00594 } 00595 } 00596 } 00597 #else 00598 if (KdpMoveMemory( 00599 (PCHAR)KdpBreakpointTable[Index].Address, 00600 (PCHAR)&KdpBreakpointTable[Index].Content, 00601 sizeof(KDP_BREAKPOINT_TYPE) 00602 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00603 KdpOweBreakpoint = TRUE; 00604 DPRINT(("KD: write to 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00605 } else { 00606 //DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address)); 00607 if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) { 00608 KdpBreakpointTable[Index].Flags = KD_BREAKPOINT_SUSPENDED | KD_BREAKPOINT_IN_USE; 00609 } else { 00610 KdpBreakpointTable[Index].Flags = 0; 00611 } 00612 } 00613 #endif // _IA64_ 00614 00615 } 00616 } 00617 00618 } else { 00619 00620 // 00621 // Breakpoint is local and its directory base does not match 00622 // 00623 00624 KdpOweBreakpoint = TRUE; 00625 } 00626 } 00627 } 00628 00629 KdExitDebugger(Enable); 00630 return; 00631 } 00632 00633 00634 BOOLEAN 00635 KdpLowWriteContent ( 00636 IN ULONG Index 00637 ) 00638 00639 /*++ 00640 00641 Routine Description: 00642 00643 This routine attempts to replace the code that a breakpoint is 00644 written over. This routine, KdpAddBreakpoint, 00645 KdpLowRestoreBreakpoint and KdSetOwedBreakpoints are responsible 00646 for getting data written as requested. Callers should not 00647 examine or use KdpOweBreakpoints, and they should not set the 00648 NEEDS_WRITE or NEEDS_REPLACE flags. 00649 00650 Callers must still look at the return value from this function, 00651 however: if it returns FALSE, the breakpoint record must not be 00652 reused until KdSetOwedBreakpoints has finished with it. 00653 00654 Arguments: 00655 00656 Index - Supplies the index of the breakpoint table entry 00657 which is to be deleted. 00658 00659 Return Value: 00660 00661 Returns TRUE if the breakpoint was removed, FALSE if it was deferred. 00662 00663 --*/ 00664 00665 { 00666 #if defined(_IA64_) 00667 KDP_BREAKPOINT_TYPE mBuf; 00668 PVOID BundleAddress; 00669 #endif 00670 00671 // 00672 // Do the contents need to be replaced at all? 00673 // 00674 00675 if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_WRITE) { 00676 00677 // 00678 // The breakpoint was never written out. Clear the flag 00679 // and we are done. 00680 // 00681 00682 KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_NEEDS_WRITE; 00683 //DPRINT(("KD: Breakpoint at 0x%08x never written; flag cleared.\n", 00684 // KdpBreakpointTable[Index].Address)); 00685 return TRUE; 00686 } 00687 00688 #if !defined(_IA64_) 00689 if (KdpBreakpointTable[Index].Content == KdpBreakpointInstruction) { 00690 00691 // 00692 // The instruction is a breakpoint anyway. 00693 // 00694 00695 //DPRINT(("KD: Breakpoint at 0x%08x; instr is really BP; flag cleared.\n", 00696 // KdpBreakpointTable[Index].Address)); 00697 00698 return TRUE; 00699 } 00700 #endif 00701 00702 00703 // 00704 // Restore the instruction contents. 00705 // 00706 00707 #if defined(_IA64_) 00708 // Read in memory since adjancent instructions in the same bundle may have 00709 // been modified after we save them. 00710 if (KdpMoveMemory( 00711 (PCHAR)&mBuf, 00712 (PCHAR)KdpBreakpointTable[Index].Address, 00713 sizeof(KDP_BREAKPOINT_TYPE)) != sizeof(KDP_BREAKPOINT_TYPE)) { 00714 KdpOweBreakpoint = TRUE; 00715 DPRINT(("KD: read 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00716 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_REPLACE; 00717 return FALSE; 00718 } 00719 else { 00720 00721 switch ((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) { 00722 case 0: 00723 mBuf = (mBuf & ~(INST_SLOT0_MASK)) 00724 | (KdpBreakpointTable[Index].Content & INST_SLOT0_MASK); 00725 break; 00726 00727 case 4: 00728 mBuf = (mBuf & ~(INST_SLOT1_MASK)) 00729 | (KdpBreakpointTable[Index].Content & INST_SLOT1_MASK); 00730 break; 00731 00732 case 8: 00733 mBuf = (mBuf & ~(INST_SLOT2_MASK)) 00734 | (KdpBreakpointTable[Index].Content & INST_SLOT2_MASK); 00735 break; 00736 00737 default: 00738 KdpOweBreakpoint = TRUE; 00739 DPRINT(("KD: illegal instruction address 0x%08x\n", KdpBreakpointTable[Index].Address)); 00740 return FALSE; 00741 } 00742 00743 if (KdpMoveMemory( 00744 (PCHAR)KdpBreakpointTable[Index].Address, 00745 (PCHAR)&mBuf, 00746 sizeof(KDP_BREAKPOINT_TYPE)) != sizeof(KDP_BREAKPOINT_TYPE)) { 00747 KdpOweBreakpoint = TRUE; 00748 DPRINT(("KD: write to 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00749 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_REPLACE; 00750 return FALSE; 00751 } 00752 else { 00753 #ifdef _GAMBIT_ 00754 if (KdpMoveMemory( 00755 (PCHAR)&mBuf, 00756 (PCHAR)KdpBreakpointTable[Index].Address, 00757 sizeof(KDP_BREAKPOINT_TYPE)) == sizeof(KDP_BREAKPOINT_TYPE)) { 00758 DPRINT(("\tcontent after memory move = 0x%08x 0x%08x\n", (ULONG)(mBuf >> 32), (ULONG)mBuf)); 00759 } 00760 #endif // _GAMBIT_ 00761 00762 00763 // restore template to MLI if displaced instruction was MOVL 00764 00765 if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IA64_MOVL) { 00766 (ULONG_PTR)BundleAddress = (ULONG_PTR)KdpBreakpointTable[Index].Address & ~(0xf); 00767 if (KdpMoveMemory( 00768 (PCHAR)&mBuf, 00769 (PCHAR)BundleAddress, 00770 sizeof(KDP_BREAKPOINT_TYPE) 00771 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00772 KdpOweBreakpoint = TRUE; 00773 DPRINT(("KD: read template 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00774 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_REPLACE; 00775 return FALSE; 00776 } 00777 else { 00778 mBuf &= ~((INST_TEMPL_MASK >> 1) << 1); // set template to MLI 00779 mBuf |= 0x4; 00780 00781 if (KdpMoveMemory( 00782 (PCHAR)BundleAddress, 00783 (PCHAR)&mBuf, 00784 sizeof(KDP_BREAKPOINT_TYPE) 00785 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00786 KdpOweBreakpoint = TRUE; 00787 DPRINT(("KD: write template to 0x%08x failed\n", KdpBreakpointTable[Index].Address)); 00788 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_REPLACE; 00789 return FALSE; 00790 } else { 00791 //DPRINT(("KD: Breakpoint at 0x%08x cleared.\n", 00792 // KdpBreakpointTable[Index].Address)); 00793 return TRUE; 00794 } 00795 } 00796 } 00797 else { // not MOVL 00798 //DPRINT(("KD: Breakpoint at 0x%08x cleared.\n", 00799 // KdpBreakpointTable[Index].Address)); 00800 return TRUE; 00801 } 00802 } 00803 } 00804 #else 00805 if (KdpMoveMemory( (PCHAR)KdpBreakpointTable[Index].Address, 00806 (PCHAR)&KdpBreakpointTable[Index].Content, 00807 sizeof(KDP_BREAKPOINT_TYPE) ) != sizeof(KDP_BREAKPOINT_TYPE)) { 00808 00809 KdpOweBreakpoint = TRUE; 00810 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_REPLACE; 00811 //DPRINT(("KD: Breakpoint at 0x%08x; unable to clear, flag set.\n", 00812 //KdpBreakpointTable[Index].Address)); 00813 return FALSE; 00814 } else { 00815 //DPRINT(("KD: Breakpoint at 0x%08x cleared.\n", 00816 //KdpBreakpointTable[Index].Address)); 00817 return TRUE; 00818 } 00819 #endif 00820 00821 } 00822 00823 00824 00825 BOOLEAN 00826 KdpDeleteBreakpoint ( 00827 IN ULONG Handle 00828 ) 00829 00830 /*++ 00831 00832 Routine Description: 00833 00834 This routine deletes an entry from the breakpoint table. 00835 00836 Arguments: 00837 00838 Handle - Supplies the index plus one of the breakpoint table entry 00839 which is to be deleted. 00840 00841 Return Value: 00842 00843 A value of FALSE is returned if the specified handle is not a valid 00844 value or the breakpoint cannot be deleted because the old instruction 00845 cannot be replaced. Otherwise, a value of TRUE is returned. 00846 00847 --*/ 00848 00849 { 00850 ULONG Index = Handle - 1; 00851 00852 // 00853 // If the specified handle is not valid, then return FALSE. 00854 // 00855 00856 if ((Handle == 0) || (Handle > BREAKPOINT_TABLE_SIZE)) { 00857 DPRINT(("KD: Breakpoint %d invalid.\n", Index)); 00858 return FALSE; 00859 } 00860 00861 // 00862 // If the specified breakpoint table entry is not valid, then return FALSE. 00863 // 00864 00865 if (KdpBreakpointTable[Index].Flags == 0) { 00866 //DPRINT(("KD: Breakpoint %d already clear.\n", Index)); 00867 return FALSE; 00868 } 00869 00870 // 00871 // If the breakpoint is already suspended, just delete it from the table. 00872 // 00873 00874 if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) { 00875 //DPRINT(("KD: Deleting suspended breakpoint %d \n", Index)); 00876 if ( !(KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_REPLACE) ) { 00877 //DPRINT(("KD: already clear.\n")); 00878 KdpBreakpointTable[Index].Flags = 0; 00879 return TRUE; 00880 } 00881 } 00882 00883 // 00884 // Replace the instruction contents. 00885 // 00886 00887 if (KdpLowWriteContent(Index)) { 00888 00889 // 00890 // Delete breakpoint table entry 00891 // 00892 00893 //DPRINT(("KD: Breakpoint %d deleted successfully.\n", Index)); 00894 KdpBreakpointTable[Index].Flags = 0; 00895 } 00896 00897 return TRUE; 00898 } 00899 00900 00901 BOOLEAN 00902 KdpDeleteBreakpointRange ( 00903 IN PVOID Lower, 00904 IN PVOID Upper 00905 ) 00906 00907 /*++ 00908 00909 Routine Description: 00910 00911 This routine deletes all breakpoints falling in a given range 00912 from the breakpoint table. 00913 00914 Arguments: 00915 00916 Lower - inclusive lower address of range from which to remove BPs. 00917 00918 Upper - include upper address of range from which to remove BPs. 00919 00920 Return Value: 00921 00922 TRUE if any breakpoints removed, FALSE otherwise. 00923 00924 --*/ 00925 00926 { 00927 ULONG Index; 00928 BOOLEAN ReturnStatus = FALSE; 00929 00930 // 00931 // Examine each entry in the table in turn 00932 // 00933 00934 for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++) { 00935 00936 if ( (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) && 00937 ((KdpBreakpointTable[Index].Address >= Lower) && 00938 (KdpBreakpointTable[Index].Address <= Upper)) 00939 ) { 00940 00941 // 00942 // Breakpoint is in use and falls in range, clear it. 00943 // 00944 00945 ReturnStatus = ReturnStatus || KdpDeleteBreakpoint(Index+1); 00946 } 00947 } 00948 00949 return ReturnStatus; 00950 00951 } 00952 00953 VOID 00954 KdpSuspendBreakpoint ( 00955 ULONG Handle 00956 ) 00957 { 00958 ULONG Index = Handle - 1; 00959 00960 if ( (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) && 00961 !(KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) ) { 00962 00963 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_SUSPENDED; 00964 KdpLowWriteContent(Index); 00965 } 00966 00967 return; 00968 00969 } // KdpSuspendBreakpoint 00970 00971 VOID 00972 KdpSuspendAllBreakpoints ( 00973 VOID 00974 ) 00975 { 00976 ULONG Handle; 00977 00978 BreakpointsSuspended = TRUE; 00979 00980 for ( Handle = 1; Handle <= BREAKPOINT_TABLE_SIZE; Handle++ ) { 00981 KdpSuspendBreakpoint(Handle); 00982 } 00983 00984 return; 00985 00986 } // KdpSuspendAllBreakpoints 00987 00988 #if defined(_IA64_) 00989 00990 00991 BOOLEAN 00992 KdpSuspendBreakpointRange ( 00993 IN PVOID Lower, 00994 IN PVOID Upper 00995 ) 00996 00997 /*++ 00998 00999 Routine Description: 01000 01001 This routine suspend all breakpoints falling in a given range 01002 from the breakpoint table. 01003 01004 Arguments: 01005 01006 Lower - inclusive lower address of range from which to suspend BPs. 01007 01008 Upper - include upper address of range from which to suspend BPs. 01009 01010 Return Value: 01011 01012 TRUE if any breakpoints suspended, FALSE otherwise. 01013 01014 Notes: 01015 The order of suspending breakpoints is opposite that of setting 01016 them in KdpAddBreakpoint() in case of duplicate addresses. 01017 01018 --*/ 01019 01020 { 01021 ULONG Index; 01022 BOOLEAN ReturnStatus = FALSE; 01023 01024 DPRINT(("\nKD: entering KdpSuspendBreakpointRange() at 0x%08x 0x%08x\n", Lower, Upper)); 01025 01026 // 01027 // Examine each entry in the table in turn 01028 // 01029 01030 for (Index = BREAKPOINT_TABLE_SIZE - 1; Index != -1; Index--) { 01031 01032 if ( (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) && 01033 ((KdpBreakpointTable[Index].Address >= Lower) && 01034 (KdpBreakpointTable[Index].Address <= Upper)) 01035 ) { 01036 01037 // 01038 // Breakpoint is in use and falls in range, suspend it. 01039 // 01040 01041 KdpSuspendBreakpoint(Index+1); 01042 ReturnStatus = TRUE; 01043 } 01044 } 01045 DPRINT(("KD: exiting KdpSuspendBreakpointRange() return 0x%d\n", ReturnStatus)); 01046 01047 return ReturnStatus; 01048 01049 } // KdpSuspendBreakpointRange 01050 01051 01052 01053 BOOLEAN 01054 KdpRestoreBreakpointRange ( 01055 IN PVOID Lower, 01056 IN PVOID Upper 01057 ) 01058 01059 /*++ 01060 01061 Routine Description: 01062 01063 This routine writes back breakpoints falling in a given range 01064 from the breakpoint table. 01065 01066 Arguments: 01067 01068 Lower - inclusive lower address of range from which to rewrite BPs. 01069 01070 Upper - include upper address of range from which to rewrite BPs. 01071 01072 Return Value: 01073 01074 TRUE if any breakpoints written, FALSE otherwise. 01075 01076 Notes: 01077 The order of writing breakpoints is opposite that of removing 01078 them in KdpSuspendBreakpointRange() in case of duplicate addresses. 01079 01080 --*/ 01081 01082 { 01083 ULONG Index; 01084 BOOLEAN ReturnStatus = FALSE; 01085 01086 DPRINT(("\nKD: entering KdpRestoreBreakpointRange() at 0x%08x 0x%08x\n", Lower, Upper)); 01087 01088 // 01089 // Examine each entry in the table in turn 01090 // 01091 01092 for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++) { 01093 01094 if ( (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) && 01095 ((KdpBreakpointTable[Index].Address >= Lower) && 01096 (KdpBreakpointTable[Index].Address <= Upper)) 01097 ) { 01098 01099 // 01100 // suspended breakpoint that falls in range, unsuspend it. 01101 // 01102 01103 if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) { 01104 01105 KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_SUSPENDED; 01106 ReturnStatus = ReturnStatus || KdpLowRestoreBreakpoint(Index); 01107 } 01108 } 01109 } 01110 01111 DPRINT(("KD: exiting KdpRestoreBreakpointRange() return 0x%d\n", ReturnStatus)); 01112 01113 return ReturnStatus; 01114 01115 } // KdpRestoreBreakpointRange 01116 01117 #endif // _IA64_ 01118 01119 01120 BOOLEAN 01121 KdpLowRestoreBreakpoint ( 01122 IN ULONG Index 01123 ) 01124 01125 /*++ 01126 01127 Routine Description: 01128 01129 This routine attempts to write a breakpoint instruction. 01130 The old contents must have already been stored in the 01131 breakpoint record. 01132 01133 Arguments: 01134 01135 Index - Supplies the index of the breakpoint table entry 01136 which is to be written. 01137 01138 Return Value: 01139 01140 Returns TRUE if the breakpoint was written, FALSE if it was 01141 not and has been marked for writing later. 01142 01143 --*/ 01144 01145 { 01146 KDP_BREAKPOINT_TYPE Content; 01147 01148 #if defined(_IA64_) 01149 KDP_BREAKPOINT_TYPE mBuf; 01150 PVOID BundleAddress; 01151 #endif 01152 // 01153 // Does the breakpoint need to be written at all? 01154 // 01155 01156 if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_REPLACE) { 01157 01158 // 01159 // The breakpoint was never removed. Clear the flag 01160 // and we are done. 01161 // 01162 01163 KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_NEEDS_REPLACE; 01164 return TRUE; 01165 } 01166 01167 if (KdpBreakpointTable[Index].Content == KdpBreakpointInstruction) { 01168 01169 // 01170 // The instruction is a breakpoint anyway. 01171 // 01172 01173 return TRUE; 01174 } 01175 01176 // 01177 // Replace the instruction contents. 01178 // 01179 01180 #if !defined(_IA64_) 01181 if (KdpBreakpointTable[Index].Content == KdpBreakpointInstruction) { 01182 01183 // 01184 // The instruction is a breakpoint anyway. 01185 // 01186 01187 return TRUE; 01188 } 01189 #endif 01190 01191 // 01192 // Replace the instruction contents. 01193 // 01194 01195 #if defined(_IA64_) 01196 01197 // read in intruction in case the adjacent instruction has been modified. 01198 01199 if (KdpMoveMemory( 01200 (PCHAR)&mBuf, 01201 (PCHAR)KdpBreakpointTable[Index].Address, 01202 sizeof(KDP_BREAKPOINT_TYPE) 01203 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 01204 DPRINT(("KD: read 0x%p template failed\n", KdpBreakpointTable[Index].Address)); 01205 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE; 01206 KdpOweBreakpoint = TRUE; 01207 return FALSE; 01208 } 01209 01210 switch ((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) { 01211 case 0: 01212 mBuf = (mBuf & ~(INST_SLOT0_MASK)) | (KdpBreakpointInstruction << 5); 01213 break; 01214 01215 case 4: 01216 mBuf = (mBuf & ~(INST_SLOT1_MASK)) | (KdpBreakpointInstruction << 14); 01217 break; 01218 01219 case 8: 01220 mBuf = (mBuf & ~(INST_SLOT2_MASK)) | (KdpBreakpointInstruction << 23); 01221 break; 01222 01223 default: 01224 DPRINT(("KD: KdpAddBreakpoint bad instruction slot#\n")); 01225 return FALSE; 01226 } 01227 if (KdpMoveMemory( 01228 (PCHAR)KdpBreakpointTable[Index].Address, 01229 (PCHAR)&mBuf, 01230 sizeof(KDP_BREAKPOINT_TYPE) 01231 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 01232 01233 DPRINT(("KD: KdpMoveMemory failed writing BP!\n")); 01234 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE; 01235 KdpOweBreakpoint = TRUE; 01236 return FALSE; 01237 } 01238 else { 01239 01240 // check for two-slot MOVL instruction. Reject request if attempt to 01241 // set break in slot 2 of MLI template. 01242 // change template to type 0 if current instruction is MLI 01243 01244 if (((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) != 0) { 01245 (ULONG_PTR)BundleAddress = (ULONG_PTR)KdpBreakpointTable[Index].Address & ~(0xf); 01246 if (KdpMoveMemory( 01247 (PCHAR)&mBuf, 01248 (PCHAR)BundleAddress, 01249 sizeof(KDP_BREAKPOINT_TYPE) 01250 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 01251 DPRINT(("KD: read template failed at 0x%08x\n", BundleAddress)); 01252 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE; 01253 KdpOweBreakpoint = TRUE; 01254 return FALSE; 01255 } 01256 else { 01257 if (((mBuf & INST_TEMPL_MASK) >> 1) == 0x2) { 01258 if (((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) == 4) { 01259 // if template= type 2 MLI, change to type 0 01260 mBuf &= ~((INST_TEMPL_MASK >> 1) << 1); 01261 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IA64_MOVL; 01262 if (KdpMoveMemory( 01263 (PCHAR)BundleAddress, 01264 (PCHAR)&mBuf, 01265 sizeof(KDP_BREAKPOINT_TYPE) 01266 ) != sizeof(KDP_BREAKPOINT_TYPE)) { 01267 DPRINT(("KD: write to 0x%08x template failed\n", BundleAddress)); 01268 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE; 01269 KdpOweBreakpoint = TRUE; 01270 return FALSE; 01271 } 01272 else { 01273 //DPRINT(("KD: change MLI template to type 0 at 0x%08x set\n", Address)); 01274 } 01275 } else { 01276 // set breakpoint at slot 2 of MOVL is illegal 01277 DPRINT(("KD: illegal to set BP at slot 2 of MOVL at 0x%08x\n", BundleAddress)); 01278 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE; 01279 KdpOweBreakpoint = TRUE; 01280 return FALSE; 01281 } 01282 } 01283 } 01284 } 01285 //DPRINT(("KD: breakpoint at 0x%08x set\n", Address)); 01286 return TRUE; 01287 } 01288 01289 #else 01290 if (KdpMoveMemory( (PCHAR)KdpBreakpointTable[Index].Address, 01291 (PCHAR)&KdpBreakpointInstruction, 01292 sizeof(KDP_BREAKPOINT_TYPE) ) != sizeof(KDP_BREAKPOINT_TYPE)) { 01293 01294 KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE; 01295 KdpOweBreakpoint = TRUE; 01296 return FALSE; 01297 01298 } else { 01299 01300 KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_NEEDS_WRITE; 01301 return TRUE; 01302 } 01303 #endif 01304 01305 } 01306 01307 01308 VOID 01309 KdpRestoreAllBreakpoints ( 01310 VOID 01311 ) 01312 { 01313 ULONG Index; 01314 01315 BreakpointsSuspended = FALSE; 01316 01317 for ( Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++ ) { 01318 01319 if ((KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) && 01320 (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) ) { 01321 01322 KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_SUSPENDED; 01323 KdpLowRestoreBreakpoint(Index); 01324 } 01325 } 01326 01327 return; 01328 01329 } // KdpRestoreAllBreakpoints 01330 01331 VOID 01332 KdDeleteAllBreakpoints( 01333 VOID 01334 ) 01335 { 01336 ULONG Handle; 01337 01338 if (KdDebuggerEnabled == FALSE || KdPitchDebugger != FALSE) { 01339 return; 01340 } 01341 01342 BreakpointsSuspended = FALSE; 01343 01344 for ( Handle = 1; Handle <= BREAKPOINT_TABLE_SIZE; Handle++ ) { 01345 KdpDeleteBreakpoint(Handle); 01346 } 01347 01348 return; 01349 } // KdDeleteAllBreakpoints

Generated on Sat May 15 19:40:34 2004 for test by doxygen 1.3.7