Although still lots need to be done, this is another step towards ARM64/Linux 
support for llgs. Note that the list of visible registers is the same as in 
RegisterInfos_arm64.h which recently was extracted from Darwin implementation. 
For some reason, Darwin implementation authors didn't do anything about 32-bit 
w registers (lower halves of 64-bit x registers), I wonder why. As a result, 
read/write of just lower halves through w* register names is not possible.

http://reviews.llvm.org/D5426

Files:
  source/Plugins/Process/Linux/CMakeLists.txt
  source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
  source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
  source/Plugins/Process/Linux/NativeThreadLinux.cpp
  source/Plugins/Process/Utility/lldb-arm64-register-enums.h
Index: source/Plugins/Process/Linux/CMakeLists.txt
===================================================================
--- source/Plugins/Process/Linux/CMakeLists.txt
+++ source/Plugins/Process/Linux/CMakeLists.txt
@@ -6,6 +6,7 @@
 
 add_lldb_library(lldbPluginProcessLinux
   NativeProcessLinux.cpp
+  NativeRegisterContextLinux_arm64.cpp
   NativeRegisterContextLinux_x86_64.cpp
   NativeThreadLinux.cpp
   ProcessLinux.cpp
Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -0,0 +1,573 @@
+//===-- NativeRegisterContextLinux_arm64.cpp --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NativeRegisterContextLinux_arm64.h"
+
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-private-forward.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/RegisterValue.h"
+#include "Host/common/NativeProcessProtocol.h"
+#include "Host/common/NativeThreadProtocol.h"
+#include "Plugins/Process/Linux/NativeProcessLinux.h"
+
+#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(struct RegisterContextLinux_arm64::FPU))
+
+// ----------------------------------------------------------------------------
+// Private namespace.
+// ----------------------------------------------------------------------------
+
+namespace
+{
+    // ARM64 general purpose registers.
+    const uint32_t g_gpr_regnums_arm64[] =
+    {
+        lldb_private::gpr_x0_arm64,
+        lldb_private::gpr_x1_arm64,
+        lldb_private::gpr_x2_arm64,
+        lldb_private::gpr_x3_arm64,
+        lldb_private::gpr_x4_arm64,
+        lldb_private::gpr_x5_arm64,
+        lldb_private::gpr_x6_arm64,
+        lldb_private::gpr_x7_arm64,
+        lldb_private::gpr_x8_arm64,
+        lldb_private::gpr_x9_arm64,
+        lldb_private::gpr_x10_arm64,
+        lldb_private::gpr_x11_arm64,
+        lldb_private::gpr_x12_arm64,
+        lldb_private::gpr_x13_arm64,
+        lldb_private::gpr_x14_arm64,
+        lldb_private::gpr_x15_arm64,
+        lldb_private::gpr_x16_arm64,
+        lldb_private::gpr_x17_arm64,
+        lldb_private::gpr_x18_arm64,
+        lldb_private::gpr_x19_arm64,
+        lldb_private::gpr_x20_arm64,
+        lldb_private::gpr_x21_arm64,
+        lldb_private::gpr_x22_arm64,
+        lldb_private::gpr_x23_arm64,
+        lldb_private::gpr_x24_arm64,
+        lldb_private::gpr_x25_arm64,
+        lldb_private::gpr_x26_arm64,
+        lldb_private::gpr_x27_arm64,
+        lldb_private::gpr_x28_arm64,
+        lldb_private::gpr_fp_arm64,
+        lldb_private::gpr_lr_arm64,
+        lldb_private::gpr_sp_arm64,
+        lldb_private::gpr_pc_arm64,
+        lldb_private::gpr_cpsr_arm64,
+        LLDB_INVALID_REGNUM // register sets need to end with this flag
+    };
+    static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == lldb_private::k_num_gpr_registers_arm64, \
+                  "g_gpr_regnums_arm64 has wrong number of register infos");
+
+    // ARM64 floating point registers.
+    static const uint32_t g_fpu_regnums_arm64[] =
+    {
+        lldb_private::fpu_v0_arm64,
+        lldb_private::fpu_v1_arm64,
+        lldb_private::fpu_v2_arm64,
+        lldb_private::fpu_v3_arm64,
+        lldb_private::fpu_v4_arm64,
+        lldb_private::fpu_v5_arm64,
+        lldb_private::fpu_v6_arm64,
+        lldb_private::fpu_v7_arm64,
+        lldb_private::fpu_v8_arm64,
+        lldb_private::fpu_v9_arm64,
+        lldb_private::fpu_v10_arm64,
+        lldb_private::fpu_v11_arm64,
+        lldb_private::fpu_v12_arm64,
+        lldb_private::fpu_v13_arm64,
+        lldb_private::fpu_v14_arm64,
+        lldb_private::fpu_v15_arm64,
+        lldb_private::fpu_v16_arm64,
+        lldb_private::fpu_v17_arm64,
+        lldb_private::fpu_v18_arm64,
+        lldb_private::fpu_v19_arm64,
+        lldb_private::fpu_v20_arm64,
+        lldb_private::fpu_v21_arm64,
+        lldb_private::fpu_v22_arm64,
+        lldb_private::fpu_v23_arm64,
+        lldb_private::fpu_v24_arm64,
+        lldb_private::fpu_v25_arm64,
+        lldb_private::fpu_v26_arm64,
+        lldb_private::fpu_v27_arm64,
+        lldb_private::fpu_v28_arm64,
+        lldb_private::fpu_v29_arm64,
+        lldb_private::fpu_v30_arm64,
+        lldb_private::fpu_v31_arm64,
+        lldb_private::fpu_fpsr_arm64,
+        lldb_private::fpu_fpcr_arm64,
+        LLDB_INVALID_REGNUM // register sets need to end with this flag
+    };
+    static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == lldb_private::k_num_fpr_registers_arm64, \
+                  "g_fpu_regnums_arm64 has wrong number of register infos");
+
+    // Number of register sets provided by this context.
+    enum
+    {
+        k_num_register_sets = 2
+    };
+
+    // Register sets for ARM64.
+    static const lldb_private::RegisterSet
+    g_reg_sets_arm64[k_num_register_sets] =
+    {
+        { "General Purpose Registers",  "gpr", lldb_private::k_num_gpr_registers_arm64, g_gpr_regnums_arm64 },
+        { "Floating Point Registers",   "fpu", lldb_private::k_num_fpr_registers_arm64, g_fpu_regnums_arm64 }
+    };
+}
+
+// ----------------------------------------------------------------------------
+// NativeRegisterContextLinux_arm64 members.
+// ----------------------------------------------------------------------------
+
+lldb_private::NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(lldb_private::NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, lldb_private::RegisterInfoInterface *reg_info_interface_p) :
+    lldb_private::NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, reg_info_interface_p),
+    m_reg_info(),
+    m_gpr_arm64(),
+    m_fpr()
+{
+    // Set up data about ranges of valid registers.
+    switch (reg_info_interface_p->GetTargetArchitecture().GetMachine())
+    {
+        case llvm::Triple::aarch64:
+            m_reg_info.num_registers     = lldb_private::k_num_registers_arm64;
+            m_reg_info.num_gpr_registers = lldb_private::k_num_gpr_registers_arm64;
+            m_reg_info.num_fpr_registers = lldb_private::k_num_fpr_registers_arm64;
+            m_reg_info.last_gpr          = lldb_private::k_last_gpr_arm64;
+            m_reg_info.first_fpr         = lldb_private::k_first_fpr_arm64;
+            m_reg_info.last_fpr          = lldb_private::k_last_fpr_arm64;
+            m_reg_info.first_fpr_v       = lldb_private::fpu_v0_arm64;
+            m_reg_info.last_fpr_v        = lldb_private::fpu_v31_arm64;
+            m_reg_info.gpr_flags         = lldb_private::gpr_cpsr_arm64;
+            break;
+        default:
+            assert(false && "Unhandled target architecture.");
+            break;
+    }
+    ::memset(&m_fpr, 0, sizeof m_fpr);
+}
+
+bool
+lldb_private::NativeRegisterContextLinux_arm64::IsRegisterSetAvailable(uint32_t set_index) const
+{
+    return set_index < k_num_register_sets;
+}
+
+uint32_t
+lldb_private::NativeRegisterContextLinux_arm64::GetRegisterSetCount() const
+{
+    uint32_t sets = 0;
+
+    for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
+    {
+        if (IsRegisterSetAvailable(set_index))
+            ++sets;
+    }
+    return sets;
+}
+
+const lldb_private::RegisterSet *
+lldb_private::NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const
+{
+    if (!IsRegisterSetAvailable(set_index))
+        return nullptr;
+
+    switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine())
+    {
+        case llvm::Triple::aarch64:
+            return &g_reg_sets_arm64[set_index];
+        default:
+            assert (false && "Unhandled target architecture.");
+            return nullptr;
+    }
+
+    return nullptr;
+}
+
+lldb_private::Error
+lldb_private::NativeRegisterContextLinux_arm64::ReadRegisterRaw(uint32_t reg_index, lldb_private::RegisterValue &reg_value)
+{
+    Error error;
+    const lldb_private::RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index);
+    if (!reg_info)
+    {
+        error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index);
+        return error;
+    }
+
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+    {
+        error.SetErrorString ("NativeProcessProtocol is NULL");
+        return error;
+    }
+
+    NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
+    if (!process_p->ReadRegisterValue(m_thread.GetID(),
+                                     reg_info->byte_offset,
+                                     reg_info->name,
+                                     reg_info->byte_size,
+                                     reg_value))
+        error.SetErrorString ("NativeProcessLinux::ReadRegisterValue() failed");
+
+    return error;
+}
+
+lldb_private::Error
+lldb_private::NativeRegisterContextLinux_arm64::ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &reg_value)
+{
+    lldb_private::Error error;
+
+    if (!reg_info)
+    {
+        error.SetErrorString ("reg_info NULL");
+        return error;
+    }
+
+    const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+    if (reg == LLDB_INVALID_REGNUM)
+    {
+        // This is likely an internal register for lldb use only and should not be directly queried.
+        error.SetErrorStringWithFormat ("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name);
+        return error;
+    }
+
+    if (IsFPR(reg))
+    {
+        if (!ReadFPR())
+        {
+            error.SetErrorString ("failed to read floating point register");
+            return error;
+        }
+    }
+    else
+    {
+        uint32_t full_reg = reg;
+        bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
+
+        if (is_subreg)
+        {
+            // Read the full aligned 64-bit register.
+            full_reg = reg_info->invalidate_regs[0];
+        }
+
+        error = ReadRegisterRaw(full_reg, reg_value);
+
+        if (error.Success ())
+        {
+            // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
+            if (is_subreg && (reg_info->byte_offset & 0x1))
+                reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
+
+            // If our return byte size was greater than the return value reg size, then
+            // use the type specified by reg_info rather than the uint64_t default
+            if (reg_value.GetByteSize() > reg_info->byte_size)
+                reg_value.SetType(reg_info);
+        }
+
+        return error;
+    }
+
+    if (reg_info->encoding == lldb::eEncodingVector)
+    {
+        lldb::ByteOrder byte_order = GetByteOrder();
+
+        if (byte_order != lldb::eByteOrderInvalid)
+        {
+            if (reg >= m_reg_info.first_fpr_v && reg <= m_reg_info.last_fpr_v)
+                reg_value.SetBytes(m_fpr.v[reg - m_reg_info.first_fpr_v].bytes, reg_info->byte_size, byte_order);
+            if (reg_value.GetType() != lldb_private::RegisterValue::eTypeBytes)
+                error.SetErrorString ("write failed - type was expected to be RegisterValue::eTypeBytes");
+
+            return error;
+        }
+
+        error.SetErrorString ("byte order is invalid");
+        return error;
+    }
+
+    return error;
+}
+
+lldb_private::Error
+lldb_private::NativeRegisterContextLinux_arm64::WriteRegister(const uint32_t reg, const lldb_private::RegisterValue &value)
+{
+    Error error;
+
+    uint32_t reg_to_write = reg;
+    lldb_private::RegisterValue value_to_write = value;
+
+    // Check if this is a subregister of a full register.
+    const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+    if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
+    {
+        lldb_private::RegisterValue full_value;
+        uint32_t full_reg = reg_info->invalidate_regs[0];
+        const lldb_private::RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
+
+        // Read the full register.
+        error = ReadRegister(full_reg_info, full_value);
+        if (error.Fail ())
+            return error;
+
+        lldb::ByteOrder byte_order = GetByteOrder();
+        uint8_t dst[lldb_private::RegisterValue::kMaxRegisterByteSize];
+
+        // Get the bytes for the full register.
+        const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
+                                                               dst,
+                                                               sizeof dst,
+                                                               byte_order,
+                                                               error);
+        if (error.Success() && dest_size)
+        {
+            uint8_t src[lldb_private::RegisterValue::kMaxRegisterByteSize];
+
+            // Get the bytes for the source data.
+            const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof src, byte_order, error);
+            if (error.Success() && src_size && (src_size < dest_size))
+            {
+                // Copy the src bytes to the destination.
+                ::memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
+                // Set this full register as the value to write.
+                value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
+                value_to_write.SetType(full_reg_info);
+                reg_to_write = full_reg;
+            }
+        }
+    }
+
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+    {
+        error.SetErrorString ("NativeProcessProtocol is NULL");
+        return error;
+    }
+
+    const lldb_private::RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
+    assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
+    if (!register_to_write_info_p)
+    {
+        error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
+        return error;
+    }
+
+    NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
+    if (!process_p->WriteRegisterValue(m_thread.GetID(),
+                                       register_to_write_info_p->byte_offset,
+                                       register_to_write_info_p->name,
+                                       value_to_write))
+        error.SetErrorString ("NativeProcessLinux::WriteRegisterValue() failed");
+
+    return error;
+}
+
+lldb_private::Error
+lldb_private::NativeRegisterContextLinux_arm64::WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &reg_value)
+{
+    assert (reg_info && "reg_info is null");
+
+    const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
+    if (reg_index == LLDB_INVALID_REGNUM)
+        return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
+    if (IsGPR(reg_index))
+        return WriteRegister(reg_index, reg_value);
+    if (IsFPR(reg_index))
+    {
+        if (reg_info->encoding == lldb::eEncodingVector)
+        {
+            if (reg_index >= m_reg_info.first_fpr_v && reg_index <= m_reg_info.last_fpr_v)
+                ::memcpy (m_fpr.v[reg_index - m_reg_info.first_fpr_v].bytes, reg_value.GetBytes(), reg_value.GetByteSize());
+        }
+        else
+        {
+            // Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
+            assert (reg_info->byte_offset < sizeof m_fpr.v);
+            uint8_t *dst = reinterpret_cast<uint8_t *>(&m_fpr.v[0]) + reg_info->byte_offset;
+            switch (reg_info->byte_size)
+            {
+                case 2:
+                    *(uint16_t *)dst = reg_value.GetAsUInt16();
+                    break;
+                case 4:
+                    *(uint32_t *)dst = reg_value.GetAsUInt32();
+                    break;
+                case 8:
+                    *(uint64_t *)dst = reg_value.GetAsUInt64();
+                    break;
+                default:
+                    assert(false && "Unhandled data size.");
+                    return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
+            }
+        }
+
+        if (WriteFPR())
+            return Error ();
+    }
+    return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
+}
+
+lldb_private::Error
+lldb_private::NativeRegisterContextLinux_arm64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+    Error error;
+
+    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+    if (!data_sp)
+    {
+        error.SetErrorStringWithFormat ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE);
+        return error;
+    }
+
+    if (!ReadGPR ())
+    {
+        error.SetErrorString ("ReadGPR() failed");
+        return error;
+    }
+
+    if (!ReadFPR ())
+    {
+        error.SetErrorString ("ReadFPR() failed");
+        return error;
+    }
+
+    uint8_t *dst = data_sp->GetBytes ();
+    if (dst == nullptr)
+    {
+        error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE);
+        return error;
+    }
+
+    ::memcpy (dst, &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ());
+    dst += GetRegisterInfoInterface ().GetGPRSize ();
+    ::memcpy (dst, &m_fpr, sizeof m_fpr);
+
+    return error;
+}
+
+lldb_private::Error
+lldb_private::NativeRegisterContextLinux_arm64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+    Error error;
+
+    if (!data_sp)
+    {
+        error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm64::%s invalid data_sp provided", __FUNCTION__);
+        return error;
+    }
+
+    if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
+    {
+        error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ());
+        return error;
+    }
+
+    uint8_t *src = data_sp->GetBytes ();
+    if (src == nullptr)
+    {
+        error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
+        return error;
+    }
+    ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ());
+
+    if (!WriteGPR ())
+    {
+        error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__);
+        return error;
+    }
+
+    src += GetRegisterInfoInterface ().GetGPRSize ();
+    ::memcpy (&m_fpr, src, sizeof m_fpr);
+
+    if (!WriteFPR ())
+    {
+        error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__);
+        return error;
+    }
+
+    return error;
+}
+
+lldb::ByteOrder
+lldb_private::NativeRegisterContextLinux_arm64::GetByteOrder() const
+{
+    // Get the target process whose privileged thread was used for the register read.
+    lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
+
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+        return byte_order;
+
+    if (!process_sp->GetByteOrder (byte_order))
+    {
+        // FIXME log here
+    }
+
+    return byte_order;
+}
+
+bool
+lldb_private::NativeRegisterContextLinux_arm64::IsGPR(uint32_t reg_index) const
+{
+    // GPRs come first.
+    return reg_index <= m_reg_info.last_gpr;
+}
+
+bool
+lldb_private::NativeRegisterContextLinux_arm64::IsFPR(uint32_t reg_index) const
+{
+    return (m_reg_info.first_fpr <= reg_index) && (reg_index <= m_reg_info.last_fpr);
+}
+
+bool
+lldb_private::NativeRegisterContextLinux_arm64::ReadFPR()
+{
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+        return false;
+    NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
+
+    return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof m_fpr);
+}
+
+bool
+lldb_private::NativeRegisterContextLinux_arm64::WriteFPR()
+{
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+        return false;
+    NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
+
+    return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof m_fpr);
+}
+
+bool
+lldb_private::NativeRegisterContextLinux_arm64::ReadGPR()
+{
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+        return false;
+    NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
+
+    return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ());
+}
+
+bool
+lldb_private::NativeRegisterContextLinux_arm64::WriteGPR()
+{
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+        return false;
+    NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
+
+    return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ());
+}
Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
===================================================================
--- /dev/null
+++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -0,0 +1,103 @@
+//===-- NativeRegisterContextLinux_arm64.h ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef lldb_NativeRegisterContextLinux_arm64_h
+#define lldb_NativeRegisterContextLinux_arm64_h
+
+#include "lldb/Target/NativeRegisterContextRegisterInfo.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-types.h"
+#include "lldb/lldb-private-forward.h"
+#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
+#include "lldb-arm64-register-enums.h"
+
+namespace lldb_private
+{
+    class NativeProcessLinux;
+
+    class NativeRegisterContextLinux_arm64 : public NativeRegisterContextRegisterInfo
+    {
+    public:
+        NativeRegisterContextLinux_arm64(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p);
+
+        uint32_t
+        GetRegisterSetCount() const override;
+
+        const RegisterSet *
+        GetRegisterSet(uint32_t set_index) const override;
+
+        Error
+        ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value) override;
+
+        Error
+        WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value) override;
+
+        Error
+        ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+        Error
+        WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+    private:
+
+        // Info about register ranges.
+        struct RegInfo
+        {
+            uint32_t num_registers;
+            uint32_t num_gpr_registers;
+            uint32_t num_fpr_registers;
+
+            uint32_t last_gpr;
+            uint32_t first_fpr;
+            uint32_t last_fpr;
+
+            uint32_t first_fpr_v;
+            uint32_t last_fpr_v;
+
+            uint32_t gpr_flags;
+        } m_reg_info;
+        uint64_t m_gpr_arm64[k_num_gpr_registers_arm64];
+        struct RegisterContextLinux_arm64::FPU m_fpr;
+
+        // Determines if an extended register set is supported on the processor running the inferior process.
+        virtual bool
+        IsRegisterSetAvailable(uint32_t set_index) const;
+
+        lldb::ByteOrder
+        GetByteOrder() const;
+
+        Error
+        ReadRegisterRaw(uint32_t reg_index, RegisterValue &reg_value);
+
+        Error
+        WriteRegister(const uint32_t reg, const RegisterValue &value);
+
+        bool
+        IsGPR(uint32_t reg_index) const;
+
+        bool
+        IsFPR(uint32_t reg_index) const;
+
+        bool
+        ReadFPR();
+
+        bool
+        WriteFPR();
+
+        bool
+        ReadGPR();
+
+        bool
+        WriteGPR();
+    };
+}
+
+#endif // #ifndef lldb_NativeRegisterContextLinux_arm64_h
Index: source/Plugins/Process/Linux/NativeThreadLinux.cpp
===================================================================
--- source/Plugins/Process/Linux/NativeThreadLinux.cpp
+++ source/Plugins/Process/Linux/NativeThreadLinux.cpp
@@ -12,6 +12,7 @@
 #include <signal.h>
 
 #include "NativeProcessLinux.h"
+#include "NativeRegisterContextLinux_arm64.h"
 #include "NativeRegisterContextLinux_x86_64.h"
 
 #include "lldb/Core/Log.h"
@@ -172,6 +173,12 @@
     // Now create the register context.
     switch (target_arch.GetMachine())
     {
+        case llvm::Triple::aarch64:
+        {
+            const uint32_t concrete_frame_idx = 0;
+            m_reg_context_sp.reset (new NativeRegisterContextLinux_arm64(*this, concrete_frame_idx, reg_interface));
+            break;
+        }
 #if 0
         case llvm::Triple::mips64:
         {
Index: source/Plugins/Process/Utility/lldb-arm64-register-enums.h
===================================================================
--- /dev/null
+++ source/Plugins/Process/Utility/lldb-arm64-register-enums.h
@@ -0,0 +1,172 @@
+//===-- lldb-arm64-register-enums.h -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_arm64_register_enums_h
+#define lldb_arm64_register_enums_h
+
+namespace lldb_private
+{
+
+    //---------------------------------------------------------------------------
+    // Internal codes for all ARM64 registers.
+    //---------------------------------------------------------------------------
+    enum
+    {
+        k_first_gpr_arm64,
+        gpr_x0_arm64 = k_first_gpr_arm64,
+        gpr_x1_arm64,
+        gpr_x2_arm64,
+        gpr_x3_arm64,
+        gpr_x4_arm64,
+        gpr_x5_arm64,
+        gpr_x6_arm64,
+        gpr_x7_arm64,
+        gpr_x8_arm64,
+        gpr_x9_arm64,
+        gpr_x10_arm64,
+        gpr_x11_arm64,
+        gpr_x12_arm64,
+        gpr_x13_arm64,
+        gpr_x14_arm64,
+        gpr_x15_arm64,
+        gpr_x16_arm64,
+        gpr_x17_arm64,
+        gpr_x18_arm64,
+        gpr_x19_arm64,
+        gpr_x20_arm64,
+        gpr_x21_arm64,
+        gpr_x22_arm64,
+        gpr_x23_arm64,
+        gpr_x24_arm64,
+        gpr_x25_arm64,
+        gpr_x26_arm64,
+        gpr_x27_arm64,
+        gpr_x28_arm64,
+        gpr_fp_arm64,
+        gpr_lr_arm64,
+        gpr_sp_arm64,
+        gpr_pc_arm64,
+        gpr_cpsr_arm64,
+
+        k_last_gpr_arm64 = gpr_cpsr_arm64,
+
+        k_first_fpr_arm64,
+        fpu_v0_arm64 = k_first_fpr_arm64,
+        fpu_v1_arm64,
+        fpu_v2_arm64,
+        fpu_v3_arm64,
+        fpu_v4_arm64,
+        fpu_v5_arm64,
+        fpu_v6_arm64,
+        fpu_v7_arm64,
+        fpu_v8_arm64,
+        fpu_v9_arm64,
+        fpu_v10_arm64,
+        fpu_v11_arm64,
+        fpu_v12_arm64,
+        fpu_v13_arm64,
+        fpu_v14_arm64,
+        fpu_v15_arm64,
+        fpu_v16_arm64,
+        fpu_v17_arm64,
+        fpu_v18_arm64,
+        fpu_v19_arm64,
+        fpu_v20_arm64,
+        fpu_v21_arm64,
+        fpu_v22_arm64,
+        fpu_v23_arm64,
+        fpu_v24_arm64,
+        fpu_v25_arm64,
+        fpu_v26_arm64,
+        fpu_v27_arm64,
+        fpu_v28_arm64,
+        fpu_v29_arm64,
+        fpu_v30_arm64,
+        fpu_v31_arm64,
+        fpu_fpsr_arm64,
+        fpu_fpcr_arm64,
+
+        k_last_fpr_arm64 = fpu_fpcr_arm64,
+
+        exc_far_arm64,
+        exc_esr_arm64,
+        exc_exception_arm64,
+
+        dbg_bvr0_arm64,
+        dbg_bvr1_arm64,
+        dbg_bvr2_arm64,
+        dbg_bvr3_arm64,
+        dbg_bvr4_arm64,
+        dbg_bvr5_arm64,
+        dbg_bvr6_arm64,
+        dbg_bvr7_arm64,
+        dbg_bvr8_arm64,
+        dbg_bvr9_arm64,
+        dbg_bvr10_arm64,
+        dbg_bvr11_arm64,
+        dbg_bvr12_arm64,
+        dbg_bvr13_arm64,
+        dbg_bvr14_arm64,
+        dbg_bvr15_arm64,
+        dbg_bcr0_arm64,
+        dbg_bcr1_arm64,
+        dbg_bcr2_arm64,
+        dbg_bcr3_arm64,
+        dbg_bcr4_arm64,
+        dbg_bcr5_arm64,
+        dbg_bcr6_arm64,
+        dbg_bcr7_arm64,
+        dbg_bcr8_arm64,
+        dbg_bcr9_arm64,
+        dbg_bcr10_arm64,
+        dbg_bcr11_arm64,
+        dbg_bcr12_arm64,
+        dbg_bcr13_arm64,
+        dbg_bcr14_arm64,
+        dbg_bcr15_arm64,
+        dbg_wvr0_arm64,
+        dbg_wvr1_arm64,
+        dbg_wvr2_arm64,
+        dbg_wvr3_arm64,
+        dbg_wvr4_arm64,
+        dbg_wvr5_arm64,
+        dbg_wvr6_arm64,
+        dbg_wvr7_arm64,
+        dbg_wvr8_arm64,
+        dbg_wvr9_arm64,
+        dbg_wvr10_arm64,
+        dbg_wvr11_arm64,
+        dbg_wvr12_arm64,
+        dbg_wvr13_arm64,
+        dbg_wvr14_arm64,
+        dbg_wvr15_arm64,
+        dbg_wcr0_arm64,
+        dbg_wcr1_arm64,
+        dbg_wcr2_arm64,
+        dbg_wcr3_arm64,
+        dbg_wcr4_arm64,
+        dbg_wcr5_arm64,
+        dbg_wcr6_arm64,
+        dbg_wcr7_arm64,
+        dbg_wcr8_arm64,
+        dbg_wcr9_arm64,
+        dbg_wcr10_arm64,
+        dbg_wcr11_arm64,
+        dbg_wcr12_arm64,
+        dbg_wcr13_arm64,
+        dbg_wcr14_arm64,
+        dbg_wcr15_arm64,
+
+        k_num_registers_arm64,
+        k_num_gpr_registers_arm64 = k_last_gpr_arm64 - k_first_gpr_arm64 + 1,
+        k_num_fpr_registers_arm64 = k_last_fpr_arm64 - k_first_fpr_arm64 + 1
+    };
+}
+
+#endif // #ifndef lldb_arm64_register_enums_h
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to