Fetch module specification from remote process also

Previously the remote module sepcification was fetched only from the
remote platform. With this CL if we have a remote process then we ask it
if it have any information from a given module. It is required because
on android the dynamic linker only reports the name of the SO file and
the platform can't always find it without a full path (the process can
do it based on /proc/<pid>/maps).

Differential revision: http://reviews.llvm.org/D8547

llvm-svn: 233061
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index d9acf6c..aad69a0 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -21,6 +21,7 @@
 #include "llvm/ADT/Triple.h"
 #include "lldb/Interpreter/Args.h"
 #include "lldb/Core/Log.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/State.h"
 #include "lldb/Core/StreamGDBRemote.h"
 #include "lldb/Core/StreamString.h"
@@ -3705,20 +3706,72 @@
 }
 
 bool
-GDBRemoteCommunicationClient::GetModuleInfo (const char* module_path,
+GDBRemoteCommunicationClient::GetModuleInfo (const FileSpec& module_file_spec,
                                              const lldb_private::ArchSpec& arch_spec,
-                                             StringExtractorGDBRemote &response)
+                                             ModuleSpec &module_spec)
 {
-    if (!(module_path && module_path[0]))
+    std::string module_path = module_file_spec.GetPath ();
+    if (module_path.empty ())
         return false;
 
     StreamString packet;
     packet.PutCString("qModuleInfo:");
-    packet.PutBytesAsRawHex8(module_path, strlen(module_path));
+    packet.PutCStringAsRawHex8(module_path.c_str());
     packet.PutCString(";");
     const auto& tripple = arch_spec.GetTriple().getTriple();
     packet.PutBytesAsRawHex8(tripple.c_str(), tripple.size());
 
-    return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success &&
-        !response.IsErrorResponse ();
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) != PacketResult::Success)
+        return false;
+
+    if (response.IsErrorResponse ())
+        return false;
+
+    std::string name;
+    std::string value;
+    bool success;
+    StringExtractor extractor;
+
+    module_spec.Clear ();
+    module_spec.GetFileSpec () = module_file_spec;
+
+    while (response.GetNameColonValue (name, value))
+    {
+        if (name == "uuid" || name == "md5")
+        {
+            extractor.GetStringRef ().swap (value);
+            extractor.SetFilePos (0);
+            extractor.GetHexByteString (value);
+            module_spec.GetUUID().SetFromCString (value.c_str(), value.size() / 2);
+        }
+        else if (name == "triple")
+        {
+            extractor.GetStringRef ().swap (value);
+            extractor.SetFilePos (0);
+            extractor.GetHexByteString (value);
+            module_spec.GetArchitecture().SetTriple (value.c_str ());
+        }
+        else if (name == "file_offset")
+        {
+            const auto ival = StringConvert::ToUInt64 (value.c_str (), 0, 16, &success);
+            if (success)
+                module_spec.SetObjectOffset (ival);
+        }
+        else if (name == "file_size")
+        {
+            const auto ival = StringConvert::ToUInt64 (value.c_str (), 0, 16, &success);
+            if (success)
+                module_spec.SetObjectSize (ival);
+        }
+        else if (name == "file_path")
+        {
+            extractor.GetStringRef ().swap (value);
+            extractor.SetFilePos (0);
+            extractor.GetHexByteString (value);
+            module_spec.GetFileSpec () = FileSpec (value.c_str(), false);
+        }
+    }
+
+    return true;
 }
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 0a0f0e4..acd8a17 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -535,9 +535,9 @@
     GetThreadExtendedInfoSupported();
 
     bool
-    GetModuleInfo (const char* module_path,
+    GetModuleInfo (const lldb_private::FileSpec& module_file_spec,
                    const lldb_private::ArchSpec& arch_spec,
-                   StringExtractorGDBRemote &response);
+                   lldb_private::ModuleSpec &module_spec);
 
 protected:
 
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 74e2863..3e9ad7c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -1144,12 +1144,7 @@
     packet.GetHexByteString(triple);
     ArchSpec arch(triple.c_str());
 
-#ifdef __ANDROID__
-    const FileSpec module_path_spec = HostInfoAndroid::ResolveLibraryPath(module_path, arch);
-#else
-    const FileSpec module_path_spec(module_path.c_str(), true);
-#endif
-
+    const FileSpec module_path_spec = FindModuleFile(module_path, arch);
     const ModuleSpec module_spec(module_path_spec, arch);
 
     ModuleSpecList module_specs;
@@ -1293,3 +1288,14 @@
             response.PutCString ("ptrsize:2;");
     }
 }
+
+FileSpec
+GDBRemoteCommunicationServerCommon::FindModuleFile(const std::string& module_path,
+                                                   const ArchSpec& arch)
+{
+#ifdef __ANDROID__
+    return HostInfoAndroid::ResolveLibraryPath(module_path, arch);
+#else
+    return FileSpec(module_path.c_str(), true);
+#endif
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
index 8b5248a..8fc270f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
@@ -35,26 +35,6 @@
     virtual
     ~GDBRemoteCommunicationServerCommon();
 
-    bool
-    GetThreadSuffixSupported () override
-    {
-        return true;
-    }
-
-    //------------------------------------------------------------------
-    /// Launch a process with the current launch settings.
-    ///
-    /// This method supports running an lldb-gdbserver or similar
-    /// server in a situation where the startup code has been provided
-    /// with all the information for a child process to be launched.
-    ///
-    /// @return
-    ///     An Error object indicating the success or failure of the
-    ///     launch.
-    //------------------------------------------------------------------
-    virtual lldb_private::Error
-    LaunchProcess () = 0;
-
 protected:
     std::set<lldb::pid_t> m_spawned_pids;
     lldb_private::Mutex m_spawned_pids_mutex;
@@ -195,6 +175,29 @@
                                   return (static_cast<T*>(this)->*handler) (packet);
                               });
     }
+
+    bool
+    GetThreadSuffixSupported () override
+    {
+        return true;
+    }
+
+    //------------------------------------------------------------------
+    /// Launch a process with the current launch settings.
+    ///
+    /// This method supports running an lldb-gdbserver or similar
+    /// server in a situation where the startup code has been provided
+    /// with all the information for a child process to be launched.
+    ///
+    /// @return
+    ///     An Error object indicating the success or failure of the
+    ///     launch.
+    //------------------------------------------------------------------
+    virtual lldb_private::Error
+    LaunchProcess () = 0;
+
+    virtual lldb_private::FileSpec
+    FindModuleFile (const std::string& module_path, const lldb_private::ArchSpec& arch);
 };
 
 #endif  // liblldb_GDBRemoteCommunicationServerCommon_h_
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index d4a1643..3892f48 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -2735,3 +2735,20 @@
     m_active_auxv_buffer_sp.reset ();
 #endif
 }
+
+FileSpec
+GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string& module_path,
+                                                 const ArchSpec& arch)
+{
+    if (m_debugged_process_sp)
+    {
+        FileSpec file_spec;
+        if (m_debugged_process_sp->GetLoadedModuleFileSpec(module_path.c_str(), file_spec).Success())
+        {
+            if (file_spec.Exists())
+                return file_spec;
+        }
+    }
+
+    return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch);
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index 5c8f669..d7fc115 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -252,6 +252,9 @@
     static void
     STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
 
+    lldb_private::FileSpec
+    FindModuleFile (const std::string& module_path, const lldb_private::ArchSpec& arch) override;
+
 private:
     bool
     DebuggedProcessReaped (lldb::pid_t pid);
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 62695b4..d9912cc 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -3398,6 +3398,34 @@
     }
 }
 
+bool
+ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec,
+                                const ArchSpec& arch,
+                                ModuleSpec &module_spec)
+{
+    Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM);
+
+    if (!m_gdb_comm.GetModuleInfo (module_file_spec, arch, module_spec))
+    {
+        if (log)
+            log->Printf ("ProcessGDBRemote::%s - failed to get module info for %s:%s",
+                         __FUNCTION__, module_file_spec.GetPath ().c_str (),
+                         arch.GetTriple ().getTriple ().c_str ());
+        return false;
+    }
+
+    if (log)
+    {
+        StreamString stream;
+        module_spec.Dump (stream);
+        log->Printf ("ProcessGDBRemote::%s - got module info for (%s:%s) : %s",
+                     __FUNCTION__, module_file_spec.GetPath ().c_str (),
+                     arch.GetTriple ().getTriple ().c_str (), stream.GetString ().c_str ());
+    }
+
+    return true;
+}
+
 class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed
 {
 private:
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 736525a..8cd445e 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -236,6 +236,11 @@
     void
     SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max);
 
+    bool
+    GetModuleSpec(const lldb_private::FileSpec& module_file_spec,
+                  const lldb_private::ArchSpec& arch,
+                  lldb_private::ModuleSpec &module_spec) override;
+
 protected:
     friend class ThreadGDBRemote;
     friend class GDBRemoteCommunicationClient;