forked from OSchip/llvm-project
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:
parent
26411d6929
commit
c5c4e3a35b
|
@ -10,6 +10,7 @@ add_lldb_library(lldbPluginProcessPOSIX
|
|||
ProcessMessage.cpp
|
||||
ProcessPOSIX.cpp
|
||||
ProcessPOSIXLog.cpp
|
||||
RegisterContextPOSIXProcessMonitor_arm64.cpp
|
||||
RegisterContextPOSIXProcessMonitor_mips64.cpp
|
||||
RegisterContextPOSIXProcessMonitor_x86.cpp
|
||||
)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
Loading…
Reference in New Issue