This patch combines common code from Linux and FreeBSD into
a new POSIX platform.  It also contains fixes for 64bit FreeBSD.
The patch is based on changes by Mark Peek <mp@FreeBSD.org> and
"K. Macy" <kmacy@freebsd.org> in their github repo located at
https://github.com/fbsd/lldb.
llvm-svn: 147609
diff --git a/lldb/source/Host/freebsd/Host.cpp b/lldb/source/Host/freebsd/Host.cpp
index 3d6596c..3a4174f 100644
--- a/lldb/source/Host/freebsd/Host.cpp
+++ b/lldb/source/Host/freebsd/Host.cpp
@@ -9,12 +9,18 @@
 
 // C Includes
 #include <stdio.h>
+#include <dlfcn.h>
 #include <execinfo.h>
 #include <sys/types.h>
 #include <sys/user.h>
 #include <sys/utsname.h>
 #include <sys/sysctl.h>
 
+#include <sys/ptrace.h>
+#include <sys/exec.h>
+#include <machine/elf.h>
+
+
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
@@ -26,15 +32,19 @@
 #include "lldb/Core/StreamString.h"
 #include "lldb/Target/Process.h"
 
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
 #include "llvm/Support/Host.h"
 
+
 extern "C" {
-    char **environ;
+    extern char **environ;
 }
 
 using namespace lldb;
 using namespace lldb_private;
 
+
 class FreeBSDThread
 {
 public:
@@ -77,7 +87,7 @@
         std::vector<void *> frame_buffer (max_frames, NULL);
         int count = ::backtrace (&frame_buffer[0], frame_buffer.size());
         ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd);
-        
+
         const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR);
 
         if (::lseek(backtrace_fd, 0, SEEK_SET) == 0)
@@ -101,7 +111,7 @@
 {
     char *v;
     char **var = environ;
-    for (var = environ; var != NULL; ++var) {
+    for (; var != NULL && *var != NULL; ++var) {
         v = strchr(*var, (int)'-');
         if (v == NULL)
             continue;
@@ -168,49 +178,47 @@
                       ProcessInstanceInfo &process_info)
 {
     if (process_info.ProcessIDIsValid()) {
-        int mib[3] = { CTL_KERN, KERN_PROC_ARGS, process_info.GetProcessID() };
+        int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, process_info.GetProcessID() };
 
         char arg_data[8192];
         size_t arg_data_size = sizeof(arg_data);
-        if (::sysctl (mib, 3, arg_data, &arg_data_size , NULL, 0) == 0)
+        if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0)
         {
             DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
             uint32_t offset = 0;
-            uint32_t start_offset;
-            uint32_t argc = data.GetU32 (&offset);
             const char *cstr;
-            
+
             cstr = data.GetCStr (&offset);
             if (cstr)
             {
                 process_info.GetExecutableFile().SetFile(cstr, false);
 
-                if (match_info_ptr == NULL || 
+                if (!(match_info_ptr == NULL || 
                     NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(),
                                  match_info_ptr->GetNameMatchType(),
-                                 match_info_ptr->GetProcessInfo().GetName()))
+                                 match_info_ptr->GetProcessInfo().GetName())))
+                    return false;
+
+                Args &proc_args = process_info.GetArguments();
+                while (1)
                 {
-                    // Skip NULLs
-                    while (1)
+                    const uint8_t *p = data.PeekData(offset, 1);
+                    while ((p != NULL) && (*p == '\0') && offset < arg_data_size)
                     {
-                        const uint8_t *p = data.PeekData(offset, 1);
-                        if ((p == NULL) || (*p != '\0'))
-                            break;
                         ++offset;
+                        p = data.PeekData(offset, 1);
                     }
-                    // Now extract all arguments
-                    Args &proc_args = process_info.GetArguments();
-                    for (int i=0; i<argc; ++i)
-                    {
-                        start_offset = offset;
-                        cstr = data.GetCStr(&offset);
-                        if (cstr)
-                            proc_args.AppendArgument(cstr);
-                    }
-                    return true;
+                    if (p == NULL || offset >= arg_data_size)
+                        return true;
+
+                    cstr = data.GetCStr(&offset);
+                    if (cstr)
+                        proc_args.AppendArgument(cstr);
+                    else
+                        return true;
                 }
             }
-        }
+        } 
     }
     return false;
 }
@@ -219,8 +227,8 @@
 GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info)
 {
     if (process_info.ProcessIDIsValid()) {
-        // TODO: This
-        // return true;
+        process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
+        return true;
     }
     process_info.GetArchitecture().Clear();
     return false;
@@ -249,7 +257,7 @@
                 if (proc_kinfo.ki_ngroups > 0)
                     process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]);
                 else
-                    process_info.SetEffectiveGroupID (UINT32_MAX);            
+                    process_info.SetEffectiveGroupID (UINT32_MAX);
                 return true;
             }
         }
@@ -258,7 +266,7 @@
     process_info.SetUserID (UINT32_MAX);
     process_info.SetGroupID (UINT32_MAX);
     process_info.SetEffectiveUserID (UINT32_MAX);
-    process_info.SetEffectiveGroupID (UINT32_MAX);            
+    process_info.SetEffectiveGroupID (UINT32_MAX);
     return false;
 }
 
@@ -275,3 +283,46 @@
     process_info.Clear();
     return false;
 }
+
+lldb::DataBufferSP
+Host::GetAuxvData(lldb_private::Process *process)
+{
+   int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
+   void *ps_strings_addr, *auxv_addr;
+   size_t ps_strings_size = sizeof(void *);
+   Elf_Auxinfo aux_info[AT_COUNT];
+   struct ps_strings ps_strings;
+   struct ptrace_io_desc pid;
+   DataBufferSP buf_sp;
+   std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
+
+   if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) {
+           pid.piod_op = PIOD_READ_D;
+           pid.piod_addr = &ps_strings;
+           pid.piod_offs = ps_strings_addr;
+           pid.piod_len = sizeof(ps_strings);
+           if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) {
+                   perror("failed to fetch ps_strings");
+                   buf_ap.release();
+                   goto done;
+           }
+
+           auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1;
+
+           pid.piod_addr = aux_info;
+           pid.piod_offs = auxv_addr;
+           pid.piod_len = sizeof(aux_info);
+           if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) {
+                   perror("failed to fetch aux_info");
+                   buf_ap.release();
+                   goto done;
+           }
+           memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len);
+           buf_sp.reset(buf_ap.release());
+   } else {
+           perror("sysctl failed on ps_strings");
+   }
+
+   done:
+   return buf_sp;
+}
diff --git a/lldb/source/Host/linux/Host.cpp b/lldb/source/Host/linux/Host.cpp
index 4ebacc5..432dfd5 100644
--- a/lldb/source/Host/linux/Host.cpp
+++ b/lldb/source/Host/linux/Host.cpp
@@ -10,12 +10,20 @@
 // C Includes
 #include <stdio.h>
 #include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
 #include "lldb/Core/Error.h"
+#include "lldb/Target/Process.h"
+
 #include "lldb/Host/Host.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -43,3 +51,48 @@
     return error;
 }
 
+lldb::DataBufferSP
+Host::GetAuxvData(lldb_private::Process *process)
+{
+    static const size_t path_size = 128;
+    static char path[path_size];
+    lldb::DataBufferSP buf_sp;
+
+    int fd;
+
+    // Ideally, we would simply create a FileSpec and call ReadFileContents.
+    // However, files in procfs have zero size (since they are, in general,
+    // 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/%d/auxv", process->GetID()) < 0)
+        return buf_sp;
+
+    if ((fd = open(path, O_RDONLY, 0)) < 0)
+        return buf_sp;
+
+    size_t bytes_read = 0;
+    std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
+    for (;;) 
+    {
+        size_t avail = buf_ap->GetByteSize() - bytes_read;
+        ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
+
+        if (status < 0) 
+            break;
+
+        bytes_read += status;
+
+        if (status == 0) 
+        {
+            buf_ap->SetByteSize(bytes_read);
+            buf_sp.reset(buf_ap.release());
+            break;
+        }
+
+        if (avail - status == 0)
+            buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
+    }
+
+    return buf_sp;
+}