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)) { StreamString stream; stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can only be used for debug launches.", launch_info.GetExecutableFile().GetPath().c_str()); std::string message = stream.GetString(); result.SetErrorString(message.c_str()); WINERR_IFALL(WINDOWS_LOG_PROCESS, message.c_str()); return result; } bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry); m_session_data.reset(new ProcessWindowsData(stop_at_entry)); 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); if (result.Fail()) { WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", launch_info.GetExecutableFile().GetPath().c_str(), result.AsCString()); return result; } HostProcess process; Error error = WaitForDebuggerConnection(debugger, process); if (error.Fail()) { WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", launch_info.GetExecutableFile().GetPath().c_str(), error.AsCString()); return error; } WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'", launch_info.GetExecutableFile().GetPath().c_str()); // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the private state // should already be set to eStateStopped as a result of hitting the initial breakpoint. If // it was not set, the breakpoint should have already been resumed from and the private state // should already be eStateRunning. launch_info.SetProcessID(process.GetProcessId()); SetID(process.GetProcessId()); return result; }
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 Host::LaunchProcess(ProcessLaunchInfo &launch_info) { std::unique_ptr<ProcessLauncher> delegate_launcher; #if defined(_WIN32) delegate_launcher.reset(new ProcessLauncherWindows()); #elif defined(__linux__) delegate_launcher.reset(new ProcessLauncherLinux()); #else delegate_launcher.reset(new ProcessLauncherPosix()); #endif MonitoringProcessLauncher launcher(std::move(delegate_launcher)); Error error; HostProcess process = launcher.LaunchProcess(launch_info, error); // TODO(zturner): It would be better if the entire HostProcess were returned // instead of writing // it into this structure. launch_info.SetProcessID(process.GetProcessId()); return error; }
Error ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid, const ProcessAttachInfo &attach_info) { m_session_data.reset(new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); DebuggerThreadSP debugger(new DebuggerThread(delegate)); m_session_data->m_debugger = debugger; DWORD process_id = static_cast<DWORD>(pid); Error error = debugger->DebugAttach(process_id, attach_info); if (error.Fail()) { WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an error occurred initiating the asynchronous attach. %s", error.AsCString()); return error; } HostProcess process; error = WaitForDebuggerConnection(debugger, process); if (error.Fail()) { WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an error waiting for the debugger to connect. %s", error.AsCString()); return error; } WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID successfully attached to process with pid=%u", process_id); // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the private state // should already be set to eStateStopped as a result of hitting the initial breakpoint. If // it was not set, the breakpoint should have already been resumed from and the private state // should already be eStateRunning. SetID(process.GetProcessId()); return error; }
HostProcess MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Status &error) { ProcessLaunchInfo resolved_info(launch_info); error.Clear(); char exe_path[PATH_MAX]; PlatformSP host_platform_sp(Platform::GetHostPlatform()); const ArchSpec &arch_spec = resolved_info.GetArchitecture(); FileSpec exe_spec(resolved_info.GetExecutableFile()); llvm::sys::fs::file_status stats; status(exe_spec.GetPath(), stats); if (!is_regular_file(stats)) { ModuleSpec module_spec(exe_spec, arch_spec); lldb::ModuleSP exe_module_sp; error = host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL); if (error.Fail()) return HostProcess(); if (exe_module_sp) { exe_spec = exe_module_sp->GetFileSpec(); status(exe_spec.GetPath(), stats); } } if (exists(stats)) { exe_spec.GetPath(exe_path, sizeof(exe_path)); } else { resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); return HostProcess(); } resolved_info.SetExecutableFile(exe_spec, false); assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY)); HostProcess process = m_delegate_launcher->LaunchProcess(resolved_info, error); if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); Host::MonitorChildProcessCallback callback = launch_info.GetMonitorProcessCallback(); bool monitor_signals = false; if (callback) { // If the ProcessLaunchInfo specified a callback, use that. monitor_signals = launch_info.GetMonitorSignals(); } else { callback = Process::SetProcessExitStatus; } process.StartMonitoring(callback, monitor_signals); if (log) log->PutCString("started monitoring child process."); } else { // Invalid process ID, something didn't go well if (error.Success()) error.SetErrorString("process launch failed for unknown reasons"); } return process; }