1*053eb356SAaron Smith //===-- ProcessDebugger.cpp -------------------------------------*- C++ -*-===// 2*053eb356SAaron Smith // 3*053eb356SAaron Smith // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*053eb356SAaron Smith // See https://llvm.org/LICENSE.txt for license information. 5*053eb356SAaron Smith // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*053eb356SAaron Smith // 7*053eb356SAaron Smith //===----------------------------------------------------------------------===// 8*053eb356SAaron Smith 9*053eb356SAaron Smith #include "ProcessDebugger.h" 10*053eb356SAaron Smith 11*053eb356SAaron Smith // Windows includes 12*053eb356SAaron Smith #include "lldb/Host/windows/windows.h" 13*053eb356SAaron Smith #include <psapi.h> 14*053eb356SAaron Smith 15*053eb356SAaron Smith #include "lldb/Host/FileSystem.h" 16*053eb356SAaron Smith #include "lldb/Host/HostNativeProcessBase.h" 17*053eb356SAaron Smith #include "lldb/Host/HostProcess.h" 18*053eb356SAaron Smith #include "lldb/Host/HostThread.h" 19*053eb356SAaron Smith #include "lldb/Host/ProcessLaunchInfo.h" 20*053eb356SAaron Smith #include "lldb/Target/MemoryRegionInfo.h" 21*053eb356SAaron Smith #include "lldb/Target/Process.h" 22*053eb356SAaron Smith #include "llvm/Support/ConvertUTF.h" 23*053eb356SAaron Smith #include "llvm/Support/Error.h" 24*053eb356SAaron Smith 25*053eb356SAaron Smith #include "DebuggerThread.h" 26*053eb356SAaron Smith #include "ExceptionRecord.h" 27*053eb356SAaron Smith #include "ProcessWindowsLog.h" 28*053eb356SAaron Smith 29*053eb356SAaron Smith using namespace lldb; 30*053eb356SAaron Smith using namespace lldb_private; 31*053eb356SAaron Smith 32*053eb356SAaron Smith static DWORD ConvertLldbToWinApiProtect(uint32_t protect) { 33*053eb356SAaron Smith // We also can process a read / write permissions here, but if the debugger 34*053eb356SAaron Smith // will make later a write into the allocated memory, it will fail. To get 35*053eb356SAaron Smith // around it is possible inside DoWriteMemory to remember memory permissions, 36*053eb356SAaron Smith // allow write, write and restore permissions, but for now we process only 37*053eb356SAaron Smith // the executable permission. 38*053eb356SAaron Smith // 39*053eb356SAaron Smith // TODO: Process permissions other than executable 40*053eb356SAaron Smith if (protect & ePermissionsExecutable) 41*053eb356SAaron Smith return PAGE_EXECUTE_READWRITE; 42*053eb356SAaron Smith 43*053eb356SAaron Smith return PAGE_READWRITE; 44*053eb356SAaron Smith } 45*053eb356SAaron Smith 46*053eb356SAaron Smith // The Windows page protection bits are NOT independent masks that can be 47*053eb356SAaron Smith // bitwise-ORed together. For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE 48*053eb356SAaron Smith // | PAGE_READ). To test for an access type, it's necessary to test for any of 49*053eb356SAaron Smith // the bits that provide that access type. 50*053eb356SAaron Smith static bool IsPageReadable(uint32_t protect) { 51*053eb356SAaron Smith return (protect & PAGE_NOACCESS) == 0; 52*053eb356SAaron Smith } 53*053eb356SAaron Smith 54*053eb356SAaron Smith static bool IsPageWritable(uint32_t protect) { 55*053eb356SAaron Smith return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | 56*053eb356SAaron Smith PAGE_READWRITE | PAGE_WRITECOPY)) != 0; 57*053eb356SAaron Smith } 58*053eb356SAaron Smith 59*053eb356SAaron Smith static bool IsPageExecutable(uint32_t protect) { 60*053eb356SAaron Smith return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | 61*053eb356SAaron Smith PAGE_EXECUTE_WRITECOPY)) != 0; 62*053eb356SAaron Smith } 63*053eb356SAaron Smith 64*053eb356SAaron Smith namespace lldb_private { 65*053eb356SAaron Smith 66*053eb356SAaron Smith lldb::pid_t ProcessDebugger::GetDebuggedProcessId() const { 67*053eb356SAaron Smith if (m_session_data) 68*053eb356SAaron Smith return m_session_data->m_debugger->GetProcess().GetProcessId(); 69*053eb356SAaron Smith return LLDB_INVALID_PROCESS_ID; 70*053eb356SAaron Smith } 71*053eb356SAaron Smith 72*053eb356SAaron Smith Status ProcessDebugger::DetachProcess() { 73*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 74*053eb356SAaron Smith DebuggerThreadSP debugger_thread; 75*053eb356SAaron Smith { 76*053eb356SAaron Smith // Acquire the lock only long enough to get the DebuggerThread. 77*053eb356SAaron Smith // StopDebugging() will trigger a call back into ProcessDebugger which will 78*053eb356SAaron Smith // also acquire the lock. Thus we have to release the lock before calling 79*053eb356SAaron Smith // StopDebugging(). 80*053eb356SAaron Smith llvm::sys::ScopedLock lock(m_mutex); 81*053eb356SAaron Smith 82*053eb356SAaron Smith if (!m_session_data) { 83*053eb356SAaron Smith LLDB_LOG(log, "there is no active session."); 84*053eb356SAaron Smith return Status(); 85*053eb356SAaron Smith } 86*053eb356SAaron Smith 87*053eb356SAaron Smith debugger_thread = m_session_data->m_debugger; 88*053eb356SAaron Smith } 89*053eb356SAaron Smith 90*053eb356SAaron Smith Status error; 91*053eb356SAaron Smith 92*053eb356SAaron Smith LLDB_LOG(log, "detaching from process {0}.", 93*053eb356SAaron Smith debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle()); 94*053eb356SAaron Smith error = debugger_thread->StopDebugging(false); 95*053eb356SAaron Smith 96*053eb356SAaron Smith // By the time StopDebugging returns, there is no more debugger thread, so 97*053eb356SAaron Smith // we can be assured that no other thread will race for the session data. 98*053eb356SAaron Smith m_session_data.reset(); 99*053eb356SAaron Smith 100*053eb356SAaron Smith return error; 101*053eb356SAaron Smith } 102*053eb356SAaron Smith 103*053eb356SAaron Smith Status ProcessDebugger::LaunchProcess(ProcessLaunchInfo &launch_info, 104*053eb356SAaron Smith DebugDelegateSP delegate) { 105*053eb356SAaron Smith // Even though m_session_data is accessed here, it is before a debugger 106*053eb356SAaron Smith // thread has been kicked off. So there's no race conditions, and it 107*053eb356SAaron Smith // shouldn't be necessary to acquire the mutex. 108*053eb356SAaron Smith 109*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 110*053eb356SAaron Smith Status result; 111*053eb356SAaron Smith 112*053eb356SAaron Smith FileSpec working_dir = launch_info.GetWorkingDirectory(); 113*053eb356SAaron Smith namespace fs = llvm::sys::fs; 114*053eb356SAaron Smith if (working_dir) { 115*053eb356SAaron Smith FileSystem::Instance().Resolve(working_dir); 116*053eb356SAaron Smith if (!FileSystem::Instance().IsDirectory(working_dir)) { 117*053eb356SAaron Smith result.SetErrorStringWithFormat("No such file or directory: %s", 118*053eb356SAaron Smith working_dir.GetCString()); 119*053eb356SAaron Smith return result; 120*053eb356SAaron Smith } 121*053eb356SAaron Smith } 122*053eb356SAaron Smith 123*053eb356SAaron Smith if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) { 124*053eb356SAaron Smith StreamString stream; 125*053eb356SAaron Smith stream.Printf("ProcessDebugger unable to launch '%s'. ProcessDebugger can " 126*053eb356SAaron Smith "only be used for debug launches.", 127*053eb356SAaron Smith launch_info.GetExecutableFile().GetPath().c_str()); 128*053eb356SAaron Smith std::string message = stream.GetString(); 129*053eb356SAaron Smith result.SetErrorString(message.c_str()); 130*053eb356SAaron Smith 131*053eb356SAaron Smith LLDB_LOG(log, "error: {0}", message); 132*053eb356SAaron Smith return result; 133*053eb356SAaron Smith } 134*053eb356SAaron Smith 135*053eb356SAaron Smith bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry); 136*053eb356SAaron Smith m_session_data.reset(new ProcessWindowsData(stop_at_entry)); 137*053eb356SAaron Smith m_session_data->m_debugger.reset(new DebuggerThread(delegate)); 138*053eb356SAaron Smith DebuggerThreadSP debugger = m_session_data->m_debugger; 139*053eb356SAaron Smith 140*053eb356SAaron Smith // Kick off the DebugLaunch asynchronously and wait for it to complete. 141*053eb356SAaron Smith result = debugger->DebugLaunch(launch_info); 142*053eb356SAaron Smith if (result.Fail()) { 143*053eb356SAaron Smith LLDB_LOG(log, "failed launching '{0}'. {1}", 144*053eb356SAaron Smith launch_info.GetExecutableFile().GetPath(), result); 145*053eb356SAaron Smith return result; 146*053eb356SAaron Smith } 147*053eb356SAaron Smith 148*053eb356SAaron Smith HostProcess process; 149*053eb356SAaron Smith Status error = WaitForDebuggerConnection(debugger, process); 150*053eb356SAaron Smith if (error.Fail()) { 151*053eb356SAaron Smith LLDB_LOG(log, "failed launching '{0}'. {1}", 152*053eb356SAaron Smith launch_info.GetExecutableFile().GetPath(), error); 153*053eb356SAaron Smith return error; 154*053eb356SAaron Smith } 155*053eb356SAaron Smith 156*053eb356SAaron Smith LLDB_LOG(log, "successfully launched '{0}'", 157*053eb356SAaron Smith launch_info.GetExecutableFile().GetPath()); 158*053eb356SAaron Smith 159*053eb356SAaron Smith // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the 160*053eb356SAaron Smith // private state should already be set to eStateStopped as a result of 161*053eb356SAaron Smith // hitting the initial breakpoint. If it was not set, the breakpoint should 162*053eb356SAaron Smith // have already been resumed from and the private state should already be 163*053eb356SAaron Smith // eStateRunning. 164*053eb356SAaron Smith launch_info.SetProcessID(process.GetProcessId()); 165*053eb356SAaron Smith 166*053eb356SAaron Smith return result; 167*053eb356SAaron Smith } 168*053eb356SAaron Smith 169*053eb356SAaron Smith Status ProcessDebugger::AttachProcess(lldb::pid_t pid, 170*053eb356SAaron Smith const ProcessAttachInfo &attach_info, 171*053eb356SAaron Smith DebugDelegateSP delegate) { 172*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 173*053eb356SAaron Smith m_session_data.reset( 174*053eb356SAaron Smith new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); 175*053eb356SAaron Smith DebuggerThreadSP debugger(new DebuggerThread(delegate)); 176*053eb356SAaron Smith 177*053eb356SAaron Smith m_session_data->m_debugger = debugger; 178*053eb356SAaron Smith 179*053eb356SAaron Smith DWORD process_id = static_cast<DWORD>(pid); 180*053eb356SAaron Smith Status error = debugger->DebugAttach(process_id, attach_info); 181*053eb356SAaron Smith if (error.Fail()) { 182*053eb356SAaron Smith LLDB_LOG( 183*053eb356SAaron Smith log, 184*053eb356SAaron Smith "encountered an error occurred initiating the asynchronous attach. {0}", 185*053eb356SAaron Smith error); 186*053eb356SAaron Smith return error; 187*053eb356SAaron Smith } 188*053eb356SAaron Smith 189*053eb356SAaron Smith HostProcess process; 190*053eb356SAaron Smith error = WaitForDebuggerConnection(debugger, process); 191*053eb356SAaron Smith if (error.Fail()) { 192*053eb356SAaron Smith LLDB_LOG(log, 193*053eb356SAaron Smith "encountered an error waiting for the debugger to connect. {0}", 194*053eb356SAaron Smith error); 195*053eb356SAaron Smith return error; 196*053eb356SAaron Smith } 197*053eb356SAaron Smith 198*053eb356SAaron Smith LLDB_LOG(log, "successfully attached to process with pid={0}", process_id); 199*053eb356SAaron Smith 200*053eb356SAaron Smith // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the 201*053eb356SAaron Smith // private state should already be set to eStateStopped as a result of 202*053eb356SAaron Smith // hitting the initial breakpoint. If it was not set, the breakpoint should 203*053eb356SAaron Smith // have already been resumed from and the private state should already be 204*053eb356SAaron Smith // eStateRunning. 205*053eb356SAaron Smith 206*053eb356SAaron Smith return error; 207*053eb356SAaron Smith } 208*053eb356SAaron Smith 209*053eb356SAaron Smith Status ProcessDebugger::DestroyProcess(const lldb::StateType state) { 210*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 211*053eb356SAaron Smith DebuggerThreadSP debugger_thread; 212*053eb356SAaron Smith { 213*053eb356SAaron Smith // Acquire this lock inside an inner scope, only long enough to get the 214*053eb356SAaron Smith // DebuggerThread. StopDebugging() will trigger a call back into 215*053eb356SAaron Smith // ProcessDebugger which will acquire the lock again, so we need to not 216*053eb356SAaron Smith // deadlock. 217*053eb356SAaron Smith llvm::sys::ScopedLock lock(m_mutex); 218*053eb356SAaron Smith 219*053eb356SAaron Smith if (!m_session_data) { 220*053eb356SAaron Smith LLDB_LOG(log, "warning: state = {0}, but there is no active session.", 221*053eb356SAaron Smith state); 222*053eb356SAaron Smith return Status(); 223*053eb356SAaron Smith } 224*053eb356SAaron Smith 225*053eb356SAaron Smith debugger_thread = m_session_data->m_debugger; 226*053eb356SAaron Smith } 227*053eb356SAaron Smith 228*053eb356SAaron Smith Status error; 229*053eb356SAaron Smith if (state != eStateExited && state != eStateDetached) { 230*053eb356SAaron Smith LLDB_LOG( 231*053eb356SAaron Smith log, "Shutting down process {0}.", 232*053eb356SAaron Smith debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle()); 233*053eb356SAaron Smith error = debugger_thread->StopDebugging(true); 234*053eb356SAaron Smith 235*053eb356SAaron Smith // By the time StopDebugging returns, there is no more debugger thread, so 236*053eb356SAaron Smith // we can be assured that no other thread will race for the session data. 237*053eb356SAaron Smith m_session_data.reset(); 238*053eb356SAaron Smith } else { 239*053eb356SAaron Smith error.SetErrorStringWithFormat("cannot destroy process %" PRIx64 240*053eb356SAaron Smith " while state = %d", 241*053eb356SAaron Smith GetDebuggedProcessId(), state); 242*053eb356SAaron Smith LLDB_LOG(log, "error: {0}", error); 243*053eb356SAaron Smith } 244*053eb356SAaron Smith return error; 245*053eb356SAaron Smith } 246*053eb356SAaron Smith 247*053eb356SAaron Smith Status ProcessDebugger::HaltProcess(bool &caused_stop) { 248*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 249*053eb356SAaron Smith Status error; 250*053eb356SAaron Smith llvm::sys::ScopedLock lock(m_mutex); 251*053eb356SAaron Smith caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess() 252*053eb356SAaron Smith .GetNativeProcess() 253*053eb356SAaron Smith .GetSystemHandle()); 254*053eb356SAaron Smith if (!caused_stop) { 255*053eb356SAaron Smith error.SetError(::GetLastError(), eErrorTypeWin32); 256*053eb356SAaron Smith LLDB_LOG(log, "DebugBreakProcess failed with error {0}", error); 257*053eb356SAaron Smith } 258*053eb356SAaron Smith 259*053eb356SAaron Smith return error; 260*053eb356SAaron Smith } 261*053eb356SAaron Smith 262*053eb356SAaron Smith Status ProcessDebugger::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, 263*053eb356SAaron Smith size_t &bytes_read) { 264*053eb356SAaron Smith Status error; 265*053eb356SAaron Smith bytes_read = 0; 266*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); 267*053eb356SAaron Smith llvm::sys::ScopedLock lock(m_mutex); 268*053eb356SAaron Smith 269*053eb356SAaron Smith if (!m_session_data) { 270*053eb356SAaron Smith error.SetErrorString( 271*053eb356SAaron Smith "cannot read, there is no active debugger connection."); 272*053eb356SAaron Smith LLDB_LOG(log, "error: {0}", error); 273*053eb356SAaron Smith return error; 274*053eb356SAaron Smith } 275*053eb356SAaron Smith 276*053eb356SAaron Smith LLDB_LOG(log, "attempting to read {0} bytes from address {1:x}", size, 277*053eb356SAaron Smith vm_addr); 278*053eb356SAaron Smith 279*053eb356SAaron Smith HostProcess process = m_session_data->m_debugger->GetProcess(); 280*053eb356SAaron Smith void *addr = reinterpret_cast<void *>(vm_addr); 281*053eb356SAaron Smith SIZE_T num_of_bytes_read = 0; 282*053eb356SAaron Smith if (!::ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr, 283*053eb356SAaron Smith buf, size, &num_of_bytes_read)) { 284*053eb356SAaron Smith // Reading from the process can fail for a number of reasons - set the 285*053eb356SAaron Smith // error code and make sure that the number of bytes read is set back to 0 286*053eb356SAaron Smith // because in some scenarios the value of bytes_read returned from the API 287*053eb356SAaron Smith // is garbage. 288*053eb356SAaron Smith error.SetError(GetLastError(), eErrorTypeWin32); 289*053eb356SAaron Smith LLDB_LOG(log, "reading failed with error: {0}", error); 290*053eb356SAaron Smith } else { 291*053eb356SAaron Smith bytes_read = num_of_bytes_read; 292*053eb356SAaron Smith } 293*053eb356SAaron Smith return error; 294*053eb356SAaron Smith } 295*053eb356SAaron Smith 296*053eb356SAaron Smith Status ProcessDebugger::WriteMemory(lldb::addr_t vm_addr, const void *buf, 297*053eb356SAaron Smith size_t size, size_t &bytes_written) { 298*053eb356SAaron Smith Status error; 299*053eb356SAaron Smith bytes_written = 0; 300*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); 301*053eb356SAaron Smith llvm::sys::ScopedLock lock(m_mutex); 302*053eb356SAaron Smith LLDB_LOG(log, "attempting to write {0} bytes into address {1:x}", size, 303*053eb356SAaron Smith vm_addr); 304*053eb356SAaron Smith 305*053eb356SAaron Smith if (!m_session_data) { 306*053eb356SAaron Smith error.SetErrorString( 307*053eb356SAaron Smith "cannot write, there is no active debugger connection."); 308*053eb356SAaron Smith LLDB_LOG(log, "error: {0}", error); 309*053eb356SAaron Smith return error; 310*053eb356SAaron Smith } 311*053eb356SAaron Smith 312*053eb356SAaron Smith HostProcess process = m_session_data->m_debugger->GetProcess(); 313*053eb356SAaron Smith void *addr = reinterpret_cast<void *>(vm_addr); 314*053eb356SAaron Smith SIZE_T num_of_bytes_written = 0; 315*053eb356SAaron Smith lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); 316*053eb356SAaron Smith if (::WriteProcessMemory(handle, addr, buf, size, &num_of_bytes_written)) { 317*053eb356SAaron Smith FlushInstructionCache(handle, addr, num_of_bytes_written); 318*053eb356SAaron Smith bytes_written = num_of_bytes_written; 319*053eb356SAaron Smith } else { 320*053eb356SAaron Smith error.SetError(GetLastError(), eErrorTypeWin32); 321*053eb356SAaron Smith LLDB_LOG(log, "writing failed with error: {0}", error); 322*053eb356SAaron Smith } 323*053eb356SAaron Smith return error; 324*053eb356SAaron Smith } 325*053eb356SAaron Smith 326*053eb356SAaron Smith Status ProcessDebugger::AllocateMemory(size_t size, uint32_t permissions, 327*053eb356SAaron Smith lldb::addr_t &addr) { 328*053eb356SAaron Smith Status error; 329*053eb356SAaron Smith addr = LLDB_INVALID_ADDRESS; 330*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); 331*053eb356SAaron Smith llvm::sys::ScopedLock lock(m_mutex); 332*053eb356SAaron Smith LLDB_LOG(log, "attempting to allocate {0} bytes with permissions {1}", size, 333*053eb356SAaron Smith permissions); 334*053eb356SAaron Smith 335*053eb356SAaron Smith if (!m_session_data) { 336*053eb356SAaron Smith error.SetErrorString( 337*053eb356SAaron Smith "cannot allocate, there is no active debugger connection"); 338*053eb356SAaron Smith LLDB_LOG(log, "error: {0}", error); 339*053eb356SAaron Smith return error; 340*053eb356SAaron Smith } 341*053eb356SAaron Smith 342*053eb356SAaron Smith HostProcess process = m_session_data->m_debugger->GetProcess(); 343*053eb356SAaron Smith lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); 344*053eb356SAaron Smith auto protect = ConvertLldbToWinApiProtect(permissions); 345*053eb356SAaron Smith auto result = ::VirtualAllocEx(handle, nullptr, size, MEM_COMMIT, protect); 346*053eb356SAaron Smith if (!result) { 347*053eb356SAaron Smith error.SetError(GetLastError(), eErrorTypeWin32); 348*053eb356SAaron Smith LLDB_LOG(log, "allocating failed with error: {0}", error); 349*053eb356SAaron Smith } else { 350*053eb356SAaron Smith addr = reinterpret_cast<addr_t>(result); 351*053eb356SAaron Smith } 352*053eb356SAaron Smith return error; 353*053eb356SAaron Smith } 354*053eb356SAaron Smith 355*053eb356SAaron Smith Status ProcessDebugger::DeallocateMemory(lldb::addr_t vm_addr) { 356*053eb356SAaron Smith Status result; 357*053eb356SAaron Smith 358*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); 359*053eb356SAaron Smith llvm::sys::ScopedLock lock(m_mutex); 360*053eb356SAaron Smith LLDB_LOG(log, "attempting to deallocate bytes at address {0}", vm_addr); 361*053eb356SAaron Smith 362*053eb356SAaron Smith if (!m_session_data) { 363*053eb356SAaron Smith result.SetErrorString( 364*053eb356SAaron Smith "cannot deallocate, there is no active debugger connection"); 365*053eb356SAaron Smith LLDB_LOG(log, "error: {0}", result); 366*053eb356SAaron Smith return result; 367*053eb356SAaron Smith } 368*053eb356SAaron Smith 369*053eb356SAaron Smith HostProcess process = m_session_data->m_debugger->GetProcess(); 370*053eb356SAaron Smith lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); 371*053eb356SAaron Smith if (!::VirtualFreeEx(handle, reinterpret_cast<LPVOID>(vm_addr), 0, 372*053eb356SAaron Smith MEM_RELEASE)) { 373*053eb356SAaron Smith result.SetError(GetLastError(), eErrorTypeWin32); 374*053eb356SAaron Smith LLDB_LOG(log, "deallocating failed with error: {0}", result); 375*053eb356SAaron Smith } 376*053eb356SAaron Smith 377*053eb356SAaron Smith return result; 378*053eb356SAaron Smith } 379*053eb356SAaron Smith 380*053eb356SAaron Smith Status ProcessDebugger::GetMemoryRegionInfo(lldb::addr_t vm_addr, 381*053eb356SAaron Smith MemoryRegionInfo &info) { 382*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); 383*053eb356SAaron Smith Status error; 384*053eb356SAaron Smith llvm::sys::ScopedLock lock(m_mutex); 385*053eb356SAaron Smith info.Clear(); 386*053eb356SAaron Smith 387*053eb356SAaron Smith if (!m_session_data) { 388*053eb356SAaron Smith error.SetErrorString( 389*053eb356SAaron Smith "GetMemoryRegionInfo called with no debugging session."); 390*053eb356SAaron Smith LLDB_LOG(log, "error: {0}", error); 391*053eb356SAaron Smith return error; 392*053eb356SAaron Smith } 393*053eb356SAaron Smith HostProcess process = m_session_data->m_debugger->GetProcess(); 394*053eb356SAaron Smith lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); 395*053eb356SAaron Smith if (handle == nullptr || handle == LLDB_INVALID_PROCESS) { 396*053eb356SAaron Smith error.SetErrorString( 397*053eb356SAaron Smith "GetMemoryRegionInfo called with an invalid target process."); 398*053eb356SAaron Smith LLDB_LOG(log, "error: {0}", error); 399*053eb356SAaron Smith return error; 400*053eb356SAaron Smith } 401*053eb356SAaron Smith 402*053eb356SAaron Smith LLDB_LOG(log, "getting info for address {0:x}", vm_addr); 403*053eb356SAaron Smith 404*053eb356SAaron Smith void *addr = reinterpret_cast<void *>(vm_addr); 405*053eb356SAaron Smith MEMORY_BASIC_INFORMATION mem_info = {}; 406*053eb356SAaron Smith SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); 407*053eb356SAaron Smith if (result == 0) { 408*053eb356SAaron Smith if (::GetLastError() == ERROR_INVALID_PARAMETER) { 409*053eb356SAaron Smith // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with 410*053eb356SAaron Smith // an address past the highest accessible address. We should return a 411*053eb356SAaron Smith // range from the vm_addr to LLDB_INVALID_ADDRESS 412*053eb356SAaron Smith info.GetRange().SetRangeBase(vm_addr); 413*053eb356SAaron Smith info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); 414*053eb356SAaron Smith info.SetReadable(MemoryRegionInfo::eNo); 415*053eb356SAaron Smith info.SetExecutable(MemoryRegionInfo::eNo); 416*053eb356SAaron Smith info.SetWritable(MemoryRegionInfo::eNo); 417*053eb356SAaron Smith info.SetMapped(MemoryRegionInfo::eNo); 418*053eb356SAaron Smith return error; 419*053eb356SAaron Smith } else { 420*053eb356SAaron Smith error.SetError(::GetLastError(), eErrorTypeWin32); 421*053eb356SAaron Smith LLDB_LOG(log, 422*053eb356SAaron Smith "VirtualQueryEx returned error {0} while getting memory " 423*053eb356SAaron Smith "region info for address {1:x}", 424*053eb356SAaron Smith error, vm_addr); 425*053eb356SAaron Smith return error; 426*053eb356SAaron Smith } 427*053eb356SAaron Smith } 428*053eb356SAaron Smith 429*053eb356SAaron Smith // Protect bits are only valid for MEM_COMMIT regions. 430*053eb356SAaron Smith if (mem_info.State == MEM_COMMIT) { 431*053eb356SAaron Smith const bool readable = IsPageReadable(mem_info.Protect); 432*053eb356SAaron Smith const bool executable = IsPageExecutable(mem_info.Protect); 433*053eb356SAaron Smith const bool writable = IsPageWritable(mem_info.Protect); 434*053eb356SAaron Smith info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); 435*053eb356SAaron Smith info.SetExecutable(executable ? MemoryRegionInfo::eYes 436*053eb356SAaron Smith : MemoryRegionInfo::eNo); 437*053eb356SAaron Smith info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); 438*053eb356SAaron Smith } else { 439*053eb356SAaron Smith info.SetReadable(MemoryRegionInfo::eNo); 440*053eb356SAaron Smith info.SetExecutable(MemoryRegionInfo::eNo); 441*053eb356SAaron Smith info.SetWritable(MemoryRegionInfo::eNo); 442*053eb356SAaron Smith } 443*053eb356SAaron Smith 444*053eb356SAaron Smith // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE. 445*053eb356SAaron Smith if (mem_info.State != MEM_FREE) { 446*053eb356SAaron Smith info.GetRange().SetRangeBase( 447*053eb356SAaron Smith reinterpret_cast<addr_t>(mem_info.AllocationBase)); 448*053eb356SAaron Smith info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) + 449*053eb356SAaron Smith mem_info.RegionSize); 450*053eb356SAaron Smith info.SetMapped(MemoryRegionInfo::eYes); 451*053eb356SAaron Smith } else { 452*053eb356SAaron Smith // In the unmapped case we need to return the distance to the next block of 453*053eb356SAaron Smith // memory. VirtualQueryEx nearly does that except that it gives the 454*053eb356SAaron Smith // distance from the start of the page containing vm_addr. 455*053eb356SAaron Smith SYSTEM_INFO data; 456*053eb356SAaron Smith ::GetSystemInfo(&data); 457*053eb356SAaron Smith DWORD page_offset = vm_addr % data.dwPageSize; 458*053eb356SAaron Smith info.GetRange().SetRangeBase(vm_addr); 459*053eb356SAaron Smith info.GetRange().SetByteSize(mem_info.RegionSize - page_offset); 460*053eb356SAaron Smith info.SetMapped(MemoryRegionInfo::eNo); 461*053eb356SAaron Smith } 462*053eb356SAaron Smith 463*053eb356SAaron Smith error.SetError(::GetLastError(), eErrorTypeWin32); 464*053eb356SAaron Smith LLDB_LOGV(log, 465*053eb356SAaron Smith "Memory region info for address {0}: readable={1}, " 466*053eb356SAaron Smith "executable={2}, writable={3}", 467*053eb356SAaron Smith vm_addr, info.GetReadable(), info.GetExecutable(), 468*053eb356SAaron Smith info.GetWritable()); 469*053eb356SAaron Smith return error; 470*053eb356SAaron Smith } 471*053eb356SAaron Smith 472*053eb356SAaron Smith void ProcessDebugger::OnExitProcess(uint32_t exit_code) { 473*053eb356SAaron Smith // If the process exits before any initial stop then notify the debugger 474*053eb356SAaron Smith // of the error otherwise WaitForDebuggerConnection() will be blocked. 475*053eb356SAaron Smith // An example of this issue is when a process fails to load a dependent DLL. 476*053eb356SAaron Smith if (m_session_data && !m_session_data->m_initial_stop_received) { 477*053eb356SAaron Smith Status error(exit_code, eErrorTypeWin32); 478*053eb356SAaron Smith OnDebuggerError(error, 0); 479*053eb356SAaron Smith } 480*053eb356SAaron Smith } 481*053eb356SAaron Smith 482*053eb356SAaron Smith void ProcessDebugger::OnDebuggerConnected(lldb::addr_t image_base) {} 483*053eb356SAaron Smith 484*053eb356SAaron Smith ExceptionResult 485*053eb356SAaron Smith ProcessDebugger::OnDebugException(bool first_chance, 486*053eb356SAaron Smith const ExceptionRecord &record) { 487*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION); 488*053eb356SAaron Smith llvm::sys::ScopedLock lock(m_mutex); 489*053eb356SAaron Smith // FIXME: Without this check, occasionally when running the test suite 490*053eb356SAaron Smith // there is an issue where m_session_data can be null. It's not clear how 491*053eb356SAaron Smith // this could happen but it only surfaces while running the test suite. In 492*053eb356SAaron Smith // order to properly diagnose this, we probably need to first figure allow the 493*053eb356SAaron Smith // test suite to print out full lldb logs, and then add logging to the process 494*053eb356SAaron Smith // plugin. 495*053eb356SAaron Smith if (!m_session_data) { 496*053eb356SAaron Smith LLDB_LOG(log, 497*053eb356SAaron Smith "Debugger thread reported exception {0:x} at address {1:x}, but " 498*053eb356SAaron Smith "there is no session.", 499*053eb356SAaron Smith record.GetExceptionCode(), record.GetExceptionAddress()); 500*053eb356SAaron Smith return ExceptionResult::SendToApplication; 501*053eb356SAaron Smith } 502*053eb356SAaron Smith 503*053eb356SAaron Smith ExceptionResult result = ExceptionResult::SendToApplication; 504*053eb356SAaron Smith if ((record.GetExceptionCode() == EXCEPTION_BREAKPOINT || 505*053eb356SAaron Smith record.GetExceptionCode() == 506*053eb356SAaron Smith 0x4000001FL /*WOW64 STATUS_WX86_BREAKPOINT*/) && 507*053eb356SAaron Smith !m_session_data->m_initial_stop_received) { 508*053eb356SAaron Smith // Handle breakpoints at the first chance. 509*053eb356SAaron Smith result = ExceptionResult::BreakInDebugger; 510*053eb356SAaron Smith LLDB_LOG( 511*053eb356SAaron Smith log, 512*053eb356SAaron Smith "Hit loader breakpoint at address {0:x}, setting initial stop event.", 513*053eb356SAaron Smith record.GetExceptionAddress()); 514*053eb356SAaron Smith m_session_data->m_initial_stop_received = true; 515*053eb356SAaron Smith ::SetEvent(m_session_data->m_initial_stop_event); 516*053eb356SAaron Smith } 517*053eb356SAaron Smith return result; 518*053eb356SAaron Smith } 519*053eb356SAaron Smith 520*053eb356SAaron Smith void ProcessDebugger::OnCreateThread(const HostThread &thread) { 521*053eb356SAaron Smith // Do nothing by default 522*053eb356SAaron Smith } 523*053eb356SAaron Smith 524*053eb356SAaron Smith void ProcessDebugger::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) { 525*053eb356SAaron Smith // Do nothing by default 526*053eb356SAaron Smith } 527*053eb356SAaron Smith 528*053eb356SAaron Smith void ProcessDebugger::OnLoadDll(const ModuleSpec &module_spec, 529*053eb356SAaron Smith lldb::addr_t module_addr) { 530*053eb356SAaron Smith // Do nothing by default 531*053eb356SAaron Smith } 532*053eb356SAaron Smith 533*053eb356SAaron Smith void ProcessDebugger::OnUnloadDll(lldb::addr_t module_addr) { 534*053eb356SAaron Smith // Do nothing by default 535*053eb356SAaron Smith } 536*053eb356SAaron Smith 537*053eb356SAaron Smith void ProcessDebugger::OnDebugString(const std::string &string) {} 538*053eb356SAaron Smith 539*053eb356SAaron Smith void ProcessDebugger::OnDebuggerError(const Status &error, uint32_t type) { 540*053eb356SAaron Smith llvm::sys::ScopedLock lock(m_mutex); 541*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 542*053eb356SAaron Smith 543*053eb356SAaron Smith if (m_session_data->m_initial_stop_received) { 544*053eb356SAaron Smith // This happened while debugging. Do we shutdown the debugging session, 545*053eb356SAaron Smith // try to continue, or do something else? 546*053eb356SAaron Smith LLDB_LOG(log, 547*053eb356SAaron Smith "Error {0} occurred during debugging. Unexpected behavior " 548*053eb356SAaron Smith "may result. {1}", 549*053eb356SAaron Smith error.GetError(), error); 550*053eb356SAaron Smith } else { 551*053eb356SAaron Smith // If we haven't actually launched the process yet, this was an error 552*053eb356SAaron Smith // launching the process. Set the internal error and signal the initial 553*053eb356SAaron Smith // stop event so that the DoLaunch method wakes up and returns a failure. 554*053eb356SAaron Smith m_session_data->m_launch_error = error; 555*053eb356SAaron Smith ::SetEvent(m_session_data->m_initial_stop_event); 556*053eb356SAaron Smith LLDB_LOG(log, 557*053eb356SAaron Smith "Error {0} occurred launching the process before the initial " 558*053eb356SAaron Smith "stop. {1}", 559*053eb356SAaron Smith error.GetError(), error); 560*053eb356SAaron Smith return; 561*053eb356SAaron Smith } 562*053eb356SAaron Smith } 563*053eb356SAaron Smith 564*053eb356SAaron Smith Status ProcessDebugger::WaitForDebuggerConnection(DebuggerThreadSP debugger, 565*053eb356SAaron Smith HostProcess &process) { 566*053eb356SAaron Smith Status result; 567*053eb356SAaron Smith Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS | 568*053eb356SAaron Smith WINDOWS_LOG_BREAKPOINTS); 569*053eb356SAaron Smith LLDB_LOG(log, "Waiting for loader breakpoint."); 570*053eb356SAaron Smith 571*053eb356SAaron Smith // Block this function until we receive the initial stop from the process. 572*053eb356SAaron Smith if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == 573*053eb356SAaron Smith WAIT_OBJECT_0) { 574*053eb356SAaron Smith LLDB_LOG(log, "hit loader breakpoint, returning."); 575*053eb356SAaron Smith 576*053eb356SAaron Smith process = debugger->GetProcess(); 577*053eb356SAaron Smith return m_session_data->m_launch_error; 578*053eb356SAaron Smith } else 579*053eb356SAaron Smith return Status(::GetLastError(), eErrorTypeWin32); 580*053eb356SAaron Smith } 581*053eb356SAaron Smith 582*053eb356SAaron Smith } // namespace lldb_private 583