[Lldb-commits] [lldb] r228757 - Extract attach core logic from SBTarget::Attach* methods into unified SBTarget::AttachToProcess and make it work with platform for remote attach purposes.

Oleksiy Vyalov ovyalov at google.com
Tue Feb 10 14:49:58 PST 2015


Author: ovyalov
Date: Tue Feb 10 16:49:57 2015
New Revision: 228757

URL: http://llvm.org/viewvc/llvm-project?rev=228757&view=rev
Log:
Extract attach core logic from SBTarget::Attach* methods into unified SBTarget::AttachToProcess and make it work with platform for remote attach purposes.

http://reviews.llvm.org/D7471


Modified:
    lldb/trunk/include/lldb/Target/Target.h
    lldb/trunk/source/API/SBTarget.cpp
    lldb/trunk/source/Commands/CommandObjectProcess.cpp
    lldb/trunk/source/Target/Target.cpp

Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=228757&r1=228756&r2=228757&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Tue Feb 10 16:49:57 2015
@@ -617,7 +617,11 @@ public:
     
     Error
     Launch (ProcessLaunchInfo &launch_info,
-            Stream *stream); // Optional stream to receive first stop info
+            Stream *stream);  // Optional stream to receive first stop info
+
+    Error
+    Attach (ProcessAttachInfo &attach_info,
+            Stream *stream);  // Optional stream to receive first stop info
 
     //------------------------------------------------------------------
     // This part handles the breakpoints.

Modified: lldb/trunk/source/API/SBTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTarget.cpp?rev=228757&r1=228756&r2=228757&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTarget.cpp (original)
+++ lldb/trunk/source/API/SBTarget.cpp Tue Feb 10 16:49:57 2015
@@ -291,6 +291,32 @@ SBAttachInfo::SetListener (SBListener &l
     m_opaque_sp->SetListener(listener.GetSP());
 }
 
+namespace {
+
+Error
+AttachToProcess (ProcessAttachInfo &attach_info, Target &target)
+{
+    Mutex::Locker api_locker (target.GetAPIMutex ());
+
+    auto process_sp = target.GetProcessSP ();
+    if (process_sp)
+    {
+        const auto state = process_sp->GetState ();
+        if (process_sp->IsAlive () && state == eStateConnected)
+        {
+            // If we are already connected, then we have already specified the
+            // listener, so if a valid listener is supplied, we need to error out
+            // to let the client know.
+            if (attach_info.GetListener ())
+                return Error ("process is connected and already has a listener, pass empty listener");
+        }
+    }
+
+    return target.Attach (attach_info, nullptr);
+}
+
+}  // namespace
+
 //----------------------------------------------------------------------
 // SBTarget constructor
 //----------------------------------------------------------------------
@@ -613,7 +639,6 @@ SBTarget::Attach (SBAttachInfo &sb_attac
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     SBProcess sb_process;
-    ProcessSP process_sp;
     TargetSP target_sp(GetSP());
 
     if (log)
@@ -622,72 +647,34 @@ SBTarget::Attach (SBAttachInfo &sb_attac
 
     if (target_sp)
     {
-        Mutex::Locker api_locker (target_sp->GetAPIMutex());
-
-        StateType state = eStateInvalid;
-        process_sp = target_sp->GetProcessSP();
-        if (process_sp)
+        ProcessAttachInfo &attach_info = sb_attach_info.ref();
+        if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid())
         {
-            state = process_sp->GetState();
-
-            if (process_sp->IsAlive() && state != eStateConnected)
+            PlatformSP platform_sp = target_sp->GetPlatform();
+            // See if we can pre-verify if a process exists or not
+            if (platform_sp && platform_sp->IsConnected())
             {
-                if (state == eStateAttaching)
-                    error.SetErrorString ("process attach is in progress");
+                lldb::pid_t attach_pid = attach_info.GetProcessID();
+                ProcessInstanceInfo instance_info;
+                if (platform_sp->GetProcessInfo(attach_pid, instance_info))
+                {
+                    attach_info.SetUserID(instance_info.GetEffectiveUserID());
+                }
                 else
-                    error.SetErrorString ("a process is already being debugged");
-                if (log)
-                    log->Printf ("SBTarget(%p)::Attach (...) => error %s",
-                                 static_cast<void*>(target_sp.get()),
-                                 error.GetCString());
-                return sb_process;
-            }
-        }
-
-        if (state != eStateConnected)
-            process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
-
-        if (process_sp)
-        {
-            ProcessAttachInfo &attach_info = sb_attach_info.ref();
-            if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid())
-            {
-                PlatformSP platform_sp = target_sp->GetPlatform();
-                // See if we can pre-verify if a process exists or not
-                if (platform_sp && platform_sp->IsConnected())
                 {
-                    lldb::pid_t attach_pid = attach_info.GetProcessID();
-                    ProcessInstanceInfo instance_info;
-                    if (platform_sp->GetProcessInfo(attach_pid, instance_info))
+                    error.ref().SetErrorStringWithFormat("no process found with process ID %" PRIu64, attach_pid);
+                    if (log)
                     {
-                        attach_info.SetUserID(instance_info.GetEffectiveUserID());
-                    }
-                    else
-                    {
-                        error.ref().SetErrorStringWithFormat("no process found with process ID %" PRIu64, attach_pid);
-                        if (log)
-                        {
-                            log->Printf ("SBTarget(%p)::Attach (...) => error %s",
-                                         static_cast<void*>(target_sp.get()), error.GetCString());
-                        }
-                        return sb_process;
+                        log->Printf ("SBTarget(%p)::Attach (...) => error %s",
+                                     static_cast<void*>(target_sp.get()), error.GetCString());
                     }
+                    return sb_process;
                 }
             }
-            error.SetError (process_sp->Attach (attach_info));
-            if (error.Success())
-            {
-                sb_process.SetSP (process_sp);
-                // If we are doing synchronous mode, then wait for the
-                // process to stop!
-                if (target_sp->GetDebugger().GetAsyncExecution () == false)
-                    process_sp->WaitForProcessToStop (NULL);
-            }
-        }
-        else
-        {
-            error.SetErrorString ("unable to create lldb_private::Process");
         }
+        error.SetError(AttachToProcess(attach_info, *target_sp));
+        if (error.Success())
+            sb_process.SetSP(target_sp->GetProcessSP());
     }
     else
     {
@@ -697,7 +684,7 @@ SBTarget::Attach (SBAttachInfo &sb_attac
     if (log)
         log->Printf ("SBTarget(%p)::Attach (...) => SBProcess(%p)",
                      static_cast<void*>(target_sp.get()),
-                     static_cast<void*>(process_sp.get()));
+                     static_cast<void*>(sb_process.GetSP().get()));
 
     return sb_process;
 }
@@ -726,87 +713,37 @@ SBTarget::AttachToProcessWithID
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     SBProcess sb_process;
-    ProcessSP process_sp;
     TargetSP target_sp(GetSP());
 
     if (log)
-        log->Printf ("SBTarget(%p)::AttachToProcessWithID (listener, pid=%" PRId64 ", error)...",
-                     static_cast<void*>(target_sp.get()), pid);
+        log->Printf ("SBTarget(%p)::%s (listener, pid=%" PRId64 ", error)...",
+                     static_cast<void*>(target_sp.get()),
+                     __FUNCTION__,
+                     pid);
 
     if (target_sp)
     {
-        Mutex::Locker api_locker (target_sp->GetAPIMutex());
-
-        StateType state = eStateInvalid;
-        process_sp = target_sp->GetProcessSP();
-        if (process_sp)
-        {
-            state = process_sp->GetState();
-
-            if (process_sp->IsAlive() && state != eStateConnected)
-            {
-                if (state == eStateAttaching)
-                    error.SetErrorString ("process attach is in progress");
-                else
-                    error.SetErrorString ("a process is already being debugged");
-                return sb_process;
-            }
-        }
-
-        if (state == eStateConnected)
-        {
-            // If we are already connected, then we have already specified the
-            // listener, so if a valid listener is supplied, we need to error out
-            // to let the client know.
-            if (listener.IsValid())
-            {
-                error.SetErrorString ("process is connected and already has a listener, pass empty listener");
-                return sb_process;
-            }
-        }
-        else
-        {
-            if (listener.IsValid())
-                process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL);
-            else
-                process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
-        }
-        if (process_sp)
-        {
-            sb_process.SetSP (process_sp);
-
-            ProcessAttachInfo attach_info;
-            attach_info.SetProcessID (pid);
+        ProcessAttachInfo attach_info;
+        attach_info.SetProcessID (pid);
+        if (listener.IsValid())
+            attach_info.SetListener(listener.GetSP());
 
-            PlatformSP platform_sp = target_sp->GetPlatform();
-            ProcessInstanceInfo instance_info;
-            if (platform_sp->GetProcessInfo(pid, instance_info))
-            {
-                attach_info.SetUserID(instance_info.GetEffectiveUserID());
-            }
-            error.SetError (process_sp->Attach (attach_info));            
-            if (error.Success())
-            {
-                // If we are doing synchronous mode, then wait for the
-                // process to stop!
-                if (target_sp->GetDebugger().GetAsyncExecution () == false)
-                    process_sp->WaitForProcessToStop (NULL);
-            }
-        }
-        else
-        {
-            error.SetErrorString ("unable to create lldb_private::Process");
-        }
+        ProcessInstanceInfo instance_info;
+        if (target_sp->GetPlatform ()->GetProcessInfo (pid, instance_info))
+            attach_info.SetUserID (instance_info.GetEffectiveUserID ());
+
+        error.SetError (AttachToProcess (attach_info, *target_sp));
+        if (error.Success ())
+            sb_process.SetSP (target_sp->GetProcessSP ());
     }
     else
-    {
         error.SetErrorString ("SBTarget is invalid");
-    }
 
     if (log)
-        log->Printf ("SBTarget(%p)::AttachToProcessWithID (...) => SBProcess(%p)",
-                     static_cast<void*>(target_sp.get()),
-                     static_cast<void*>(process_sp.get()));
+        log->Printf ("SBTarget(%p)::%s (...) => SBProcess(%p)",
+                     static_cast<void*>(target_sp.get ()),
+                     __FUNCTION__,
+                     static_cast<void*>(sb_process.GetSP().get ()));
     return sb_process;
 }
 
@@ -822,82 +759,35 @@ SBTarget::AttachToProcessWithName
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     SBProcess sb_process;
-    ProcessSP process_sp;
     TargetSP target_sp(GetSP());
 
     if (log)
-        log->Printf ("SBTarget(%p)::AttachToProcessWithName (listener, name=%s, wait_for=%s, error)...",
-                     static_cast<void*>(target_sp.get()), name,
+        log->Printf ("SBTarget(%p)::%s (listener, name=%s, wait_for=%s, error)...",
+                     static_cast<void*>(target_sp.get()),
+                     __FUNCTION__,
+                     name,
                      wait_for ? "true" : "false");
 
     if (name && target_sp)
     {
-        Mutex::Locker api_locker (target_sp->GetAPIMutex());
-
-        StateType state = eStateInvalid;
-        process_sp = target_sp->GetProcessSP();
-        if (process_sp)
-        {
-            state = process_sp->GetState();
-
-            if (process_sp->IsAlive() && state != eStateConnected)
-            {
-                if (state == eStateAttaching)
-                    error.SetErrorString ("process attach is in progress");
-                else
-                    error.SetErrorString ("a process is already being debugged");
-                return sb_process;
-            }
-        }
-
-        if (state == eStateConnected)
-        {
-            // If we are already connected, then we have already specified the
-            // listener, so if a valid listener is supplied, we need to error out
-            // to let the client know.
-            if (listener.IsValid())
-            {
-                error.SetErrorString ("process is connected and already has a listener, pass empty listener");
-                return sb_process;
-            }
-        }
-        else
-        {
-            if (listener.IsValid())
-                process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL);
-            else
-                process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
-        }
+        ProcessAttachInfo attach_info;
+        attach_info.GetExecutableFile().SetFile(name, false);
+        attach_info.SetWaitForLaunch(wait_for);
+        if (listener.IsValid())
+            attach_info.SetListener(listener.GetSP());
 
-        if (process_sp)
-        {
-            sb_process.SetSP (process_sp);
-            ProcessAttachInfo attach_info;
-            attach_info.GetExecutableFile().SetFile(name, false);
-            attach_info.SetWaitForLaunch(wait_for);
-            error.SetError (process_sp->Attach (attach_info));
-            if (error.Success())
-            {
-                // If we are doing synchronous mode, then wait for the
-                // process to stop!
-                if (target_sp->GetDebugger().GetAsyncExecution () == false)
-                    process_sp->WaitForProcessToStop (NULL);
-            }
-        }
-        else
-        {
-            error.SetErrorString ("unable to create lldb_private::Process");
-        }
+        error.SetError (AttachToProcess (attach_info, *target_sp));
+        if (error.Success ())
+            sb_process.SetSP (target_sp->GetProcessSP ());
     }
     else
-    {
         error.SetErrorString ("SBTarget is invalid");
-    }
 
     if (log)
-        log->Printf ("SBTarget(%p)::AttachToPorcessWithName (...) => SBProcess(%p)",
+        log->Printf ("SBTarget(%p)::%s (...) => SBProcess(%p)",
                      static_cast<void*>(target_sp.get()),
-                     static_cast<void*>(process_sp.get()));
+                     __FUNCTION__,
+                     static_cast<void*>(sb_process.GetSP().get()));
     return sb_process;
 }
 
@@ -2678,4 +2568,3 @@ SBTarget::GetStackRedZoneSize()
     }
     return 0;
 }
-

Modified: lldb/trunk/source/Commands/CommandObjectProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectProcess.cpp?rev=228757&r1=228756&r2=228757&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectProcess.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectProcess.cpp Tue Feb 10 16:49:57 2015
@@ -529,8 +529,6 @@ protected:
         ModuleSP old_exec_module_sp = target->GetExecutableModule();
         ArchSpec old_arch_spec = target->GetArchitecture();
 
-        ProcessSP process_sp;
-        Error error;
         if (command.GetArgumentCount())
         {
             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
@@ -539,70 +537,21 @@ protected:
         }
 
         m_interpreter.UpdateExecutionContext(nullptr);
-        ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack"));
-        m_options.attach_info.SetHijackListener(listener_sp);
-
-        // If no process info was specified, then use the target executable
-        // name as the process to attach to by default
-        if (!m_options.attach_info.ProcessInfoSpecified ())
-        {
-            if (old_exec_module_sp)
-                m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetPlatformFileSpec().GetFilename();
-
-            if (!m_options.attach_info.ProcessInfoSpecified ())
-            {
-                error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option");
-            }
-        }
-
+        StreamString stream;
+        const auto error = target->Attach(m_options.attach_info, &stream);
         if (error.Success())
         {
-            if (state != eStateConnected && platform_sp != nullptr && platform_sp->CanDebugProcess())
-            {
-                target->SetPlatform(platform_sp);
-                process = platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), target, error).get();
-            }
-            else
-            {
-                if (state != eStateConnected)
-                {
-                    const char *plugin_name = m_options.attach_info.GetProcessPluginName();
-                    process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, nullptr).get();
-                    if (process == nullptr)
-                        error.SetErrorStringWithFormat("failed to create process using plugin %s", plugin_name);
-                }
-                if (process)
-                {
-                    process->HijackProcessEvents(listener_sp.get());
-                    error = process->Attach(m_options.attach_info);
-                }
-            }
-        }
-
-        if (error.Success() && process != nullptr)
-        {
-            result.SetStatus (eReturnStatusSuccessContinuingNoResult);
-            StreamString stream;
-            StateType state = process->WaitForProcessToStop (nullptr, nullptr, false, listener_sp.get(), &stream);
-
-            process->RestoreProcessEvents();
-            result.SetDidChangeProcessState (true);
-
-            if (stream.GetData())
-                result.AppendMessage(stream.GetData());
-
-            if (state == eStateStopped)
+            ProcessSP process_sp (target->GetProcessSP());
+            if (process_sp)
             {
+                if (stream.GetData())
+                    result.AppendMessage(stream.GetData());
                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                result.SetDidChangeProcessState (true);
             }
             else
             {
-                const char *exit_desc = process->GetExitDescription();
-                if (exit_desc)
-                    result.AppendErrorWithFormat ("attach failed: %s", exit_desc);
-                else
-                    result.AppendError ("attach failed: process did not stop (no such process or permission problem?)");
-                process->Destroy();
+                result.AppendError("no error returned from Target::Attach, and target has no process");
                 result.SetStatus (eReturnStatusFailed);
             }
         }

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=228757&r1=228756&r2=228757&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Tue Feb 10 16:49:57 2015
@@ -2594,6 +2594,83 @@ Target::Launch (ProcessLaunchInfo &launc
     }
     return error;
 }
+
+Error
+Target::Attach (ProcessAttachInfo &attach_info, Stream *stream)
+{
+    auto state = eStateInvalid;
+    auto process_sp = GetProcessSP ();
+    if (process_sp)
+    {
+        state = process_sp->GetState ();
+        if (process_sp->IsAlive () && state != eStateConnected)
+        {
+            if (state == eStateAttaching)
+                return Error ("process attach is in progress");
+            return Error ("a process is already being debugged");
+        }
+    }
+
+    ListenerSP hijack_listener_sp (new Listener ("lldb.Target.Attach.attach.hijack"));
+    attach_info.SetHijackListener (hijack_listener_sp);
+
+    const ModuleSP old_exec_module_sp = GetExecutableModule ();
+
+    // If no process info was specified, then use the target executable
+    // name as the process to attach to by default
+    if (!attach_info.ProcessInfoSpecified ())
+    {
+        if (old_exec_module_sp)
+            attach_info.GetExecutableFile ().GetFilename () = old_exec_module_sp->GetPlatformFileSpec ().GetFilename ();
+
+        if (!attach_info.ProcessInfoSpecified ())
+        {
+            return Error ("no process specified, create a target with a file, or specify the --pid or --name");
+        }
+    }
+
+    const auto platform_sp = GetDebugger ().GetPlatformList ().GetSelectedPlatform ();
+
+    Error error;
+    if (state != eStateConnected && platform_sp != nullptr && platform_sp->CanDebugProcess ())
+    {
+        SetPlatform (platform_sp);
+        process_sp = platform_sp->Attach (attach_info, GetDebugger (), this, error);
+    }
+    else
+    {
+        if (state != eStateConnected)
+        {
+            const char *plugin_name = attach_info.GetProcessPluginName ();
+            process_sp = CreateProcess (attach_info.GetListenerForProcess (GetDebugger ()), plugin_name, nullptr);
+            if (process_sp == nullptr)
+            {
+                error.SetErrorStringWithFormat ("failed to create process using plugin %s", (plugin_name) ? plugin_name : "null");
+                return error;
+            }
+        }
+        process_sp->HijackProcessEvents (hijack_listener_sp.get ());
+        error = process_sp->Attach (attach_info);
+    }
+
+    if (error.Success () && process_sp)
+    {
+        state = process_sp->WaitForProcessToStop (nullptr, nullptr, false, attach_info.GetHijackListener ().get (), stream);
+        process_sp->RestoreProcessEvents ();
+
+        if (state != eStateStopped)
+        {
+            const char *exit_desc = process_sp->GetExitDescription ();
+            if (exit_desc)
+                error.SetErrorStringWithFormat ("attach failed: %s", exit_desc);
+            else
+                error.SetErrorString ("attach failed: process did not stop (no such process or permission problem?)");
+            process_sp->Destroy ();
+        }
+    }
+    return error;
+}
+
 //--------------------------------------------------------------
 // Target::StopHook
 //--------------------------------------------------------------





More information about the lldb-commits mailing list