118a9135dSAdrian McCarthy //===-- ProcessWindows.cpp --------------------------------------*- C++ -*-===// 218a9135dSAdrian McCarthy // 318a9135dSAdrian McCarthy // The LLVM Compiler Infrastructure 418a9135dSAdrian McCarthy // 518a9135dSAdrian McCarthy // This file is distributed under the University of Illinois Open Source 618a9135dSAdrian McCarthy // License. See LICENSE.TXT for details. 718a9135dSAdrian McCarthy // 818a9135dSAdrian McCarthy //===----------------------------------------------------------------------===// 918a9135dSAdrian McCarthy 1018a9135dSAdrian McCarthy #include "ProcessWindows.h" 1118a9135dSAdrian McCarthy 12*4ad5def9SAdrian McCarthy // Windows includes 13*4ad5def9SAdrian McCarthy #include "lldb/Host/windows/windows.h" 14*4ad5def9SAdrian McCarthy #include <psapi.h> 15*4ad5def9SAdrian McCarthy 1618a9135dSAdrian McCarthy // Other libraries and framework includes 1718a9135dSAdrian McCarthy #include "lldb/Core/Module.h" 1818a9135dSAdrian McCarthy #include "lldb/Core/ModuleSpec.h" 1918a9135dSAdrian McCarthy #include "lldb/Core/PluginManager.h" 2018a9135dSAdrian McCarthy #include "lldb/Core/Section.h" 2118a9135dSAdrian McCarthy #include "lldb/Core/State.h" 22*4ad5def9SAdrian McCarthy #include "lldb/Host/HostNativeProcessBase.h" 23*4ad5def9SAdrian McCarthy #include "lldb/Host/HostProcess.h" 24*4ad5def9SAdrian McCarthy #include "lldb/Host/windows/HostThreadWindows.h" 250c35cde9SAdrian McCarthy #include "lldb/Host/windows/windows.h" 2618a9135dSAdrian McCarthy #include "lldb/Target/DynamicLoader.h" 2718a9135dSAdrian McCarthy #include "lldb/Target/MemoryRegionInfo.h" 28*4ad5def9SAdrian McCarthy #include "lldb/Target/StopInfo.h" 2918a9135dSAdrian McCarthy #include "lldb/Target/Target.h" 3018a9135dSAdrian McCarthy 31*4ad5def9SAdrian McCarthy #include "llvm/Support/ConvertUTF.h" 32*4ad5def9SAdrian McCarthy #include "llvm/Support/Format.h" 33*4ad5def9SAdrian McCarthy #include "llvm/Support/raw_ostream.h" 34*4ad5def9SAdrian McCarthy 35*4ad5def9SAdrian McCarthy #include "DebuggerThread.h" 36*4ad5def9SAdrian McCarthy #include "ExceptionRecord.h" 37*4ad5def9SAdrian McCarthy #include "ForwardDecl.h" 38*4ad5def9SAdrian McCarthy #include "LocalDebugDelegate.h" 39*4ad5def9SAdrian McCarthy #include "ProcessWindowsLog.h" 40*4ad5def9SAdrian McCarthy #include "TargetThreadWindows.h" 41*4ad5def9SAdrian McCarthy 4218a9135dSAdrian McCarthy using namespace lldb; 4318a9135dSAdrian McCarthy using namespace lldb_private; 4418a9135dSAdrian McCarthy 45*4ad5def9SAdrian McCarthy namespace { 46*4ad5def9SAdrian McCarthy std::string GetProcessExecutableName(HANDLE process_handle) { 47*4ad5def9SAdrian McCarthy std::vector<wchar_t> file_name; 48*4ad5def9SAdrian McCarthy DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit 49*4ad5def9SAdrian McCarthy DWORD copied = 0; 50*4ad5def9SAdrian McCarthy do { 51*4ad5def9SAdrian McCarthy file_name_size *= 2; 52*4ad5def9SAdrian McCarthy file_name.resize(file_name_size); 53*4ad5def9SAdrian McCarthy copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(), 54*4ad5def9SAdrian McCarthy file_name_size); 55*4ad5def9SAdrian McCarthy } while (copied >= file_name_size); 56*4ad5def9SAdrian McCarthy file_name.resize(copied); 57*4ad5def9SAdrian McCarthy std::string result; 58*4ad5def9SAdrian McCarthy llvm::convertWideToUTF8(file_name.data(), result); 59*4ad5def9SAdrian McCarthy return result; 60*4ad5def9SAdrian McCarthy } 61*4ad5def9SAdrian McCarthy 62*4ad5def9SAdrian McCarthy std::string GetProcessExecutableName(DWORD pid) { 63*4ad5def9SAdrian McCarthy std::string file_name; 64*4ad5def9SAdrian McCarthy HANDLE process_handle = 65*4ad5def9SAdrian McCarthy ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); 66*4ad5def9SAdrian McCarthy if (process_handle != NULL) { 67*4ad5def9SAdrian McCarthy file_name = GetProcessExecutableName(process_handle); 68*4ad5def9SAdrian McCarthy ::CloseHandle(process_handle); 69*4ad5def9SAdrian McCarthy } 70*4ad5def9SAdrian McCarthy return file_name; 71*4ad5def9SAdrian McCarthy } 72*4ad5def9SAdrian McCarthy 73*4ad5def9SAdrian McCarthy } // anonymous namespace 74*4ad5def9SAdrian McCarthy 75b9c1b51eSKate Stone namespace lldb_private { 7618a9135dSAdrian McCarthy 77*4ad5def9SAdrian McCarthy // We store a pointer to this class in the ProcessWindows, so that we don't 78*4ad5def9SAdrian McCarthy // expose Windows-specific types and implementation details from a public header 79*4ad5def9SAdrian McCarthy // file. 80*4ad5def9SAdrian McCarthy class ProcessWindowsData { 81*4ad5def9SAdrian McCarthy public: 82*4ad5def9SAdrian McCarthy ProcessWindowsData(bool stop_at_entry) : m_stop_at_entry(stop_at_entry) { 83*4ad5def9SAdrian McCarthy m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); 84*4ad5def9SAdrian McCarthy } 85*4ad5def9SAdrian McCarthy 86*4ad5def9SAdrian McCarthy ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); } 87*4ad5def9SAdrian McCarthy 88*4ad5def9SAdrian McCarthy Error m_launch_error; 89*4ad5def9SAdrian McCarthy DebuggerThreadSP m_debugger; 90*4ad5def9SAdrian McCarthy StopInfoSP m_pending_stop_info; 91*4ad5def9SAdrian McCarthy HANDLE m_initial_stop_event = nullptr; 92*4ad5def9SAdrian McCarthy bool m_initial_stop_received = false; 93*4ad5def9SAdrian McCarthy bool m_stop_at_entry; 94*4ad5def9SAdrian McCarthy std::map<lldb::tid_t, HostThread> m_new_threads; 95*4ad5def9SAdrian McCarthy std::set<lldb::tid_t> m_exited_threads; 96*4ad5def9SAdrian McCarthy }; 97*4ad5def9SAdrian McCarthy 98*4ad5def9SAdrian McCarthy ProcessSP ProcessWindows::CreateInstance(lldb::TargetSP target_sp, 99*4ad5def9SAdrian McCarthy lldb::ListenerSP listener_sp, 100*4ad5def9SAdrian McCarthy const FileSpec *) { 101*4ad5def9SAdrian McCarthy return ProcessSP(new ProcessWindows(target_sp, listener_sp)); 102*4ad5def9SAdrian McCarthy } 103*4ad5def9SAdrian McCarthy 104*4ad5def9SAdrian McCarthy void ProcessWindows::Initialize() { 105*4ad5def9SAdrian McCarthy static std::once_flag g_once_flag; 106*4ad5def9SAdrian McCarthy 107*4ad5def9SAdrian McCarthy std::call_once(g_once_flag, []() { 108*4ad5def9SAdrian McCarthy PluginManager::RegisterPlugin(GetPluginNameStatic(), 109*4ad5def9SAdrian McCarthy GetPluginDescriptionStatic(), CreateInstance); 110*4ad5def9SAdrian McCarthy }); 111*4ad5def9SAdrian McCarthy } 112*4ad5def9SAdrian McCarthy 113*4ad5def9SAdrian McCarthy void ProcessWindows::Terminate() {} 114*4ad5def9SAdrian McCarthy 115*4ad5def9SAdrian McCarthy lldb_private::ConstString ProcessWindows::GetPluginNameStatic() { 116*4ad5def9SAdrian McCarthy static ConstString g_name("windows"); 117*4ad5def9SAdrian McCarthy return g_name; 118*4ad5def9SAdrian McCarthy } 119*4ad5def9SAdrian McCarthy 120*4ad5def9SAdrian McCarthy const char *ProcessWindows::GetPluginDescriptionStatic() { 121*4ad5def9SAdrian McCarthy return "Process plugin for Windows"; 122*4ad5def9SAdrian McCarthy } 123*4ad5def9SAdrian McCarthy 12418a9135dSAdrian McCarthy //------------------------------------------------------------------------------ 12518a9135dSAdrian McCarthy // Constructors and destructors. 12618a9135dSAdrian McCarthy 127b9c1b51eSKate Stone ProcessWindows::ProcessWindows(lldb::TargetSP target_sp, 128b9c1b51eSKate Stone lldb::ListenerSP listener_sp) 129b9c1b51eSKate Stone : lldb_private::Process(target_sp, listener_sp) {} 13018a9135dSAdrian McCarthy 131b9c1b51eSKate Stone ProcessWindows::~ProcessWindows() {} 13218a9135dSAdrian McCarthy 133b9c1b51eSKate Stone size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Error &error) { 13418a9135dSAdrian McCarthy error.SetErrorString("GetSTDOUT unsupported on Windows"); 13518a9135dSAdrian McCarthy return 0; 13618a9135dSAdrian McCarthy } 13718a9135dSAdrian McCarthy 138b9c1b51eSKate Stone size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Error &error) { 13918a9135dSAdrian McCarthy error.SetErrorString("GetSTDERR unsupported on Windows"); 14018a9135dSAdrian McCarthy return 0; 14118a9135dSAdrian McCarthy } 14218a9135dSAdrian McCarthy 143b9c1b51eSKate Stone size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size, 144b9c1b51eSKate Stone Error &error) { 14518a9135dSAdrian McCarthy error.SetErrorString("PutSTDIN unsupported on Windows"); 14618a9135dSAdrian McCarthy return 0; 14718a9135dSAdrian McCarthy } 14818a9135dSAdrian McCarthy 14918a9135dSAdrian McCarthy //------------------------------------------------------------------------------ 15018a9135dSAdrian McCarthy // ProcessInterface protocol. 15118a9135dSAdrian McCarthy 152*4ad5def9SAdrian McCarthy lldb_private::ConstString ProcessWindows::GetPluginName() { 153*4ad5def9SAdrian McCarthy return GetPluginNameStatic(); 154*4ad5def9SAdrian McCarthy } 155*4ad5def9SAdrian McCarthy 156*4ad5def9SAdrian McCarthy uint32_t ProcessWindows::GetPluginVersion() { return 1; } 157*4ad5def9SAdrian McCarthy 158*4ad5def9SAdrian McCarthy Error ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) { 159*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, 160*4ad5def9SAdrian McCarthy "EnableBreakpointSite called with bp_site 0x%p " 161*4ad5def9SAdrian McCarthy "(id=%d, addr=0x%llx)", 162*4ad5def9SAdrian McCarthy bp_site, bp_site->GetID(), bp_site->GetLoadAddress()); 163*4ad5def9SAdrian McCarthy 164*4ad5def9SAdrian McCarthy Error error = EnableSoftwareBreakpoint(bp_site); 165*4ad5def9SAdrian McCarthy if (!error.Success()) { 166*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed. %s", 167*4ad5def9SAdrian McCarthy error.AsCString()); 168*4ad5def9SAdrian McCarthy } 169*4ad5def9SAdrian McCarthy return error; 170*4ad5def9SAdrian McCarthy } 171*4ad5def9SAdrian McCarthy 172*4ad5def9SAdrian McCarthy Error ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) { 173*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, 174*4ad5def9SAdrian McCarthy "DisableBreakpointSite called with bp_site 0x%p " 175*4ad5def9SAdrian McCarthy "(id=%d, addr=0x%llx)", 176*4ad5def9SAdrian McCarthy bp_site, bp_site->GetID(), bp_site->GetLoadAddress()); 177*4ad5def9SAdrian McCarthy 178*4ad5def9SAdrian McCarthy Error error = DisableSoftwareBreakpoint(bp_site); 179*4ad5def9SAdrian McCarthy 180*4ad5def9SAdrian McCarthy if (!error.Success()) { 181*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite failed. %s", 182*4ad5def9SAdrian McCarthy error.AsCString()); 183*4ad5def9SAdrian McCarthy } 184*4ad5def9SAdrian McCarthy return error; 185*4ad5def9SAdrian McCarthy } 186*4ad5def9SAdrian McCarthy 187*4ad5def9SAdrian McCarthy Error ProcessWindows::DoDetach(bool keep_stopped) { 188*4ad5def9SAdrian McCarthy DebuggerThreadSP debugger_thread; 189*4ad5def9SAdrian McCarthy StateType private_state; 190*4ad5def9SAdrian McCarthy { 191*4ad5def9SAdrian McCarthy // Acquire the lock only long enough to get the DebuggerThread. 192*4ad5def9SAdrian McCarthy // StopDebugging() will trigger a call back into ProcessWindows which 193*4ad5def9SAdrian McCarthy // will also acquire the lock. Thus we have to release the lock before 194*4ad5def9SAdrian McCarthy // calling StopDebugging(). 195*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 196*4ad5def9SAdrian McCarthy 197*4ad5def9SAdrian McCarthy private_state = GetPrivateState(); 198*4ad5def9SAdrian McCarthy 199*4ad5def9SAdrian McCarthy if (!m_session_data) { 200*4ad5def9SAdrian McCarthy WINWARN_IFALL( 201*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 202*4ad5def9SAdrian McCarthy "DoDetach called while state = %u, but there is no active session.", 203*4ad5def9SAdrian McCarthy private_state); 204*4ad5def9SAdrian McCarthy return Error(); 205*4ad5def9SAdrian McCarthy } 206*4ad5def9SAdrian McCarthy 207*4ad5def9SAdrian McCarthy debugger_thread = m_session_data->m_debugger; 208*4ad5def9SAdrian McCarthy } 209*4ad5def9SAdrian McCarthy 210*4ad5def9SAdrian McCarthy Error error; 211*4ad5def9SAdrian McCarthy if (private_state != eStateExited && private_state != eStateDetached) { 212*4ad5def9SAdrian McCarthy WINLOG_IFALL( 213*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 214*4ad5def9SAdrian McCarthy "DoDetach called for process %p while state = %d. Detaching...", 215*4ad5def9SAdrian McCarthy debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), 216*4ad5def9SAdrian McCarthy private_state); 217*4ad5def9SAdrian McCarthy error = debugger_thread->StopDebugging(false); 218*4ad5def9SAdrian McCarthy if (error.Success()) { 219*4ad5def9SAdrian McCarthy SetPrivateState(eStateDetached); 220*4ad5def9SAdrian McCarthy } 221*4ad5def9SAdrian McCarthy 222*4ad5def9SAdrian McCarthy // By the time StopDebugging returns, there is no more debugger thread, so 223*4ad5def9SAdrian McCarthy // we can be assured that no other thread will race for the session data. 224*4ad5def9SAdrian McCarthy m_session_data.reset(); 225*4ad5def9SAdrian McCarthy } else { 226*4ad5def9SAdrian McCarthy WINERR_IFALL( 227*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, "DoDetach called for process %p while state = " 228*4ad5def9SAdrian McCarthy "%d, but cannot destroy in this state.", 229*4ad5def9SAdrian McCarthy debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), 230*4ad5def9SAdrian McCarthy private_state); 231*4ad5def9SAdrian McCarthy } 232*4ad5def9SAdrian McCarthy 233*4ad5def9SAdrian McCarthy return error; 234*4ad5def9SAdrian McCarthy } 235*4ad5def9SAdrian McCarthy 236*4ad5def9SAdrian McCarthy Error ProcessWindows::DoLaunch(Module *exe_module, 237*4ad5def9SAdrian McCarthy ProcessLaunchInfo &launch_info) { 238*4ad5def9SAdrian McCarthy // Even though m_session_data is accessed here, it is before a debugger thread 239*4ad5def9SAdrian McCarthy // has been 240*4ad5def9SAdrian McCarthy // kicked off. So there's no race conditions, and it shouldn't be necessary 241*4ad5def9SAdrian McCarthy // to acquire 242*4ad5def9SAdrian McCarthy // the mutex. 243*4ad5def9SAdrian McCarthy 244*4ad5def9SAdrian McCarthy Error result; 245*4ad5def9SAdrian McCarthy if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) { 246*4ad5def9SAdrian McCarthy StreamString stream; 247*4ad5def9SAdrian McCarthy stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can " 248*4ad5def9SAdrian McCarthy "only be used for debug launches.", 249*4ad5def9SAdrian McCarthy launch_info.GetExecutableFile().GetPath().c_str()); 250*4ad5def9SAdrian McCarthy std::string message = stream.GetString(); 251*4ad5def9SAdrian McCarthy result.SetErrorString(message.c_str()); 252*4ad5def9SAdrian McCarthy 253*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, "%s", message.c_str()); 254*4ad5def9SAdrian McCarthy return result; 255*4ad5def9SAdrian McCarthy } 256*4ad5def9SAdrian McCarthy 257*4ad5def9SAdrian McCarthy bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry); 258*4ad5def9SAdrian McCarthy m_session_data.reset(new ProcessWindowsData(stop_at_entry)); 259*4ad5def9SAdrian McCarthy 260*4ad5def9SAdrian McCarthy SetPrivateState(eStateLaunching); 261*4ad5def9SAdrian McCarthy DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); 262*4ad5def9SAdrian McCarthy m_session_data->m_debugger.reset(new DebuggerThread(delegate)); 263*4ad5def9SAdrian McCarthy DebuggerThreadSP debugger = m_session_data->m_debugger; 264*4ad5def9SAdrian McCarthy 265*4ad5def9SAdrian McCarthy // Kick off the DebugLaunch asynchronously and wait for it to complete. 266*4ad5def9SAdrian McCarthy result = debugger->DebugLaunch(launch_info); 267*4ad5def9SAdrian McCarthy if (result.Fail()) { 268*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", 269*4ad5def9SAdrian McCarthy launch_info.GetExecutableFile().GetPath().c_str(), 270*4ad5def9SAdrian McCarthy result.AsCString()); 271*4ad5def9SAdrian McCarthy return result; 272*4ad5def9SAdrian McCarthy } 273*4ad5def9SAdrian McCarthy 274*4ad5def9SAdrian McCarthy HostProcess process; 275*4ad5def9SAdrian McCarthy Error error = WaitForDebuggerConnection(debugger, process); 276*4ad5def9SAdrian McCarthy if (error.Fail()) { 277*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", 278*4ad5def9SAdrian McCarthy launch_info.GetExecutableFile().GetPath().c_str(), 279*4ad5def9SAdrian McCarthy error.AsCString()); 280*4ad5def9SAdrian McCarthy return error; 281*4ad5def9SAdrian McCarthy } 282*4ad5def9SAdrian McCarthy 283*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'", 284*4ad5def9SAdrian McCarthy launch_info.GetExecutableFile().GetPath().c_str()); 285*4ad5def9SAdrian McCarthy 286*4ad5def9SAdrian McCarthy // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the 287*4ad5def9SAdrian McCarthy // private state 288*4ad5def9SAdrian McCarthy // should already be set to eStateStopped as a result of hitting the initial 289*4ad5def9SAdrian McCarthy // breakpoint. If 290*4ad5def9SAdrian McCarthy // it was not set, the breakpoint should have already been resumed from and 291*4ad5def9SAdrian McCarthy // the private state 292*4ad5def9SAdrian McCarthy // should already be eStateRunning. 293*4ad5def9SAdrian McCarthy launch_info.SetProcessID(process.GetProcessId()); 294*4ad5def9SAdrian McCarthy SetID(process.GetProcessId()); 295*4ad5def9SAdrian McCarthy 296*4ad5def9SAdrian McCarthy return result; 297*4ad5def9SAdrian McCarthy } 298*4ad5def9SAdrian McCarthy 299*4ad5def9SAdrian McCarthy Error ProcessWindows::DoAttachToProcessWithID( 300*4ad5def9SAdrian McCarthy lldb::pid_t pid, const ProcessAttachInfo &attach_info) { 301*4ad5def9SAdrian McCarthy m_session_data.reset( 302*4ad5def9SAdrian McCarthy new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); 303*4ad5def9SAdrian McCarthy 304*4ad5def9SAdrian McCarthy DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); 305*4ad5def9SAdrian McCarthy DebuggerThreadSP debugger(new DebuggerThread(delegate)); 306*4ad5def9SAdrian McCarthy 307*4ad5def9SAdrian McCarthy m_session_data->m_debugger = debugger; 308*4ad5def9SAdrian McCarthy 309*4ad5def9SAdrian McCarthy DWORD process_id = static_cast<DWORD>(pid); 310*4ad5def9SAdrian McCarthy Error error = debugger->DebugAttach(process_id, attach_info); 311*4ad5def9SAdrian McCarthy if (error.Fail()) { 312*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an " 313*4ad5def9SAdrian McCarthy "error occurred initiating the " 314*4ad5def9SAdrian McCarthy "asynchronous attach. %s", 315*4ad5def9SAdrian McCarthy error.AsCString()); 316*4ad5def9SAdrian McCarthy return error; 317*4ad5def9SAdrian McCarthy } 318*4ad5def9SAdrian McCarthy 319*4ad5def9SAdrian McCarthy HostProcess process; 320*4ad5def9SAdrian McCarthy error = WaitForDebuggerConnection(debugger, process); 321*4ad5def9SAdrian McCarthy if (error.Fail()) { 322*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an " 323*4ad5def9SAdrian McCarthy "error waiting for the debugger to " 324*4ad5def9SAdrian McCarthy "connect. %s", 325*4ad5def9SAdrian McCarthy error.AsCString()); 326*4ad5def9SAdrian McCarthy return error; 327*4ad5def9SAdrian McCarthy } 328*4ad5def9SAdrian McCarthy 329*4ad5def9SAdrian McCarthy WINLOG_IFALL( 330*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 331*4ad5def9SAdrian McCarthy "DoAttachToProcessWithID successfully attached to process with pid=%lu", 332*4ad5def9SAdrian McCarthy process_id); 333*4ad5def9SAdrian McCarthy 334*4ad5def9SAdrian McCarthy // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the 335*4ad5def9SAdrian McCarthy // private state 336*4ad5def9SAdrian McCarthy // should already be set to eStateStopped as a result of hitting the initial 337*4ad5def9SAdrian McCarthy // breakpoint. If 338*4ad5def9SAdrian McCarthy // it was not set, the breakpoint should have already been resumed from and 339*4ad5def9SAdrian McCarthy // the private state 340*4ad5def9SAdrian McCarthy // should already be eStateRunning. 341*4ad5def9SAdrian McCarthy SetID(process.GetProcessId()); 342*4ad5def9SAdrian McCarthy return error; 343*4ad5def9SAdrian McCarthy } 344*4ad5def9SAdrian McCarthy 345*4ad5def9SAdrian McCarthy Error ProcessWindows::DoResume() { 346*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 347*4ad5def9SAdrian McCarthy Error error; 348*4ad5def9SAdrian McCarthy 349*4ad5def9SAdrian McCarthy StateType private_state = GetPrivateState(); 350*4ad5def9SAdrian McCarthy if (private_state == eStateStopped || private_state == eStateCrashed) { 351*4ad5def9SAdrian McCarthy WINLOG_IFALL( 352*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 353*4ad5def9SAdrian McCarthy "DoResume called for process %I64u while state is %u. Resuming...", 354*4ad5def9SAdrian McCarthy m_session_data->m_debugger->GetProcess().GetProcessId(), 355*4ad5def9SAdrian McCarthy GetPrivateState()); 356*4ad5def9SAdrian McCarthy 357*4ad5def9SAdrian McCarthy ExceptionRecordSP active_exception = 358*4ad5def9SAdrian McCarthy m_session_data->m_debugger->GetActiveException().lock(); 359*4ad5def9SAdrian McCarthy if (active_exception) { 360*4ad5def9SAdrian McCarthy // Resume the process and continue processing debug events. Mask 361*4ad5def9SAdrian McCarthy // the exception so that from the process's view, there is no 362*4ad5def9SAdrian McCarthy // indication that anything happened. 363*4ad5def9SAdrian McCarthy m_session_data->m_debugger->ContinueAsyncException( 364*4ad5def9SAdrian McCarthy ExceptionResult::MaskException); 365*4ad5def9SAdrian McCarthy } 366*4ad5def9SAdrian McCarthy 367*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_THREAD, 368*4ad5def9SAdrian McCarthy "DoResume resuming %u threads.", m_thread_list.GetSize()); 369*4ad5def9SAdrian McCarthy 370*4ad5def9SAdrian McCarthy for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) { 371*4ad5def9SAdrian McCarthy auto thread = std::static_pointer_cast<TargetThreadWindows>( 372*4ad5def9SAdrian McCarthy m_thread_list.GetThreadAtIndex(i)); 373*4ad5def9SAdrian McCarthy thread->DoResume(); 374*4ad5def9SAdrian McCarthy } 375*4ad5def9SAdrian McCarthy 376*4ad5def9SAdrian McCarthy SetPrivateState(eStateRunning); 377*4ad5def9SAdrian McCarthy } else { 378*4ad5def9SAdrian McCarthy WINERR_IFALL( 379*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 380*4ad5def9SAdrian McCarthy "DoResume called for process %I64u but state is %u. Returning...", 381*4ad5def9SAdrian McCarthy m_session_data->m_debugger->GetProcess().GetProcessId(), 382*4ad5def9SAdrian McCarthy GetPrivateState()); 383*4ad5def9SAdrian McCarthy } 384*4ad5def9SAdrian McCarthy return error; 385*4ad5def9SAdrian McCarthy } 386*4ad5def9SAdrian McCarthy 387*4ad5def9SAdrian McCarthy Error ProcessWindows::DoDestroy() { 388*4ad5def9SAdrian McCarthy DebuggerThreadSP debugger_thread; 389*4ad5def9SAdrian McCarthy StateType private_state; 390*4ad5def9SAdrian McCarthy { 391*4ad5def9SAdrian McCarthy // Acquire this lock inside an inner scope, only long enough to get the 392*4ad5def9SAdrian McCarthy // DebuggerThread. 393*4ad5def9SAdrian McCarthy // StopDebugging() will trigger a call back into ProcessWindows which will 394*4ad5def9SAdrian McCarthy // acquire the lock 395*4ad5def9SAdrian McCarthy // again, so we need to not deadlock. 396*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 397*4ad5def9SAdrian McCarthy 398*4ad5def9SAdrian McCarthy private_state = GetPrivateState(); 399*4ad5def9SAdrian McCarthy 400*4ad5def9SAdrian McCarthy if (!m_session_data) { 401*4ad5def9SAdrian McCarthy WINWARN_IFALL( 402*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 403*4ad5def9SAdrian McCarthy "DoDestroy called while state = %u, but there is no active session.", 404*4ad5def9SAdrian McCarthy private_state); 405*4ad5def9SAdrian McCarthy return Error(); 406*4ad5def9SAdrian McCarthy } 407*4ad5def9SAdrian McCarthy 408*4ad5def9SAdrian McCarthy debugger_thread = m_session_data->m_debugger; 409*4ad5def9SAdrian McCarthy } 410*4ad5def9SAdrian McCarthy 411*4ad5def9SAdrian McCarthy Error error; 412*4ad5def9SAdrian McCarthy if (private_state != eStateExited && private_state != eStateDetached) { 413*4ad5def9SAdrian McCarthy WINLOG_IFALL( 414*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, "DoDestroy called for process %p while state = " 415*4ad5def9SAdrian McCarthy "%u. Shutting down...", 416*4ad5def9SAdrian McCarthy debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), 417*4ad5def9SAdrian McCarthy private_state); 418*4ad5def9SAdrian McCarthy error = debugger_thread->StopDebugging(true); 419*4ad5def9SAdrian McCarthy 420*4ad5def9SAdrian McCarthy // By the time StopDebugging returns, there is no more debugger thread, so 421*4ad5def9SAdrian McCarthy // we can be assured that no other thread will race for the session data. 422*4ad5def9SAdrian McCarthy m_session_data.reset(); 423*4ad5def9SAdrian McCarthy } else { 424*4ad5def9SAdrian McCarthy WINERR_IFALL( 425*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, "DoDestroy called for process %p while state = " 426*4ad5def9SAdrian McCarthy "%d, but cannot destroy in this state.", 427*4ad5def9SAdrian McCarthy debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), 428*4ad5def9SAdrian McCarthy private_state); 429*4ad5def9SAdrian McCarthy } 430*4ad5def9SAdrian McCarthy 431*4ad5def9SAdrian McCarthy return error; 432*4ad5def9SAdrian McCarthy } 433*4ad5def9SAdrian McCarthy 434*4ad5def9SAdrian McCarthy Error ProcessWindows::DoHalt(bool &caused_stop) { 435*4ad5def9SAdrian McCarthy Error error; 436*4ad5def9SAdrian McCarthy StateType state = GetPrivateState(); 437*4ad5def9SAdrian McCarthy if (state == eStateStopped) 438*4ad5def9SAdrian McCarthy caused_stop = false; 439*4ad5def9SAdrian McCarthy else { 440*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 441*4ad5def9SAdrian McCarthy caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess() 442*4ad5def9SAdrian McCarthy .GetNativeProcess() 443*4ad5def9SAdrian McCarthy .GetSystemHandle()); 444*4ad5def9SAdrian McCarthy if (!caused_stop) { 445*4ad5def9SAdrian McCarthy error.SetError(::GetLastError(), eErrorTypeWin32); 446*4ad5def9SAdrian McCarthy WINERR_IFALL( 447*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 448*4ad5def9SAdrian McCarthy "DoHalt called DebugBreakProcess, but it failed with error %u", 449*4ad5def9SAdrian McCarthy error.GetError()); 450*4ad5def9SAdrian McCarthy } 451*4ad5def9SAdrian McCarthy } 452*4ad5def9SAdrian McCarthy return error; 453*4ad5def9SAdrian McCarthy } 454*4ad5def9SAdrian McCarthy 455*4ad5def9SAdrian McCarthy void ProcessWindows::DidLaunch() { 456*4ad5def9SAdrian McCarthy ArchSpec arch_spec; 457*4ad5def9SAdrian McCarthy DidAttach(arch_spec); 458*4ad5def9SAdrian McCarthy } 459*4ad5def9SAdrian McCarthy 460*4ad5def9SAdrian McCarthy void ProcessWindows::DidAttach(ArchSpec &arch_spec) { 461*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 462*4ad5def9SAdrian McCarthy 463*4ad5def9SAdrian McCarthy // The initial stop won't broadcast the state change event, so account for 464*4ad5def9SAdrian McCarthy // that here. 465*4ad5def9SAdrian McCarthy if (m_session_data && GetPrivateState() == eStateStopped && 466*4ad5def9SAdrian McCarthy m_session_data->m_stop_at_entry) 467*4ad5def9SAdrian McCarthy RefreshStateAfterStop(); 468*4ad5def9SAdrian McCarthy } 469*4ad5def9SAdrian McCarthy 470*4ad5def9SAdrian McCarthy void ProcessWindows::RefreshStateAfterStop() { 471*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 472*4ad5def9SAdrian McCarthy 473*4ad5def9SAdrian McCarthy if (!m_session_data) { 474*4ad5def9SAdrian McCarthy WINWARN_IFALL( 475*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 476*4ad5def9SAdrian McCarthy "RefreshStateAfterStop called with no active session. Returning..."); 477*4ad5def9SAdrian McCarthy return; 478*4ad5def9SAdrian McCarthy } 479*4ad5def9SAdrian McCarthy 480*4ad5def9SAdrian McCarthy m_thread_list.RefreshStateAfterStop(); 481*4ad5def9SAdrian McCarthy 482*4ad5def9SAdrian McCarthy std::weak_ptr<ExceptionRecord> exception_record = 483*4ad5def9SAdrian McCarthy m_session_data->m_debugger->GetActiveException(); 484*4ad5def9SAdrian McCarthy ExceptionRecordSP active_exception = exception_record.lock(); 485*4ad5def9SAdrian McCarthy if (!active_exception) { 486*4ad5def9SAdrian McCarthy WINERR_IFALL( 487*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 488*4ad5def9SAdrian McCarthy "RefreshStateAfterStop called for process %I64u but there is no " 489*4ad5def9SAdrian McCarthy "active exception. Why is the process stopped?", 490*4ad5def9SAdrian McCarthy m_session_data->m_debugger->GetProcess().GetProcessId()); 491*4ad5def9SAdrian McCarthy return; 492*4ad5def9SAdrian McCarthy } 493*4ad5def9SAdrian McCarthy 494*4ad5def9SAdrian McCarthy StopInfoSP stop_info; 495*4ad5def9SAdrian McCarthy m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); 496*4ad5def9SAdrian McCarthy ThreadSP stop_thread = m_thread_list.GetSelectedThread(); 497*4ad5def9SAdrian McCarthy if (!stop_thread) 498*4ad5def9SAdrian McCarthy return; 499*4ad5def9SAdrian McCarthy 500*4ad5def9SAdrian McCarthy switch (active_exception->GetExceptionCode()) { 501*4ad5def9SAdrian McCarthy case EXCEPTION_SINGLE_STEP: { 502*4ad5def9SAdrian McCarthy RegisterContextSP register_context = stop_thread->GetRegisterContext(); 503*4ad5def9SAdrian McCarthy const uint64_t pc = register_context->GetPC(); 504*4ad5def9SAdrian McCarthy BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); 505*4ad5def9SAdrian McCarthy if (site && site->ValidForThisThread(stop_thread.get())) { 506*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION | 507*4ad5def9SAdrian McCarthy WINDOWS_LOG_STEP, 508*4ad5def9SAdrian McCarthy "Single-stepped onto a breakpoint in process %I64u at " 509*4ad5def9SAdrian McCarthy "address 0x%I64x with breakpoint site %d", 510*4ad5def9SAdrian McCarthy m_session_data->m_debugger->GetProcess().GetProcessId(), pc, 511*4ad5def9SAdrian McCarthy site->GetID()); 512*4ad5def9SAdrian McCarthy stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, 513*4ad5def9SAdrian McCarthy site->GetID()); 514*4ad5def9SAdrian McCarthy stop_thread->SetStopInfo(stop_info); 515*4ad5def9SAdrian McCarthy } else { 516*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, 517*4ad5def9SAdrian McCarthy "RefreshStateAfterStop single stepping thread %llu", 518*4ad5def9SAdrian McCarthy stop_thread->GetID()); 519*4ad5def9SAdrian McCarthy stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); 520*4ad5def9SAdrian McCarthy stop_thread->SetStopInfo(stop_info); 521*4ad5def9SAdrian McCarthy } 522*4ad5def9SAdrian McCarthy return; 523*4ad5def9SAdrian McCarthy } 524*4ad5def9SAdrian McCarthy 525*4ad5def9SAdrian McCarthy case EXCEPTION_BREAKPOINT: { 526*4ad5def9SAdrian McCarthy RegisterContextSP register_context = stop_thread->GetRegisterContext(); 527*4ad5def9SAdrian McCarthy 528*4ad5def9SAdrian McCarthy // The current EIP is AFTER the BP opcode, which is one byte. 529*4ad5def9SAdrian McCarthy uint64_t pc = register_context->GetPC() - 1; 530*4ad5def9SAdrian McCarthy 531*4ad5def9SAdrian McCarthy BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); 532*4ad5def9SAdrian McCarthy if (site) { 533*4ad5def9SAdrian McCarthy WINLOG_IFANY( 534*4ad5def9SAdrian McCarthy WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, 535*4ad5def9SAdrian McCarthy "RefreshStateAfterStop detected breakpoint in process %I64u at " 536*4ad5def9SAdrian McCarthy "address 0x%I64x with breakpoint site %d", 537*4ad5def9SAdrian McCarthy m_session_data->m_debugger->GetProcess().GetProcessId(), pc, 538*4ad5def9SAdrian McCarthy site->GetID()); 539*4ad5def9SAdrian McCarthy 540*4ad5def9SAdrian McCarthy if (site->ValidForThisThread(stop_thread.get())) { 541*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, 542*4ad5def9SAdrian McCarthy "Breakpoint site %d is valid for this thread (0x%I64x), " 543*4ad5def9SAdrian McCarthy "creating stop info.", 544*4ad5def9SAdrian McCarthy site->GetID(), stop_thread->GetID()); 545*4ad5def9SAdrian McCarthy 546*4ad5def9SAdrian McCarthy stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID( 547*4ad5def9SAdrian McCarthy *stop_thread, site->GetID()); 548*4ad5def9SAdrian McCarthy register_context->SetPC(pc); 549*4ad5def9SAdrian McCarthy } else { 550*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, 551*4ad5def9SAdrian McCarthy "Breakpoint site %d is not valid for this thread, " 552*4ad5def9SAdrian McCarthy "creating empty stop info.", 553*4ad5def9SAdrian McCarthy site->GetID()); 554*4ad5def9SAdrian McCarthy } 555*4ad5def9SAdrian McCarthy stop_thread->SetStopInfo(stop_info); 556*4ad5def9SAdrian McCarthy return; 557*4ad5def9SAdrian McCarthy } else { 558*4ad5def9SAdrian McCarthy // The thread hit a hard-coded breakpoint like an `int 3` or 559*4ad5def9SAdrian McCarthy // `__debugbreak()`. 560*4ad5def9SAdrian McCarthy WINLOG_IFALL( 561*4ad5def9SAdrian McCarthy WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, 562*4ad5def9SAdrian McCarthy "No breakpoint site matches for this thread. __debugbreak()? " 563*4ad5def9SAdrian McCarthy "Creating stop info with the exception."); 564*4ad5def9SAdrian McCarthy // FALLTHROUGH: We'll treat this as a generic exception record in the 565*4ad5def9SAdrian McCarthy // default case. 566*4ad5def9SAdrian McCarthy } 567*4ad5def9SAdrian McCarthy } 568*4ad5def9SAdrian McCarthy 569*4ad5def9SAdrian McCarthy default: { 570*4ad5def9SAdrian McCarthy std::string desc; 571*4ad5def9SAdrian McCarthy llvm::raw_string_ostream desc_stream(desc); 572*4ad5def9SAdrian McCarthy desc_stream << "Exception " 573*4ad5def9SAdrian McCarthy << llvm::format_hex(active_exception->GetExceptionCode(), 8) 574*4ad5def9SAdrian McCarthy << " encountered at address " 575*4ad5def9SAdrian McCarthy << llvm::format_hex(active_exception->GetExceptionAddress(), 8); 576*4ad5def9SAdrian McCarthy stop_info = StopInfo::CreateStopReasonWithException( 577*4ad5def9SAdrian McCarthy *stop_thread, desc_stream.str().c_str()); 578*4ad5def9SAdrian McCarthy stop_thread->SetStopInfo(stop_info); 579*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, "%s", desc_stream.str().c_str()); 580*4ad5def9SAdrian McCarthy return; 581*4ad5def9SAdrian McCarthy } 582*4ad5def9SAdrian McCarthy } 583*4ad5def9SAdrian McCarthy } 584*4ad5def9SAdrian McCarthy 585*4ad5def9SAdrian McCarthy bool ProcessWindows::CanDebug(lldb::TargetSP target_sp, 586*4ad5def9SAdrian McCarthy bool plugin_specified_by_name) { 587*4ad5def9SAdrian McCarthy if (plugin_specified_by_name) 588*4ad5def9SAdrian McCarthy return true; 589*4ad5def9SAdrian McCarthy 590*4ad5def9SAdrian McCarthy // For now we are just making sure the file exists for a given module 591*4ad5def9SAdrian McCarthy ModuleSP exe_module_sp(target_sp->GetExecutableModule()); 592*4ad5def9SAdrian McCarthy if (exe_module_sp.get()) 593*4ad5def9SAdrian McCarthy return exe_module_sp->GetFileSpec().Exists(); 594*4ad5def9SAdrian McCarthy // However, if there is no executable module, we return true since we might be 595*4ad5def9SAdrian McCarthy // preparing to attach. 596*4ad5def9SAdrian McCarthy return true; 597*4ad5def9SAdrian McCarthy } 598*4ad5def9SAdrian McCarthy 599*4ad5def9SAdrian McCarthy bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list, 600*4ad5def9SAdrian McCarthy ThreadList &new_thread_list) { 601*4ad5def9SAdrian McCarthy // Add all the threads that were previously running and for which we did not 602*4ad5def9SAdrian McCarthy // detect a thread exited event. 603*4ad5def9SAdrian McCarthy int new_size = 0; 604*4ad5def9SAdrian McCarthy int continued_threads = 0; 605*4ad5def9SAdrian McCarthy int exited_threads = 0; 606*4ad5def9SAdrian McCarthy int new_threads = 0; 607*4ad5def9SAdrian McCarthy 608*4ad5def9SAdrian McCarthy for (ThreadSP old_thread : old_thread_list.Threads()) { 609*4ad5def9SAdrian McCarthy lldb::tid_t old_thread_id = old_thread->GetID(); 610*4ad5def9SAdrian McCarthy auto exited_thread_iter = 611*4ad5def9SAdrian McCarthy m_session_data->m_exited_threads.find(old_thread_id); 612*4ad5def9SAdrian McCarthy if (exited_thread_iter == m_session_data->m_exited_threads.end()) { 613*4ad5def9SAdrian McCarthy new_thread_list.AddThread(old_thread); 614*4ad5def9SAdrian McCarthy ++new_size; 615*4ad5def9SAdrian McCarthy ++continued_threads; 616*4ad5def9SAdrian McCarthy WINLOGV_IFALL( 617*4ad5def9SAdrian McCarthy WINDOWS_LOG_THREAD, 618*4ad5def9SAdrian McCarthy "UpdateThreadList - Thread %llu was running and is still running.", 619*4ad5def9SAdrian McCarthy old_thread_id); 620*4ad5def9SAdrian McCarthy } else { 621*4ad5def9SAdrian McCarthy WINLOGV_IFALL( 622*4ad5def9SAdrian McCarthy WINDOWS_LOG_THREAD, 623*4ad5def9SAdrian McCarthy "UpdateThreadList - Thread %llu was running and has exited.", 624*4ad5def9SAdrian McCarthy old_thread_id); 625*4ad5def9SAdrian McCarthy ++exited_threads; 626*4ad5def9SAdrian McCarthy } 627*4ad5def9SAdrian McCarthy } 628*4ad5def9SAdrian McCarthy 629*4ad5def9SAdrian McCarthy // Also add all the threads that are new since the last time we broke into the 630*4ad5def9SAdrian McCarthy // debugger. 631*4ad5def9SAdrian McCarthy for (const auto &thread_info : m_session_data->m_new_threads) { 632*4ad5def9SAdrian McCarthy ThreadSP thread(new TargetThreadWindows(*this, thread_info.second)); 633*4ad5def9SAdrian McCarthy thread->SetID(thread_info.first); 634*4ad5def9SAdrian McCarthy new_thread_list.AddThread(thread); 635*4ad5def9SAdrian McCarthy ++new_size; 636*4ad5def9SAdrian McCarthy ++new_threads; 637*4ad5def9SAdrian McCarthy WINLOGV_IFALL(WINDOWS_LOG_THREAD, 638*4ad5def9SAdrian McCarthy "UpdateThreadList - Thread %llu is new since last update.", 639*4ad5def9SAdrian McCarthy thread_info.first); 640*4ad5def9SAdrian McCarthy } 641*4ad5def9SAdrian McCarthy 642*4ad5def9SAdrian McCarthy WINLOG_IFALL( 643*4ad5def9SAdrian McCarthy WINDOWS_LOG_THREAD, 644*4ad5def9SAdrian McCarthy "UpdateThreadList - %d new threads, %d old threads, %d exited threads.", 645*4ad5def9SAdrian McCarthy new_threads, continued_threads, exited_threads); 646*4ad5def9SAdrian McCarthy 647*4ad5def9SAdrian McCarthy m_session_data->m_new_threads.clear(); 648*4ad5def9SAdrian McCarthy m_session_data->m_exited_threads.clear(); 649*4ad5def9SAdrian McCarthy 650*4ad5def9SAdrian McCarthy return new_size > 0; 651*4ad5def9SAdrian McCarthy } 652*4ad5def9SAdrian McCarthy 653*4ad5def9SAdrian McCarthy bool ProcessWindows::IsAlive() { 654*4ad5def9SAdrian McCarthy StateType state = GetPrivateState(); 655*4ad5def9SAdrian McCarthy switch (state) { 656*4ad5def9SAdrian McCarthy case eStateCrashed: 657*4ad5def9SAdrian McCarthy case eStateDetached: 658*4ad5def9SAdrian McCarthy case eStateUnloaded: 659*4ad5def9SAdrian McCarthy case eStateExited: 660*4ad5def9SAdrian McCarthy case eStateInvalid: 661*4ad5def9SAdrian McCarthy return false; 662*4ad5def9SAdrian McCarthy default: 663*4ad5def9SAdrian McCarthy return true; 664*4ad5def9SAdrian McCarthy } 665*4ad5def9SAdrian McCarthy } 666*4ad5def9SAdrian McCarthy 667*4ad5def9SAdrian McCarthy size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf, 668*4ad5def9SAdrian McCarthy size_t size, Error &error) { 669*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 670*4ad5def9SAdrian McCarthy 671*4ad5def9SAdrian McCarthy if (!m_session_data) 672*4ad5def9SAdrian McCarthy return 0; 673*4ad5def9SAdrian McCarthy 674*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_MEMORY, 675*4ad5def9SAdrian McCarthy "DoReadMemory attempting to read %u bytes from address 0x%I64x", 676*4ad5def9SAdrian McCarthy size, vm_addr); 677*4ad5def9SAdrian McCarthy 678*4ad5def9SAdrian McCarthy HostProcess process = m_session_data->m_debugger->GetProcess(); 679*4ad5def9SAdrian McCarthy void *addr = reinterpret_cast<void *>(vm_addr); 680*4ad5def9SAdrian McCarthy SIZE_T bytes_read = 0; 681*4ad5def9SAdrian McCarthy if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr, 682*4ad5def9SAdrian McCarthy buf, size, &bytes_read)) { 683*4ad5def9SAdrian McCarthy error.SetError(GetLastError(), eErrorTypeWin32); 684*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory failed with error code %u", 685*4ad5def9SAdrian McCarthy error.GetError()); 686*4ad5def9SAdrian McCarthy } 687*4ad5def9SAdrian McCarthy return bytes_read; 688*4ad5def9SAdrian McCarthy } 689*4ad5def9SAdrian McCarthy 690*4ad5def9SAdrian McCarthy size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, 691*4ad5def9SAdrian McCarthy size_t size, Error &error) { 692*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 693*4ad5def9SAdrian McCarthy WINLOG_IFALL( 694*4ad5def9SAdrian McCarthy WINDOWS_LOG_MEMORY, 695*4ad5def9SAdrian McCarthy "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size, 696*4ad5def9SAdrian McCarthy vm_addr); 697*4ad5def9SAdrian McCarthy 698*4ad5def9SAdrian McCarthy if (!m_session_data) { 699*4ad5def9SAdrian McCarthy WINERR_IFANY( 700*4ad5def9SAdrian McCarthy WINDOWS_LOG_MEMORY, 701*4ad5def9SAdrian McCarthy "DoWriteMemory cannot write, there is no active debugger connection."); 702*4ad5def9SAdrian McCarthy return 0; 703*4ad5def9SAdrian McCarthy } 704*4ad5def9SAdrian McCarthy 705*4ad5def9SAdrian McCarthy HostProcess process = m_session_data->m_debugger->GetProcess(); 706*4ad5def9SAdrian McCarthy void *addr = reinterpret_cast<void *>(vm_addr); 707*4ad5def9SAdrian McCarthy SIZE_T bytes_written = 0; 708*4ad5def9SAdrian McCarthy lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); 709*4ad5def9SAdrian McCarthy if (WriteProcessMemory(handle, addr, buf, size, &bytes_written)) 710*4ad5def9SAdrian McCarthy FlushInstructionCache(handle, addr, bytes_written); 711*4ad5def9SAdrian McCarthy else { 712*4ad5def9SAdrian McCarthy error.SetError(GetLastError(), eErrorTypeWin32); 713*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory failed with error code %u", 714*4ad5def9SAdrian McCarthy error.GetError()); 715*4ad5def9SAdrian McCarthy } 716*4ad5def9SAdrian McCarthy return bytes_written; 717*4ad5def9SAdrian McCarthy } 718*4ad5def9SAdrian McCarthy 719*4ad5def9SAdrian McCarthy #define BOOL_STR(b) ((b) ? "true" : "false") 720*4ad5def9SAdrian McCarthy 721*4ad5def9SAdrian McCarthy Error ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr, 722*4ad5def9SAdrian McCarthy MemoryRegionInfo &info) { 723*4ad5def9SAdrian McCarthy Error error; 724*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 725*4ad5def9SAdrian McCarthy info.Clear(); 726*4ad5def9SAdrian McCarthy 727*4ad5def9SAdrian McCarthy if (!m_session_data) { 728*4ad5def9SAdrian McCarthy error.SetErrorString( 729*4ad5def9SAdrian McCarthy "GetMemoryRegionInfo called with no debugging session."); 730*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_MEMORY, "%s", error.AsCString()); 731*4ad5def9SAdrian McCarthy return error; 732*4ad5def9SAdrian McCarthy } 733*4ad5def9SAdrian McCarthy HostProcess process = m_session_data->m_debugger->GetProcess(); 734*4ad5def9SAdrian McCarthy lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); 735*4ad5def9SAdrian McCarthy if (handle == nullptr || handle == LLDB_INVALID_PROCESS) { 736*4ad5def9SAdrian McCarthy error.SetErrorString( 737*4ad5def9SAdrian McCarthy "GetMemoryRegionInfo called with an invalid target process."); 738*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_MEMORY, "%s", error.AsCString()); 739*4ad5def9SAdrian McCarthy return error; 740*4ad5def9SAdrian McCarthy } 741*4ad5def9SAdrian McCarthy 742*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_MEMORY, 743*4ad5def9SAdrian McCarthy "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr); 744*4ad5def9SAdrian McCarthy 745*4ad5def9SAdrian McCarthy void *addr = reinterpret_cast<void *>(vm_addr); 746*4ad5def9SAdrian McCarthy MEMORY_BASIC_INFORMATION mem_info = {}; 747*4ad5def9SAdrian McCarthy SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); 748*4ad5def9SAdrian McCarthy if (result == 0) { 749*4ad5def9SAdrian McCarthy if (::GetLastError() == ERROR_INVALID_PARAMETER) { 750*4ad5def9SAdrian McCarthy // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an 751*4ad5def9SAdrian McCarthy // address 752*4ad5def9SAdrian McCarthy // past the highest accessible address. We should return a range from the 753*4ad5def9SAdrian McCarthy // vm_addr 754*4ad5def9SAdrian McCarthy // to LLDB_INVALID_ADDRESS 755*4ad5def9SAdrian McCarthy info.GetRange().SetRangeBase(vm_addr); 756*4ad5def9SAdrian McCarthy info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); 757*4ad5def9SAdrian McCarthy info.SetReadable(MemoryRegionInfo::eNo); 758*4ad5def9SAdrian McCarthy info.SetExecutable(MemoryRegionInfo::eNo); 759*4ad5def9SAdrian McCarthy info.SetWritable(MemoryRegionInfo::eNo); 760*4ad5def9SAdrian McCarthy info.SetMapped(MemoryRegionInfo::eNo); 761*4ad5def9SAdrian McCarthy return error; 762*4ad5def9SAdrian McCarthy } else { 763*4ad5def9SAdrian McCarthy error.SetError(::GetLastError(), eErrorTypeWin32); 764*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_MEMORY, "VirtualQueryEx returned error %u while " 765*4ad5def9SAdrian McCarthy "getting memory region info for address " 766*4ad5def9SAdrian McCarthy "0x%I64x", 767*4ad5def9SAdrian McCarthy error.GetError(), vm_addr); 768*4ad5def9SAdrian McCarthy return error; 769*4ad5def9SAdrian McCarthy } 770*4ad5def9SAdrian McCarthy } 771*4ad5def9SAdrian McCarthy 772*4ad5def9SAdrian McCarthy // Protect bits are only valid for MEM_COMMIT regions. 773*4ad5def9SAdrian McCarthy if (mem_info.State == MEM_COMMIT) { 774*4ad5def9SAdrian McCarthy const bool readable = IsPageReadable(mem_info.Protect); 775*4ad5def9SAdrian McCarthy const bool executable = IsPageExecutable(mem_info.Protect); 776*4ad5def9SAdrian McCarthy const bool writable = IsPageWritable(mem_info.Protect); 777*4ad5def9SAdrian McCarthy info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); 778*4ad5def9SAdrian McCarthy info.SetExecutable(executable ? MemoryRegionInfo::eYes 779*4ad5def9SAdrian McCarthy : MemoryRegionInfo::eNo); 780*4ad5def9SAdrian McCarthy info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); 781*4ad5def9SAdrian McCarthy } else { 782*4ad5def9SAdrian McCarthy info.SetReadable(MemoryRegionInfo::eNo); 783*4ad5def9SAdrian McCarthy info.SetExecutable(MemoryRegionInfo::eNo); 784*4ad5def9SAdrian McCarthy info.SetWritable(MemoryRegionInfo::eNo); 785*4ad5def9SAdrian McCarthy } 786*4ad5def9SAdrian McCarthy 787*4ad5def9SAdrian McCarthy // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE. 788*4ad5def9SAdrian McCarthy if (mem_info.State != MEM_FREE) { 789*4ad5def9SAdrian McCarthy info.GetRange().SetRangeBase( 790*4ad5def9SAdrian McCarthy reinterpret_cast<addr_t>(mem_info.AllocationBase)); 791*4ad5def9SAdrian McCarthy info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) + 792*4ad5def9SAdrian McCarthy mem_info.RegionSize); 793*4ad5def9SAdrian McCarthy info.SetMapped(MemoryRegionInfo::eYes); 794*4ad5def9SAdrian McCarthy } else { 795*4ad5def9SAdrian McCarthy // In the unmapped case we need to return the distance to the next block of 796*4ad5def9SAdrian McCarthy // memory. 797*4ad5def9SAdrian McCarthy // VirtualQueryEx nearly does that except that it gives the distance from 798*4ad5def9SAdrian McCarthy // the start 799*4ad5def9SAdrian McCarthy // of the page containing vm_addr. 800*4ad5def9SAdrian McCarthy SYSTEM_INFO data; 801*4ad5def9SAdrian McCarthy GetSystemInfo(&data); 802*4ad5def9SAdrian McCarthy DWORD page_offset = vm_addr % data.dwPageSize; 803*4ad5def9SAdrian McCarthy info.GetRange().SetRangeBase(vm_addr); 804*4ad5def9SAdrian McCarthy info.GetRange().SetByteSize(mem_info.RegionSize - page_offset); 805*4ad5def9SAdrian McCarthy info.SetMapped(MemoryRegionInfo::eNo); 806*4ad5def9SAdrian McCarthy } 807*4ad5def9SAdrian McCarthy 808*4ad5def9SAdrian McCarthy error.SetError(::GetLastError(), eErrorTypeWin32); 809*4ad5def9SAdrian McCarthy WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address %llu: " 810*4ad5def9SAdrian McCarthy "readable=%s, executable=%s, writable=%s", 811*4ad5def9SAdrian McCarthy vm_addr, BOOL_STR(info.GetReadable()), 812*4ad5def9SAdrian McCarthy BOOL_STR(info.GetExecutable()), BOOL_STR(info.GetWritable())); 813*4ad5def9SAdrian McCarthy return error; 814*4ad5def9SAdrian McCarthy } 815*4ad5def9SAdrian McCarthy 816b9c1b51eSKate Stone lldb::addr_t ProcessWindows::GetImageInfoAddress() { 81718a9135dSAdrian McCarthy Target &target = GetTarget(); 81818a9135dSAdrian McCarthy ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile(); 81918a9135dSAdrian McCarthy Address addr = obj_file->GetImageInfoAddress(&target); 82018a9135dSAdrian McCarthy if (addr.IsValid()) 82118a9135dSAdrian McCarthy return addr.GetLoadAddress(&target); 82218a9135dSAdrian McCarthy else 82318a9135dSAdrian McCarthy return LLDB_INVALID_ADDRESS; 82418a9135dSAdrian McCarthy } 82518a9135dSAdrian McCarthy 826*4ad5def9SAdrian McCarthy void ProcessWindows::OnExitProcess(uint32_t exit_code) { 827*4ad5def9SAdrian McCarthy // No need to acquire the lock since m_session_data isn't accessed. 828*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Process %llu exited with code %u", GetID(), 829*4ad5def9SAdrian McCarthy exit_code); 830*4ad5def9SAdrian McCarthy 831*4ad5def9SAdrian McCarthy TargetSP target = m_target_sp.lock(); 832*4ad5def9SAdrian McCarthy if (target) { 833*4ad5def9SAdrian McCarthy ModuleSP executable_module = target->GetExecutableModule(); 834*4ad5def9SAdrian McCarthy ModuleList unloaded_modules; 835*4ad5def9SAdrian McCarthy unloaded_modules.Append(executable_module); 836*4ad5def9SAdrian McCarthy target->ModulesDidUnload(unloaded_modules, true); 837*4ad5def9SAdrian McCarthy } 838*4ad5def9SAdrian McCarthy 839*4ad5def9SAdrian McCarthy SetProcessExitStatus(GetID(), true, 0, exit_code); 840*4ad5def9SAdrian McCarthy SetPrivateState(eStateExited); 841*4ad5def9SAdrian McCarthy } 842*4ad5def9SAdrian McCarthy 843*4ad5def9SAdrian McCarthy void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) { 844*4ad5def9SAdrian McCarthy DebuggerThreadSP debugger = m_session_data->m_debugger; 845*4ad5def9SAdrian McCarthy 846*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, 847*4ad5def9SAdrian McCarthy "Debugger connected to process %I64u. Image base = 0x%I64x", 848*4ad5def9SAdrian McCarthy debugger->GetProcess().GetProcessId(), image_base); 849*4ad5def9SAdrian McCarthy 850*4ad5def9SAdrian McCarthy ModuleSP module = GetTarget().GetExecutableModule(); 851*4ad5def9SAdrian McCarthy if (!module) { 852*4ad5def9SAdrian McCarthy // During attach, we won't have the executable module, so find it now. 853*4ad5def9SAdrian McCarthy const DWORD pid = debugger->GetProcess().GetProcessId(); 854*4ad5def9SAdrian McCarthy const std::string file_name = GetProcessExecutableName(pid); 855*4ad5def9SAdrian McCarthy if (file_name.empty()) { 856*4ad5def9SAdrian McCarthy return; 857*4ad5def9SAdrian McCarthy } 858*4ad5def9SAdrian McCarthy 859*4ad5def9SAdrian McCarthy FileSpec executable_file(file_name, true); 860*4ad5def9SAdrian McCarthy ModuleSpec module_spec(executable_file); 861*4ad5def9SAdrian McCarthy Error error; 862*4ad5def9SAdrian McCarthy module = GetTarget().GetSharedModule(module_spec, &error); 863*4ad5def9SAdrian McCarthy if (!module) { 864*4ad5def9SAdrian McCarthy return; 865*4ad5def9SAdrian McCarthy } 866*4ad5def9SAdrian McCarthy 867*4ad5def9SAdrian McCarthy GetTarget().SetExecutableModule(module, false); 868*4ad5def9SAdrian McCarthy } 869*4ad5def9SAdrian McCarthy 870*4ad5def9SAdrian McCarthy bool load_addr_changed; 871*4ad5def9SAdrian McCarthy module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed); 872*4ad5def9SAdrian McCarthy 873*4ad5def9SAdrian McCarthy ModuleList loaded_modules; 874*4ad5def9SAdrian McCarthy loaded_modules.Append(module); 875*4ad5def9SAdrian McCarthy GetTarget().ModulesDidLoad(loaded_modules); 876*4ad5def9SAdrian McCarthy 877*4ad5def9SAdrian McCarthy // Add the main executable module to the list of pending module loads. We 878*4ad5def9SAdrian McCarthy // can't call 879*4ad5def9SAdrian McCarthy // GetTarget().ModulesDidLoad() here because we still haven't returned from 880*4ad5def9SAdrian McCarthy // DoLaunch() / DoAttach() yet 881*4ad5def9SAdrian McCarthy // so the target may not have set the process instance to `this` yet. 882*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 883*4ad5def9SAdrian McCarthy const HostThreadWindows &wmain_thread = 884*4ad5def9SAdrian McCarthy debugger->GetMainThread().GetNativeThread(); 885*4ad5def9SAdrian McCarthy m_session_data->m_new_threads[wmain_thread.GetThreadId()] = 886*4ad5def9SAdrian McCarthy debugger->GetMainThread(); 887*4ad5def9SAdrian McCarthy } 888*4ad5def9SAdrian McCarthy 889*4ad5def9SAdrian McCarthy ExceptionResult 890*4ad5def9SAdrian McCarthy ProcessWindows::OnDebugException(bool first_chance, 891*4ad5def9SAdrian McCarthy const ExceptionRecord &record) { 892*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 893*4ad5def9SAdrian McCarthy 894*4ad5def9SAdrian McCarthy // FIXME: Without this check, occasionally when running the test suite there 895*4ad5def9SAdrian McCarthy // is 896*4ad5def9SAdrian McCarthy // an issue where m_session_data can be null. It's not clear how this could 897*4ad5def9SAdrian McCarthy // happen 898*4ad5def9SAdrian McCarthy // but it only surfaces while running the test suite. In order to properly 899*4ad5def9SAdrian McCarthy // diagnose 900*4ad5def9SAdrian McCarthy // this, we probably need to first figure allow the test suite to print out 901*4ad5def9SAdrian McCarthy // full 902*4ad5def9SAdrian McCarthy // lldb logs, and then add logging to the process plugin. 903*4ad5def9SAdrian McCarthy if (!m_session_data) { 904*4ad5def9SAdrian McCarthy WINERR_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception " 905*4ad5def9SAdrian McCarthy "0x%lx at address 0x%llu, but there is " 906*4ad5def9SAdrian McCarthy "no session.", 907*4ad5def9SAdrian McCarthy record.GetExceptionCode(), record.GetExceptionAddress()); 908*4ad5def9SAdrian McCarthy return ExceptionResult::SendToApplication; 909*4ad5def9SAdrian McCarthy } 910*4ad5def9SAdrian McCarthy 911*4ad5def9SAdrian McCarthy if (!first_chance) { 912*4ad5def9SAdrian McCarthy // Any second chance exception is an application crash by definition. 913*4ad5def9SAdrian McCarthy SetPrivateState(eStateCrashed); 914*4ad5def9SAdrian McCarthy } 915*4ad5def9SAdrian McCarthy 916*4ad5def9SAdrian McCarthy ExceptionResult result = ExceptionResult::SendToApplication; 917*4ad5def9SAdrian McCarthy switch (record.GetExceptionCode()) { 918*4ad5def9SAdrian McCarthy case EXCEPTION_BREAKPOINT: 919*4ad5def9SAdrian McCarthy // Handle breakpoints at the first chance. 920*4ad5def9SAdrian McCarthy result = ExceptionResult::BreakInDebugger; 921*4ad5def9SAdrian McCarthy 922*4ad5def9SAdrian McCarthy if (!m_session_data->m_initial_stop_received) { 923*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, "Hit loader breakpoint at address " 924*4ad5def9SAdrian McCarthy "0x%I64x, setting initial stop " 925*4ad5def9SAdrian McCarthy "event.", 926*4ad5def9SAdrian McCarthy record.GetExceptionAddress()); 927*4ad5def9SAdrian McCarthy m_session_data->m_initial_stop_received = true; 928*4ad5def9SAdrian McCarthy ::SetEvent(m_session_data->m_initial_stop_event); 929*4ad5def9SAdrian McCarthy } else { 930*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, 931*4ad5def9SAdrian McCarthy "Hit non-loader breakpoint at address 0x%I64x.", 932*4ad5def9SAdrian McCarthy record.GetExceptionAddress()); 933*4ad5def9SAdrian McCarthy } 934*4ad5def9SAdrian McCarthy SetPrivateState(eStateStopped); 935*4ad5def9SAdrian McCarthy break; 936*4ad5def9SAdrian McCarthy case EXCEPTION_SINGLE_STEP: 937*4ad5def9SAdrian McCarthy result = ExceptionResult::BreakInDebugger; 938*4ad5def9SAdrian McCarthy SetPrivateState(eStateStopped); 939*4ad5def9SAdrian McCarthy break; 940*4ad5def9SAdrian McCarthy default: 941*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception " 942*4ad5def9SAdrian McCarthy "0x%lx at address 0x%llx " 943*4ad5def9SAdrian McCarthy "(first_chance=%s)", 944*4ad5def9SAdrian McCarthy record.GetExceptionCode(), record.GetExceptionAddress(), 945*4ad5def9SAdrian McCarthy BOOL_STR(first_chance)); 946*4ad5def9SAdrian McCarthy // For non-breakpoints, give the application a chance to handle the 947*4ad5def9SAdrian McCarthy // exception first. 948*4ad5def9SAdrian McCarthy if (first_chance) 949*4ad5def9SAdrian McCarthy result = ExceptionResult::SendToApplication; 950*4ad5def9SAdrian McCarthy else 951*4ad5def9SAdrian McCarthy result = ExceptionResult::BreakInDebugger; 952*4ad5def9SAdrian McCarthy } 953*4ad5def9SAdrian McCarthy 954*4ad5def9SAdrian McCarthy return result; 955*4ad5def9SAdrian McCarthy } 956*4ad5def9SAdrian McCarthy 957*4ad5def9SAdrian McCarthy void ProcessWindows::OnCreateThread(const HostThread &new_thread) { 958*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 959*4ad5def9SAdrian McCarthy const HostThreadWindows &wnew_thread = new_thread.GetNativeThread(); 960*4ad5def9SAdrian McCarthy m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread; 961*4ad5def9SAdrian McCarthy } 962*4ad5def9SAdrian McCarthy 963*4ad5def9SAdrian McCarthy void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) { 964*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 965*4ad5def9SAdrian McCarthy 966*4ad5def9SAdrian McCarthy // On a forced termination, we may get exit thread events after the session 967*4ad5def9SAdrian McCarthy // data has been cleaned up. 968*4ad5def9SAdrian McCarthy if (!m_session_data) 969*4ad5def9SAdrian McCarthy return; 970*4ad5def9SAdrian McCarthy 971*4ad5def9SAdrian McCarthy // A thread may have started and exited before the debugger stopped allowing a 972*4ad5def9SAdrian McCarthy // refresh. 973*4ad5def9SAdrian McCarthy // Just remove it from the new threads list in that case. 974*4ad5def9SAdrian McCarthy auto iter = m_session_data->m_new_threads.find(thread_id); 975*4ad5def9SAdrian McCarthy if (iter != m_session_data->m_new_threads.end()) 976*4ad5def9SAdrian McCarthy m_session_data->m_new_threads.erase(iter); 977*4ad5def9SAdrian McCarthy else 978*4ad5def9SAdrian McCarthy m_session_data->m_exited_threads.insert(thread_id); 979*4ad5def9SAdrian McCarthy } 980*4ad5def9SAdrian McCarthy 981*4ad5def9SAdrian McCarthy void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec, 982*4ad5def9SAdrian McCarthy lldb::addr_t module_addr) { 983*4ad5def9SAdrian McCarthy // Confusingly, there is no Target::AddSharedModule. Instead, calling 984*4ad5def9SAdrian McCarthy // GetSharedModule() with 985*4ad5def9SAdrian McCarthy // a new module will add it to the module list and return a corresponding 986*4ad5def9SAdrian McCarthy // ModuleSP. 987*4ad5def9SAdrian McCarthy Error error; 988*4ad5def9SAdrian McCarthy ModuleSP module = GetTarget().GetSharedModule(module_spec, &error); 989*4ad5def9SAdrian McCarthy bool load_addr_changed = false; 990*4ad5def9SAdrian McCarthy module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed); 991*4ad5def9SAdrian McCarthy 992*4ad5def9SAdrian McCarthy ModuleList loaded_modules; 993*4ad5def9SAdrian McCarthy loaded_modules.Append(module); 994*4ad5def9SAdrian McCarthy GetTarget().ModulesDidLoad(loaded_modules); 995*4ad5def9SAdrian McCarthy } 996*4ad5def9SAdrian McCarthy 997*4ad5def9SAdrian McCarthy void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) { 998*4ad5def9SAdrian McCarthy Address resolved_addr; 999*4ad5def9SAdrian McCarthy if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) { 1000*4ad5def9SAdrian McCarthy ModuleSP module = resolved_addr.GetModule(); 1001*4ad5def9SAdrian McCarthy if (module) { 1002*4ad5def9SAdrian McCarthy ModuleList unloaded_modules; 1003*4ad5def9SAdrian McCarthy unloaded_modules.Append(module); 1004*4ad5def9SAdrian McCarthy GetTarget().ModulesDidUnload(unloaded_modules, false); 1005*4ad5def9SAdrian McCarthy } 1006*4ad5def9SAdrian McCarthy } 1007*4ad5def9SAdrian McCarthy } 1008*4ad5def9SAdrian McCarthy 1009*4ad5def9SAdrian McCarthy void ProcessWindows::OnDebugString(const std::string &string) {} 1010*4ad5def9SAdrian McCarthy 1011*4ad5def9SAdrian McCarthy void ProcessWindows::OnDebuggerError(const Error &error, uint32_t type) { 1012*4ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex); 1013*4ad5def9SAdrian McCarthy 1014*4ad5def9SAdrian McCarthy if (m_session_data->m_initial_stop_received) { 1015*4ad5def9SAdrian McCarthy // This happened while debugging. Do we shutdown the debugging session, try 1016*4ad5def9SAdrian McCarthy // to continue, 1017*4ad5def9SAdrian McCarthy // or do something else? 1018*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging. " 1019*4ad5def9SAdrian McCarthy "Unexpected behavior may result. %s", 1020*4ad5def9SAdrian McCarthy error.GetError(), error.AsCString()); 1021*4ad5def9SAdrian McCarthy } else { 1022*4ad5def9SAdrian McCarthy // If we haven't actually launched the process yet, this was an error 1023*4ad5def9SAdrian McCarthy // launching the 1024*4ad5def9SAdrian McCarthy // process. Set the internal error and signal the initial stop event so 1025*4ad5def9SAdrian McCarthy // that the DoLaunch 1026*4ad5def9SAdrian McCarthy // method wakes up and returns a failure. 1027*4ad5def9SAdrian McCarthy m_session_data->m_launch_error = error; 1028*4ad5def9SAdrian McCarthy ::SetEvent(m_session_data->m_initial_stop_event); 1029*4ad5def9SAdrian McCarthy WINERR_IFALL( 1030*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 1031*4ad5def9SAdrian McCarthy "Error %u occurred launching the process before the initial stop. %s", 1032*4ad5def9SAdrian McCarthy error.GetError(), error.AsCString()); 1033*4ad5def9SAdrian McCarthy return; 1034*4ad5def9SAdrian McCarthy } 1035*4ad5def9SAdrian McCarthy } 1036*4ad5def9SAdrian McCarthy 1037*4ad5def9SAdrian McCarthy Error ProcessWindows::WaitForDebuggerConnection(DebuggerThreadSP debugger, 1038*4ad5def9SAdrian McCarthy HostProcess &process) { 1039*4ad5def9SAdrian McCarthy Error result; 1040*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS, 1041*4ad5def9SAdrian McCarthy "WaitForDebuggerConnection Waiting for loader breakpoint."); 1042*4ad5def9SAdrian McCarthy 1043*4ad5def9SAdrian McCarthy // Block this function until we receive the initial stop from the process. 1044*4ad5def9SAdrian McCarthy if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == 1045*4ad5def9SAdrian McCarthy WAIT_OBJECT_0) { 1046*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS, 1047*4ad5def9SAdrian McCarthy "WaitForDebuggerConnection hit loader breakpoint, returning."); 1048*4ad5def9SAdrian McCarthy 1049*4ad5def9SAdrian McCarthy process = debugger->GetProcess(); 1050*4ad5def9SAdrian McCarthy return m_session_data->m_launch_error; 1051*4ad5def9SAdrian McCarthy } else 1052*4ad5def9SAdrian McCarthy return Error(::GetLastError(), eErrorTypeWin32); 1053*4ad5def9SAdrian McCarthy } 1054*4ad5def9SAdrian McCarthy 1055b9c1b51eSKate Stone // The Windows page protection bits are NOT independent masks that can be 1056*4ad5def9SAdrian McCarthy // bitwise-ORed together. For example, PAGE_EXECUTE_READ is not 1057*4ad5def9SAdrian McCarthy // (PAGE_EXECUTE | PAGE_READ). To test for an access type, it's necessary to 1058*4ad5def9SAdrian McCarthy // test for any of the bits that provide that access type. 1059b9c1b51eSKate Stone bool ProcessWindows::IsPageReadable(uint32_t protect) { 10600c35cde9SAdrian McCarthy return (protect & PAGE_NOACCESS) == 0; 10610c35cde9SAdrian McCarthy } 10620c35cde9SAdrian McCarthy 1063b9c1b51eSKate Stone bool ProcessWindows::IsPageWritable(uint32_t protect) { 1064b9c1b51eSKate Stone return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | 1065b9c1b51eSKate Stone PAGE_READWRITE | PAGE_WRITECOPY)) != 0; 10660c35cde9SAdrian McCarthy } 10670c35cde9SAdrian McCarthy 1068b9c1b51eSKate Stone bool ProcessWindows::IsPageExecutable(uint32_t protect) { 1069b9c1b51eSKate Stone return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | 1070b9c1b51eSKate Stone PAGE_EXECUTE_WRITECOPY)) != 0; 10710c35cde9SAdrian McCarthy } 1072*4ad5def9SAdrian McCarthy 1073*4ad5def9SAdrian McCarthy } // namespace lldb_private 1074