Windows NT 4.0 source code leak
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.

1346 lines
30 KiB

4 years ago
  1. #include "precomp.h"
  2. #pragma hdrstop
  3. SetFile()
  4. BREAKPOINT masterBP = {0L,0L};
  5. PBREAKPOINT bpList = &masterBP;
  6. extern HTHDX thdList;
  7. extern CRITICAL_SECTION csThreadProcList;
  8. PBREAKPOINT
  9. GetNewBp(
  10. HPRCX hprc,
  11. HTHDX hthd,
  12. BPTP BpType,
  13. BPNS BpNotify,
  14. ADDR *AddrBp,
  15. HPID id,
  16. PBREAKPOINT BpUse
  17. )
  18. /*++
  19. Routine Description:
  20. Allocates a BREAKPOINT structure and initializes it. Note that
  21. this does NOT add the structure to the breakpoint list (bplist).
  22. If it is not an address bp (i.e. it is a watchpoint), the hwalk
  23. field must be initialized later.
  24. Arguments:
  25. hprc - Supplies process to put BP in
  26. hthd - Supplies optional thread
  27. AddrBp - Supplies address structure for the breakpoint
  28. id - Supplies EM id for BP
  29. BpUse - Supplies other BP on same address (so we can steal the
  30. original code from it instead of reading).
  31. This last one is optional.
  32. Return Value:
  33. PBREAKPOINT - Pointer to allocated and initialized structure.
  34. --*/
  35. {
  36. PBREAKPOINT Bp;
  37. ADDR Addr;
  38. DWORD i;
  39. assert( !BpUse || ( BpUse->hthd != hthd ) );
  40. Bp = (PBREAKPOINT)malloc(sizeof(BREAKPOINT));
  41. assert( Bp );
  42. if ( Bp ) {
  43. assert( bpList );
  44. Bp->next = NULL;
  45. Bp->hprc = hprc;
  46. Bp->hthd = hthd;
  47. Bp->id = id;
  48. Bp->instances = 1;
  49. Bp->isStep = FALSE;
  50. Bp->hBreakPoint = 0;
  51. Bp->bpType = BpType;
  52. Bp->bpNotify = BpNotify;
  53. Bp->hWalk = NULL;
  54. memset(&Bp->addr, 0, sizeof(Bp->addr));
  55. //
  56. // Get the opcode from the indicated address
  57. //
  58. if ( BpUse ) {
  59. Bp->instr1 = BpUse->instr1;
  60. } else if (AddrBp) {
  61. Bp->instr1 = 0;
  62. Addr = *AddrBp;
  63. Bp->addr = *AddrBp;
  64. //
  65. // Check to make sure that what we have is not a linker index
  66. // number in the address structure. If it is then we can not
  67. // currently set this breakpoint due to the fact that we
  68. // don't have a real address
  69. //
  70. if ( ADDR_IS_LI(Addr) ) {
  71. assert(!"Addr is LI");
  72. free( Bp );
  73. Bp = NULL;
  74. }
  75. else if (!AddrReadMemory(hprc, hthd, &Addr, &(Bp->instr1), BP_SIZE,
  76. &i) ||
  77. (i != BP_SIZE)) {
  78. #ifdef KERNEL
  79. Bp->instr1 = 0;
  80. #else
  81. assert(!"AddrReadMemory failed");
  82. free(Bp);
  83. Bp = NULL;
  84. #endif
  85. }
  86. }
  87. }
  88. return Bp;
  89. }
  90. PBREAKPOINT
  91. SetBP(
  92. HPRCX hprc,
  93. HTHDX hthd,
  94. BPTP bptype,
  95. BPNS bpnotify,
  96. LPADDR paddr,
  97. HPID id
  98. )
  99. /*++
  100. Routine Description:
  101. Set a breakpoint, or increment instance count on an existing bp.
  102. if hthd is non-NULL, BP is only for that thread.
  103. Arguments:
  104. hprc - Supplies process to put BP in
  105. hthd - Supplies optional thread
  106. bptype - Supplies OSDEBUG BP type
  107. paddr - Supplies address structure for the breakpoint
  108. id - Supplies EM id for BP
  109. Return Value:
  110. pointer to bp structure, or NULL for failure
  111. --*/
  112. {
  113. PBREAKPOINT pbp;
  114. PBREAKPOINT pbpT;
  115. ADDR addr;
  116. ADDR addr2;
  117. if (!hprc) {
  118. return (PBREAKPOINT)NULL;
  119. }
  120. EnterCriticalSection(&csThreadProcList);
  121. /*
  122. * First let's try to find a breakpoint that
  123. * matches this description
  124. */
  125. pbpT = FindBP(hprc, hthd, bptype, bpnotify, paddr, FALSE);
  126. /*
  127. * If this thread has a breakpoint here,
  128. * increment reference count.
  129. */
  130. if (pbpT && pbpT->hthd == hthd) {
  131. pbp = pbpT;
  132. pbp->instances++;
  133. } else if ( pbp = GetNewBp( hprc, hthd, bptype, bpnotify, paddr, id, pbpT )) {
  134. if ( !pbpT ) {
  135. //
  136. // Now write the cpu-specific breakpoint code.
  137. //
  138. assert(!ADDR_IS_LI(pbp->addr));
  139. if ( WriteBreakPoint(pbp) ) {
  140. AddBpToList(pbp);
  141. } else {
  142. free( pbp );
  143. pbp = NULL;
  144. }
  145. } else {
  146. //
  147. // Breakpoint exists, but for wrong thread.
  148. //
  149. *pbp = *pbpT;
  150. pbp->hthd = hthd;
  151. pbp->instances = 1;
  152. }
  153. /*
  154. * Make it a linear address to start with
  155. */
  156. addr2 = *paddr;
  157. TranslateAddress(hprc, hthd, &addr2, TRUE);
  158. /*
  159. * Check with the threads to see if we are at this address. If so then
  160. * we need to set the BP field so we don't hit the bp imeadiately
  161. */
  162. if (hthd) {
  163. AddrFromHthdx(&addr, hthd);
  164. if ((hthd->tstate & ts_stopped) &&
  165. (AtBP(hthd) == NULL) &&
  166. AreAddrsEqual(hprc, hthd, &addr, &addr2)) {
  167. SetBPFlag(hthd, pbp);
  168. }
  169. } else {
  170. for (hthd = hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
  171. AddrFromHthdx(&addr, hthd);
  172. if ((hthd->tstate & ts_stopped) &&
  173. (AtBP(hthd) == NULL) &&
  174. AreAddrsEqual(hprc, hthd, &addr, &addr2)) {
  175. SetBPFlag(hthd, pbp);
  176. }
  177. }
  178. }
  179. }
  180. LeaveCriticalSection(&csThreadProcList);
  181. return pbp;
  182. } /* SetBP() */
  183. #ifdef KERNEL
  184. BOOL
  185. SetBPEx(
  186. HPRCX hprc,
  187. HTHDX hthd,
  188. HPID id,
  189. DWORD Count,
  190. ADDR *Addrs,
  191. PBREAKPOINT *Bps,
  192. DWORD ContinueStatus
  193. )
  194. /*++
  195. Routine Description:
  196. Allocates a bunch of breakpoints from a given list of linear offsets.
  197. Arguments:
  198. hprc - Supplies process to put BP in
  199. hthd - Supplies optional thread
  200. Count - Supplies count of breakpoints to set
  201. Addrs - Supplies list with Count addresses
  202. Bps - Supplies buffer to be filled with Count pointers to
  203. BREAKPOINT structures. Original contents is
  204. overwritten.
  205. ContinueStatus -
  206. Return Value:
  207. BOOL - If TRUE, then ALL breakpoints were set.
  208. If FALSE, then NONE of the breakpoints were set.
  209. NOTENOTE - Not sure of what will happen if the list contains duplicated
  210. addresses!
  211. --*/
  212. {
  213. PDBGKD_WRITE_BREAKPOINT DbgKdBp;
  214. PDBGKD_RESTORE_BREAKPOINT DbgKdBpRes;
  215. DWORD SetCount = 0;
  216. DWORD NewCount = 0;
  217. DWORD i;
  218. DWORD j;
  219. PBREAKPOINT BpT;
  220. BOOL Ok;
  221. ADDR Addr;
  222. ADDR Addr2;
  223. if (!hprc) {
  224. assert(!"hprc == NULL is SetBPEx");
  225. return FALSE;
  226. }
  227. assert( Count > 0 );
  228. assert( Addrs );
  229. assert( Bps );
  230. if ( Count == 1 ) {
  231. //
  232. // Only one breakpoint, faster to simply call SetBP
  233. //
  234. Bps[0] = SetBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[0], id );
  235. return ( Bps[0] != NULL );
  236. }
  237. EnterCriticalSection(&csThreadProcList);
  238. AddrInit( &Addr, 0, 0, 0, TRUE, TRUE, FALSE, FALSE );
  239. //
  240. // Allocate space for Count breakpoints
  241. //
  242. DbgKdBp = (PDBGKD_WRITE_BREAKPOINT)
  243. malloc( sizeof(DBGKD_WRITE_BREAKPOINT) * Count );
  244. assert( DbgKdBp );
  245. if ( !DbgKdBp ) {
  246. LeaveCriticalSection(&csThreadProcList);
  247. return FALSE;
  248. }
  249. for ( i=0; i<Count; i++ ) {
  250. //
  251. // See if we already have a breakpoint at this address.
  252. //
  253. Bps[i] = FindBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], FALSE );
  254. if ( !Bps[i] ) {
  255. DbgKdBp[ NewCount ].BreakPointAddress =
  256. (PVOID)GetAddrOff(Addrs[i]);
  257. DbgKdBp[ NewCount++ ].BreakPointHandle = (ULONG)NULL;
  258. Bps[i] = GetNewBp( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], id, NULL );
  259. assert( Bps[i] );
  260. } else if (Bps[i]->hthd != hthd ) {
  261. BpT = Bps[i];
  262. Bps[i] = GetNewBp( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], id, NULL );
  263. // BUGBUG kentf should instances be changed?
  264. *Bps[i] = *BpT;
  265. Bps[i]->hthd = hthd;
  266. }
  267. }
  268. Ok = TRUE;
  269. if ( NewCount > 0 ) {
  270. //
  271. // Set all new breakpoints
  272. //
  273. assert( NewCount <= Count );
  274. Ok = WriteBreakPointEx( hthd, NewCount, DbgKdBp, ContinueStatus );
  275. }
  276. if ( Ok ) {
  277. //
  278. // Fill in the breakpoint list
  279. //
  280. j = 0;
  281. for ( i=0; i<Count; i++ ) {
  282. if ( Bps[i] && Bps[i]->hBreakPoint && Bps[i]->hthd == hthd ) {
  283. //
  284. // Will reuse BP, just increment reference count.
  285. //
  286. Bps[i]->instances++;
  287. } else {
  288. assert( (PVOID)GetAddrOff(Addrs[i]) ==
  289. DbgKdBp[j].BreakPointAddress );
  290. //
  291. // Allocate new BP structure and get handle from
  292. // the breakpoint packet. Note that we rely on the
  293. // order of the breakpoints in the breakpoint packet.
  294. //
  295. Bps[i]->hBreakPoint = DbgKdBp[j].BreakPointHandle;
  296. AddBpToList(Bps[i]);
  297. j++;
  298. }
  299. SetCount++;
  300. //
  301. // Check with the threads to see if we are at this address.
  302. // If so then we need to set the BP field so we don't hit
  303. // the bp imeadiately
  304. //
  305. Addr2 = Bps[i]->addr;
  306. if ( hthd ) {
  307. AddrFromHthdx( &Addr, hthd );
  308. if ((hthd->tstate & ts_stopped) &&
  309. (AtBP(hthd) == NULL) &&
  310. AreAddrsEqual(hprc, hthd, &Addr, &Addr2 )) {
  311. SetBPFlag(hthd, Bps[i]);
  312. }
  313. } else {
  314. for (hthd=hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
  315. AddrFromHthdx( &Addr, hthd );
  316. if ((hthd->tstate & ts_stopped) &&
  317. (AtBP(hthd) == NULL) &&
  318. AreAddrsEqual(hprc, hthd, &Addr, &Addr2)) {
  319. SetBPFlag(hthd, Bps[i]);
  320. }
  321. }
  322. }
  323. }
  324. assert( j == NewCount );
  325. } else {
  326. //
  327. // Clean up any breakpoints that were set.
  328. //
  329. DbgKdBpRes = (PDBGKD_RESTORE_BREAKPOINT)
  330. malloc( sizeof(DBGKD_RESTORE_BREAKPOINT) * NewCount );
  331. assert( DbgKdBpRes );
  332. if ( DbgKdBpRes ) {
  333. //
  334. // Put all breakpoints with a valid handle on the list of
  335. // breakpoints to be removed.
  336. //
  337. j = 0;
  338. for ( i=0; i<NewCount;i++) {
  339. if ( DbgKdBp[i].BreakPointHandle != (ULONG)NULL ) {
  340. DbgKdBpRes[j++].BreakPointHandle =
  341. DbgKdBp[i].BreakPointHandle;
  342. }
  343. }
  344. //
  345. // Now remove them
  346. //
  347. if ( j > 0 ) {
  348. assert( j <= NewCount );
  349. RestoreBreakPointEx( j, DbgKdBpRes );
  350. }
  351. free( DbgKdBpRes );
  352. //
  353. // Remove allocated BP structures
  354. //
  355. for ( i=0; i<Count; i++ ) {
  356. if ( Bps[i] && !Bps[i]->hBreakPoint ) {
  357. assert( !Bps[i]->next );
  358. free( Bps[i] );
  359. Bps[i] = NULL;
  360. }
  361. }
  362. }
  363. }
  364. free( DbgKdBp );
  365. LeaveCriticalSection(&csThreadProcList);
  366. return (SetCount == Count);
  367. }
  368. #else // KERNEL
  369. BOOL
  370. SetBPEx(
  371. HPRCX hprc,
  372. HTHDX hthd,
  373. HPID id,
  374. DWORD Count,
  375. ADDR *Addrs,
  376. PBREAKPOINT *Bps,
  377. DWORD ContinueStatus
  378. )
  379. /*++
  380. Routine Description:
  381. Allocates a bunch of breakpoints from a given list of linear offsets.
  382. Arguments:
  383. hprc - Supplies process to put BP in
  384. hthd - Supplies optional thread
  385. Count - Supplies count of breakpoints to set
  386. Addrs - Supplies list with Count addresses
  387. Bps - Supplies buffer to be filled with Count pointers to
  388. BREAKPOINT structures. Original contents is
  389. overwritten.
  390. ContinueStatus -
  391. Return Value:
  392. BOOL - If TRUE, then ALL breakpoints were set.
  393. If FALSE, then NONE of the breakpoints were set.
  394. NOTENOTE - Not sure of what will happen if the list contains duplicated
  395. addresses!
  396. --*/
  397. {
  398. DWORD SetCount = 0;
  399. DWORD NewCount = 0;
  400. DWORD i;
  401. DWORD j;
  402. DWORD k;
  403. ADDR Addr;
  404. ADDR Addr2;
  405. BP_UNIT opcode = BP_OPCODE;
  406. if (!hprc) {
  407. assert(!"hprc == NULL in SetBPEx");
  408. return FALSE;
  409. }
  410. assert( Count > 0 );
  411. assert( Addrs );
  412. assert( Bps );
  413. if ( Count == 1 ) {
  414. //
  415. // Only one breakpoint, faster to simply call SetBP
  416. //
  417. Bps[0] = SetBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[0], id );
  418. return ( Bps[0] != NULL );
  419. }
  420. EnterCriticalSection(&csThreadProcList);
  421. for ( i=0; i<Count; i++ ) {
  422. //
  423. // See if we already have a breakpoint at this address.
  424. //
  425. Bps[i] = FindBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], FALSE );
  426. if ( Bps[i] && Bps[i]->hthd == hthd ) {
  427. //
  428. // Reuse this breakpoint
  429. //
  430. Bps[i]->instances++;
  431. assert( Bps[i]->instances > 1 );
  432. } else {
  433. //
  434. // Get new breakpoint
  435. //
  436. Bps[i] = GetNewBp(hprc, hthd, bptpExec, bpnsStop, &Addrs[i], id, NULL);
  437. if ( !Bps[i] ) {
  438. assert(!"GetNewBp failed in SetBPEx");
  439. break;
  440. }
  441. if ( !ADDR_IS_LI(Bps[i]->addr) ) {
  442. if ( !AddrWriteMemory(hprc, hthd, &Bps[i]->addr,
  443. (LPBYTE) &opcode, BP_SIZE, &j) ) {
  444. free( Bps[i] );
  445. Bps[i] = NULL;
  446. assert(!"DbgWriteMemory failed in SetBPEx");
  447. break;
  448. }
  449. }
  450. }
  451. }
  452. if ( i < Count ) {
  453. //
  454. // Something went wrong, will backtrack
  455. //
  456. assert(!"i < Count in SetBPEx");
  457. for ( j=0; j<i; j++ ) {
  458. assert( Bps[j] );
  459. Bps[j]->instances--;
  460. if ( Bps[j]->instances == 0 ) {
  461. if ( !ADDR_IS_LI(Bps[j]->addr) ) {
  462. AddrWriteMemory(hprc, hthd, &Bps[j]->addr,
  463. (LPBYTE) &Bps[j]->instr1, BP_SIZE, &k);
  464. }
  465. free( Bps[j] );
  466. Bps[j] = NULL;
  467. }
  468. }
  469. } else {
  470. //
  471. // Add all the new breakpoints to the list
  472. //
  473. for ( i=0; i<Count; i++ ) {
  474. if ( Bps[i]->instances == 1 ) {
  475. AddBpToList(Bps[i]);
  476. }
  477. //
  478. // Check with the threads to see if we are at this address. If so then
  479. // we need to set the BP field so we don't hit the bp imeadiately
  480. //
  481. Addr2 = Bps[i]->addr;
  482. if ( hthd ) {
  483. AddrFromHthdx( &Addr, hthd );
  484. if ((hthd->tstate & ts_stopped) &&
  485. (AtBP(hthd) == NULL) &&
  486. AreAddrsEqual(hprc, hthd, &Addr, &Addr2 )) {
  487. SetBPFlag(hthd, Bps[i]);
  488. }
  489. } else {
  490. for (hthd=hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
  491. AddrFromHthdx( &Addr, hthd );
  492. if ((hthd->tstate & ts_stopped) &&
  493. (AtBP(hthd) == NULL) &&
  494. AreAddrsEqual(hprc, hthd, &Addr, &Addr2)) {
  495. SetBPFlag(hthd, Bps[i]);
  496. }
  497. }
  498. }
  499. }
  500. SetCount = Count;
  501. }
  502. LeaveCriticalSection(&csThreadProcList);
  503. return (SetCount == Count);
  504. }
  505. #endif // KERNEL
  506. BOOL
  507. BPInRange(
  508. HPRCX hprc,
  509. HTHDX hthd,
  510. PBREAKPOINT bp,
  511. LPADDR paddrStart,
  512. DWORD cb,
  513. LPDWORD offset,
  514. BP_UNIT * instr
  515. )
  516. {
  517. ADDR addr1;
  518. ADDR addr2;
  519. /*
  520. * If the breakpoint has a Loader index address then we can not
  521. * possibly match it
  522. */
  523. assert (!ADDR_IS_LI(*paddrStart) );
  524. if (ADDR_IS_LI(bp->addr)) {
  525. return FALSE;
  526. }
  527. *offset = 0;
  528. /*
  529. * Now check for "equality" of the addresses.
  530. *
  531. * Need to include size of BP in the address range check. Since
  532. * the address may start half way through a breakpoint.
  533. */
  534. if ((ADDR_IS_FLAT(*paddrStart) == TRUE) &&
  535. (ADDR_IS_FLAT(bp->addr) == TRUE)) {
  536. if ((GetAddrOff(*paddrStart) - sizeof(BP_UNIT) + 1 <=
  537. GetAddrOff(bp->addr)) &&
  538. (GetAddrOff(bp->addr) < GetAddrOff(*paddrStart) + cb)) {
  539. *offset = (DWORD) GetAddrOff(bp->addr) -
  540. (DWORD) GetAddrOff(*paddrStart);
  541. *instr = bp->instr1;
  542. return TRUE;
  543. }
  544. return FALSE;
  545. }
  546. /*
  547. * The two addresses did not start out as flat addresses. So change
  548. * them to linear addresses so that we can see if the addresses are
  549. * are really the same
  550. */
  551. addr1 = *paddrStart;
  552. if (!TranslateAddress(hprc, hthd, &addr1, TRUE)) {
  553. return FALSE;
  554. }
  555. addr2 = bp->addr;
  556. if (!TranslateAddress(hprc, hthd, &addr2, TRUE)) {
  557. return FALSE;
  558. }
  559. if ((GetAddrOff(addr1) - sizeof(BP_UNIT) + 1 <= GetAddrOff(addr2)) &&
  560. (GetAddrOff(addr2) < GetAddrOff(addr1) + cb)) {
  561. *offset = (DWORD) GetAddrOff(addr2) - (DWORD) GetAddrOff(addr1);
  562. *instr = bp->instr1;
  563. return TRUE;
  564. }
  565. return FALSE;
  566. }
  567. PBREAKPOINT
  568. FindBP(
  569. HPRCX hprc,
  570. HTHDX hthd,
  571. BPTP bptype,
  572. BPNS bpnotify,
  573. LPADDR paddr,
  574. BOOL fExact
  575. )
  576. /*++
  577. Routine Description:
  578. Find and return a pointer to a BP struct. Always returns a BP that
  579. matches hthd thread if one exists; if fExact is FALSE and there is no
  580. exact match, a BP matching only hprc and address will succeed.
  581. Arguments:
  582. hprc - Supplies process
  583. hthd - Supplies thread
  584. bptype - Supplies OSDEBUG BP type
  585. paddr - Supplies address
  586. fExact - Supplies TRUE if must be for a certain thread
  587. Return Value:
  588. pointer to BREAKPOINT struct, or NULL if not found.
  589. --*/
  590. {
  591. PBREAKPOINT pbp;
  592. PBREAKPOINT pbpFound = NULL;
  593. ADDR addr;
  594. EnterCriticalSection(&csThreadProcList);
  595. /*
  596. * Pre-translate the address to a linear address
  597. */
  598. addr = *paddr;
  599. TranslateAddress(hprc, hthd, &addr, TRUE);
  600. /*
  601. * Check for an equivalent breakpoint. Breakpoints will be equal if
  602. *
  603. * 1. The process is the same
  604. * 2. The addresses of the breakpoints are the same
  605. */
  606. for (pbp=bpList->next; pbp; pbp=pbp->next) {
  607. if ((pbp->hprc == hprc) &&
  608. AreAddrsEqual(hprc, hthd, &pbp->addr, &addr)) {
  609. pbpFound = pbp;
  610. if (pbp->hthd == hthd) {
  611. break;
  612. }
  613. }
  614. }
  615. LeaveCriticalSection(&csThreadProcList);
  616. if (!fExact || (pbpFound && pbpFound->hthd == hthd)) {
  617. return pbpFound;
  618. } else {
  619. return NULL;
  620. }
  621. } /* FindBP() */
  622. PBREAKPOINT
  623. BPNextHprcPbp(
  624. HPRCX hprc,
  625. PBREAKPOINT pbp
  626. )
  627. /*++
  628. Routine Description:
  629. Find the next breakpoint for the given process after pbp.
  630. If pbp is NULL start at the front of the list, for a find
  631. first, find next behaviour.
  632. Arguments:
  633. hprc - Supplies the process handle to match breakpoints for
  634. pbp - Supplies pointer to breakpoint item to start searching after
  635. Return Value:
  636. NULL if no matching breakpoint is found else a pointer to the
  637. matching breakpoint
  638. --*/
  639. {
  640. EnterCriticalSection(&csThreadProcList);
  641. if (pbp == NULL) {
  642. pbp = bpList->next;
  643. } else {
  644. pbp = pbp->next;
  645. }
  646. for ( ; pbp; pbp = pbp->next ) {
  647. if (pbp->hprc == hprc) {
  648. break;
  649. }
  650. }
  651. LeaveCriticalSection(&csThreadProcList);
  652. return pbp;
  653. } /* BPNextHprcPbp() */
  654. PBREAKPOINT
  655. BPNextHthdPbp(
  656. HTHDX hthd,
  657. PBREAKPOINT pbp
  658. )
  659. /*++
  660. Routine Description:
  661. Find the next breakpoint for the given thread after pbp.
  662. If pbp is NULL start at the front of the list for find
  663. first, find next behaviour.
  664. Arguments:
  665. hthd - Supplies the thread handle to match breakpoints for
  666. pbp - Supplies pointer to breakpoint item to start searching after
  667. Return Value:
  668. NULL if no matching breakpoint is found else a pointer to the
  669. matching breakpoint
  670. --*/
  671. {
  672. EnterCriticalSection(&csThreadProcList);
  673. if (pbp == NULL) {
  674. pbp = bpList->next;
  675. } else {
  676. pbp = pbp->next;
  677. }
  678. for ( ; pbp; pbp = pbp->next ) {
  679. if (pbp->hthd == hthd) {
  680. break;
  681. }
  682. }
  683. LeaveCriticalSection(&csThreadProcList);
  684. return pbp;
  685. } /* BPNextHthdPbp() */
  686. BOOL
  687. RemoveBPHelper(
  688. PBREAKPOINT pbp,
  689. BOOL fRestore
  690. )
  691. {
  692. PBREAKPOINT pbpPrev;
  693. PBREAKPOINT pbpCur;
  694. PBREAKPOINT pbpT;
  695. HTHDX hthd;
  696. BOOL rVal = FALSE;
  697. //
  698. // first, is it real?
  699. //
  700. if (!pbp || pbp == EMBEDDED_BP) {
  701. return FALSE;
  702. }
  703. EnterCriticalSection(&csThreadProcList);
  704. /* Decrement the instances counter */
  705. if (--pbp->instances) {
  706. /*
  707. * BUGBUG: jimsch -- Feb 29 1993
  708. * This piece of code is most likely incorrect. We need to
  709. * know if we are the DM freeing a breakpoint or the user
  710. * freeing a breakpoint before we clear the step bit. Otherwise
  711. * we may be in the following situation
  712. *
  713. * Set a thread specific breakpoint on an address
  714. * Step the thread so that the address is the destination is
  715. * where the step ends up (but it takes some time such
  716. * as over a function call)
  717. * Clear the thread specific breakpoint
  718. *
  719. * This will cause the step breakpoint to be cleared so we will
  720. * stop at the address instead of just continuing stepping.
  721. */
  722. pbp->isStep = FALSE;
  723. LeaveCriticalSection(&csThreadProcList);
  724. return FALSE;
  725. }
  726. /* Search the list for the specified breakpoint */
  727. for ( pbpPrev = bpList, pbpCur = bpList->next;
  728. pbpCur;
  729. pbpPrev = pbpCur, pbpCur = pbpCur->next) {
  730. if (pbpCur == pbp) {
  731. /*
  732. * Remove this bp from the list:
  733. */
  734. pbpPrev->next = pbpCur->next;
  735. /*
  736. * see if there is another bp on the same address:
  737. */
  738. pbpT = FindBP(pbpCur->hprc,
  739. pbpCur->hthd,
  740. pbpCur->bpType,
  741. pbpCur->bpNotify,
  742. &pbpCur->addr,
  743. FALSE);
  744. if (!pbpT && pbpCur->bpType == bptpExec) {
  745. /*
  746. * if this was the only one, put the
  747. * opcode back where it belongs.
  748. */
  749. if ( fRestore ) {
  750. RestoreBreakPoint( pbpCur );
  751. }
  752. }
  753. /*
  754. * Now we have to go through all the threads to see
  755. * if any of them are on this breakpoint and clear
  756. * the breakpoint indicator on these threads
  757. */
  758. /*
  759. * Could be on any thread:
  760. */
  761. /*
  762. * (We are already in the ThreadProcList critical section)
  763. */
  764. for (hthd = thdList->next; hthd; hthd = hthd->next) {
  765. if (hthd->atBP == pbpCur) {
  766. hthd->atBP = pbpT;
  767. }
  768. }
  769. free(pbpCur);
  770. rVal = TRUE;
  771. break;
  772. }
  773. }
  774. LeaveCriticalSection(&csThreadProcList);
  775. return rVal;
  776. }
  777. BOOL
  778. RemoveBP(
  779. PBREAKPOINT pbp
  780. )
  781. {
  782. return RemoveBPHelper( pbp, TRUE );
  783. }
  784. #ifdef KERNEL
  785. BOOL
  786. RemoveBPEx(
  787. DWORD Count,
  788. PBREAKPOINT *Bps
  789. )
  790. {
  791. PDBGKD_RESTORE_BREAKPOINT DbgKdBp;
  792. DWORD RestoreCount = 0;
  793. DWORD GoneCount = 0;
  794. DWORD i;
  795. PBREAKPOINT BpCur;
  796. PBREAKPOINT BpOther;
  797. assert( Count > 0 );
  798. if ( Count == 1 ) {
  799. //
  800. // Only one breakpoint, its faster to simply call RemoveBP
  801. //
  802. return RemoveBP( Bps[0] );
  803. }
  804. EnterCriticalSection(&csThreadProcList);
  805. DbgKdBp = (PDBGKD_RESTORE_BREAKPOINT)malloc( sizeof(DBGKD_RESTORE_BREAKPOINT) * Count );
  806. assert( DbgKdBp );
  807. if ( DbgKdBp ) {
  808. //
  809. // Find out what breakpoints we have to restore and put them in
  810. // the list.
  811. //
  812. for ( i=0; i<Count;i++ ) {
  813. assert( Bps[i] != EMBEDDED_BP );
  814. for ( BpCur = bpList->next; BpCur; BpCur = BpCur->next) {
  815. if ( BpCur == Bps[i] ) {
  816. //
  817. // See if there is another bp on the same address.
  818. //
  819. for ( BpOther = bpList->next; BpOther; BpOther = BpOther->next ) {
  820. if ( (BpOther != BpCur) &&
  821. AreAddrsEqual( BpCur->hprc, BpCur->hthd, &BpCur->addr, &BpOther->addr ) ) {
  822. break;
  823. }
  824. }
  825. if ( !BpOther ) {
  826. //
  827. // If this was the only one, put it in the list.
  828. //
  829. DbgKdBp[GoneCount++].BreakPointHandle = Bps[i]->hBreakPoint;
  830. }
  831. break;
  832. }
  833. }
  834. }
  835. //
  836. // Restore the breakpoints in the list.
  837. //
  838. if ( GoneCount > 0 ) {
  839. assert( GoneCount <= Count );
  840. RestoreBreakPointEx( GoneCount, DbgKdBp );
  841. }
  842. //
  843. // All breakpoints that were to be restored have been
  844. // restored, now go ahead and do the cleaning up stuff.
  845. //
  846. for ( i=0; i<Count;i++ ) {
  847. RemoveBPHelper( Bps[i], FALSE );
  848. RestoreCount++;
  849. }
  850. free( DbgKdBp );
  851. }
  852. LeaveCriticalSection(&csThreadProcList);
  853. return ( RestoreCount == Count );
  854. }
  855. #else // KERNEL
  856. BOOL
  857. RemoveBPEx(
  858. DWORD Count,
  859. PBREAKPOINT *Bps
  860. )
  861. {
  862. DWORD i;
  863. assert( Count > 0 );
  864. for ( i=0; i<Count;i++ ) {
  865. RemoveBPHelper( Bps[i], TRUE );
  866. }
  867. return TRUE;
  868. }
  869. #endif // KERNEL
  870. void
  871. SetBPFlag(
  872. HTHDX hthd,
  873. PBREAKPOINT bp
  874. )
  875. {
  876. hthd->atBP = bp;
  877. }
  878. PBREAKPOINT
  879. AtBP(
  880. HTHDX hthd
  881. )
  882. {
  883. return hthd->atBP;
  884. }
  885. void
  886. ClearBPFlag(
  887. HTHDX hthd
  888. )
  889. {
  890. hthd->atBP = NULL;
  891. }
  892. void
  893. RestoreInstrBP(
  894. HTHDX hthd,
  895. PBREAKPOINT bp
  896. )
  897. /*++
  898. Routine Description:
  899. Replace the instruction for a breakpoint. If it was not
  900. the debugger's BP, skip the IP past it.
  901. Arguments:
  902. hthd - Thread
  903. bp - breakpoint data
  904. Return Value:
  905. --*/
  906. {
  907. //
  908. // Check if this is an embedded breakpoint
  909. //
  910. if (bp == EMBEDDED_BP) {
  911. //
  912. // It was, so there is no instruction to restore,
  913. // just increment the EIP
  914. //
  915. IncrementIP(hthd);
  916. return;
  917. }
  918. if (bp->hWalk) {
  919. //
  920. // This is really a hardware breakpoint. Let the
  921. // walk manager fix this.
  922. //
  923. ExprBPClearBPForStep(hthd);
  924. } else {
  925. //
  926. // Replace the breakpoint current in memory with the correct
  927. // instruction
  928. //
  929. RestoreBreakPoint( bp );
  930. bp->hBreakPoint = 0;
  931. }
  932. return;
  933. }
  934. VOID
  935. DeleteAllBps(
  936. VOID
  937. )
  938. /*++
  939. Routine Description:
  940. Arguments:
  941. Return Value:
  942. --*/
  943. {
  944. PBREAKPOINT pbp, bpn;
  945. EnterCriticalSection(&csThreadProcList);
  946. pbp = bpList->next;
  947. while (pbp) {
  948. bpn = pbp->next;
  949. if (bpn) {
  950. free( pbp );
  951. }
  952. pbp = bpn;
  953. }
  954. bpList->next = NULL;
  955. bpList->hprc = NULL;
  956. LeaveCriticalSection(&csThreadProcList);
  957. }
  958. void
  959. AddBpToList(
  960. PBREAKPOINT pbp
  961. )
  962. {
  963. assert(bpList);
  964. EnterCriticalSection(&csThreadProcList);
  965. pbp->next = bpList->next;
  966. bpList->next = pbp;
  967. LeaveCriticalSection(&csThreadProcList);
  968. }
  969. PBREAKPOINT
  970. FindBpForWalk(
  971. PVOID pWalk
  972. )
  973. {
  974. PBREAKPOINT pbp;
  975. EnterCriticalSection(&csThreadProcList);
  976. pbp = bpList;
  977. while (pbp) {
  978. if (IsWalkInGroup(pbp->hWalk, pWalk)) {
  979. break;
  980. }
  981. pbp = pbp->next;
  982. }
  983. LeaveCriticalSection(&csThreadProcList);
  984. return pbp;
  985. }
  986. PBREAKPOINT
  987. SetWP(
  988. HPRCX hprc,
  989. HTHDX hthd,
  990. BPTP bptype,
  991. BPNS bpnotify,
  992. ADDR addr
  993. )
  994. {
  995. return (PBREAKPOINT)0;
  996. }