+2011-08-03 Philippe Waroquiers <philippe.waroquiers@skynet.be>
+
+ * 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.
+
2011-08-03 Jan Kratochvil <jan.kratochvil@redhat.com>
* stack.c (print_frame_arguments_choices): Comment typo fix.
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.
}
}
+/* 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
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. */
loc2->watchpoint_type = old_loc->watchpoint_type;
}
- if (loc2 != old_loc && should_be_inserted (loc2))
+ /* 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))
{
- loc2->inserted = 1;
- loc2->target_info = old_loc->target_info;
+ swap_insertion (old_loc, loc2);
keep_in_target = 1;
break;
}
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
# 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
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.*" "initial check breakpoint state"
+gdb_test_no_output "disable" "initial disable all breakpoints"
+gdb_test_no_output "enable" "initial enable all breakpoints"
+gdb_test_no_output "disable" "re-disable all breakpoints"
+gdb_test_no_output "enable 3" "enable 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.*" "before re-enable check breakpoint state"
+gdb_test_no_output "enable" "re-enable all breakpoints"
gdb_continue_to_breakpoint "bar" ".*break-always.c:$bar_location.*"