void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) { DebuggerThreadSP debugger = m_session_data->m_debugger; WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Debugger connected to process %I64u. Image base = 0x%I64x", debugger->GetProcess().GetProcessId(), image_base); ModuleSP module = GetTarget().GetExecutableModule(); if (!module) { // During attach, we won't have the executable module, so find it now. const DWORD pid = debugger->GetProcess().GetProcessId(); const std::string file_name = GetProcessExecutableName(pid); if (file_name.empty()) { return; } FileSpec executable_file(file_name, true); ModuleSpec module_spec(executable_file); Error error; module = GetTarget().GetSharedModule(module_spec, &error); if (!module) { return; } GetTarget().SetExecutableModule(module, false); } bool load_addr_changed; module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed); ModuleList loaded_modules; loaded_modules.Append(module); GetTarget().ModulesDidLoad(loaded_modules); // Add the main executable module to the list of pending module loads. We can't call // GetTarget().ModulesDidLoad() here because we still haven't returned from DoLaunch() / DoAttach() yet // so the target may not have set the process instance to `this` yet. llvm::sys::ScopedLock lock(m_mutex); const HostThreadWindows &wmain_thread = debugger->GetMainThread().GetNativeThread(); m_session_data->m_new_threads[wmain_thread.GetThreadId()] = debugger->GetMainThread(); }
Error ProcessWindows::DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) { // Even though m_session_data is accessed here, it is before a debugger thread has been // kicked off. So there's no race conditions, and it shouldn't be necessary to acquire // the mutex. Error result; if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) { result.SetErrorString("ProcessWindows can only be used to launch processes for debugging."); return result; } m_session_data.reset(new ProcessWindowsData(launch_info)); SetPrivateState(eStateLaunching); DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); m_session_data->m_debugger.reset(new DebuggerThread(delegate)); DebuggerThreadSP debugger = m_session_data->m_debugger; // Kick off the DebugLaunch asynchronously and wait for it to complete. result = debugger->DebugLaunch(launch_info); HostProcess process; if (result.Success()) { // Block this function until we receive the initial stop from the process. if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == WAIT_OBJECT_0) { process = debugger->GetProcess(); if (m_session_data->m_launch_error.Fail()) result = m_session_data->m_launch_error; } else result.SetError(::GetLastError(), eErrorTypeWin32); } if (!result.Success()) return result; // We've hit the initial stop. The private state should already be set to stopped as a result // of encountering the breakpoint exception in ProcessWindows::OnDebugException. launch_info.SetProcessID(process.GetProcessId()); SetID(process.GetProcessId()); return result; }
Error ProcessWindows::WaitForDebuggerConnection(DebuggerThreadSP debugger, HostProcess &process) { Error result; WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_BREAKPOINTS, "WaitForDebuggerConnection Waiting for loader breakpoint."); // Block this function until we receive the initial stop from the process. if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == WAIT_OBJECT_0) { WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_BREAKPOINTS, "WaitForDebuggerConnection hit loader breakpoint, returning."); process = debugger->GetProcess(); return m_session_data->m_launch_error; } else return Error(::GetLastError(), eErrorTypeWin32); }