Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -74,6 +74,9 @@ GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override; lldb::addr_t + GetWatchpointHitAddress (uint32_t wp_index) override; + + lldb::addr_t GetWatchpointAddress (uint32_t wp_index) override; uint32_t @@ -161,6 +164,8 @@ struct DREG { lldb::addr_t address; // Breakpoint/watchpoint address value. + lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception occurred. + lldb::addr_t real_addr; // Address value that should cause target to stop. uint32_t control; // Breakpoint/watchpoint control value. uint32_t refcount; // Serves as enable/disable and refernce counter. }; Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -566,6 +566,7 @@ 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. @@ -588,9 +589,23 @@ 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; @@ -620,6 +635,7 @@ 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; @@ -801,6 +817,7 @@ 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(); } } @@ -821,7 +838,24 @@ 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; } Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -2059,7 +2059,8 @@ { WatchpointSP wp_sp; ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); - if (core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) + if ((core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) || + (core >= ArchSpec::eCore_arm_arm64 && core <= ArchSpec::eCore_arm_aarch64)) wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr); if (!wp_sp) wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);