Summary: | 'until' behavion in watchpoint.c (for loops) incompatible with loop condition instructions at the top of the loop | ||
---|---|---|---|
Product: | gdb | Reporter: | David Blaikie <dblaikie> |
Component: | c++ | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | evans_chen1, guinevere |
Priority: | P2 | ||
Version: | 7.7 | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Last reconfirmed: |
Description
David Blaikie
2014-08-26 22:20:28 UTC
ping *** Bug 27196 has been marked as a duplicate of this bug. *** I believe I have a solution for this problem. The issue wasn't that the loop condition was at the top, but rather that there were lines at the bottom that weren't marked as is_stmt. This way, when calculating the maximum PC to execute to, it landed on that !is_stmt instruction, assumed the inferior was out of the block and GDB stopped at the next is_stmt instruction, the one inside the loop My patch fixes this by searching the first instance of an is_stmt instruction, or the first instruction that happens on a different line, and sets that as the stopping PC The patch is available here: https://sourceware.org/pipermail/gdb-patches/2022-January/184799.html The master branch has been updated by Andrew Burgess <aburgess@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9ab50efc463ff723b8e9102f1f68a6983d320517 commit 9ab50efc463ff723b8e9102f1f68a6983d320517 Author: Bruno Larsen <blarsen@redhat.com> Date: Wed Jan 26 10:08:13 2022 -0300 gdb: fix until behavior with trailing !is_stmt lines When using the command "until", it is expected that GDB will exit a loop if the current instruction is the last one related to that loop. However, if there were trailing non-statement instructions, "until" would just behave as "next". This was noticeable in clang-compiled code, but might happen with gcc-compiled as well. PR gdb/17315 relates to this problem, as running gdb.base/watchpoint.exp with clang would fail for this reason. To better understand this issue, consider the following source code, with line numbers marked on the left: 10: for (i = 0; i < 10; ++i) 11: loop_body (); 12: other_stuff (); If we transform this to pseudo-assembler, and generate a line table, we could end up with something like this: Address | Pseudo-Assembler | Line | Is-Statement? 0x100 | i = 0 | 10 | Yes 0x104 | loop_body () | 11 | Yes 0x108 | i = i + 1 | 10 | Yes 0x10c | if (i < 10): | 10 | No 0x110 | goto 0x104 | 10 | No 0x114 | other_stuff () | 12 | Yes Notice the two non-statement instructions at the end of the loop. The problem is that when we reach address 0x108 and use 'until', hoping to leave the loop, GDB sets up a stepping range that runs from the start of the function (0x100 in our example) to the end of the current line table entry, that is 0x10c in our example. GDB then starts stepping forward. When 0x10c is reached GDB spots that we have left the stepping range, that the new location is not a statement, and that the new location is associated with the same source line number as the previous stepping range. GDB then sets up a new stepping range that runs from 0x10c to 0x114, and continues stepping forward. Within that stepping range the inferior hits the goto (at 0x110) and loops back to address 0x104. At 0x104 GDB spots that we have left the previous stepping range, that the new address is marked as a statement, and that the new address is for a different source line. As a result, GDB stops and returns control to the user. This is not what the user was expecting, they expected GDB to exit the loop. The fix proposed in this patch, is that, when the user issues the 'until' command, and GDB sets up the initial stepping range, GDB will check subsequent SALs (symtab_and_lines) to see if they are non-statements associated with the same line number. If they are then the end of the initial stepping range is extended to the end of the non-statement SALs. In our example above, the user is at 0x108 and uses 'until', GDB now sets up a stepping range from the start of the function 0x100 to 0x114, the first address associated with a different line. Now as GDB steps around the loop it never leaves the initial stepping range. It is only when GDB exits the loop that we leave the stepping range, and the stepping finishes at address 0x114. This patch also adds a test case that can be run with gcc to test that this functionality is not broken in the future. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=17315 Sorry for the delay in closing this. The above-mentioned commit should fix this issue |