Adding support for process attach by pid on Linux.

llvm-svn: 181374
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index f5f8dd2..fc84dfd 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -1189,7 +1189,7 @@
 }
 #endif
 
-#if !defined (__APPLE__) && !defined (__FreeBSD__)
+#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined(__linux__)
 bool
 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
 {
diff --git a/lldb/source/Host/linux/Host.cpp b/lldb/source/Host/linux/Host.cpp
index cddc5db..c173a25 100644
--- a/lldb/source/Host/linux/Host.cpp
+++ b/lldb/source/Host/linux/Host.cpp
@@ -28,31 +28,11 @@
 using namespace lldb;
 using namespace lldb_private;
 
-bool
-Host::GetOSVersion(uint32_t &major, 
-                   uint32_t &minor, 
-                   uint32_t &update)
+namespace
 {
-    struct utsname un;
-    int status;
-
-    if (uname(&un))
-        return false;
-
-    status = sscanf(un.release, "%u.%u.%u", &major, &minor, &update);
-     return status == 3;
-}
-
-Error
-Host::LaunchProcess (ProcessLaunchInfo &launch_info)
-{
-    Error error;
-    assert(!"Not implemented yet!!!");
-    return error;
-}
 
 lldb::DataBufferSP
-Host::GetAuxvData(lldb_private::Process *process)
+ReadProcPseudoFile(lldb::pid_t pid, const char *name)
 {
     static const size_t path_size = 128;
     static char path[path_size];
@@ -65,7 +45,7 @@
     // dynamically generated by the kernel) which is incompatible with the
     // current ReadFileContents implementation.  Therefore we simply stream the
     // data into a DataBuffer ourselves.
-    if (snprintf(path, path_size, "/proc/%" PRIu64 "/auxv", process->GetID()) < 0)
+    if (snprintf(path, path_size, "/proc/%" PRIu64 "/%s", pid, name) < 0)
         return buf_sp;
 
     if ((fd = open(path, O_RDONLY, 0)) < 0)
@@ -96,3 +76,97 @@
 
     return buf_sp;
 }
+
+} // anonymous namespace
+
+bool
+Host::GetOSVersion(uint32_t &major,
+                   uint32_t &minor,
+                   uint32_t &update)
+{
+    struct utsname un;
+    int status;
+
+    if (uname(&un))
+        return false;
+
+    status = sscanf(un.release, "%u.%u.%u", &major, &minor, &update);
+    return status == 3;
+}
+
+Error
+Host::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+    Error error;
+    assert(!"Not implemented yet!!!");
+    return error;
+}
+
+lldb::DataBufferSP
+Host::GetAuxvData(lldb_private::Process *process)
+{
+    return ReadProcPseudoFile(process->GetID(), "auxv");
+}
+
+
+bool
+Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+    process_info.Clear();
+    process_info.SetProcessID(pid);
+
+    // Architecture is intentionally omitted because that's better resolved
+    // in other places (see ProcessPOSIX::DoAttachWithID().
+
+    // Use special code here because proc/[pid]/exe is a symbolic link.
+    char link_path[PATH_MAX];
+    char exe_path[PATH_MAX] = "";
+    if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) > 0)
+    {
+        ssize_t len = readlink(link_path, exe_path, sizeof(exe_path) - 1);
+        if (len > 0)
+            exe_path[len] = 0;
+
+        static const ssize_t deleted_len = strlen(" (deleted)");
+        if (len > deleted_len &&
+            !strcmp(exe_path + len - deleted_len, " (deleted)"))
+        {
+            exe_path[len - deleted_len] = 0;
+        }
+    }
+    process_info.GetExecutableFile().SetFile(exe_path, false);
+
+    lldb::DataBufferSP buf_sp;
+
+    // Get the process environment.
+    buf_sp = ReadProcPseudoFile(pid, "environ");
+    Args &info_env = process_info.GetEnvironmentEntries();
+    char *next_var = (char *)buf_sp->GetBytes();
+    char *end_buf = next_var + buf_sp->GetByteSize();
+    while (next_var < end_buf && 0 != *next_var)
+    {
+        info_env.AppendArgument(next_var);
+        next_var += strlen(next_var) + 1;
+    }
+
+    // Get the commond line used to start the process.
+    buf_sp = ReadProcPseudoFile(pid, "cmdline");
+
+    // Grab Arg0 first.
+    char *cmd = (char *)buf_sp->GetBytes();
+    process_info.SetArg0(cmd);
+
+    // Now process any remaining arguments.
+    Args &info_args = process_info.GetArguments();
+    char *next_arg = cmd + strlen(cmd) + 1;
+    end_buf = cmd + buf_sp->GetByteSize();
+    while (next_arg < end_buf && 0 != *next_arg)
+    {
+        info_args.AppendArgument(next_arg);
+        next_arg += strlen(next_arg) + 1;
+    }
+
+    // FIXME: Parse /proc/<pid>/status to get uid, gid, euid, egid and parent_pid
+
+    return true;
+}
\ No newline at end of file
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index e832739..3e1b529 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -59,7 +59,12 @@
       m_removed_soentries()
 {
     // Cache a copy of the executable path
-    m_process->GetTarget().GetExecutableModule().get()->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
+    if (m_process)
+    {
+        Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
+        if (exe_mod)
+            exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
+    }
 }
 
 bool
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index f010568..471843b 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -22,6 +22,7 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Platform.h"
 #include "lldb/Target/Target.h"
 
 #include "ProcessPOSIX.h"
@@ -99,7 +100,8 @@
     ModuleSP exe_module_sp(target.GetExecutableModule());
     if (exe_module_sp.get())
         return exe_module_sp->GetFileSpec().Exists();
-    return false;
+    // If there is no executable module, we return true since we might be preparing to attach.
+    return true;
 }
 
 Error
@@ -117,7 +119,38 @@
     if (!error.Success())
         return error;
 
+    PlatformSP platform_sp (m_target.GetPlatform ());
+    assert (platform_sp.get());
+    if (!platform_sp)
+        return error;  // FIXME: Detatch?
+
+    // Find out what we can about this process
+    ProcessInstanceInfo process_info;
+    platform_sp->GetProcessInfo (pid, process_info);
+
+    // Resolve the executable module
+    ModuleSP exe_module_sp;
+    FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+    error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(),
+                                           m_target.GetArchitecture(),
+                                           exe_module_sp,
+                                           executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+
+    // Fix the target architecture if necessary
+    const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
+    if (module_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(module_arch))
+        m_target.SetArchitecture(module_arch);
+
+    // Initialize the target module list
+    m_target.SetExecutableModule (exe_module_sp, true);
+
+    if (!error.Success())
+        return error;
+
+    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
+
     SetID(pid);
+
     return error;
 }