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 ®_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 ®_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 ®_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 ®_value) override;
+
+ Error
+ WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_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 ®_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