lldb::ProcessSP PlatformRemoteGDBServer::Attach( ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new target, else use // existing one Error &error) { lldb::ProcessSP process_sp; if (IsRemote()) { if (IsConnected()) { lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; std::string connect_url; if (!LaunchGDBServer(debugserver_pid, connect_url)) { error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'", GetHostname()); } else { if (target == NULL) { TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget( debugger, NULL, NULL, false, NULL, new_target_sp); target = new_target_sp.get(); } else error.Clear(); if (target && error.Success()) { debugger.GetTargetList().SetSelectedTarget(target); // The darwin always currently uses the GDB remote debugger plug-in // so even when debugging locally we are debugging remotely! process_sp = target->CreateProcess( attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); if (process_sp) { error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); if (error.Success()) { ListenerSP listener_sp = attach_info.GetHijackListener(); if (listener_sp) process_sp->HijackProcessEvents(listener_sp); error = process_sp->Attach(attach_info); } if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) { KillSpawnedProcess(debugserver_pid); } } } } } else { error.SetErrorString("not connected to remote gdb server"); } } return process_sp; }
lldb::ProcessSP PlatformWindows::Attach(ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, Error &error) { error.Clear(); lldb::ProcessSP process_sp; if (!IsHost()) { if (m_remote_platform_sp) process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error); else error.SetErrorString ("the platform is not currently connected"); return process_sp; } if (target == nullptr) { TargetSP new_target_sp; FileSpec emptyFileSpec; ArchSpec emptyArchSpec; error = debugger.GetTargetList().CreateTarget(debugger, nullptr, nullptr, false, nullptr, new_target_sp); target = new_target_sp.get(); } if (!target || error.Fail()) return process_sp; debugger.GetTargetList().SetSelectedTarget(target); const char *plugin_name = attach_info.GetProcessPluginName(); process_sp = target->CreateProcess(attach_info.GetListenerForProcess(debugger), plugin_name, nullptr); process_sp->HijackProcessEvents(attach_info.GetHijackListener()); if (process_sp) error = process_sp->Attach (attach_info); return process_sp; }
lldb::ProcessSP PlatformLinux::Attach(ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, Listener &listener, Error &error) { lldb::ProcessSP process_sp; if (IsHost()) { if (target == NULL) { TargetSP new_target_sp; FileSpec emptyFileSpec; ArchSpec emptyArchSpec; error = debugger.GetTargetList().CreateTarget (debugger, emptyFileSpec, emptyArchSpec, false, m_remote_platform_sp, new_target_sp); target = new_target_sp.get(); } else error.Clear(); if (target && error.Success()) { debugger.GetTargetList().SetSelectedTarget(target); process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName(), NULL); if (process_sp) error = process_sp->Attach (attach_info); } } else { if (m_remote_platform_sp) process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); else error.SetErrorString ("the platform is not currently connected"); } return process_sp; }
lldb::ProcessSP PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, Error &error) { lldb::ProcessSP process_sp; if (IsHost()) { if (target == NULL) { TargetSP new_target_sp; ArchSpec emptyArchSpec; error = debugger.GetTargetList().CreateTarget (debugger, NULL, emptyArchSpec, false, m_remote_platform_sp, new_target_sp); target = new_target_sp.get(); } else error.Clear(); if (target && error.Success()) { debugger.GetTargetList().SetSelectedTarget(target); // The freebsd always currently uses the GDB remote debugger plug-in // so even when debugging locally we are debugging remotely! // Just like the darwin plugin. process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); if (process_sp) error = process_sp->Attach (attach_info); } } else { if (m_remote_platform_sp) process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error); else error.SetErrorString ("the platform is not currently connected"); } return process_sp; }
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; }
lldb::ProcessSP PlatformPOSIX::Attach (ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, Error &error) { lldb::ProcessSP process_sp; Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (IsHost()) { if (target == NULL) { TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget (debugger, NULL, NULL, false, NULL, new_target_sp); target = new_target_sp.get(); if (log) log->Printf ("PlatformPOSIX::%s created new target", __FUNCTION__); } else { error.Clear(); if (log) log->Printf ("PlatformPOSIX::%s target already existed, setting target", __FUNCTION__); } if (target && error.Success()) { debugger.GetTargetList().SetSelectedTarget(target); if (log) { ModuleSP exe_module_sp = target->GetExecutableModule (); log->Printf("PlatformPOSIX::%s set selected target to %p %s", __FUNCTION__, (void *)target, exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() : "<null>"); } process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), attach_info.GetProcessPluginName(), NULL); if (process_sp) { // Set UnixSignals appropriately. process_sp->SetUnixSignals (Host::GetUnixSignals ()); auto listener_sp = attach_info.GetHijackListener(); if (listener_sp == nullptr) { listener_sp.reset(new Listener("lldb.PlatformPOSIX.attach.hijack")); attach_info.SetHijackListener(listener_sp); } process_sp->HijackProcessEvents(listener_sp.get()); error = process_sp->Attach (attach_info); } } } else { if (m_remote_platform_sp) process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error); else error.SetErrorString ("the platform is not currently connected"); } return process_sp; }