[Lldb-commits] [lldb] r216907 - Linux ARM64: add ProcessMonitor-related RegisterContext support.

Todd Fiala todd.fiala at gmail.com
Tue Sep 2 07:50:01 PDT 2014


Author: tfiala
Date: Tue Sep  2 09:50:01 2014
New Revision: 216907

URL: http://llvm.org/viewvc/llvm-project?rev=216907&view=rev
Log:
Linux ARM64: add ProcessMonitor-related RegisterContext support.

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

Change by Paul Osmialowski.

Added:
    lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp
    lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
Modified:
    lldb/trunk/source/Plugins/Process/POSIX/CMakeLists.txt
    lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp
    lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt

Modified: lldb/trunk/source/Plugins/Process/POSIX/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/CMakeLists.txt?rev=216907&r1=216906&r2=216907&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/CMakeLists.txt Tue Sep  2 09:50:01 2014
@@ -10,6 +10,7 @@ add_lldb_library(lldbPluginProcessPOSIX
   ProcessMessage.cpp
   ProcessPOSIX.cpp
   ProcessPOSIXLog.cpp
+  RegisterContextPOSIXProcessMonitor_arm64.cpp
   RegisterContextPOSIXProcessMonitor_mips64.cpp
   RegisterContextPOSIXProcessMonitor_x86.cpp
   )

Modified: lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp?rev=216907&r1=216906&r2=216907&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp Tue Sep  2 09:50:01 2014
@@ -30,6 +30,7 @@
 #include "ProcessPOSIX.h"
 #include "ProcessPOSIXLog.h"
 #include "ProcessMonitor.h"
+#include "RegisterContextPOSIXProcessMonitor_arm64.h"
 #include "RegisterContextPOSIXProcessMonitor_mips64.h"
 #include "RegisterContextPOSIXProcessMonitor_x86.h"
 #include "RegisterContextLinux_arm64.h"
@@ -211,6 +212,13 @@ POSIXThread::GetRegisterContext()
 
         switch (target_arch.GetMachine())
         {
+            case llvm::Triple::aarch64:
+                {
+                    RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface);
+                    m_posix_thread = reg_ctx;
+                    m_reg_context_sp.reset(reg_ctx);
+                    break;
+                }
             case llvm::Triple::mips64:
                 {
                     RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
@@ -611,6 +619,7 @@ POSIXThread::GetRegisterIndexFromOffset(
         llvm_unreachable("CPU type not supported!");
         break;
 
+    case llvm::Triple::aarch64:
     case llvm::Triple::mips64:
     case llvm::Triple::x86:
     case llvm::Triple::x86_64:
@@ -641,6 +650,7 @@ POSIXThread::GetRegisterName(unsigned re
         assert(false && "CPU type not supported!");
         break;
 
+    case llvm::Triple::aarch64:
     case llvm::Triple::mips64:
     case llvm::Triple::x86:
     case llvm::Triple::x86_64:

Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp?rev=216907&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp (added)
+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp Tue Sep  2 09:50:01 2014
@@ -0,0 +1,318 @@
+//===-- RegisterContextPOSIXProcessMonitor_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 "lldb/Target/Thread.h"
+#include "lldb/Core/RegisterValue.h"
+
+#include "RegisterContextPOSIX_arm64.h"
+#include "ProcessPOSIX.h"
+#include "RegisterContextPOSIXProcessMonitor_arm64.h"
+#include "ProcessMonitor.h"
+
+#define REG_CONTEXT_SIZE (GetGPRSize())
+
+RegisterContextPOSIXProcessMonitor_arm64::RegisterContextPOSIXProcessMonitor_arm64(lldb_private::Thread &thread,
+                                                                                   uint32_t concrete_frame_idx,
+                                                                                   lldb_private::RegisterInfoInterface *register_info)
+    : RegisterContextPOSIX_arm64(thread, concrete_frame_idx, register_info)
+{
+}
+
+ProcessMonitor &
+RegisterContextPOSIXProcessMonitor_arm64::GetMonitor()
+{
+    lldb::ProcessSP base = CalculateProcess();
+    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+    return process->GetMonitor();
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ReadGPR()
+{
+     ProcessMonitor &monitor = GetMonitor();
+     return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ReadFPR()
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::WriteGPR()
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::WriteFPR()
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(const unsigned reg,
+                                                       lldb_private::RegisterValue &value)
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.ReadRegisterValue(m_thread.GetID(),
+                                     GetRegisterOffset(reg),
+                                     GetRegisterName(reg),
+                                     GetRegisterSize(reg),
+                                     value);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(const unsigned reg,
+                                                         const lldb_private::RegisterValue &value)
+{
+    unsigned 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.
+        if (ReadRegister(full_reg_info, full_value))
+        {
+            lldb_private::Error 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;
+                }
+            }
+        }
+    }
+
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteRegisterValue(m_thread.GetID(),
+                                      GetRegisterOffset(reg_to_write),
+                                      GetRegisterName(reg_to_write),
+                                      value_to_write);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value)
+{
+    if (!reg_info)
+        return false;
+
+    const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+    if (IsFPR(reg))
+    {
+        if (!ReadFPR())
+            return false;
+    }
+    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];
+        }
+        return ReadRegister(full_reg, value);
+    }
+
+    // Get pointer to m_fpr variable and set the data from it.
+    assert (reg_info->byte_offset < sizeof m_fpr);
+    uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
+    switch (reg_info->byte_size)
+    {
+        case 2:
+            value.SetUInt16(*(uint16_t *)src);
+            return true;
+        case 4:
+            value.SetUInt32(*(uint32_t *)src);
+            return true;
+        case 8:
+            value.SetUInt64(*(uint64_t *)src);
+            return true;
+        default:
+            assert(false && "Unhandled data size.");
+            return false;
+    }
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+    if (IsGPR(reg))
+        return WriteRegister(reg, value);
+
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+    bool success = false;
+    data_sp.reset (new lldb_private::DataBufferHeap (REG_CONTEXT_SIZE, 0));
+    if (data_sp && ReadGPR () && ReadFPR ())
+    {
+        uint8_t *dst = data_sp->GetBytes();
+        success = dst != 0;
+
+        if (success)
+        {
+            ::memcpy (dst, &m_gpr_arm64, GetGPRSize());
+            dst += GetGPRSize();
+            ::memcpy (dst, &m_fpr, sizeof m_fpr);
+        }
+    }
+    return success;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+    bool success = false;
+    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+    {
+        uint8_t *src = data_sp->GetBytes();
+        if (src)
+        {
+            ::memcpy (&m_gpr_arm64, src, GetGPRSize());
+            if (WriteGPR()) {
+                src += GetGPRSize();
+                ::memcpy (&m_fpr, src, sizeof m_fpr);
+                success = WriteFPR();
+            }
+        }
+    }
+    return success;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+                                                                bool read, bool write)
+{
+    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+    uint32_t hw_index;
+
+    for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+    {
+        if (IsWatchpointVacant(hw_index))
+            return SetHardwareWatchpointWithIndex(addr, size,
+                                                  read, write,
+                                                  hw_index);
+    }
+
+    return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable)
+{
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint()
+{
+    // PC points one byte past the int3 responsible for the breakpoint.
+    lldb::addr_t pc;
+
+    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+        return false;
+
+    SetPC(pc - 1);
+    return true;
+}
+
+unsigned
+RegisterContextPOSIXProcessMonitor_arm64::GetRegisterIndexFromOffset(unsigned offset)
+{
+    unsigned reg;
+    for (reg = 0; reg < k_num_registers_arm64; reg++)
+    {
+        if (GetRegisterInfo()[reg].byte_offset == offset)
+            break;
+    }
+    assert(reg < k_num_registers_arm64 && "Invalid register offset.");
+    return reg;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointHit(uint32_t hw_index)
+{
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::ClearWatchpointHits()
+{
+    return false;
+}
+
+lldb::addr_t
+RegisterContextPOSIXProcessMonitor_arm64::GetWatchpointAddress(uint32_t hw_index)
+{
+    return LLDB_INVALID_ADDRESS;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointVacant(uint32_t hw_index)
+{
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
+                                                                         bool read, bool write,
+                                                                         uint32_t hw_index)
+{
+    return false;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_arm64::NumSupportedHardwareWatchpoints()
+{
+    return 0;
+}

Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h?rev=216907&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h (added)
+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h Tue Sep  2 09:50:01 2014
@@ -0,0 +1,95 @@
+//===-- RegisterContextPOSIXProcessMonitor_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 liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
+#define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
+
+#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
+
+class RegisterContextPOSIXProcessMonitor_arm64:
+    public RegisterContextPOSIX_arm64,
+    public POSIXBreakpointProtocol
+{
+public:
+    RegisterContextPOSIXProcessMonitor_arm64(lldb_private::Thread &thread,
+                                             uint32_t concrete_frame_idx,
+                                             lldb_private::RegisterInfoInterface *register_info);
+
+protected:
+    bool
+    ReadGPR();
+
+    bool
+    ReadFPR();
+
+    bool
+    WriteGPR();
+
+    bool
+    WriteFPR();
+
+    // lldb_private::RegisterContext
+    bool
+    ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
+
+    bool
+    WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
+
+    bool
+    ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+    bool
+    WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+    bool
+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+    bool
+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+    uint32_t
+    SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write);
+
+    bool
+    ClearHardwareWatchpoint(uint32_t hw_index);
+
+    bool
+    HardwareSingleStep(bool enable);
+
+    // POSIXBreakpointProtocol
+    bool
+    UpdateAfterBreakpoint();
+
+    unsigned
+    GetRegisterIndexFromOffset(unsigned offset);
+
+    bool
+    IsWatchpointHit(uint32_t hw_index);
+
+    bool
+    ClearWatchpointHits();
+
+    lldb::addr_t
+    GetWatchpointAddress(uint32_t hw_index);
+
+    bool
+    IsWatchpointVacant(uint32_t hw_index);
+
+    bool
+    SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index);
+
+    uint32_t
+    NumSupportedHardwareWatchpoints();
+
+private:
+    ProcessMonitor &
+    GetMonitor();
+};
+
+#endif

Modified: lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt?rev=216907&r1=216906&r2=216907&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt Tue Sep  2 09:50:01 2014
@@ -27,6 +27,7 @@ add_lldb_library(lldbPluginProcessUtilit
   RegisterContextMach_i386.cpp
   RegisterContextMach_x86_64.cpp
   RegisterContextMemory.cpp
+  RegisterContextPOSIX_arm64.cpp
   RegisterContextPOSIX_mips64.cpp
   RegisterContextPOSIX_x86.cpp
   RegisterContextThreadMemory.cpp

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp?rev=216907&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp Tue Sep  2 09:50:01 2014
@@ -0,0 +1,299 @@
+//===-- RegisterContextPOSIX_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 <cstring>
+#include <errno.h>
+#include <stdint.h>
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Host/Endian.h"
+#include "llvm/Support/Compiler.h"
+
+#include "RegisterContextPOSIX_arm64.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+
+// ARM64 general purpose registers.
+const uint32_t g_gpr_regnums_arm64[] =
+{
+    gpr_x0_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,
+    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) == 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[] =
+{
+    fpu_v0_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,
+    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) == 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", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 },
+    { "Floating Point Registers",   "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 }
+};
+
+bool RegisterContextPOSIX_arm64::IsGPR(unsigned reg)
+{
+    return reg <= m_reg_info.last_gpr;   // GPR's come first.
+}
+
+bool RegisterContextPOSIX_arm64::IsFPR(unsigned reg)
+{
+    return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
+}
+
+RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(lldb_private::Thread &thread,
+                                                       uint32_t concrete_frame_idx,
+                                                       lldb_private::RegisterInfoInterface *register_info)
+    : lldb_private::RegisterContext(thread, concrete_frame_idx)
+{
+    m_register_info_ap.reset(register_info);
+
+    switch (register_info->m_target_arch.GetMachine())
+    {
+        case llvm::Triple::aarch64:
+            m_reg_info.num_registers     = k_num_registers_arm64;
+            m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64;
+            m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64;
+            m_reg_info.last_gpr          = k_last_gpr_arm64;
+            m_reg_info.first_fpr         = k_first_fpr_arm64;
+            m_reg_info.last_fpr          = k_last_fpr_arm64;
+            m_reg_info.first_fpr_v       = fpu_v0_arm64;
+            m_reg_info.last_fpr_v        = fpu_v31_arm64;
+            m_reg_info.gpr_flags         = gpr_cpsr_arm64;
+            break;
+        default:
+            assert(false && "Unhandled target architecture.");
+            break;
+    }
+
+    ::memset(&m_fpr, 0, sizeof m_fpr);
+
+    // elf-core yet to support ReadFPR()
+    lldb::ProcessSP base = CalculateProcess();
+    if (base.get()->GetPluginName() ==  ProcessElfCore::GetPluginNameStatic())
+        return;
+}
+
+RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64()
+{
+}
+
+void
+RegisterContextPOSIX_arm64::Invalidate()
+{
+}
+
+void
+RegisterContextPOSIX_arm64::InvalidateAllRegisters()
+{
+}
+
+unsigned
+RegisterContextPOSIX_arm64::GetRegisterOffset(unsigned reg)
+{
+    assert(reg < m_reg_info.num_registers && "Invalid register number.");
+    return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContextPOSIX_arm64::GetRegisterSize(unsigned reg)
+{
+    assert(reg < m_reg_info.num_registers && "Invalid register number.");
+    return GetRegisterInfo()[reg].byte_size;
+}
+
+size_t
+RegisterContextPOSIX_arm64::GetRegisterCount()
+{
+    size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers;
+    return num_registers;
+}
+
+size_t
+RegisterContextPOSIX_arm64::GetGPRSize()
+{
+    return m_register_info_ap->GetGPRSize ();
+}
+
+const lldb_private::RegisterInfo *
+RegisterContextPOSIX_arm64::GetRegisterInfo()
+{
+    // Commonly, this method is overridden and g_register_infos is copied and specialized.
+    // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+    return m_register_info_ap->GetRegisterInfo ();
+}
+
+const lldb_private::RegisterInfo *
+RegisterContextPOSIX_arm64::GetRegisterInfoAtIndex(size_t reg)
+{
+    if (reg < m_reg_info.num_registers)
+        return &GetRegisterInfo()[reg];
+    else
+        return NULL;
+}
+
+size_t
+RegisterContextPOSIX_arm64::GetRegisterSetCount()
+{
+    size_t sets = 0;
+    for (size_t set = 0; set < k_num_register_sets; ++set)
+    {
+        if (IsRegisterSetAvailable(set))
+            ++sets;
+    }
+
+    return sets;
+}
+
+const lldb_private::RegisterSet *
+RegisterContextPOSIX_arm64::GetRegisterSet(size_t set)
+{
+    if (IsRegisterSetAvailable(set))
+    {
+        switch (m_register_info_ap->m_target_arch.GetMachine())
+        {
+            case llvm::Triple::aarch64:
+                return &g_reg_sets_arm64[set];
+            default:
+                assert(false && "Unhandled target architecture.");
+                return NULL;
+        }
+    }
+    return NULL;
+}
+
+const char *
+RegisterContextPOSIX_arm64::GetRegisterName(unsigned reg)
+{
+    assert(reg < m_reg_info.num_registers && "Invalid register offset.");
+    return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContextPOSIX_arm64::GetByteOrder()
+{
+    // Get the target process whose privileged thread was used for the register read.
+    lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
+    lldb_private::Process *process = CalculateProcess().get();
+
+    if (process)
+        byte_order = process->GetByteOrder();
+    return byte_order;
+}
+
+bool
+RegisterContextPOSIX_arm64::IsRegisterSetAvailable(size_t set_index)
+{
+    return set_index < k_num_register_sets;
+}
+
+
+// Used when parsing DWARF and EH frame information and any other
+// object file sections that contain register numbers in them. 
+uint32_t
+RegisterContextPOSIX_arm64::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+                                                                uint32_t num)
+{
+    const uint32_t num_regs = GetRegisterCount();
+
+    assert (kind < lldb::kNumRegisterKinds);
+    for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
+    {
+        const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx);
+
+        if (reg_info->kinds[kind] == num)
+            return reg_idx;
+    }
+
+    return LLDB_INVALID_REGNUM;
+}

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h?rev=216907&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h Tue Sep  2 09:50:01 2014
@@ -0,0 +1,272 @@
+//===-- RegisterContextPOSIX_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 liblldb_RegisterContextPOSIX_arm64_H_
+#define liblldb_RegisterContextPOSIX_arm64_H_
+
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+
+class ProcessMonitor;
+
+//---------------------------------------------------------------------------
+// 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
+};
+
+class RegisterContextPOSIX_arm64
+  : public lldb_private::RegisterContext
+{
+public:
+    RegisterContextPOSIX_arm64 (lldb_private::Thread &thread,
+                            uint32_t concrete_frame_idx,
+                            lldb_private::RegisterInfoInterface *register_info);
+
+    ~RegisterContextPOSIX_arm64();
+
+    void
+    Invalidate();
+
+    void
+    InvalidateAllRegisters();
+
+    size_t
+    GetRegisterCount();
+
+    virtual size_t
+    GetGPRSize();
+
+    virtual unsigned
+    GetRegisterSize(unsigned reg);
+
+    virtual unsigned
+    GetRegisterOffset(unsigned reg);
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex(size_t reg);
+
+    size_t
+    GetRegisterSetCount();
+
+    const lldb_private::RegisterSet *
+    GetRegisterSet(size_t set);
+
+    const char *
+    GetRegisterName(unsigned reg);
+
+    uint32_t
+    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+
+protected:
+    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;
+    };
+
+    // based on RegisterContextDarwin_arm64.h
+    struct VReg
+    {
+        uint8_t bytes[16];
+    };
+
+    // based on RegisterContextDarwin_arm64.h
+    struct FPU
+    {
+        VReg        v[32];
+        uint32_t    fpsr;
+        uint32_t    fpcr;
+    };
+
+    uint64_t m_gpr_arm64[k_num_gpr_registers_arm64];           // 64-bit general purpose registers.
+    RegInfo  m_reg_info;
+    struct RegisterContextPOSIX_arm64::FPU    m_fpr;           // floating-point registers including extended register sets.
+    std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux)
+
+    // Determines if an extended register set is supported on the processor running the inferior process.
+    virtual bool
+    IsRegisterSetAvailable(size_t set_index);
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfo();
+
+    bool
+    IsGPR(unsigned reg);
+
+    bool
+    IsFPR(unsigned reg);
+
+    lldb::ByteOrder GetByteOrder();
+
+    virtual bool ReadGPR() = 0;
+    virtual bool ReadFPR() = 0;
+    virtual bool WriteGPR() = 0;
+    virtual bool WriteFPR() = 0;
+};
+
+#endif // #ifndef liblldb_RegisterContextPOSIX_arm64_H_





More information about the lldb-commits mailing list