lldb fix ARM64 register access - llgs side

See http://reviews.llvm.org/D5341 for more details.

Change by Paul Osmialowski.

llvm-svn: 217788
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 5de9731..47f66cb 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <linux/unistd.h>
 #include <sys/personality.h>
+#include <sys/procfs.h>
 #include <sys/ptrace.h>
 #include <sys/uio.h>
 #include <sys/socket.h>
@@ -592,6 +593,59 @@
     void
     ReadRegOperation::Execute(NativeProcessLinux *monitor)
     {
+#if defined (__arm64__) || defined (__aarch64__)
+        if (m_offset > sizeof(struct user_pt_regs))
+        {
+            uintptr_t offset = m_offset - sizeof(struct user_pt_regs);
+            if (offset > sizeof(struct user_fpsimd_state))
+            {
+                m_result = false;
+            }
+            else
+            {
+                elf_fpregset_t regs;
+                int regset = NT_FPREGSET;
+                struct iovec ioVec;
+
+                ioVec.iov_base = &regs;
+                ioVec.iov_len = sizeof regs;
+                if (PTRACE(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs) < 0)
+                    m_result = false;
+                else
+                {
+                    lldb_private::ArchSpec arch;
+                    if (monitor->GetArchitecture(arch))
+                    {
+                        m_result = true;
+                        m_value.SetBytes((void *)(((unsigned char *)(&regs)) + offset), 16, arch.GetByteOrder());
+                    }
+                    else
+                        m_result = false;
+                }
+            }
+        }
+        else
+        {
+            elf_gregset_t regs;
+            int regset = NT_PRSTATUS;
+            struct iovec ioVec;
+
+            ioVec.iov_base = &regs;
+            ioVec.iov_len = sizeof regs;
+            if (PTRACE(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs) < 0)
+                m_result = false;
+            else
+            {
+                lldb_private::ArchSpec arch;
+                if (monitor->GetArchitecture(arch))
+                {
+                    m_result = true;
+                    m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder());
+                } else
+                    m_result = false;
+            }
+        }
+#else
         Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
 
         // Set errno to zero so that we can detect a failed peek.
@@ -607,6 +661,7 @@
         if (log)
             log->Printf ("NativeProcessLinux::%s() reg %s: 0x%" PRIx64, __FUNCTION__,
                     m_reg_name, data);
+#endif
     }
 
     //------------------------------------------------------------------------------
@@ -634,6 +689,54 @@
     void
     WriteRegOperation::Execute(NativeProcessLinux *monitor)
     {
+#if defined (__arm64__) || defined (__aarch64__)
+        if (m_offset > sizeof(struct user_pt_regs))
+        {
+            uintptr_t offset = m_offset - sizeof(struct user_pt_regs);
+            if (offset > sizeof(struct user_fpsimd_state))
+            {
+                m_result = false;
+            }
+            else
+            {
+                elf_fpregset_t regs;
+                int regset = NT_FPREGSET;
+                struct iovec ioVec;
+
+                ioVec.iov_base = &regs;
+                ioVec.iov_len = sizeof regs;
+                if (PTRACE(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs) < 0)
+                    m_result = false;
+                else
+                {
+                    ::memcpy((void *)(((unsigned char *)(&regs)) + offset), m_value.GetBytes(), 16);
+                    if (PTRACE(PTRACE_SETREGSET, m_tid, &regset, &ioVec, sizeof regs) < 0)
+                        m_result = false;
+                    else
+                        m_result = true;
+                }
+            }
+        }
+        else
+        {
+            elf_gregset_t regs;
+            int regset = NT_PRSTATUS;
+            struct iovec ioVec;
+
+            ioVec.iov_base = &regs;
+            ioVec.iov_len = sizeof regs;
+            if (PTRACE(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs) < 0)
+                m_result = false;
+            else
+            {
+                ::memcpy((void *)(((unsigned char *)(&regs)) + m_offset), m_value.GetBytes(), 8);
+                if (PTRACE(PTRACE_SETREGSET, m_tid, &regset, &ioVec, sizeof regs) < 0)
+                    m_result = false;
+                else
+                    m_result = true;
+            }
+        }
+#else
         void* buf;
         Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
 
@@ -645,6 +748,7 @@
             m_result = false;
         else
             m_result = true;
+#endif
     }
 
     //------------------------------------------------------------------------------