Leaked source code of windows server 2003
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.

4649 lines
127 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Breakpoint handling functions.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. // Currently used only to watch for list changes when
  10. // doing callbacks for breakpoint hit notifications.
  11. BOOL g_BreakpointListChanged;
  12. // Always update data breakpoints the very first time in
  13. // order to flush out any stale data breakpoints.
  14. BOOL g_UpdateDataBreakpoints = TRUE;
  15. BOOL g_DataBreakpointsChanged;
  16. BOOL g_BreakpointsSuspended;
  17. Breakpoint* g_StepTraceBp; // Trace breakpoint.
  18. CHAR g_StepTraceCmdState;
  19. Breakpoint* g_DeferBp; // Deferred breakpoint.
  20. BOOL g_DeferDefined; // TRUE if deferred breakpoint is active.
  21. Breakpoint* g_LastBreakpointHit;
  22. ADDR g_LastBreakpointHitPc;
  23. HRESULT
  24. BreakpointInit(void)
  25. {
  26. // These breakpoints are never put in any list so their
  27. // IDs can be anything. Pick unusual numbers to make them
  28. // easy to identify when debugging the debugger.
  29. g_StepTraceBp = new
  30. CodeBreakpoint(NULL, 0xffff0000, IMAGE_FILE_MACHINE_UNKNOWN);
  31. g_StepTraceCmdState = 't';
  32. g_DeferBp = new
  33. CodeBreakpoint(NULL, 0xffff0001, IMAGE_FILE_MACHINE_UNKNOWN);
  34. if (g_StepTraceBp == NULL ||
  35. g_DeferBp == NULL)
  36. {
  37. delete g_StepTraceBp;
  38. g_StepTraceBp = NULL;
  39. delete g_DeferBp;
  40. g_DeferBp = NULL;
  41. return E_OUTOFMEMORY;
  42. }
  43. return S_OK;
  44. }
  45. //----------------------------------------------------------------------------
  46. //
  47. // Breakpoint.
  48. //
  49. //----------------------------------------------------------------------------
  50. Breakpoint::Breakpoint(DebugClient* Adder, ULONG Id, ULONG Type,
  51. ULONG ProcType)
  52. {
  53. m_Next = NULL;
  54. m_Prev = NULL;
  55. m_Refs = 1;
  56. m_Id = Id;
  57. m_BreakType = Type;
  58. // Breakpoints are always created disabled since they
  59. // are not initialized at the time of creation.
  60. m_Flags = 0;
  61. m_CodeFlags = IBI_DEFAULT;
  62. ADDRFLAT(&m_Addr, 0);
  63. // Initial data parameters must be set to something
  64. // valid so that Validate calls will allow the offset
  65. // to be changed.
  66. m_DataSize = 1;
  67. m_DataAccessType = DEBUG_BREAK_EXECUTE;
  68. m_PassCount = 1;
  69. m_CurPassCount = 1;
  70. m_CommandLen = 0;
  71. m_Command = NULL;
  72. m_MatchThread = NULL;
  73. m_Process = g_Process;
  74. m_OffsetExprLen = 0;
  75. m_OffsetExpr = NULL;
  76. m_Adder = Adder;
  77. m_MatchThreadData = 0;
  78. m_MatchProcessData = 0;
  79. SetProcType(ProcType);
  80. if (m_BreakType == DEBUG_BREAKPOINT_DATA)
  81. {
  82. g_DataBreakpointsChanged = TRUE;
  83. }
  84. }
  85. Breakpoint::~Breakpoint(void)
  86. {
  87. ULONG i;
  88. // There used to be an assert here checking that
  89. // the inserted flag wasn't set before a breakpoint
  90. // structure was deleted. However, the inserted flag
  91. // might still be set at this point if a breakpoint
  92. // restore failed, so the assert is not valid.
  93. if (m_BreakType == DEBUG_BREAKPOINT_DATA)
  94. {
  95. g_DataBreakpointsChanged = TRUE;
  96. }
  97. // Make sure stale pointers aren't left in the
  98. // go breakpoints array. This can happen if
  99. // a process exits or the target reboots while
  100. // go breakpoints are active.
  101. for (i = 0; i < g_NumGoBreakpoints; i++)
  102. {
  103. if (g_GoBreakpoints[i] == this)
  104. {
  105. g_GoBreakpoints[i] = NULL;
  106. }
  107. }
  108. if (this == g_LastBreakpointHit)
  109. {
  110. g_LastBreakpointHit = NULL;
  111. }
  112. // Take this item out of the list if necessary.
  113. if (m_Flags & BREAKPOINT_IN_LIST)
  114. {
  115. UnlinkFromList();
  116. }
  117. delete [] (PSTR)m_Command;
  118. delete [] (PSTR)m_OffsetExpr;
  119. }
  120. STDMETHODIMP
  121. Breakpoint::QueryInterface(
  122. THIS_
  123. IN REFIID InterfaceId,
  124. OUT PVOID* Interface
  125. )
  126. {
  127. *Interface = NULL;
  128. // Interface specific casts are necessary in order to
  129. // get the right vtable pointer in our multiple
  130. // inheritance scheme.
  131. if (DbgIsEqualIID(InterfaceId, IID_IUnknown) ||
  132. DbgIsEqualIID(InterfaceId, IID_IDebugBreakpoint))
  133. {
  134. *Interface = (IDebugBreakpoint *)this;
  135. AddRef();
  136. return S_OK;
  137. }
  138. else
  139. {
  140. return E_NOINTERFACE;
  141. }
  142. }
  143. STDMETHODIMP_(ULONG)
  144. Breakpoint::AddRef(
  145. THIS
  146. )
  147. {
  148. // This object's lifetime is not controlled by
  149. // the interface.
  150. return 1;
  151. }
  152. STDMETHODIMP_(ULONG)
  153. Breakpoint::Release(
  154. THIS
  155. )
  156. {
  157. // This object's lifetime is not controlled by
  158. // the interface.
  159. return 0;
  160. }
  161. STDMETHODIMP
  162. Breakpoint::GetId(
  163. THIS_
  164. OUT PULONG Id
  165. )
  166. {
  167. ENTER_ENGINE();
  168. *Id = m_Id;
  169. LEAVE_ENGINE();
  170. return S_OK;
  171. }
  172. STDMETHODIMP
  173. Breakpoint::GetType(
  174. THIS_
  175. OUT PULONG BreakType,
  176. OUT PULONG ProcType
  177. )
  178. {
  179. ENTER_ENGINE();
  180. *BreakType = m_BreakType;
  181. *ProcType = m_ProcType;
  182. LEAVE_ENGINE();
  183. return S_OK;
  184. }
  185. STDMETHODIMP
  186. Breakpoint::GetAdder(
  187. THIS_
  188. OUT PDEBUG_CLIENT* Adder
  189. )
  190. {
  191. ENTER_ENGINE();
  192. *Adder = (PDEBUG_CLIENT)m_Adder;
  193. m_Adder->AddRef();
  194. LEAVE_ENGINE();
  195. return S_OK;
  196. }
  197. STDMETHODIMP
  198. Breakpoint::GetFlags(
  199. THIS_
  200. OUT PULONG Flags
  201. )
  202. {
  203. ENTER_ENGINE();
  204. *Flags = m_Flags & BREAKPOINT_EXTERNAL_FLAGS;
  205. LEAVE_ENGINE();
  206. return S_OK;
  207. }
  208. STDMETHODIMP
  209. Breakpoint::AddFlags(
  210. THIS_
  211. IN ULONG Flags
  212. )
  213. {
  214. if (Flags & ~BREAKPOINT_EXTERNAL_MODIFY_FLAGS)
  215. {
  216. return E_INVALIDARG;
  217. }
  218. ENTER_ENGINE();
  219. m_Flags |= Flags;
  220. if (m_BreakType == DEBUG_BREAKPOINT_DATA)
  221. {
  222. g_DataBreakpointsChanged = TRUE;
  223. }
  224. UpdateInternal();
  225. NotifyChanged();
  226. LEAVE_ENGINE();
  227. return S_OK;
  228. }
  229. STDMETHODIMP
  230. Breakpoint::RemoveFlags(
  231. THIS_
  232. IN ULONG Flags
  233. )
  234. {
  235. if (Flags & ~BREAKPOINT_EXTERNAL_MODIFY_FLAGS)
  236. {
  237. return E_INVALIDARG;
  238. }
  239. ENTER_ENGINE();
  240. m_Flags &= ~Flags;
  241. if (m_BreakType == DEBUG_BREAKPOINT_DATA)
  242. {
  243. g_DataBreakpointsChanged = TRUE;
  244. }
  245. UpdateInternal();
  246. NotifyChanged();
  247. LEAVE_ENGINE();
  248. return S_OK;
  249. }
  250. STDMETHODIMP
  251. Breakpoint::SetFlags(
  252. THIS_
  253. IN ULONG Flags
  254. )
  255. {
  256. if (Flags & ~BREAKPOINT_EXTERNAL_MODIFY_FLAGS)
  257. {
  258. return E_INVALIDARG;
  259. }
  260. ENTER_ENGINE();
  261. m_Flags = (m_Flags & ~BREAKPOINT_EXTERNAL_MODIFY_FLAGS) |
  262. (Flags & BREAKPOINT_EXTERNAL_MODIFY_FLAGS);
  263. if (m_BreakType == DEBUG_BREAKPOINT_DATA)
  264. {
  265. g_DataBreakpointsChanged = TRUE;
  266. }
  267. UpdateInternal();
  268. NotifyChanged();
  269. LEAVE_ENGINE();
  270. return S_OK;
  271. }
  272. STDMETHODIMP
  273. Breakpoint::GetOffset(
  274. THIS_
  275. OUT PULONG64 Offset
  276. )
  277. {
  278. if (m_Flags & DEBUG_BREAKPOINT_DEFERRED)
  279. {
  280. return E_NOINTERFACE;
  281. }
  282. ENTER_ENGINE();
  283. *Offset = Flat(m_Addr);
  284. LEAVE_ENGINE();
  285. return S_OK;
  286. }
  287. STDMETHODIMP
  288. Breakpoint::SetOffset(
  289. THIS_
  290. IN ULONG64 Offset
  291. )
  292. {
  293. if (m_Flags & DEBUG_BREAKPOINT_DEFERRED)
  294. {
  295. return E_UNEXPECTED;
  296. }
  297. ENTER_ENGINE();
  298. ADDR Addr;
  299. HRESULT Status;
  300. ADDRFLAT(&Addr, Offset);
  301. Status = SetAddr(&Addr, BREAKPOINT_WARN_MATCH);
  302. if (Status == S_OK)
  303. {
  304. NotifyChanged();
  305. }
  306. LEAVE_ENGINE();
  307. return Status;
  308. }
  309. STDMETHODIMP
  310. Breakpoint::GetDataParameters(
  311. THIS_
  312. OUT PULONG Size,
  313. OUT PULONG AccessType
  314. )
  315. {
  316. if (m_BreakType != DEBUG_BREAKPOINT_DATA)
  317. {
  318. return E_NOINTERFACE;
  319. }
  320. ENTER_ENGINE();
  321. *Size = m_DataSize;
  322. *AccessType = m_DataAccessType;
  323. LEAVE_ENGINE();
  324. return S_OK;
  325. }
  326. STDMETHODIMP
  327. Breakpoint::SetDataParameters(
  328. THIS_
  329. IN ULONG Size,
  330. IN ULONG AccessType
  331. )
  332. {
  333. if (m_BreakType != DEBUG_BREAKPOINT_DATA)
  334. {
  335. return E_NOINTERFACE;
  336. }
  337. ENTER_ENGINE();
  338. ULONG OldSize = m_DataSize;
  339. ULONG OldAccess = m_DataAccessType;
  340. HRESULT Status;
  341. m_DataSize = Size;
  342. m_DataAccessType = AccessType;
  343. Status = Validate();
  344. if (Status != S_OK)
  345. {
  346. m_DataSize = OldSize;
  347. m_DataAccessType = OldAccess;
  348. }
  349. else
  350. {
  351. g_DataBreakpointsChanged = TRUE;
  352. NotifyChanged();
  353. }
  354. LEAVE_ENGINE();
  355. return Status;
  356. }
  357. STDMETHODIMP
  358. Breakpoint::GetPassCount(
  359. THIS_
  360. OUT PULONG Count
  361. )
  362. {
  363. ENTER_ENGINE();
  364. *Count = m_PassCount;
  365. LEAVE_ENGINE();
  366. return S_OK;
  367. }
  368. STDMETHODIMP
  369. Breakpoint::SetPassCount(
  370. THIS_
  371. IN ULONG Count
  372. )
  373. {
  374. if (Count < 1)
  375. {
  376. return E_INVALIDARG;
  377. }
  378. ENTER_ENGINE();
  379. m_PassCount = Count;
  380. m_CurPassCount = Count;
  381. NotifyChanged();
  382. LEAVE_ENGINE();
  383. return S_OK;
  384. }
  385. STDMETHODIMP
  386. Breakpoint::GetCurrentPassCount(
  387. THIS_
  388. OUT PULONG Count
  389. )
  390. {
  391. ENTER_ENGINE();
  392. *Count = m_CurPassCount;
  393. LEAVE_ENGINE();
  394. return S_OK;
  395. }
  396. STDMETHODIMP
  397. Breakpoint::GetMatchThreadId(
  398. THIS_
  399. OUT PULONG Id
  400. )
  401. {
  402. HRESULT Status;
  403. ENTER_ENGINE();
  404. if (m_MatchThread)
  405. {
  406. *Id = m_MatchThread->m_UserId;
  407. Status = S_OK;
  408. }
  409. else
  410. {
  411. Status = E_NOINTERFACE;
  412. }
  413. LEAVE_ENGINE();
  414. return Status;
  415. }
  416. STDMETHODIMP
  417. Breakpoint::SetMatchThreadId(
  418. THIS_
  419. IN ULONG Id
  420. )
  421. {
  422. HRESULT Status;
  423. ENTER_ENGINE();
  424. if (IS_KERNEL_TARGET(m_Process->m_Target) &&
  425. m_BreakType == DEBUG_BREAKPOINT_DATA)
  426. {
  427. ErrOut("Kernel data breakpoints cannot be limited to a processor\n");
  428. Status = E_INVALIDARG;
  429. }
  430. else
  431. {
  432. ThreadInfo* Thread = FindAnyThreadByUserId(Id);
  433. if (Thread != NULL)
  434. {
  435. m_MatchThread = Thread;
  436. NotifyChanged();
  437. Status = S_OK;
  438. }
  439. else
  440. {
  441. Status = E_NOINTERFACE;
  442. }
  443. }
  444. LEAVE_ENGINE();
  445. return Status;
  446. }
  447. STDMETHODIMP
  448. Breakpoint::GetCommand(
  449. THIS_
  450. OUT OPTIONAL PSTR Buffer,
  451. IN ULONG BufferSize,
  452. OUT OPTIONAL PULONG CommandSize
  453. )
  454. {
  455. ENTER_ENGINE();
  456. HRESULT Status = FillStringBuffer(m_Command, m_CommandLen,
  457. Buffer, BufferSize, CommandSize);
  458. LEAVE_ENGINE();
  459. return Status;
  460. }
  461. STDMETHODIMP
  462. Breakpoint::SetCommand(
  463. THIS_
  464. IN PCSTR Command
  465. )
  466. {
  467. HRESULT Status;
  468. if (strlen(Command) >= MAX_COMMAND)
  469. {
  470. return E_INVALIDARG;
  471. }
  472. ENTER_ENGINE();
  473. Status = ChangeString((PSTR*)&m_Command, &m_CommandLen, Command);
  474. if (Status == S_OK)
  475. {
  476. NotifyChanged();
  477. }
  478. LEAVE_ENGINE();
  479. return Status;
  480. }
  481. STDMETHODIMP
  482. Breakpoint::GetOffsetExpression(
  483. THIS_
  484. OUT OPTIONAL PSTR Buffer,
  485. IN ULONG BufferSize,
  486. OUT OPTIONAL PULONG ExpressionSize
  487. )
  488. {
  489. ENTER_ENGINE();
  490. HRESULT Status = FillStringBuffer(m_OffsetExpr, m_OffsetExprLen,
  491. Buffer, BufferSize, ExpressionSize);
  492. LEAVE_ENGINE();
  493. return Status;
  494. }
  495. HRESULT
  496. Breakpoint::SetEvaluatedOffsetExpression(PCSTR Expr,
  497. BreakpointEvalResult Valid,
  498. PADDR Addr)
  499. {
  500. HRESULT Status =
  501. ChangeString((PSTR*)&m_OffsetExpr, &m_OffsetExprLen, Expr);
  502. if (Status != S_OK)
  503. {
  504. return Status;
  505. }
  506. if (Expr != NULL)
  507. {
  508. // Do initial evaluation in case the expression can be
  509. // resolved right away. This will also set the deferred
  510. // flag if the expression can't be evaluated.
  511. EvalOffsetExpr(Valid, Addr);
  512. }
  513. else
  514. {
  515. // This breakpoint is no longer deferred since there's
  516. // no way to activate it later any more.
  517. m_Flags &= ~DEBUG_BREAKPOINT_DEFERRED;
  518. UpdateInternal();
  519. }
  520. NotifyChanged();
  521. return S_OK;
  522. }
  523. STDMETHODIMP
  524. Breakpoint::SetOffsetExpression(
  525. THIS_
  526. IN PCSTR Expression
  527. )
  528. {
  529. HRESULT Status;
  530. if (strlen(Expression) >= MAX_COMMAND)
  531. {
  532. return E_INVALIDARG;
  533. }
  534. ENTER_ENGINE();
  535. ADDR Addr;
  536. Status = SetEvaluatedOffsetExpression(Expression, BPEVAL_UNKNOWN, &Addr);
  537. LEAVE_ENGINE();
  538. return Status;
  539. }
  540. STDMETHODIMP
  541. Breakpoint::GetParameters(
  542. THIS_
  543. OUT PDEBUG_BREAKPOINT_PARAMETERS Params
  544. )
  545. {
  546. ENTER_ENGINE();
  547. if (m_Flags & DEBUG_BREAKPOINT_DEFERRED)
  548. {
  549. Params->Offset = DEBUG_INVALID_OFFSET;
  550. }
  551. else
  552. {
  553. Params->Offset = Flat(m_Addr);
  554. }
  555. Params->Id = m_Id;
  556. Params->BreakType = m_BreakType;
  557. Params->ProcType = m_ProcType;
  558. Params->Flags = m_Flags & BREAKPOINT_EXTERNAL_FLAGS;
  559. if (m_BreakType == DEBUG_BREAKPOINT_DATA)
  560. {
  561. Params->DataSize = m_DataSize;
  562. Params->DataAccessType = m_DataAccessType;
  563. }
  564. else
  565. {
  566. Params->DataSize = 0;
  567. Params->DataAccessType = 0;
  568. }
  569. Params->PassCount = m_PassCount;
  570. Params->CurrentPassCount = m_CurPassCount;
  571. Params->MatchThread = m_MatchThread != NULL ?
  572. m_MatchThread->m_UserId : DEBUG_ANY_ID;
  573. Params->CommandSize = m_CommandLen;
  574. Params->OffsetExpressionSize = m_OffsetExprLen;
  575. LEAVE_ENGINE();
  576. return S_OK;
  577. }
  578. void
  579. Breakpoint::LinkIntoList(void)
  580. {
  581. Breakpoint* NextBp;
  582. Breakpoint* PrevBp;
  583. DBG_ASSERT((m_Flags & BREAKPOINT_IN_LIST) == 0);
  584. // Link into list sorted by ID.
  585. PrevBp = NULL;
  586. for (NextBp = m_Process->m_Breakpoints;
  587. NextBp != NULL;
  588. NextBp = NextBp->m_Next)
  589. {
  590. if (m_Id < NextBp->m_Id)
  591. {
  592. break;
  593. }
  594. PrevBp = NextBp;
  595. }
  596. m_Prev = PrevBp;
  597. if (PrevBp == NULL)
  598. {
  599. m_Process->m_Breakpoints = this;
  600. }
  601. else
  602. {
  603. PrevBp->m_Next = this;
  604. }
  605. m_Next = NextBp;
  606. if (NextBp == NULL)
  607. {
  608. m_Process->m_BreakpointsTail = this;
  609. }
  610. else
  611. {
  612. NextBp->m_Prev = this;
  613. }
  614. m_Flags |= BREAKPOINT_IN_LIST;
  615. m_Process->m_NumBreakpoints++;
  616. g_BreakpointListChanged = TRUE;
  617. }
  618. void
  619. Breakpoint::UnlinkFromList(void)
  620. {
  621. DBG_ASSERT(m_Flags & BREAKPOINT_IN_LIST);
  622. if (m_Prev == NULL)
  623. {
  624. m_Process->m_Breakpoints = m_Next;
  625. }
  626. else
  627. {
  628. m_Prev->m_Next = m_Next;
  629. }
  630. if (m_Next == NULL)
  631. {
  632. m_Process->m_BreakpointsTail = m_Prev;
  633. }
  634. else
  635. {
  636. m_Next->m_Prev = m_Prev;
  637. }
  638. m_Flags &= ~BREAKPOINT_IN_LIST;
  639. m_Process->m_NumBreakpoints--;
  640. g_BreakpointListChanged = TRUE;
  641. }
  642. void
  643. Breakpoint::UpdateInternal(void)
  644. {
  645. // This only has an effect with internal breakpoints.
  646. if ((m_Flags & BREAKPOINT_KD_INTERNAL) == 0)
  647. {
  648. return;
  649. }
  650. // If the breakpoint is ready turn it on, otherwise
  651. // turn it off.
  652. ULONG Flags;
  653. if ((m_Flags & (DEBUG_BREAKPOINT_ENABLED |
  654. DEBUG_BREAKPOINT_DEFERRED)) == DEBUG_BREAKPOINT_ENABLED)
  655. {
  656. Flags = (m_Flags & BREAKPOINT_KD_COUNT_ONLY) ?
  657. DBGKD_INTERNAL_BP_FLAG_COUNTONLY : 0;
  658. }
  659. else
  660. {
  661. Flags = DBGKD_INTERNAL_BP_FLAG_INVALID;
  662. }
  663. BpOut("Set internal bp at %s to %X\n",
  664. FormatAddr64(Flat(m_Addr)), Flags);
  665. if (Flags != DBGKD_INTERNAL_BP_FLAG_INVALID)
  666. {
  667. m_Process->m_Target->
  668. InsertTargetCountBreakpoint(&m_Addr, Flags);
  669. }
  670. else
  671. {
  672. m_Process->m_Target->
  673. RemoveTargetCountBreakpoint(&m_Addr);
  674. }
  675. }
  676. BreakpointEvalResult
  677. EvalAddrExpression(ProcessInfo* Process, ULONG Machine, PADDR Addr)
  678. {
  679. BOOL Error = FALSE;
  680. ULONG NumUn;
  681. StackSaveLayers Save;
  682. EvalExpression* Eval;
  683. EvalExpression* RelChain;
  684. //
  685. // This function can be reentered if evaluating an
  686. // expression causes symbol changes which provoke
  687. // reevaluation of existing address expressions.
  688. // Save away current settings to support nesting.
  689. //
  690. // Evaluate the expression in the context of the breakpoint's
  691. // machine type so that registers and such are available.
  692. ULONG OldMachine = Process->m_Target->m_EffMachineType;
  693. Process->m_Target->SetEffMachine(Machine, FALSE);
  694. SetLayersFromProcess(Process);
  695. RelChain = g_EvalReleaseChain;
  696. g_EvalReleaseChain = NULL;
  697. __try
  698. {
  699. Eval = GetCurEvaluator();
  700. Eval->m_AllowUnresolvedSymbols++;
  701. Eval->EvalCurAddr(SEGREG_CODE, Addr);
  702. NumUn = Eval->m_NumUnresolvedSymbols;
  703. ReleaseEvaluator(Eval);
  704. }
  705. __except(CommandExceptionFilter(GetExceptionInformation()))
  706. {
  707. // Skip the remainder of the command as there
  708. // was an error during processing.
  709. g_CurCmd += strlen(g_CurCmd);
  710. Error = TRUE;
  711. }
  712. g_EvalReleaseChain = RelChain;
  713. Process->m_Target->SetEffMachine(OldMachine, FALSE);
  714. if (Error)
  715. {
  716. return BPEVAL_ERROR;
  717. }
  718. else if (NumUn > 0)
  719. {
  720. return BPEVAL_UNRESOLVED;
  721. }
  722. else
  723. {
  724. ImageInfo* Image;
  725. // Check if this address falls within an existing module.
  726. for (Image = Process->m_ImageHead;
  727. Image != NULL;
  728. Image = Image->m_Next)
  729. {
  730. if (Flat(*Addr) >= Image->m_BaseOfImage &&
  731. Flat(*Addr) < Image->m_BaseOfImage + Image->m_SizeOfImage)
  732. {
  733. return BPEVAL_RESOLVED;
  734. }
  735. }
  736. return BPEVAL_RESOLVED_NO_MODULE;
  737. }
  738. }
  739. BOOL
  740. Breakpoint::EvalOffsetExpr(BreakpointEvalResult Valid, PADDR Addr)
  741. {
  742. ULONG OldFlags = m_Flags;
  743. DBG_ASSERT(m_OffsetExpr != NULL);
  744. if (Valid == BPEVAL_UNKNOWN)
  745. {
  746. PSTR CurCommand = g_CurCmd;
  747. g_CurCmd = (PSTR)m_OffsetExpr;
  748. g_DisableErrorPrint++;
  749. g_PrefixSymbols = TRUE;
  750. Valid = EvalAddrExpression(m_Process, m_ProcType, Addr);
  751. g_PrefixSymbols = FALSE;
  752. g_DisableErrorPrint--;
  753. g_CurCmd = CurCommand;
  754. }
  755. // Silently allow matching breakpoints when resolving
  756. // as it is difficult for the expression setter to know
  757. // whether there'll be matches or not at the time
  758. // the expression is set.
  759. if (Valid == BPEVAL_RESOLVED)
  760. {
  761. m_Flags &= ~DEBUG_BREAKPOINT_DEFERRED;
  762. if (SetAddr(Addr, BREAKPOINT_ALLOW_MATCH) != S_OK)
  763. {
  764. m_Flags |= DEBUG_BREAKPOINT_DEFERRED;
  765. }
  766. }
  767. else
  768. {
  769. m_Flags |= DEBUG_BREAKPOINT_DEFERRED;
  770. // The module containing the breakpoint is being
  771. // unloaded so just mark this breakpoint as not-inserted.
  772. m_Flags &= ~BREAKPOINT_INSERTED;
  773. }
  774. if ((OldFlags ^ m_Flags) & DEBUG_BREAKPOINT_DEFERRED)
  775. {
  776. // Update internal BP status.
  777. UpdateInternal();
  778. if (m_Flags & DEBUG_BREAKPOINT_DEFERRED)
  779. {
  780. BpOut("Deferring %u '%s'\n", m_Id, m_OffsetExpr);
  781. }
  782. else
  783. {
  784. BpOut("Enabling deferred %u '%s' at %s\n",
  785. m_Id, m_OffsetExpr, FormatAddr64(Flat(m_Addr)));
  786. }
  787. return TRUE;
  788. }
  789. return FALSE;
  790. }
  791. HRESULT
  792. Breakpoint::CheckAddr(PADDR Addr)
  793. {
  794. ULONG AddrSpace, AddrFlags;
  795. if (m_Process->m_Target->
  796. QueryAddressInformation(m_Process,
  797. Flat(*Addr), DBGKD_QUERY_MEMORY_VIRTUAL,
  798. &AddrSpace, &AddrFlags) != S_OK)
  799. {
  800. ErrOut("Invalid breakpoint address\n");
  801. return E_INVALIDARG;
  802. }
  803. if (m_BreakType != DEBUG_BREAKPOINT_DATA &&
  804. !(AddrFlags & DBGKD_QUERY_MEMORY_WRITE) ||
  805. (AddrFlags & DBGKD_QUERY_MEMORY_FIXED))
  806. {
  807. ErrOut("Software breakpoints cannot be used on ROM code or\n"
  808. "other read-only memory. "
  809. "Use hardware execution breakpoints (ba e) instead.\n");
  810. return E_INVALIDARG;
  811. }
  812. if (m_BreakType != DEBUG_BREAKPOINT_DATA &&
  813. AddrSpace == DBGKD_QUERY_MEMORY_SESSION)
  814. {
  815. WarnOut("WARNING: Software breakpoints on session "
  816. "addresses can cause bugchecks.\n"
  817. "Use hardware execution breakpoints (ba e) "
  818. "if possible.\n");
  819. return S_FALSE;
  820. }
  821. return S_OK;
  822. }
  823. HRESULT
  824. Breakpoint::SetAddr(PADDR Addr, BreakpointMatchAction MatchAction)
  825. {
  826. if (m_Flags & DEBUG_BREAKPOINT_DEFERRED)
  827. {
  828. // Address is unknown.
  829. return S_OK;
  830. }
  831. // Lock the breakpoint processor type to the
  832. // type of the module containing it.
  833. ULONG ProcType = m_ProcType;
  834. if (m_BreakType == DEBUG_BREAKPOINT_CODE)
  835. {
  836. ImageInfo* Image = m_Process->FindImageByOffset(Flat(*Addr), FALSE);
  837. if (Image)
  838. {
  839. ProcType = Image->GetMachineType();
  840. if (ProcType == IMAGE_FILE_MACHINE_UNKNOWN)
  841. {
  842. ProcType = m_ProcType;
  843. }
  844. }
  845. else
  846. {
  847. ProcType = m_ProcType;
  848. }
  849. }
  850. if (m_Flags & BREAKPOINT_VIRT_ADDR)
  851. {
  852. // Old flag used on ALPHA
  853. }
  854. ADDR OldAddr = m_Addr;
  855. HRESULT Valid;
  856. m_Addr = *Addr;
  857. Valid = Validate();
  858. if (Valid != S_OK)
  859. {
  860. m_Addr = OldAddr;
  861. return Valid;
  862. }
  863. if (ProcType != m_ProcType)
  864. {
  865. SetProcType(ProcType);
  866. }
  867. if (m_BreakType == DEBUG_BREAKPOINT_DATA)
  868. {
  869. g_DataBreakpointsChanged = TRUE;
  870. }
  871. if (MatchAction == BREAKPOINT_ALLOW_MATCH)
  872. {
  873. return S_OK;
  874. }
  875. for (;;)
  876. {
  877. Breakpoint* MatchBp;
  878. MatchBp = CheckMatchingBreakpoints(this, TRUE, 0xffffffff);
  879. if (MatchBp == NULL)
  880. {
  881. break;
  882. }
  883. if (MatchAction == BREAKPOINT_REMOVE_MATCH)
  884. {
  885. ULONG MoveId;
  886. WarnOut("breakpoint %u redefined\n", MatchBp->m_Id);
  887. // Move breakpoint towards lower IDs.
  888. if (MatchBp->m_Id < m_Id)
  889. {
  890. MoveId = MatchBp->m_Id;
  891. }
  892. else
  893. {
  894. MoveId = DEBUG_ANY_ID;
  895. }
  896. RemoveBreakpoint(MatchBp);
  897. if (MoveId != DEBUG_ANY_ID)
  898. {
  899. // Take over the removed ID.
  900. UnlinkFromList();
  901. m_Id = MoveId;
  902. LinkIntoList();
  903. }
  904. }
  905. else
  906. {
  907. WarnOut("Breakpoints %u and %u match\n",
  908. m_Id, MatchBp->m_Id);
  909. break;
  910. }
  911. }
  912. return S_OK;
  913. }
  914. #define INSERTION_MATCH_FLAGS \
  915. (BREAKPOINT_KD_INTERNAL | BREAKPOINT_VIRT_ADDR)
  916. BOOL
  917. Breakpoint::IsInsertionMatch(Breakpoint* Match)
  918. {
  919. if ((m_Flags & DEBUG_BREAKPOINT_DEFERRED) ||
  920. (Match->m_Flags & DEBUG_BREAKPOINT_DEFERRED) ||
  921. m_BreakType != Match->m_BreakType ||
  922. ((m_Flags ^ Match->m_Flags) & INSERTION_MATCH_FLAGS) ||
  923. !AddrEqu(m_Addr, Match->m_Addr) ||
  924. m_Process != Match->m_Process ||
  925. (m_BreakType == DEBUG_BREAKPOINT_DATA &&
  926. m_MatchThread != Match->m_MatchThread))
  927. {
  928. return FALSE;
  929. }
  930. else
  931. {
  932. return TRUE;
  933. }
  934. }
  935. #define PUBLIC_MATCH_FLAGS \
  936. (BREAKPOINT_HIDDEN | DEBUG_BREAKPOINT_ADDER_ONLY)
  937. BOOL
  938. Breakpoint::IsPublicMatch(Breakpoint* Match)
  939. {
  940. if (!IsInsertionMatch(Match) ||
  941. m_ProcType != Match->m_ProcType ||
  942. ((m_Flags ^ Match->m_Flags) & PUBLIC_MATCH_FLAGS) ||
  943. ((m_Flags & DEBUG_BREAKPOINT_ADDER_ONLY) &&
  944. m_Adder != Match->m_Adder) ||
  945. m_MatchThread != Match->m_MatchThread ||
  946. m_MatchThreadData != Match->m_MatchThreadData ||
  947. m_MatchProcessData != Match->m_MatchProcessData)
  948. {
  949. return FALSE;
  950. }
  951. else
  952. {
  953. return TRUE;
  954. }
  955. }
  956. BOOL
  957. Breakpoint::MatchesCurrentState(void)
  958. {
  959. HRESULT Status;
  960. ULONG64 ThreadData = 0, ProcData = 0;
  961. // If querying the current state fails go ahead
  962. // and return a match so that the breakpoint will
  963. // break as often as possible.
  964. if (m_MatchThreadData)
  965. {
  966. if ((Status = g_EventTarget->
  967. GetThreadInfoDataOffset(g_EventThread, 0, &ThreadData)) != S_OK)
  968. {
  969. ErrOut("Unable to determine current thread data, %s\n",
  970. FormatStatusCode(Status));
  971. return TRUE;
  972. }
  973. }
  974. if (m_MatchProcessData)
  975. {
  976. if ((Status = g_EventTarget->
  977. GetProcessInfoDataOffset(g_EventThread, 0, 0, &ProcData)) != S_OK)
  978. {
  979. ErrOut("Unable to determine current process data, %s\n",
  980. FormatStatusCode(Status));
  981. return TRUE;
  982. }
  983. }
  984. return
  985. (m_MatchThread == NULL ||
  986. m_MatchThread == g_EventThread) &&
  987. m_MatchThreadData == ThreadData &&
  988. m_MatchProcessData == ProcData;
  989. }
  990. //----------------------------------------------------------------------------
  991. //
  992. // CodeBreakpoint.
  993. //
  994. //----------------------------------------------------------------------------
  995. HRESULT
  996. CodeBreakpoint::Validate(void)
  997. {
  998. // No easy way to check for validity of offset.
  999. return S_OK;
  1000. }
  1001. HRESULT
  1002. CodeBreakpoint::Insert(void)
  1003. {
  1004. if (m_Flags & BREAKPOINT_INSERTED)
  1005. {
  1006. // Nothing to insert. This can happen in cases where
  1007. // the breakpoint remove failed.
  1008. return S_OK;
  1009. }
  1010. if (!m_Process)
  1011. {
  1012. return E_UNEXPECTED;
  1013. }
  1014. HRESULT Status;
  1015. DBG_ASSERT((m_Flags & (DEBUG_BREAKPOINT_DEFERRED |
  1016. BREAKPOINT_KD_INTERNAL)) == 0);
  1017. // Force recomputation of flat address.
  1018. NotFlat(m_Addr);
  1019. ComputeFlatAddress(&m_Addr, NULL);
  1020. Status = m_Process->m_Target->
  1021. InsertCodeBreakpoint(m_Process,
  1022. m_Process->m_Target->
  1023. m_Machines[m_ProcIndex],
  1024. &m_Addr,
  1025. m_CodeFlags,
  1026. m_InsertStorage);
  1027. if (Status == S_OK)
  1028. {
  1029. BpOut(" inserted bp %u at %s\n",
  1030. m_Id, FormatAddr64(Flat(m_Addr)));
  1031. m_Flags |= BREAKPOINT_INSERTED;
  1032. return S_OK;
  1033. }
  1034. else
  1035. {
  1036. ErrOut("Unable to insert breakpoint %u at %s, %s\n \"%s\"\n",
  1037. m_Id, FormatAddr64(Flat(m_Addr)),
  1038. FormatStatusCode(Status), FormatStatus(Status));
  1039. return Status;
  1040. }
  1041. }
  1042. HRESULT
  1043. CodeBreakpoint::Remove(void)
  1044. {
  1045. if ((m_Flags & BREAKPOINT_INSERTED) == 0)
  1046. {
  1047. // Nothing to remove. This can happen in cases where
  1048. // the breakpoint insertion failed.
  1049. return S_OK;
  1050. }
  1051. if (!m_Process)
  1052. {
  1053. return E_UNEXPECTED;
  1054. }
  1055. HRESULT Status;
  1056. DBG_ASSERT((m_Flags & (DEBUG_BREAKPOINT_DEFERRED |
  1057. BREAKPOINT_KD_INTERNAL)) == 0);
  1058. // Force recomputation of flat address.
  1059. NotFlat(m_Addr);
  1060. ComputeFlatAddress(&m_Addr, NULL);
  1061. Status = m_Process->m_Target->
  1062. RemoveCodeBreakpoint(m_Process,
  1063. m_Process->m_Target->
  1064. m_Machines[m_ProcIndex],
  1065. &m_Addr,
  1066. m_CodeFlags,
  1067. m_InsertStorage);
  1068. if (Status == S_OK)
  1069. {
  1070. BpOut(" removed bp %u from %s\n",
  1071. m_Id, FormatAddr64(Flat(m_Addr)));
  1072. m_Flags &= ~BREAKPOINT_INSERTED;
  1073. return S_OK;
  1074. }
  1075. else
  1076. {
  1077. ErrOut("Unable to remove breakpoint %u at %s, %s\n \"%s\"\n",
  1078. m_Id, FormatAddr64(Flat(m_Addr)),
  1079. FormatStatusCode(Status), FormatStatus(Status));
  1080. return Status;
  1081. }
  1082. }
  1083. ULONG
  1084. CodeBreakpoint::IsHit(PADDR Addr)
  1085. {
  1086. // Code breakpoints are code modifications and
  1087. // therefore aren't restricted to a particular
  1088. // thread.
  1089. // If this breakpoint can only match hits on
  1090. // a particular thread this is a partial hit
  1091. // because the exception occurred but it's
  1092. // being ignored.
  1093. if (AddrEqu(m_Addr, *Addr))
  1094. {
  1095. if (MatchesCurrentState())
  1096. {
  1097. return BREAKPOINT_HIT;
  1098. }
  1099. else
  1100. {
  1101. return BREAKPOINT_HIT_IGNORED;
  1102. }
  1103. }
  1104. else
  1105. {
  1106. return BREAKPOINT_NOT_HIT;
  1107. }
  1108. }
  1109. //----------------------------------------------------------------------------
  1110. //
  1111. // DataBreakpoint.
  1112. //
  1113. //----------------------------------------------------------------------------
  1114. HRESULT
  1115. DataBreakpoint::Insert(void)
  1116. {
  1117. HRESULT Status;
  1118. ThreadInfo* Thread;
  1119. DBG_ASSERT((m_Flags & (BREAKPOINT_INSERTED |
  1120. DEBUG_BREAKPOINT_DEFERRED)) == 0);
  1121. // Force recomputation of flat address for non-I/O breakpoints.
  1122. if (m_Flags & BREAKPOINT_VIRT_ADDR)
  1123. {
  1124. NotFlat(m_Addr);
  1125. ComputeFlatAddress(&m_Addr, NULL);
  1126. }
  1127. Status = m_Process->m_Target->
  1128. InsertDataBreakpoint(m_Process,
  1129. m_MatchThread,
  1130. m_Process->m_Target->
  1131. m_Machines[m_ProcIndex],
  1132. &m_Addr,
  1133. m_DataSize,
  1134. m_DataAccessType,
  1135. m_InsertStorage);
  1136. // If the target returns S_FALSE it wants
  1137. // the generic insertion processing to occur.
  1138. if (Status == S_OK)
  1139. {
  1140. BpOut(" service inserted dbp %u at %s\n",
  1141. m_Id, FormatAddr64(Flat(m_Addr)));
  1142. m_Flags |= BREAKPOINT_INSERTED;
  1143. return Status;
  1144. }
  1145. else if (Status != S_FALSE)
  1146. {
  1147. ErrOut("Unable to insert breakpoint %u at %s, %s\n \"%s\"\n",
  1148. m_Id, FormatAddr64(Flat(m_Addr)),
  1149. FormatStatusCode(Status), FormatStatus(Status));
  1150. return Status;
  1151. }
  1152. // If this breakpoint is restricted to a thread
  1153. // only modify that thread's state. Otherwise
  1154. // update all threads in the process.
  1155. Thread = m_Process->m_ThreadHead;
  1156. while (Thread)
  1157. {
  1158. if (Thread->m_NumDataBreaks >=
  1159. m_Process->m_Target->m_Machine->m_MaxDataBreakpoints)
  1160. {
  1161. ErrOut("Too many data breakpoints for %s %d\n",
  1162. IS_KERNEL_TARGET(m_Process->m_Target) ?
  1163. "processor" : "thread", Thread->m_UserId);
  1164. return HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  1165. }
  1166. else if (m_MatchThread == NULL || m_MatchThread == Thread)
  1167. {
  1168. BpOut("Add %s data bp %u to thread %u\n",
  1169. m_Process->m_Target->m_Machines[m_ProcIndex]->m_AbbrevName,
  1170. m_Id, Thread->m_UserId);
  1171. AddToThread(Thread);
  1172. }
  1173. Thread = Thread->m_Next;
  1174. }
  1175. g_UpdateDataBreakpoints = TRUE;
  1176. m_Flags |= BREAKPOINT_INSERTED;
  1177. return S_OK;
  1178. }
  1179. HRESULT
  1180. DataBreakpoint::Remove(void)
  1181. {
  1182. HRESULT Status;
  1183. if ((m_Flags & BREAKPOINT_INSERTED) == 0)
  1184. {
  1185. // Nothing to remove. This can happen in cases where
  1186. // the breakpoint insertion failed.
  1187. return S_OK;
  1188. }
  1189. DBG_ASSERT((m_Flags & DEBUG_BREAKPOINT_DEFERRED) == 0);
  1190. Status = m_Process->m_Target->
  1191. RemoveDataBreakpoint(m_Process,
  1192. m_MatchThread,
  1193. m_Process->m_Target->
  1194. m_Machines[m_ProcIndex],
  1195. &m_Addr,
  1196. m_DataSize,
  1197. m_DataAccessType,
  1198. m_InsertStorage);
  1199. // If the target returns S_FALSE it wants
  1200. // the generic removal processing to occur.
  1201. if (Status == S_OK)
  1202. {
  1203. BpOut(" service removed dbp %u at %s\n",
  1204. m_Id, FormatAddr64(Flat(m_Addr)));
  1205. m_Flags &= ~BREAKPOINT_INSERTED;
  1206. return Status;
  1207. }
  1208. else if (Status != S_FALSE)
  1209. {
  1210. ErrOut("Unable to remove breakpoint %u at %s, %s\n \"%s\"\n",
  1211. m_Id, FormatAddr64(Flat(m_Addr)),
  1212. FormatStatusCode(Status), FormatStatus(Status));
  1213. return Status;
  1214. }
  1215. // When breakpoints are inserted the data breakpoint state
  1216. // is always started completely empty so no special
  1217. // work needs to be done when removing.
  1218. g_UpdateDataBreakpoints = TRUE;
  1219. m_Flags &= ~BREAKPOINT_INSERTED;
  1220. return S_OK;
  1221. }
  1222. void
  1223. DataBreakpoint::ClearThreadDataBreaks(ThreadInfo* Thread)
  1224. {
  1225. Thread->m_NumDataBreaks = 0;
  1226. memset(Thread->m_DataBreakBps, 0, sizeof(Thread->m_DataBreakBps));
  1227. }
  1228. void
  1229. DataBreakpoint::AddToThread(ThreadInfo* Thread)
  1230. {
  1231. DBG_ASSERT(Thread->m_NumDataBreaks <
  1232. Thread->m_Process->m_Target->m_Machine->m_MaxDataBreakpoints);
  1233. Thread->m_DataBreakBps[Thread->m_NumDataBreaks] = this;
  1234. Thread->m_NumDataBreaks++;
  1235. }
  1236. //----------------------------------------------------------------------------
  1237. //
  1238. // X86DataBreakpoint.
  1239. //
  1240. //----------------------------------------------------------------------------
  1241. HRESULT
  1242. X86DataBreakpoint::Validate(void)
  1243. {
  1244. ULONG Dr7Bits;
  1245. ULONG Align;
  1246. if (!IsPow2(m_DataSize) || m_DataSize == 0 ||
  1247. (m_ProcType == IMAGE_FILE_MACHINE_AMD64 && m_DataSize > 8) ||
  1248. (m_ProcType != IMAGE_FILE_MACHINE_AMD64 && m_DataSize > 4))
  1249. {
  1250. ErrOut("Unsupported data breakpoint size\n");
  1251. return E_INVALIDARG;
  1252. }
  1253. Align = (ULONG)(Flat(m_Addr) & (m_DataSize - 1));
  1254. if (Align != 0)
  1255. {
  1256. ErrOut("Data breakpoint must be aligned\n");
  1257. return E_INVALIDARG;
  1258. }
  1259. if (m_DataSize < 8)
  1260. {
  1261. Dr7Bits = (m_DataSize - 1) << X86_DR7_LEN0_SHIFT;
  1262. }
  1263. else
  1264. {
  1265. Dr7Bits = 2 << X86_DR7_LEN0_SHIFT;
  1266. }
  1267. switch(m_DataAccessType)
  1268. {
  1269. case DEBUG_BREAK_EXECUTE:
  1270. Dr7Bits |= X86_DR7_RW0_EXECUTE;
  1271. // Code execution breakpoints must have a
  1272. // size of one.
  1273. // They must also be at the beginning
  1274. // of an instruction. This could be checked via
  1275. // examining the instructions but it doesn't seem
  1276. // that worth the trouble.
  1277. if (m_DataSize > 1)
  1278. {
  1279. ErrOut("Execution data breakpoint too large\n");
  1280. return E_INVALIDARG;
  1281. }
  1282. break;
  1283. case DEBUG_BREAK_WRITE:
  1284. Dr7Bits |= X86_DR7_RW0_WRITE;
  1285. break;
  1286. case DEBUG_BREAK_IO:
  1287. if (IS_USER_TARGET(m_Process->m_Target) ||
  1288. !(m_Process->m_Target->m_Machines[m_ProcIndex]->
  1289. GetReg32(m_Cr4Reg) & X86_CR4_DEBUG_EXTENSIONS))
  1290. {
  1291. ErrOut("I/O breakpoints not enabled\n");
  1292. return E_INVALIDARG;
  1293. }
  1294. if (Flat(m_Addr) > 0xffff)
  1295. {
  1296. ErrOut("I/O breakpoint port too large\n");
  1297. return E_INVALIDARG;
  1298. }
  1299. Dr7Bits |= X86_DR7_RW0_IO;
  1300. break;
  1301. case DEBUG_BREAK_READ:
  1302. case DEBUG_BREAK_READ | DEBUG_BREAK_WRITE:
  1303. // There is no pure read-only option so
  1304. // lump it in with read-write.
  1305. Dr7Bits |= X86_DR7_RW0_READ_WRITE;
  1306. break;
  1307. default:
  1308. ErrOut("Unsupported data breakpoint access type\n");
  1309. return E_INVALIDARG;
  1310. }
  1311. m_Dr7Bits = Dr7Bits | X86_DR7_L0_ENABLE;
  1312. if (m_DataAccessType == DEBUG_BREAK_IO)
  1313. {
  1314. m_Flags &= ~BREAKPOINT_VIRT_ADDR;
  1315. }
  1316. else
  1317. {
  1318. m_Flags |= BREAKPOINT_VIRT_ADDR;
  1319. }
  1320. return S_OK;
  1321. }
  1322. ULONG
  1323. X86DataBreakpoint::IsHit(PADDR Addr)
  1324. {
  1325. ULONG i;
  1326. ThreadInfo* Thread = g_EventThread;
  1327. HRESULT Status;
  1328. // Data breakpoints are only inserted in the contexts
  1329. // of matching threads so if the event thread doesn't match
  1330. // the breakpoint can't be hit.
  1331. if (m_MatchThread && m_MatchThread != Thread)
  1332. {
  1333. return BREAKPOINT_NOT_HIT;
  1334. }
  1335. Status = m_Process->m_Target->
  1336. IsDataBreakpointHit(Thread, &m_Addr,
  1337. m_DataSize, m_DataAccessType,
  1338. m_InsertStorage);
  1339. // If the target returns S_FALSE it wants
  1340. // the generic processing to occur.
  1341. if (Status == S_OK)
  1342. {
  1343. if (MatchesCurrentState())
  1344. {
  1345. return BREAKPOINT_HIT;
  1346. }
  1347. else
  1348. {
  1349. return BREAKPOINT_HIT_IGNORED;
  1350. }
  1351. }
  1352. else if (Status != S_FALSE)
  1353. {
  1354. return BREAKPOINT_NOT_HIT;
  1355. }
  1356. // Locate this breakpoint in the thread's data breakpoints
  1357. // if possible.
  1358. for (i = 0; i < Thread->m_NumDataBreaks; i++)
  1359. {
  1360. // Check for match in addition to equality to handle
  1361. // multiple identical data breakpoints.
  1362. if (Thread->m_DataBreakBps[i] == this ||
  1363. IsInsertionMatch(Thread->m_DataBreakBps[i]))
  1364. {
  1365. // Is this breakpoint's index set in the debug status register?
  1366. // Address is not meaningful so this is the only way to check.
  1367. if ((m_Process->m_Target->m_Machines[m_ProcIndex]->
  1368. GetReg32(m_Dr6Reg) >> i) & 1)
  1369. {
  1370. if (MatchesCurrentState())
  1371. {
  1372. return BREAKPOINT_HIT;
  1373. }
  1374. else
  1375. {
  1376. return BREAKPOINT_HIT_IGNORED;
  1377. }
  1378. }
  1379. else
  1380. {
  1381. // Breakpoint can't be listed in more than one slot
  1382. // so there's no need to finish the loop.
  1383. return BREAKPOINT_NOT_HIT;
  1384. }
  1385. }
  1386. }
  1387. return BREAKPOINT_NOT_HIT;
  1388. }
  1389. //----------------------------------------------------------------------------
  1390. //
  1391. // Ia64DataBreakpoint.
  1392. //
  1393. //----------------------------------------------------------------------------
  1394. HRESULT
  1395. Ia64DataBreakpoint::Validate(void)
  1396. {
  1397. if (!IsPow2(m_DataSize))
  1398. {
  1399. ErrOut("Hardware breakpoint size must be power of 2\n");
  1400. return E_INVALIDARG;
  1401. }
  1402. if (Flat(m_Addr) & (m_DataSize - 1))
  1403. {
  1404. ErrOut("Hardware breakpoint must be size aligned\n");
  1405. return E_INVALIDARG;
  1406. }
  1407. switch (m_DataAccessType)
  1408. {
  1409. case DEBUG_BREAK_WRITE:
  1410. case DEBUG_BREAK_READ:
  1411. case DEBUG_BREAK_READ | DEBUG_BREAK_WRITE:
  1412. break;
  1413. case DEBUG_BREAK_EXECUTE:
  1414. if (m_DataSize & 0xf)
  1415. {
  1416. if (m_DataSize > 0xf)
  1417. {
  1418. ErrOut("Execution breakpoint size must be bundle aligned.\n");
  1419. return E_INVALIDARG;
  1420. }
  1421. else
  1422. {
  1423. WarnOut("Execution breakpoint size extended to bundle size "
  1424. "(16 bytes).\n");
  1425. m_DataSize = 0x10;
  1426. }
  1427. }
  1428. break;
  1429. default:
  1430. ErrOut("Unsupported data breakpoint access type\n");
  1431. return E_INVALIDARG;
  1432. }
  1433. m_Control = GetControl(m_DataAccessType, m_DataSize);
  1434. m_Flags |= BREAKPOINT_VIRT_ADDR;
  1435. return S_OK;
  1436. }
  1437. ULONG
  1438. Ia64DataBreakpoint::IsHit(PADDR Addr)
  1439. {
  1440. HRESULT Status;
  1441. ULONG i;
  1442. ThreadInfo* Thread = g_EventThread;
  1443. // Data breakpoints are only inserted in the contexts
  1444. // of matching threads so if the event thread doesn't match
  1445. // the breakpoint can't be hit.
  1446. if (m_MatchThread && m_MatchThread != Thread)
  1447. {
  1448. return BREAKPOINT_NOT_HIT;
  1449. }
  1450. Status = m_Process->m_Target->
  1451. IsDataBreakpointHit(Thread, &m_Addr,
  1452. m_DataSize, m_DataAccessType,
  1453. m_InsertStorage);
  1454. // If the target returns S_FALSE it wants
  1455. // the generic processing to occur.
  1456. if (Status == S_OK)
  1457. {
  1458. if (MatchesCurrentState())
  1459. {
  1460. return BREAKPOINT_HIT;
  1461. }
  1462. else
  1463. {
  1464. return BREAKPOINT_HIT_IGNORED;
  1465. }
  1466. }
  1467. else if (Status != S_FALSE)
  1468. {
  1469. return BREAKPOINT_NOT_HIT;
  1470. }
  1471. // Locate this breakpoint in the thread's data breakpoints
  1472. // if possible.
  1473. for (i = 0; i < Thread->m_NumDataBreaks; i++)
  1474. {
  1475. // Check for match in addition to equality to handle
  1476. // multiple identical data breakpoints.
  1477. if (Thread->m_DataBreakBps[i] == this ||
  1478. IsInsertionMatch(Thread->m_DataBreakBps[i]))
  1479. {
  1480. if ((Flat(*Thread->m_DataBreakBps[i]->GetAddr()) ^
  1481. Flat(*Addr)) &
  1482. (m_Control & IA64_DBG_MASK_MASK))
  1483. {
  1484. // Breakpoint can't be listed in more than one slot
  1485. // so there's no need to finish the loop.
  1486. return BREAKPOINT_NOT_HIT;
  1487. }
  1488. else
  1489. {
  1490. if (MatchesCurrentState())
  1491. {
  1492. return BREAKPOINT_HIT;
  1493. }
  1494. else
  1495. {
  1496. return BREAKPOINT_HIT_IGNORED;
  1497. }
  1498. }
  1499. }
  1500. }
  1501. return BREAKPOINT_NOT_HIT;
  1502. }
  1503. ULONG64
  1504. Ia64DataBreakpoint::GetControl(ULONG AccessType, ULONG Size)
  1505. {
  1506. ULONG64 Control = (ULONG64(IA64_DBG_REG_PLM_ALL) |
  1507. ULONG64(IA64_DBG_MASK_MASK)) &
  1508. ~ULONG64(Size - 1);
  1509. switch (AccessType)
  1510. {
  1511. case DEBUG_BREAK_WRITE:
  1512. Control |= IA64_DBR_WR;
  1513. break;
  1514. case DEBUG_BREAK_READ:
  1515. Control |= IA64_DBR_RD;
  1516. break;
  1517. case DEBUG_BREAK_READ | DEBUG_BREAK_WRITE:
  1518. Control |= IA64_DBR_RDWR;
  1519. break;
  1520. case DEBUG_BREAK_EXECUTE:
  1521. Control |= IA64_DBR_EXEC;
  1522. break;
  1523. }
  1524. return Control;
  1525. }
  1526. //----------------------------------------------------------------------------
  1527. //
  1528. // X86OnIa64DataBreakpoint.
  1529. //
  1530. //----------------------------------------------------------------------------
  1531. X86OnIa64DataBreakpoint::X86OnIa64DataBreakpoint(DebugClient* Adder, ULONG Id)
  1532. : X86DataBreakpoint(Adder, Id, X86_CR4, X86_DR6, IMAGE_FILE_MACHINE_I386)
  1533. {
  1534. m_Control = 0;
  1535. }
  1536. HRESULT
  1537. X86OnIa64DataBreakpoint::Validate(void)
  1538. {
  1539. HRESULT Status = X86DataBreakpoint::Validate();
  1540. if (Status != S_OK)
  1541. {
  1542. return Status;
  1543. }
  1544. switch (m_DataAccessType)
  1545. {
  1546. case DEBUG_BREAK_WRITE:
  1547. case DEBUG_BREAK_READ:
  1548. case DEBUG_BREAK_READ | DEBUG_BREAK_WRITE:
  1549. case DEBUG_BREAK_EXECUTE:
  1550. break;
  1551. default:
  1552. ErrOut("Unsupported data breakpoint access type\n");
  1553. return E_INVALIDARG;
  1554. }
  1555. m_Control = Ia64DataBreakpoint::GetControl(m_DataAccessType, m_DataSize);
  1556. return S_OK;
  1557. }
  1558. // XXX olegk -This is pure hack
  1559. // (see X86OnIa64MachineInfo::IsBreakpointOrStepException implementation
  1560. // for more info)
  1561. ULONG
  1562. X86OnIa64DataBreakpoint::IsHit(PADDR Addr)
  1563. {
  1564. HRESULT Status;
  1565. ULONG i;
  1566. ThreadInfo* Thread = g_EventThread;
  1567. // Data breakpoints are only inserted in the contexts
  1568. // of matching threads so if the event thread doesn't match
  1569. // the breakpoint can't be hit.
  1570. if (m_MatchThread && m_MatchThread != Thread)
  1571. {
  1572. return BREAKPOINT_NOT_HIT;
  1573. }
  1574. Status = m_Process->m_Target->
  1575. IsDataBreakpointHit(Thread, &m_Addr,
  1576. m_DataSize, m_DataAccessType,
  1577. m_InsertStorage);
  1578. // If the target returns S_FALSE it wants
  1579. // the generic processing to occur.
  1580. if (Status == S_OK)
  1581. {
  1582. if (MatchesCurrentState())
  1583. {
  1584. return BREAKPOINT_HIT;
  1585. }
  1586. else
  1587. {
  1588. return BREAKPOINT_HIT_IGNORED;
  1589. }
  1590. }
  1591. else if (Status != S_FALSE)
  1592. {
  1593. return BREAKPOINT_NOT_HIT;
  1594. }
  1595. // Locate this breakpoint in the thread's data breakpoints
  1596. // if possible.
  1597. for (i = 0; i < Thread->m_NumDataBreaks; i++)
  1598. {
  1599. // Check for match in addition to equality to handle
  1600. // multiple identical data breakpoints.
  1601. if (Thread->m_DataBreakBps[i] == this ||
  1602. IsInsertionMatch(Thread->m_DataBreakBps[i]))
  1603. {
  1604. if (((ULONG)Flat(*Thread->m_DataBreakBps[i]->GetAddr()) ^
  1605. (ULONG)Flat(*Addr)) &
  1606. (ULONG)(m_Control & IA64_DBG_MASK_MASK))
  1607. {
  1608. // Breakpoint can't be listed in more than one slot
  1609. // so there's no need to finish the loop.
  1610. return BREAKPOINT_NOT_HIT;
  1611. }
  1612. else
  1613. {
  1614. if (MatchesCurrentState())
  1615. {
  1616. return BREAKPOINT_HIT;
  1617. }
  1618. else
  1619. {
  1620. return BREAKPOINT_HIT_IGNORED;
  1621. }
  1622. }
  1623. }
  1624. }
  1625. return BREAKPOINT_NOT_HIT;
  1626. }
  1627. //----------------------------------------------------------------------------
  1628. //
  1629. // Functions.
  1630. //
  1631. //----------------------------------------------------------------------------
  1632. BOOL
  1633. BreakpointNeedsToBeDeferred(Breakpoint* Bp,
  1634. ProcessInfo* Process, PADDR PcAddr)
  1635. {
  1636. if (Process && IS_CONTEXT_POSSIBLE(Process->m_Target) &&
  1637. (Bp->m_Process == Process))
  1638. {
  1639. // If this breakpoint matches the current IP and
  1640. // the current thread is going to be running
  1641. // we can't insert the breakpoint as the thread
  1642. // needs to run the real code.
  1643. if ((Bp->m_Flags & BREAKPOINT_VIRT_ADDR) &&
  1644. AddrEqu(*Bp->GetAddr(), *PcAddr) &&
  1645. ThreadWillResume(g_EventThread))
  1646. {
  1647. return TRUE;
  1648. }
  1649. if ((Bp == g_LastBreakpointHit) && Bp->PcAtHit() &&
  1650. AddrEqu(g_LastBreakpointHitPc, *PcAddr))
  1651. {
  1652. if (g_ContextChanged)
  1653. {
  1654. WarnOut("Breakpoint %u will not be deferred because of "
  1655. "changes in the context. Breakpoint may hit again.\n",
  1656. Bp->m_Id);
  1657. return FALSE;
  1658. }
  1659. return TRUE;
  1660. }
  1661. }
  1662. return FALSE;
  1663. }
  1664. //----------------------------------------------------------------------------
  1665. //
  1666. // Modify debuggee to activate current breakpoints.
  1667. //
  1668. //----------------------------------------------------------------------------
  1669. HRESULT
  1670. InsertBreakpoints(void)
  1671. {
  1672. HRESULT Status = S_OK;
  1673. ADDR PcAddr;
  1674. BOOL DeferredData = FALSE;
  1675. ThreadInfo* OldThread;
  1676. if (g_Thread != NULL)
  1677. {
  1678. // Aggressively clear this flag always in order to be
  1679. // as conservative as possible when recognizing
  1680. // trace events. We would rather misrecognize
  1681. // single-step events and break in instead of
  1682. // misrecognizing an app-generated single-step and
  1683. // ignoring it.
  1684. g_Thread->m_Flags &= ~ENG_THREAD_DEFER_BP_TRACE;
  1685. }
  1686. if ((g_EngStatus & ENG_STATUS_BREAKPOINTS_INSERTED) ||
  1687. (g_EngStatus & ENG_STATUS_SUSPENDED) == 0)
  1688. {
  1689. return Status;
  1690. }
  1691. g_DeferDefined = FALSE;
  1692. ADDRFLAT(&PcAddr, 0);
  1693. // Switch to the event thread to get the event thread's
  1694. // PC so we can see if we need to defer breakpoints in
  1695. // order to allow the event thread to keep running.
  1696. if (g_EventTarget)
  1697. {
  1698. OldThread = g_EventTarget->m_RegContextThread;
  1699. g_EventTarget->ChangeRegContext(g_EventThread);
  1700. }
  1701. if (g_BreakpointsSuspended)
  1702. {
  1703. goto StepTraceOnly;
  1704. }
  1705. //
  1706. // Turn off all data breakpoints. (We will turn the enabled ones back
  1707. // on when we restart execution).
  1708. //
  1709. TargetInfo* Target;
  1710. // Allow target to prepare for breakpoint insertion.
  1711. ForAllLayersToTarget()
  1712. {
  1713. if ((Status = Target->BeginInsertingBreakpoints()) != S_OK)
  1714. {
  1715. return Status;
  1716. }
  1717. }
  1718. if (IS_CONTEXT_POSSIBLE(g_EventTarget))
  1719. {
  1720. g_EventTarget->m_EffMachine->GetPC(&PcAddr);
  1721. }
  1722. BpOut("InsertBreakpoints PC ");
  1723. if (IS_CONTEXT_POSSIBLE(g_EventTarget))
  1724. {
  1725. MaskOutAddr(DEBUG_IOUTPUT_BREAKPOINT, &PcAddr);
  1726. BpOut("\n");
  1727. }
  1728. else
  1729. {
  1730. BpOut("?\n");
  1731. }
  1732. //
  1733. // Set any appropriate permanent breakpoints.
  1734. //
  1735. Breakpoint* Bp;
  1736. ProcessInfo* Process;
  1737. ForAllLayersToProcess()
  1738. {
  1739. BpOut(" Process %d with %d bps\n", Process->m_UserId,
  1740. Process->m_NumBreakpoints);
  1741. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  1742. {
  1743. if (Bp->IsNormalEnabled() &&
  1744. (g_CmdState == 'g' ||
  1745. (Bp->m_Flags & DEBUG_BREAKPOINT_GO_ONLY) == 0))
  1746. {
  1747. Bp->ForceFlatAddr();
  1748. // Check if this breakpoint matches a previously
  1749. // inserted breakpoint. If so there's no need
  1750. // to insert this one.
  1751. Breakpoint* MatchBp;
  1752. for (MatchBp = Bp->m_Prev;
  1753. MatchBp != NULL;
  1754. MatchBp = MatchBp->m_Prev)
  1755. {
  1756. if ((MatchBp->m_Flags & BREAKPOINT_INSERTED) &&
  1757. Bp->IsInsertionMatch(MatchBp))
  1758. {
  1759. break;
  1760. }
  1761. }
  1762. if (MatchBp != NULL)
  1763. {
  1764. // Skip this breakpoint. It won't be marked as
  1765. // inserted so Remove is automatically handled.
  1766. continue;
  1767. }
  1768. if (BreakpointNeedsToBeDeferred(Bp,
  1769. g_EventProcess, &PcAddr))
  1770. {
  1771. g_DeferDefined = TRUE;
  1772. if (Bp->m_BreakType == DEBUG_BREAKPOINT_DATA)
  1773. {
  1774. DeferredData = TRUE;
  1775. // Force data breakpoint addresses to
  1776. // get updated because a dbp will now
  1777. // be missing.
  1778. g_DataBreakpointsChanged = TRUE;
  1779. }
  1780. BpOut(" deferred bp %u, dd %d\n",
  1781. Bp->m_Id, DeferredData);
  1782. }
  1783. else
  1784. {
  1785. HRESULT InsertStatus;
  1786. InsertStatus = Bp->Insert();
  1787. if (InsertStatus != S_OK)
  1788. {
  1789. if (Bp->m_Flags & DEBUG_BREAKPOINT_GO_ONLY)
  1790. {
  1791. ErrOut("go ");
  1792. }
  1793. ErrOut("bp%u at ", Bp->m_Id);
  1794. MaskOutAddr(DEBUG_OUTPUT_ERROR, Bp->GetAddr());
  1795. ErrOut("failed\n");
  1796. Status = InsertStatus;
  1797. }
  1798. }
  1799. }
  1800. }
  1801. }
  1802. ForAllLayersToTarget()
  1803. {
  1804. Target->EndInsertingBreakpoints();
  1805. }
  1806. // If we deferred a data breakpoint we haven't
  1807. // fully updated the data breakpoint state
  1808. // so leave the update flags set.
  1809. if (g_UpdateDataBreakpoints && !DeferredData)
  1810. {
  1811. g_UpdateDataBreakpoints = FALSE;
  1812. g_DataBreakpointsChanged = FALSE;
  1813. }
  1814. BpOut(" after insert udb %d, dbc %d\n",
  1815. g_UpdateDataBreakpoints, g_DataBreakpointsChanged);
  1816. StepTraceOnly:
  1817. // set the step/trace breakpoint if appropriate
  1818. if (g_StepTraceBp->m_Flags & DEBUG_BREAKPOINT_ENABLED)
  1819. {
  1820. BpOut("Step/trace addr = ");
  1821. MaskOutAddr(DEBUG_IOUTPUT_BREAKPOINT, g_StepTraceBp->GetAddr());
  1822. BpOut("\n");
  1823. if (Flat(*g_StepTraceBp->GetAddr()) == OFFSET_TRACE)
  1824. {
  1825. ThreadInfo* StepRegThread;
  1826. Target = g_StepTraceBp->m_Process->m_Target;
  1827. if (g_StepTraceBp->m_MatchThread &&
  1828. IS_USER_TARGET(Target))
  1829. {
  1830. StepRegThread = Target->m_RegContextThread;
  1831. Target->ChangeRegContext(g_StepTraceBp->m_MatchThread);
  1832. }
  1833. BpOut("Setting trace flag for step/trace thread %d:%x\n",
  1834. Target->m_RegContextThread ?
  1835. Target->m_RegContextThread->m_UserId : 0,
  1836. Target->m_RegContextThread ?
  1837. Target->m_RegContextThread->m_SystemId : 0);
  1838. Target->m_EffMachine->
  1839. QuietSetTraceMode(g_StepTraceCmdState == 'b' ?
  1840. TRACE_TAKEN_BRANCH :
  1841. TRACE_INSTRUCTION);
  1842. if (g_StepTraceBp->m_MatchThread &&
  1843. IS_USER_TARGET(Target))
  1844. {
  1845. Target->ChangeRegContext(StepRegThread);
  1846. }
  1847. }
  1848. else if (IS_CONTEXT_POSSIBLE(g_EventTarget) &&
  1849. AddrEqu(*g_StepTraceBp->GetAddr(), PcAddr))
  1850. {
  1851. BpOut("Setting defer flag for step/trace\n");
  1852. g_DeferDefined = TRUE;
  1853. }
  1854. else if (CheckMatchingBreakpoints(g_StepTraceBp, FALSE,
  1855. BREAKPOINT_INSERTED))
  1856. {
  1857. // There's already a breakpoint inserted at the
  1858. // step/trace address so we don't need to set another.
  1859. BpOut("Trace bp matches existing bp\n");
  1860. }
  1861. else
  1862. {
  1863. if (g_StepTraceBp->Insert() != S_OK)
  1864. {
  1865. ErrOut("Trace bp at addr ");
  1866. MaskOutAddr(DEBUG_OUTPUT_ERROR, g_StepTraceBp->GetAddr());
  1867. ErrOut("failed\n");
  1868. Status = E_FAIL;
  1869. }
  1870. else
  1871. {
  1872. BpOut("Trace bp at addr ");
  1873. MaskOutAddr(DEBUG_IOUTPUT_BREAKPOINT,
  1874. g_StepTraceBp->GetAddr());
  1875. BpOut("succeeded\n");
  1876. }
  1877. }
  1878. }
  1879. // Process deferred breakpoint.
  1880. // If a deferred breakpoint is active it means that
  1881. // the debugger needs to do some work on the current instruction
  1882. // so it wants to step forward one instruction and then
  1883. // get control back. The deferred breakpoint forces a break
  1884. // back to the debugger as soon as possible so that it
  1885. // can carry out any deferred work.
  1886. if (g_DeferDefined)
  1887. {
  1888. ULONG NextMachine;
  1889. g_DeferBp->m_Process = g_EventProcess;
  1890. g_EventTarget->m_EffMachine->
  1891. GetNextOffset(g_EventProcess, FALSE,
  1892. g_DeferBp->GetAddr(), &NextMachine);
  1893. g_DeferBp->SetProcType(NextMachine);
  1894. BpOut("Defer addr = ");
  1895. MaskOutAddr(DEBUG_IOUTPUT_BREAKPOINT, g_DeferBp->GetAddr());
  1896. BpOut("\n");
  1897. if ((g_EngOptions & DEBUG_ENGOPT_SYNCHRONIZE_BREAKPOINTS) &&
  1898. IS_USER_TARGET(g_Target) &&
  1899. !IsSelectedExecutionThread(NULL, SELTHREAD_ANY))
  1900. {
  1901. // The user wants breakpoint management to occur
  1902. // precisely in order to properly handle breakpoints
  1903. // in code executed by multiple threads. Force
  1904. // the defer thread to be the only thread executing
  1905. // in order to avoid other threads running through
  1906. // the breakpoint location or generating events.
  1907. SelectExecutionThread(g_EventThread, SELTHREAD_INTERNAL_THREAD);
  1908. }
  1909. if (Flat(*g_DeferBp->GetAddr()) == OFFSET_TRACE)
  1910. {
  1911. BpOut("Setting trace flag for defer thread %d:%x\n",
  1912. g_EventTarget->m_RegContextThread ?
  1913. g_EventTarget->m_RegContextThread->m_UserId : 0,
  1914. g_EventTarget->m_RegContextThread ?
  1915. g_EventTarget->m_RegContextThread->m_SystemId : 0);
  1916. g_EventTarget->m_EffMachine->
  1917. QuietSetTraceMode(TRACE_INSTRUCTION);
  1918. if (IS_USER_TARGET(g_EventTarget) &&
  1919. g_EventThread != NULL)
  1920. {
  1921. // If the debugger is setting the trace flag
  1922. // for the current thread remember that it
  1923. // did so in order to properly recognize
  1924. // debugger-provoked single-step events even
  1925. // when events occur on other threads before
  1926. // the single-step event comes back.
  1927. g_EventThread->m_Flags |=
  1928. ENG_THREAD_DEFER_BP_TRACE;
  1929. }
  1930. }
  1931. else
  1932. {
  1933. // If an existing breakpoint or the step/trace breakpoint
  1934. // isn't already set on the next offset, insert the deferred
  1935. // breakpoint.
  1936. if (CheckMatchingBreakpoints(g_DeferBp, FALSE,
  1937. BREAKPOINT_INSERTED) == NULL &&
  1938. ((g_StepTraceBp->m_Flags & BREAKPOINT_INSERTED) == 0 ||
  1939. !AddrEqu(*g_StepTraceBp->GetAddr(), *g_DeferBp->GetAddr())))
  1940. {
  1941. if (g_DeferBp->Insert() != S_OK)
  1942. {
  1943. ErrOut("Deferred bp at addr ");
  1944. MaskOutAddr(DEBUG_OUTPUT_ERROR, g_DeferBp->GetAddr());
  1945. ErrOut("failed\n");
  1946. Status = E_FAIL;
  1947. }
  1948. else
  1949. {
  1950. BpOut("Deferred bp at addr ");
  1951. MaskOutAddr(DEBUG_IOUTPUT_BREAKPOINT,
  1952. g_DeferBp->GetAddr());
  1953. BpOut("succeeded\n");
  1954. }
  1955. }
  1956. else
  1957. {
  1958. BpOut("Defer bp matches existing bp\n");
  1959. }
  1960. }
  1961. }
  1962. if (g_EventTarget)
  1963. {
  1964. g_EventTarget->ChangeRegContext(OldThread);
  1965. }
  1966. // Always consider breakpoints inserted since some
  1967. // of them may have been inserted even if some failed.
  1968. g_EngStatus |= ENG_STATUS_BREAKPOINTS_INSERTED;
  1969. return Status;
  1970. }
  1971. //----------------------------------------------------------------------------
  1972. //
  1973. // Reverse any debuggee changes caused by breakpoint insertion.
  1974. //
  1975. //----------------------------------------------------------------------------
  1976. HRESULT
  1977. RemoveBreakpoints(void)
  1978. {
  1979. if ((g_EngStatus & ENG_STATUS_BREAKPOINTS_INSERTED) == 0 ||
  1980. (g_EngStatus & ENG_STATUS_SUSPENDED) == 0)
  1981. {
  1982. return S_FALSE; // do nothing
  1983. }
  1984. BpOut("RemoveBreakpoints\n");
  1985. // restore the deferred breakpoint if set
  1986. g_DeferBp->Remove();
  1987. // restore the step/trace breakpoint if set
  1988. g_StepTraceBp->Remove();
  1989. if (!g_BreakpointsSuspended)
  1990. {
  1991. //
  1992. // Restore any appropriate permanent breakpoints (reverse order).
  1993. //
  1994. TargetInfo* Target;
  1995. ProcessInfo* Process;
  1996. Breakpoint* Bp;
  1997. ForAllLayersToTarget()
  1998. {
  1999. Target->BeginRemovingBreakpoints();
  2000. }
  2001. ForAllLayersToProcess()
  2002. {
  2003. BpOut(" Process %d with %d bps\n", Process->m_UserId,
  2004. Process->m_NumBreakpoints);
  2005. for (Bp = Process->m_BreakpointsTail;
  2006. Bp != NULL;
  2007. Bp = Bp->m_Prev)
  2008. {
  2009. Bp->Remove();
  2010. }
  2011. }
  2012. ForAllLayersToTarget()
  2013. {
  2014. Target->EndRemovingBreakpoints();
  2015. }
  2016. }
  2017. g_EngStatus &= ~ENG_STATUS_BREAKPOINTS_INSERTED;
  2018. return S_OK;
  2019. }
  2020. //----------------------------------------------------------------------------
  2021. //
  2022. // Create a new breakpoint object.
  2023. //
  2024. //----------------------------------------------------------------------------
  2025. HRESULT
  2026. AddBreakpoint(DebugClient* Client,
  2027. MachineInfo* Machine,
  2028. ULONG Type,
  2029. ULONG DesiredId,
  2030. Breakpoint** RetBp)
  2031. {
  2032. Breakpoint* Bp;
  2033. ULONG Id;
  2034. TargetInfo* Target;
  2035. ProcessInfo* Process;
  2036. if (DesiredId == DEBUG_ANY_ID)
  2037. {
  2038. // Find the lowest unused ID across all processes.
  2039. // Breakpoint IDs are kept unique across all
  2040. // breakpoints to prevent user confusion and also
  2041. // to give extensions a unique ID for breakpoints.
  2042. Id = 0;
  2043. Restart:
  2044. // Search all bps to see if the current ID is in use.
  2045. ForAllLayersToProcess()
  2046. {
  2047. for (Bp = Process->m_Breakpoints; Bp; Bp = Bp->m_Next)
  2048. {
  2049. if (Bp->m_Id == Id)
  2050. {
  2051. // A breakpoint is already using the current ID.
  2052. // Try the next one.
  2053. Id++;
  2054. goto Restart;
  2055. }
  2056. }
  2057. }
  2058. }
  2059. else
  2060. {
  2061. // Check to see if the desired ID is in use.
  2062. ForAllLayersToProcess()
  2063. {
  2064. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  2065. {
  2066. if (Bp->m_Id == DesiredId)
  2067. {
  2068. return E_INVALIDARG;
  2069. }
  2070. }
  2071. }
  2072. Id = DesiredId;
  2073. }
  2074. HRESULT Status = Machine->NewBreakpoint(Client, Type, Id, &Bp);
  2075. if (Status != S_OK)
  2076. {
  2077. return Status;
  2078. }
  2079. *RetBp = Bp;
  2080. Bp->LinkIntoList();
  2081. // If this is an internal, hidden breakpoint set
  2082. // the flag immediately and do not notify.
  2083. if (Type & BREAKPOINT_HIDDEN)
  2084. {
  2085. Bp->m_Flags |= BREAKPOINT_HIDDEN;
  2086. }
  2087. else
  2088. {
  2089. NotifyChangeEngineState(DEBUG_CES_BREAKPOINTS, Id, TRUE);
  2090. }
  2091. return S_OK;
  2092. }
  2093. //----------------------------------------------------------------------------
  2094. //
  2095. // Delete a breakpoint object.
  2096. //
  2097. //----------------------------------------------------------------------------
  2098. void
  2099. RemoveBreakpoint(Breakpoint* Bp)
  2100. {
  2101. ULONG Id = Bp->m_Id;
  2102. ULONG Flags = Bp->m_Flags;
  2103. Bp->Relinquish();
  2104. if ((Flags & BREAKPOINT_HIDDEN) == 0)
  2105. {
  2106. NotifyChangeEngineState(DEBUG_CES_BREAKPOINTS, Id, TRUE);
  2107. }
  2108. }
  2109. //----------------------------------------------------------------------------
  2110. //
  2111. // Clean up breakpoints owned by a particular process or thread.
  2112. //
  2113. //----------------------------------------------------------------------------
  2114. void
  2115. RemoveProcessBreakpoints(ProcessInfo* Process)
  2116. {
  2117. g_EngNotify++;
  2118. Breakpoint* Bp;
  2119. Breakpoint* NextBp;
  2120. BOOL NeedNotify = FALSE;
  2121. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = NextBp)
  2122. {
  2123. NextBp = Bp->m_Next;
  2124. DBG_ASSERT(Bp->m_Process == Process);
  2125. RemoveBreakpoint(Bp);
  2126. NeedNotify = TRUE;
  2127. }
  2128. g_EngNotify--;
  2129. if (NeedNotify)
  2130. {
  2131. NotifyChangeEngineState(DEBUG_CES_BREAKPOINTS, DEBUG_ANY_ID, TRUE);
  2132. }
  2133. }
  2134. void
  2135. RemoveThreadBreakpoints(ThreadInfo* Thread)
  2136. {
  2137. g_EngNotify++;
  2138. Breakpoint* Bp;
  2139. Breakpoint* NextBp;
  2140. BOOL NeedNotify = FALSE;
  2141. DBG_ASSERT(Thread->m_Process);
  2142. for (Bp = Thread->m_Process->m_Breakpoints; Bp != NULL; Bp = NextBp)
  2143. {
  2144. NextBp = Bp->m_Next;
  2145. DBG_ASSERT(Bp->m_Process == Thread->m_Process);
  2146. if (Bp->m_MatchThread == Thread)
  2147. {
  2148. RemoveBreakpoint(Bp);
  2149. NeedNotify = TRUE;
  2150. }
  2151. }
  2152. g_EngNotify--;
  2153. if (NeedNotify)
  2154. {
  2155. NotifyChangeEngineState(DEBUG_CES_BREAKPOINTS, DEBUG_ANY_ID, TRUE);
  2156. }
  2157. }
  2158. //----------------------------------------------------------------------------
  2159. //
  2160. // Remove all breakpoints and reset breakpoint state.
  2161. //
  2162. //----------------------------------------------------------------------------
  2163. void
  2164. RemoveAllBreakpoints(ULONG Reason)
  2165. {
  2166. TargetInfo* Target;
  2167. ProcessInfo* Process;
  2168. g_EngNotify++;
  2169. ForAllLayersToProcess()
  2170. {
  2171. while (Process->m_Breakpoints != NULL)
  2172. {
  2173. RemoveBreakpoint(Process->m_Breakpoints);
  2174. }
  2175. }
  2176. g_EngNotify--;
  2177. NotifyChangeEngineState(DEBUG_CES_BREAKPOINTS, DEBUG_ANY_ID, TRUE);
  2178. g_NumGoBreakpoints = 0;
  2179. // If the machine is not waiting for commands we can't
  2180. // remove breakpoints. This happens when rebooting or
  2181. // when a wait doesn't successfully receive a state change.
  2182. if (Reason != DEBUG_SESSION_REBOOT &&
  2183. Reason != DEBUG_SESSION_HIBERNATE &&
  2184. Reason != DEBUG_SESSION_FAILURE &&
  2185. (g_EngStatus & ENG_STATUS_WAIT_SUCCESSFUL))
  2186. {
  2187. ForAllLayersToTarget()
  2188. {
  2189. Target->RemoveAllTargetBreakpoints();
  2190. ForTargetProcesses(Target)
  2191. {
  2192. Target->RemoveAllDataBreakpoints(Process);
  2193. }
  2194. }
  2195. }
  2196. // Always update data breakpoints the very first time in
  2197. // order to flush out any stale data breakpoints.
  2198. g_UpdateDataBreakpoints = TRUE;
  2199. g_DataBreakpointsChanged = FALSE;
  2200. g_BreakpointsSuspended = FALSE;
  2201. g_DeferDefined = FALSE;
  2202. }
  2203. //----------------------------------------------------------------------------
  2204. //
  2205. // Look up breakpoints.
  2206. //
  2207. //----------------------------------------------------------------------------
  2208. Breakpoint*
  2209. GetBreakpointByIndex(DebugClient* Client, ULONG Index)
  2210. {
  2211. Breakpoint* Bp;
  2212. DBG_ASSERT(g_Process);
  2213. for (Bp = g_Process->m_Breakpoints;
  2214. Bp != NULL && Index > 0;
  2215. Bp = Bp->m_Next)
  2216. {
  2217. Index--;
  2218. }
  2219. if (Bp != NULL &&
  2220. (Bp->m_Flags & BREAKPOINT_HIDDEN) == 0 &&
  2221. ((Bp->m_Flags & DEBUG_BREAKPOINT_ADDER_ONLY) == 0 ||
  2222. Bp->m_Adder == Client))
  2223. {
  2224. return Bp;
  2225. }
  2226. return NULL;
  2227. }
  2228. Breakpoint*
  2229. GetBreakpointById(DebugClient* Client, ULONG Id)
  2230. {
  2231. Breakpoint* Bp;
  2232. DBG_ASSERT(g_Process);
  2233. for (Bp = g_Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  2234. {
  2235. if (Bp->m_Id == Id)
  2236. {
  2237. if ((Bp->m_Flags & BREAKPOINT_HIDDEN) == 0 &&
  2238. ((Bp->m_Flags & DEBUG_BREAKPOINT_ADDER_ONLY) == 0 ||
  2239. Bp->m_Adder == Client))
  2240. {
  2241. return Bp;
  2242. }
  2243. break;
  2244. }
  2245. }
  2246. return NULL;
  2247. }
  2248. //----------------------------------------------------------------------------
  2249. //
  2250. // Check to see if two breakpoints refer to the same breakpoint
  2251. // conditions.
  2252. //
  2253. //----------------------------------------------------------------------------
  2254. Breakpoint*
  2255. CheckMatchingBreakpoints(Breakpoint* Match, BOOL Public, ULONG IncFlags)
  2256. {
  2257. Breakpoint* Bp;
  2258. for (Bp = Match->m_Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  2259. {
  2260. if (Bp == Match || (Bp->m_Flags & IncFlags) == 0)
  2261. {
  2262. continue;
  2263. }
  2264. if ((Public && Bp->IsPublicMatch(Match)) ||
  2265. (!Public && Bp->IsInsertionMatch(Match)))
  2266. {
  2267. return Bp;
  2268. }
  2269. }
  2270. return NULL;
  2271. }
  2272. //----------------------------------------------------------------------------
  2273. //
  2274. // Starting at the given breakpoint, check to see if a breakpoint
  2275. // is hit with the current processor state. Breakpoint types
  2276. // can be included or excluded by flags.
  2277. //
  2278. //----------------------------------------------------------------------------
  2279. Breakpoint*
  2280. CheckBreakpointHit(ProcessInfo* Process, Breakpoint* Start, PADDR Addr,
  2281. ULONG ExbsType, ULONG IncFlags, ULONG ExcFlags,
  2282. PULONG HitType,
  2283. BOOL SetLastBreakpointHit)
  2284. {
  2285. DBG_ASSERT(ExbsType & EXBS_BREAKPOINT_ANY);
  2286. ULONG BreakType;
  2287. switch(ExbsType)
  2288. {
  2289. case EXBS_BREAKPOINT_CODE:
  2290. BreakType = DEBUG_BREAKPOINT_CODE;
  2291. break;
  2292. case EXBS_BREAKPOINT_DATA:
  2293. BreakType = DEBUG_BREAKPOINT_DATA;
  2294. break;
  2295. default:
  2296. ExbsType = EXBS_BREAKPOINT_ANY;
  2297. break;
  2298. }
  2299. Breakpoint* Bp;
  2300. BpOut("CheckBp addr ");
  2301. MaskOutAddr(DEBUG_IOUTPUT_BREAKPOINT, Addr);
  2302. BpOut("\n");
  2303. for (Bp = (Start == NULL ? Process->m_Breakpoints : Start);
  2304. Bp != NULL;
  2305. Bp = Bp->m_Next)
  2306. {
  2307. // Allow different kinds of breakpoints to be scanned
  2308. // separately if desired.
  2309. if ((ExbsType != EXBS_BREAKPOINT_ANY &&
  2310. Bp->m_BreakType != BreakType) ||
  2311. (Bp->m_Flags & IncFlags) == 0 ||
  2312. (Bp->m_Flags & ExcFlags) != 0)
  2313. {
  2314. continue;
  2315. }
  2316. // Common code is inlined here rather than in the
  2317. // base class because both pre- and post-derived
  2318. // checks are necessary.
  2319. // Force recomputation of flat address.
  2320. if (Bp->m_Flags & BREAKPOINT_VIRT_ADDR)
  2321. {
  2322. NotFlat(*Bp->GetAddr());
  2323. ComputeFlatAddress(Bp->GetAddr(), NULL);
  2324. }
  2325. if (Bp->IsNormalEnabled())
  2326. {
  2327. // We've got a partial match. Further checks
  2328. // depend on what kind of breakpoint it is.
  2329. *HitType = Bp->IsHit(Addr);
  2330. if (*HitType != BREAKPOINT_NOT_HIT)
  2331. {
  2332. // Do a final check for the pass count. If the
  2333. // pass count is nonzero this will become a partial hit.
  2334. if (*HitType == BREAKPOINT_HIT &&
  2335. !Bp->PassHit())
  2336. {
  2337. *HitType = BREAKPOINT_HIT_IGNORED;
  2338. }
  2339. BpOut(" hit %u\n", Bp->m_Id);
  2340. if (SetLastBreakpointHit)
  2341. {
  2342. g_LastBreakpointHit = Bp;
  2343. g_Target->m_EffMachine->GetPC(&g_LastBreakpointHitPc);
  2344. }
  2345. return Bp;
  2346. }
  2347. }
  2348. }
  2349. BpOut(" no hit\n");
  2350. *HitType = BREAKPOINT_NOT_HIT;
  2351. if (SetLastBreakpointHit)
  2352. {
  2353. g_LastBreakpointHit = NULL;
  2354. ZeroMemory(&g_LastBreakpointHitPc, sizeof(g_LastBreakpointHitPc));
  2355. }
  2356. return NULL;
  2357. }
  2358. //----------------------------------------------------------------------------
  2359. //
  2360. // Walk the breakpoint list and invoke event callbacks for
  2361. // any breakpoints that need it. Watch for and handle list changes
  2362. // caused by callbacks.
  2363. //
  2364. //----------------------------------------------------------------------------
  2365. ULONG
  2366. NotifyHitBreakpoints(ULONG EventStatus)
  2367. {
  2368. Breakpoint* Bp;
  2369. TargetInfo* Target;
  2370. ProcessInfo* Process;
  2371. Restart:
  2372. g_BreakpointListChanged = FALSE;
  2373. ForAllLayersToProcess()
  2374. {
  2375. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  2376. {
  2377. if (Bp->m_Flags & BREAKPOINT_NOTIFY)
  2378. {
  2379. // Ensure the breakpoint isn't cleaned up before
  2380. // we're done with it.
  2381. Bp->Preserve();
  2382. Bp->m_Flags &= ~BREAKPOINT_NOTIFY;
  2383. EventStatus = NotifyBreakpointEvent(EventStatus, Bp);
  2384. if (Bp->m_Flags & DEBUG_BREAKPOINT_ONE_SHOT)
  2385. {
  2386. RemoveBreakpoint(Bp);
  2387. }
  2388. Bp->Relinquish();
  2389. // If the callback caused the breakpoint list to
  2390. // change we can no longer rely on the pointer
  2391. // we have and we need to restart the iteration.
  2392. if (g_BreakpointListChanged)
  2393. {
  2394. goto Restart;
  2395. }
  2396. }
  2397. }
  2398. }
  2399. return EventStatus;
  2400. }
  2401. //----------------------------------------------------------------------------
  2402. //
  2403. // A module load/unload event has occurred so go through every
  2404. // breakpoint with an offset expression and reevaluate it.
  2405. //
  2406. //----------------------------------------------------------------------------
  2407. void
  2408. EvaluateOffsetExpressions(ProcessInfo* Process, ULONG Flags)
  2409. {
  2410. static BOOL s_Evaluating;
  2411. // Don't reevaluate when not notifying because
  2412. // lack of notification usually means that a group
  2413. // of operations is being done and that notify/reevaluate
  2414. // will be done later after all of them are finished.
  2415. // It is also possible to have nested evaluations as
  2416. // evaluation may provoke symbol loads on deferred
  2417. // modules, which leads to a symbol notification and
  2418. // thus another evaluation. If we're already evaluating
  2419. // there's no need to evaluate again.
  2420. if (g_EngNotify > 0 || s_Evaluating)
  2421. {
  2422. return;
  2423. }
  2424. s_Evaluating = TRUE;
  2425. Breakpoint* Bp;
  2426. BOOL AnyEnabled = FALSE;
  2427. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  2428. {
  2429. // Optimize evaluation somewhat.
  2430. // If a module is added then deferred breakpoints
  2431. // can become active. If a module is removed then
  2432. // active breakpoints can become deferred.
  2433. // XXX drewb - This doesn't hold up with general
  2434. // conditional expressions but currently the
  2435. // only thing that is officially supported is a simple symbol.
  2436. if (Bp->m_OffsetExpr != NULL &&
  2437. (((Flags & DEBUG_CSS_LOADS) &&
  2438. (Bp->m_Flags & DEBUG_BREAKPOINT_DEFERRED)) ||
  2439. ((Flags & DEBUG_CSS_UNLOADS) &&
  2440. (Bp->m_Flags & DEBUG_BREAKPOINT_DEFERRED) == 0)))
  2441. {
  2442. ADDR Addr;
  2443. if (Bp->EvalOffsetExpr(BPEVAL_UNKNOWN, &Addr) &&
  2444. (Bp->m_Flags & DEBUG_BREAKPOINT_DEFERRED) == 0)
  2445. {
  2446. // No need to update on newly disabled breakpoints
  2447. // as the module is being unloaded so they'll
  2448. // go away anyway. The disabled breakpoint
  2449. // is simply marked not-inserted in EvalOffsetExpr.
  2450. AnyEnabled = TRUE;
  2451. }
  2452. }
  2453. if (PollUserInterrupt(TRUE))
  2454. {
  2455. // Leave the interrupt set as this may be
  2456. // called in the middle of a symbol operation
  2457. // and we want the interrupt to interrupt
  2458. // the entire symbol operation.
  2459. break;
  2460. }
  2461. }
  2462. if (AnyEnabled)
  2463. {
  2464. // A deferred breakpoint has become enabled.
  2465. // Force a refresh of the breakpoints so
  2466. // that the newly enabled breakpoints get inserted.
  2467. SuspendExecution();
  2468. RemoveBreakpoints();
  2469. }
  2470. s_Evaluating = FALSE;
  2471. }
  2472. //----------------------------------------------------------------------------
  2473. //
  2474. // Alters breakpoint state for b[cde]<idlist>.
  2475. //
  2476. //----------------------------------------------------------------------------
  2477. void
  2478. ChangeBreakpointState(DebugClient* Client, ProcessInfo* ForProcess,
  2479. ULONG Id, UCHAR StateChange)
  2480. {
  2481. Breakpoint* Bp;
  2482. Breakpoint* NextBp;
  2483. TargetInfo* Target;
  2484. ProcessInfo* Process;
  2485. ForAllLayersToProcess()
  2486. {
  2487. if (ForProcess != NULL && Process != ForProcess)
  2488. {
  2489. continue;
  2490. }
  2491. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = NextBp)
  2492. {
  2493. // Prefetch the next breakpoint in case we remove
  2494. // the current breakpoint from the list.
  2495. NextBp = Bp->m_Next;
  2496. if ((Id == ALL_ID_LIST || Bp->m_Id == Id) &&
  2497. (Bp->m_Flags & BREAKPOINT_HIDDEN) == 0 &&
  2498. ((Bp->m_Flags & DEBUG_BREAKPOINT_ADDER_ONLY) == 0 ||
  2499. Bp->m_Adder == Client))
  2500. {
  2501. if (StateChange == 'c')
  2502. {
  2503. RemoveBreakpoint(Bp);
  2504. }
  2505. else
  2506. {
  2507. if (StateChange == 'e')
  2508. {
  2509. Bp->AddFlags(DEBUG_BREAKPOINT_ENABLED);
  2510. }
  2511. else
  2512. {
  2513. Bp->RemoveFlags(DEBUG_BREAKPOINT_ENABLED);
  2514. }
  2515. }
  2516. }
  2517. }
  2518. }
  2519. }
  2520. //----------------------------------------------------------------------------
  2521. //
  2522. // Lists current breakpoints for bl.
  2523. //
  2524. //----------------------------------------------------------------------------
  2525. void
  2526. ListBreakpoints(DebugClient* Client, ProcessInfo* ForProcess,
  2527. ULONG Id)
  2528. {
  2529. StackSaveLayers Save;
  2530. Breakpoint* Bp;
  2531. TargetInfo* Target;
  2532. ProcessInfo* Process;
  2533. ForAllLayersToProcess()
  2534. {
  2535. if (ForProcess != NULL && Process != ForProcess)
  2536. {
  2537. continue;
  2538. }
  2539. SetLayersFromProcess(Process);
  2540. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  2541. {
  2542. char StatusChar;
  2543. if ((Bp->m_Flags & BREAKPOINT_HIDDEN) ||
  2544. ((Bp->m_Flags & DEBUG_BREAKPOINT_ADDER_ONLY) &&
  2545. Client != Bp->m_Adder) ||
  2546. (Id != ALL_ID_LIST && Bp->m_Id != Id))
  2547. {
  2548. continue;
  2549. }
  2550. if (Bp->m_Flags & DEBUG_BREAKPOINT_ENABLED)
  2551. {
  2552. if (Bp->m_Flags & BREAKPOINT_KD_INTERNAL)
  2553. {
  2554. StatusChar = (Bp->m_Flags & BREAKPOINT_KD_COUNT_ONLY) ?
  2555. 'i' : 'w';
  2556. }
  2557. else
  2558. {
  2559. StatusChar = 'e';
  2560. }
  2561. }
  2562. else
  2563. {
  2564. StatusChar = 'd';
  2565. }
  2566. dprintf("%2u %c", Bp->m_Id, StatusChar);
  2567. if (Bp->GetProcType() != g_Target->m_MachineType)
  2568. {
  2569. dprintf("%s ",
  2570. Bp->m_Process->m_Target->
  2571. m_Machines[Bp->GetProcIndex()]->m_AbbrevName);
  2572. }
  2573. if ((Bp->m_Flags & DEBUG_BREAKPOINT_DEFERRED) == 0)
  2574. {
  2575. dprintf(" ");
  2576. if (Bp->m_BreakType == DEBUG_BREAKPOINT_CODE &&
  2577. (g_SrcOptions & SRCOPT_STEP_SOURCE))
  2578. {
  2579. if (!OutputLineAddr(Flat(*Bp->GetAddr()), "[%s @ %d]"))
  2580. {
  2581. dprintAddr(Bp->GetAddr());
  2582. }
  2583. }
  2584. else
  2585. {
  2586. dprintAddr(Bp->GetAddr());
  2587. }
  2588. }
  2589. else if (g_Target->m_Machine->m_Ptr64)
  2590. {
  2591. dprintf("u ");
  2592. }
  2593. else
  2594. {
  2595. dprintf("u ");
  2596. }
  2597. char OptionChar;
  2598. if (Bp->m_BreakType == DEBUG_BREAKPOINT_DATA)
  2599. {
  2600. switch(Bp->m_DataAccessType)
  2601. {
  2602. case DEBUG_BREAK_EXECUTE:
  2603. OptionChar = 'e';
  2604. break;
  2605. case DEBUG_BREAK_WRITE:
  2606. OptionChar = 'w';
  2607. break;
  2608. case DEBUG_BREAK_IO:
  2609. OptionChar = 'i';
  2610. break;
  2611. case DEBUG_BREAK_READ:
  2612. case DEBUG_BREAK_READ | DEBUG_BREAK_WRITE:
  2613. OptionChar = 'r';
  2614. break;
  2615. default:
  2616. OptionChar = '?';
  2617. break;
  2618. }
  2619. dprintf("%c %d", OptionChar, Bp->m_DataSize);
  2620. }
  2621. else
  2622. {
  2623. dprintf(" ");
  2624. }
  2625. if (Bp->m_Flags & DEBUG_BREAKPOINT_ONE_SHOT)
  2626. {
  2627. dprintf("/1 ");
  2628. }
  2629. dprintf(" %04lx (%04lx) ",
  2630. Bp->m_CurPassCount, Bp->m_PassCount);
  2631. if ((Bp->m_Flags & DEBUG_BREAKPOINT_DEFERRED) == 0)
  2632. {
  2633. if (IS_USER_TARGET(Bp->m_Process->m_Target))
  2634. {
  2635. dprintf("%2ld:", Bp->m_Process->m_UserId);
  2636. if (Bp->m_MatchThread != NULL)
  2637. {
  2638. dprintf("~%03ld ", Bp->m_MatchThread->m_UserId);
  2639. }
  2640. else
  2641. {
  2642. dprintf("*** ");
  2643. }
  2644. }
  2645. OutputSymAddr(Flat(*Bp->GetAddr()), SYMADDR_FORCE, NULL);
  2646. if (Bp->m_Command != NULL)
  2647. {
  2648. dprintf("\"%s\"", Bp->m_Command);
  2649. }
  2650. }
  2651. else
  2652. {
  2653. dprintf(" (%s)", Bp->m_OffsetExpr);
  2654. }
  2655. dprintf("\n");
  2656. if (Bp->m_MatchThreadData || Bp->m_MatchProcessData)
  2657. {
  2658. dprintf(" ");
  2659. if (Bp->m_MatchThreadData)
  2660. {
  2661. dprintf(" Match thread data %s",
  2662. FormatAddr64(Bp->m_MatchThreadData));
  2663. }
  2664. if (Bp->m_MatchProcessData)
  2665. {
  2666. dprintf(" Match process data %s",
  2667. FormatAddr64(Bp->m_MatchProcessData));
  2668. }
  2669. dprintf("\n");
  2670. }
  2671. }
  2672. }
  2673. if (IS_KERNEL_TARGET(g_Target))
  2674. {
  2675. dprintf("\n");
  2676. ForAllLayersToProcess()
  2677. {
  2678. if (ForProcess != NULL && Process != ForProcess)
  2679. {
  2680. continue;
  2681. }
  2682. SetLayersFromProcess(Process);
  2683. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  2684. {
  2685. if (Bp->m_Flags & BREAKPOINT_KD_INTERNAL)
  2686. {
  2687. ULONG Flags, Calls, MinInst, MaxInst, TotInst, MaxCps;
  2688. g_Target->QueryTargetCountBreakpoint(Bp->GetAddr(),
  2689. &Flags,
  2690. &Calls,
  2691. &MinInst,
  2692. &MaxInst,
  2693. &TotInst,
  2694. &MaxCps);
  2695. dprintf("%s %6d %8d %8d %8d %2x %4d",
  2696. FormatAddr64(Flat(*Bp->GetAddr())),
  2697. Calls, MinInst, MaxInst,
  2698. TotInst, Flags, MaxCps);
  2699. OutputSymAddr(Flat(*Bp->GetAddr()), SYMADDR_FORCE, " ");
  2700. dprintf("\n");
  2701. }
  2702. }
  2703. }
  2704. }
  2705. }
  2706. //----------------------------------------------------------------------------
  2707. //
  2708. // Outputs commands necessary to recreate current breakpoints.
  2709. //
  2710. //----------------------------------------------------------------------------
  2711. void
  2712. ListBreakpointsAsCommands(DebugClient* Client, ProcessInfo* Process,
  2713. ULONG Flags)
  2714. {
  2715. Breakpoint* Bp;
  2716. if (Process == NULL)
  2717. {
  2718. return;
  2719. }
  2720. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  2721. {
  2722. if ((Bp->m_Flags & BREAKPOINT_HIDDEN) ||
  2723. ((Bp->m_Flags & DEBUG_BREAKPOINT_ADDER_ONLY) &&
  2724. Client != Bp->m_Adder) ||
  2725. ((Flags & BPCMDS_EXPR_ONLY && Bp->m_OffsetExpr == NULL)))
  2726. {
  2727. continue;
  2728. }
  2729. if (IS_USER_TARGET(Bp->m_Process->m_Target))
  2730. {
  2731. if (Bp->m_MatchThread != NULL ||
  2732. Bp->m_MatchThreadData ||
  2733. Bp->m_MatchProcessData)
  2734. {
  2735. // Ignore thread- and data-specific breakpoints
  2736. // as the things they are specific to may
  2737. // not exist in a new session.
  2738. continue;
  2739. }
  2740. }
  2741. if (Bp->GetProcType() != Process->m_Target->m_MachineType)
  2742. {
  2743. dprintf(".effmach %s;%c",
  2744. Bp->m_Process->m_Target->
  2745. m_Machines[Bp->GetProcIndex()]->m_AbbrevName,
  2746. (Flags & BPCMDS_ONE_LINE) ? ' ' : '\n');
  2747. }
  2748. if ((Flags & BPCMDS_MODULE_HINT) &&
  2749. (Bp->m_Flags & (DEBUG_BREAKPOINT_DEFERRED |
  2750. BREAKPOINT_VIRT_ADDR)) == BREAKPOINT_VIRT_ADDR)
  2751. {
  2752. ImageInfo* Image =
  2753. Bp->m_Process->FindImageByOffset(Flat(*Bp->GetAddr()), FALSE);
  2754. if (Image != NULL)
  2755. {
  2756. dprintf("ld %s;%c", Image->m_ModuleName,
  2757. (Flags & BPCMDS_ONE_LINE) ? ' ' : '\n');
  2758. }
  2759. }
  2760. char TypeChar;
  2761. if (Bp->m_Flags & BREAKPOINT_KD_INTERNAL)
  2762. {
  2763. TypeChar = (Bp->m_Flags & BREAKPOINT_KD_COUNT_ONLY) ? 'i' : 'w';
  2764. }
  2765. else if (Bp->m_BreakType == DEBUG_BREAKPOINT_CODE)
  2766. {
  2767. TypeChar = Bp->m_OffsetExpr != NULL ? 'u' : 'p';
  2768. }
  2769. else
  2770. {
  2771. TypeChar = 'a';
  2772. }
  2773. dprintf("b%c%u", TypeChar, Bp->m_Id);
  2774. char OptionChar;
  2775. if (Bp->m_BreakType == DEBUG_BREAKPOINT_DATA)
  2776. {
  2777. switch(Bp->m_DataAccessType)
  2778. {
  2779. case DEBUG_BREAK_EXECUTE:
  2780. OptionChar = 'e';
  2781. break;
  2782. case DEBUG_BREAK_WRITE:
  2783. OptionChar = 'w';
  2784. break;
  2785. case DEBUG_BREAK_IO:
  2786. OptionChar = 'i';
  2787. break;
  2788. case DEBUG_BREAK_READ:
  2789. case DEBUG_BREAK_READ | DEBUG_BREAK_WRITE:
  2790. OptionChar = 'r';
  2791. break;
  2792. default:
  2793. continue;
  2794. }
  2795. dprintf(" %c%d", OptionChar, Bp->m_DataSize);
  2796. }
  2797. if (Bp->m_Flags & DEBUG_BREAKPOINT_ONE_SHOT)
  2798. {
  2799. dprintf(" /1");
  2800. }
  2801. if (Bp->m_OffsetExpr != NULL)
  2802. {
  2803. dprintf(" %s", Bp->m_OffsetExpr);
  2804. }
  2805. else
  2806. {
  2807. dprintf(" 0x");
  2808. dprintAddr(Bp->GetAddr());
  2809. }
  2810. if (Bp->m_PassCount > 1)
  2811. {
  2812. dprintf(" 0x%x", Bp->m_PassCount);
  2813. }
  2814. if (Bp->m_Command != NULL)
  2815. {
  2816. dprintf(" \"%s\"", Bp->m_Command);
  2817. }
  2818. dprintf(";%c", (Flags & BPCMDS_ONE_LINE) ? ' ' : '\n');
  2819. if ((Flags & BPCMDS_FORCE_DISABLE) ||
  2820. (Bp->m_Flags & DEBUG_BREAKPOINT_ENABLED) == 0)
  2821. {
  2822. dprintf("bd %u;%c", Bp->m_Id,
  2823. (Flags & BPCMDS_ONE_LINE) ? ' ' : '\n');
  2824. }
  2825. if (Bp->GetProcType() != Process->m_Target->m_MachineType)
  2826. {
  2827. dprintf(".effmach .;%c",
  2828. (Flags & BPCMDS_ONE_LINE) ? ' ' : '\n');
  2829. }
  2830. }
  2831. if (Flags & BPCMDS_ONE_LINE)
  2832. {
  2833. dprintf("\n");
  2834. }
  2835. }
  2836. //----------------------------------------------------------------------------
  2837. //
  2838. // Parses command-line breakpoint commands for b[aimpw].
  2839. //
  2840. //----------------------------------------------------------------------------
  2841. struct SET_SYMBOL_MATCH_BP
  2842. {
  2843. DebugClient* Client;
  2844. ProcessInfo* Process;
  2845. PSTR MatchString;
  2846. Breakpoint* ProtoBp;
  2847. ULONG Matches;
  2848. ULONG Error;
  2849. };
  2850. BOOL CALLBACK
  2851. SetSymbolMatchBp(PSYMBOL_INFO SymInfo,
  2852. ULONG Size,
  2853. PVOID UserContext)
  2854. {
  2855. SET_SYMBOL_MATCH_BP* Context =
  2856. (SET_SYMBOL_MATCH_BP*)UserContext;
  2857. ImageInfo* Image = Context->Process->
  2858. FindImageByOffset(SymInfo->Address, FALSE);
  2859. if (!Image)
  2860. {
  2861. return TRUE;
  2862. }
  2863. MachineInfo* Machine = MachineTypeInfo(Context->Process->m_Target,
  2864. Image->GetMachineType());
  2865. if (IgnoreEnumeratedSymbol(Context->Process, Context->MatchString,
  2866. Machine, SymInfo) ||
  2867. !ForceSymbolCodeAddress(Context->Process, SymInfo, Machine))
  2868. {
  2869. return TRUE;
  2870. }
  2871. ADDR Addr;
  2872. ADDRFLAT(&Addr, SymInfo->Address);
  2873. if (FAILED(Context->ProtoBp->CheckAddr(&Addr)))
  2874. {
  2875. Context->Error = MEMORY;
  2876. return FALSE;
  2877. }
  2878. Breakpoint* Bp;
  2879. if (AddBreakpoint(Context->Client, Machine, DEBUG_BREAKPOINT_CODE,
  2880. DEBUG_ANY_ID, &Bp) != S_OK)
  2881. {
  2882. Context->Error = BPLISTFULL;
  2883. return FALSE;
  2884. }
  2885. if (Context->ProtoBp->m_Flags & DEBUG_BREAKPOINT_ONE_SHOT)
  2886. {
  2887. Bp->AddFlags(DEBUG_BREAKPOINT_ONE_SHOT);
  2888. }
  2889. Bp->m_CodeFlags = Context->ProtoBp->m_CodeFlags;
  2890. Bp->m_MatchProcessData = Context->ProtoBp->m_MatchProcessData;
  2891. Bp->m_MatchThreadData = Context->ProtoBp->m_MatchThreadData;
  2892. Bp->SetPassCount(Context->ProtoBp->m_PassCount);
  2893. if (Context->ProtoBp->m_MatchThread)
  2894. {
  2895. Bp->SetMatchThreadId(Context->ProtoBp->m_MatchThread->m_UserId);
  2896. }
  2897. if (Bp->SetAddr(&Addr, BREAKPOINT_REMOVE_MATCH) != S_OK ||
  2898. (Context->ProtoBp->m_Command &&
  2899. Bp->SetCommand(Context->ProtoBp->m_Command) != S_OK))
  2900. {
  2901. Bp->Relinquish();
  2902. Context->Error = NOMEMORY;
  2903. return FALSE;
  2904. }
  2905. Bp->AddFlags(DEBUG_BREAKPOINT_ENABLED);
  2906. dprintf("%3d: %s %s!%s\n",
  2907. Bp->m_Id, FormatAddr64(SymInfo->Address),
  2908. Image->m_ModuleName, SymInfo->Name);
  2909. Context->Matches++;
  2910. return TRUE;
  2911. }
  2912. PDEBUG_BREAKPOINT
  2913. ParseBpCmd(DebugClient* Client,
  2914. UCHAR Type,
  2915. ThreadInfo* Thread)
  2916. {
  2917. ULONG UserId = DEBUG_ANY_ID;
  2918. char Ch;
  2919. ADDR Addr;
  2920. Breakpoint* Bp;
  2921. if (IS_LOCAL_KERNEL_TARGET(g_Target) || IS_DUMP_TARGET(g_Target))
  2922. {
  2923. error(SESSIONNOTSUP);
  2924. }
  2925. if (!IS_CUR_CONTEXT_ACCESSIBLE())
  2926. {
  2927. error(BADTHREAD);
  2928. }
  2929. if (IS_LIVE_USER_TARGET(g_Target) && Type == 'a' &&
  2930. (g_EngStatus & ENG_STATUS_AT_INITIAL_BREAK))
  2931. {
  2932. ErrOut("The system resets thread contexts after the process\n");
  2933. ErrOut("breakpoint so hardware breakpoints cannot be set.\n");
  2934. ErrOut("Go to the executable's entry point and set it then.\n");
  2935. *g_CurCmd = 0;
  2936. return NULL;
  2937. }
  2938. // get the breakpoint number if given
  2939. Ch = *g_CurCmd;
  2940. if (Ch == '[')
  2941. {
  2942. UserId = (ULONG)GetTermExpression("Breakpoint ID missing from");
  2943. }
  2944. else if (Ch >= '0' && Ch <= '9')
  2945. {
  2946. UserId = Ch - '0';
  2947. Ch = *++g_CurCmd;
  2948. while (Ch >= '0' && Ch <= '9')
  2949. {
  2950. UserId = UserId * 10 + Ch - '0';
  2951. Ch = *++g_CurCmd;
  2952. }
  2953. if (Ch != ' ' && Ch != '\t' && Ch != '\0')
  2954. {
  2955. error(SYNTAX);
  2956. }
  2957. }
  2958. if (UserId != DEBUG_ANY_ID)
  2959. {
  2960. // Remove any existing breakpoint with the given ID.
  2961. Breakpoint* IdBp;
  2962. if (Type == 'm')
  2963. {
  2964. error(SYNTAX);
  2965. }
  2966. if ((IdBp = GetBreakpointById(Client, UserId)) != NULL)
  2967. {
  2968. WarnOut("breakpoint %ld exists, redefining\n", UserId);
  2969. RemoveBreakpoint(IdBp);
  2970. }
  2971. }
  2972. // Create a new breakpoint.
  2973. if (AddBreakpoint(Client, g_Machine, Type == 'a' ?
  2974. DEBUG_BREAKPOINT_DATA : DEBUG_BREAKPOINT_CODE,
  2975. UserId, &Bp) != S_OK)
  2976. {
  2977. error(BPLISTFULL);
  2978. }
  2979. // Add in KD internal flags if necessary.
  2980. if (Type == 'i' || Type == 'w')
  2981. {
  2982. if (IS_KERNEL_TARGET(g_Target))
  2983. {
  2984. Bp->m_Flags = Bp->m_Flags | BREAKPOINT_KD_INTERNAL |
  2985. (Type == 'i' ? BREAKPOINT_KD_COUNT_ONLY : 0);
  2986. if (Type == 'w')
  2987. {
  2988. g_Target->InitializeTargetControlledStepping();
  2989. }
  2990. }
  2991. else
  2992. {
  2993. // KD internal breakpoints are only supported in
  2994. // kernel debugging.
  2995. Bp->Relinquish();
  2996. error(SYNTAX);
  2997. }
  2998. }
  2999. // If data breakpoint, get option and size values.
  3000. if (Type == 'a')
  3001. {
  3002. ULONG64 Size;
  3003. ULONG AccessType;
  3004. Ch = PeekChar();
  3005. Ch = (char)tolower(Ch);
  3006. if (Ch == 'e')
  3007. {
  3008. AccessType = DEBUG_BREAK_EXECUTE;
  3009. }
  3010. else if (Ch == 'w')
  3011. {
  3012. AccessType = DEBUG_BREAK_WRITE;
  3013. }
  3014. else if (Ch == 'i')
  3015. {
  3016. AccessType = DEBUG_BREAK_IO;
  3017. }
  3018. else if (Ch == 'r')
  3019. {
  3020. AccessType = DEBUG_BREAK_READ;
  3021. }
  3022. else
  3023. {
  3024. Bp->Relinquish();
  3025. error(SYNTAX);
  3026. }
  3027. g_CurCmd++;
  3028. Size = GetTermExpression("Hardware breakpoint length missing from");
  3029. if (Size & ~ULONG(-1))
  3030. {
  3031. ErrOut("Breakpoint length too big\n");
  3032. Bp->Relinquish();
  3033. error(SYNTAX);
  3034. }
  3035. // Validate the selections. This assumes that
  3036. // the default offset of zero won't cause problems.
  3037. if (Bp->SetDataParameters((ULONG)Size, AccessType) != S_OK)
  3038. {
  3039. Bp->Relinquish();
  3040. error(SYNTAX);
  3041. }
  3042. g_CurCmd++;
  3043. }
  3044. //
  3045. // Parse breakpoint options.
  3046. //
  3047. while (PeekChar() == '/')
  3048. {
  3049. g_CurCmd++;
  3050. switch(*g_CurCmd++)
  3051. {
  3052. case '1':
  3053. Bp->AddFlags(DEBUG_BREAKPOINT_ONE_SHOT);
  3054. break;
  3055. case 'f':
  3056. Bp->m_CodeFlags = (ULONG)GetTermExpression(NULL);
  3057. break;
  3058. case 'p':
  3059. Bp->m_MatchProcessData = GetTermExpression(NULL);
  3060. break;
  3061. case 't':
  3062. Bp->m_MatchThreadData = GetTermExpression(NULL);
  3063. break;
  3064. default:
  3065. ErrOut("Unknown option '%c'\n", *g_CurCmd);
  3066. break;
  3067. }
  3068. }
  3069. PSTR ExprStart, ExprEnd;
  3070. Ch = PeekChar();
  3071. if (Type == 'm')
  3072. {
  3073. char Save;
  3074. ExprStart = StringValue(STRV_SPACE_IS_SEPARATOR |
  3075. STRV_TRIM_TRAILING_SPACE, &Save);
  3076. ExprEnd = g_CurCmd;
  3077. *g_CurCmd = Save;
  3078. Ch = PeekChar();
  3079. }
  3080. else
  3081. {
  3082. //
  3083. // Get the breakpoint address, if given, otherwise
  3084. // default to the current IP.
  3085. //
  3086. BreakpointEvalResult AddrValid = BPEVAL_RESOLVED;
  3087. g_Target->m_EffMachine->GetPC(&Addr);
  3088. if (Ch != '"' && Ch != '\0')
  3089. {
  3090. ExprStart = g_CurCmd;
  3091. g_PrefixSymbols = Type == 'p' || Type == 'u';
  3092. AddrValid = EvalAddrExpression(g_Process,
  3093. g_Target->m_EffMachineType,
  3094. &Addr);
  3095. g_PrefixSymbols = FALSE;
  3096. if (AddrValid == BPEVAL_ERROR)
  3097. {
  3098. Bp->Relinquish();
  3099. return NULL;
  3100. }
  3101. // If an unresolved symbol was encountered this
  3102. // breakpoint will be deferred. Users can also force
  3103. // breakpoints to use expressions for cases where the
  3104. // address could be resolved but also may become invalid
  3105. // later.
  3106. if (Type == 'u' || AddrValid == BPEVAL_UNRESOLVED)
  3107. {
  3108. HRESULT Status;
  3109. UCHAR Save = *g_CurCmd;
  3110. *g_CurCmd = 0;
  3111. Status = Bp->SetEvaluatedOffsetExpression(ExprStart,
  3112. AddrValid,
  3113. &Addr);
  3114. if (Type != 'u' && Status == S_OK)
  3115. {
  3116. WarnOut("Bp expression '%s' could not be resolved, "
  3117. "adding deferred bp\n", ExprStart);
  3118. }
  3119. *g_CurCmd = Save;
  3120. if (Status != S_OK)
  3121. {
  3122. Bp->Relinquish();
  3123. error(NOMEMORY);
  3124. }
  3125. }
  3126. Ch = PeekChar();
  3127. }
  3128. if (AddrValid != BPEVAL_UNRESOLVED &&
  3129. FAILED(Bp->CheckAddr(&Addr)))
  3130. {
  3131. Bp->Relinquish();
  3132. error(MEMORY);
  3133. }
  3134. // The public interface only supports flat addresses
  3135. // so use an internal method to set the true address.
  3136. // Do not allow matching breakpoints through the parsing
  3137. // interface as that was the previous behavior.
  3138. if (Bp->SetAddr(&Addr, BREAKPOINT_REMOVE_MATCH) != S_OK)
  3139. {
  3140. Bp->Relinquish();
  3141. error(SYNTAX);
  3142. }
  3143. }
  3144. // Get the pass count, if given.
  3145. if (Ch != '"' && Ch != ';' && Ch != '\0')
  3146. {
  3147. ULONG64 PassCount = GetExpression();
  3148. if (PassCount < 1 || PassCount > 0xffffffff)
  3149. {
  3150. error(BADRANGE);
  3151. }
  3152. Bp->SetPassCount((ULONG)PassCount);
  3153. Ch = PeekChar();
  3154. }
  3155. // If next character is double quote, get the command string.
  3156. if (Ch == '"')
  3157. {
  3158. PSTR Str;
  3159. CHAR Save;
  3160. Str = StringValue(STRV_ESCAPED_CHARACTERS, &Save);
  3161. if (Bp->SetCommand(Str) != S_OK)
  3162. {
  3163. Bp->Relinquish();
  3164. error(NOMEMORY);
  3165. }
  3166. *g_CurCmd = Save;
  3167. }
  3168. // Set some final information.
  3169. if (Thread != NULL)
  3170. {
  3171. Bp->SetMatchThreadId(Thread->m_UserId);
  3172. }
  3173. // Turn breakpoint on.
  3174. Bp->AddFlags(DEBUG_BREAKPOINT_ENABLED);
  3175. if (Type == 'm')
  3176. {
  3177. SET_SYMBOL_MATCH_BP Context;
  3178. // Now that we have the prototype breakpoint created,
  3179. // enumerate all symbol matches for the symbol
  3180. // expression and create specific breakpoints for
  3181. // each hit from the prototype breakpoint.
  3182. *ExprEnd = 0;
  3183. Context.Client = Client;
  3184. Context.Process = g_Process;
  3185. Context.MatchString = ExprStart;
  3186. Context.ProtoBp = Bp;
  3187. Context.Matches = 0;
  3188. Context.Error = 0;
  3189. SymEnumSymbols(g_Process->m_SymHandle, 0, ExprStart,
  3190. SetSymbolMatchBp, &Context);
  3191. if (Context.Error)
  3192. {
  3193. error(Context.Error);
  3194. }
  3195. if (!Context.Matches)
  3196. {
  3197. ErrOut("No matching symbols found, no breakpoints set\n");
  3198. }
  3199. Bp->Relinquish();
  3200. Bp = NULL;
  3201. }
  3202. return Bp;
  3203. }
  3204. inline BOOL
  3205. IsCodeBreakpointInsertedInRange(Breakpoint* Bp,
  3206. ULONG64 Start, ULONG64 End)
  3207. {
  3208. return (Bp->m_Flags & BREAKPOINT_INSERTED) &&
  3209. Bp->m_BreakType == DEBUG_BREAKPOINT_CODE &&
  3210. Flat(*Bp->GetAddr()) >= Start &&
  3211. Flat(*Bp->GetAddr()) <= End;
  3212. }
  3213. BOOL
  3214. CheckBreakpointInsertedInRange(ProcessInfo* Process,
  3215. ULONG64 Start, ULONG64 End)
  3216. {
  3217. if ((g_EngStatus & ENG_STATUS_BREAKPOINTS_INSERTED) == 0)
  3218. {
  3219. return FALSE;
  3220. }
  3221. //
  3222. // Check for a breakpoint that might have caused
  3223. // a break instruction to be inserted in the given
  3224. // offset range. Data breakpoints don't count
  3225. // as they don't actually modify the address they
  3226. // break on.
  3227. //
  3228. Breakpoint* Bp;
  3229. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  3230. {
  3231. if (IsCodeBreakpointInsertedInRange(Bp, Start, End))
  3232. {
  3233. return TRUE;
  3234. }
  3235. }
  3236. if ((g_DeferBp->m_Process == Process &&
  3237. IsCodeBreakpointInsertedInRange(g_DeferBp, Start, End)) ||
  3238. (g_StepTraceBp->m_Process == Process &&
  3239. IsCodeBreakpointInsertedInRange(g_StepTraceBp, Start, End)))
  3240. {
  3241. return TRUE;
  3242. }
  3243. return FALSE;
  3244. }
  3245. //----------------------------------------------------------------------------
  3246. //
  3247. // TargetInfo methods.
  3248. //
  3249. //----------------------------------------------------------------------------
  3250. HRESULT
  3251. TargetInfo::BeginInsertingBreakpoints(void)
  3252. {
  3253. ProcessInfo* Process;
  3254. ThreadInfo* Thread;
  3255. ForTargetProcesses(this)
  3256. {
  3257. ForProcessThreads(Process)
  3258. {
  3259. DataBreakpoint::ClearThreadDataBreaks(Thread);
  3260. }
  3261. }
  3262. return S_OK;
  3263. }
  3264. HRESULT
  3265. TargetInfo::InsertDataBreakpoint(ProcessInfo* Process,
  3266. ThreadInfo* Thread,
  3267. class MachineInfo* Machine,
  3268. PADDR Addr,
  3269. ULONG Size,
  3270. ULONG AccessType,
  3271. PUCHAR StorageSpace)
  3272. {
  3273. // Ask for default processing.
  3274. return S_FALSE;
  3275. }
  3276. void
  3277. TargetInfo::EndInsertingBreakpoints(void)
  3278. {
  3279. ProcessInfo* Process;
  3280. ThreadInfo* Thread;
  3281. if (!g_UpdateDataBreakpoints ||
  3282. !IS_CONTEXT_POSSIBLE(this))
  3283. {
  3284. return;
  3285. }
  3286. //
  3287. // It's the target machine's responsibility to manage
  3288. // all data breakpoints for all machines, so always
  3289. // force the usage of the target machine here.
  3290. //
  3291. ThreadInfo* SaveThread = m_RegContextThread;
  3292. ForTargetProcesses(this)
  3293. {
  3294. ForProcessThreads(Process)
  3295. {
  3296. SetLayersFromThread(Thread);
  3297. ChangeRegContext(Thread);
  3298. m_Machine->InsertThreadDataBreakpoints();
  3299. }
  3300. }
  3301. ChangeRegContext(SaveThread);
  3302. }
  3303. void
  3304. TargetInfo::BeginRemovingBreakpoints(void)
  3305. {
  3306. // No work necessary.
  3307. }
  3308. HRESULT
  3309. TargetInfo::RemoveDataBreakpoint(ProcessInfo* Process,
  3310. ThreadInfo* Thread,
  3311. class MachineInfo* Machine,
  3312. PADDR Addr,
  3313. ULONG Size,
  3314. ULONG AccessType,
  3315. PUCHAR StorageSpace)
  3316. {
  3317. // Ask for default processing.
  3318. return S_FALSE;
  3319. }
  3320. void
  3321. TargetInfo::EndRemovingBreakpoints(void)
  3322. {
  3323. // No work necessary.
  3324. }
  3325. HRESULT
  3326. TargetInfo::RemoveAllDataBreakpoints(ProcessInfo* Process)
  3327. {
  3328. // No work necessary.
  3329. return S_OK;
  3330. }
  3331. HRESULT
  3332. TargetInfo::RemoveAllTargetBreakpoints(void)
  3333. {
  3334. // No work necessary.
  3335. return S_OK;
  3336. }
  3337. HRESULT
  3338. TargetInfo::IsDataBreakpointHit(ThreadInfo* Thread,
  3339. PADDR Addr,
  3340. ULONG Size,
  3341. ULONG AccessType,
  3342. PUCHAR StorageSpace)
  3343. {
  3344. // Ask for default processing.
  3345. return S_FALSE;
  3346. }
  3347. HRESULT
  3348. ConnLiveKernelTargetInfo::InsertCodeBreakpoint(ProcessInfo* Process,
  3349. MachineInfo* Machine,
  3350. PADDR Addr,
  3351. ULONG InstrFlags,
  3352. PUCHAR StorageSpace)
  3353. {
  3354. if (InstrFlags != IBI_DEFAULT)
  3355. {
  3356. return E_INVALIDARG;
  3357. }
  3358. DBGKD_MANIPULATE_STATE64 m;
  3359. PDBGKD_MANIPULATE_STATE64 Reply;
  3360. PDBGKD_WRITE_BREAKPOINT64 a = &m.u.WriteBreakPoint;
  3361. NTSTATUS st;
  3362. ULONG rc;
  3363. //
  3364. // Format state manipulate message
  3365. //
  3366. m.ApiNumber = DbgKdWriteBreakPointApi;
  3367. m.ReturnStatus = STATUS_PENDING;
  3368. a->BreakPointAddress = Flat(*Addr);
  3369. //
  3370. // Send the message and context and then wait for reply
  3371. //
  3372. do
  3373. {
  3374. m_Transport->WritePacket(&m, sizeof(m),
  3375. PACKET_TYPE_KD_STATE_MANIPULATE,
  3376. NULL, 0);
  3377. rc = m_Transport->
  3378. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  3379. } while (rc != DBGKD_WAIT_PACKET ||
  3380. Reply->ApiNumber != DbgKdWriteBreakPointApi);
  3381. st = Reply->ReturnStatus;
  3382. *(PULONG)StorageSpace = Reply->u.WriteBreakPoint.BreakPointHandle;
  3383. KdOut("DbgKdWriteBreakPoint(%s) returns %08lx, %x\n",
  3384. FormatAddr64(Flat(*Addr)), st,
  3385. Reply->u.WriteBreakPoint.BreakPointHandle);
  3386. return CONV_NT_STATUS(st);
  3387. }
  3388. NTSTATUS
  3389. ConnLiveKernelTargetInfo::KdRestoreBreakPoint(ULONG BreakPointHandle)
  3390. {
  3391. DBGKD_MANIPULATE_STATE64 m;
  3392. PDBGKD_MANIPULATE_STATE64 Reply;
  3393. PDBGKD_RESTORE_BREAKPOINT a = &m.u.RestoreBreakPoint;
  3394. NTSTATUS st;
  3395. ULONG rc;
  3396. //
  3397. // Format state manipulate message
  3398. //
  3399. m.ApiNumber = DbgKdRestoreBreakPointApi;
  3400. m.ReturnStatus = STATUS_PENDING;
  3401. a->BreakPointHandle = BreakPointHandle;
  3402. //
  3403. // Send the message and context and then wait for reply
  3404. //
  3405. do
  3406. {
  3407. m_Transport->WritePacket(&m, sizeof(m),
  3408. PACKET_TYPE_KD_STATE_MANIPULATE,
  3409. NULL, 0);
  3410. rc = m_Transport->
  3411. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  3412. } while (rc != DBGKD_WAIT_PACKET ||
  3413. Reply->ApiNumber != DbgKdRestoreBreakPointApi);
  3414. st = Reply->ReturnStatus;
  3415. KdOut("DbgKdRestoreBreakPoint(%x) returns %08lx\n",
  3416. BreakPointHandle, st);
  3417. return st;
  3418. }
  3419. HRESULT
  3420. ConnLiveKernelTargetInfo::RemoveCodeBreakpoint(ProcessInfo* Process,
  3421. MachineInfo* Machine,
  3422. PADDR Addr,
  3423. ULONG InstrFlags,
  3424. PUCHAR StorageSpace)
  3425. {
  3426. // When the kernel fills out the CONTROL_REPORT.InstructionStream
  3427. // array it clears any breakpoints that might fall within the
  3428. // array. This means that some breakpoints may already be
  3429. // restored, so the restore call will fail. We could do some
  3430. // checks to try and figure out which ones might be affected
  3431. // but it doesn't seem worthwhile. Just ignore the return
  3432. // value from the restore.
  3433. KdRestoreBreakPoint(*(PULONG)StorageSpace);
  3434. return S_OK;
  3435. }
  3436. HRESULT
  3437. ConnLiveKernelTargetInfo::RemoveAllDataBreakpoints(ProcessInfo* Process)
  3438. {
  3439. if (m_Transport->m_WaitingThread)
  3440. {
  3441. // A thread is waiting so we can't communicate
  3442. // with the target machine.
  3443. return E_UNEXPECTED;
  3444. }
  3445. // If there were any data breakpoints active
  3446. // remove them from all processors. This can't be in
  3447. // RemoveAllKernelBreakpoints as that
  3448. // code is called in the middle of state
  3449. // change processing when the context hasn't
  3450. // been initialized.
  3451. if (g_UpdateDataBreakpoints)
  3452. {
  3453. ULONG Proc;
  3454. SetEffMachine(m_MachineType, FALSE);
  3455. g_EngNotify++;
  3456. for (Proc = 0; Proc < m_NumProcessors; Proc++)
  3457. {
  3458. SetCurrentProcessorThread(this, Proc, TRUE);
  3459. // Force the context to be dirty so it
  3460. // gets written back.
  3461. m_Machine->GetContextState(MCTX_DIRTY);
  3462. m_Machine->RemoveThreadDataBreakpoints();
  3463. }
  3464. g_EngNotify--;
  3465. // Flush final context.
  3466. ChangeRegContext(NULL);
  3467. }
  3468. return S_OK;
  3469. }
  3470. HRESULT
  3471. ConnLiveKernelTargetInfo::RemoveAllTargetBreakpoints(void)
  3472. {
  3473. ULONG i;
  3474. if (m_Transport->m_WaitingThread)
  3475. {
  3476. // A thread is waiting so we can't communicate
  3477. // with the target machine.
  3478. return E_UNEXPECTED;
  3479. }
  3480. // Indices are array index plus one.
  3481. for (i = 1; i <= BREAKPOINT_TABLE_SIZE; i++)
  3482. {
  3483. KdRestoreBreakPoint(i);
  3484. }
  3485. // ClearAllInternalBreakpointsApi was added for XP
  3486. // so it fails against any previous OS.
  3487. if (m_KdMaxManipulate > DbgKdClearAllInternalBreakpointsApi)
  3488. {
  3489. DBGKD_MANIPULATE_STATE64 Request;
  3490. Request.ApiNumber = DbgKdClearAllInternalBreakpointsApi;
  3491. Request.ReturnStatus = STATUS_PENDING;
  3492. m_Transport->WritePacket(&Request, sizeof(Request),
  3493. PACKET_TYPE_KD_STATE_MANIPULATE,
  3494. NULL, 0);
  3495. }
  3496. return S_OK;
  3497. }
  3498. HRESULT
  3499. ConnLiveKernelTargetInfo::InsertTargetCountBreakpoint(PADDR Addr,
  3500. ULONG Flags)
  3501. {
  3502. DBGKD_MANIPULATE_STATE64 m;
  3503. ULONG64 Offset = Flat(*Addr);
  3504. m.ApiNumber = DbgKdSetInternalBreakPointApi;
  3505. m.ReturnStatus = STATUS_PENDING;
  3506. #ifdef IBP_WORKAROUND
  3507. // The kernel code keeps a ULONG64 for an internal breakpoint
  3508. // address but older kernels did not sign-extend the current IP
  3509. // when comparing against them. In order to work with both
  3510. // broken and fixed kernels send down zero-extended addresses.
  3511. // Don't actually enable this workaround right now as other
  3512. // internal breakpoint bugs can cause the machine to bugcheck.
  3513. Offset = m_Machine->m_Ptr64 ? Offset : (ULONG)Offset;
  3514. #endif
  3515. m.u.SetInternalBreakpoint.BreakpointAddress = Offset;
  3516. m.u.SetInternalBreakpoint.Flags = Flags;
  3517. m_Transport->WritePacket(&m, sizeof(m),
  3518. PACKET_TYPE_KD_STATE_MANIPULATE,
  3519. NULL, 0);
  3520. KdOut("DbgKdSetInternalBp returns 0x00000000\n");
  3521. return S_OK;
  3522. }
  3523. HRESULT
  3524. ConnLiveKernelTargetInfo::RemoveTargetCountBreakpoint(PADDR Addr)
  3525. {
  3526. DBGKD_MANIPULATE_STATE64 m;
  3527. ULONG64 Offset = Flat(*Addr);
  3528. m.ApiNumber = DbgKdSetInternalBreakPointApi;
  3529. m.ReturnStatus = STATUS_PENDING;
  3530. #ifdef IBP_WORKAROUND
  3531. // The kernel code keeps a ULONG64 for an internal breakpoint
  3532. // address but older kernels did not sign-extend the current IP
  3533. // when comparing against them. In order to work with both
  3534. // broken and fixed kernels send down zero-extended addresses.
  3535. // Don't actually enable this workaround right now as other
  3536. // internal breakpoint bugs can cause the machine to bugcheck.
  3537. Offset = m_Machine->m_Ptr64 ? Offset : (ULONG)Offset;
  3538. #endif
  3539. m.u.SetInternalBreakpoint.BreakpointAddress = Offset;
  3540. m.u.SetInternalBreakpoint.Flags = DBGKD_INTERNAL_BP_FLAG_INVALID;
  3541. m_Transport->WritePacket(&m, sizeof(m),
  3542. PACKET_TYPE_KD_STATE_MANIPULATE,
  3543. NULL, 0);
  3544. KdOut("DbgKdSetInternalBp returns 0x00000000\n");
  3545. return S_OK;
  3546. }
  3547. HRESULT
  3548. ConnLiveKernelTargetInfo::QueryTargetCountBreakpoint(PADDR Addr,
  3549. PULONG Flags,
  3550. PULONG Calls,
  3551. PULONG MinInstr,
  3552. PULONG MaxInstr,
  3553. PULONG TotInstr,
  3554. PULONG MaxCps)
  3555. {
  3556. DBGKD_MANIPULATE_STATE64 m;
  3557. PDBGKD_MANIPULATE_STATE64 Reply;
  3558. ULONG rc;
  3559. ULONG64 Offset = Flat(*Addr);
  3560. m.ApiNumber = DbgKdGetInternalBreakPointApi;
  3561. m.ReturnStatus = STATUS_PENDING;
  3562. #ifdef IBP_WORKAROUND
  3563. // The kernel code keeps a ULONG64 for an internal breakpoint
  3564. // address but older kernels did not sign-extend the current IP
  3565. // when comparing against them. In order to work with both
  3566. // broken and fixed kernels send down zero-extended addresses.
  3567. // Don't actually enable this workaround right now as other
  3568. // internal breakpoint bugs can cause the machine to bugcheck.
  3569. Offset = m_Machine->m_Ptr64 ? Offset : (ULONG)Offset;
  3570. #endif
  3571. m.u.GetInternalBreakpoint.BreakpointAddress = Offset;
  3572. do
  3573. {
  3574. m_Transport->WritePacket(&m, sizeof(m),
  3575. PACKET_TYPE_KD_STATE_MANIPULATE,
  3576. NULL, 0);
  3577. rc = m_Transport->
  3578. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  3579. }
  3580. while (rc != DBGKD_WAIT_PACKET);
  3581. *Flags = Reply->u.GetInternalBreakpoint.Flags;
  3582. *Calls = Reply->u.GetInternalBreakpoint.Calls;
  3583. *MaxInstr = Reply->u.GetInternalBreakpoint.MaxInstructions;
  3584. *MinInstr = Reply->u.GetInternalBreakpoint.MinInstructions;
  3585. *TotInstr = Reply->u.GetInternalBreakpoint.TotalInstructions;
  3586. *MaxCps = Reply->u.GetInternalBreakpoint.MaxCallsPerPeriod;
  3587. KdOut("DbgKdGetInternalBp returns 0x00000000\n");
  3588. return S_OK;
  3589. }
  3590. HRESULT
  3591. ExdiLiveKernelTargetInfo::BeginInsertingBreakpoints(void)
  3592. {
  3593. if (!m_ExdiDataBreaks)
  3594. {
  3595. return TargetInfo::BeginInsertingBreakpoints();
  3596. }
  3597. else
  3598. {
  3599. // If direct eXDI support for data breakpoints is
  3600. // used this method doesn't need to do anything.
  3601. return S_OK;
  3602. }
  3603. }
  3604. HRESULT
  3605. ExdiLiveKernelTargetInfo::InsertCodeBreakpoint(ProcessInfo* Process,
  3606. MachineInfo* Machine,
  3607. PADDR Addr,
  3608. ULONG InstrFlags,
  3609. PUCHAR StorageSpace)
  3610. {
  3611. if (InstrFlags != IBI_DEFAULT)
  3612. {
  3613. return E_INVALIDARG;
  3614. }
  3615. IeXdiCodeBreakpoint** BpStorage = (IeXdiCodeBreakpoint**)StorageSpace;
  3616. HRESULT Status = m_Server->
  3617. AddCodeBreakpoint(Flat(*Addr), m_CodeBpType, mtVirtual, 0, 0,
  3618. BpStorage);
  3619. if (Status == S_OK)
  3620. {
  3621. // Breakpoints are created disabled so enable it.
  3622. Status = (*BpStorage)->SetState(TRUE, TRUE);
  3623. if (Status != S_OK)
  3624. {
  3625. m_Server->DelCodeBreakpoint(*BpStorage);
  3626. RELEASE(*BpStorage);
  3627. }
  3628. }
  3629. return Status;
  3630. }
  3631. HRESULT
  3632. ExdiLiveKernelTargetInfo::InsertDataBreakpoint(ProcessInfo* Process,
  3633. ThreadInfo* Thread,
  3634. class MachineInfo* Machine,
  3635. PADDR Addr,
  3636. ULONG Size,
  3637. ULONG AccessType,
  3638. PUCHAR StorageSpace)
  3639. {
  3640. if (!m_ExdiDataBreaks)
  3641. {
  3642. return TargetInfo::InsertDataBreakpoint(Process, Thread, Machine,
  3643. Addr, Size, AccessType,
  3644. StorageSpace);
  3645. }
  3646. DATA_ACCESS_TYPE ExdiAccess;
  3647. if (AccessType & (DEBUG_BREAK_IO | DEBUG_BREAK_EXECUTE))
  3648. {
  3649. // Not supported.
  3650. return E_NOTIMPL;
  3651. }
  3652. switch(AccessType)
  3653. {
  3654. case 0:
  3655. return E_INVALIDARG;
  3656. case DEBUG_BREAK_READ:
  3657. ExdiAccess = daRead;
  3658. break;
  3659. case DEBUG_BREAK_WRITE:
  3660. ExdiAccess = daWrite;
  3661. break;
  3662. case DEBUG_BREAK_READ | DEBUG_BREAK_WRITE:
  3663. ExdiAccess = daBoth;
  3664. break;
  3665. }
  3666. IeXdiDataBreakpoint** BpStorage = (IeXdiDataBreakpoint**)StorageSpace;
  3667. HRESULT Status = m_Server->
  3668. AddDataBreakpoint(Flat(*Addr), -1, 0, 0, (BYTE)(Size * 8),
  3669. mtVirtual, 0, ExdiAccess, 0, BpStorage);
  3670. if (Status == S_OK)
  3671. {
  3672. // Breakpoints are created disabled so enable it.
  3673. Status = (*BpStorage)->SetState(TRUE, TRUE);
  3674. if (Status != S_OK)
  3675. {
  3676. m_Server->DelDataBreakpoint(*BpStorage);
  3677. RELEASE(*BpStorage);
  3678. }
  3679. }
  3680. return Status;
  3681. }
  3682. void
  3683. ExdiLiveKernelTargetInfo::EndInsertingBreakpoints(void)
  3684. {
  3685. if (!m_ExdiDataBreaks)
  3686. {
  3687. TargetInfo::EndInsertingBreakpoints();
  3688. }
  3689. }
  3690. void
  3691. ExdiLiveKernelTargetInfo::BeginRemovingBreakpoints(void)
  3692. {
  3693. if (!m_ExdiDataBreaks)
  3694. {
  3695. TargetInfo::BeginRemovingBreakpoints();
  3696. }
  3697. }
  3698. HRESULT
  3699. ExdiLiveKernelTargetInfo::RemoveCodeBreakpoint(ProcessInfo* Process,
  3700. MachineInfo* Machine,
  3701. PADDR Addr,
  3702. ULONG InstrFlags,
  3703. PUCHAR StorageSpace)
  3704. {
  3705. IeXdiCodeBreakpoint** BpStorage = (IeXdiCodeBreakpoint**)StorageSpace;
  3706. HRESULT Status = m_Server->
  3707. DelCodeBreakpoint(*BpStorage);
  3708. if (Status == S_OK)
  3709. {
  3710. RELEASE(*BpStorage);
  3711. }
  3712. return Status;
  3713. }
  3714. HRESULT
  3715. ExdiLiveKernelTargetInfo::RemoveDataBreakpoint(ProcessInfo* Process,
  3716. ThreadInfo* Thread,
  3717. class MachineInfo* Machine,
  3718. PADDR Addr,
  3719. ULONG Size,
  3720. ULONG AccessType,
  3721. PUCHAR StorageSpace)
  3722. {
  3723. if (!m_ExdiDataBreaks)
  3724. {
  3725. return TargetInfo::RemoveDataBreakpoint(Process, Thread, Machine,
  3726. Addr, Size, AccessType,
  3727. StorageSpace);
  3728. }
  3729. IeXdiDataBreakpoint** BpStorage = (IeXdiDataBreakpoint**)StorageSpace;
  3730. HRESULT Status = m_Server->
  3731. DelDataBreakpoint(*BpStorage);
  3732. if (Status == S_OK)
  3733. {
  3734. RELEASE(*BpStorage);
  3735. }
  3736. return Status;
  3737. }
  3738. void
  3739. ExdiLiveKernelTargetInfo::EndRemovingBreakpoints(void)
  3740. {
  3741. if (!m_ExdiDataBreaks)
  3742. {
  3743. TargetInfo::EndRemovingBreakpoints();
  3744. }
  3745. }
  3746. HRESULT
  3747. ExdiLiveKernelTargetInfo::IsDataBreakpointHit(ThreadInfo* Thread,
  3748. PADDR Addr,
  3749. ULONG Size,
  3750. ULONG AccessType,
  3751. PUCHAR StorageSpace)
  3752. {
  3753. if (!m_ExdiDataBreaks)
  3754. {
  3755. return S_FALSE;
  3756. }
  3757. if (m_BpHit.Type != DBGENG_EXDI_IOCTL_BREAKPOINT_DATA ||
  3758. m_BpHit.Address != Flat(*Addr) ||
  3759. m_BpHit.AccessWidth != Size)
  3760. {
  3761. return E_NOINTERFACE;
  3762. }
  3763. return S_OK;
  3764. }
  3765. HRESULT
  3766. LiveUserTargetInfo::BeginInsertingBreakpoints(void)
  3767. {
  3768. if (m_ServiceFlags & DBGSVC_GENERIC_DATA_BREAKPOINTS)
  3769. {
  3770. return TargetInfo::BeginInsertingBreakpoints();
  3771. }
  3772. // Services handle everything so there's no preparation.
  3773. return S_OK;
  3774. }
  3775. HRESULT
  3776. LiveUserTargetInfo::InsertCodeBreakpoint(ProcessInfo* Process,
  3777. MachineInfo* Machine,
  3778. PADDR Addr,
  3779. ULONG InstrFlags,
  3780. PUCHAR StorageSpace)
  3781. {
  3782. HRESULT Status;
  3783. if (m_ServiceFlags & DBGSVC_GENERIC_CODE_BREAKPOINTS)
  3784. {
  3785. ULONG64 ChangeStart;
  3786. ULONG ChangeLen;
  3787. Status = Machine->
  3788. InsertBreakpointInstruction(m_Services,
  3789. Process->m_SysHandle,
  3790. Flat(*Addr), InstrFlags, StorageSpace,
  3791. &ChangeStart, &ChangeLen);
  3792. if ((Status == HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY) ||
  3793. Status == HRESULT_FROM_WIN32(ERROR_NOACCESS) ||
  3794. Status == HRESULT_FROM_WIN32(ERROR_WRITE_FAULT)) &&
  3795. (g_EngOptions & DEBUG_ENGOPT_ALLOW_READ_ONLY_BREAKPOINTS))
  3796. {
  3797. HRESULT NewStatus;
  3798. ULONG OldProtect;
  3799. // Change the page protections to read-write and try again.
  3800. NewStatus = m_Services->
  3801. ProtectVirtual(Process->m_SysHandle, ChangeStart, ChangeLen,
  3802. PAGE_READWRITE, &OldProtect);
  3803. if (NewStatus == S_OK)
  3804. {
  3805. // If the page was already writable there's no point in
  3806. // retrying
  3807. if ((OldProtect & (PAGE_READWRITE |
  3808. PAGE_WRITECOPY |
  3809. PAGE_EXECUTE_READWRITE |
  3810. PAGE_EXECUTE_WRITECOPY)) == 0)
  3811. {
  3812. NewStatus = Machine->
  3813. InsertBreakpointInstruction(m_Services,
  3814. Process->m_SysHandle,
  3815. Flat(*Addr), InstrFlags,
  3816. StorageSpace,
  3817. &ChangeStart, &ChangeLen);
  3818. if (NewStatus == S_OK)
  3819. {
  3820. Status = S_OK;
  3821. }
  3822. }
  3823. NewStatus = m_Services->
  3824. ProtectVirtual(Process->m_SysHandle,
  3825. ChangeStart, ChangeLen,
  3826. OldProtect, &OldProtect);
  3827. if (NewStatus != S_OK)
  3828. {
  3829. // Couldn't restore page permissions so fail.
  3830. if (Status == S_OK)
  3831. {
  3832. Machine->
  3833. RemoveBreakpointInstruction(m_Services,
  3834. Process->m_SysHandle,
  3835. Flat(*Addr),
  3836. StorageSpace,
  3837. &ChangeStart,
  3838. &ChangeLen);
  3839. }
  3840. Status = NewStatus;
  3841. }
  3842. }
  3843. }
  3844. return Status;
  3845. }
  3846. else
  3847. {
  3848. if (InstrFlags != IBI_DEFAULT)
  3849. {
  3850. return E_INVALIDARG;
  3851. }
  3852. return m_Services->
  3853. InsertCodeBreakpoint(Process->m_SysHandle,
  3854. Flat(*Addr), Machine->m_ExecTypes[0],
  3855. StorageSpace, MAX_BREAKPOINT_LENGTH);
  3856. }
  3857. }
  3858. HRESULT
  3859. LiveUserTargetInfo::InsertDataBreakpoint(ProcessInfo* Process,
  3860. ThreadInfo* Thread,
  3861. class MachineInfo* Machine,
  3862. PADDR Addr,
  3863. ULONG Size,
  3864. ULONG AccessType,
  3865. PUCHAR StorageSpace)
  3866. {
  3867. if (m_ServiceFlags & DBGSVC_GENERIC_DATA_BREAKPOINTS)
  3868. {
  3869. return S_FALSE;
  3870. }
  3871. return m_Services->
  3872. InsertDataBreakpoint(Process->m_SysHandle,
  3873. Thread ? Thread->m_Handle : 0,
  3874. Flat(*Addr), Size, AccessType,
  3875. Machine->m_ExecTypes[0]);
  3876. }
  3877. void
  3878. LiveUserTargetInfo::EndInsertingBreakpoints(void)
  3879. {
  3880. if (m_ServiceFlags & DBGSVC_GENERIC_DATA_BREAKPOINTS)
  3881. {
  3882. return TargetInfo::EndInsertingBreakpoints();
  3883. }
  3884. // Services handle everything so there's no preparation.
  3885. }
  3886. HRESULT
  3887. LiveUserTargetInfo::RemoveCodeBreakpoint(ProcessInfo* Process,
  3888. MachineInfo* Machine,
  3889. PADDR Addr,
  3890. ULONG InstrFlags,
  3891. PUCHAR StorageSpace)
  3892. {
  3893. HRESULT Status;
  3894. if (m_ServiceFlags & DBGSVC_GENERIC_CODE_BREAKPOINTS)
  3895. {
  3896. ULONG64 ChangeStart;
  3897. ULONG ChangeLen;
  3898. Status = Machine->
  3899. RemoveBreakpointInstruction(m_Services,
  3900. Process->m_SysHandle,
  3901. Flat(*Addr), StorageSpace,
  3902. &ChangeStart, &ChangeLen);
  3903. if ((Status == HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY) ||
  3904. Status == HRESULT_FROM_WIN32(ERROR_NOACCESS) ||
  3905. Status == HRESULT_FROM_WIN32(ERROR_WRITE_FAULT)) &&
  3906. (g_EngOptions & DEBUG_ENGOPT_ALLOW_READ_ONLY_BREAKPOINTS))
  3907. {
  3908. HRESULT NewStatus;
  3909. ULONG OldProtect;
  3910. // Change the page protections to read-write and try again.
  3911. NewStatus = m_Services->
  3912. ProtectVirtual(Process->m_SysHandle, ChangeStart, ChangeLen,
  3913. PAGE_READWRITE, &OldProtect);
  3914. if (NewStatus == S_OK)
  3915. {
  3916. // If the page was already writable there's no point in
  3917. // retrying
  3918. if ((OldProtect & (PAGE_READWRITE |
  3919. PAGE_WRITECOPY |
  3920. PAGE_EXECUTE_READWRITE |
  3921. PAGE_EXECUTE_WRITECOPY)) == 0)
  3922. {
  3923. NewStatus = Machine->
  3924. RemoveBreakpointInstruction(m_Services,
  3925. Process->m_SysHandle,
  3926. Flat(*Addr), StorageSpace,
  3927. &ChangeStart, &ChangeLen);
  3928. if (NewStatus == S_OK)
  3929. {
  3930. Status = S_OK;
  3931. }
  3932. }
  3933. NewStatus = m_Services->
  3934. ProtectVirtual(Process->m_SysHandle, ChangeStart,
  3935. ChangeLen, OldProtect, &OldProtect);
  3936. if (NewStatus != S_OK)
  3937. {
  3938. // Couldn't restore page permissions so fail.
  3939. if (Status == S_OK)
  3940. {
  3941. Machine->
  3942. InsertBreakpointInstruction(m_Services,
  3943. Process->m_SysHandle,
  3944. Flat(*Addr),
  3945. InstrFlags,
  3946. StorageSpace,
  3947. &ChangeStart,
  3948. &ChangeLen);
  3949. }
  3950. Status = NewStatus;
  3951. }
  3952. }
  3953. }
  3954. return Status;
  3955. }
  3956. else
  3957. {
  3958. return m_Services->
  3959. RemoveCodeBreakpoint(Process->m_SysHandle,
  3960. Flat(*Addr), Machine->m_ExecTypes[0],
  3961. StorageSpace, MAX_BREAKPOINT_LENGTH);
  3962. }
  3963. }
  3964. HRESULT
  3965. LiveUserTargetInfo::RemoveDataBreakpoint(ProcessInfo* Process,
  3966. ThreadInfo* Thread,
  3967. class MachineInfo* Machine,
  3968. PADDR Addr,
  3969. ULONG Size,
  3970. ULONG AccessType,
  3971. PUCHAR StorageSpace)
  3972. {
  3973. if (m_ServiceFlags & DBGSVC_GENERIC_DATA_BREAKPOINTS)
  3974. {
  3975. return S_FALSE;
  3976. }
  3977. return m_Services->
  3978. RemoveDataBreakpoint(Process->m_SysHandle,
  3979. Thread ? Thread->m_Handle : 0,
  3980. Flat(*Addr), Size, AccessType,
  3981. Machine->m_ExecTypes[0]);
  3982. }
  3983. HRESULT
  3984. LiveUserTargetInfo::IsDataBreakpointHit(ThreadInfo* Thread,
  3985. PADDR Addr,
  3986. ULONG Size,
  3987. ULONG AccessType,
  3988. PUCHAR StorageSpace)
  3989. {
  3990. if (m_ServiceFlags & DBGSVC_GENERIC_DATA_BREAKPOINTS)
  3991. {
  3992. // Ask for default processing.
  3993. return S_FALSE;
  3994. }
  3995. if (!m_DataBpAddrValid)
  3996. {
  3997. m_DataBpAddrStatus = m_Services->
  3998. GetLastDataBreakpointHit(Thread->m_Process->m_SysHandle,
  3999. Thread->m_Handle,
  4000. &m_DataBpAddr, &m_DataBpAccess);
  4001. m_DataBpAddrValid = TRUE;
  4002. }
  4003. if (m_DataBpAddrStatus != S_OK ||
  4004. m_DataBpAddr < Flat(*Addr) ||
  4005. m_DataBpAddr >= Flat(*Addr) + Size ||
  4006. !(m_DataBpAccess & AccessType))
  4007. {
  4008. return E_NOINTERFACE;
  4009. }
  4010. else
  4011. {
  4012. return S_OK;
  4013. }
  4014. }