Index: experimental/windows_debugger/debugger/core/debuggee_process.cc |
diff --git a/experimental/windows_debugger/debugger/core/debuggee_process.cc b/experimental/windows_debugger/debugger/core/debuggee_process.cc |
deleted file mode 100644 |
index 7439d8352f6a2fe5f9d212ae21258496cdfe1802..0000000000000000000000000000000000000000 |
--- a/experimental/windows_debugger/debugger/core/debuggee_process.cc |
+++ /dev/null |
@@ -1,324 +0,0 @@ |
-// Copyright (c) 2011 The Native Client Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
-#include "debugger/core/debuggee_process.h" |
-#include <assert.h> |
-#include "debugger/core/debug_api.h" |
-#include "debugger/core/debug_breakpoint.h" |
-#include "debugger/core/debug_event.h" |
- |
-namespace debug { |
-DebuggeeProcess::DebuggeeProcess(int id, |
- HANDLE handle, |
- HANDLE file_handle, |
- DebugAPI* debug_api) |
- : id_(id), |
- handle_(handle), |
- file_handle_(file_handle), |
- state_(kRunning), |
- exit_code_(0), |
- debug_api_(*debug_api), |
- nexe_mem_base_(NULL), |
- nexe_entry_point_(NULL) { |
-} |
- |
-DebuggeeProcess::~DebuggeeProcess() { |
- DeleteThreads(); |
- if (NULL != file_handle_) { |
- debug_api().CloseHandle(file_handle_); |
- file_handle_ = NULL; |
- } |
- // Delete breakpoints. |
- std::map<void*, Breakpoint*>::const_iterator it = breakpoints_.begin(); |
- while (it != breakpoints_.end()) { |
- delete it->second; |
- ++it; |
- } |
- breakpoints_.clear(); |
-} |
- |
-/// Implementation relies on the fact that 32 bit debugger cannot run |
-/// 64 bit debuggee process (::CreateProcess with DEBUG_PROCESS fails). |
-/// Also, 32 bit debugger is not able to attach to 64 bit process. |
-/// |
-/// Debugger x debuggee matrix: |
-/// a) 32 x 32 -> _WIN64 not defined, not WoW, returns 32 |
-/// b) 32 x 64 -> ::CreateProcess fails, impossible to get here |
-/// c) 64 x 64 -> _WIN64 is defined, not WoW, returns 64 |
-/// d) 64 x 32 -> _WIN64 is defined, WoW, returns 32 |
-int DebuggeeProcess::GetWordSizeInBits() { |
-#ifndef _WIN64 |
- // Not 64-bit debugger, so must be a 32-bit debugger and debuggee. |
- return 32; |
-#else |
- if (IsWoW()) |
- return 32; |
- return 64; |
-#endif |
-} |
- |
-bool DebuggeeProcess::IsWoW() { |
-#ifndef _WIN64 |
- return false; |
-#else |
- BOOL is_wow = FALSE; |
- if (!debug_api().IsWoW64Process(handle_, &is_wow)) |
- return false; |
- return is_wow ? true : false; |
-#endif |
-} |
- |
-void* DebuggeeProcess::FromNexeToFlatAddress(void* addr) const { |
-#ifndef _WIN64 |
- addr = reinterpret_cast<char*>(addr) + |
- reinterpret_cast<size_t>(nexe_mem_base_); |
-#endif |
- return addr; |
-} |
- |
-bool DebuggeeProcess::Continue() { |
- return ContinueHaltedThread(DebuggeeThread::kContinue); |
-} |
- |
-bool DebuggeeProcess::ContinueAndPassExceptionToDebuggee() { |
- return ContinueHaltedThread(DebuggeeThread::kContinueAndPassException); |
-} |
- |
-bool DebuggeeProcess::SingleStep() { |
- return ContinueHaltedThread(DebuggeeThread::kSingleStep); |
-} |
- |
-bool DebuggeeProcess::Break() { |
- return (FALSE != debug_api().DebugBreakProcess(handle_)); |
-} |
- |
-bool DebuggeeProcess::Kill() { |
- std::deque<DebuggeeThread*>::const_iterator it = threads_.begin(); |
- while (it != threads_.end()) { |
- DebuggeeThread* thread = *it; |
- ++it; |
- if (NULL != thread) |
- thread->Kill(); |
- } |
- return Continue(); |
-} |
- |
-bool DebuggeeProcess::Detach() { |
- BOOL res = debug_api().DebugActiveProcessStop(id()); |
- DeleteThreads(); |
- state_ = kDead; |
- return (FALSE != res); |
-} |
- |
-DebuggeeThread* DebuggeeProcess::GetThread(int id) { |
- std::deque<DebuggeeThread*>::iterator it = threads_.begin(); |
- while (it != threads_.end()) { |
- DebuggeeThread* thread = *it; |
- if (thread->id() == id) |
- return thread; |
- ++it; |
- } |
- return NULL; |
-} |
- |
-DebuggeeThread* DebuggeeProcess::GetHaltedThread() { |
- std::deque<DebuggeeThread*>::const_iterator it = threads_.begin(); |
- while (it != threads_.end()) { |
- DebuggeeThread* thread = *it++; |
- if (thread->IsHalted()) |
- return thread; |
- } |
- return NULL; |
-} |
- |
-void DebuggeeProcess::GetThreadIds(std::deque<int>* threads) const { |
- if (NULL == threads) |
- return; |
- threads->clear(); |
- std::deque<DebuggeeThread*>::const_iterator it = threads_.begin(); |
- while (it != threads_.end()) { |
- DebuggeeThread* thread = *it++; |
- threads->push_back(thread->id()); |
- } |
-} |
- |
-bool DebuggeeProcess::ReadMemory(const void* addr, |
- size_t size, |
- void* destination) { |
- // There's no need to change memory protection, because debugger |
- // has full access to the debuggee memory. |
- // The function fails if the requested read operation crosses into an area |
- // of the process that is inaccessible. |
- if (!debug_api().ReadProcessMemory(handle_, addr, destination, size, NULL)) { |
- return false; |
- } |
- return true; |
-} |
- |
-bool DebuggeeProcess::WriteMemory(const void* addr, |
- size_t size, |
- const void* source) { |
- if (!IsHalted()) |
- return false; |
- // There's no need to change memory protection, because debugger |
- // has full access to the debuggee memory. |
- // The function fails if the requested write operation crosses into an area |
- // of the process that is inaccessible. |
- BOOL res = debug_api().WriteProcessMemory(handle_, |
- const_cast<void*>(addr), |
- source, |
- size, |
- NULL); |
- if (!res) { |
- return false; |
- } |
- // Flushes the instruction cache for the debuggee process. |
- // The CPU cannot detect the change, and may execute the old code it cached. |
- res = debug_api().FlushInstructionCache(handle_, addr, size); |
- if (!res) { |
- return false; |
- } |
- return true; |
-} |
- |
-bool DebuggeeProcess::SetBreakpoint(void* addr) { |
- if (!IsHalted()) |
- return false; |
- |
- if (NULL != GetBreakpoint(addr)) |
- return false; |
- |
- Breakpoint* br = new Breakpoint(addr, this); |
- if (br->Init()) { |
- breakpoints_[addr] = br; |
- return true; |
- } |
- delete br; |
- return false; |
-} |
- |
-Breakpoint* DebuggeeProcess::GetBreakpoint(void* addr) { |
- std::map<void*, Breakpoint*>::iterator it = breakpoints_.find(addr); |
- if (breakpoints_.end() == it) |
- return NULL; |
- return it->second; |
-} |
- |
-bool DebuggeeProcess::RemoveBreakpoint(void* addr) { |
- if (!IsHalted()) |
- return false; |
- |
- bool result = true; |
- std::map<void*, Breakpoint*>::iterator it = breakpoints_.find(addr); |
- if (breakpoints_.end() != it) { |
- Breakpoint* br = it->second; |
- if (!br->RecoverCodeAtBreakpoint()) |
- result = false; |
- delete br; |
- breakpoints_.erase(it); |
- } |
- return result; |
-} |
- |
-void DebuggeeProcess::GetBreakpoints(std::deque<Breakpoint*>* breakpoints) { |
- if (NULL == breakpoints) |
- return; |
- breakpoints->clear(); |
- std::map<void*, Breakpoint*>::const_iterator it = breakpoints_.begin(); |
- while (it != breakpoints_.end()) { |
- breakpoints->push_back(it->second); |
- ++it; |
- } |
-} |
- |
-void DebuggeeProcess::OnDebugEvent(DebugEvent* debug_event) { |
- last_debug_event_ = *debug_event; |
- DEBUG_EVENT wde = debug_event->windows_debug_event(); |
- |
- switch (wde.dwDebugEventCode) { |
- case CREATE_PROCESS_DEBUG_EVENT: { |
- AddThread( |
- wde.dwThreadId, |
- wde.u.CreateProcessInfo.hThread); |
- break; |
- } |
- case CREATE_THREAD_DEBUG_EVENT: { |
- AddThread( |
- wde.dwThreadId, |
- wde.u.CreateThread.hThread); |
- break; |
- } |
- case EXIT_PROCESS_DEBUG_EVENT: { |
- exit_code_ = wde.u.ExitProcess.dwExitCode; |
- break; |
- } |
- } |
- DebuggeeThread* thread = GetThread(wde.dwThreadId); |
- if (NULL != thread) { |
- thread->OnDebugEvent(debug_event); |
- if (thread->IsHalted()) |
- state_ = kHalted; |
- } else { |
- /// To prevent halting the process in case we lost the thread |
- /// object somehow. |
- debug_api().ContinueDebugEvent(id(), wde.dwThreadId, DBG_CONTINUE); |
- } |
-} |
- |
-bool DebuggeeProcess::ContinueHaltedThread( |
- DebuggeeThread::ContinueOption option) { |
- if (state_ != kHalted) |
- return false; |
- |
- DebuggeeThread* halted_thread = GetHaltedThread(); |
- assert(NULL != halted_thread); |
- |
- if (NULL != halted_thread) { |
- bool res = halted_thread->Continue(option); |
- if (halted_thread->state() == DebuggeeThread::kDead) |
- RemoveThread(halted_thread->id()); |
- |
- int last_debug_event_id = |
- last_debug_event_.windows_debug_event().dwDebugEventCode; |
- if (EXIT_PROCESS_DEBUG_EVENT == last_debug_event_id) |
- state_ = kDead; |
- else |
- state_ = kRunning; |
- return (TRUE == res); |
- } |
- return false; |
-} |
- |
-DebuggeeThread* DebuggeeProcess::AddThread(int id, HANDLE handle) { |
- DebuggeeThread* thread = GetThread(id); |
- if (NULL == thread) { |
- thread = new DebuggeeThread(id, handle, this); |
- threads_.push_back(thread); |
- } |
- return thread; |
-} |
- |
-void DebuggeeProcess::RemoveThread(int id) { |
- std::deque<DebuggeeThread*>::iterator it = threads_.begin(); |
- while (it != threads_.end()) { |
- DebuggeeThread* thread = *it; |
- if (thread->id() == id) { |
- threads_.erase(it); |
- delete thread; |
- break; |
- } |
- ++it; |
- } |
-} |
- |
-void DebuggeeProcess::DeleteThreads() { |
- std::deque<DebuggeeThread*>::const_iterator it = threads_.begin(); |
- while (it != threads_.end()) { |
- DebuggeeThread* thread = *it; |
- delete thread; |
- ++it; |
- } |
- threads_.clear(); |
-} |
-} // namespace debug |
- |