[Lldb-commits] [lldb] r237419 - This patch adds support for setting/clearing hardware watchpoints and breakpoints on AArch64 (Arm v8) 64-bit hardware.
Tamas Berghammer
tberghammer at google.com
Fri May 15 08:58:00 PDT 2015
Hi Omair,
This CL caused a build breakage for android-aarch64 (
http://lab.llvm.org:8011/builders/lldb-x86_64-ubuntu-14.04-android/builds/164).
Can you look into it why?
Thanks,
Tamas
On Fri, May 15, 2015 at 7:30 AM, Omair Javaid <omair.javaid at linaro.org>
wrote:
> Author: omjavaid
> Date: Fri May 15 01:29:58 2015
> New Revision: 237419
>
> URL: http://llvm.org/viewvc/llvm-project?rev=237419&view=rev
> Log:
> This patch adds support for setting/clearing hardware watchpoints and
> breakpoints on AArch64 (Arm v8) 64-bit hardware.
>
> http://reviews.llvm.org/D9706
>
>
> Modified:
> lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h
> lldb/trunk/source/Host/common/NativeRegisterContext.cpp
> lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
> lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
>
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
>
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
>
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
>
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
> lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
> lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h
>
> Modified: lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h?rev=237419&r1=237418&r2=237419&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h (original)
> +++ lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h Fri May 15
> 01:29:58 2015
> @@ -103,7 +103,7 @@ public:
> IsWatchpointHit(uint32_t wp_index, bool &is_hit);
>
> virtual Error
> - GetWatchpointHitIndex(uint32_t &wp_index);
> + GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr);
>
> virtual Error
> IsWatchpointVacant (uint32_t wp_index, bool &is_vacant);
>
> Modified: lldb/trunk/source/Host/common/NativeRegisterContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeRegisterContext.cpp?rev=237419&r1=237418&r2=237419&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Host/common/NativeRegisterContext.cpp (original)
> +++ lldb/trunk/source/Host/common/NativeRegisterContext.cpp Fri May 15
> 01:29:58 2015
> @@ -309,7 +309,7 @@ NativeRegisterContext::IsWatchpointHit(u
> }
>
> Error
> -NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index)
> +NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index,
> lldb::addr_t trap_addr)
> {
> wp_index = LLDB_INVALID_INDEX32;
> return Error ("not implemented");
>
> Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=237419&r1=237418&r2=237419&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
> (original)
> +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Fri May
> 15 01:29:58 2015
> @@ -762,6 +762,47 @@ namespace
> #endif
> }
>
> +#if defined (__arm64__) || defined (__aarch64__)
> +
> //------------------------------------------------------------------------------
> + /// @class ReadDBGROperation
> + /// @brief Implements NativeProcessLinux::ReadDBGR.
> + class ReadDBGROperation : public Operation
> + {
> + public:
> + ReadDBGROperation(lldb::tid_t tid, unsigned int &count_wp,
> unsigned int &count_bp)
> + : m_tid(tid),
> + m_count_wp(count_wp),
> + m_count_bp(count_bp)
> + { }
> +
> + void Execute(NativeProcessLinux *monitor) override;
> +
> + private:
> + lldb::tid_t m_tid;
> + unsigned int &m_count_wp;
> + unsigned int &m_count_bp;
> + };
> +
> + void
> + ReadDBGROperation::Execute(NativeProcessLinux *monitor)
> + {
> + int regset = NT_ARM_HW_WATCH;
> + struct iovec ioVec;
> + struct user_hwdebug_state dreg_state;
> +
> + ioVec.iov_base = &dreg_state;
> + ioVec.iov_len = sizeof (dreg_state);
> +
> + PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len,
> m_error);
> +
> + m_count_wp = dreg_state.dbg_info & 0xff;
> + regset = NT_ARM_HW_BREAK;
> +
> + PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len,
> m_error);
> + m_count_bp = dreg_state.dbg_info & 0xff;
> + }
> +#endif
> +
>
> //------------------------------------------------------------------------------
> /// @class ReadRegisterSetOperation
> /// @brief Implements NativeProcessLinux::ReadRegisterSet.
> @@ -853,6 +894,57 @@ namespace
> #endif
> }
>
> +#if defined (__arm64__) || defined (__aarch64__)
> +
> //------------------------------------------------------------------------------
> + /// @class WriteDBGROperation
> + /// @brief Implements NativeProcessLinux::WriteFPR.
> + class WriteDBGROperation : public Operation
> + {
> + public:
> + WriteDBGROperation(lldb::tid_t tid, lldb::addr_t *addr_buf,
> + uint32_t *cntrl_buf, int type, int count)
> + : m_tid(tid),
> + m_address(addr_buf),
> + m_control(cntrl_buf),
> + m_type(type),
> + m_count(count)
> + { }
> +
> + void Execute(NativeProcessLinux *monitor) override;
> +
> + private:
> + lldb::tid_t m_tid;
> + lldb::addr_t * m_address;
> + uint32_t * m_control;
> + int m_type;
> + int m_count;
> + };
> +
> + void
> + WriteDBGROperation::Execute(NativeProcessLinux *monitor)
> + {
> + struct iovec ioVec;
> + struct user_hwdebug_state dreg_state;
> +
> + memset (&dreg_state, 0, sizeof (dreg_state));
> + ioVec.iov_len = (__builtin_offsetof (struct user_hwdebug_state,
> dbg_regs[m_count - 1])
> + + sizeof (dreg_state.dbg_regs [m_count - 1]));
> +
> + if (m_type == 0)
> + m_type = NT_ARM_HW_WATCH;
> + else
> + m_type = NT_ARM_HW_BREAK;
> +
> + for (int i = 0; i < m_count; i++)
> + {
> + dreg_state.dbg_regs[i].addr = m_address[i];
> + dreg_state.dbg_regs[i].ctrl = m_control[i];
> + }
> +
> + PTRACE(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len,
> m_error);
> + }
> +#endif
> +
>
> //------------------------------------------------------------------------------
> /// @class WriteRegisterSetOperation
> /// @brief Implements NativeProcessLinux::WriteRegisterSet.
> @@ -2436,7 +2528,7 @@ NativeProcessLinux::MonitorSIGTRAP(const
> {
> // If a watchpoint was hit, report it
> uint32_t wp_index;
> - Error error =
> thread_sp->GetRegisterContext()->GetWatchpointHitIndex(wp_index);
> + Error error =
> thread_sp->GetRegisterContext()->GetWatchpointHitIndex(wp_index,
> (lldb::addr_t)info->si_addr);
> if (error.Fail() && log)
> log->Printf("NativeProcessLinux::%s() "
> "received error while checking for watchpoint
> hits, "
> @@ -3841,6 +3933,26 @@ NativeProcessLinux::ReadRegisterSet(lldb
> return op.GetError();
> }
>
> +#if defined (__arm64__) || defined (__aarch64__)
> +
> +Error
> +NativeProcessLinux::ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int
> &watch_count , unsigned int &break_count)
> +{
> + ReadDBGROperation op(tid, watch_count, break_count);
> + m_monitor_up->DoOperation(&op);
> + return op.GetError();
> +}
> +
> +Error
> +NativeProcessLinux::WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t
> *addr_buf, uint32_t *cntrl_buf, int type, int count)
> +{
> + WriteDBGROperation op(tid, addr_buf, cntrl_buf, type, count);
> + m_monitor_up->DoOperation(&op);
> + return op.GetError();
> +}
> +
> +#endif
> +
> Error
> NativeProcessLinux::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size)
> {
>
> Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h?rev=237419&r1=237418&r2=237419&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h (original)
> +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h Fri May
> 15 01:29:58 2015
> @@ -151,6 +151,17 @@ namespace process_linux {
> Error
> ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
>
> +#if defined (__arm64__) || defined (__aarch64__)
> + /// Reads hardware breakpoints and watchpoints capability
> information.
> + Error
> + ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count
> ,
> + unsigned int &break_count);
> +
> + /// Write hardware breakpoint/watchpoint control and address
> registers.
> + Error
> + WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf,
> + uint32_t *cntrl_buf, int type, int count);
> +#endif
> /// Reads the specified register set into the specified buffer.
> /// For instance, the extended floating-point register set.
> Error
>
> Modified:
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp?rev=237419&r1=237418&r2=237419&view=diff
>
> ==============================================================================
> ---
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
> (original)
> +++
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
> Fri May 15 01:29:58 2015
> @@ -12,10 +12,12 @@
> #include "lldb/lldb-private-forward.h"
> #include "lldb/Core/DataBufferHeap.h"
> #include "lldb/Core/Error.h"
> +#include "lldb/Core/StreamString.h"
> #include "lldb/Core/RegisterValue.h"
> #include "lldb/Host/common/NativeProcessProtocol.h"
> #include "lldb/Host/common/NativeThreadProtocol.h"
> #include "Plugins/Process/Linux/NativeProcessLinux.h"
> +#include "lldb/Core/Log.h"
>
> #define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
>
> @@ -149,6 +151,12 @@ NativeRegisterContextLinux_arm64::Native
>
> ::memset(&m_fpr, 0, sizeof (m_fpr));
> ::memset(&m_gpr_arm64, 0, sizeof (m_gpr_arm64));
> + ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs));
> +
> + // 16 is just a maximum value, query hardware for actual watchpoint
> count
> + m_max_hwp_supported = 16;
> + m_max_hbp_supported = 16;
> + m_refresh_hwdebug_info = true;
> }
>
> uint32_t
> @@ -536,3 +544,356 @@ NativeRegisterContextLinux_arm64::GetGPR
> {
> return GetRegisterInfoInterface().GetGPRSize();
> }
> +
> +uint32_t
> +NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t
> addr, size_t size)
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> +
> + NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
> + if (!process_sp)
> + return false;
> +
> + NativeProcessLinux *const process_p =
> reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
> + // Check if our hardware breakpoint and watchpoint information is
> updated.
> + if (m_refresh_hwdebug_info)
> + {
> + process_p->ReadHardwareDebugInfo (m_thread.GetID (),
> m_max_hwp_supported,
> + m_max_hbp_supported);
> + m_refresh_hwdebug_info = false;
> + }
> +
> + uint32_t control_value, bp_index;
> +
> + // Check if size has a valid hardware breakpoint length.
> + if (size != 4)
> + return LLDB_INVALID_INDEX32; // Invalid size for a AArch64
> hardware breakpoint
> +
> + // Check 4-byte alignment for hardware breakpoint target address.
> + if (addr & 0x03)
> + return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte
> aligned.
> +
> + // Setup control value
> + control_value = 0;
> + control_value |= ((1 << size) - 1) << 5;
> + control_value |= (2 << 1) | 1;
> +
> + // Iterate over stored hardware breakpoints
> + // Find a free bp_index or update reference count if duplicate.
> + bp_index = LLDB_INVALID_INDEX32;
> + for (uint32_t i = 0; i < m_max_hbp_supported; i++)
> + {
> + if ((m_hbr_regs[i].control & 1) == 0)
> + {
> + bp_index = i; // Mark last free slot
> + }
> + else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control
> == control_value)
> + {
> + bp_index = i; // Mark duplicate index
> + break; // Stop searching here
> + }
> + }
> +
> + if (bp_index == LLDB_INVALID_INDEX32)
> + return LLDB_INVALID_INDEX32;
> +
> + // Add new or update existing watchpoint
> + if ((m_hbr_regs[bp_index].control & 1) == 0)
> + {
> + m_hbr_regs[bp_index].address = addr;
> + m_hbr_regs[bp_index].control = control_value;
> + m_hbr_regs[bp_index].refcount = 1;
> +
> + //TODO: PTRACE CALL HERE for an UPDATE
> + }
> + else
> + m_hbr_regs[bp_index].refcount++;
> +
> + return bp_index;
> +}
> +
> +bool
> +NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t
> hw_idx)
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> +
> + if (hw_idx >= m_max_hbp_supported)
> + return false;
> +
> + // Update reference count if multiple references.
> + if (m_hbr_regs[hw_idx].refcount > 1)
> + {
> + m_hbr_regs[hw_idx].refcount--;
> + return true;
> + }
> + else if (m_hbr_regs[hw_idx].refcount == 1)
> + {
> + m_hbr_regs[hw_idx].control &= ~1;
> + m_hbr_regs[hw_idx].address = 0;
> + m_hbr_regs[hw_idx].refcount = 0;
> +
> + //TODO: PTRACE CALL HERE for an UPDATE
> + return true;
> + }
> +
> + return false;
> +}
> +
> +uint32_t
> +NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints ()
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> +
> + return m_max_hwp_supported;
> +}
> +
> +uint32_t
> +NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t
> addr, size_t size, uint32_t watch_flags)
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> +
> + NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
> + if (!process_sp)
> + return false;
> +
> + NativeProcessLinux *const process_p =
> reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
> + // Check if our hardware breakpoint and watchpoint information is
> updated.
> + if (m_refresh_hwdebug_info)
> + {
> + process_p->ReadHardwareDebugInfo (m_thread.GetID (),
> m_max_hwp_supported,
> + m_max_hbp_supported);
> + m_refresh_hwdebug_info = false;
> + }
> +
> + uint32_t control_value, wp_index;
> +
> +
> + if (watch_flags != 0x1 && watch_flags != 0x2 && watch_flags != 0x3)
> + return 0;//Error ("Invalid read/write bits for watchpoint");
> +
> + // Check if size has a valid hardware watchpoint length.
> + if (size != 1 && size != 2 && size != 4 && size != 8)
> + return 0;//Error ("Invalid size for watchpoint");
> +
> + // Check 8-byte alignment for hardware watchpoint target address.
> + // TODO: Add support for watching un-aligned addresses
> + if (addr & 0x07)
> + return 0;//Error ("LLDB for AArch64 currently supports 8-byte
> alignment for hardware watchpoint target address.");
> +
> + // Setup control value
> + control_value = watch_flags << 3;
> + control_value |= ((1 << size) - 1) << 5;
> + control_value |= (2 << 1) | 1;
> +
> + // Iterate over stored watchpoints
> + // Find a free wp_index or update reference count if duplicate.
> + wp_index = LLDB_INVALID_INDEX32;
> + for (uint32_t i = 0; i < m_max_hwp_supported; i++)
> + {
> + if ((m_hwp_regs[i].control & 1) == 0)
> + {
> + wp_index = i; // Mark last free slot
> + }
> + else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control
> == control_value)
> + {
> + wp_index = i; // Mark duplicate index
> + break; // Stop searching here
> + }
> + }
> +
> + if (wp_index == LLDB_INVALID_INDEX32)
> + return LLDB_INVALID_INDEX32;
> +
> + // Add new or update existing watchpoint
> + if ((m_hwp_regs[wp_index].control & 1) == 0)
> + {
> + m_hwp_regs[wp_index].address = addr;
> + m_hwp_regs[wp_index].control = control_value;
> + m_hwp_regs[wp_index].refcount = 1;
> +
> + // PTRACE call to set corresponding watchpoint register.
> + process_p->WriteHardwareDebugRegs(m_thread.GetID (), &addr,
> + &control_value, 0, wp_index);
> + }
> + else
> + m_hwp_regs[wp_index].refcount++;
> +
> + return wp_index;
> +}
> +
> +bool
> +NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t
> wp_index)
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> +
> + NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
> + if (!process_sp)
> + return false;
> +
> + NativeProcessLinux *const process_p =
> reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
> +
> + if (wp_index >= m_max_hwp_supported)
> + return false;
> +
> + // Update reference count if multiple references.
> + if (m_hwp_regs[wp_index].refcount > 1)
> + {
> + m_hwp_regs[wp_index].refcount--;
> + return true;
> + }
> + else if (m_hwp_regs[wp_index].refcount == 1)
> + {
> + m_hwp_regs[wp_index].control &= ~1;
> + m_hwp_regs[wp_index].address = 0;
> + m_hwp_regs[wp_index].refcount = 0;
> +
> + //TODO: PTRACE CALL HERE for an UPDATE
> + process_p->WriteHardwareDebugRegs(m_thread.GetID (),
> + &m_hwp_regs[wp_index].address,
> + &m_hwp_regs[wp_index].control,
> + 0, wp_index);
> + return true;
> + }
> +
> + return false;
> +}
> +
> +Error
> +NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints ()
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> +
> + NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
> +
> + Error ml_error;
> + ml_error.SetErrorToErrno();
> + if (!process_sp)
> + return ml_error;
> +
> + NativeProcessLinux *const process_p =
> reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
> +
> + for (uint32_t i = 0; i < m_max_hwp_supported; i++)
> + {
> + if (m_hwp_regs[i].control & 0x01)
> + {
> + m_hwp_regs[i].control &= ~1;
> + m_hwp_regs[i].address = 0;
> + m_hwp_regs[i].refcount = 0;
> +
> + process_p->WriteHardwareDebugRegs(m_thread.GetID (),
> + &m_hwp_regs[i].address,
> + &m_hwp_regs[i].control,
> + 0, i);
> + }
> + }
> +
> + return Error();
> +}
> +
> +uint32_t
> +NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index)
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> + switch ((m_hwp_regs[wp_index].control >> 5) & 0xff)
> + {
> + case 0x01:
> + return 1;
> + case 0x03:
> + return 2;
> + case 0x0f:
> + return 4;
> + case 0xff:
> + return 8;
> + default:
> + return 0;
> + }
> +}
> +bool
> +NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index)
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> +
> + if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
> + return true;
> + else
> + return false;
> +}
> +
> +Error
> +NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t
> &wp_index, lldb::addr_t trap_addr)
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> +
> + uint32_t watch_size;
> + lldb::addr_t watch_addr;
> +
> + for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index)
> + {
> + watch_size = GetWatchpointSize (wp_index);
> + watch_addr = m_hwp_regs[wp_index].address;
> +
> + if (m_hwp_regs[wp_index].refcount >= 1 &&
> WatchpointIsEnabled(wp_index)
> + && trap_addr >= watch_addr && trap_addr < watch_addr +
> watch_size)
> + {
> + return Error();
> + }
> + }
> +
> + wp_index = LLDB_INVALID_INDEX32;
> + return Error();
> +}
> +
> +lldb::addr_t
> +NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index)
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> +
> + if (wp_index >= m_max_hwp_supported)
> + return LLDB_INVALID_ADDRESS;
> +
> + if (WatchpointIsEnabled(wp_index))
> + return m_hwp_regs[wp_index].address;
> + else
> + return LLDB_INVALID_ADDRESS;
> +}
> +
> +bool
> +NativeRegisterContextLinux_arm64::HardwareSingleStep (bool enable)
> +{
> + Log *log(lldb_private::GetLogIfAllCategoriesSet
> (LIBLLDB_LOG_WATCHPOINTS));
> +
> + if (log)
> + log->Printf ("NativeRegisterContextLinux_arm64::%s()",
> __FUNCTION__);
> +
> + return false;
> +}
>
> Modified:
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h?rev=237419&r1=237418&r2=237419&view=diff
>
> ==============================================================================
> ---
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
> (original)
> +++
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
> Fri May 15 01:29:58 2015
> @@ -44,6 +44,43 @@ namespace process_linux {
> Error
> WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
> override;
>
> +
> //------------------------------------------------------------------
> + // Hardware breakpoints/watchpoint mangement functions
> +
> //------------------------------------------------------------------
> +
> + uint32_t
> + SetHardwareBreakpoint (lldb::addr_t addr, size_t size) override;
> +
> + bool
> + ClearHardwareBreakpoint (uint32_t hw_idx) override;
> +
> + uint32_t
> + NumSupportedHardwareWatchpoints () override;
> +
> + uint32_t
> + SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t
> watch_flags) override;
> +
> + bool
> + ClearHardwareWatchpoint (uint32_t hw_index) override;
> +
> + Error
> + ClearAllHardwareWatchpoints () override;
> +
> + Error
> + GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
> override;
> +
> + lldb::addr_t
> + GetWatchpointAddress (uint32_t wp_index) override;
> +
> + bool
> + HardwareSingleStep (bool enable) override;
> +
> + uint32_t
> + GetWatchpointSize(uint32_t wp_index);
> +
> + bool
> + WatchpointIsEnabled(uint32_t wp_index);
> +
> private:
> struct RegInfo
> {
> @@ -79,6 +116,21 @@ namespace process_linux {
> RegInfo m_reg_info;
> FPU m_fpr; // floating-point registers including extended
> register sets.
>
> + // Debug register info for hardware breakpoints and watchpoints
> management.
> + struct DREG
> + {
> + lldb::addr_t address; // Breakpoint/watchpoint address value.
> + uint32_t control; // Breakpoint/watchpoint control value.
> + uint32_t refcount; // Serves as enable/disable and refernce
> counter.
> + };
> +
> + struct DREG m_hbr_regs[16]; // Arm native linux hardware
> breakpoints
> + struct DREG m_hwp_regs[16]; // Arm native linux hardware
> watchpoints
> +
> + uint32_t m_max_hwp_supported;
> + uint32_t m_max_hbp_supported;
> + bool m_refresh_hwdebug_info;
> +
> bool
> IsGPR(unsigned reg) const;
>
>
> Modified:
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp?rev=237419&r1=237418&r2=237419&view=diff
>
> ==============================================================================
> ---
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
> (original)
> +++
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
> Fri May 15 01:29:58 2015
> @@ -1069,7 +1069,7 @@ NativeRegisterContextLinux_x86_64::IsWat
> }
>
> Error
> -NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(uint32_t
> &wp_index) {
> +NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(uint32_t
> &wp_index, lldb::addr_t trap_addr) {
> uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
> for (wp_index = 0; wp_index < num_hw_wps; ++wp_index)
> {
>
> Modified:
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h?rev=237419&r1=237418&r2=237419&view=diff
>
> ==============================================================================
> ---
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
> (original)
> +++
> lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
> Fri May 15 01:29:58 2015
> @@ -50,7 +50,7 @@ namespace process_linux {
> IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
>
> Error
> - GetWatchpointHitIndex(uint32_t &wp_index) override;
> + GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
> override;
>
> Error
> IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
>
> Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp?rev=237419&r1=237418&r2=237419&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp (original)
> +++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp Fri May 15
> 01:29:58 2015
> @@ -548,7 +548,96 @@ ReadRegOperation::Execute(ProcessMonitor
> #endif
> }
>
>
> -//------------------------------------------------------------------------------
> +#if defined (__arm64__) || defined (__aarch64__)
> +
> //------------------------------------------------------------------------------
> + /// @class ReadDBGROperation
> + /// @brief Implements NativeProcessLinux::ReadDBGR.
> + class ReadDBGROperation : public Operation
> + {
> + public:
> + ReadDBGROperation(lldb::tid_t tid, unsigned int &count_wp,
> unsigned int &count_bp)
> + : m_tid(tid),
> + m_count_wp(count_wp),
> + m_count_bp(count_bp)
> + { }
> +
> + void Execute(ProcessMonitor *monitor) override;
> +
> + private:
> + lldb::tid_t m_tid;
> + unsigned int &m_count_wp;
> + unsigned int &m_count_bp;
> + };
> +
> + void
> + ReadDBGROperation::Execute(ProcessMonitor *monitor)
> + {
> + int regset = NT_ARM_HW_WATCH;
> + struct iovec ioVec;
> + struct user_hwdebug_state dreg_state;
> +
> + ioVec.iov_base = &dreg_state;
> + ioVec.iov_len = sizeof (dreg_state);
> +
> + PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len);
> +
> + m_count_wp = dreg_state.dbg_info & 0xff;
> + regset = NT_ARM_HW_BREAK;
> +
> + PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len);
> + m_count_bp = dreg_state.dbg_info & 0xff;
> + }
> +#endif
> +
> +#if defined (__arm64__) || defined (__aarch64__)
> +
> //------------------------------------------------------------------------------
> + /// @class WriteDBGROperation
> + /// @brief Implements NativeProcessLinux::WriteFPR.
> + class WriteDBGROperation : public Operation
> + {
> + public:
> + WriteDBGROperation(lldb::tid_t tid, lldb::addr_t *addr_buf,
> uint32_t *cntrl_buf, int type, int count)
> + : m_tid(tid),
> + m_addr_buf(addr_buf),
> + m_cntrl_buf(cntrl_buf),
> + m_type(type),
> + m_count(count)
> + { }
> +
> + void Execute(ProcessMonitor *monitor) override;
> +
> + private:
> + lldb::tid_t m_tid;
> + lldb::addr_t *m_addr_buf;
> + uint32_t *m_cntrl_buf;
> + int m_type;
> + int m_count;
> + };
> +
> + void
> + WriteDBGROperation::Execute(ProcessMonitor *monitor)
> + {
> + struct iovec ioVec;
> + struct user_hwdebug_state dreg_state;
> +
> + memset (&dreg_state, 0, sizeof (dreg_state));
> + ioVec.iov_len = (__builtin_offsetof (struct user_hwdebug_state,
> dbg_regs[m_count - 1])
> + + sizeof (dreg_state.dbg_regs [m_count - 1]));
> +
> + if (m_type == 0)
> + m_type = NT_ARM_HW_WATCH;
> + else
> + m_type = NT_ARM_HW_BREAK;
> +
> + for (int i = 0; i < m_count; i++)
> + {
> + dreg_state.dbg_regs[i].addr = m_addr_buf[i];
> + dreg_state.dbg_regs[i].ctrl = m_cntrl_buf[i];
> + }
> +
> + PTRACE(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len);
> + }
>
> +#endif//------------------------------------------------------------------------------
> /// @class WriteRegOperation
> /// @brief Implements ProcessMonitor::WriteRegisterValue.
> class WriteRegOperation : public Operation
> @@ -2159,6 +2248,27 @@ ProcessMonitor::ReadRegisterValue(lldb::
> return result;
> }
>
> +#if defined (__arm64__) || defined (__aarch64__)
> +
> +bool
> +ProcessMonitor::ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int
> &watch_count , unsigned int &break_count)
> +{
> + bool result = true;
> + ReadDBGROperation op(tid, watch_count, break_count);
> + DoOperation(&op);
> + return result;
> +}
> +
> +bool
> +ProcessMonitor::WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t
> *addr_buf, uint32_t *cntrl_buf, int type, int count)
> +{
> + bool result = true;
> + WriteDBGROperation op(tid, addr_buf, cntrl_buf, type, count);
> + DoOperation(&op);
> + return result;
> +}
> +
> +#endif
> bool
> ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
> const char* reg_name, const
> RegisterValue &value)
>
> Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h?rev=237419&r1=237418&r2=237419&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h (original)
> +++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h Fri May 15
> 01:29:58 2015
> @@ -138,6 +138,18 @@ public:
> bool
> ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
>
> +#if defined (__arm64__) || defined (__aarch64__)
> + /// Reads hardware breakpoints and watchpoints capability information.
> + bool
> + ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count ,
> + unsigned int &break_count);
> +
> + /// Write hardware breakpoint/watchpoint control and address
> registers.
> + bool
> + WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf,
> + uint32_t *cntrl_buf, int type, int count);
> +#endif
> +
> /// Reads the specified register set into the specified buffer.
> /// For instance, the extended floating-point register set.
> bool
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20150515/0eb42a36/attachment.html>
More information about the lldb-commits
mailing list