[Lldb-commits] [lldb] r227899 - Make "process attach" command to support attaching to remote process in case if selected platform allows this.

Oleksiy Vyalov ovyalov at google.com
Mon Feb 2 16:04:35 PST 2015


Author: ovyalov
Date: Mon Feb  2 18:04:35 2015
New Revision: 227899

URL: http://llvm.org/viewvc/llvm-project?rev=227899&view=rev
Log:
Make "process attach" command to support attaching to remote process in case if selected platform allows this.

http://reviews.llvm.org/D7358

Modified:
    lldb/trunk/source/Commands/CommandObjectProcess.cpp
    lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
    lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
    lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp

Modified: lldb/trunk/source/Commands/CommandObjectProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectProcess.cpp?rev=227899&r1=227898&r2=227899&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectProcess.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectProcess.cpp Mon Feb  2 18:04:35 2015
@@ -489,6 +489,8 @@ protected:
     DoExecute (Args& command,
              CommandReturnObject &result)
     {
+        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+
         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
         // N.B. The attach should be synchronous.  It doesn't help much to get the prompt back between initiating the attach
         // and the target actually stopping.  So even if the interpreter is set to be asynchronous, we wait for the stop
@@ -527,122 +529,130 @@ 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());
             result.SetStatus (eReturnStatusFailed);
+            return false;
         }
-        else
+
+        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 (state != eStateConnected)
+            if (old_exec_module_sp)
+                m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetPlatformFileSpec().GetFilename();
+
+            if (!m_options.attach_info.ProcessInfoSpecified ())
             {
-                const char *plugin_name = m_options.attach_info.GetProcessPluginName();
-                process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
+                error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option");
             }
+        }
 
-            if (process)
+        if (error.Success())
+        {
+            if (state != eStateConnected && platform_sp != nullptr && platform_sp->CanDebugProcess())
             {
-                Error error;
-                // 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 ())
+                target->SetPlatform(platform_sp);
+                process = platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), target, error).get();
+            }
+            else
+            {
+                if (state != eStateConnected)
                 {
-                    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");
-                    }
+                    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 (error.Success())
+                if (process)
                 {
-                    // Update the execution context so the current target and process are now selected
-                    // in case we interrupt
-                    m_interpreter.UpdateExecutionContext(NULL);
-                    ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack"));
-                    m_options.attach_info.SetHijackListener(listener_sp);
                     process->HijackProcessEvents(listener_sp.get());
-                    error = process->Attach (m_options.attach_info);
-                    
-                    if (error.Success())
-                    {
-                        result.SetStatus (eReturnStatusSuccessContinuingNoResult);
-                        StreamString stream;
-                        StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get(), &stream);
-
-                        process->RestoreProcessEvents();
-
-                        result.SetDidChangeProcessState (true);
-                        
-                        if (stream.GetData())
-                            result.AppendMessage(stream.GetData());
-
-                        if (state == eStateStopped)
-                        {
-                            result.SetStatus (eReturnStatusSuccessFinishNoResult);
-                        }
-                        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.SetStatus (eReturnStatusFailed);
-                        }
-                    }
-                    else
-                    {
-                        result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
-                        result.SetStatus (eReturnStatusFailed);
-                    }
+                    error = process->Attach(m_options.attach_info);
                 }
             }
         }
-        
-        if (result.Succeeded())
+
+        if (error.Success() && process != nullptr)
         {
-            // Okay, we're done.  Last step is to warn if the executable module has changed:
-            char new_path[PATH_MAX];
-            ModuleSP new_exec_module_sp (target->GetExecutableModule());
-            if (!old_exec_module_sp)
-            {
-                // We might not have a module if we attached to a raw pid...
-                if (new_exec_module_sp)
-                {
-                    new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
-                    result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
-                }
-            }
-            else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec())
+            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)
             {
-                char old_path[PATH_MAX];
-                
-                old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX);
-                new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX);
-                
-                result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
-                                                    old_path, new_path);
+                result.SetStatus (eReturnStatusSuccessFinishNoResult);
             }
-            
-            if (!old_arch_spec.IsValid())
+            else
             {
-                result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str());
+                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.SetStatus (eReturnStatusFailed);
             }
-            else if (!old_arch_spec.IsExactMatch(target->GetArchitecture()))
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
+            result.SetStatus (eReturnStatusFailed);
+        }
+
+        if (!result.Succeeded())
+            return false;
+
+        // Okay, we're done.  Last step is to warn if the executable module has changed:
+        char new_path[PATH_MAX];
+        ModuleSP new_exec_module_sp (target->GetExecutableModule());
+        if (!old_exec_module_sp)
+        {
+            // We might not have a module if we attached to a raw pid...
+            if (new_exec_module_sp)
             {
-                result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 
-                                               old_arch_spec.GetTriple().getTriple().c_str(),
-                                               target->GetArchitecture().GetTriple().getTriple().c_str());
+                new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
+                result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
             }
+        }
+        else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec())
+        {
+            char old_path[PATH_MAX];
+
+            old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX);
+            new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX);
+
+            result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
+                                                old_path, new_path);
+        }
 
-            // This supports the use-case scenario of immediately continuing the process once attached.
-            if (m_options.attach_info.GetContinueOnceAttached())
-                m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
+        if (!old_arch_spec.IsValid())
+        {
+            result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str());
+        }
+        else if (!old_arch_spec.IsExactMatch(target->GetArchitecture()))
+        {
+            result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
+                                           old_arch_spec.GetTriple().getTriple().c_str(),
+                                           target->GetArchitecture().GetTriple().getTriple().c_str());
         }
+
+        // This supports the use-case scenario of immediately continuing the process once attached.
+        if (m_options.attach_info.GetContinueOnceAttached())
+            m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
+
         return result.Succeeded();
     }
     

Modified: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp?rev=227899&r1=227898&r2=227899&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp Mon Feb  2 18:04:35 2015
@@ -542,6 +542,9 @@ DynamicLoaderPOSIXDYLD::ComputeLoadOffse
         return LLDB_INVALID_ADDRESS;
 
     ObjectFile *exe = module->GetObjectFile();
+    if (!exe)
+        return LLDB_INVALID_ADDRESS;
+
     Address file_entry = exe->GetEntryPointAddress();
 
     if (!file_entry.IsValid())

Modified: lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp?rev=227899&r1=227898&r2=227899&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp Mon Feb  2 18:04:35 2015
@@ -765,8 +765,12 @@ PlatformPOSIX::Attach (ProcessAttachInfo
                 // Set UnixSignals appropriately.
                 process_sp->SetUnixSignals (Host::GetUnixSignals ());
 
-                ListenerSP listener_sp (new Listener("lldb.PlatformPOSIX.attach.hijack"));
-                attach_info.SetHijackListener(listener_sp);
+                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);
             }

Modified: lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp?rev=227899&r1=227898&r2=227899&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp Mon Feb  2 18:04:35 2015
@@ -665,10 +665,16 @@ PlatformRemoteGDBServer::Attach (lldb_pr
                                                                 override_hostname ? override_hostname : m_platform_hostname.c_str(),
                                                                 port + port_offset);
                         assert (connect_url_len < (int)sizeof(connect_url));
-                        error = process_sp->ConnectRemote (NULL, connect_url);
+                        error = process_sp->ConnectRemote(nullptr, connect_url);
                         if (error.Success())
+                        {
+                            auto listener = attach_info.GetHijackListener();
+                            if (listener != nullptr)
+                                process_sp->HijackProcessEvents(listener.get());
                             error = process_sp->Attach(attach_info);
-                        else if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+                        }
+
+                        if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID)
                         {
                             m_gdb_client.KillSpawnedProcess(debugserver_pid);
                         }





More information about the lldb-commits mailing list