[Lldb-commits] [lldb] r124846 - in /lldb/trunk: include/lldb/ include/lldb/Core/ include/lldb/Target/ source/Commands/ source/Core/ source/Host/common/ source/Interpreter/ source/Plugins/DynamicLoader/MacOSX-DYLD/ source/Plugins/ObjectContainer/Universal-Mach-O/ source/Plugins/Process/gdb-remote/ source/Target/ tools/driver/

Greg Clayton gclayton at apple.com
Thu Feb 3 17:58:07 PST 2011


Author: gclayton
Date: Thu Feb  3 19:58:07 2011
New Revision: 124846

URL: http://llvm.org/viewvc/llvm-project?rev=124846&view=rev
Log:
Added support for attaching to a remote debug server with the new command:
(lldb) process connect <remote-url>

Currently when you specify a file with the file command it helps us to find
a process plug-in that is suitable for debugging. If you specify a file you
can rely upon this to find the correct debugger plug-in:

% lldb a.out
Current executable set to 'a.out' (x86_64).
(lldb) process connect connect://localhost:2345
...

If you don't specify a file, you will need to specify the plug-in name that
you wish to use:

% lldb
(lldb) process connect --plugin process.gdb-remote connect://localhost:2345

Other connection URL examples:

(lldb) process connect connect://localhost:2345
(lldb) process connect tcp://127.0.0.1
(lldb) process connect file:///dev/ttyS1

We are currently treating the "connect://host:port" as a way to do raw socket
connections. If there is a URL for this already, please let me know and we
will adopt it.

So now you can connect to a remote debug server with the ProcessGDBRemote
plug-in. After connection, it will ask for the pid info using the "qC" packet
and if it responds with a valid process ID, it will be equivalent to attaching.
If it response with an error or invalid process ID, the LLDB process will be
in a new state: eStateConnected. This allows us to then download a program or
specify the program to run (using the 'A' packet), or specify a process to
attach to (using the "vAttach" packets), or query info about the processes
that might be available.



Modified:
    lldb/trunk/include/lldb/Core/ArchSpec.h
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/include/lldb/lldb-enumerations.h
    lldb/trunk/source/Commands/CommandObjectProcess.cpp
    lldb/trunk/source/Core/ArchSpec.cpp
    lldb/trunk/source/Core/State.cpp
    lldb/trunk/source/Host/common/Host.cpp
    lldb/trunk/source/Interpreter/CommandObject.cpp
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
    lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/trunk/source/Target/Process.cpp
    lldb/trunk/tools/driver/Driver.cpp

Modified: lldb/trunk/include/lldb/Core/ArchSpec.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ArchSpec.h?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ArchSpec.h (original)
+++ lldb/trunk/include/lldb/Core/ArchSpec.h Thu Feb  3 19:58:07 2011
@@ -262,23 +262,12 @@
     /// @param[in] subtype The new CPU subtype
     //------------------------------------------------------------------
     void
-    SetArch (uint32_t cpu, uint32_t subtype);
-
-    //------------------------------------------------------------------
-    /// Change the CPU subtype given a new value of the CPU subtype.
-    ///
-    /// @param[in] subtype The new CPU subtype.
-    //------------------------------------------------------------------
-    void
-    SetCPUSubtype (uint32_t subtype);
-
-    //------------------------------------------------------------------
-    /// Change the CPU type given a new value of the CPU type.
-    ///
-    /// @param[in] cpu The new CPU type.
-    //------------------------------------------------------------------
-    void
-    SetCPUType (uint32_t cpu);
+    SetMachOArch (uint32_t cpu, uint32_t sub)
+    {
+        m_type = lldb::eArchTypeMachO;
+        m_cpu = cpu;
+        m_sub = sub;
+    }
 
     //------------------------------------------------------------------
     /// Returns the default endianness of the architecture.

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Thu Feb  3 19:58:07 2011
@@ -595,6 +595,8 @@
     virtual Error
     Attach (const char *process_name, bool wait_for_launch);
     
+    virtual Error
+    ConnectRemote (const char *remote_url);
     //------------------------------------------------------------------
     /// List the processes matching the given partial name.
     ///
@@ -856,6 +858,14 @@
         return Error(); 
     }
 
+    virtual Error
+    DoConnectRemote (const char *remote_url)
+    {
+        Error error;
+        error.SetErrorString ("remote connections are not supported");
+        return error;
+    }
+
     //------------------------------------------------------------------
     /// Attach to an existing process using a process ID.
     ///

Modified: lldb/trunk/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Thu Feb  3 19:58:07 2011
@@ -18,16 +18,19 @@
 typedef enum StateType
 {
     eStateInvalid = 0,
-    eStateUnloaded,
-    eStateAttaching,
-    eStateLaunching,
-    eStateStopped,
-    eStateRunning,
-    eStateStepping,
-    eStateCrashed,
-    eStateDetached,
-    eStateExited,
-    eStateSuspended
+    eStateUnloaded,     ///< Process is object is valid, but not currently loaded
+    eStateConnected,    ///< Process is connected to remote debug services, but not launched or attached to anything yet
+    eStateAttaching,    ///< Process is currently trying to attach
+    eStateLaunching,    ///< Process is in the process of launching
+    eStateStopped,      ///< Process or thread is stopped and can be examined.
+    eStateRunning,      ///< Process or thread is running and can't be examined.
+    eStateStepping,     ///< Process or thread is in the process of stepping and can not be examined.
+    eStateCrashed,      ///< Process or thread has crashed and can be examined.
+    eStateDetached,     ///< Process has been detached and can't be examined.
+    eStateExited,       ///< Process has exited and can't be examined.
+    eStateSuspended     ///< Process or thread is in a suspended state as far
+                        ///< as the debugger is concerned while other processes
+                        ///< or threads get the chance to run.
 } StateType;
 
 //----------------------------------------------------------------------

Modified: lldb/trunk/source/Commands/CommandObjectProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectProcess.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectProcess.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectProcess.cpp Thu Feb  3 19:58:07 2011
@@ -572,7 +572,7 @@
             target = new_target_sp.get();
             if (target == NULL || error.Fail())
             {
-                result.AppendError(error.AsCString("Error creating empty target"));
+                result.AppendError(error.AsCString("Error creating target"));
                 return false;
             }
             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
@@ -930,6 +930,182 @@
 };
 
 //-------------------------------------------------------------------------
+// CommandObjectProcessConnect
+//-------------------------------------------------------------------------
+#pragma mark CommandObjectProcessConnect
+
+class CommandObjectProcessConnect : public CommandObject
+{
+public:
+    
+    class CommandOptions : public Options
+    {
+    public:
+        
+        CommandOptions () :
+        Options()
+        {
+            // Keep default values of all options in one place: ResetOptionValues ()
+            ResetOptionValues ();
+        }
+        
+        ~CommandOptions ()
+        {
+        }
+        
+        Error
+        SetOptionValue (int option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+            
+            switch (short_option)
+            {
+            case 'p':   
+                plugin_name.assign (option_arg);    
+                break;
+
+            default:
+                error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+                break;
+            }
+            return error;
+        }
+        
+        void
+        ResetOptionValues ()
+        {
+            Options::ResetOptionValues();
+            plugin_name.clear();
+        }
+        
+        const lldb::OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+        
+        // Options table: Required for subclasses of Options.
+        
+        static lldb::OptionDefinition g_option_table[];
+        
+        // Instance variables to hold the values for command options.
+        
+        std::string plugin_name;        
+    };
+
+    CommandObjectProcessConnect (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "process connect",
+                   "Connect to a remote debug service.",
+                   "process connect <remote-url>",
+                   0)
+    {
+    }
+    
+    ~CommandObjectProcessConnect ()
+    {
+    }
+
+    
+    bool
+    Execute (Args& command,
+             CommandReturnObject &result)
+    {
+        
+        TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
+        Error error;        
+        Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+        if (process)
+        {
+            if (process->IsAlive())
+            {
+                result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before connecting.\n", 
+                                              process->GetID());
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+        }
+        
+        if (!target_sp)
+        {
+            // If there isn't a current target create one.
+            FileSpec emptyFileSpec;
+            ArchSpec emptyArchSpec;
+            
+            error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 
+                                                                              emptyFileSpec,
+                                                                              emptyArchSpec, 
+                                                                              NULL, 
+                                                                              false,
+                                                                              target_sp);
+            if (!target_sp || error.Fail())
+            {
+                result.AppendError(error.AsCString("Error creating target"));
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            }
+            m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
+        }
+        
+        if (command.GetArgumentCount() == 1)
+        {
+            const char *plugin_name = NULL;
+            if (!m_options.plugin_name.empty())
+                plugin_name = m_options.plugin_name.c_str();
+
+            const char *remote_url = command.GetArgumentAtIndex(0);
+            process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
+            
+            if (process)
+            {
+                error = process->ConnectRemote (remote_url);
+
+                if (error.Fail())
+                {
+                    result.AppendError(error.AsCString("Remote connect failed"));
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+            }
+            else
+            {
+                result.AppendErrorWithFormat ("Unable to find process plug-in for remote URL '%s'.\nPlease specify a process plug-in name with the --plugin option, or specify an object file using the \"file\" command: \n", 
+                                              m_cmd_name.c_str(),
+                                              m_cmd_syntax.c_str());
+                result.SetStatus (eReturnStatusFailed);
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: \n", 
+                                          m_cmd_name.c_str(),
+                                          m_cmd_syntax.c_str());
+            result.SetStatus (eReturnStatusFailed);
+        }
+        return result.Succeeded();
+    }
+
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+    
+protected:
+    
+    CommandOptions m_options;
+};
+
+
+lldb::OptionDefinition
+CommandObjectProcessConnect::CommandOptions::g_option_table[] =
+{
+    { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
+    { 0,                false, NULL,      0 , 0,                 NULL, 0, eArgTypeNone,   NULL }
+};
+
+//-------------------------------------------------------------------------
 // CommandObjectProcessLoad
 //-------------------------------------------------------------------------
 #pragma mark CommandObjectProcessLoad
@@ -1656,6 +1832,7 @@
     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
+    LoadSubCommand ("connect",     CommandObjectSP (new CommandObjectProcessConnect (interpreter)));
     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
     LoadSubCommand ("load",        CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
     LoadSubCommand ("unload",      CommandObjectSP (new CommandObjectProcessUnload (interpreter)));

Modified: lldb/trunk/source/Core/ArchSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ArchSpec.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Core/ArchSpec.cpp (original)
+++ lldb/trunk/source/Core/ArchSpec.cpp Thu Feb  3 19:58:07 2011
@@ -1776,34 +1776,6 @@
     return false;
 }
 
-//----------------------------------------------------------------------
-// CPU type and subtype set accessor.
-//----------------------------------------------------------------------
-void
-ArchSpec::SetArch (uint32_t cpu_type, uint32_t cpu_subtype)
-{
-    m_cpu = cpu_type;
-    m_sub = cpu_subtype;
-}
-
-//----------------------------------------------------------------------
-// CPU type set accessor.
-//----------------------------------------------------------------------
-void
-ArchSpec::SetCPUType (uint32_t cpu)
-{
-    m_cpu = cpu;
-}
-
-//----------------------------------------------------------------------
-// CPU subtype set accessor.
-//----------------------------------------------------------------------
-void
-ArchSpec::SetCPUSubtype (uint32_t subtype)
-{
-    m_sub = subtype;
-}
-
 ByteOrder
 ArchSpec::GetDefaultEndian () const
 {

Modified: lldb/trunk/source/Core/State.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/State.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Core/State.cpp (original)
+++ lldb/trunk/source/Core/State.cpp Thu Feb  3 19:58:07 2011
@@ -24,6 +24,7 @@
     {
     case eStateInvalid:     return "invalid";
     case eStateUnloaded:    return "unloaded";
+    case eStateConnected:   return "connected";
     case eStateAttaching:   return "attaching";
     case eStateLaunching:   return "launching";
     case eStateStopped:     return "stopped";
@@ -50,6 +51,7 @@
     case eStateStepping:
         return true;
 
+    case eStateConnected:
     case eStateDetached:
     case eStateInvalid:
     case eStateUnloaded:
@@ -69,6 +71,7 @@
     switch (state)
     {
     case eStateInvalid:
+    case eStateConnected:
     case eStateAttaching:
     case eStateLaunching:
     case eStateRunning:

Modified: lldb/trunk/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Host.cpp (original)
+++ lldb/trunk/source/Host/common/Host.cpp Thu Feb  3 19:58:07 2011
@@ -229,7 +229,7 @@
         {
             len = sizeof(cpusubtype);
             if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
-                g_host_arch.SetArch(cputype, cpusubtype);
+                g_host_arch.SetMachOArch (cputype, cpusubtype);
             
             len = sizeof (is_64_bit_capable);
             if  (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)

Modified: lldb/trunk/source/Interpreter/CommandObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObject.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObject.cpp Thu Feb  3 19:58:07 2011
@@ -217,48 +217,49 @@
             args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
     }
 
-    Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
-    if (process == NULL)
+    if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
     {
-        if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
+        Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+        if (process == NULL)
         {
             result.AppendError ("Process must exist.");
             result.SetStatus (eReturnStatusFailed);
             return false;
         }
-    }
-    else
-    {
-        StateType state = process->GetState();
-        
-        switch (state)
+        else
         {
-        
-        case eStateAttaching:
-        case eStateLaunching:
-        case eStateSuspended:
-        case eStateCrashed:
-        case eStateStopped:
-            break;
-        
-        case eStateDetached:
-        case eStateExited:
-        case eStateUnloaded:
-            if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched))
-            {
-                result.AppendError ("Process must be launched.");
-                result.SetStatus (eReturnStatusFailed);
-                return false;
-            }
-            break;
-
-        case eStateRunning:
-        case eStateStepping:
-            if (GetFlags().Test(CommandObject::eFlagProcessMustBePaused))
+            StateType state = process->GetState();
+            
+            switch (state)
             {
-                result.AppendError ("Process is running.  Use 'process interrupt' to pause execution.");
-                result.SetStatus (eReturnStatusFailed);
-                return false;
+            
+            case eStateSuspended:
+            case eStateCrashed:
+            case eStateStopped:
+                break;
+            
+            case eStateConnected:
+            case eStateAttaching:
+            case eStateLaunching:
+            case eStateDetached:
+            case eStateExited:
+            case eStateUnloaded:
+                if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched))
+                {
+                    result.AppendError ("Process must be launched.");
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+                break;
+
+            case eStateRunning:
+            case eStateStepping:
+                if (GetFlags().Test(CommandObject::eFlagProcessMustBePaused))
+                {
+                    result.AppendError ("Process is running.  Use 'process interrupt' to pause execution.");
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
             }
         }
     }

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Thu Feb  3 19:58:07 2011
@@ -1106,6 +1106,7 @@
     DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state));
     switch (state)
     {
+    case eStateConnected:
     case eStateAttaching:
     case eStateLaunching:
     case eStateInvalid:

Modified: lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp Thu Feb  3 19:58:07 2011
@@ -190,7 +190,7 @@
 {
     if (idx < m_header.nfat_arch)
     {
-        arch.SetArch(m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype);
+        arch.SetMachOArch (m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype);
         return true;
     }
     return false;

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Thu Feb  3 19:58:07 2011
@@ -836,17 +836,20 @@
         
         std::string name;
         std::string value;
+        uint32_t cpu = LLDB_INVALID_CPUTYPE;
+        uint32_t sub = 0;
+    
         while (response.GetNameColonValue(name, value))
         {
             if (name.compare("cputype") == 0)
             {
                 // exception type in big endian hex
-                m_arch.SetCPUType(Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0));
+                cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
             }
             else if (name.compare("cpusubtype") == 0)
             {
                 // exception count in big endian hex
-                m_arch.SetCPUSubtype(Args::StringToUInt32 (value.c_str(), 0, 0));
+                sub = Args::StringToUInt32 (value.c_str(), 0, 0);
             }
             else if (name.compare("ostype") == 0)
             {
@@ -871,6 +874,9 @@
                 m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
             }
         }
+        
+        if (cpu != LLDB_INVALID_CPUTYPE)
+            m_arch.SetMachOArch (cpu, sub);
     }
     return HostInfoIsValid();
 }

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Thu Feb  3 19:58:07 2011
@@ -354,6 +354,56 @@
 }
 
 Error
+ProcessGDBRemote::DoConnectRemote (const char *remote_url)
+{
+    Error error (WillLaunchOrAttach ());
+    
+    if (error.Fail())
+        return error;
+
+    if (strncmp (remote_url, "connect://", strlen ("connect://")) == 0)
+    {
+        error = ConnectToDebugserver (remote_url);
+    }
+    else
+    {
+        error.SetErrorStringWithFormat ("unsupported remote url: %s", remote_url);
+    }
+
+    if (error.Fail())
+        return error;
+    StartAsyncThread ();
+
+    lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID (m_packet_timeout);
+    if (pid == LLDB_INVALID_PROCESS_ID)
+    {
+        // We don't have a valid process ID, so note that we are connected
+        // and could now request to launch or attach, or get remote process 
+        // listings...
+        SetPrivateState (eStateConnected);
+    }
+    else
+    {
+        // We have a valid process
+        SetID (pid);
+        StringExtractorGDBRemote response;
+        if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, response, m_packet_timeout, false))
+        {
+            const StateType state = SetThreadStopInfo (response);
+            if (state == eStateStopped)
+            {
+                SetPrivateState (state);
+            }
+            else
+                error.SetErrorStringWithFormat ("Process %i was reported after connecting to '%s', but state was not stopped: %s", pid, remote_url, StateAsCString (state));
+        }
+        else
+            error.SetErrorStringWithFormat ("Process %i was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url);
+    }
+    return error;
+}
+
+Error
 ProcessGDBRemote::WillLaunchOrAttach ()
 {
     Error error;
@@ -394,6 +444,8 @@
         ArchSpec inferior_arch(module->GetArchitecture());
         char host_port[128];
         snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
+        char connect_url[128];
+        snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
 
         const bool launch_process = true;
         bool start_debugserver_with_inferior_args = false;
@@ -417,7 +469,7 @@
             if (error.Fail())
                 return error;
 
-            error = ConnectToDebugserver (host_port);
+            error = ConnectToDebugserver (connect_url);
             if (error.Success())
             {
                 SetID (m_gdb_comm.GetCurrentProcessID (m_packet_timeout));
@@ -441,7 +493,7 @@
             if (error.Fail())
                 return error;
 
-            error = ConnectToDebugserver (host_port);
+            error = ConnectToDebugserver (connect_url);
             if (error.Success())
             {
                 // Send the environment and the program + arguments after we connect
@@ -515,20 +567,18 @@
 
 
 Error
-ProcessGDBRemote::ConnectToDebugserver (const char *host_port)
+ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
 {
     Error error;
     // Sleep and wait a bit for debugserver to start to listen...
     std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
     if (conn_ap.get())
     {
-        std::string connect_url("connect://");
-        connect_url.append (host_port);
         const uint32_t max_retry_count = 50;
         uint32_t retry_count = 0;
         while (!m_gdb_comm.IsConnected())
         {
-            if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
+            if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
             {
                 m_gdb_comm.SetConnection (conn_ap.release());
                 break;
@@ -596,21 +646,31 @@
 
         StreamString strm;
 
-        ArchSpec inferior_arch;
+        ArchSpec inferior_arch (m_gdb_comm.GetHostArchitecture());
+
         // See if the GDB server supports the qHostInfo information
         const char *vendor = m_gdb_comm.GetVendorString().AsCString();
         const char *os_type = m_gdb_comm.GetOSString().AsCString();
-        ArchSpec arch_spec (GetTarget().GetArchitecture());
-        
-        if (arch_spec.IsValid() && arch_spec == ArchSpec ("arm"))
+        const ArchSpec target_arch (GetTarget().GetArchitecture());
+        const ArchSpec arm_any("arm");
+        bool set_target_arch = true;
+        if (target_arch.IsValid())
         {
-            // For ARM we can't trust the arch of the process as it could
-            // have an armv6 object file, but be running on armv7 kernel.
-            inferior_arch = m_gdb_comm.GetHostArchitecture();
+            if (inferior_arch == arm_any)
+            {
+                // For ARM we can't trust the arch of the process as it could
+                // have an armv6 object file, but be running on armv7 kernel.
+                // So we only set the ARM architecture if the target isn't set
+                // to ARM already...
+                if (target_arch == arm_any)
+                {
+                    inferior_arch = target_arch;
+                    set_target_arch = false;
+                }
+            }
         }
-        
-        if (!inferior_arch.IsValid())
-            inferior_arch = arch_spec;
+        if (set_target_arch)
+            GetTarget().SetArchitecture (inferior_arch);
 
         if (vendor == NULL)
             vendor = Host::GetVendorString().AsCString("apple");
@@ -652,6 +712,9 @@
     {
         char host_port[128];
         snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
+        char connect_url[128];
+        snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
+
         error = StartDebugserverProcess (host_port,                 // debugserver_url
                                          NULL,                      // inferior_argv
                                          NULL,                      // inferior_envp
@@ -676,7 +739,7 @@
         }
         else
         {
-            error = ConnectToDebugserver (host_port);
+            error = ConnectToDebugserver (connect_url);
             if (error.Success())
             {
                 char packet[64];
@@ -722,9 +785,13 @@
     //LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
     if (process_name && process_name[0])
     {
-        char host_port[128];
         ArchSpec arch_spec = GetTarget().GetArchitecture();
+
+        char host_port[128];
         snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
+        char connect_url[128];
+        snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
+
         error = StartDebugserverProcess (host_port,                 // debugserver_url
                                          NULL,                      // inferior_argv
                                          NULL,                      // inferior_envp
@@ -748,7 +815,7 @@
         }
         else
         {
-            error = ConnectToDebugserver (host_port);
+            error = ConnectToDebugserver (connect_url);
             if (error.Success())
             {
                 StreamString packet;
@@ -772,9 +839,9 @@
 void
 ProcessGDBRemote::DidAttach ()
 {
+    DidLaunchOrAttach ();
     if (m_dynamic_loader_ap.get())
         m_dynamic_loader_ap->DidAttach();
-    DidLaunchOrAttach ();
 }
 
 Error

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Thu Feb  3 19:58:07 2011
@@ -95,6 +95,9 @@
     virtual lldb_private::Error
     WillAttachToProcessWithName (const char *process_name, bool wait_for_launch);
 
+    virtual lldb_private::Error
+    DoConnectRemote (const char *remote_url);
+    
     lldb_private::Error
     WillLaunchOrAttach ();
 

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Thu Feb  3 19:58:07 2011
@@ -1737,6 +1737,49 @@
 }
 
 Error
+Process::ConnectRemote (const char *remote_url)
+{
+    m_target_triple.Clear();
+    m_abi_sp.reset();
+    m_process_input_reader.reset();
+    
+    // Find the process and its architecture.  Make sure it matches the architecture
+    // of the current Target, and if not adjust it.
+    
+    Error error (DoConnectRemote (remote_url));
+    if (error.Success())
+    {
+        SetNextEventAction(new Process::AttachCompletionHandler(this));
+        StartPrivateStateThread();
+//        TimeValue timeout;
+//        timeout = TimeValue::Now();
+//        timeout.OffsetWithMicroSeconds(000);
+//        EventSP event_sp;
+//        StateType state = WaitForProcessStopPrivate(NULL, event_sp);
+//        
+//        if (state == eStateStopped || state == eStateCrashed)
+//        {
+//            DidLaunch ();
+//            
+//            // This delays passing the stopped event to listeners till DidLaunch gets
+//            // a chance to complete...
+//            HandlePrivateEvent (event_sp);
+//            StartPrivateStateThread ();
+//        }
+//        else if (state == eStateExited)
+//        {
+//            // We exited while trying to launch somehow.  Don't call DidLaunch as that's
+//            // not likely to work, and return an invalid pid.
+//            HandlePrivateEvent (event_sp);
+//        }
+//
+//        StartPrivateStateThread();
+    }
+    return error;
+}
+
+
+Error
 Process::Resume ()
 {
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
@@ -1948,6 +1991,7 @@
 
     switch (state)
     {
+        case eStateConnected:
         case eStateAttaching:
         case eStateLaunching:
         case eStateDetached:

Modified: lldb/trunk/tools/driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.cpp?rev=124846&r1=124845&r2=124846&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.cpp (original)
+++ lldb/trunk/tools/driver/Driver.cpp Thu Feb  3 19:58:07 2011
@@ -822,6 +822,7 @@
         {
         case eStateInvalid:
         case eStateUnloaded:
+        case eStateConnected:
         case eStateAttaching:
         case eStateLaunching:
         case eStateStepping:





More information about the lldb-commits mailing list