22 #include "llvm/Support/ConvertUTF.h"
23 #include "llvm/Support/Error.h"
40 if (protect & ePermissionsExecutable)
41 return PAGE_EXECUTE_READWRITE;
43 return PAGE_READWRITE;
51 return (protect & PAGE_NOACCESS) == 0;
55 return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY |
56 PAGE_READWRITE | PAGE_WRITECOPY)) != 0;
60 return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
61 PAGE_EXECUTE_WRITECOPY)) != 0;
66 ProcessDebugger::~ProcessDebugger() {}
70 return m_session_data->m_debugger->GetProcess().GetProcessId();
74 Status ProcessDebugger::DetachProcess() {
82 llvm::sys::ScopedLock lock(m_mutex);
84 if (!m_session_data) {
85 LLDB_LOG(log,
"there is no active session.");
89 debugger_thread = m_session_data->m_debugger;
94 LLDB_LOG(log,
"detaching from process {0}.",
95 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
96 error = debugger_thread->StopDebugging(
false);
100 m_session_data.reset();
115 namespace fs = llvm::sys::fs;
117 FileSystem::Instance().Resolve(working_dir);
118 if (!FileSystem::Instance().IsDirectory(working_dir)) {
127 stream.
Printf(
"ProcessDebugger unable to launch '%s'. ProcessDebugger can "
128 "only be used for debug launches.",
137 bool stop_at_entry = launch_info.
GetFlags().
Test(eLaunchFlagStopAtEntry);
143 result = debugger->DebugLaunch(launch_info);
145 LLDB_LOG(log,
"failed launching '{0}'. {1}",
151 Status error = WaitForDebuggerConnection(debugger, process);
153 LLDB_LOG(log,
"failed launching '{0}'. {1}",
158 LLDB_LOG(log,
"successfully launched '{0}'",
175 m_session_data.reset(
179 m_session_data->m_debugger = debugger;
181 DWORD process_id =
static_cast<DWORD
>(pid);
182 Status error = debugger->DebugAttach(process_id, attach_info);
186 "encountered an error occurred initiating the asynchronous attach. {0}",
192 error = WaitForDebuggerConnection(debugger, process);
195 "encountered an error waiting for the debugger to connect. {0}",
200 LLDB_LOG(log,
"successfully attached to process with pid={0}", process_id);
219 llvm::sys::ScopedLock lock(m_mutex);
221 if (!m_session_data) {
222 LLDB_LOG(log,
"warning: state = {0}, but there is no active session.",
227 debugger_thread = m_session_data->m_debugger;
231 LLDB_LOG(log,
"warning: cannot destroy process {0} while state = {1}.",
232 GetDebuggedProcessId(), state);
236 LLDB_LOG(log,
"Shutting down process {0}.",
237 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
238 auto error = debugger_thread->StopDebugging(
true);
242 m_session_data.reset();
247 Status ProcessDebugger::HaltProcess(
bool &caused_stop) {
250 llvm::sys::ScopedLock lock(m_mutex);
251 caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess()
256 LLDB_LOG(log,
"DebugBreakProcess failed with error {0}",
error);
263 size_t &bytes_read) {
267 llvm::sys::ScopedLock lock(m_mutex);
269 if (!m_session_data) {
270 error.SetErrorString(
271 "cannot read, there is no active debugger connection.");
276 LLDB_LOG(log,
"attempting to read {0} bytes from address {1:x}", size,
279 HostProcess process = m_session_data->m_debugger->GetProcess();
280 void *addr =
reinterpret_cast<void *
>(vm_addr);
281 SIZE_T num_of_bytes_read = 0;
283 buf, size, &num_of_bytes_read)) {
287 bytes_read = num_of_bytes_read;
293 size_t size,
size_t &bytes_written) {
297 llvm::sys::ScopedLock lock(m_mutex);
298 LLDB_LOG(log,
"attempting to write {0} bytes into address {1:x}", size,
301 if (!m_session_data) {
302 error.SetErrorString(
303 "cannot write, there is no active debugger connection.");
308 HostProcess process = m_session_data->m_debugger->GetProcess();
309 void *addr =
reinterpret_cast<void *
>(vm_addr);
310 SIZE_T num_of_bytes_written = 0;
312 if (::WriteProcessMemory(handle, addr, buf, size, &num_of_bytes_written)) {
313 FlushInstructionCache(handle, addr, num_of_bytes_written);
314 bytes_written = num_of_bytes_written;
327 llvm::sys::ScopedLock lock(m_mutex);
328 LLDB_LOG(log,
"attempting to allocate {0} bytes with permissions {1}", size,
331 if (!m_session_data) {
332 error.SetErrorString(
333 "cannot allocate, there is no active debugger connection");
338 HostProcess process = m_session_data->m_debugger->GetProcess();
341 auto result = ::VirtualAllocEx(handle,
nullptr, size, MEM_COMMIT, protect);
346 addr =
reinterpret_cast<addr_t>(result);
355 llvm::sys::ScopedLock lock(m_mutex);
356 LLDB_LOG(log,
"attempting to deallocate bytes at address {0}", vm_addr);
358 if (!m_session_data) {
360 "cannot deallocate, there is no active debugger connection");
361 LLDB_LOG(log,
"error: {0}", result);
365 HostProcess process = m_session_data->m_debugger->GetProcess();
367 if (!::VirtualFreeEx(handle,
reinterpret_cast<LPVOID
>(vm_addr), 0,
370 LLDB_LOG(log,
"deallocating failed with error: {0}", result);
380 llvm::sys::ScopedLock lock(m_mutex);
383 if (!m_session_data) {
384 error.SetErrorString(
385 "GetMemoryRegionInfo called with no debugging session.");
389 HostProcess process = m_session_data->m_debugger->GetProcess();
392 error.SetErrorString(
393 "GetMemoryRegionInfo called with an invalid target process.");
398 LLDB_LOG(log,
"getting info for address {0:x}", vm_addr);
400 void *addr =
reinterpret_cast<void *
>(vm_addr);
401 MEMORY_BASIC_INFORMATION mem_info = {};
402 SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info,
sizeof(mem_info));
404 DWORD last_error = ::GetLastError();
405 if (last_error == ERROR_INVALID_PARAMETER) {
419 "VirtualQueryEx returned error {0} while getting memory "
420 "region info for address {1:x}",
427 if (mem_info.State == MEM_COMMIT) {
431 info.
SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
433 : MemoryRegionInfo::eNo);
434 info.
SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
442 if (mem_info.State != MEM_FREE) {
444 reinterpret_cast<addr_t>(mem_info.AllocationBase));
446 mem_info.RegionSize);
453 ::GetSystemInfo(&data);
454 DWORD page_offset = vm_addr % data.dwPageSize;
461 "Memory region info for address {0}: readable={1}, "
462 "executable={2}, writable={3}",
468 void ProcessDebugger::OnExitProcess(
uint32_t exit_code) {
472 if (m_session_data && !m_session_data->m_initial_stop_received) {
474 OnDebuggerError(
error, 0);
481 ProcessDebugger::OnDebugException(
bool first_chance,
483 Log *log =
GetLog(WindowsLog::Exception);
484 llvm::sys::ScopedLock lock(m_mutex);
491 if (!m_session_data) {
493 "Debugger thread reported exception {0:x} at address {1:x}, but "
494 "there is no session.",
503 !m_session_data->m_initial_stop_received) {
508 "Hit loader breakpoint at address {0:x}, setting initial stop event.",
510 m_session_data->m_initial_stop_received =
true;
511 ::SetEvent(m_session_data->m_initial_stop_event);
516 void ProcessDebugger::OnCreateThread(
const HostThread &thread) {
524 void ProcessDebugger::OnLoadDll(
const ModuleSpec &module_spec,
536 llvm::sys::ScopedLock lock(m_mutex);
539 if (m_session_data->m_initial_stop_received) {
543 "Error {0} occurred during debugging. Unexpected behavior "
550 m_session_data->m_launch_error =
error;
551 ::SetEvent(m_session_data->m_initial_stop_event);
553 "Error {0} occurred launching the process before the initial "
563 Log *log =
GetLog(WindowsLog::Process | WindowsLog::Breakpoints);
564 LLDB_LOG(log,
"Waiting for loader breakpoint.");
567 if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) ==
569 LLDB_LOG(log,
"hit loader breakpoint, returning.");
571 process = debugger->GetProcess();
572 return m_session_data->m_launch_error;