520 changes: 520 additions & 0 deletions lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp

Large diffs are not rendered by default.

116 changes: 116 additions & 0 deletions lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
Original file line number Diff line number Diff line change
@@ -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 &reg_value) override;

Error
WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_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 &reg_value);

Error
WriteRegisterRaw (uint32_t reg_index, const RegisterValue &reg_value);

lldb::ByteOrder
GetByteOrder() const;

size_t
GetGPRSize() const;
};

} // namespace process_linux
} // namespace lldb_private

#endif // #ifndef lldb_NativeRegisterContextLinux_arm_h

12 changes: 12 additions & 0 deletions lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <sstream>

#include "NativeProcessLinux.h"
#include "NativeRegisterContextLinux_arm.h"
#include "NativeRegisterContextLinux_arm64.h"
#include "NativeRegisterContextLinux_x86_64.h"
#include "NativeRegisterContextLinux_mips64.h"
Expand All @@ -29,6 +30,7 @@

#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_i386.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
Expand Down Expand Up @@ -184,6 +186,10 @@ NativeThreadLinux::GetRegisterContext ()
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));
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_64:
if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
Expand Down Expand Up @@ -242,6 +248,12 @@ NativeThreadLinux::GetRegisterContext ()
m_reg_context_sp.reset (new NativeRegisterContextLinux_arm64(*this, concrete_frame_idx, reg_interface));
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_64:
{
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/POSIX/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ add_lldb_library(lldbPluginProcessPOSIX
ProcessMessage.cpp
ProcessPOSIX.cpp
ProcessPOSIXLog.cpp
RegisterContextPOSIXProcessMonitor_arm.cpp
RegisterContextPOSIXProcessMonitor_arm64.cpp
RegisterContextPOSIXProcessMonitor_mips64.cpp
RegisterContextPOSIXProcessMonitor_powerpc.cpp
Expand Down
15 changes: 15 additions & 0 deletions lldb/source/Plugins/Process/POSIX/POSIXThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@
#include "ProcessPOSIX.h"
#include "ProcessPOSIXLog.h"
#include "Plugins/Process/Linux/ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_arm.h"
#include "RegisterContextPOSIXProcessMonitor_arm64.h"
#include "RegisterContextPOSIXProcessMonitor_mips64.h"
#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
#include "RegisterContextPOSIXProcessMonitor_x86.h"
#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
Expand Down Expand Up @@ -198,6 +200,10 @@ POSIXThread::GetRegisterContext()
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));
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_64:
if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
Expand Down Expand Up @@ -232,6 +238,13 @@ POSIXThread::GetRegisterContext()
m_reg_context_sp.reset(reg_ctx);
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:
{
RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
Expand Down Expand Up @@ -644,6 +657,7 @@ POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
break;

case llvm::Triple::aarch64:
case llvm::Triple::arm:
case llvm::Triple::mips64:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
Expand Down Expand Up @@ -677,6 +691,7 @@ POSIXThread::GetRegisterName(unsigned reg)
break;

case llvm::Triple::aarch64:
case llvm::Triple::arm:
case llvm::Triple::mips64:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
Expand Down
28 changes: 28 additions & 0 deletions lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

// C++ Includes
// Other libraries and framework includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
Expand Down Expand Up @@ -638,6 +639,33 @@ ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
assert(false && "CPU type not supported!");
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:
opcode = g_aarch64_opcode;
opcode_size = sizeof(g_aarch64_opcode);
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}

Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions lldb/source/Plugins/Process/Utility/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ add_lldb_library(lldbPluginProcessUtility
RegisterContextFreeBSD_powerpc.cpp
RegisterContextFreeBSD_x86_64.cpp
RegisterContextHistory.cpp
RegisterContextLinux_arm.cpp
RegisterContextLinux_arm64.cpp
RegisterContextLinux_i386.cpp
RegisterContextLinux_x86_64.cpp
Expand All @@ -31,6 +32,7 @@ add_lldb_library(lldbPluginProcessUtility
RegisterContextMach_i386.cpp
RegisterContextMach_x86_64.cpp
RegisterContextMemory.cpp
RegisterContextPOSIX_arm.cpp
RegisterContextPOSIX_arm64.cpp
RegisterContextPOSIX_mips64.cpp
RegisterContextPOSIX_powerpc.cpp
Expand Down
87 changes: 87 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
76 changes: 76 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.h
Original file line number Diff line number Diff line change
@@ -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_

287 changes: 287 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
Original file line number Diff line number Diff line change
@@ -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;
}

121 changes: 121 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
Original file line number Diff line number Diff line change
@@ -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_

303 changes: 303 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h

Large diffs are not rendered by default.

153 changes: 153 additions & 0 deletions lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/elf-core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set(LLVM_NO_RTTI 1)
add_lldb_library(lldbPluginProcessElfCore
ProcessElfCore.cpp
ThreadElfCore.cpp
RegisterContextPOSIXCore_arm.cpp
RegisterContextPOSIXCore_arm64.cpp
RegisterContextPOSIXCore_mips64.cpp
RegisterContextPOSIXCore_powerpc.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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_
8 changes: 8 additions & 0 deletions lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@

#include "ThreadElfCore.h"
#include "ProcessElfCore.h"
#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
#include "RegisterContextPOSIXCore_arm.h"
#include "RegisterContextPOSIXCore_arm64.h"
#include "RegisterContextPOSIXCore_mips64.h"
#include "RegisterContextPOSIXCore_powerpc.h"
Expand Down Expand Up @@ -127,6 +129,9 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
{
switch (arch.GetMachine())
{
case llvm::Triple::arm:
reg_interface = new RegisterContextLinux_arm(arch);
break;
case llvm::Triple::x86_64:
reg_interface = new RegisterContextLinux_x86_64(arch);
break;
Expand All @@ -152,6 +157,9 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
case llvm::Triple::aarch64:
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
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:
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
break;
Expand Down