[debugserver/ARM64] Make sure watchpoints hit are attributed correctly.

This didn't happen for arm64 if you have watches for variables
that are contigous in memory.

<rdar://problem/55135006>
This commit is contained in:
Davide Italiano 2020-03-31 13:55:36 -07:00
parent e094dd5adc
commit 64799fbebd
4 changed files with 79 additions and 17 deletions

View File

@ -0,0 +1,3 @@
C_SOURCES := main.c
include Makefile.rules

View File

@ -0,0 +1,43 @@
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestWatchpointCount(TestBase):
mydir = TestBase.compute_mydir(__file__)
NO_DEBUG_INFO_TESTCASE = True
def setUp(self):
TestBase.setUp(self)
def test_watchpoint_count(self):
self.build()
(_, process, thread, _) = lldbutil.run_to_source_breakpoint(self, "patatino", lldb.SBFileSpec("main.c"))
frame = thread.GetFrameAtIndex(0)
first_var = frame.FindVariable("x1")
second_var = frame.FindVariable("x2")
error = lldb.SBError()
first_watch = first_var.Watch(True, False, True, error)
if not error.Success():
self.fail(
"Failed to make watchpoint for x1: %s" %
(error.GetCString()))
second_watch = second_var.Watch(True, False, True, error)
if not error.Success():
self.fail(
"Failed to make watchpoint for x2: %s" %
(error.GetCString()))
process.Continue()
stop_reason = thread.GetStopReason()
self.assertEqual(stop_reason, lldb.eStopReasonWatchpoint, "watchpoint for x1 not hit")
stop_reason_descr = thread.GetStopDescription(256)
self.assertEqual(stop_reason_descr, "watchpoint 1")
process.Continue()
stop_reason = thread.GetStopReason()
self.assertEqual(stop_reason, lldb.eStopReasonWatchpoint, "watchpoint for x2 not hit")
stop_reason_descr = thread.GetStopDescription(256)
self.assertEqual(stop_reason_descr, "watchpoint 2")

View File

@ -0,0 +1,13 @@
#include <stdint.h>
#include <stdio.h>
int main() {
uint8_t x1 = 0;
uint16_t x2 = 0;
printf("patatino\n");
x1 += 1;
x2 += 2;
return 0;
}

View File

@ -1067,31 +1067,34 @@ uint32_t DNBArchMachARM64::GetHardwareWatchpointHit(nub_addr_t &addr) {
"DNBArchMachARM64::GetHardwareWatchpointHit() addr = 0x%llx",
(uint64_t)addr);
// This is the watchpoint value to match against, i.e., word address.
nub_addr_t wp_val = addr & ~((nub_addr_t)3);
if (kret == KERN_SUCCESS) {
DBG &debug_state = m_state.dbg;
uint32_t i, num = NumSupportedHardwareWatchpoints();
for (i = 0; i < num; ++i) {
nub_addr_t wp_addr = GetWatchAddress(debug_state, i);
DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::"
"GetHardwareWatchpointHit() slot: %u "
"(addr = 0x%llx).",
i, (uint64_t)wp_addr);
if (wp_val == wp_addr) {
uint32_t byte_mask = bits(debug_state.__wcr[i], 12, 5);
uint32_t byte_mask = bits(debug_state.__wcr[i], 12, 5);
// Sanity check the byte_mask, first.
if (LowestBitSet(byte_mask) < 0)
continue;
DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::"
"GetHardwareWatchpointHit() slot: %u "
"(addr = 0x%llx; byte_mask = 0x%x)",
i, static_cast<uint64_t>(wp_addr),
byte_mask);
// Check that the watchpoint is enabled.
if (!IsWatchpointEnabled(debug_state, i))
continue;
if (!IsWatchpointEnabled(debug_state, i))
continue;
// Compute the starting address (from the point of view of the
// debugger).
addr = wp_addr + LowestBitSet(byte_mask);
if (bits(wp_addr, 48, 3) != bits(addr, 48, 3))
continue;
// Sanity check the byte_mask
uint32_t lsb = LowestBitSet(byte_mask);
if (lsb < 0)
continue;
uint64_t byte_to_match = bits(addr, 2, 0);
if (byte_mask & (1 << byte_to_match)) {
addr = wp_addr + lsb;
return i;
}
}