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.

513 lines
14 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Breakpoint support.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #ifndef _BRKPT_HPP_
  9. #define _BRKPT_HPP_
  10. // Ways in which a breakpoint can be hit. There's full
  11. // match, hit but ignored and not hit.
  12. #define BREAKPOINT_HIT 0
  13. #define BREAKPOINT_HIT_IGNORED 1
  14. #define BREAKPOINT_NOT_HIT 2
  15. //----------------------------------------------------------------------------
  16. //
  17. // Breakpoint.
  18. //
  19. //----------------------------------------------------------------------------
  20. #define BREAKPOINT_EXTERNAL_MODIFY_FLAGS \
  21. (DEBUG_BREAKPOINT_GO_ONLY | DEBUG_BREAKPOINT_ENABLED | \
  22. DEBUG_BREAKPOINT_ADDER_ONLY | DEBUG_BREAKPOINT_ONE_SHOT)
  23. #define BREAKPOINT_EXTERNAL_FLAGS \
  24. (BREAKPOINT_EXTERNAL_MODIFY_FLAGS | DEBUG_BREAKPOINT_DEFERRED)
  25. // Internal flags.
  26. #define BREAKPOINT_KD_INTERNAL 0x80000000
  27. #define BREAKPOINT_KD_COUNT_ONLY 0x40000000
  28. #define BREAKPOINT_VIRT_ADDR 0x20000000
  29. #define BREAKPOINT_INSERTED 0x10000000
  30. #define BREAKPOINT_IN_LIST 0x08000000
  31. #define BREAKPOINT_HIDDEN 0x04000000
  32. #define BREAKPOINT_NOTIFY 0x02000000
  33. // Internal types.
  34. #define EXBS_NONE 0x00000000
  35. #define EXBS_BREAKPOINT_DATA 0x00000001
  36. #define EXBS_BREAKPOINT_CODE 0x00000002
  37. #define EXBS_BREAKPOINT_ANY 0x00000003
  38. #define EXBS_STEP_INSTRUCTION 0x00000004
  39. #define EXBS_STEP_BRANCH 0x00000008
  40. #define EXBS_STEP_ANY 0x0000000c
  41. #define EXBS_ANY 0xffffffff
  42. enum BreakpointMatchAction
  43. {
  44. BREAKPOINT_ALLOW_MATCH,
  45. BREAKPOINT_WARN_MATCH,
  46. BREAKPOINT_REMOVE_MATCH
  47. };
  48. enum BreakpointEvalResult
  49. {
  50. BPEVAL_RESOLVED,
  51. BPEVAL_RESOLVED_NO_MODULE,
  52. BPEVAL_UNRESOLVED,
  53. BPEVAL_ERROR,
  54. BPEVAL_UNKNOWN,
  55. };
  56. class Breakpoint
  57. : public IDebugBreakpoint
  58. {
  59. public:
  60. Breakpoint* m_Next;
  61. Breakpoint* m_Prev;
  62. ULONG m_Refs;
  63. ULONG m_Id;
  64. ULONG m_BreakType;
  65. ULONG m_Flags;
  66. ULONG m_CodeFlags;
  67. ULONG m_DataSize;
  68. ULONG m_DataAccessType;
  69. ULONG m_PassCount;
  70. ULONG m_CurPassCount;
  71. PCSTR m_Command;
  72. ThreadInfo* m_MatchThread;
  73. ProcessInfo* m_Process;
  74. PCSTR m_OffsetExpr;
  75. DebugClient* m_Adder;
  76. ULONG64 m_MatchThreadData;
  77. ULONG64 m_MatchProcessData;
  78. Breakpoint(DebugClient* Adder, ULONG Id, ULONG Type, ULONG ProcType);
  79. ~Breakpoint(void);
  80. //
  81. // IUnknown.
  82. //
  83. STDMETHOD(QueryInterface)(
  84. THIS_
  85. IN REFIID InterfaceId,
  86. OUT PVOID* Interface
  87. );
  88. STDMETHOD_(ULONG, AddRef)(
  89. THIS
  90. );
  91. STDMETHOD_(ULONG, Release)(
  92. THIS
  93. );
  94. //
  95. // IDebugBreakpoint.
  96. //
  97. STDMETHOD(GetId)(
  98. THIS_
  99. OUT PULONG Id
  100. );
  101. STDMETHOD(GetType)(
  102. THIS_
  103. OUT PULONG BreakType,
  104. OUT PULONG ProcType
  105. );
  106. STDMETHOD(GetAdder)(
  107. THIS_
  108. OUT PDEBUG_CLIENT* Adder
  109. );
  110. STDMETHOD(GetFlags)(
  111. THIS_
  112. OUT PULONG Flags
  113. );
  114. STDMETHOD(AddFlags)(
  115. THIS_
  116. IN ULONG Flags
  117. );
  118. STDMETHOD(RemoveFlags)(
  119. THIS_
  120. IN ULONG Flags
  121. );
  122. STDMETHOD(SetFlags)(
  123. THIS_
  124. IN ULONG Flags
  125. );
  126. STDMETHOD(GetOffset)(
  127. THIS_
  128. OUT PULONG64 Offset
  129. );
  130. STDMETHOD(SetOffset)(
  131. THIS_
  132. IN ULONG64 Offset
  133. );
  134. STDMETHOD(GetDataParameters)(
  135. THIS_
  136. OUT PULONG Size,
  137. OUT PULONG AccessType
  138. );
  139. STDMETHOD(SetDataParameters)(
  140. THIS_
  141. IN ULONG Size,
  142. IN ULONG AccessType
  143. );
  144. STDMETHOD(GetPassCount)(
  145. THIS_
  146. OUT PULONG Count
  147. );
  148. STDMETHOD(SetPassCount)(
  149. THIS_
  150. IN ULONG Count
  151. );
  152. STDMETHOD(GetCurrentPassCount)(
  153. THIS_
  154. OUT PULONG Count
  155. );
  156. STDMETHOD(GetMatchThreadId)(
  157. THIS_
  158. OUT PULONG Id
  159. );
  160. STDMETHOD(SetMatchThreadId)(
  161. THIS_
  162. IN ULONG Id
  163. );
  164. STDMETHOD(GetCommand)(
  165. THIS_
  166. OUT OPTIONAL PSTR Buffer,
  167. IN ULONG BufferSize,
  168. OUT OPTIONAL PULONG CommandSize
  169. );
  170. STDMETHOD(SetCommand)(
  171. THIS_
  172. IN PCSTR Command
  173. );
  174. STDMETHOD(GetOffsetExpression)(
  175. THIS_
  176. OUT OPTIONAL PSTR Buffer,
  177. IN ULONG BufferSize,
  178. OUT OPTIONAL PULONG ExpressionSize
  179. );
  180. STDMETHOD(SetOffsetExpression)(
  181. THIS_
  182. IN PCSTR Expression
  183. );
  184. STDMETHOD(GetParameters)(
  185. THIS_
  186. OUT PDEBUG_BREAKPOINT_PARAMETERS Params
  187. );
  188. //
  189. // Breakpoint.
  190. //
  191. virtual HRESULT Validate(void) = 0;
  192. virtual HRESULT Insert(void) = 0;
  193. virtual HRESULT Remove(void) = 0;
  194. virtual ULONG IsHit(PADDR Addr) = 0;
  195. // Must resturn true if in case of THIS breakpoint hit
  196. // Pc points to the instruction caused the hit
  197. virtual BOOL PcAtHit() = 0;
  198. // Internal refcounting which does true counting,
  199. // as opposed to the disabled public AddRef/Release.
  200. void Preserve(void)
  201. {
  202. m_Refs++;
  203. }
  204. void Relinquish(void)
  205. {
  206. if (--m_Refs == 0)
  207. {
  208. delete this;
  209. }
  210. }
  211. PADDR GetAddr(void)
  212. {
  213. return &m_Addr;
  214. }
  215. BOOL PassHit(void)
  216. {
  217. if (--m_CurPassCount == 0)
  218. {
  219. m_CurPassCount = 1;
  220. return TRUE;
  221. }
  222. else
  223. {
  224. return FALSE;
  225. }
  226. }
  227. ULONG GetProcType(void)
  228. {
  229. return m_ProcType;
  230. }
  231. void SetProcType(ULONG ProcType)
  232. {
  233. m_ProcType = ProcType;
  234. m_ProcIndex = MachineTypeIndex(ProcType);
  235. }
  236. ULONG GetProcIndex(void)
  237. {
  238. return m_ProcIndex;
  239. }
  240. void ForceFlatAddr(void)
  241. {
  242. NotFlat(m_Addr);
  243. ComputeFlatAddress(&m_Addr, NULL);
  244. }
  245. // Breakpoint is enabled, not deferred, not internal.
  246. BOOL IsNormalEnabled(void)
  247. {
  248. return (m_Flags & (DEBUG_BREAKPOINT_ENABLED |
  249. BREAKPOINT_KD_INTERNAL |
  250. DEBUG_BREAKPOINT_DEFERRED)) ==
  251. DEBUG_BREAKPOINT_ENABLED;
  252. }
  253. void NotifyChanged(void)
  254. {
  255. if (!(m_Flags & BREAKPOINT_HIDDEN))
  256. {
  257. NotifyChangeEngineState(DEBUG_CES_BREAKPOINTS, m_Id, TRUE);
  258. }
  259. }
  260. HRESULT SetEvaluatedOffsetExpression(PCSTR Expr,
  261. BreakpointEvalResult Valid,
  262. PADDR Addr);
  263. void LinkIntoList(void);
  264. void UnlinkFromList(void);
  265. void UpdateInternal(void);
  266. BOOL EvalOffsetExpr(BreakpointEvalResult Valid, PADDR Addr);
  267. HRESULT CheckAddr(PADDR Addr);
  268. HRESULT SetAddr(PADDR Addr, BreakpointMatchAction MatchAction);
  269. // Matches breakpoints if they have the same insertion effect.
  270. // Used when determining whether a breakpoint needs to be
  271. // inserted or if another breakpoint is already covering the break.
  272. BOOL IsInsertionMatch(Breakpoint* Match);
  273. // Matches breakpoints if they have an insertion match and
  274. // if they match publicly, such as between flags, hiddenness
  275. // and so on. Used when determining whether a user breakpoint
  276. // redefines an existing breakpoint.
  277. BOOL IsPublicMatch(Breakpoint* Match);
  278. // Check m_Match* fields against current state.
  279. BOOL MatchesCurrentState(void);
  280. protected:
  281. // ProcType is private so that ProcType and ProcIndex can
  282. // be kept in sync.
  283. ULONG m_ProcType;
  284. MachineIndex m_ProcIndex;
  285. // Address is private to force users to go through SetAddr.
  286. ADDR m_Addr;
  287. ULONG m_CommandLen;
  288. ULONG m_OffsetExprLen;
  289. UCHAR m_InsertStorage[MAX_BREAKPOINT_LENGTH];
  290. };
  291. //----------------------------------------------------------------------------
  292. //
  293. // CodeBreakpoint.
  294. //
  295. //----------------------------------------------------------------------------
  296. class CodeBreakpoint :
  297. public Breakpoint
  298. {
  299. public:
  300. CodeBreakpoint(DebugClient* Adder, ULONG Id, ULONG ProcType)
  301. : Breakpoint(Adder, Id, DEBUG_BREAKPOINT_CODE, ProcType)
  302. {
  303. m_Flags |= BREAKPOINT_VIRT_ADDR;
  304. }
  305. // Breakpoint.
  306. virtual HRESULT Validate(void);
  307. virtual HRESULT Insert(void);
  308. virtual HRESULT Remove(void);
  309. virtual ULONG IsHit(PADDR Addr);
  310. virtual BOOL PcAtHit()
  311. {
  312. return TRUE;
  313. }
  314. };
  315. //----------------------------------------------------------------------------
  316. //
  317. // DataBreakpoint.
  318. //
  319. //----------------------------------------------------------------------------
  320. class DataBreakpoint :
  321. public Breakpoint
  322. {
  323. public:
  324. DataBreakpoint(DebugClient* Adder, ULONG Id, ULONG ProcType)
  325. : Breakpoint(Adder, Id, DEBUG_BREAKPOINT_DATA, ProcType) {}
  326. // Breakpoint.
  327. virtual HRESULT Insert(void);
  328. virtual HRESULT Remove(void);
  329. // DataBreakpoint.
  330. static void ClearThreadDataBreaks(ThreadInfo* Thread);
  331. void AddToThread(ThreadInfo* Thread);
  332. };
  333. //----------------------------------------------------------------------------
  334. //
  335. // X86DataBreakpoint.
  336. //
  337. //----------------------------------------------------------------------------
  338. class X86DataBreakpoint :
  339. public DataBreakpoint
  340. {
  341. public:
  342. X86DataBreakpoint(DebugClient* Adder, ULONG Id,
  343. ULONG Cr4Reg, ULONG Dr6Reg, ULONG ProcType)
  344. : DataBreakpoint(Adder, Id, ProcType)
  345. {
  346. m_Dr7Bits = 0;
  347. m_Cr4Reg = Cr4Reg;
  348. m_Dr6Reg = Dr6Reg;
  349. }
  350. // Breakpoint.
  351. virtual HRESULT Validate(void);
  352. virtual ULONG IsHit(PADDR Addr);
  353. virtual BOOL PcAtHit()
  354. {
  355. return FALSE;
  356. }
  357. private:
  358. // Precomputed enable bits.
  359. ULONG m_Dr7Bits;
  360. // Register indices for getting breakpoint-related information.
  361. ULONG m_Cr4Reg;
  362. ULONG m_Dr6Reg;
  363. friend class X86MachineInfo;
  364. friend class Amd64MachineInfo;
  365. };
  366. //----------------------------------------------------------------------------
  367. //
  368. // Ia64DataBreakpoint.
  369. //
  370. //----------------------------------------------------------------------------
  371. class Ia64DataBreakpoint :
  372. public DataBreakpoint
  373. {
  374. public:
  375. Ia64DataBreakpoint(DebugClient* Adder, ULONG Id)
  376. : DataBreakpoint(Adder, Id, IMAGE_FILE_MACHINE_IA64)
  377. {
  378. m_Control = 0;
  379. }
  380. // Breakpoint.
  381. virtual HRESULT Validate(void);
  382. virtual ULONG IsHit(PADDR Addr);
  383. virtual BOOL PcAtHit()
  384. {
  385. return TRUE;
  386. }
  387. static ULONG64 GetControl(ULONG AccessType, ULONG Size);
  388. private:
  389. ULONG64 m_Control;
  390. friend class Ia64MachineInfo;
  391. };
  392. //----------------------------------------------------------------------------
  393. //
  394. // X86OnIa64DataBreakpoint.
  395. //
  396. //----------------------------------------------------------------------------
  397. class X86OnIa64DataBreakpoint :
  398. public X86DataBreakpoint
  399. {
  400. public:
  401. X86OnIa64DataBreakpoint(DebugClient* Adder, ULONG Id);
  402. // Breakpoint.
  403. virtual HRESULT Validate(void);
  404. virtual ULONG IsHit(PADDR Addr);
  405. private:
  406. ULONG64 m_Control;
  407. friend class Ia64MachineInfo;
  408. };
  409. extern BOOL g_BreakpointListChanged;
  410. extern BOOL g_UpdateDataBreakpoints;
  411. extern BOOL g_DataBreakpointsChanged;
  412. extern BOOL g_BreakpointsSuspended;
  413. extern BOOL g_DeferDefined;
  414. extern Breakpoint* g_DeferBp;
  415. extern Breakpoint* g_StepTraceBp;
  416. extern CHAR g_StepTraceCmdState;
  417. HRESULT BreakpointInit(void);
  418. HRESULT InsertBreakpoints(void);
  419. HRESULT RemoveBreakpoints(void);
  420. HRESULT AddBreakpoint(DebugClient* Client,
  421. MachineInfo* Machine,
  422. ULONG Type,
  423. ULONG DesiredId,
  424. Breakpoint** Bp);
  425. void RemoveBreakpoint(Breakpoint* Bp);
  426. void RemoveProcessBreakpoints(ProcessInfo* Process);
  427. void RemoveThreadBreakpoints(ThreadInfo* Thread);
  428. void RemoveAllBreakpoints(ULONG Reason);
  429. Breakpoint* GetBreakpointByIndex(DebugClient* Client, ULONG Index);
  430. Breakpoint* GetBreakpointById(DebugClient* Client, ULONG Id);
  431. Breakpoint* CheckMatchingBreakpoints(Breakpoint* Match, BOOL PUBLIC,
  432. ULONG IncFlags);
  433. Breakpoint* CheckBreakpointHit(ProcessInfo* Process,
  434. Breakpoint* Start, PADDR Addr,
  435. ULONG ExbsType, ULONG IncFlags, ULONG ExcFlags,
  436. PULONG HitType,
  437. BOOL SetLastBreakpointHit);
  438. ULONG NotifyHitBreakpoints(ULONG EventStatus);
  439. void EvaluateOffsetExpressions(ProcessInfo* Process, ULONG Flags);
  440. #define BPCMDS_FORCE_DISABLE 0x00000001
  441. #define BPCMDS_ONE_LINE 0x00000002
  442. #define BPCMDS_EXPR_ONLY 0x00000004
  443. #define BPCMDS_MODULE_HINT 0x00000008
  444. void ChangeBreakpointState(DebugClient* Client, ProcessInfo* ForProcess,
  445. ULONG Id, UCHAR StateChange);
  446. void ListBreakpoints(DebugClient* Client, ProcessInfo* ForProcess,
  447. ULONG Id);
  448. void ListBreakpointsAsCommands(DebugClient* Client, ProcessInfo* Process,
  449. ULONG Flags);
  450. PDEBUG_BREAKPOINT ParseBpCmd(DebugClient* Client, UCHAR Type,
  451. ThreadInfo* Thread);
  452. BOOL CheckBreakpointInsertedInRange(ProcessInfo* Process,
  453. ULONG64 Start, ULONG64 End);
  454. #endif // #ifndef _BRKPT_HPP_