Linux ARM64: add ProcessMonitor-related RegisterContext support.

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

Change by Paul Osmialowski.

llvm-svn: 216907
This commit is contained in:
Todd Fiala 2014-09-02 14:50:01 +00:00
parent 26411d6929
commit c5c4e3a35b
7 changed files with 996 additions and 0 deletions

View File

@ -10,6 +10,7 @@ add_lldb_library(lldbPluginProcessPOSIX
ProcessMessage.cpp
ProcessPOSIX.cpp
ProcessPOSIXLog.cpp
RegisterContextPOSIXProcessMonitor_arm64.cpp
RegisterContextPOSIXProcessMonitor_mips64.cpp
RegisterContextPOSIXProcessMonitor_x86.cpp
)

View File

@ -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(unsigned offset)
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 reg)
assert(false && "CPU type not supported!");
break;
case llvm::Triple::aarch64:
case llvm::Triple::mips64:
case llvm::Triple::x86:
case llvm::Triple::x86_64:

View File

@ -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;
}

View File

@ -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

View File

@ -27,6 +27,7 @@ add_lldb_library(lldbPluginProcessUtility
RegisterContextMach_i386.cpp
RegisterContextMach_x86_64.cpp
RegisterContextMemory.cpp
RegisterContextPOSIX_arm64.cpp
RegisterContextPOSIX_mips64.cpp
RegisterContextPOSIX_x86.cpp
RegisterContextThreadMemory.cpp

View File

@ -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;
}

View File

@ -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_