From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
To: gdb-patches@sourceware.org
Subject: patch: fix bug with enabling/disabling breakpoints for duplicated locations
Date: Sun, 31 Jul 2011 20:36:00 -0000 [thread overview]
Message-ID: <1312074212.8735.4.camel@soleil> (raw)
When breakpoint always-inserted is on, and there are duplicated
locations, enabling/disabling breakpoints is giving errors
(at least with gdbserver, because multiple z or Z packets are being sent
for the same address).
The logic to handle duplicated locations in breakpoints.c
is that in a list of duplicated location that should be inserted:
- the first one is not marked as duplicated and is inserted
- following ones are marked as duplicated and are not inserted.
This invariant was not properly maintained by update_global_location_list.
Tested on f12/x86 in native and gdbserver mode.
Tested on debian5/amd64 in native and gdbserver mode.
No regression identified.
Ok to apply ?
gdb/ChangeLog
* breakpoint.c (update_global_location_list): Ensure
invariant 'first loc marked not duplicated and inserted,
following locs marked duplicated/not inserted' is respected
for multiple locations at the same address.
(unduplicated_should_be_inserted) New function.
(swap_insertion) New function.
gdb/testsuite/ChangeLog
* gdb/testsuite/gdb.base/break-always.exp: Complete the test
with duplicated breakpoints and enabling/disabling them.
Index: gdb/breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.603
diff -c -p -r1.603 breakpoint.c
*** gdb/breakpoint.c 26 Jul 2011 19:39:58 -0000 1.603
--- gdb/breakpoint.c 30 Jul 2011 21:40:39 -0000
*************** should_be_inserted (struct bp_location *
*** 1571,1576 ****
--- 1571,1589 ----
return 1;
}
+ /* Same as should_be_inserted but does the check assuming
+ that the location is not duplicated. */
+ static int
+ unduplicated_should_be_inserted (struct bp_location *bl)
+ {
+ int result;
+ const int save_duplicate = bl->duplicate;
+ bl->duplicate = 0;
+ result = should_be_inserted (bl);
+ bl->duplicate = save_duplicate;
+ return result;
+ }
+
/* Insert a low-level "breakpoint" of some type. BL is the breakpoint
location. Any error messages are printed to TMP_ERROR_STREAM; and
DISABLED_BREAKS, and HW_BREAKPOINT_ERROR are used to report problems.
*************** bp_location_target_extensions_update (vo
*** 10238,10243 ****
--- 10251,10272 ----
}
}
+ /* Swap the insertion/duplication state between two locations. */
+
+ static void
+ swap_insertion (struct bp_location *left, struct bp_location *right)
+ {
+ const int left_inserted = left->inserted;
+ const int left_duplicate = left->duplicate;
+ const struct bp_target_info left_target_info = left->target_info;
+ left->inserted = right->inserted;
+ left->duplicate = right->duplicate;
+ left->target_info = right->target_info;
+ right->inserted = left_inserted;
+ right->duplicate = left_duplicate;
+ right->target_info = left_target_info;
+ }
+
/* If SHOULD_INSERT is false, do not insert any breakpoint locations
into the inferior, only remove already-inserted locations that no
longer should be inserted. Functions that delete a breakpoint or
*************** update_global_location_list (int should_
*** 10374,10384 ****
if (breakpoint_locations_match (loc2, old_loc))
{
- /* For the sake of should_be_inserted.
- Duplicates check below will fix up this
- later. */
- loc2->duplicate = 0;
-
/* Read watchpoint locations are switched to
access watchpoints, if the former are not
supported, but the latter are. */
--- 10403,10408 ----
*************** update_global_location_list (int should_
*** 10388,10397 ****
loc2->watchpoint_type = old_loc->watchpoint_type;
}
! if (loc2 != old_loc && should_be_inserted (loc2))
{
! loc2->inserted = 1;
! loc2->target_info = old_loc->target_info;
keep_in_target = 1;
break;
}
--- 10412,10424 ----
loc2->watchpoint_type = old_loc->watchpoint_type;
}
! /* loc2 is a duplicated location. We need to check
! if it should be inserted in case it will be
! unduplicated. */
! if (loc2 != old_loc
! && unduplicated_should_be_inserted (loc2))
{
! swap_insertion (old_loc, loc2);
keep_in_target = 1;
break;
}
*************** update_global_location_list (int should_
*** 10538,10543 ****
--- 10565,10576 ----
continue;
}
+
+ /* This and the above ensure the invariant that the first location
+ is not duplicated, and is the inserted one.
+ All following are marked as duplicated, and are not inserted. */
+ if (loc->inserted)
+ swap_insertion(loc, *loc_first_p);
loc->duplicate = 1;
if ((*loc_first_p)->owner->enable_state == bp_permanent && loc->inserted
Index: gdb/testsuite/gdb.base/break-always.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/break-always.exp,v
retrieving revision 1.7
diff -c -p -r1.7 break-always.exp
*** gdb/testsuite/gdb.base/break-always.exp 1 Jan 2011 15:33:40 -0000 1.7
--- gdb/testsuite/gdb.base/break-always.exp 30 Jul 2011 21:40:40 -0000
***************
*** 14,19 ****
--- 14,21 ----
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Test that 'set breakpoint always-inserted 1' is not a brick
+ # Also verifies that breakpoint enabling/disabling works properly
+ # with duplicated breakpoints.
if { [prepare_for_testing break-always.exp break-always break-always.c] } {
return -1
*************** gdb_test "show breakpoint always-inserte
*** 29,34 ****
--- 31,54 ----
runto foo
gdb_test "break bar" "Breakpoint 2.*" "set breakpoint on bar"
+ gdb_test "break bar" "Note: breakpoint 2 also set.*Breakpoint 3.*" "set 2nd breakpoint on bar"
+ gdb_test "break bar" "Note: breakpoints 2 and 3 also set.*Breakpoint 4.*" "set 3rd breakpoint on bar"
+ gdb_test "break bar" "Note: breakpoints 2, 3 and 4 also set.*Breakpoint 5.*" "set 4th breakpoint on bar"
+ gdb_test "info breakpoints" "keep y.*keep y.*keep y.*keep y.*keep y.*" "check breakpoint state"
+ gdb_test_no_output "disable" "disable all breakpoints"
+ gdb_test_no_output "enable" "enable all breakpoints"
+ gdb_test_no_output "disable" "disable all breakpoints"
+ gdb_test_no_output "enable 3" "enable 3 3.A"
+ gdb_test_no_output "disable 3" "disable 3.B"
+ gdb_test_no_output "enable 3" "enable 3.C"
+ gdb_test_no_output "enable 2" "enable 2.D"
+ gdb_test_no_output "disable 2" "disable 2.E"
+ gdb_test_no_output "disable 3" "disable 3.F"
+ gdb_test_no_output "enable 3" "enable 3.G"
+ gdb_test_no_output "enable 2" "enable 2.H"
+ gdb_test_no_output "disable 2" "disable 2.I"
+ gdb_test "info breakpoints" "keep n.*keep n.*keep y.*keep n.*keep n.*" "check breakpoint state"
+ gdb_test_no_output "enable" "enable all breakpoints"
gdb_continue_to_breakpoint "bar" ".*break-always.c:$bar_location.*"
next reply other threads:[~2011-07-31 1:03 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-31 20:36 Philippe Waroquiers [this message]
2011-08-03 15:09 ` Pedro Alves
2011-08-03 21:28 ` Philippe Waroquiers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1312074212.8735.4.camel@soleil \
--to=philippe.waroquiers@skynet.be \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox