Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: experimental/windows_debugger/debugger/core/debuggee_process.cc

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 #include "debugger/core/debuggee_process.h"
5 #include <assert.h>
6 #include "debugger/core/debug_api.h"
7 #include "debugger/core/debug_breakpoint.h"
8 #include "debugger/core/debug_event.h"
9
10 namespace debug {
11 DebuggeeProcess::DebuggeeProcess(int id,
12 HANDLE handle,
13 HANDLE file_handle,
14 DebugAPI* debug_api)
15 : id_(id),
16 handle_(handle),
17 file_handle_(file_handle),
18 state_(kRunning),
19 exit_code_(0),
20 debug_api_(*debug_api),
21 nexe_mem_base_(NULL),
22 nexe_entry_point_(NULL) {
23 }
24
25 DebuggeeProcess::~DebuggeeProcess() {
26 DeleteThreads();
27 if (NULL != file_handle_) {
28 debug_api().CloseHandle(file_handle_);
29 file_handle_ = NULL;
30 }
31 // Delete breakpoints.
32 std::map<void*, Breakpoint*>::const_iterator it = breakpoints_.begin();
33 while (it != breakpoints_.end()) {
34 delete it->second;
35 ++it;
36 }
37 breakpoints_.clear();
38 }
39
40 /// Implementation relies on the fact that 32 bit debugger cannot run
41 /// 64 bit debuggee process (::CreateProcess with DEBUG_PROCESS fails).
42 /// Also, 32 bit debugger is not able to attach to 64 bit process.
43 ///
44 /// Debugger x debuggee matrix:
45 /// a) 32 x 32 -> _WIN64 not defined, not WoW, returns 32
46 /// b) 32 x 64 -> ::CreateProcess fails, impossible to get here
47 /// c) 64 x 64 -> _WIN64 is defined, not WoW, returns 64
48 /// d) 64 x 32 -> _WIN64 is defined, WoW, returns 32
49 int DebuggeeProcess::GetWordSizeInBits() {
50 #ifndef _WIN64
51 // Not 64-bit debugger, so must be a 32-bit debugger and debuggee.
52 return 32;
53 #else
54 if (IsWoW())
55 return 32;
56 return 64;
57 #endif
58 }
59
60 bool DebuggeeProcess::IsWoW() {
61 #ifndef _WIN64
62 return false;
63 #else
64 BOOL is_wow = FALSE;
65 if (!debug_api().IsWoW64Process(handle_, &is_wow))
66 return false;
67 return is_wow ? true : false;
68 #endif
69 }
70
71 void* DebuggeeProcess::FromNexeToFlatAddress(void* addr) const {
72 #ifndef _WIN64
73 addr = reinterpret_cast<char*>(addr) +
74 reinterpret_cast<size_t>(nexe_mem_base_);
75 #endif
76 return addr;
77 }
78
79 bool DebuggeeProcess::Continue() {
80 return ContinueHaltedThread(DebuggeeThread::kContinue);
81 }
82
83 bool DebuggeeProcess::ContinueAndPassExceptionToDebuggee() {
84 return ContinueHaltedThread(DebuggeeThread::kContinueAndPassException);
85 }
86
87 bool DebuggeeProcess::SingleStep() {
88 return ContinueHaltedThread(DebuggeeThread::kSingleStep);
89 }
90
91 bool DebuggeeProcess::Break() {
92 return (FALSE != debug_api().DebugBreakProcess(handle_));
93 }
94
95 bool DebuggeeProcess::Kill() {
96 std::deque<DebuggeeThread*>::const_iterator it = threads_.begin();
97 while (it != threads_.end()) {
98 DebuggeeThread* thread = *it;
99 ++it;
100 if (NULL != thread)
101 thread->Kill();
102 }
103 return Continue();
104 }
105
106 bool DebuggeeProcess::Detach() {
107 BOOL res = debug_api().DebugActiveProcessStop(id());
108 DeleteThreads();
109 state_ = kDead;
110 return (FALSE != res);
111 }
112
113 DebuggeeThread* DebuggeeProcess::GetThread(int id) {
114 std::deque<DebuggeeThread*>::iterator it = threads_.begin();
115 while (it != threads_.end()) {
116 DebuggeeThread* thread = *it;
117 if (thread->id() == id)
118 return thread;
119 ++it;
120 }
121 return NULL;
122 }
123
124 DebuggeeThread* DebuggeeProcess::GetHaltedThread() {
125 std::deque<DebuggeeThread*>::const_iterator it = threads_.begin();
126 while (it != threads_.end()) {
127 DebuggeeThread* thread = *it++;
128 if (thread->IsHalted())
129 return thread;
130 }
131 return NULL;
132 }
133
134 void DebuggeeProcess::GetThreadIds(std::deque<int>* threads) const {
135 if (NULL == threads)
136 return;
137 threads->clear();
138 std::deque<DebuggeeThread*>::const_iterator it = threads_.begin();
139 while (it != threads_.end()) {
140 DebuggeeThread* thread = *it++;
141 threads->push_back(thread->id());
142 }
143 }
144
145 bool DebuggeeProcess::ReadMemory(const void* addr,
146 size_t size,
147 void* destination) {
148 // There's no need to change memory protection, because debugger
149 // has full access to the debuggee memory.
150 // The function fails if the requested read operation crosses into an area
151 // of the process that is inaccessible.
152 if (!debug_api().ReadProcessMemory(handle_, addr, destination, size, NULL)) {
153 return false;
154 }
155 return true;
156 }
157
158 bool DebuggeeProcess::WriteMemory(const void* addr,
159 size_t size,
160 const void* source) {
161 if (!IsHalted())
162 return false;
163 // There's no need to change memory protection, because debugger
164 // has full access to the debuggee memory.
165 // The function fails if the requested write operation crosses into an area
166 // of the process that is inaccessible.
167 BOOL res = debug_api().WriteProcessMemory(handle_,
168 const_cast<void*>(addr),
169 source,
170 size,
171 NULL);
172 if (!res) {
173 return false;
174 }
175 // Flushes the instruction cache for the debuggee process.
176 // The CPU cannot detect the change, and may execute the old code it cached.
177 res = debug_api().FlushInstructionCache(handle_, addr, size);
178 if (!res) {
179 return false;
180 }
181 return true;
182 }
183
184 bool DebuggeeProcess::SetBreakpoint(void* addr) {
185 if (!IsHalted())
186 return false;
187
188 if (NULL != GetBreakpoint(addr))
189 return false;
190
191 Breakpoint* br = new Breakpoint(addr, this);
192 if (br->Init()) {
193 breakpoints_[addr] = br;
194 return true;
195 }
196 delete br;
197 return false;
198 }
199
200 Breakpoint* DebuggeeProcess::GetBreakpoint(void* addr) {
201 std::map<void*, Breakpoint*>::iterator it = breakpoints_.find(addr);
202 if (breakpoints_.end() == it)
203 return NULL;
204 return it->second;
205 }
206
207 bool DebuggeeProcess::RemoveBreakpoint(void* addr) {
208 if (!IsHalted())
209 return false;
210
211 bool result = true;
212 std::map<void*, Breakpoint*>::iterator it = breakpoints_.find(addr);
213 if (breakpoints_.end() != it) {
214 Breakpoint* br = it->second;
215 if (!br->RecoverCodeAtBreakpoint())
216 result = false;
217 delete br;
218 breakpoints_.erase(it);
219 }
220 return result;
221 }
222
223 void DebuggeeProcess::GetBreakpoints(std::deque<Breakpoint*>* breakpoints) {
224 if (NULL == breakpoints)
225 return;
226 breakpoints->clear();
227 std::map<void*, Breakpoint*>::const_iterator it = breakpoints_.begin();
228 while (it != breakpoints_.end()) {
229 breakpoints->push_back(it->second);
230 ++it;
231 }
232 }
233
234 void DebuggeeProcess::OnDebugEvent(DebugEvent* debug_event) {
235 last_debug_event_ = *debug_event;
236 DEBUG_EVENT wde = debug_event->windows_debug_event();
237
238 switch (wde.dwDebugEventCode) {
239 case CREATE_PROCESS_DEBUG_EVENT: {
240 AddThread(
241 wde.dwThreadId,
242 wde.u.CreateProcessInfo.hThread);
243 break;
244 }
245 case CREATE_THREAD_DEBUG_EVENT: {
246 AddThread(
247 wde.dwThreadId,
248 wde.u.CreateThread.hThread);
249 break;
250 }
251 case EXIT_PROCESS_DEBUG_EVENT: {
252 exit_code_ = wde.u.ExitProcess.dwExitCode;
253 break;
254 }
255 }
256 DebuggeeThread* thread = GetThread(wde.dwThreadId);
257 if (NULL != thread) {
258 thread->OnDebugEvent(debug_event);
259 if (thread->IsHalted())
260 state_ = kHalted;
261 } else {
262 /// To prevent halting the process in case we lost the thread
263 /// object somehow.
264 debug_api().ContinueDebugEvent(id(), wde.dwThreadId, DBG_CONTINUE);
265 }
266 }
267
268 bool DebuggeeProcess::ContinueHaltedThread(
269 DebuggeeThread::ContinueOption option) {
270 if (state_ != kHalted)
271 return false;
272
273 DebuggeeThread* halted_thread = GetHaltedThread();
274 assert(NULL != halted_thread);
275
276 if (NULL != halted_thread) {
277 bool res = halted_thread->Continue(option);
278 if (halted_thread->state() == DebuggeeThread::kDead)
279 RemoveThread(halted_thread->id());
280
281 int last_debug_event_id =
282 last_debug_event_.windows_debug_event().dwDebugEventCode;
283 if (EXIT_PROCESS_DEBUG_EVENT == last_debug_event_id)
284 state_ = kDead;
285 else
286 state_ = kRunning;
287 return (TRUE == res);
288 }
289 return false;
290 }
291
292 DebuggeeThread* DebuggeeProcess::AddThread(int id, HANDLE handle) {
293 DebuggeeThread* thread = GetThread(id);
294 if (NULL == thread) {
295 thread = new DebuggeeThread(id, handle, this);
296 threads_.push_back(thread);
297 }
298 return thread;
299 }
300
301 void DebuggeeProcess::RemoveThread(int id) {
302 std::deque<DebuggeeThread*>::iterator it = threads_.begin();
303 while (it != threads_.end()) {
304 DebuggeeThread* thread = *it;
305 if (thread->id() == id) {
306 threads_.erase(it);
307 delete thread;
308 break;
309 }
310 ++it;
311 }
312 }
313
314 void DebuggeeProcess::DeleteThreads() {
315 std::deque<DebuggeeThread*>::const_iterator it = threads_.begin();
316 while (it != threads_.end()) {
317 DebuggeeThread* thread = *it;
318 delete thread;
319 ++it;
320 }
321 threads_.clear();
322 }
323 } // namespace debug
324
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698