aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp')
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp44
1 files changed, 40 insertions, 4 deletions
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 22cdbb40d15c..9489f00c1afe 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -32,6 +32,8 @@
#include <sys/socket.h>
// NT_PRSTATUS and NT_FPREGSET definition
#include <elf.h>
+// user_hwdebug_state definition
+#include <asm/ptrace.h>
#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
@@ -542,7 +544,7 @@ NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints ()
error = ReadHardwareDebugInfo ();
if (error.Fail())
- return LLDB_INVALID_INDEX32;
+ return 0;
return m_max_hwp_supported;
}
@@ -564,6 +566,7 @@ NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size
return LLDB_INVALID_INDEX32;
uint32_t control_value = 0, wp_index = 0;
+ lldb::addr_t real_addr = addr;
// Check if we are setting watchpoint other than read/write/access
// Also update watchpoint flag to match AArch64 write-read bit configuration.
@@ -586,9 +589,23 @@ NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size
return LLDB_INVALID_INDEX32;
// Check 8-byte alignment for hardware watchpoint target address.
- // TODO: Add support for watching un-aligned addresses
+ // Below is a hack to recalculate address and size in order to
+ // make sure we can watch non 8-byte alligned addresses as well.
if (addr & 0x07)
- return LLDB_INVALID_INDEX32;
+ {
+ uint8_t watch_mask = (addr & 0x07) + size;
+
+ if (watch_mask > 0x08)
+ return LLDB_INVALID_INDEX32;
+ else if (watch_mask <= 0x02)
+ size = 2;
+ else if (watch_mask <= 0x04)
+ size = 4;
+ else
+ size = 8;
+
+ addr = addr & (~0x07);
+ }
// Setup control value
control_value = watch_flags << 3;
@@ -618,6 +635,7 @@ NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size
if ((m_hwp_regs[wp_index].control & 1) == 0)
{
// Update watchpoint in local cache
+ m_hwp_regs[wp_index].real_addr = real_addr;
m_hwp_regs[wp_index].address = addr;
m_hwp_regs[wp_index].control = control_value;
m_hwp_regs[wp_index].refcount = 1;
@@ -799,6 +817,7 @@ NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t &wp_index, lldb
if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index)
&& trap_addr >= watch_addr && trap_addr < watch_addr + watch_size)
{
+ m_hwp_regs[wp_index].hit_addr = trap_addr;
return Error();
}
}
@@ -819,7 +838,24 @@ NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index)
return LLDB_INVALID_ADDRESS;
if (WatchpointIsEnabled(wp_index))
- return m_hwp_regs[wp_index].address;
+ return m_hwp_regs[wp_index].real_addr;
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
+lldb::addr_t
+NativeRegisterContextLinux_arm64::GetWatchpointHitAddress (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].hit_addr;
else
return LLDB_INVALID_ADDRESS;
}