| 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 ®_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 | ||
|
|
| 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 |
| 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; | ||
| } |
| 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_ | ||
|
|
| 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; | ||
| } | ||
|
|
| 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_ | ||
|
|
| 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 |
| 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_ |