[Lldb-commits] [PATCH] enable lldb-platform exe for platform "remote-linux"

Todd Fiala todd.fiala at gmail.com
Mon Jul 21 18:12:35 PDT 2014


This change enables lldb-platform for Linux.  In addition, it does the
following:

* fixes Host::GetLLDBPath() to work on Linux/*BSD for
ePathTypeSupportExecutableDir-relative paths.

* adds more logging and comments around lldb-platform startup and remote
lldb-platform usage.

* refactors lldb-platform remote-* support for Darwin and Linux into
PlatformPOSIX.  This, in theory, is the bulk of what is needed for *BSD to
make remote connections to lldb-platform as well (although I haven't tested
that yet).

* teaches GDBRemoteCommunication to use lldb-gdbserver for non-Apple hosts.

See attached patch for details.

Tested:
Linux - Ubuntu 14.04 x86_64, local test suite, clang-3.5-built lldb
MacOSX - OS X 10.9.4 x86_64, local test suite (x86_64 architecture), Xcode
6 Beta 3-built lldb.
-- 
-Todd
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20140721/77137cfe/attachment.html>
-------------- next part --------------
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index 0006a61..d5c91cd 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -1092,6 +1092,29 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
                         ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path));
 #endif
                     }
+#elif defined (__linux__) || defined (__FreeBSD__) || defined (__NetBSD__)
+                    // Linux/*BSD will attempt to replace a */lib with */bin as the base directory for
+                    // helper exe programs.  This will fail if the /lib and /bin directories are rooted in entirely
+                    // different trees.
+                    if (log)
+                        log->Printf ("Host::%s() attempting to derive the bin path (ePathTypeSupportExecutableDir) from this path: %s", __FUNCTION__, raw_path);
+                    char *lib_pos = ::strstr (raw_path, "/lib");
+                    if (lib_pos != nullptr)
+                    {
+                        // First terminate the raw path at the start of lib.
+                        *lib_pos = '\0';
+
+                        // Now write in bin in place of lib.
+                        ::strncpy (lib_pos, "/bin", PATH_MAX - (lib_pos - raw_path));
+
+                        if (log)
+                            log->Printf ("Host::%s() derived the bin path as: %s", __FUNCTION__, raw_path);
+                    }
+                    else
+                    {
+                        if (log)
+                            log->Printf ("Host::%s() failed to find /lib/liblldb within the shared lib path, bailing on bin path construction", __FUNCTION__);
+                    }
 #endif  // #if defined (__APPLE__)
                     FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
                     g_lldb_support_exe_dir.SetCString(resolved_path);
diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp
index 847f8a0..62f95e1 100644
--- a/source/Plugins/Platform/Linux/PlatformLinux.cpp
+++ b/source/Plugins/Platform/Linux/PlatformLinux.cpp
@@ -23,6 +23,7 @@
 // Project includes
 #include "lldb/Core/Error.h"
 #include "lldb/Core/Debugger.h"
+#include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
 #include "lldb/Core/ModuleSpec.h"
@@ -45,6 +46,20 @@ static uint32_t g_initialize_count = 0;
 Platform *
 PlatformLinux::CreateInstance (bool force, const ArchSpec *arch)
 {
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
+    if (log)
+    {
+        const char *arch_name;
+        if (arch && arch->GetArchitectureName ())
+            arch_name = arch->GetArchitectureName ();
+        else
+            arch_name = "<null>";
+
+        const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";
+
+        log->Printf ("PlatformLinux::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
+    }
+
     bool create = force;
     if (create == false && arch && arch->IsValid())
     {
@@ -59,7 +74,7 @@ PlatformLinux::CreateInstance (bool force, const ArchSpec *arch)
             // Only accept "unknown" for the vendor if the host is linux and
             // it "unknown" wasn't specified (it was just returned because it
             // was NOT specified_
-            case llvm::Triple::UnknownArch:
+            case llvm::Triple::VendorType::UnknownVendor:
                 create = !arch->TripleVendorWasSpecified();
                 break;
 #endif
@@ -78,7 +93,7 @@ PlatformLinux::CreateInstance (bool force, const ArchSpec *arch)
                 // Only accept "unknown" for the OS if the host is linux and
                 // it "unknown" wasn't specified (it was just returned because it
                 // was NOT specified)
-                case llvm::Triple::UnknownOS:
+                case llvm::Triple::OSType::UnknownOS:
                     create = !arch->TripleOSWasSpecified();
                     break;
 #endif
@@ -88,8 +103,17 @@ PlatformLinux::CreateInstance (bool force, const ArchSpec *arch)
             }
         }
     }
+
     if (create)
+    {
+        if (log)
+            log->Printf ("PlatformLinux::%s() creating remote-linux platform", __FUNCTION__);
         return new PlatformLinux(false);
+    }
+
+    if (log)
+        log->Printf ("PlatformLinux::%s() aborting creation of remote-linux platform", __FUNCTION__);
+
     return NULL;
 }
 
@@ -308,8 +332,7 @@ PlatformLinux::GetFileWithUUID (const FileSpec &platform_file,
 /// Default Constructor
 //------------------------------------------------------------------
 PlatformLinux::PlatformLinux (bool is_host) :
-    Platform(is_host),  // This is the local host platform
-    m_remote_platform_sp ()
+    PlatformPOSIX(is_host)  // This is the local host platform
 {
 }
 
@@ -417,10 +440,14 @@ PlatformLinux::GetSoftwareBreakpointTrapOpcode (Target &target,
 Error
 PlatformLinux::LaunchProcess (ProcessLaunchInfo &launch_info)
 {
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
     Error error;
     
     if (IsHost())
     {
+        if (log)
+            log->Printf ("PlatformLinux::%s() launching process as host", __FUNCTION__);
+
         if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
         {
             const bool is_localhost = true;
@@ -438,11 +465,34 @@ PlatformLinux::LaunchProcess (ProcessLaunchInfo &launch_info)
     }
     else
     {
-        error.SetErrorString ("the platform is not currently connected");
+        if (m_remote_platform_sp)
+        {
+            if (log)
+                log->Printf ("PlatformLinux::%s() attempting to launch remote process", __FUNCTION__);
+            error = m_remote_platform_sp->LaunchProcess (launch_info);
+        }
+        else
+        {
+            if (log)
+                log->Printf ("PlatformLinux::%s() attempted to launch process but is not the host and no remote platform set", __FUNCTION__);
+            error.SetErrorString ("the platform is not currently connected");
+        }
     }
     return error;
 }
 
+// Linux processes can not be launched by spawning and attaching.
+bool
+PlatformLinux::CanDebugProcess ()
+{
+    // If we're the host, launch via normal host setup.
+    if (IsHost ())
+        return false;
+
+    // If we're connected, we can debug.
+    return IsConnected ();
+}
+
 lldb::ProcessSP
 PlatformLinux::Attach(ProcessAttachInfo &attach_info,
                       Debugger &debugger,
@@ -550,4 +600,3 @@ PlatformLinux::AttachNativeProcess (lldb::pid_t pid,
     return NativeProcessLinux::AttachToProcess (pid, native_delegate, process_sp);
 #endif
 }
-
diff --git a/source/Plugins/Platform/Linux/PlatformLinux.h b/source/Plugins/Platform/Linux/PlatformLinux.h
index 39b2c6b..891620d 100644
--- a/source/Plugins/Platform/Linux/PlatformLinux.h
+++ b/source/Plugins/Platform/Linux/PlatformLinux.h
@@ -14,11 +14,11 @@
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
-#include "lldb/Target/Platform.h"
+#include "Plugins/Platform/POSIX/PlatformPOSIX.h"
 
 namespace lldb_private {
 
-    class PlatformLinux : public Platform
+    class PlatformLinux : public PlatformPOSIX
     {
     public:
 
@@ -45,11 +45,11 @@ namespace lldb_private {
         static const char *
         GetPluginDescriptionStatic (bool is_host);
 
-        virtual lldb_private::ConstString
-        GetPluginName();
+        lldb_private::ConstString
+        GetPluginName() override;
         
-        virtual uint32_t
-        GetPluginVersion()
+        uint32_t
+        GetPluginVersion() override
         {
             return 1;
         }
@@ -57,51 +57,47 @@ namespace lldb_private {
         //------------------------------------------------------------
         // lldb_private::Platform functions
         //------------------------------------------------------------
-        virtual Error
+        Error
         ResolveExecutable (const FileSpec &exe_file,
                            const ArchSpec &arch,
                            lldb::ModuleSP &module_sp,
-                           const FileSpecList *module_search_paths_ptr);
+                           const FileSpecList *module_search_paths_ptr) override;
 
-        virtual const char *
-        GetDescription ()
+        const char *
+        GetDescription () override
         {
             return GetPluginDescriptionStatic(IsHost());
         }
 
-        virtual void
-        GetStatus (Stream &strm);
+        void
+        GetStatus (Stream &strm) override;
 
-        virtual Error
+        Error
         GetFileWithUUID (const FileSpec &platform_file,
-                         const UUID* uuid, FileSpec &local_file);
+                         const UUID* uuid, FileSpec &local_file) override;
 
-        virtual bool
-        GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info);
+        bool
+        GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info) override;
 
-        virtual bool
-        GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch);
+        bool
+        GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) override;
 
-        virtual size_t
+        size_t
         GetSoftwareBreakpointTrapOpcode (Target &target, 
-                                         BreakpointSite *bp_site);
+                                         BreakpointSite *bp_site) override;
 
-        virtual lldb_private::Error
-        LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
+        lldb_private::Error
+        LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info) override;
 
-        virtual lldb::ProcessSP
+        lldb::ProcessSP
         Attach(ProcessAttachInfo &attach_info, Debugger &debugger,
-               Target *target, Listener &listener, Error &error);
+               Target *target, Listener &listener, Error &error) override;
 
-        // Linux processes can not be launched by spawning and attaching.
-        virtual bool
-        CanDebugProcess ()
-        {
-            return false;
-        }
+        bool
+        CanDebugProcess () override;
 
-        virtual void
-        CalculateTrapHandlerSymbolNames ();
+        void
+        CalculateTrapHandlerSymbolNames () override;
 
         Error
         LaunchNativeProcess (
@@ -114,9 +110,6 @@ namespace lldb_private {
                              lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
                              NativeProcessProtocolSP &process_sp) override;
 
-    protected:
-        lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote darwin OS
-
     private:
         DISALLOW_COPY_AND_ASSIGN (PlatformLinux);
     };
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index 64bc2ae..9012ffa 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -591,135 +591,6 @@ PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite
 }
 
 bool
-PlatformDarwin::GetRemoteOSVersion ()
-{
-    if (m_remote_platform_sp)
-        return m_remote_platform_sp->GetOSVersion (m_major_os_version, 
-                                                   m_minor_os_version, 
-                                                   m_update_os_version);
-    return false;
-}
-
-bool
-PlatformDarwin::GetRemoteOSBuildString (std::string &s)
-{
-    if (m_remote_platform_sp)
-        return m_remote_platform_sp->GetRemoteOSBuildString (s);
-    s.clear();
-    return false;
-}
-
-bool
-PlatformDarwin::GetRemoteOSKernelDescription (std::string &s)
-{
-    if (m_remote_platform_sp)
-        return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
-    s.clear();
-    return false;
-}
-
-// Remote Platform subclasses need to override this function
-ArchSpec
-PlatformDarwin::GetRemoteSystemArchitecture ()
-{
-    if (m_remote_platform_sp)
-        return m_remote_platform_sp->GetRemoteSystemArchitecture ();
-    return ArchSpec();
-}
-
-
-const char *
-PlatformDarwin::GetHostname ()
-{
-    if (IsHost())
-        return Platform::GetHostname();
-
-    if (m_remote_platform_sp)
-        return m_remote_platform_sp->GetHostname ();
-    return NULL;
-}
-
-bool
-PlatformDarwin::IsConnected () const
-{
-    if (IsHost())
-        return true;
-    else if (m_remote_platform_sp)
-        return m_remote_platform_sp->IsConnected();
-    return false;
-}
-
-Error
-PlatformDarwin::ConnectRemote (Args& args)
-{
-    Error error;
-    if (IsHost())
-    {
-        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
-    }
-    else
-    {
-        if (!m_remote_platform_sp)
-            m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
-
-        if (m_remote_platform_sp && error.Success())
-            error = m_remote_platform_sp->ConnectRemote (args);
-        else
-            error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
-        
-        if (error.Fail())
-            m_remote_platform_sp.reset();
-    }
-    
-    if (error.Success() && m_remote_platform_sp)
-    {
-        if (m_options.get())
-        {
-            OptionGroupOptions* options = m_options.get();
-            OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r');
-            OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s');
-            OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c');
-            
-            if (m_rsync_options->m_rsync)
-            {
-                SetSupportsRSync(true);
-                SetRSyncOpts(m_rsync_options->m_rsync_opts.c_str());
-                SetRSyncPrefix(m_rsync_options->m_rsync_prefix.c_str());
-                SetIgnoresRemoteHostname(m_rsync_options->m_ignores_remote_hostname);
-            }
-            if (m_ssh_options->m_ssh)
-            {
-                SetSupportsSSH(true);
-                SetSSHOpts(m_ssh_options->m_ssh_opts.c_str());
-            }
-            SetLocalCacheDirectory(m_cache_options->m_cache_dir.c_str());
-        }
-    }
-
-    return error;
-}
-
-Error
-PlatformDarwin::DisconnectRemote ()
-{
-    Error error;
-    
-    if (IsHost())
-    {
-        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
-    }
-    else
-    {
-        if (m_remote_platform_sp)
-            error = m_remote_platform_sp->DisconnectRemote ();
-        else
-            error.SetErrorString ("the platform is not currently connected");
-    }
-    return error;
-}
-
-
-bool
 PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
 {
     bool sucess = false;
@@ -735,8 +606,6 @@ PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_in
     return sucess;
 }
 
-
-
 uint32_t
 PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info,
                                ProcessInstanceInfoList &process_infos)
@@ -776,35 +645,6 @@ PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info)
 }
 
 lldb::ProcessSP
-PlatformDarwin::DebugProcess (ProcessLaunchInfo &launch_info,
-                              Debugger &debugger,
-                              Target *target,       // Can be NULL, if NULL create a new target, else use existing one
-                              Listener &listener,
-                              Error &error)
-{
-    ProcessSP process_sp;
-    
-    if (IsHost())
-    {
-        // We are going to hand this process off to debugserver which will be in charge of setting the exit status.
-        // We still need to reap it from lldb but if we let the monitor thread also set the exit status, we set up a
-        // race between debugserver & us for who will find out about the debugged process's death.
-        launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus);
-        process_sp = Platform::DebugProcess (launch_info, debugger, target, listener, error);
-    }
-    else
-    {
-        if (m_remote_platform_sp)
-            process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, listener, error);
-        else
-            error.SetErrorString ("the platform is not currently connected");
-    }
-    return process_sp;
-    
-}
-
-
-lldb::ProcessSP
 PlatformDarwin::Attach (ProcessAttachInfo &attach_info,
                         Debugger &debugger,
                         Target *target,
@@ -855,31 +695,6 @@ PlatformDarwin::Attach (ProcessAttachInfo &attach_info,
     return process_sp;
 }
 
-const char *
-PlatformDarwin::GetUserName (uint32_t uid)
-{
-    // Check the cache in Platform in case we have already looked this uid up
-    const char *user_name = Platform::GetUserName(uid);
-    if (user_name)
-        return user_name;
-
-    if (IsRemote() && m_remote_platform_sp)
-        return m_remote_platform_sp->GetUserName(uid);
-    return NULL;
-}
-
-const char *
-PlatformDarwin::GetGroupName (uint32_t gid)
-{
-    const char *group_name = Platform::GetGroupName(gid);
-    if (group_name)
-        return group_name;
-
-    if (IsRemote() && m_remote_platform_sp)
-        return m_remote_platform_sp->GetGroupName(gid);
-    return NULL;
-}
-
 bool
 PlatformDarwin::ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp)
 {
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/source/Plugins/Platform/MacOSX/PlatformDarwin.h
index d96f11b..21529a8 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwin.h
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.h
@@ -54,37 +54,6 @@ public:
                                      lldb_private::BreakpointSite *bp_site);
 
     virtual bool
-    GetRemoteOSVersion ();
-
-    virtual bool
-    GetRemoteOSBuildString (std::string &s);
-    
-    virtual bool
-    GetRemoteOSKernelDescription (std::string &s);
-
-    // Remote Platform subclasses need to override this function
-    virtual lldb_private::ArchSpec
-    GetRemoteSystemArchitecture ();
-
-    virtual bool
-    IsConnected () const;
-
-    virtual lldb_private::Error
-    ConnectRemote (lldb_private::Args& args);
-
-    virtual lldb_private::Error
-    DisconnectRemote ();
-
-    virtual const char *
-    GetHostname ();
-
-    virtual const char *
-    GetUserName (uint32_t uid);
-    
-    virtual const char *
-    GetGroupName (uint32_t gid);
-
-    virtual bool
     GetProcessInfo (lldb::pid_t pid, 
                     lldb_private::ProcessInstanceInfo &proc_info);
     
@@ -99,13 +68,6 @@ public:
     LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
 
     virtual lldb::ProcessSP
-    DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,
-                  lldb_private::Debugger &debugger,
-                  lldb_private::Target *target,       // Can be NULL, if NULL create a new target, else use existing one
-                  lldb_private::Listener &listener,
-                  lldb_private::Error &error);
-
-    virtual lldb::ProcessSP
     Attach (lldb_private::ProcessAttachInfo &attach_info,
             lldb_private::Debugger &debugger,
             lldb_private::Target *target,       // Can be NULL, if NULL create a new target, else use existing one
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index bb07d99..f0dab8d 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -20,6 +20,7 @@
 #include "lldb/Host/File.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -57,6 +58,16 @@ PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpret
     return m_options.get();
 }
 
+bool
+PlatformPOSIX::IsConnected () const
+{
+    if (IsHost())
+        return true;
+    else if (m_remote_platform_sp)
+        return m_remote_platform_sp->IsConnected();
+    return false;
+}
+
 lldb_private::Error
 PlatformPOSIX::RunShellCommand (const char *command,           // Shouldn't be NULL
                                 const char *working_dir,       // Pass NULL to use the current working directory
@@ -589,6 +600,176 @@ PlatformPOSIX::SetRemoteWorkingDirectory(const lldb_private::ConstString &path)
         return Platform::SetRemoteWorkingDirectory(path);
 }
 
+bool
+PlatformPOSIX::GetRemoteOSVersion ()
+{
+    if (m_remote_platform_sp)
+        return m_remote_platform_sp->GetOSVersion (m_major_os_version,
+                                                   m_minor_os_version,
+                                                   m_update_os_version);
+    return false;
+}
+
+bool
+PlatformPOSIX::GetRemoteOSBuildString (std::string &s)
+{
+    if (m_remote_platform_sp)
+        return m_remote_platform_sp->GetRemoteOSBuildString (s);
+    s.clear();
+    return false;
+}
+
+bool
+PlatformPOSIX::GetRemoteOSKernelDescription (std::string &s)
+{
+    if (m_remote_platform_sp)
+        return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
+    s.clear();
+    return false;
+}
+
+// Remote Platform subclasses need to override this function
+ArchSpec
+PlatformPOSIX::GetRemoteSystemArchitecture ()
+{
+    if (m_remote_platform_sp)
+        return m_remote_platform_sp->GetRemoteSystemArchitecture ();
+    return ArchSpec();
+}
+
+const char *
+PlatformPOSIX::GetHostname ()
+{
+    if (IsHost())
+        return Platform::GetHostname();
+
+    if (m_remote_platform_sp)
+        return m_remote_platform_sp->GetHostname ();
+    return NULL;
+}
+
+const char *
+PlatformPOSIX::GetUserName (uint32_t uid)
+{
+    // Check the cache in Platform in case we have already looked this uid up
+    const char *user_name = Platform::GetUserName(uid);
+    if (user_name)
+        return user_name;
+
+    if (IsRemote() && m_remote_platform_sp)
+        return m_remote_platform_sp->GetUserName(uid);
+    return NULL;
+}
+
+const char *
+PlatformPOSIX::GetGroupName (uint32_t gid)
+{
+    const char *group_name = Platform::GetGroupName(gid);
+    if (group_name)
+        return group_name;
+
+    if (IsRemote() && m_remote_platform_sp)
+        return m_remote_platform_sp->GetGroupName(gid);
+    return NULL;
+}
+
+Error
+PlatformPOSIX::ConnectRemote (Args& args)
+{
+    Error error;
+    if (IsHost())
+    {
+        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
+    }
+    else
+    {
+        if (!m_remote_platform_sp)
+            m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
+
+        if (m_remote_platform_sp && error.Success())
+            error = m_remote_platform_sp->ConnectRemote (args);
+        else
+            error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
+
+        if (error.Fail())
+            m_remote_platform_sp.reset();
+    }
+
+    if (error.Success() && m_remote_platform_sp)
+    {
+        if (m_options.get())
+        {
+            OptionGroupOptions* options = m_options.get();
+            OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r');
+            OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s');
+            OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c');
+
+            if (m_rsync_options->m_rsync)
+            {
+                SetSupportsRSync(true);
+                SetRSyncOpts(m_rsync_options->m_rsync_opts.c_str());
+                SetRSyncPrefix(m_rsync_options->m_rsync_prefix.c_str());
+                SetIgnoresRemoteHostname(m_rsync_options->m_ignores_remote_hostname);
+            }
+            if (m_ssh_options->m_ssh)
+            {
+                SetSupportsSSH(true);
+                SetSSHOpts(m_ssh_options->m_ssh_opts.c_str());
+            }
+            SetLocalCacheDirectory(m_cache_options->m_cache_dir.c_str());
+        }
+    }
+
+    return error;
+}
+
+Error
+PlatformPOSIX::DisconnectRemote ()
+{
+    Error error;
+
+    if (IsHost())
+    {
+        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
+    }
+    else
+    {
+        if (m_remote_platform_sp)
+            error = m_remote_platform_sp->DisconnectRemote ();
+        else
+            error.SetErrorString ("the platform is not currently connected");
+    }
+    return error;
+}
+
+lldb::ProcessSP
+PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info,
+                              Debugger &debugger,
+                              Target *target,       // Can be NULL, if NULL create a new target, else use existing one
+                              Listener &listener,
+                              Error &error)
+{
+    ProcessSP process_sp;
+
+    if (IsHost())
+    {
+        // We are going to hand this process off to debugserver which will be in charge of setting the exit status.
+        // We still need to reap it from lldb but if we let the monitor thread also set the exit status, we set up a
+        // race between debugserver & us for who will find out about the debugged process's death.
+        launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus);
+        process_sp = Platform::DebugProcess (launch_info, debugger, target, listener, error);
+    }
+    else
+    {
+        if (m_remote_platform_sp)
+            process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, listener, error);
+        else
+            error.SetErrorString ("the platform is not currently connected");
+    }
+    return process_sp;
+
+}
+
 void
 PlatformPOSIX::CalculateTrapHandlerSymbolNames ()
 {   
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 130c84b..374e364 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -33,7 +33,16 @@ public:
     //------------------------------------------------------------
     virtual lldb_private::OptionGroupOptions*
     GetConnectionOptions (lldb_private::CommandInterpreter& interpreter);
-    
+
+    const char *
+    GetHostname () override;
+
+    const char *
+    GetUserName (uint32_t uid) override;
+
+    const char *
+    GetGroupName (uint32_t gid) override;
+
     virtual lldb_private::Error
     PutFile (const lldb_private::FileSpec& source,
              const lldb_private::FileSpec& destination,
@@ -79,7 +88,22 @@ public:
     
     virtual bool
     SetRemoteWorkingDirectory(const lldb_private::ConstString &path);
-    
+
+    bool
+    GetRemoteOSVersion () override;
+
+    bool
+    GetRemoteOSBuildString (std::string &s) override;
+
+    bool
+    GetRemoteOSKernelDescription (std::string &s) override;
+
+    lldb_private::ArchSpec
+    GetRemoteSystemArchitecture () override;
+
+    bool
+    IsConnected () const override;
+
     virtual lldb_private::Error
     RunShellCommand (const char *command,           // Shouldn't be NULL
                      const char *working_dir,       // Pass NULL to use the current working directory
@@ -103,6 +127,13 @@ public:
     virtual lldb_private::Error
     Unlink (const char *path);
 
+    lldb::ProcessSP
+    DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,
+                  lldb_private::Debugger &debugger,
+                  lldb_private::Target *target,       // Can be NULL, if NULL create a new target, else use existing one
+                  lldb_private::Listener &listener,
+                  lldb_private::Error &error) override;
+
     virtual std::string
     GetPlatformSpecificConnectionInformation();
     
@@ -114,6 +145,12 @@ public:
     virtual void
     CalculateTrapHandlerSymbolNames ();
 
+    lldb_private::Error
+    ConnectRemote (lldb_private::Args& args) override;
+
+    lldb_private::Error
+    DisconnectRemote () override;
+
 protected:
     std::unique_ptr<lldb_private::OptionGroupOptions> m_options;
         
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 6641998..4e9ec8b 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -24,6 +24,7 @@
 #include "lldb/Core/ConnectionFileDescriptor.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
 #include "lldb/Core/PluginManager.h"
@@ -346,9 +347,13 @@ PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &p
 Error
 PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
 {
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
     Error error;
     lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
-    
+
+    if (log)
+        log->Printf ("PlatformRemoteGDBServer::%s() called", __FUNCTION__);
+
     m_gdb_client.SetSTDIN ("/dev/null");
     m_gdb_client.SetSTDOUT ("/dev/null");
     m_gdb_client.SetSTDERR ("/dev/null");
@@ -378,7 +383,9 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
     const char *arch_triple = arch_spec.GetTriple().str().c_str();
     
     m_gdb_client.SendLaunchArchPacket(arch_triple);
-    
+    if (log)
+        log->Printf ("PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", __FUNCTION__, arch_triple ? arch_triple : "<NULL>");
+
     const uint32_t old_packet_timeout = m_gdb_client.SetPacketTimeout (5);
     int arg_packet_err = m_gdb_client.SendArgumentsPacket (launch_info);
     m_gdb_client.SetPacketTimeout (old_packet_timeout);
@@ -389,11 +396,23 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
         {
             pid = m_gdb_client.GetCurrentProcessID ();
             if (pid != LLDB_INVALID_PROCESS_ID)
+            {
                 launch_info.SetProcessID (pid);
+                if (log)
+                    log->Printf ("PlatformRemoteGDBServer::%s() pid %" PRIu64 " launched successfully", __FUNCTION__, pid);
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("PlatformRemoteGDBServer::%s() launch succeeded but we didn't get a valid process id back!", __FUNCTION__);
+                // FIXME isn't this an error condition? Do we need to set an error here?  Check with Greg.
+            }
         }
         else
         {
             error.SetErrorString (error_str.c_str());
+            if (log)
+                log->Printf ("PlatformRemoteGDBServer::%s() launch failed: %s", __FUNCTION__, error.AsCString ());
         }
     }
     else
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index d3ab3b8..be90eb2 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -29,7 +29,11 @@
 // Project includes
 #include "ProcessGDBRemoteLog.h"
 
-#define DEBUGSERVER_BASENAME    "debugserver"
+#if defined(__APPLE__)
+# define DEBUGSERVER_BASENAME    "debugserver"
+#else
+# define DEBUGSERVER_BASENAME    "lldb-gdbserver"
+#endif
 
 using namespace lldb;
 using namespace lldb_private;
@@ -650,6 +654,10 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
                                                  lldb_private::ProcessLaunchInfo &launch_info,
                                                  uint16_t &out_port)
 {
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+    if (log)
+        log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port);
+
     out_port = in_port;
     Error error;
     // If we locate debugserver, keep that located version around
@@ -662,7 +670,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
     // to the debugserver to use and use it if we do.
     const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
     if (env_debugserver_path)
+    {
         debugserver_file_spec.SetFile (env_debugserver_path, false);
+        if (log)
+            log->Printf ("GDBRemoteCommunication::%s() gdb-remote stub exe path set from environment variable: %s", __FUNCTION__, env_debugserver_path);
+    }
     else
         debugserver_file_spec = g_debugserver_file_spec;
     bool debugserver_exists = debugserver_file_spec.Exists();
@@ -676,10 +688,16 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
             debugserver_exists = debugserver_file_spec.Exists();
             if (debugserver_exists)
             {
+                if (log)
+                    log->Printf ("GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
+
                 g_debugserver_file_spec = debugserver_file_spec;
             }
             else
             {
+                if (log)
+                    log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
+
                 g_debugserver_file_spec.Clear();
                 debugserver_file_spec.Clear();
             }
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 8cda558..b9d59e7 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -1824,14 +1824,18 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
 #ifdef _WIN32
     return SendErrorResponse(9);
 #else
+    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+
     // Spawn a local debugserver as a platform so we can then attach or launch
     // a process...
 
     if (m_is_platform)
     {
+        if (log)
+            log->Printf ("GDBRemoteCommunicationServer::%s() called", __FUNCTION__);
+
         // Sleep and wait a bit for debugserver to start to listen...
         ConnectionFileDescriptor file_conn;
-        Error error;
         std::string hostname;
         // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
         // with the TMPDIR environment variable
@@ -1852,53 +1856,57 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
         // Spawn a new thread to accept the port that gets bound after
         // binding to port 0 (zero).
 
-        if (error.Success())
-        {
-            // Spawn a debugserver and try to get the port it listens to.
-            ProcessLaunchInfo debugserver_launch_info;
-            if (hostname.empty())
-                hostname = "127.0.0.1";
-            Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
-            if (log)
-                log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
+        // Spawn a debugserver and try to get the port it listens to.
+        ProcessLaunchInfo debugserver_launch_info;
+        if (hostname.empty())
+            hostname = "127.0.0.1";
+        if (log)
+            log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
 
-            debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
-            
-            error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
-                                             port,
-                                             debugserver_launch_info,
-                                             port);
+        debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
 
-            lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+        Error error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
+                                         port,
+                                         debugserver_launch_info,
+                                         port);
 
+        lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
 
-            if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
-            {
-                Mutex::Locker locker (m_spawned_pids_mutex);
-                m_spawned_pids.insert(debugserver_pid);
-                if (port > 0)
-                    AssociatePortWithProcess(port, debugserver_pid);
-            }
-            else
-            {
-                if (port > 0)
-                    FreePort (port);
-            }
 
-            if (error.Success())
-            {
-                char response[256];
-                const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
-                assert (response_len < (int)sizeof(response));
-                PacketResult packet_result = SendPacketNoLock (response, response_len);
+        if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+        {
+            Mutex::Locker locker (m_spawned_pids_mutex);
+            m_spawned_pids.insert(debugserver_pid);
+            if (port > 0)
+                AssociatePortWithProcess(port, debugserver_pid);
+        }
+        else
+        {
+            if (port > 0)
+                FreePort (port);
+        }
 
-                if (packet_result != PacketResult::Success)
-                {
-                    if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
-                        ::kill (debugserver_pid, SIGINT);
-                }
-                return packet_result;
+        if (error.Success())
+        {
+            if (log)
+                log->Printf ("GDBRemoteCommunicationServer::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
+
+            char response[256];
+            const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
+            assert (response_len < (int)sizeof(response));
+            PacketResult packet_result = SendPacketNoLock (response, response_len);
+
+            if (packet_result != PacketResult::Success)
+            {
+                if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+                    ::kill (debugserver_pid, SIGINT);
             }
+            return packet_result;
+        }
+        else
+        {
+            if (log)
+                log->Printf ("GDBRemoteCommunicationServer::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
         }
     }
     return SendErrorResponse (9);
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index bc46df9..d48df88 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -2368,7 +2368,8 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
     
     if (!launch_info.GetArchitecture().IsValid())
         launch_info.GetArchitecture() = GetArchitecture();
-    
+
+    // If we're not already connected to the process, and if we have a platform that can launch a process for debugging, go ahead and do that here.
     if (state != eStateConnected && platform_sp && platform_sp->CanDebugProcess ())
     {
         m_process_sp = GetPlatform()->DebugProcess (launch_info,
@@ -2385,10 +2386,12 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
         }
         else
         {
+            // Use a Process plugin to construct the process.
             const char *plugin_name = launch_info.GetProcessPluginName();
             CreateProcess (listener, plugin_name, NULL);
         }
-        
+
+        // Since we didn't have a platform launch the process, launch it here.
         if (m_process_sp)
             error = m_process_sp->Launch (launch_info);
     }


More information about the lldb-commits mailing list