Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1295 lines
43 KiB

  1. /*++
  2. Copyright (c) 1990-2001 Microsoft Corporation
  3. Module Name:
  4. kdbreak.c
  5. Abstract:
  6. This module implements machine dependent functions to add and delete
  7. breakpoints from the kernel debugger breakpoint table.
  8. Author:
  9. David N. Cutler 2-Aug-1990
  10. Revision History:
  11. --*/
  12. #include "kdp.h"
  13. //
  14. // Define external references.
  15. //
  16. VOID
  17. KdSetOwedBreakpoints(
  18. VOID
  19. );
  20. BOOLEAN
  21. KdpLowWriteContent(
  22. ULONG Index
  23. );
  24. BOOLEAN
  25. KdpLowRestoreBreakpoint(
  26. ULONG Index
  27. );
  28. #ifdef ALLOC_PRAGMA
  29. #pragma alloc_text(PAGEKD, KdpAddBreakpoint)
  30. #pragma alloc_text(PAGEKD, KdpDeleteBreakpoint)
  31. #pragma alloc_text(PAGEKD, KdpDeleteBreakpointRange)
  32. #pragma alloc_text(PAGEKD, KdpSuspendBreakpoint)
  33. #pragma alloc_text(PAGEKD, KdpSuspendAllBreakpoints)
  34. #pragma alloc_text(PAGEKD, KdpRestoreAllBreakpoints)
  35. #pragma alloc_text(PAGEKD, KdpLowWriteContent)
  36. #pragma alloc_text(PAGEKD, KdpLowRestoreBreakpoint)
  37. #if defined(_IA64_)
  38. #pragma alloc_text(PAGEKD, KdpSuspendBreakpointRange)
  39. #pragma alloc_text(PAGEKD, KdpRestoreBreakpointRange)
  40. #endif
  41. #endif
  42. ULONG
  43. KdpAddBreakpoint (
  44. IN PVOID Address
  45. )
  46. /*++
  47. Routine Description:
  48. This routine adds an entry to the breakpoint table and returns a handle
  49. to the breakpoint table entry.
  50. Arguments:
  51. Address - Supplies the address where to set the breakpoint.
  52. Return Value:
  53. A value of zero is returned if the specified address is already in the
  54. breakpoint table, there are no free entries in the breakpoint table, the
  55. specified address is not correctly aligned, or the specified address is
  56. not valid. Otherwise, the index of the assigned breakpoint table entry
  57. plus one is returned as the function value.
  58. --*/
  59. {
  60. KDP_BREAKPOINT_TYPE Content;
  61. ULONG Index;
  62. BOOLEAN Accessible;
  63. //DPRINT(("KD: Setting breakpoint at 0x%08x\n", Address));
  64. //
  65. // If the specified address is not properly aligned, then return zero.
  66. //
  67. if (((ULONG_PTR)Address & KDP_BREAKPOINT_ALIGN) != 0) {
  68. return 0;
  69. }
  70. //
  71. // Don't allow setting the same breakpoint twice.
  72. //
  73. for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index += 1) {
  74. if ((KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) != 0 &&
  75. KdpBreakpointTable[Index].Address == Address) {
  76. if ((KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_REPLACE) != 0) {
  77. //
  78. // Breakpoint was set, the page was written out and was not
  79. // accessible when the breakpoint was cleared. Now the breakpoint
  80. // is being set again. Just clear the defer flag:
  81. //
  82. KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_NEEDS_REPLACE;
  83. return Index + 1;
  84. } else {
  85. DPRINT(("KD: Attempt to set breakpoint %08x twice!\n", Address));
  86. return 0;
  87. }
  88. }
  89. }
  90. //
  91. // Search the breakpoint table for a free entry.
  92. //
  93. for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index += 1) {
  94. if (KdpBreakpointTable[Index].Flags == 0) {
  95. break;
  96. }
  97. }
  98. //
  99. // If a free entry was found, then write breakpoint and return the handle
  100. // value plus one. Otherwise, return zero.
  101. //
  102. if (Index == BREAKPOINT_TABLE_SIZE) {
  103. DPRINT(("KD: ran out of breakpoints!\n"));
  104. return 0;
  105. }
  106. //DPRINT(("KD: using Index %d\n", Index));
  107. //
  108. // Get the instruction to be replaced. If the instruction cannot be read,
  109. // then mark breakpoint as not accessible.
  110. //
  111. Accessible = NT_SUCCESS(KdpCopyFromPtr(&Content,
  112. Address,
  113. sizeof(KDP_BREAKPOINT_TYPE),
  114. NULL));
  115. //DPRINT(("KD: memory %saccessible\n", Accessible ? "" : "in"));
  116. #if defined(_IA64_)
  117. if ( Accessible ) {
  118. KDP_BREAKPOINT_TYPE mBuf;
  119. PVOID BundleAddress;
  120. // change template to type 0 if current instruction is MLI
  121. // read in intruction template if current instruction is NOT slot 0.
  122. // check for two-slot MOVL instruction. Reject request if attempt to
  123. // set break in slot 2 of MLI template.
  124. if (((ULONG_PTR)Address & 0xf) != 0) {
  125. (ULONG_PTR)BundleAddress = (ULONG_PTR)Address & ~(0xf);
  126. if (!NT_SUCCESS(KdpCopyFromPtr(&mBuf,
  127. BundleAddress,
  128. sizeof(KDP_BREAKPOINT_TYPE),
  129. NULL))) {
  130. //DPRINT(("KD: read 0x%08x template failed\n", BundleAddress));
  131. return 0;
  132. } else {
  133. if (((mBuf & INST_TEMPL_MASK) >> 1) == 0x2) {
  134. if (((ULONG_PTR)Address & 0xf) == 4) {
  135. // if template= type 2 MLI, change to type 0
  136. mBuf &= ~((INST_TEMPL_MASK >> 1) << 1);
  137. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IA64_MOVL;
  138. if (!NT_SUCCESS(KdpCopyToPtr(BundleAddress,
  139. &mBuf,
  140. sizeof(KDP_BREAKPOINT_TYPE),
  141. NULL))) {
  142. //DPRINT(("KD: write to 0x%08x template failed\n", BundleAddress));
  143. return 0;
  144. }
  145. else {
  146. //DPRINT(("KD: change MLI template to type 0 at 0x%08x set\n", Address));
  147. }
  148. } else {
  149. // set breakpoint at slot 2 of MOVL is illegal
  150. //DPRINT(("KD: illegal to set BP at slot 2 of MOVL at 0x%08x\n", BundleAddress));
  151. return 0;
  152. }
  153. }
  154. }
  155. }
  156. // insert break instruction
  157. KdpBreakpointTable[Index].Address = Address;
  158. KdpBreakpointTable[Index].Content = Content;
  159. KdpBreakpointTable[Index].Flags &= ~(KD_BREAKPOINT_STATE_MASK);
  160. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IN_USE;
  161. if (Address < (PVOID)GLOBAL_BREAKPOINT_LIMIT) {
  162. KdpBreakpointTable[Index].DirectoryTableBase =
  163. KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0];
  164. }
  165. switch ((ULONG_PTR)Address & 0xf) {
  166. case 0:
  167. Content = (Content & ~(INST_SLOT0_MASK)) | (KdpBreakpointInstruction << 5);
  168. break;
  169. case 4:
  170. Content = (Content & ~(INST_SLOT1_MASK)) | (KdpBreakpointInstruction << 14);
  171. break;
  172. case 8:
  173. Content = (Content & ~(INST_SLOT2_MASK)) | (KdpBreakpointInstruction << 23);
  174. break;
  175. default:
  176. //DPRINT(("KD: KdpAddBreakpoint bad instruction slot#\n"));
  177. return 0;
  178. }
  179. if (!NT_SUCCESS(KdpCopyToPtr(Address,
  180. &Content,
  181. sizeof(KDP_BREAKPOINT_TYPE),
  182. NULL))) {
  183. //DPRINT(("KD: Unable to write BP!\n"));
  184. return 0;
  185. }
  186. else {
  187. //DPRINT(("KD: breakpoint at 0x%08x set\n", Address));
  188. }
  189. } else { // memory not accessible
  190. KdpBreakpointTable[Index].Address = Address;
  191. KdpBreakpointTable[Index].Flags &= ~(KD_BREAKPOINT_STATE_MASK);
  192. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IN_USE;
  193. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE;
  194. KdpOweBreakpoint = TRUE;
  195. //DPRINT(("KD: breakpoint write deferred\n"));
  196. if (Address < (PVOID)GLOBAL_BREAKPOINT_LIMIT) {
  197. KdpBreakpointTable[Index].DirectoryTableBase =
  198. KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0];
  199. }
  200. }
  201. #else
  202. if ( Accessible ) {
  203. KdpBreakpointTable[Index].Address = Address;
  204. KdpBreakpointTable[Index].Content = Content;
  205. KdpBreakpointTable[Index].Flags = KD_BREAKPOINT_IN_USE;
  206. if (Address < (PVOID)GLOBAL_BREAKPOINT_LIMIT) {
  207. KdpBreakpointTable[Index].DirectoryTableBase =
  208. KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0];
  209. }
  210. if (!NT_SUCCESS(KdpCopyToPtr(Address,
  211. &KdpBreakpointInstruction,
  212. sizeof(KDP_BREAKPOINT_TYPE),
  213. NULL))) {
  214. DPRINT(("KD: Unable to write BP!\n"));
  215. }
  216. } else {
  217. KdpBreakpointTable[Index].Address = Address;
  218. KdpBreakpointTable[Index].Flags = KD_BREAKPOINT_IN_USE | KD_BREAKPOINT_NEEDS_WRITE;
  219. KdpOweBreakpoint = TRUE;
  220. //DPRINT(("KD: breakpoint write deferred\n"));
  221. if (Address < (PVOID)GLOBAL_BREAKPOINT_LIMIT) {
  222. KdpBreakpointTable[Index].DirectoryTableBase =
  223. KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0];
  224. }
  225. }
  226. #endif // IA64
  227. return Index + 1;
  228. }
  229. VOID
  230. KdSetOwedBreakpoints(
  231. VOID
  232. )
  233. /*++
  234. Routine Description:
  235. This function is called after returning from memory management calls
  236. that may cause an inpage. Its purpose is to store pending
  237. breakpoints in pages just made valid.
  238. Arguments:
  239. None.
  240. Return Value:
  241. None.
  242. --*/
  243. {
  244. KDP_BREAKPOINT_TYPE Content;
  245. BOOLEAN Enable;
  246. LONG Index;
  247. //
  248. // If we don't owe any breakpoints then return
  249. //
  250. if ( !KdpOweBreakpoint ) {
  251. return;
  252. }
  253. //
  254. // Freeze all other processors, disable interrupts, and save debug
  255. // port state.
  256. //
  257. Enable = KdEnterDebugger(NULL, NULL);
  258. KdpOweBreakpoint = FALSE;
  259. //
  260. // Search the breakpoint table for breakpoints that need to be
  261. // written or replaced.
  262. //
  263. for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index += 1) {
  264. if (KdpBreakpointTable[Index].Flags &
  265. (KD_BREAKPOINT_NEEDS_WRITE | KD_BREAKPOINT_NEEDS_REPLACE) ) {
  266. //
  267. // Breakpoint needs to be written
  268. //
  269. //DPRINT(("KD: Breakpoint %d at 0x%08x: trying to %s after page in.\n",
  270. // Index,
  271. // KdpBreakpointTable[Index].Address,
  272. // (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_WRITE) ?
  273. // "set" : "clear"));
  274. if ((KdpBreakpointTable[Index].Address >= (PVOID)GLOBAL_BREAKPOINT_LIMIT) ||
  275. (KdpBreakpointTable[Index].DirectoryTableBase ==
  276. KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0])) {
  277. //
  278. // Breakpoint is global, or its directory base matches
  279. //
  280. if (!NT_SUCCESS(KdpCopyFromPtr(&Content,
  281. KdpBreakpointTable[Index].Address,
  282. sizeof(KDP_BREAKPOINT_TYPE),
  283. NULL))) {
  284. //DPRINT(("KD: read from 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  285. KdpOweBreakpoint = TRUE;
  286. } else {
  287. if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_WRITE) {
  288. KdpBreakpointTable[Index].Content = Content;
  289. #if defined(_IA64_)
  290. switch ((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) {
  291. case 0:
  292. Content = (Content & ~(INST_SLOT0_MASK)) | (KdpBreakpointInstruction << 5);
  293. break;
  294. case 4:
  295. Content = (Content & ~(INST_SLOT1_MASK)) | (KdpBreakpointInstruction << 14);
  296. break;
  297. case 8:
  298. Content = (Content & ~(INST_SLOT2_MASK)) | (KdpBreakpointInstruction << 23);
  299. break;
  300. default:
  301. //DPRINT(("KD: illegal instruction address 0x%08x\n", KdpBreakpointTable[Index].Address));
  302. break;
  303. }
  304. if (!NT_SUCCESS(KdpCopyToPtr(KdpBreakpointTable[Index].Address,
  305. &Content,
  306. sizeof(KDP_BREAKPOINT_TYPE),
  307. NULL))) {
  308. KdpOweBreakpoint = TRUE;
  309. //DPRINT(("KD: write to 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  310. }
  311. // read in intruction template if current instruction is NOT slot 0.
  312. // check for two-slot MOVL instruction. Reject request if attempt to
  313. // set break in slot 2 of MLI template.
  314. else if (((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) != 0) {
  315. KDP_BREAKPOINT_TYPE mBuf;
  316. PVOID BundleAddress;
  317. (ULONG_PTR)BundleAddress = (ULONG_PTR)KdpBreakpointTable[Index].Address & ~(0xf);
  318. if (!NT_SUCCESS(KdpCopyFromPtr(&mBuf,
  319. BundleAddress,
  320. sizeof(KDP_BREAKPOINT_TYPE),
  321. NULL))) {
  322. KdpOweBreakpoint = TRUE;
  323. //DPRINT(("KD: read 0x%08x template failed\n", KdpBreakpointTable[Index].Address));
  324. } else {
  325. if (((mBuf & INST_TEMPL_MASK) >> 1) == 0x2) {
  326. if (((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) == 4) {
  327. // if template= type 2 MLI, change to type 0
  328. mBuf &= ~((INST_TEMPL_MASK >> 1) << 1);
  329. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IA64_MOVL;
  330. if (!NT_SUCCESS(KdpCopyToPtr(BundleAddress,
  331. &mBuf,
  332. sizeof(KDP_BREAKPOINT_TYPE),
  333. NULL))) {
  334. KdpOweBreakpoint = TRUE;
  335. //DPRINT(("KD: write to 0x%08x template failed\n", KdpBreakpointTable[Index].Address));
  336. }
  337. else {
  338. KdpBreakpointTable[Index].Flags &= ~(KD_BREAKPOINT_STATE_MASK);
  339. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IN_USE;
  340. //DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address));
  341. }
  342. } else {
  343. // set breakpoint at slot 2 of MOVL is illegal
  344. KdpOweBreakpoint = TRUE;
  345. //DPRINT(("KD: illegal attempt to set BP at slot 2 of 0x%08x\n", KdpBreakpointTable[Index].Address));
  346. }
  347. }
  348. else {
  349. KdpBreakpointTable[Index].Flags &= ~(KD_BREAKPOINT_STATE_MASK);
  350. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IN_USE;
  351. //DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address));
  352. }
  353. }
  354. }
  355. #else
  356. if (!NT_SUCCESS(KdpCopyToPtr(KdpBreakpointTable[Index].Address,
  357. &KdpBreakpointInstruction,
  358. sizeof(KDP_BREAKPOINT_TYPE),
  359. NULL))) {
  360. KdpOweBreakpoint = TRUE;
  361. DPRINT(("KD: write to 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  362. } else {
  363. KdpBreakpointTable[Index].Flags = KD_BREAKPOINT_IN_USE;
  364. DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address));
  365. }
  366. #endif
  367. } else {
  368. #if defined(_IA64_)
  369. KDP_BREAKPOINT_TYPE mBuf;
  370. PVOID BundleAddress;
  371. // restore original instruction content
  372. // Read in memory since adjancent instructions in the same bundle may have
  373. // been modified after we save them.
  374. if (!NT_SUCCESS(KdpCopyFromPtr(&mBuf,
  375. KdpBreakpointTable[Index].Address,
  376. sizeof(KDP_BREAKPOINT_TYPE),
  377. NULL))) {
  378. KdpOweBreakpoint = TRUE;
  379. //DPRINT(("KD: read 0x%08x template failed\n", KdpBreakpointTable[Index].Address));
  380. }
  381. else {
  382. switch ((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) {
  383. case 0:
  384. mBuf = (mBuf & ~(INST_SLOT0_MASK))
  385. | (KdpBreakpointTable[Index].Content & INST_SLOT0_MASK);
  386. break;
  387. case 4:
  388. mBuf = (mBuf & ~(INST_SLOT1_MASK))
  389. | (KdpBreakpointTable[Index].Content & INST_SLOT1_MASK);
  390. break;
  391. case 8:
  392. mBuf = (mBuf & ~(INST_SLOT2_MASK))
  393. | (KdpBreakpointTable[Index].Content & INST_SLOT2_MASK);
  394. break;
  395. default:
  396. KdpOweBreakpoint = TRUE;
  397. //DPRINT(("KD: illegal instruction address 0x%08x\n", KdpBreakpointTable[Index].Address));
  398. }
  399. if (!NT_SUCCESS(KdpCopyToPtr(KdpBreakpointTable[Index].Address,
  400. &mBuf,
  401. sizeof(KDP_BREAKPOINT_TYPE),
  402. NULL))) {
  403. KdpOweBreakpoint = TRUE;
  404. //DPRINT(("KD: write to 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  405. }
  406. else {
  407. // restore template to MLI if displaced instruction was MOVL
  408. if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IA64_MOVL) {
  409. (ULONG_PTR)BundleAddress = (ULONG_PTR)KdpBreakpointTable[Index].Address & ~(0xf);
  410. if (!NT_SUCCESS(KdpCopyFromPtr(&mBuf,
  411. BundleAddress,
  412. sizeof(KDP_BREAKPOINT_TYPE),
  413. NULL))) {
  414. KdpOweBreakpoint = TRUE;
  415. //DPRINT(("KD: read template 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  416. }
  417. else {
  418. mBuf &= ~((INST_TEMPL_MASK >> 1) << 1); // set template to MLI
  419. mBuf |= 0x4;
  420. if (!NT_SUCCESS(KdpCopyToPtr(BundleAddress,
  421. &mBuf,
  422. sizeof(KDP_BREAKPOINT_TYPE),
  423. NULL))) {
  424. KdpOweBreakpoint = TRUE;
  425. //DPRINT(("KD: write template to 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  426. } else {
  427. //DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address));
  428. if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) {
  429. KdpBreakpointTable[Index].Flags |= (KD_BREAKPOINT_SUSPENDED | KD_BREAKPOINT_IN_USE);
  430. } else {
  431. KdpBreakpointTable[Index].Flags = 0;
  432. }
  433. }
  434. }
  435. } else {
  436. //DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address));
  437. if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) {
  438. KdpBreakpointTable[Index].Flags |= (KD_BREAKPOINT_SUSPENDED | KD_BREAKPOINT_IN_USE);
  439. } else {
  440. KdpBreakpointTable[Index].Flags = 0;
  441. }
  442. }
  443. }
  444. }
  445. #else
  446. if (!NT_SUCCESS(KdpCopyToPtr(KdpBreakpointTable[Index].Address,
  447. &KdpBreakpointTable[Index].Content,
  448. sizeof(KDP_BREAKPOINT_TYPE),
  449. NULL))) {
  450. KdpOweBreakpoint = TRUE;
  451. DPRINT(("KD: write to 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  452. } else {
  453. //DPRINT(("KD: write to 0x%08x ok\n", KdpBreakpointTable[Index].Address));
  454. if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) {
  455. KdpBreakpointTable[Index].Flags = KD_BREAKPOINT_SUSPENDED | KD_BREAKPOINT_IN_USE;
  456. } else {
  457. KdpBreakpointTable[Index].Flags = 0;
  458. }
  459. }
  460. #endif // _IA64_
  461. }
  462. }
  463. } else {
  464. //
  465. // Breakpoint is local and its directory base does not match
  466. //
  467. KdpOweBreakpoint = TRUE;
  468. }
  469. }
  470. }
  471. KdExitDebugger(Enable);
  472. return;
  473. }
  474. BOOLEAN
  475. KdpLowWriteContent (
  476. IN ULONG Index
  477. )
  478. /*++
  479. Routine Description:
  480. This routine attempts to replace the code that a breakpoint is
  481. written over. This routine, KdpAddBreakpoint,
  482. KdpLowRestoreBreakpoint and KdSetOwedBreakpoints are responsible
  483. for getting data written as requested. Callers should not
  484. examine or use KdpOweBreakpoints, and they should not set the
  485. NEEDS_WRITE or NEEDS_REPLACE flags.
  486. Callers must still look at the return value from this function,
  487. however: if it returns FALSE, the breakpoint record must not be
  488. reused until KdSetOwedBreakpoints has finished with it.
  489. Arguments:
  490. Index - Supplies the index of the breakpoint table entry
  491. which is to be deleted.
  492. Return Value:
  493. Returns TRUE if the breakpoint was removed, FALSE if it was deferred.
  494. --*/
  495. {
  496. #if defined(_IA64_)
  497. KDP_BREAKPOINT_TYPE mBuf;
  498. PVOID BundleAddress;
  499. #endif
  500. //
  501. // Do the contents need to be replaced at all?
  502. //
  503. if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_WRITE) {
  504. //
  505. // The breakpoint was never written out. Clear the flag
  506. // and we are done.
  507. //
  508. KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_NEEDS_WRITE;
  509. //DPRINT(("KD: Breakpoint at 0x%08x never written; flag cleared.\n",
  510. // KdpBreakpointTable[Index].Address));
  511. return TRUE;
  512. }
  513. #if !defined(_IA64_)
  514. if (KdpBreakpointTable[Index].Content == KdpBreakpointInstruction) {
  515. //
  516. // The instruction is a breakpoint anyway.
  517. //
  518. //DPRINT(("KD: Breakpoint at 0x%08x; instr is really BP; flag cleared.\n",
  519. // KdpBreakpointTable[Index].Address));
  520. return TRUE;
  521. }
  522. #endif
  523. //
  524. // Restore the instruction contents.
  525. //
  526. #if defined(_IA64_)
  527. // Read in memory since adjancent instructions in the same bundle may have
  528. // been modified after we save them.
  529. if (!NT_SUCCESS(KdpCopyFromPtr(&mBuf,
  530. KdpBreakpointTable[Index].Address,
  531. sizeof(KDP_BREAKPOINT_TYPE),
  532. NULL))) {
  533. KdpOweBreakpoint = TRUE;
  534. //DPRINT(("KD: read 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  535. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_REPLACE;
  536. return FALSE;
  537. }
  538. else {
  539. switch ((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) {
  540. case 0:
  541. mBuf = (mBuf & ~(INST_SLOT0_MASK))
  542. | (KdpBreakpointTable[Index].Content & INST_SLOT0_MASK);
  543. break;
  544. case 4:
  545. mBuf = (mBuf & ~(INST_SLOT1_MASK))
  546. | (KdpBreakpointTable[Index].Content & INST_SLOT1_MASK);
  547. break;
  548. case 8:
  549. mBuf = (mBuf & ~(INST_SLOT2_MASK))
  550. | (KdpBreakpointTable[Index].Content & INST_SLOT2_MASK);
  551. break;
  552. default:
  553. KdpOweBreakpoint = TRUE;
  554. //DPRINT(("KD: illegal instruction address 0x%08x\n", KdpBreakpointTable[Index].Address));
  555. return FALSE;
  556. }
  557. if (!NT_SUCCESS(KdpCopyToPtr(KdpBreakpointTable[Index].Address,
  558. &mBuf,
  559. sizeof(KDP_BREAKPOINT_TYPE),
  560. NULL))) {
  561. KdpOweBreakpoint = TRUE;
  562. //DPRINT(("KD: write to 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  563. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_REPLACE;
  564. return FALSE;
  565. }
  566. else {
  567. if (NT_SUCCESS(KdpCopyFromPtr(&mBuf,
  568. KdpBreakpointTable[Index].Address,
  569. sizeof(KDP_BREAKPOINT_TYPE),
  570. NULL))) {
  571. //DPRINT(("\tcontent after memory move = 0x%08x 0x%08x\n", (ULONG)(mBuf >> 32), (ULONG)mBuf));
  572. }
  573. // restore template to MLI if displaced instruction was MOVL
  574. if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IA64_MOVL) {
  575. (ULONG_PTR)BundleAddress = (ULONG_PTR)KdpBreakpointTable[Index].Address & ~(0xf);
  576. if (!NT_SUCCESS(KdpCopyFromPtr(&mBuf,
  577. BundleAddress,
  578. sizeof(KDP_BREAKPOINT_TYPE),
  579. NULL))) {
  580. KdpOweBreakpoint = TRUE;
  581. //DPRINT(("KD: read template 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  582. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_REPLACE;
  583. return FALSE;
  584. }
  585. else {
  586. mBuf &= ~((INST_TEMPL_MASK >> 1) << 1); // set template to MLI
  587. mBuf |= 0x4;
  588. if (!NT_SUCCESS(KdpCopyToPtr(BundleAddress,
  589. &mBuf,
  590. sizeof(KDP_BREAKPOINT_TYPE),
  591. NULL))) {
  592. KdpOweBreakpoint = TRUE;
  593. //DPRINT(("KD: write template to 0x%08x failed\n", KdpBreakpointTable[Index].Address));
  594. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_REPLACE;
  595. return FALSE;
  596. } else {
  597. //DPRINT(("KD: Breakpoint at 0x%08x cleared.\n",
  598. // KdpBreakpointTable[Index].Address));
  599. return TRUE;
  600. }
  601. }
  602. }
  603. else { // not MOVL
  604. //DPRINT(("KD: Breakpoint at 0x%08x cleared.\n",
  605. // KdpBreakpointTable[Index].Address));
  606. return TRUE;
  607. }
  608. }
  609. }
  610. #else
  611. if (!NT_SUCCESS(KdpCopyToPtr(KdpBreakpointTable[Index].Address,
  612. &KdpBreakpointTable[Index].Content,
  613. sizeof(KDP_BREAKPOINT_TYPE),
  614. NULL))) {
  615. KdpOweBreakpoint = TRUE;
  616. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_REPLACE;
  617. //DPRINT(("KD: Breakpoint at 0x%08x; unable to clear, flag set.\n",
  618. //KdpBreakpointTable[Index].Address));
  619. return FALSE;
  620. } else {
  621. //DPRINT(("KD: Breakpoint at 0x%08x cleared.\n",
  622. //KdpBreakpointTable[Index].Address));
  623. return TRUE;
  624. }
  625. #endif
  626. }
  627. BOOLEAN
  628. KdpDeleteBreakpoint (
  629. IN ULONG Handle
  630. )
  631. /*++
  632. Routine Description:
  633. This routine deletes an entry from the breakpoint table.
  634. Arguments:
  635. Handle - Supplies the index plus one of the breakpoint table entry
  636. which is to be deleted.
  637. Return Value:
  638. A value of FALSE is returned if the specified handle is not a valid
  639. value or the breakpoint cannot be deleted because the old instruction
  640. cannot be replaced. Otherwise, a value of TRUE is returned.
  641. --*/
  642. {
  643. ULONG Index = Handle - 1;
  644. //
  645. // If the specified handle is not valid, then return FALSE.
  646. //
  647. if ((Handle == 0) || (Handle > BREAKPOINT_TABLE_SIZE)) {
  648. DPRINT(("KD: Breakpoint %d invalid.\n", Index));
  649. return FALSE;
  650. }
  651. //
  652. // If the specified breakpoint table entry is not valid, then return FALSE.
  653. //
  654. if (KdpBreakpointTable[Index].Flags == 0) {
  655. //DPRINT(("KD: Breakpoint %d already clear.\n", Index));
  656. return FALSE;
  657. }
  658. //
  659. // If the breakpoint is already suspended, just delete it from the table.
  660. //
  661. if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) {
  662. //DPRINT(("KD: Deleting suspended breakpoint %d \n", Index));
  663. if ( !(KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_REPLACE) ) {
  664. //DPRINT(("KD: already clear.\n"));
  665. KdpBreakpointTable[Index].Flags = 0;
  666. return TRUE;
  667. }
  668. }
  669. //
  670. // Replace the instruction contents.
  671. //
  672. if (KdpLowWriteContent(Index)) {
  673. //
  674. // Delete breakpoint table entry
  675. //
  676. //DPRINT(("KD: Breakpoint %d deleted successfully.\n", Index));
  677. KdpBreakpointTable[Index].Flags = 0;
  678. }
  679. return TRUE;
  680. }
  681. BOOLEAN
  682. KdpDeleteBreakpointRange (
  683. IN PVOID Lower,
  684. IN PVOID Upper
  685. )
  686. /*++
  687. Routine Description:
  688. This routine deletes all breakpoints falling in a given range
  689. from the breakpoint table.
  690. Arguments:
  691. Lower - inclusive lower address of range from which to remove BPs.
  692. Upper - include upper address of range from which to remove BPs.
  693. Return Value:
  694. TRUE if any breakpoints removed, FALSE otherwise.
  695. --*/
  696. {
  697. ULONG Index;
  698. BOOLEAN ReturnStatus = FALSE;
  699. //
  700. // Examine each entry in the table in turn
  701. //
  702. for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++)
  703. {
  704. if ( (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) &&
  705. ((KdpBreakpointTable[Index].Address >= Lower) &&
  706. (KdpBreakpointTable[Index].Address <= Upper)) )
  707. {
  708. //
  709. // Breakpoint is in use and falls in range, clear it.
  710. //
  711. if (KdpDeleteBreakpoint(Index+1))
  712. {
  713. ReturnStatus = TRUE;
  714. }
  715. }
  716. }
  717. return ReturnStatus;
  718. }
  719. VOID
  720. KdpSuspendBreakpoint (
  721. ULONG Handle
  722. )
  723. {
  724. ULONG Index = Handle - 1;
  725. if ( (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) &&
  726. !(KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) ) {
  727. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_SUSPENDED;
  728. KdpLowWriteContent(Index);
  729. }
  730. return;
  731. } // KdpSuspendBreakpoint
  732. VOID
  733. KdpSuspendAllBreakpoints (
  734. VOID
  735. )
  736. {
  737. ULONG Handle;
  738. BreakpointsSuspended = TRUE;
  739. for ( Handle = 1; Handle <= BREAKPOINT_TABLE_SIZE; Handle++ ) {
  740. KdpSuspendBreakpoint(Handle);
  741. }
  742. return;
  743. } // KdpSuspendAllBreakpoints
  744. #if defined(_IA64_)
  745. BOOLEAN
  746. KdpSuspendBreakpointRange (
  747. IN PVOID Lower,
  748. IN PVOID Upper
  749. )
  750. /*++
  751. Routine Description:
  752. This routine suspend all breakpoints falling in a given range
  753. from the breakpoint table.
  754. Arguments:
  755. Lower - inclusive lower address of range from which to suspend BPs.
  756. Upper - include upper address of range from which to suspend BPs.
  757. Return Value:
  758. TRUE if any breakpoints suspended, FALSE otherwise.
  759. Notes:
  760. The order of suspending breakpoints is opposite that of setting
  761. them in KdpAddBreakpoint() in case of duplicate addresses.
  762. --*/
  763. {
  764. ULONG Index;
  765. BOOLEAN ReturnStatus = FALSE;
  766. //DPRINT(("\nKD: entering KdpSuspendBreakpointRange() at 0x%08x 0x%08x\n", Lower, Upper));
  767. //
  768. // Examine each entry in the table in turn
  769. //
  770. for (Index = BREAKPOINT_TABLE_SIZE - 1; Index != -1; Index--) {
  771. if ( (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) &&
  772. ((KdpBreakpointTable[Index].Address >= Lower) &&
  773. (KdpBreakpointTable[Index].Address <= Upper))
  774. ) {
  775. //
  776. // Breakpoint is in use and falls in range, suspend it.
  777. //
  778. KdpSuspendBreakpoint(Index+1);
  779. ReturnStatus = TRUE;
  780. }
  781. }
  782. //DPRINT(("KD: exiting KdpSuspendBreakpointRange() return 0x%d\n", ReturnStatus));
  783. return ReturnStatus;
  784. } // KdpSuspendBreakpointRange
  785. BOOLEAN
  786. KdpRestoreBreakpointRange (
  787. IN PVOID Lower,
  788. IN PVOID Upper
  789. )
  790. /*++
  791. Routine Description:
  792. This routine writes back breakpoints falling in a given range
  793. from the breakpoint table.
  794. Arguments:
  795. Lower - inclusive lower address of range from which to rewrite BPs.
  796. Upper - include upper address of range from which to rewrite BPs.
  797. Return Value:
  798. TRUE if any breakpoints written, FALSE otherwise.
  799. Notes:
  800. The order of writing breakpoints is opposite that of removing
  801. them in KdpSuspendBreakpointRange() in case of duplicate addresses.
  802. --*/
  803. {
  804. ULONG Index;
  805. BOOLEAN ReturnStatus = FALSE;
  806. //DPRINT(("\nKD: entering KdpRestoreBreakpointRange() at 0x%08x 0x%08x\n", Lower, Upper));
  807. //
  808. // Examine each entry in the table in turn
  809. //
  810. for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++) {
  811. if ( (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) &&
  812. ((KdpBreakpointTable[Index].Address >= Lower) &&
  813. (KdpBreakpointTable[Index].Address <= Upper))
  814. ) {
  815. //
  816. // suspended breakpoint that falls in range, unsuspend it.
  817. //
  818. if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) {
  819. KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_SUSPENDED;
  820. ReturnStatus = ReturnStatus || KdpLowRestoreBreakpoint(Index);
  821. }
  822. }
  823. }
  824. //DPRINT(("KD: exiting KdpRestoreBreakpointRange() return 0x%d\n", ReturnStatus));
  825. return ReturnStatus;
  826. } // KdpRestoreBreakpointRange
  827. #endif // _IA64_
  828. BOOLEAN
  829. KdpLowRestoreBreakpoint (
  830. IN ULONG Index
  831. )
  832. /*++
  833. Routine Description:
  834. This routine attempts to write a breakpoint instruction.
  835. The old contents must have already been stored in the
  836. breakpoint record.
  837. Arguments:
  838. Index - Supplies the index of the breakpoint table entry
  839. which is to be written.
  840. Return Value:
  841. Returns TRUE if the breakpoint was written, FALSE if it was
  842. not and has been marked for writing later.
  843. --*/
  844. {
  845. KDP_BREAKPOINT_TYPE Content;
  846. #if defined(_IA64_)
  847. KDP_BREAKPOINT_TYPE mBuf;
  848. PVOID BundleAddress;
  849. #endif
  850. //
  851. // Does the breakpoint need to be written at all?
  852. //
  853. if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_NEEDS_REPLACE) {
  854. //
  855. // The breakpoint was never removed. Clear the flag
  856. // and we are done.
  857. //
  858. KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_NEEDS_REPLACE;
  859. return TRUE;
  860. }
  861. if (KdpBreakpointTable[Index].Content == KdpBreakpointInstruction) {
  862. //
  863. // The instruction is a breakpoint anyway.
  864. //
  865. return TRUE;
  866. }
  867. //
  868. // Replace the instruction contents.
  869. //
  870. #if !defined(_IA64_)
  871. if (KdpBreakpointTable[Index].Content == KdpBreakpointInstruction) {
  872. //
  873. // The instruction is a breakpoint anyway.
  874. //
  875. return TRUE;
  876. }
  877. #endif
  878. //
  879. // Replace the instruction contents.
  880. //
  881. #if defined(_IA64_)
  882. // read in intruction in case the adjacent instruction has been modified.
  883. if (!NT_SUCCESS(KdpCopyFromPtr(&mBuf,
  884. KdpBreakpointTable[Index].Address,
  885. sizeof(KDP_BREAKPOINT_TYPE),
  886. NULL))) {
  887. //DPRINT(("KD: read 0x%p template failed\n", KdpBreakpointTable[Index].Address));
  888. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE;
  889. KdpOweBreakpoint = TRUE;
  890. return FALSE;
  891. }
  892. switch ((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) {
  893. case 0:
  894. mBuf = (mBuf & ~(INST_SLOT0_MASK)) | (KdpBreakpointInstruction << 5);
  895. break;
  896. case 4:
  897. mBuf = (mBuf & ~(INST_SLOT1_MASK)) | (KdpBreakpointInstruction << 14);
  898. break;
  899. case 8:
  900. mBuf = (mBuf & ~(INST_SLOT2_MASK)) | (KdpBreakpointInstruction << 23);
  901. break;
  902. default:
  903. //DPRINT(("KD: KdpAddBreakpoint bad instruction slot#\n"));
  904. return FALSE;
  905. }
  906. if (!NT_SUCCESS(KdpCopyToPtr(KdpBreakpointTable[Index].Address,
  907. &mBuf,
  908. sizeof(KDP_BREAKPOINT_TYPE),
  909. NULL))) {
  910. //DPRINT(("KD: Unable to write BP!\n"));
  911. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE;
  912. KdpOweBreakpoint = TRUE;
  913. return FALSE;
  914. }
  915. else {
  916. // check for two-slot MOVL instruction. Reject request if attempt to
  917. // set break in slot 2 of MLI template.
  918. // change template to type 0 if current instruction is MLI
  919. if (((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) != 0) {
  920. (ULONG_PTR)BundleAddress = (ULONG_PTR)KdpBreakpointTable[Index].Address & ~(0xf);
  921. if (!NT_SUCCESS(KdpCopyFromPtr(&mBuf,
  922. BundleAddress,
  923. sizeof(KDP_BREAKPOINT_TYPE),
  924. NULL))) {
  925. //DPRINT(("KD: read template failed at 0x%08x\n", BundleAddress));
  926. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE;
  927. KdpOweBreakpoint = TRUE;
  928. return FALSE;
  929. }
  930. else {
  931. if (((mBuf & INST_TEMPL_MASK) >> 1) == 0x2) {
  932. if (((ULONG_PTR)KdpBreakpointTable[Index].Address & 0xf) == 4) {
  933. // if template= type 2 MLI, change to type 0
  934. mBuf &= ~((INST_TEMPL_MASK >> 1) << 1);
  935. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_IA64_MOVL;
  936. if (!NT_SUCCESS(KdpCopyToPtr(BundleAddress,
  937. &mBuf,
  938. sizeof(KDP_BREAKPOINT_TYPE),
  939. NULL))) {
  940. //DPRINT(("KD: write to 0x%08x template failed\n", BundleAddress));
  941. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE;
  942. KdpOweBreakpoint = TRUE;
  943. return FALSE;
  944. }
  945. else {
  946. //DPRINT(("KD: change MLI template to type 0 at 0x%08x set\n", Address));
  947. }
  948. } else {
  949. // set breakpoint at slot 2 of MOVL is illegal
  950. //DPRINT(("KD: illegal to set BP at slot 2 of MOVL at 0x%08x\n", BundleAddress));
  951. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE;
  952. KdpOweBreakpoint = TRUE;
  953. return FALSE;
  954. }
  955. }
  956. }
  957. }
  958. //DPRINT(("KD: breakpoint at 0x%08x set\n", Address));
  959. return TRUE;
  960. }
  961. #else
  962. if (!NT_SUCCESS(KdpCopyToPtr(KdpBreakpointTable[Index].Address,
  963. &KdpBreakpointInstruction,
  964. sizeof(KDP_BREAKPOINT_TYPE),
  965. NULL))) {
  966. KdpBreakpointTable[Index].Flags |= KD_BREAKPOINT_NEEDS_WRITE;
  967. KdpOweBreakpoint = TRUE;
  968. return FALSE;
  969. } else {
  970. KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_NEEDS_WRITE;
  971. return TRUE;
  972. }
  973. #endif
  974. }
  975. VOID
  976. KdpRestoreAllBreakpoints (
  977. VOID
  978. )
  979. {
  980. ULONG Index;
  981. BreakpointsSuspended = FALSE;
  982. for ( Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++ ) {
  983. if ((KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) &&
  984. (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_SUSPENDED) ) {
  985. KdpBreakpointTable[Index].Flags &= ~KD_BREAKPOINT_SUSPENDED;
  986. KdpLowRestoreBreakpoint(Index);
  987. }
  988. }
  989. return;
  990. } // KdpRestoreAllBreakpoints
  991. VOID
  992. KdDeleteAllBreakpoints(
  993. VOID
  994. )
  995. {
  996. ULONG Handle;
  997. if (KdDebuggerEnabled == FALSE || KdPitchDebugger != FALSE) {
  998. return;
  999. }
  1000. BreakpointsSuspended = FALSE;
  1001. for ( Handle = 1; Handle <= BREAKPOINT_TABLE_SIZE; Handle++ ) {
  1002. KdpDeleteBreakpoint(Handle);
  1003. }
  1004. return;
  1005. } // KdDeleteAllBreakpoints