OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 #ifndef DEBUGGER_CORE_DEBUGGEE_THREAD_H_ | |
5 #define DEBUGGER_CORE_DEBUGGEE_THREAD_H_ | |
6 | |
7 #include <windows.h> | |
8 #include "debugger/core/debug_breakpoint.h" | |
9 | |
10 namespace debug { | |
11 class IDebuggeeProcess; | |
12 class DebugAPI; | |
13 class DebugEvent; | |
14 class Breakpoint; | |
15 | |
16 /// This class represents a thread in the debugged process. | |
17 | |
18 /// Each thread belongs to one DebuggeeProcess. | |
19 /// | |
20 /// Class diagram (and more) is here: | |
21 /// https://docs.google.com/a/google.com/document/d/1lTN-IYqDd_oy9XQg9-zlNc_vbg-
qyr4q2MKNEjhSA84/edit?hl=en&authkey=CJyJlOgF# | |
22 /// | |
23 /// Note: most methods shall be called from one thread, this is limitation | |
24 /// of Windows debug API, here's links to Microsoft documentation: | |
25 /// http://msdn.microsoft.com/en-us/library/ms681423%28v=VS.85%29.aspx | |
26 /// http://msdn.microsoft.com/en-us/library/ms681675%28v=vs.85%29.aspx | |
27 /// Simple accessors can be called from any thread. | |
28 /// | |
29 /// Note: not thread-safe. | |
30 class DebuggeeThread { | |
31 public: | |
32 enum State { | |
33 kRunning = 1, // thread is alive, event loop is running | |
34 kHalted, // thread is alive, event loop is not running | |
35 kContinueFromBreakpoint, // thread is single stepping from breakpoint | |
36 kDead // thread is deleted by OS, user can only call |return_code()|, | |
37 // |id()|, |state()| methods. | |
38 }; | |
39 /// Describes a parameter type for |Continue| method. | |
40 enum ContinueOption { | |
41 kSingleStep, | |
42 kContinue, | |
43 kContinueAndPassException | |
44 }; | |
45 | |
46 /// Creates a DebuggeeThread object with specified thread |id|, | |
47 /// thread |handle| and |parent_process|. There's no need to close | |
48 /// |handle|, system will close handle when thread terminates. | |
49 /// |parent_process| shall not be NULL. | |
50 DebuggeeThread(int id, HANDLE handle, IDebuggeeProcess* parent_process); | |
51 | |
52 int id() const { return id_; } | |
53 HANDLE handle() const { return handle_; } | |
54 State state() const { return state_; } | |
55 | |
56 /// Shall be called only on dead threads (i.e. state_ == kDead). | |
57 /// @return exit code or exception number, if thread is terminated | |
58 /// by exception. | |
59 int return_code() const { return exit_code_; } | |
60 | |
61 /// @return true if this thread created to run nexe code. | |
62 bool IsNaClAppThread() const { return is_nacl_app_thread_; } | |
63 | |
64 /// Used for debugging debugger. | |
65 /// @param[in] state | |
66 /// @return name of the state | |
67 static const char* GetStateName(State state); | |
68 | |
69 /// Used for debugging debugger. | |
70 /// @param[in] continue option | |
71 /// @return name of the option | |
72 static const char* GetContinueOptionName(ContinueOption option); | |
73 | |
74 /// @return true if thread is in kHalted state | |
75 /// Halted thread is the one that caused the process to halt. | |
76 /// Note: only one thread can be halted in one process. | |
77 bool IsHalted() const; | |
78 | |
79 /// Reads registers of the thread. | |
80 /// Note that CONTEXT structure is defined differently | |
81 /// on 32-bit and 64-bit windows. | |
82 /// Shall be called only on halted process. | |
83 /// @return true if operation was successful. | |
84 bool GetContext(CONTEXT* context); | |
85 | |
86 /// Writes registers of the thread. | |
87 /// Shall be called only on halted process. | |
88 /// @return true if operation was successful. | |
89 bool SetContext(const CONTEXT& context); | |
90 | |
91 /// Reads registers of the WoW thread. | |
92 /// It should be used to work with WoW (windows-on-windows) | |
93 /// processes - i.e. 32-bit processes running on 64-bit windows. | |
94 /// Shall be called only on halted process. | |
95 /// @return true if operation was successful. | |
96 bool GetWowContext(WOW64_CONTEXT* context); | |
97 | |
98 /// Writes registers of the WoW thread. | |
99 /// It should be used to work with WoW (windows-on-windows) | |
100 /// processes - i.e. 32-bit processes running on 64-bit windows. | |
101 /// Shall be called only on halted process. | |
102 /// @return true if operation was successful. | |
103 bool SetWowContext(const WOW64_CONTEXT& context); | |
104 | |
105 /// Reads IP (instruction pointer). | |
106 /// Shall be called only on halted process. | |
107 /// @return value of EIP (for 32-bit process) or RIP (for 64-bit process). | |
108 void* GetIP(); | |
109 | |
110 /// Writes IP. | |
111 /// Shall be called only on halted process. | |
112 /// Writes EIP (for 32-bit process) or RIP (for 64-bit process). | |
113 bool SetIP(void* ip); | |
114 | |
115 protected: | |
116 friend class DebuggeeProcess; | |
117 | |
118 /// @return parent process. | |
119 IDebuggeeProcess& parent_process() { return parent_process_; } | |
120 const IDebuggeeProcess& parent_process() const { return parent_process_; } | |
121 DebugAPI& debug_api(); | |
122 | |
123 /// Allows thread execution to continue (i.e. it calls | |
124 /// ContinueDebugEvent()). | |
125 /// If |option| is kContinueAndPassException, and thread was halted due | |
126 /// to exception, that exception is passed to the debuggee thread. | |
127 bool Continue(ContinueOption option); | |
128 | |
129 /// Handler of debug events. DebuggeeThread has a FSM (finite state machine), | |
130 /// and |debug_event| is an only event consumed by FSM. | |
131 /// @param[in] debug_event debug event received from debuggee process | |
132 void OnDebugEvent(DebugEvent* debug_event); | |
133 | |
134 /// Terminates thread. | |
135 void Kill(); | |
136 | |
137 /// Changes internal state to |new_state|. | |
138 void SetState(State new_state); | |
139 | |
140 /// Changes a 'Trace' flag in CPUs EFlags register. | |
141 /// @param[in] enable single step | |
142 void EnableSingleStep(bool enable); | |
143 | |
144 /// Handler for OUTPUT_DEBUG_STRING_EVENT. | |
145 /// @param[in] debug_event debug event received from debuggee process | |
146 void OnOutputDebugString(DebugEvent* debug_event); | |
147 | |
148 /// Handler for EXCEPTION_DEBUG_EVENT.EXCEPTION_kBreakPOINT | |
149 /// @param[in] debug_event debug event received from debuggee process | |
150 void OnBreakpoint(DebugEvent* debug_event); | |
151 | |
152 /// Handler for EXCEPTION_DEBUG_EVENT.EXCEPTION_SINGLE_kStep | |
153 /// @param[in] debug_event debug event received from debuggee process | |
154 void OnSingleStep(DebugEvent* debug_event); | |
155 | |
156 /// Resumes execution of the halted thread, asuming breapoint was triggered. | |
157 bool ContinueFromBreakpoint(); | |
158 | |
159 private: | |
160 int id_; | |
161 HANDLE handle_; | |
162 IDebuggeeProcess& parent_process_; | |
163 State state_; | |
164 int exit_code_; | |
165 | |
166 /// Current breakpoint, if any. NULL if thread did not hit breakpoint. | |
167 void* triggered_breakpoint_addr_; | |
168 | |
169 // Stuff related only to nexe threads. | |
170 bool is_nacl_app_thread_; | |
171 | |
172 DebuggeeThread(const DebuggeeThread&); // DISALLOW_COPY_AND_ASSIGN | |
173 void operator=(const DebuggeeThread&); | |
174 }; | |
175 } // namespace debug | |
176 #endif // DEBUGGER_CORE_DEBUGGEE_THREAD_H_ | |
177 | |
OLD | NEW |