Orig posted in https://reviews.llvm.org/D147674 as part of a debugserver patch, creating two phabs to track those separate patches so it's easier to review.
This patch fixes a problem with watchpoints on AArch targets using lldb-server (and soon debugserver), where a large write that begins before a watched region, and extends into the watched region, is reported as a trap address before the watched memory range. I can show this on an AArch64 Ubuntu install:
{ uint8_t buf[8]; uint64_t *u64_p = (uint64_t *) buf; *u64_p = 5; // break here (*u64_p)++;
At the break here line, if and do watch set variable buf[2] and c, the packets from lldb server look like
< 21> send packet: $Z2,fffffffff36a,1#75 < 6> read packet: $OK#9a < 5> send packet: $c#63 <838> read packet: $T05thread:493;name:a.out; [...] ;reason:watchpoint;description:323831343734393736373037343334203320323831343734393736373037343332;#db
The description is 281474976707434 3 281474976707432 aka 0x0000fffffffff36a 3 0x0000fffffffff368. The first address is an address contained within the hit watchpoint. The second number is the hardware register index. The third number is the actual address that was accessed,
(lldb) v &buf u64_p (uint8_t (*)[8]) &buf = 0x0000fffffffff368 (uint64_t *) u64_p = 0x0000fffffffff368 (lldb)
Right now, lldb has a rule that "for MIPS an ARM, if the third number is NOT contained within any watchpoint region, silently continue past this watchpoint". From the user's perspective, lldb misses the watchpoint modification. We see this a lot on macOS with bzero()/memset() when you're watching an element of an object and it is overwritten.
For MIPS this behavior is correct because any access to an 8B granule triggers a watchpoint in that granule. If I watch 4 bytes at 0x1004, and someone accesses 1 byte at 0x1002, a watchpoint will trigger. Jaydeep Patil in 2015 ( https://reviews.llvm.org/D11672 ) added this third argument and the "silently step over it and don't tell the user" behavior; that patch decodes the instruction that caused the trap to determine the actual address that was accessed.
However, the intended use/meaning of this third field was very confusing (to me), and in 2016 Omair ( https://reviews.llvm.org/D21516 ) enabled the same behavior on ARM targets and reported the actual accessed address. I'm not exactly sure what issue motivated this, it may have simply been a misunderstanding of how StopInfo decodes and uses these three addresses. If nothing is done on ARM targets and an access outside a watched region, lldb stops execution and doesn't know how to disable the correct watchpoint & advance execution, my guess is that he was addressing that issue.
As the reason:watchpoint's description value has grown from "wp addr + hw reg index" to "wp addr + hw reg index + actual trap address", with implicit behavior on MIPS that an actual trap address silently continues if it's outside the range of a watchpoint, this is not the best. We should stop using description and add 2-4 keys in the stop info packet, e.g. wp-address:, wp-reg-index:, wp-hit-address:, silently-continue: that can be provided as needed. We can remove the "on MIPS do this" behavior from generic lldb -- the stub is probably in the best position to know if this is a false watchpoint tigger that should be ignored, and it can tell lldb. Looking at the latest ARM ARM A-Profile docs, this seems like a situation that can exist in some modes as well, we may need to flag this from AArch64 debugserver/lldb-server in the future.
We don't currently have MIPS supported in lldb - it was removed c. 2021 in anticipation of someone starting to actively maintain it again. But this "silently continue" behavior may be needed for AArch64, and it may be needed again for MIPS if that target is revived.
What does this "v." mean? Is it short for "see here " or some kind of citation?