forked from OSchip/llvm-project
Adds Register Context Linux/POSIX for ARM Architecture
This patch is major step towards supporting lldb on ARM. This adds all the required bits to support register manipulation on Linux Arm. Also adds utility enumerations, definitions and register context classes for arm. llvm-svn: 234870
This commit is contained in:
parent
ff499469e0
commit
3f57216ca4
|
@ -7,6 +7,7 @@ include_directories(../Utility)
|
||||||
add_lldb_library(lldbPluginProcessLinux
|
add_lldb_library(lldbPluginProcessLinux
|
||||||
LinuxThread.cpp
|
LinuxThread.cpp
|
||||||
NativeProcessLinux.cpp
|
NativeProcessLinux.cpp
|
||||||
|
NativeRegisterContextLinux_arm.cpp
|
||||||
NativeRegisterContextLinux_arm64.cpp
|
NativeRegisterContextLinux_arm64.cpp
|
||||||
NativeRegisterContextLinux_x86_64.cpp
|
NativeRegisterContextLinux_x86_64.cpp
|
||||||
NativeRegisterContextLinux_mips64.cpp
|
NativeRegisterContextLinux_mips64.cpp
|
||||||
|
|
|
@ -0,0 +1,520 @@
|
||||||
|
//===-- NativeRegisterContextLinux_arm.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_arm.h"
|
||||||
|
|
||||||
|
#include "lldb/lldb-private-forward.h"
|
||||||
|
#include "lldb/Core/DataBufferHeap.h"
|
||||||
|
#include "lldb/Core/Error.h"
|
||||||
|
#include "lldb/Core/RegisterValue.h"
|
||||||
|
#include "lldb/Host/common/NativeProcessProtocol.h"
|
||||||
|
#include "lldb/Host/common/NativeThreadProtocol.h"
|
||||||
|
#include "Plugins/Process/Linux/NativeProcessLinux.h"
|
||||||
|
|
||||||
|
#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
|
||||||
|
|
||||||
|
using namespace lldb;
|
||||||
|
using namespace lldb_private;
|
||||||
|
using namespace lldb_private::process_linux;
|
||||||
|
|
||||||
|
// arm general purpose registers.
|
||||||
|
static const uint32_t g_gpr_regnums_arm[] =
|
||||||
|
{
|
||||||
|
gpr_r0_arm,
|
||||||
|
gpr_r1_arm,
|
||||||
|
gpr_r2_arm,
|
||||||
|
gpr_r3_arm,
|
||||||
|
gpr_r4_arm,
|
||||||
|
gpr_r5_arm,
|
||||||
|
gpr_r6_arm,
|
||||||
|
gpr_r7_arm,
|
||||||
|
gpr_r8_arm,
|
||||||
|
gpr_r9_arm,
|
||||||
|
gpr_r10_arm,
|
||||||
|
gpr_r11_arm,
|
||||||
|
gpr_r12_arm,
|
||||||
|
gpr_sp_arm,
|
||||||
|
gpr_lr_arm,
|
||||||
|
gpr_pc_arm,
|
||||||
|
gpr_cpsr_arm,
|
||||||
|
LLDB_INVALID_REGNUM // register sets need to end with this flag
|
||||||
|
};
|
||||||
|
static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == k_num_gpr_registers_arm, \
|
||||||
|
"g_gpr_regnums_arm has wrong number of register infos");
|
||||||
|
|
||||||
|
// arm floating point registers.
|
||||||
|
static const uint32_t g_fpu_regnums_arm[] =
|
||||||
|
{
|
||||||
|
fpu_s0_arm,
|
||||||
|
fpu_s1_arm,
|
||||||
|
fpu_s2_arm,
|
||||||
|
fpu_s3_arm,
|
||||||
|
fpu_s4_arm,
|
||||||
|
fpu_s5_arm,
|
||||||
|
fpu_s6_arm,
|
||||||
|
fpu_s7_arm,
|
||||||
|
fpu_s8_arm,
|
||||||
|
fpu_s9_arm,
|
||||||
|
fpu_s10_arm,
|
||||||
|
fpu_s11_arm,
|
||||||
|
fpu_s12_arm,
|
||||||
|
fpu_s13_arm,
|
||||||
|
fpu_s14_arm,
|
||||||
|
fpu_s15_arm,
|
||||||
|
fpu_s16_arm,
|
||||||
|
fpu_s17_arm,
|
||||||
|
fpu_s18_arm,
|
||||||
|
fpu_s19_arm,
|
||||||
|
fpu_s20_arm,
|
||||||
|
fpu_s21_arm,
|
||||||
|
fpu_s22_arm,
|
||||||
|
fpu_s23_arm,
|
||||||
|
fpu_s24_arm,
|
||||||
|
fpu_s25_arm,
|
||||||
|
fpu_s26_arm,
|
||||||
|
fpu_s27_arm,
|
||||||
|
fpu_s28_arm,
|
||||||
|
fpu_s29_arm,
|
||||||
|
fpu_s30_arm,
|
||||||
|
fpu_s31_arm,
|
||||||
|
fpu_fpscr_arm,
|
||||||
|
LLDB_INVALID_REGNUM // register sets need to end with this flag
|
||||||
|
};
|
||||||
|
static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == k_num_fpr_registers_arm, \
|
||||||
|
"g_fpu_regnums_arm has wrong number of register infos");
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Number of register sets provided by this context.
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
k_num_register_sets = 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register sets for arm.
|
||||||
|
static const RegisterSet
|
||||||
|
g_reg_sets_arm[k_num_register_sets] =
|
||||||
|
{
|
||||||
|
{ "General Purpose Registers", "gpr", k_num_gpr_registers_arm, g_gpr_regnums_arm },
|
||||||
|
{ "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm }
|
||||||
|
};
|
||||||
|
|
||||||
|
NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (
|
||||||
|
NativeThreadProtocol &native_thread,
|
||||||
|
uint32_t concrete_frame_idx,
|
||||||
|
RegisterInfoInterface *reg_info_interface_p) :
|
||||||
|
NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p)
|
||||||
|
{
|
||||||
|
switch (reg_info_interface_p->m_target_arch.GetMachine())
|
||||||
|
{
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
m_reg_info.num_registers = k_num_registers_arm;
|
||||||
|
m_reg_info.num_gpr_registers = k_num_gpr_registers_arm;
|
||||||
|
m_reg_info.num_fpr_registers = k_num_fpr_registers_arm;
|
||||||
|
m_reg_info.last_gpr = k_last_gpr_arm;
|
||||||
|
m_reg_info.first_fpr = k_first_fpr_arm;
|
||||||
|
m_reg_info.last_fpr = k_last_fpr_arm;
|
||||||
|
m_reg_info.first_fpr_v = fpu_s0_arm;
|
||||||
|
m_reg_info.last_fpr_v = fpu_s31_arm;
|
||||||
|
m_reg_info.gpr_flags = gpr_cpsr_arm;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false && "Unhandled target architecture.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
::memset(&m_fpr, 0, sizeof (m_fpr));
|
||||||
|
::memset(&m_gpr_arm, 0, sizeof (m_gpr_arm));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
NativeRegisterContextLinux_arm::GetRegisterSetCount () const
|
||||||
|
{
|
||||||
|
return k_num_register_sets;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RegisterSet *
|
||||||
|
NativeRegisterContextLinux_arm::GetRegisterSet (uint32_t set_index) const
|
||||||
|
{
|
||||||
|
if (set_index < k_num_register_sets)
|
||||||
|
return &g_reg_sets_arm[set_index];
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error
|
||||||
|
NativeRegisterContextLinux_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value)
|
||||||
|
{
|
||||||
|
Error error;
|
||||||
|
|
||||||
|
if (!reg_info)
|
||||||
|
{
|
||||||
|
error.SetErrorString ("reg_info NULL");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
reg_value.SetUInt16(*(uint16_t *)src);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
reg_value.SetUInt32(*(uint32_t *)src);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
reg_value.SetUInt64(*(uint64_t *)src);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false && "Unhandled data size.");
|
||||||
|
error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error
|
||||||
|
NativeRegisterContextLinux_arm::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value)
|
||||||
|
{
|
||||||
|
if (!reg_info)
|
||||||
|
return Error ("reg_info 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 WriteRegisterRaw(reg_index, reg_value);
|
||||||
|
|
||||||
|
if (IsFPR(reg_index))
|
||||||
|
{
|
||||||
|
// Get pointer to m_fpr variable and set the data to it.
|
||||||
|
assert (reg_info->byte_offset < sizeof(m_fpr));
|
||||||
|
uint8_t *dst = (uint8_t *)&m_fpr + 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 ("NativeRegisterContextLinux_arm::WriteRegister: WriteFPR failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
Error
|
||||||
|
NativeRegisterContextLinux_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
|
||||||
|
{
|
||||||
|
Error error;
|
||||||
|
|
||||||
|
data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
|
||||||
|
if (!data_sp)
|
||||||
|
return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE);
|
||||||
|
|
||||||
|
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_arm, GetGPRSize());
|
||||||
|
dst += GetGPRSize();
|
||||||
|
::memcpy (dst, &m_fpr, sizeof(m_fpr));
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error
|
||||||
|
NativeRegisterContextLinux_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
|
||||||
|
{
|
||||||
|
Error error;
|
||||||
|
|
||||||
|
if (!data_sp)
|
||||||
|
{
|
||||||
|
error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
|
||||||
|
{
|
||||||
|
error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%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_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
::memcpy (&m_gpr_arm, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error
|
||||||
|
NativeRegisterContextLinux_arm::WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value)
|
||||||
|
{
|
||||||
|
Error error;
|
||||||
|
|
||||||
|
uint32_t reg_to_write = reg_index;
|
||||||
|
RegisterValue value_to_write = reg_value;
|
||||||
|
|
||||||
|
// Check if this is a subregister of a full register.
|
||||||
|
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index);
|
||||||
|
if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
|
||||||
|
{
|
||||||
|
RegisterValue full_value;
|
||||||
|
uint32_t full_reg = reg_info->invalidate_regs[0];
|
||||||
|
const 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[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[RegisterValue::kMaxRegisterByteSize];
|
||||||
|
|
||||||
|
// Get the bytes for the source data.
|
||||||
|
const uint32_t src_size = reg_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 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_arm::%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 ());
|
||||||
|
return process_p->WriteRegisterValue(m_thread.GetID(),
|
||||||
|
register_to_write_info_p->byte_offset,
|
||||||
|
register_to_write_info_p->name,
|
||||||
|
value_to_write);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error
|
||||||
|
NativeRegisterContextLinux_arm::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value)
|
||||||
|
{
|
||||||
|
Error error;
|
||||||
|
const 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 ());
|
||||||
|
return process_p->ReadRegisterValue(m_thread.GetID(),
|
||||||
|
reg_info->byte_offset,
|
||||||
|
reg_info->name,
|
||||||
|
reg_info->byte_size,
|
||||||
|
reg_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const
|
||||||
|
{
|
||||||
|
return reg <= m_reg_info.last_gpr; // GPR's come first.
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NativeRegisterContextLinux_arm::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_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NativeRegisterContextLinux_arm::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_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const
|
||||||
|
{
|
||||||
|
return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NativeRegisterContextLinux_arm::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)).Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NativeRegisterContextLinux_arm::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)).Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
lldb::ByteOrder
|
||||||
|
NativeRegisterContextLinux_arm::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
NativeRegisterContextLinux_arm::GetGPRSize() const
|
||||||
|
{
|
||||||
|
return GetRegisterInfoInterface().GetGPRSize();
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
//===-- NativeRegisterContextLinux_arm.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_arm_h
|
||||||
|
#define lldb_NativeRegisterContextLinux_arm_h
|
||||||
|
|
||||||
|
#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h"
|
||||||
|
#include "Plugins/Process/Utility/lldb-arm-register-enums.h"
|
||||||
|
|
||||||
|
namespace lldb_private {
|
||||||
|
namespace process_linux {
|
||||||
|
|
||||||
|
class NativeProcessLinux;
|
||||||
|
|
||||||
|
class NativeRegisterContextLinux_arm : public NativeRegisterContextRegisterInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NativeRegisterContextLinux_arm (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:
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QReg
|
||||||
|
{
|
||||||
|
uint8_t bytes[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FPU
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
uint32_t s[32];
|
||||||
|
uint64_t d[32];
|
||||||
|
QReg q[16]; // the 128-bit NEON registers
|
||||||
|
} floats;
|
||||||
|
uint32_t fpscr;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t m_gpr_arm[k_num_gpr_registers_arm];
|
||||||
|
RegInfo m_reg_info;
|
||||||
|
FPU m_fpr;
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsGPR(unsigned reg) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
ReadGPR ();
|
||||||
|
|
||||||
|
bool
|
||||||
|
WriteGPR ();
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsFPR(unsigned reg) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
ReadFPR ();
|
||||||
|
|
||||||
|
bool
|
||||||
|
WriteFPR ();
|
||||||
|
|
||||||
|
Error
|
||||||
|
ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value);
|
||||||
|
|
||||||
|
Error
|
||||||
|
WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value);
|
||||||
|
|
||||||
|
lldb::ByteOrder
|
||||||
|
GetByteOrder() const;
|
||||||
|
|
||||||
|
size_t
|
||||||
|
GetGPRSize() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace process_linux
|
||||||
|
} // namespace lldb_private
|
||||||
|
|
||||||
|
#endif // #ifndef lldb_NativeRegisterContextLinux_arm_h
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "NativeProcessLinux.h"
|
#include "NativeProcessLinux.h"
|
||||||
|
#include "NativeRegisterContextLinux_arm.h"
|
||||||
#include "NativeRegisterContextLinux_arm64.h"
|
#include "NativeRegisterContextLinux_arm64.h"
|
||||||
#include "NativeRegisterContextLinux_x86_64.h"
|
#include "NativeRegisterContextLinux_x86_64.h"
|
||||||
#include "NativeRegisterContextLinux_mips64.h"
|
#include "NativeRegisterContextLinux_mips64.h"
|
||||||
|
@ -29,6 +30,7 @@
|
||||||
|
|
||||||
#include "Plugins/Process/POSIX/CrashReason.h"
|
#include "Plugins/Process/POSIX/CrashReason.h"
|
||||||
|
|
||||||
|
#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
|
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
|
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
||||||
|
@ -184,6 +186,10 @@ NativeThreadLinux::GetRegisterContext ()
|
||||||
assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host");
|
assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host");
|
||||||
reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch));
|
reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch));
|
||||||
break;
|
break;
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
assert(HostInfo::GetArchitecture ().GetAddressByteSize() == 4);
|
||||||
|
reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm(target_arch));
|
||||||
|
break;
|
||||||
case llvm::Triple::x86:
|
case llvm::Triple::x86:
|
||||||
case llvm::Triple::x86_64:
|
case llvm::Triple::x86_64:
|
||||||
if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
|
if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
|
||||||
|
@ -242,6 +248,12 @@ NativeThreadLinux::GetRegisterContext ()
|
||||||
m_reg_context_sp.reset (new NativeRegisterContextLinux_arm64(*this, concrete_frame_idx, reg_interface));
|
m_reg_context_sp.reset (new NativeRegisterContextLinux_arm64(*this, concrete_frame_idx, reg_interface));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
{
|
||||||
|
const uint32_t concrete_frame_idx = 0;
|
||||||
|
m_reg_context_sp.reset (new NativeRegisterContextLinux_arm(*this, concrete_frame_idx, reg_interface));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case llvm::Triple::x86:
|
case llvm::Triple::x86:
|
||||||
case llvm::Triple::x86_64:
|
case llvm::Triple::x86_64:
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,6 +11,7 @@ add_lldb_library(lldbPluginProcessPOSIX
|
||||||
ProcessMessage.cpp
|
ProcessMessage.cpp
|
||||||
ProcessPOSIX.cpp
|
ProcessPOSIX.cpp
|
||||||
ProcessPOSIXLog.cpp
|
ProcessPOSIXLog.cpp
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm.cpp
|
||||||
RegisterContextPOSIXProcessMonitor_arm64.cpp
|
RegisterContextPOSIXProcessMonitor_arm64.cpp
|
||||||
RegisterContextPOSIXProcessMonitor_mips64.cpp
|
RegisterContextPOSIXProcessMonitor_mips64.cpp
|
||||||
RegisterContextPOSIXProcessMonitor_powerpc.cpp
|
RegisterContextPOSIXProcessMonitor_powerpc.cpp
|
||||||
|
|
|
@ -32,10 +32,12 @@
|
||||||
#include "ProcessPOSIX.h"
|
#include "ProcessPOSIX.h"
|
||||||
#include "ProcessPOSIXLog.h"
|
#include "ProcessPOSIXLog.h"
|
||||||
#include "Plugins/Process/Linux/ProcessMonitor.h"
|
#include "Plugins/Process/Linux/ProcessMonitor.h"
|
||||||
|
#include "RegisterContextPOSIXProcessMonitor_arm.h"
|
||||||
#include "RegisterContextPOSIXProcessMonitor_arm64.h"
|
#include "RegisterContextPOSIXProcessMonitor_arm64.h"
|
||||||
#include "RegisterContextPOSIXProcessMonitor_mips64.h"
|
#include "RegisterContextPOSIXProcessMonitor_mips64.h"
|
||||||
#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
|
#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
|
||||||
#include "RegisterContextPOSIXProcessMonitor_x86.h"
|
#include "RegisterContextPOSIXProcessMonitor_x86.h"
|
||||||
|
#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
|
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
|
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
||||||
|
@ -198,6 +200,10 @@ POSIXThread::GetRegisterContext()
|
||||||
assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host");
|
assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host");
|
||||||
reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch));
|
reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch));
|
||||||
break;
|
break;
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
assert(HostInfo::GetArchitecture().GetAddressByteSize() == 4);
|
||||||
|
reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm(target_arch));
|
||||||
|
break;
|
||||||
case llvm::Triple::x86:
|
case llvm::Triple::x86:
|
||||||
case llvm::Triple::x86_64:
|
case llvm::Triple::x86_64:
|
||||||
if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
|
if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
|
||||||
|
@ -232,6 +238,13 @@ POSIXThread::GetRegisterContext()
|
||||||
m_reg_context_sp.reset(reg_ctx);
|
m_reg_context_sp.reset(reg_ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
{
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm(*this, 0, reg_interface);
|
||||||
|
m_posix_thread = reg_ctx;
|
||||||
|
m_reg_context_sp.reset(reg_ctx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case llvm::Triple::mips64:
|
case llvm::Triple::mips64:
|
||||||
{
|
{
|
||||||
RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
|
RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
|
||||||
|
@ -644,6 +657,7 @@ POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case llvm::Triple::aarch64:
|
case llvm::Triple::aarch64:
|
||||||
|
case llvm::Triple::arm:
|
||||||
case llvm::Triple::mips64:
|
case llvm::Triple::mips64:
|
||||||
case llvm::Triple::ppc:
|
case llvm::Triple::ppc:
|
||||||
case llvm::Triple::ppc64:
|
case llvm::Triple::ppc64:
|
||||||
|
@ -677,6 +691,7 @@ POSIXThread::GetRegisterName(unsigned reg)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case llvm::Triple::aarch64:
|
case llvm::Triple::aarch64:
|
||||||
|
case llvm::Triple::arm:
|
||||||
case llvm::Triple::mips64:
|
case llvm::Triple::mips64:
|
||||||
case llvm::Triple::ppc:
|
case llvm::Triple::ppc:
|
||||||
case llvm::Triple::ppc64:
|
case llvm::Triple::ppc64:
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
// C++ Includes
|
// C++ Includes
|
||||||
// Other libraries and framework includes
|
// Other libraries and framework includes
|
||||||
|
#include "lldb/Breakpoint/BreakpointLocation.h"
|
||||||
#include "lldb/Breakpoint/Watchpoint.h"
|
#include "lldb/Breakpoint/Watchpoint.h"
|
||||||
#include "lldb/Core/Module.h"
|
#include "lldb/Core/Module.h"
|
||||||
#include "lldb/Core/ModuleSpec.h"
|
#include "lldb/Core/ModuleSpec.h"
|
||||||
|
@ -638,6 +639,33 @@ ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
|
||||||
assert(false && "CPU type not supported!");
|
assert(false && "CPU type not supported!");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
{
|
||||||
|
// The ARM reference recommends the use of 0xe7fddefe and 0xdefe
|
||||||
|
// but the linux kernel does otherwise.
|
||||||
|
static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
|
||||||
|
static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };
|
||||||
|
|
||||||
|
lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
|
||||||
|
AddressClass addr_class = eAddressClassUnknown;
|
||||||
|
|
||||||
|
if (bp_loc_sp)
|
||||||
|
addr_class = bp_loc_sp->GetAddress ().GetAddressClass ();
|
||||||
|
|
||||||
|
if (addr_class == eAddressClassCodeAlternateISA
|
||||||
|
|| (addr_class == eAddressClassUnknown
|
||||||
|
&& bp_loc_sp->GetAddress().GetOffset() & 1))
|
||||||
|
{
|
||||||
|
opcode = g_thumb_breakpoint_opcode;
|
||||||
|
opcode_size = sizeof(g_thumb_breakpoint_opcode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opcode = g_arm_breakpoint_opcode;
|
||||||
|
opcode_size = sizeof(g_arm_breakpoint_opcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case llvm::Triple::aarch64:
|
case llvm::Triple::aarch64:
|
||||||
opcode = g_aarch64_opcode;
|
opcode = g_aarch64_opcode;
|
||||||
opcode_size = sizeof(g_aarch64_opcode);
|
opcode_size = sizeof(g_aarch64_opcode);
|
||||||
|
|
|
@ -0,0 +1,322 @@
|
||||||
|
//===-- RegisterContextPOSIXProcessMonitor_arm.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/Core/DataBufferHeap.h"
|
||||||
|
#include "lldb/Core/RegisterValue.h"
|
||||||
|
#include "lldb/Target/Thread.h"
|
||||||
|
|
||||||
|
#include "RegisterContextPOSIX_arm.h"
|
||||||
|
#include "ProcessPOSIX.h"
|
||||||
|
#include "RegisterContextPOSIXProcessMonitor_arm.h"
|
||||||
|
#include "ProcessMonitor.h"
|
||||||
|
|
||||||
|
using namespace lldb_private;
|
||||||
|
using namespace lldb;
|
||||||
|
|
||||||
|
#define REG_CONTEXT_SIZE (GetGPRSize())
|
||||||
|
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::RegisterContextPOSIXProcessMonitor_arm(Thread &thread,
|
||||||
|
uint32_t concrete_frame_idx,
|
||||||
|
lldb_private::RegisterInfoInterface *register_info)
|
||||||
|
: RegisterContextPOSIX_arm(thread, concrete_frame_idx, register_info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessMonitor &
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::GetMonitor()
|
||||||
|
{
|
||||||
|
ProcessSP base = CalculateProcess();
|
||||||
|
ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
|
||||||
|
return process->GetMonitor();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::ReadGPR()
|
||||||
|
{
|
||||||
|
ProcessMonitor &monitor = GetMonitor();
|
||||||
|
return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::ReadFPR()
|
||||||
|
{
|
||||||
|
ProcessMonitor &monitor = GetMonitor();
|
||||||
|
return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::WriteGPR()
|
||||||
|
{
|
||||||
|
ProcessMonitor &monitor = GetMonitor();
|
||||||
|
return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::WriteFPR()
|
||||||
|
{
|
||||||
|
ProcessMonitor &monitor = GetMonitor();
|
||||||
|
return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::ReadRegister(const unsigned reg,
|
||||||
|
RegisterValue &value)
|
||||||
|
{
|
||||||
|
ProcessMonitor &monitor = GetMonitor();
|
||||||
|
return monitor.ReadRegisterValue(m_thread.GetID(),
|
||||||
|
GetRegisterOffset(reg),
|
||||||
|
GetRegisterName(reg),
|
||||||
|
GetRegisterSize(reg),
|
||||||
|
value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::WriteRegister(const unsigned reg,
|
||||||
|
const RegisterValue &value)
|
||||||
|
{
|
||||||
|
unsigned reg_to_write = reg;
|
||||||
|
RegisterValue value_to_write = value;
|
||||||
|
|
||||||
|
// Check if this is a subregister of a full register.
|
||||||
|
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
|
||||||
|
if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
|
||||||
|
{
|
||||||
|
RegisterValue full_value;
|
||||||
|
uint32_t full_reg = reg_info->invalidate_regs[0];
|
||||||
|
const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
|
||||||
|
|
||||||
|
// Read the full register.
|
||||||
|
if (ReadRegister(full_reg_info, full_value))
|
||||||
|
{
|
||||||
|
Error error;
|
||||||
|
ByteOrder byte_order = GetByteOrder();
|
||||||
|
uint8_t dst[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[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_arm::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
|
||||||
|
{
|
||||||
|
if (!reg_info)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
|
||||||
|
|
||||||
|
if (IsFPR(reg))
|
||||||
|
{
|
||||||
|
if (!ReadFPR())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ReadRegister(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_arm::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
|
||||||
|
{
|
||||||
|
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
|
||||||
|
|
||||||
|
if (IsGPR(reg))
|
||||||
|
{
|
||||||
|
return WriteRegister(reg, value);
|
||||||
|
}
|
||||||
|
else if (IsFPR(reg))
|
||||||
|
{
|
||||||
|
return WriteFPR();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::ReadAllRegisterValues(DataBufferSP &data_sp)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
data_sp.reset (new 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_arm, GetGPRSize());
|
||||||
|
dst += GetGPRSize();
|
||||||
|
::memcpy (dst, &m_fpr, sizeof(m_fpr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::WriteAllRegisterValues(const 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_arm, src, GetGPRSize());
|
||||||
|
|
||||||
|
if (WriteGPR())
|
||||||
|
{
|
||||||
|
src += GetGPRSize();
|
||||||
|
::memcpy (&m_fpr, src, sizeof(m_fpr));
|
||||||
|
|
||||||
|
success = WriteFPR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpoint(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_arm::ClearHardwareWatchpoint(uint32_t hw_index)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::HardwareSingleStep(bool enable)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::UpdateAfterBreakpoint()
|
||||||
|
{
|
||||||
|
lldb::addr_t pc;
|
||||||
|
|
||||||
|
if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::GetRegisterIndexFromOffset(unsigned offset)
|
||||||
|
{
|
||||||
|
unsigned reg;
|
||||||
|
for (reg = 0; reg < k_num_registers_arm; reg++)
|
||||||
|
{
|
||||||
|
if (GetRegisterInfo()[reg].byte_offset == offset)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(reg < k_num_registers_arm && "Invalid register offset.");
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::IsWatchpointHit(uint32_t hw_index)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::ClearWatchpointHits()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_t
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::GetWatchpointAddress(uint32_t hw_index)
|
||||||
|
{
|
||||||
|
return LLDB_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::IsWatchpointVacant(uint32_t hw_index)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
|
||||||
|
bool read, bool write,
|
||||||
|
uint32_t hw_index)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm::NumSupportedHardwareWatchpoints()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
//===-- RegisterContextPOSIXProcessMonitor_arm.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_arm_H_
|
||||||
|
#define liblldb_RegisterContextPOSIXProcessMonitor_arm_H_
|
||||||
|
|
||||||
|
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
|
||||||
|
|
||||||
|
class RegisterContextPOSIXProcessMonitor_arm:
|
||||||
|
public RegisterContextPOSIX_arm,
|
||||||
|
public POSIXBreakpointProtocol
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RegisterContextPOSIXProcessMonitor_arm(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
|
|
@ -21,6 +21,7 @@ add_lldb_library(lldbPluginProcessUtility
|
||||||
RegisterContextFreeBSD_powerpc.cpp
|
RegisterContextFreeBSD_powerpc.cpp
|
||||||
RegisterContextFreeBSD_x86_64.cpp
|
RegisterContextFreeBSD_x86_64.cpp
|
||||||
RegisterContextHistory.cpp
|
RegisterContextHistory.cpp
|
||||||
|
RegisterContextLinux_arm.cpp
|
||||||
RegisterContextLinux_arm64.cpp
|
RegisterContextLinux_arm64.cpp
|
||||||
RegisterContextLinux_i386.cpp
|
RegisterContextLinux_i386.cpp
|
||||||
RegisterContextLinux_x86_64.cpp
|
RegisterContextLinux_x86_64.cpp
|
||||||
|
@ -31,6 +32,7 @@ add_lldb_library(lldbPluginProcessUtility
|
||||||
RegisterContextMach_i386.cpp
|
RegisterContextMach_i386.cpp
|
||||||
RegisterContextMach_x86_64.cpp
|
RegisterContextMach_x86_64.cpp
|
||||||
RegisterContextMemory.cpp
|
RegisterContextMemory.cpp
|
||||||
|
RegisterContextPOSIX_arm.cpp
|
||||||
RegisterContextPOSIX_arm64.cpp
|
RegisterContextPOSIX_arm64.cpp
|
||||||
RegisterContextPOSIX_mips64.cpp
|
RegisterContextPOSIX_mips64.cpp
|
||||||
RegisterContextPOSIX_powerpc.cpp
|
RegisterContextPOSIX_powerpc.cpp
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
//===-- RegisterContextLinux_arm.cpp ---------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===---------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "llvm/Support/Compiler.h"
|
||||||
|
#include "lldb/lldb-defines.h"
|
||||||
|
|
||||||
|
#include "RegisterContextLinux_arm.h"
|
||||||
|
|
||||||
|
using namespace lldb;
|
||||||
|
using namespace lldb_private;
|
||||||
|
|
||||||
|
// Based on RegisterContextDarwin_arm.cpp
|
||||||
|
#define GPR_OFFSET(idx) ((idx) * 4)
|
||||||
|
#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextLinux_arm::GPR))
|
||||||
|
#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU))
|
||||||
|
#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextLinux_arm::DBG, reg) + sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU) + sizeof (RegisterContextLinux_arm::EXC)))
|
||||||
|
|
||||||
|
#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextLinux_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL
|
||||||
|
#define REG_CONTEXT_SIZE (sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU) + sizeof (RegisterContextLinux_arm::EXC))
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Include RegisterInfos_arm to declare our g_register_infos_arm structure.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define DECLARE_REGISTER_INFOS_ARM_STRUCT
|
||||||
|
#include "RegisterInfos_arm.h"
|
||||||
|
#undef DECLARE_REGISTER_INFOS_ARM_STRUCT
|
||||||
|
|
||||||
|
static const lldb_private::RegisterInfo *
|
||||||
|
GetRegisterInfoPtr (const lldb_private::ArchSpec &target_arch)
|
||||||
|
{
|
||||||
|
switch (target_arch.GetMachine())
|
||||||
|
{
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
return g_register_infos_arm;
|
||||||
|
default:
|
||||||
|
assert(false && "Unhandled target architecture.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch)
|
||||||
|
{
|
||||||
|
switch (target_arch.GetMachine())
|
||||||
|
{
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
return static_cast<uint32_t>(sizeof(g_register_infos_arm) / sizeof(g_register_infos_arm[0]));
|
||||||
|
default:
|
||||||
|
assert(false && "Unhandled target architecture.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterContextLinux_arm::RegisterContextLinux_arm(const lldb_private::ArchSpec &target_arch) :
|
||||||
|
lldb_private::RegisterInfoInterface(target_arch),
|
||||||
|
m_register_info_p(GetRegisterInfoPtr(target_arch)),
|
||||||
|
m_register_info_count(GetRegisterInfoCount(target_arch))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
RegisterContextLinux_arm::GetGPRSize() const
|
||||||
|
{
|
||||||
|
return sizeof(struct RegisterContextLinux_arm::GPR);
|
||||||
|
}
|
||||||
|
|
||||||
|
const lldb_private::RegisterInfo *
|
||||||
|
RegisterContextLinux_arm::GetRegisterInfo() const
|
||||||
|
{
|
||||||
|
return m_register_info_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
RegisterContextLinux_arm::GetRegisterCount() const
|
||||||
|
{
|
||||||
|
return m_register_info_count;
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
//===-- RegisterContextLinux_arm.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_RegisterContextLinux_arm_h_
|
||||||
|
#define liblldb_RegisterContextLinux_arm_h_
|
||||||
|
|
||||||
|
#include "lldb/lldb-private.h"
|
||||||
|
#include "lldb/Target/RegisterContext.h"
|
||||||
|
#include "RegisterContextPOSIX.h"
|
||||||
|
#include "RegisterInfoInterface.h"
|
||||||
|
|
||||||
|
class RegisterContextLinux_arm
|
||||||
|
: public lldb_private::RegisterInfoInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct GPR
|
||||||
|
{
|
||||||
|
uint32_t r[16]; // R0-R15
|
||||||
|
uint32_t cpsr; // CPSR
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct QReg
|
||||||
|
{
|
||||||
|
uint8_t bytes[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FPU
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
uint32_t s[32];
|
||||||
|
uint64_t d[32];
|
||||||
|
QReg q[16]; // the 128-bit NEON registers
|
||||||
|
} floats;
|
||||||
|
uint32_t fpscr;
|
||||||
|
};
|
||||||
|
struct EXC
|
||||||
|
{
|
||||||
|
uint32_t exception;
|
||||||
|
uint32_t fsr; /* Fault status */
|
||||||
|
uint32_t far; /* Virtual Fault Address */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DBG
|
||||||
|
{
|
||||||
|
uint32_t bvr[16];
|
||||||
|
uint32_t bcr[16];
|
||||||
|
uint32_t wvr[16];
|
||||||
|
uint32_t wcr[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterContextLinux_arm(const lldb_private::ArchSpec &target_arch);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
GetGPRSize() const override;
|
||||||
|
|
||||||
|
const lldb_private::RegisterInfo *
|
||||||
|
GetRegisterInfo() const override;
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
GetRegisterCount () const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const lldb_private::RegisterInfo *m_register_info_p;
|
||||||
|
uint32_t m_register_info_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // liblldb_RegisterContextLinux_arm_h_
|
||||||
|
|
|
@ -0,0 +1,287 @@
|
||||||
|
//===-- RegisterContextPOSIX_arm.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_arm.h"
|
||||||
|
#include "Plugins/Process/elf-core/ProcessElfCore.h"
|
||||||
|
|
||||||
|
using namespace lldb;
|
||||||
|
using namespace lldb_private;
|
||||||
|
|
||||||
|
// arm general purpose registers.
|
||||||
|
const uint32_t g_gpr_regnums_arm[] =
|
||||||
|
{
|
||||||
|
gpr_r0_arm,
|
||||||
|
gpr_r1_arm,
|
||||||
|
gpr_r2_arm,
|
||||||
|
gpr_r3_arm,
|
||||||
|
gpr_r4_arm,
|
||||||
|
gpr_r5_arm,
|
||||||
|
gpr_r6_arm,
|
||||||
|
gpr_r7_arm,
|
||||||
|
gpr_r8_arm,
|
||||||
|
gpr_r9_arm,
|
||||||
|
gpr_r10_arm,
|
||||||
|
gpr_r11_arm,
|
||||||
|
gpr_r12_arm,
|
||||||
|
gpr_sp_arm,
|
||||||
|
gpr_lr_arm,
|
||||||
|
gpr_pc_arm,
|
||||||
|
gpr_cpsr_arm,
|
||||||
|
LLDB_INVALID_REGNUM // register sets need to end with this flag
|
||||||
|
|
||||||
|
};
|
||||||
|
static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == k_num_gpr_registers_arm, \
|
||||||
|
"g_gpr_regnums_arm has wrong number of register infos");
|
||||||
|
|
||||||
|
// arm floating point registers.
|
||||||
|
static const uint32_t g_fpu_regnums_arm[] =
|
||||||
|
{
|
||||||
|
fpu_s0_arm,
|
||||||
|
fpu_s1_arm,
|
||||||
|
fpu_s2_arm,
|
||||||
|
fpu_s3_arm,
|
||||||
|
fpu_s4_arm,
|
||||||
|
fpu_s5_arm,
|
||||||
|
fpu_s6_arm,
|
||||||
|
fpu_s7_arm,
|
||||||
|
fpu_s8_arm,
|
||||||
|
fpu_s9_arm,
|
||||||
|
fpu_s10_arm,
|
||||||
|
fpu_s11_arm,
|
||||||
|
fpu_s12_arm,
|
||||||
|
fpu_s13_arm,
|
||||||
|
fpu_s14_arm,
|
||||||
|
fpu_s15_arm,
|
||||||
|
fpu_s16_arm,
|
||||||
|
fpu_s17_arm,
|
||||||
|
fpu_s18_arm,
|
||||||
|
fpu_s19_arm,
|
||||||
|
fpu_s20_arm,
|
||||||
|
fpu_s21_arm,
|
||||||
|
fpu_s22_arm,
|
||||||
|
fpu_s23_arm,
|
||||||
|
fpu_s24_arm,
|
||||||
|
fpu_s25_arm,
|
||||||
|
fpu_s26_arm,
|
||||||
|
fpu_s27_arm,
|
||||||
|
fpu_s28_arm,
|
||||||
|
fpu_s29_arm,
|
||||||
|
fpu_s30_arm,
|
||||||
|
fpu_s31_arm,
|
||||||
|
fpu_fpscr_arm,
|
||||||
|
LLDB_INVALID_REGNUM // register sets need to end with this flag
|
||||||
|
|
||||||
|
};
|
||||||
|
static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == k_num_fpr_registers_arm, \
|
||||||
|
"g_fpu_regnums_arm has wrong number of register infos");
|
||||||
|
|
||||||
|
// Number of register sets provided by this context.
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
k_num_register_sets = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// Register sets for arm.
|
||||||
|
static const lldb_private::RegisterSet
|
||||||
|
g_reg_sets_arm[k_num_register_sets] =
|
||||||
|
{
|
||||||
|
{ "General Purpose Registers", "gpr", k_num_gpr_registers_arm, g_gpr_regnums_arm },
|
||||||
|
{ "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm }
|
||||||
|
};
|
||||||
|
|
||||||
|
bool RegisterContextPOSIX_arm::IsGPR(unsigned reg)
|
||||||
|
{
|
||||||
|
return reg <= m_reg_info.last_gpr; // GPR's come first.
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RegisterContextPOSIX_arm::IsFPR(unsigned reg)
|
||||||
|
{
|
||||||
|
return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterContextPOSIX_arm::RegisterContextPOSIX_arm(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::arm:
|
||||||
|
m_reg_info.num_registers = k_num_registers_arm;
|
||||||
|
m_reg_info.num_gpr_registers = k_num_gpr_registers_arm;
|
||||||
|
m_reg_info.num_fpr_registers = k_num_fpr_registers_arm;
|
||||||
|
m_reg_info.last_gpr = k_last_gpr_arm;
|
||||||
|
m_reg_info.first_fpr = k_first_fpr_arm;
|
||||||
|
m_reg_info.last_fpr = k_last_fpr_arm;
|
||||||
|
m_reg_info.first_fpr_v = fpu_s0_arm;
|
||||||
|
m_reg_info.last_fpr_v = fpu_s31_arm;
|
||||||
|
m_reg_info.gpr_flags = gpr_cpsr_arm;
|
||||||
|
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_arm::~RegisterContextPOSIX_arm()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RegisterContextPOSIX_arm::Invalidate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RegisterContextPOSIX_arm::InvalidateAllRegisters()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
RegisterContextPOSIX_arm::GetRegisterOffset(unsigned reg)
|
||||||
|
{
|
||||||
|
assert(reg < m_reg_info.num_registers && "Invalid register number.");
|
||||||
|
return GetRegisterInfo()[reg].byte_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
RegisterContextPOSIX_arm::GetRegisterSize(unsigned reg)
|
||||||
|
{
|
||||||
|
assert(reg < m_reg_info.num_registers && "Invalid register number.");
|
||||||
|
return GetRegisterInfo()[reg].byte_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
RegisterContextPOSIX_arm::GetRegisterCount()
|
||||||
|
{
|
||||||
|
size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers;
|
||||||
|
return num_registers;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
RegisterContextPOSIX_arm::GetGPRSize()
|
||||||
|
{
|
||||||
|
return m_register_info_ap->GetGPRSize ();
|
||||||
|
}
|
||||||
|
|
||||||
|
const lldb_private::RegisterInfo *
|
||||||
|
RegisterContextPOSIX_arm::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_arm::GetRegisterInfoAtIndex(size_t reg)
|
||||||
|
{
|
||||||
|
if (reg < m_reg_info.num_registers)
|
||||||
|
return &GetRegisterInfo()[reg];
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
RegisterContextPOSIX_arm::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_arm::GetRegisterSet(size_t set)
|
||||||
|
{
|
||||||
|
if (IsRegisterSetAvailable(set))
|
||||||
|
{
|
||||||
|
switch (m_register_info_ap->m_target_arch.GetMachine())
|
||||||
|
{
|
||||||
|
case llvm::Triple::aarch64:
|
||||||
|
return &g_reg_sets_arm[set];
|
||||||
|
default:
|
||||||
|
assert(false && "Unhandled target architecture.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
RegisterContextPOSIX_arm::GetRegisterName(unsigned reg)
|
||||||
|
{
|
||||||
|
assert(reg < m_reg_info.num_registers && "Invalid register offset.");
|
||||||
|
return GetRegisterInfo()[reg].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
lldb::ByteOrder
|
||||||
|
RegisterContextPOSIX_arm::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_arm::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_arm::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,121 @@
|
||||||
|
//===-- RegisterContextPOSIX_arm.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_arm_H_
|
||||||
|
#define liblldb_RegisterContextPOSIX_arm_H_
|
||||||
|
|
||||||
|
#include "lldb/Core/Log.h"
|
||||||
|
#include "lldb-arm-register-enums.h"
|
||||||
|
#include "RegisterContextPOSIX.h"
|
||||||
|
|
||||||
|
class ProcessMonitor;
|
||||||
|
|
||||||
|
class RegisterContextPOSIX_arm
|
||||||
|
: public lldb_private::RegisterContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RegisterContextPOSIX_arm (lldb_private::Thread &thread,
|
||||||
|
uint32_t concrete_frame_idx,
|
||||||
|
lldb_private::RegisterInfoInterface *register_info);
|
||||||
|
|
||||||
|
~RegisterContextPOSIX_arm();
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QReg
|
||||||
|
{
|
||||||
|
uint8_t bytes[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FPU
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
uint32_t s[32];
|
||||||
|
uint64_t d[32];
|
||||||
|
QReg q[16]; // the 128-bit NEON registers
|
||||||
|
} floats;
|
||||||
|
uint32_t fpscr;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t m_gpr_arm[lldb_private::k_num_gpr_registers_arm]; // 32-bit general purpose registers.
|
||||||
|
RegInfo m_reg_info;
|
||||||
|
struct RegisterContextPOSIX_arm::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_arm_H_
|
||||||
|
|
|
@ -0,0 +1,303 @@
|
||||||
|
//===-- RegisterInfos_arm.h ----------------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===---------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifdef DECLARE_REGISTER_INFOS_ARM_STRUCT
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "lldb/lldb-private.h"
|
||||||
|
#include "lldb/lldb-defines.h"
|
||||||
|
#include "lldb/lldb-enumerations.h"
|
||||||
|
|
||||||
|
#include "Utility/ARM_GCC_Registers.h"
|
||||||
|
#include "Utility/ARM_DWARF_Registers.h"
|
||||||
|
|
||||||
|
using namespace lldb;
|
||||||
|
using namespace lldb_private;
|
||||||
|
|
||||||
|
#ifndef GPR_OFFSET
|
||||||
|
#error GPR_OFFSET must be defined before including this header file
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FPU_OFFSET
|
||||||
|
#error FPU_OFFSET must be defined before including this header file
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EXC_OFFSET
|
||||||
|
#error EXC_OFFSET_NAME must be defined before including this header file
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DBG_OFFSET
|
||||||
|
#error DBG_OFFSET_NAME must be defined before including this header file
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEFINE_DBG
|
||||||
|
#error DEFINE_DBG must be defined before including this header file
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
gpr_r0 = 0,
|
||||||
|
gpr_r1,
|
||||||
|
gpr_r2,
|
||||||
|
gpr_r3,
|
||||||
|
gpr_r4,
|
||||||
|
gpr_r5,
|
||||||
|
gpr_r6,
|
||||||
|
gpr_r7,
|
||||||
|
gpr_r8,
|
||||||
|
gpr_r9,
|
||||||
|
gpr_r10,
|
||||||
|
gpr_r11,
|
||||||
|
gpr_r12,
|
||||||
|
gpr_r13, gpr_sp = gpr_r13,
|
||||||
|
gpr_r14, gpr_lr = gpr_r14,
|
||||||
|
gpr_r15, gpr_pc = gpr_r15,
|
||||||
|
gpr_cpsr,
|
||||||
|
|
||||||
|
fpu_s0,
|
||||||
|
fpu_s1,
|
||||||
|
fpu_s2,
|
||||||
|
fpu_s3,
|
||||||
|
fpu_s4,
|
||||||
|
fpu_s5,
|
||||||
|
fpu_s6,
|
||||||
|
fpu_s7,
|
||||||
|
fpu_s8,
|
||||||
|
fpu_s9,
|
||||||
|
fpu_s10,
|
||||||
|
fpu_s11,
|
||||||
|
fpu_s12,
|
||||||
|
fpu_s13,
|
||||||
|
fpu_s14,
|
||||||
|
fpu_s15,
|
||||||
|
fpu_s16,
|
||||||
|
fpu_s17,
|
||||||
|
fpu_s18,
|
||||||
|
fpu_s19,
|
||||||
|
fpu_s20,
|
||||||
|
fpu_s21,
|
||||||
|
fpu_s22,
|
||||||
|
fpu_s23,
|
||||||
|
fpu_s24,
|
||||||
|
fpu_s25,
|
||||||
|
fpu_s26,
|
||||||
|
fpu_s27,
|
||||||
|
fpu_s28,
|
||||||
|
fpu_s29,
|
||||||
|
fpu_s30,
|
||||||
|
fpu_s31,
|
||||||
|
fpu_fpscr,
|
||||||
|
|
||||||
|
exc_exception,
|
||||||
|
exc_fsr,
|
||||||
|
exc_far,
|
||||||
|
|
||||||
|
dbg_bvr0,
|
||||||
|
dbg_bvr1,
|
||||||
|
dbg_bvr2,
|
||||||
|
dbg_bvr3,
|
||||||
|
dbg_bvr4,
|
||||||
|
dbg_bvr5,
|
||||||
|
dbg_bvr6,
|
||||||
|
dbg_bvr7,
|
||||||
|
dbg_bvr8,
|
||||||
|
dbg_bvr9,
|
||||||
|
dbg_bvr10,
|
||||||
|
dbg_bvr11,
|
||||||
|
dbg_bvr12,
|
||||||
|
dbg_bvr13,
|
||||||
|
dbg_bvr14,
|
||||||
|
dbg_bvr15,
|
||||||
|
|
||||||
|
dbg_bcr0,
|
||||||
|
dbg_bcr1,
|
||||||
|
dbg_bcr2,
|
||||||
|
dbg_bcr3,
|
||||||
|
dbg_bcr4,
|
||||||
|
dbg_bcr5,
|
||||||
|
dbg_bcr6,
|
||||||
|
dbg_bcr7,
|
||||||
|
dbg_bcr8,
|
||||||
|
dbg_bcr9,
|
||||||
|
dbg_bcr10,
|
||||||
|
dbg_bcr11,
|
||||||
|
dbg_bcr12,
|
||||||
|
dbg_bcr13,
|
||||||
|
dbg_bcr14,
|
||||||
|
dbg_bcr15,
|
||||||
|
|
||||||
|
dbg_wvr0,
|
||||||
|
dbg_wvr1,
|
||||||
|
dbg_wvr2,
|
||||||
|
dbg_wvr3,
|
||||||
|
dbg_wvr4,
|
||||||
|
dbg_wvr5,
|
||||||
|
dbg_wvr6,
|
||||||
|
dbg_wvr7,
|
||||||
|
dbg_wvr8,
|
||||||
|
dbg_wvr9,
|
||||||
|
dbg_wvr10,
|
||||||
|
dbg_wvr11,
|
||||||
|
dbg_wvr12,
|
||||||
|
dbg_wvr13,
|
||||||
|
dbg_wvr14,
|
||||||
|
dbg_wvr15,
|
||||||
|
|
||||||
|
dbg_wcr0,
|
||||||
|
dbg_wcr1,
|
||||||
|
dbg_wcr2,
|
||||||
|
dbg_wcr3,
|
||||||
|
dbg_wcr4,
|
||||||
|
dbg_wcr5,
|
||||||
|
dbg_wcr6,
|
||||||
|
dbg_wcr7,
|
||||||
|
dbg_wcr8,
|
||||||
|
dbg_wcr9,
|
||||||
|
dbg_wcr10,
|
||||||
|
dbg_wcr11,
|
||||||
|
dbg_wcr12,
|
||||||
|
dbg_wcr13,
|
||||||
|
dbg_wcr14,
|
||||||
|
dbg_wcr15,
|
||||||
|
|
||||||
|
k_num_registers
|
||||||
|
};
|
||||||
|
|
||||||
|
static RegisterInfo g_register_infos_arm[] = {
|
||||||
|
// General purpose registers
|
||||||
|
// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
|
||||||
|
// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== ===============
|
||||||
|
{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, gpr_r0 }, NULL, NULL},
|
||||||
|
{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, gpr_r1 }, NULL, NULL},
|
||||||
|
{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, gpr_r2 }, NULL, NULL},
|
||||||
|
{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, gpr_r3 }, NULL, NULL},
|
||||||
|
{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, gpr_r4 }, NULL, NULL},
|
||||||
|
{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, gpr_r5 }, NULL, NULL},
|
||||||
|
{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, gpr_r6 }, NULL, NULL},
|
||||||
|
{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_INVALID_REGNUM, gdb_arm_r7, gpr_r7 }, NULL, NULL},
|
||||||
|
{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, gpr_r8 }, NULL, NULL},
|
||||||
|
{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, gpr_r9 }, NULL, NULL},
|
||||||
|
{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, gpr_r10 }, NULL, NULL},
|
||||||
|
{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, gdb_arm_r11, gpr_r11 }, NULL, NULL},
|
||||||
|
{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, gpr_r12 }, NULL, NULL},
|
||||||
|
{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, gpr_sp }, NULL, NULL},
|
||||||
|
{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, gpr_lr }, NULL, NULL},
|
||||||
|
{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, gpr_pc }, NULL, NULL},
|
||||||
|
{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, gpr_cpsr }, NULL, NULL},
|
||||||
|
|
||||||
|
{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, fpu_s0 }, NULL, NULL},
|
||||||
|
{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, fpu_s1 }, NULL, NULL},
|
||||||
|
{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, fpu_s2 }, NULL, NULL},
|
||||||
|
{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, fpu_s3 }, NULL, NULL},
|
||||||
|
{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, fpu_s4 }, NULL, NULL},
|
||||||
|
{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, fpu_s5 }, NULL, NULL},
|
||||||
|
{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, fpu_s6 }, NULL, NULL},
|
||||||
|
{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, fpu_s7 }, NULL, NULL},
|
||||||
|
{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, fpu_s8 }, NULL, NULL},
|
||||||
|
{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, fpu_s9 }, NULL, NULL},
|
||||||
|
{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, fpu_s10 }, NULL, NULL},
|
||||||
|
{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, fpu_s11 }, NULL, NULL},
|
||||||
|
{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, fpu_s12 }, NULL, NULL},
|
||||||
|
{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, fpu_s13 }, NULL, NULL},
|
||||||
|
{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, fpu_s14 }, NULL, NULL},
|
||||||
|
{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, fpu_s15 }, NULL, NULL},
|
||||||
|
{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, fpu_s16 }, NULL, NULL},
|
||||||
|
{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, fpu_s17 }, NULL, NULL},
|
||||||
|
{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, fpu_s18 }, NULL, NULL},
|
||||||
|
{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, fpu_s19 }, NULL, NULL},
|
||||||
|
{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, fpu_s20 }, NULL, NULL},
|
||||||
|
{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, fpu_s21 }, NULL, NULL},
|
||||||
|
{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, fpu_s22 }, NULL, NULL},
|
||||||
|
{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, fpu_s23 }, NULL, NULL},
|
||||||
|
{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, fpu_s24 }, NULL, NULL},
|
||||||
|
{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, fpu_s25 }, NULL, NULL},
|
||||||
|
{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, fpu_s26 }, NULL, NULL},
|
||||||
|
{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, fpu_s27 }, NULL, NULL},
|
||||||
|
{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, fpu_s28 }, NULL, NULL},
|
||||||
|
{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, fpu_s29 }, NULL, NULL},
|
||||||
|
{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, fpu_s30 }, NULL, NULL},
|
||||||
|
{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, fpu_s31 }, NULL, NULL},
|
||||||
|
{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, fpu_fpscr }, NULL, NULL},
|
||||||
|
|
||||||
|
{ "exception",NULL, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, NULL, NULL},
|
||||||
|
{ "fsr", NULL, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }, NULL, NULL},
|
||||||
|
{ "far", NULL, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, NULL, NULL},
|
||||||
|
|
||||||
|
{ DEFINE_DBG (bvr, 0) },
|
||||||
|
{ DEFINE_DBG (bvr, 1) },
|
||||||
|
{ DEFINE_DBG (bvr, 2) },
|
||||||
|
{ DEFINE_DBG (bvr, 3) },
|
||||||
|
{ DEFINE_DBG (bvr, 4) },
|
||||||
|
{ DEFINE_DBG (bvr, 5) },
|
||||||
|
{ DEFINE_DBG (bvr, 6) },
|
||||||
|
{ DEFINE_DBG (bvr, 7) },
|
||||||
|
{ DEFINE_DBG (bvr, 8) },
|
||||||
|
{ DEFINE_DBG (bvr, 9) },
|
||||||
|
{ DEFINE_DBG (bvr, 10) },
|
||||||
|
{ DEFINE_DBG (bvr, 11) },
|
||||||
|
{ DEFINE_DBG (bvr, 12) },
|
||||||
|
{ DEFINE_DBG (bvr, 13) },
|
||||||
|
{ DEFINE_DBG (bvr, 14) },
|
||||||
|
{ DEFINE_DBG (bvr, 15) },
|
||||||
|
|
||||||
|
{ DEFINE_DBG (bcr, 0) },
|
||||||
|
{ DEFINE_DBG (bcr, 1) },
|
||||||
|
{ DEFINE_DBG (bcr, 2) },
|
||||||
|
{ DEFINE_DBG (bcr, 3) },
|
||||||
|
{ DEFINE_DBG (bcr, 4) },
|
||||||
|
{ DEFINE_DBG (bcr, 5) },
|
||||||
|
{ DEFINE_DBG (bcr, 6) },
|
||||||
|
{ DEFINE_DBG (bcr, 7) },
|
||||||
|
{ DEFINE_DBG (bcr, 8) },
|
||||||
|
{ DEFINE_DBG (bcr, 9) },
|
||||||
|
{ DEFINE_DBG (bcr, 10) },
|
||||||
|
{ DEFINE_DBG (bcr, 11) },
|
||||||
|
{ DEFINE_DBG (bcr, 12) },
|
||||||
|
{ DEFINE_DBG (bcr, 13) },
|
||||||
|
{ DEFINE_DBG (bcr, 14) },
|
||||||
|
{ DEFINE_DBG (bcr, 15) },
|
||||||
|
|
||||||
|
{ DEFINE_DBG (wvr, 0) },
|
||||||
|
{ DEFINE_DBG (wvr, 1) },
|
||||||
|
{ DEFINE_DBG (wvr, 2) },
|
||||||
|
{ DEFINE_DBG (wvr, 3) },
|
||||||
|
{ DEFINE_DBG (wvr, 4) },
|
||||||
|
{ DEFINE_DBG (wvr, 5) },
|
||||||
|
{ DEFINE_DBG (wvr, 6) },
|
||||||
|
{ DEFINE_DBG (wvr, 7) },
|
||||||
|
{ DEFINE_DBG (wvr, 8) },
|
||||||
|
{ DEFINE_DBG (wvr, 9) },
|
||||||
|
{ DEFINE_DBG (wvr, 10) },
|
||||||
|
{ DEFINE_DBG (wvr, 11) },
|
||||||
|
{ DEFINE_DBG (wvr, 12) },
|
||||||
|
{ DEFINE_DBG (wvr, 13) },
|
||||||
|
{ DEFINE_DBG (wvr, 14) },
|
||||||
|
{ DEFINE_DBG (wvr, 15) },
|
||||||
|
|
||||||
|
{ DEFINE_DBG (wcr, 0) },
|
||||||
|
{ DEFINE_DBG (wcr, 1) },
|
||||||
|
{ DEFINE_DBG (wcr, 2) },
|
||||||
|
{ DEFINE_DBG (wcr, 3) },
|
||||||
|
{ DEFINE_DBG (wcr, 4) },
|
||||||
|
{ DEFINE_DBG (wcr, 5) },
|
||||||
|
{ DEFINE_DBG (wcr, 6) },
|
||||||
|
{ DEFINE_DBG (wcr, 7) },
|
||||||
|
{ DEFINE_DBG (wcr, 8) },
|
||||||
|
{ DEFINE_DBG (wcr, 9) },
|
||||||
|
{ DEFINE_DBG (wcr, 10) },
|
||||||
|
{ DEFINE_DBG (wcr, 11) },
|
||||||
|
{ DEFINE_DBG (wcr, 12) },
|
||||||
|
{ DEFINE_DBG (wcr, 13) },
|
||||||
|
{ DEFINE_DBG (wcr, 14) },
|
||||||
|
{ DEFINE_DBG (wcr, 15) }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DECLARE_REGISTER_INFOS_ARM_STRUCT
|
|
@ -0,0 +1,153 @@
|
||||||
|
//===-- lldb-arm-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_arm_register_enums_h
|
||||||
|
#define lldb_arm_register_enums_h
|
||||||
|
|
||||||
|
namespace lldb_private
|
||||||
|
{
|
||||||
|
// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Internal codes for all ARM registers.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
k_first_gpr_arm = 0,
|
||||||
|
gpr_r0_arm = k_first_gpr_arm,
|
||||||
|
gpr_r1_arm,
|
||||||
|
gpr_r2_arm,
|
||||||
|
gpr_r3_arm,
|
||||||
|
gpr_r4_arm,
|
||||||
|
gpr_r5_arm,
|
||||||
|
gpr_r6_arm,
|
||||||
|
gpr_r7_arm,
|
||||||
|
gpr_r8_arm,
|
||||||
|
gpr_r9_arm,
|
||||||
|
gpr_r10_arm,
|
||||||
|
gpr_r11_arm,
|
||||||
|
gpr_r12_arm,
|
||||||
|
gpr_r13_arm, gpr_sp_arm = gpr_r13_arm,
|
||||||
|
gpr_r14_arm, gpr_lr_arm = gpr_r14_arm,
|
||||||
|
gpr_r15_arm, gpr_pc_arm = gpr_r15_arm,
|
||||||
|
gpr_cpsr_arm,
|
||||||
|
|
||||||
|
k_last_gpr_arm = gpr_cpsr_arm,
|
||||||
|
|
||||||
|
k_first_fpr_arm,
|
||||||
|
fpu_s0_arm = k_first_fpr_arm,
|
||||||
|
fpu_s1_arm,
|
||||||
|
fpu_s2_arm,
|
||||||
|
fpu_s3_arm,
|
||||||
|
fpu_s4_arm,
|
||||||
|
fpu_s5_arm,
|
||||||
|
fpu_s6_arm,
|
||||||
|
fpu_s7_arm,
|
||||||
|
fpu_s8_arm,
|
||||||
|
fpu_s9_arm,
|
||||||
|
fpu_s10_arm,
|
||||||
|
fpu_s11_arm,
|
||||||
|
fpu_s12_arm,
|
||||||
|
fpu_s13_arm,
|
||||||
|
fpu_s14_arm,
|
||||||
|
fpu_s15_arm,
|
||||||
|
fpu_s16_arm,
|
||||||
|
fpu_s17_arm,
|
||||||
|
fpu_s18_arm,
|
||||||
|
fpu_s19_arm,
|
||||||
|
fpu_s20_arm,
|
||||||
|
fpu_s21_arm,
|
||||||
|
fpu_s22_arm,
|
||||||
|
fpu_s23_arm,
|
||||||
|
fpu_s24_arm,
|
||||||
|
fpu_s25_arm,
|
||||||
|
fpu_s26_arm,
|
||||||
|
fpu_s27_arm,
|
||||||
|
fpu_s28_arm,
|
||||||
|
fpu_s29_arm,
|
||||||
|
fpu_s30_arm,
|
||||||
|
fpu_s31_arm,
|
||||||
|
fpu_fpscr_arm,
|
||||||
|
k_last_fpr_arm = fpu_fpscr_arm,
|
||||||
|
exc_exception_arm,
|
||||||
|
exc_fsr_arm,
|
||||||
|
exc_far_arm,
|
||||||
|
|
||||||
|
dbg_bvr0_arm,
|
||||||
|
dbg_bvr1_arm,
|
||||||
|
dbg_bvr2_arm,
|
||||||
|
dbg_bvr3_arm,
|
||||||
|
dbg_bvr4_arm,
|
||||||
|
dbg_bvr5_arm,
|
||||||
|
dbg_bvr6_arm,
|
||||||
|
dbg_bvr7_arm,
|
||||||
|
dbg_bvr8_arm,
|
||||||
|
dbg_bvr9_arm,
|
||||||
|
dbg_bvr10_arm,
|
||||||
|
dbg_bvr11_arm,
|
||||||
|
dbg_bvr12_arm,
|
||||||
|
dbg_bvr13_arm,
|
||||||
|
dbg_bvr14_arm,
|
||||||
|
dbg_bvr15_arm,
|
||||||
|
dbg_bcr0_arm,
|
||||||
|
dbg_bcr1_arm,
|
||||||
|
dbg_bcr2_arm,
|
||||||
|
dbg_bcr3_arm,
|
||||||
|
dbg_bcr4_arm,
|
||||||
|
dbg_bcr5_arm,
|
||||||
|
dbg_bcr6_arm,
|
||||||
|
dbg_bcr7_arm,
|
||||||
|
dbg_bcr8_arm,
|
||||||
|
dbg_bcr9_arm,
|
||||||
|
dbg_bcr10_arm,
|
||||||
|
dbg_bcr11_arm,
|
||||||
|
dbg_bcr12_arm,
|
||||||
|
dbg_bcr13_arm,
|
||||||
|
dbg_bcr14_arm,
|
||||||
|
dbg_bcr15_arm,
|
||||||
|
dbg_wvr0_arm,
|
||||||
|
dbg_wvr1_arm,
|
||||||
|
dbg_wvr2_arm,
|
||||||
|
dbg_wvr3_arm,
|
||||||
|
dbg_wvr4_arm,
|
||||||
|
dbg_wvr5_arm,
|
||||||
|
dbg_wvr6_arm,
|
||||||
|
dbg_wvr7_arm,
|
||||||
|
dbg_wvr8_arm,
|
||||||
|
dbg_wvr9_arm,
|
||||||
|
dbg_wvr10_arm,
|
||||||
|
dbg_wvr11_arm,
|
||||||
|
dbg_wvr12_arm,
|
||||||
|
dbg_wvr13_arm,
|
||||||
|
dbg_wvr14_arm,
|
||||||
|
dbg_wvr15_arm,
|
||||||
|
dbg_wcr0_arm,
|
||||||
|
dbg_wcr1_arm,
|
||||||
|
dbg_wcr2_arm,
|
||||||
|
dbg_wcr3_arm,
|
||||||
|
dbg_wcr4_arm,
|
||||||
|
dbg_wcr5_arm,
|
||||||
|
dbg_wcr6_arm,
|
||||||
|
dbg_wcr7_arm,
|
||||||
|
dbg_wcr8_arm,
|
||||||
|
dbg_wcr9_arm,
|
||||||
|
dbg_wcr10_arm,
|
||||||
|
dbg_wcr11_arm,
|
||||||
|
dbg_wcr12_arm,
|
||||||
|
dbg_wcr13_arm,
|
||||||
|
dbg_wcr14_arm,
|
||||||
|
dbg_wcr15_arm,
|
||||||
|
|
||||||
|
k_num_registers_arm,
|
||||||
|
k_num_gpr_registers_arm = k_last_gpr_arm - k_first_gpr_arm + 1,
|
||||||
|
k_num_fpr_registers_arm = k_last_fpr_arm - k_first_fpr_arm + 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #ifndef lldb_arm64_register_enums_h
|
|
@ -5,6 +5,7 @@ set(LLVM_NO_RTTI 1)
|
||||||
add_lldb_library(lldbPluginProcessElfCore
|
add_lldb_library(lldbPluginProcessElfCore
|
||||||
ProcessElfCore.cpp
|
ProcessElfCore.cpp
|
||||||
ThreadElfCore.cpp
|
ThreadElfCore.cpp
|
||||||
|
RegisterContextPOSIXCore_arm.cpp
|
||||||
RegisterContextPOSIXCore_arm64.cpp
|
RegisterContextPOSIXCore_arm64.cpp
|
||||||
RegisterContextPOSIXCore_mips64.cpp
|
RegisterContextPOSIXCore_mips64.cpp
|
||||||
RegisterContextPOSIXCore_powerpc.cpp
|
RegisterContextPOSIXCore_powerpc.cpp
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
//===-- RegisterContextCorePOSIX_arm.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/Core/DataExtractor.h"
|
||||||
|
#include "lldb/Core/RegisterValue.h"
|
||||||
|
#include "lldb/Target/Thread.h"
|
||||||
|
#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
|
||||||
|
#include "RegisterContextPOSIXCore_arm.h"
|
||||||
|
|
||||||
|
using namespace lldb_private;
|
||||||
|
|
||||||
|
RegisterContextCorePOSIX_arm::RegisterContextCorePOSIX_arm(Thread &thread,
|
||||||
|
RegisterInfoInterface *register_info,
|
||||||
|
const DataExtractor &gpregset,
|
||||||
|
const DataExtractor &fpregset)
|
||||||
|
: RegisterContextPOSIX_arm(thread, 0, register_info)
|
||||||
|
{
|
||||||
|
m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize()));
|
||||||
|
m_gpr.SetData(m_gpr_buffer);
|
||||||
|
m_gpr.SetByteOrder(gpregset.GetByteOrder());
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterContextCorePOSIX_arm::~RegisterContextCorePOSIX_arm()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextCorePOSIX_arm::ReadGPR()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextCorePOSIX_arm::ReadFPR()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextCorePOSIX_arm::WriteGPR()
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextCorePOSIX_arm::WriteFPR()
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextCorePOSIX_arm::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
|
||||||
|
{
|
||||||
|
lldb::offset_t offset = reg_info->byte_offset;
|
||||||
|
uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
|
||||||
|
if (offset == reg_info->byte_offset + reg_info->byte_size)
|
||||||
|
{
|
||||||
|
value = v;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextCorePOSIX_arm::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextCorePOSIX_arm::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextCorePOSIX_arm::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegisterContextCorePOSIX_arm::HardwareSingleStep(bool enable)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
//===-- RegisterContextCorePOSIX_arm.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_RegisterContextCorePOSIX_arm_H_
|
||||||
|
#define liblldb_RegisterContextCorePOSIX_arm_H_
|
||||||
|
|
||||||
|
#include "lldb/Core/DataBufferHeap.h"
|
||||||
|
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
|
||||||
|
|
||||||
|
class RegisterContextCorePOSIX_arm :
|
||||||
|
public RegisterContextPOSIX_arm
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RegisterContextCorePOSIX_arm (lldb_private::Thread &thread,
|
||||||
|
lldb_private::RegisterInfoInterface *register_info,
|
||||||
|
const lldb_private::DataExtractor &gpregset,
|
||||||
|
const lldb_private::DataExtractor &fpregset);
|
||||||
|
|
||||||
|
~RegisterContextCorePOSIX_arm();
|
||||||
|
|
||||||
|
virtual bool
|
||||||
|
ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
|
||||||
|
|
||||||
|
virtual 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);
|
||||||
|
|
||||||
|
bool
|
||||||
|
HardwareSingleStep(bool enable);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
ReadGPR();
|
||||||
|
|
||||||
|
bool
|
||||||
|
ReadFPR();
|
||||||
|
|
||||||
|
bool
|
||||||
|
WriteGPR();
|
||||||
|
|
||||||
|
bool
|
||||||
|
WriteFPR();
|
||||||
|
|
||||||
|
private:
|
||||||
|
lldb::DataBufferSP m_gpr_buffer;
|
||||||
|
lldb_private::DataExtractor m_gpr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // #ifndef liblldb_RegisterContextCorePOSIX_arm_H_
|
|
@ -16,12 +16,14 @@
|
||||||
|
|
||||||
#include "ThreadElfCore.h"
|
#include "ThreadElfCore.h"
|
||||||
#include "ProcessElfCore.h"
|
#include "ProcessElfCore.h"
|
||||||
|
#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h"
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
|
||||||
|
#include "RegisterContextPOSIXCore_arm.h"
|
||||||
#include "RegisterContextPOSIXCore_arm64.h"
|
#include "RegisterContextPOSIXCore_arm64.h"
|
||||||
#include "RegisterContextPOSIXCore_mips64.h"
|
#include "RegisterContextPOSIXCore_mips64.h"
|
||||||
#include "RegisterContextPOSIXCore_powerpc.h"
|
#include "RegisterContextPOSIXCore_powerpc.h"
|
||||||
|
@ -127,6 +129,9 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
|
||||||
{
|
{
|
||||||
switch (arch.GetMachine())
|
switch (arch.GetMachine())
|
||||||
{
|
{
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
reg_interface = new RegisterContextLinux_arm(arch);
|
||||||
|
break;
|
||||||
case llvm::Triple::x86_64:
|
case llvm::Triple::x86_64:
|
||||||
reg_interface = new RegisterContextLinux_x86_64(arch);
|
reg_interface = new RegisterContextLinux_x86_64(arch);
|
||||||
break;
|
break;
|
||||||
|
@ -152,6 +157,9 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
|
||||||
case llvm::Triple::aarch64:
|
case llvm::Triple::aarch64:
|
||||||
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
|
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
|
||||||
break;
|
break;
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm (*this, reg_interface, m_gpregset_data, m_fpregset_data));
|
||||||
|
break;
|
||||||
case llvm::Triple::mips64:
|
case llvm::Triple::mips64:
|
||||||
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
|
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue