This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA] Keep breakpoints always inserted.
- From: Vladimir Prus <vladimir at codesourcery dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Thu, 28 Feb 2008 17:17:13 +0300
- Subject: [RFA] Keep breakpoints always inserted.
This is hopefully final revision of my patch to keep
breakpoints always inserted, which is needed to support
non-stop mode. A new variable 'breakpoint always-inserted'
is introduced that enables this mode. When enabled,
breakpoints are inserted into target immediately when created,
and they are not removed when we stop.
Compared to the previous version of this patch:
- The always-inserted mode is actually configurable
- In always-inserted mode, breakpoints are removed
from target on detach/disconnect.
OK?
- Volodya
* breakpoint.h (bp_location_p): New typedef.
Register a vector of bp_location_p.
* breakpoint.c (always_inserted_mode)
(show_always_inserted_mode): New.
(unlink_locations_from_global_list): Remove.
(update_global_location_list)
(update_global_location_list_nothrow): New.
(update_watchpoint): Don't free locations.
(should_insert_location): New.
(insert_bp_location): Use should_insert_location.
(insert_breakpoint_locations): Copied from
insert_breakpoints.
(insert_breakpoint): Use insert_breakpoint_locations.
(bpstat_stop_status): Call update_global_location_list
when disabling breakpoint.
(allocate_bp_location): Don't add to bp_location_chain.
(set_raw_breakpoint)
(create_longjmp_breakpoint, enable_longjmp_breakpoint)
(disable_longjmp_breakpoint, create_overlay_event_breakpoint)
(enable_overlay_breakpoints, disable_overlay_breakpoints)
(set_longjmp_resume_breakpoint)
(enable_watchpoints_after_interactive_call_stop)
(disable_watchpoints_before_interactive_call_start)
(create_internal_breakpoint)
(create_fork_vfork_event_catchpoint)
(create_exec_event_catchpoint, set_momentary_breakpoint)
(create_breakpoints, break_command_1, watch_command_1)
(create_exception_catchpoint)
(handle_gnu_v3_exceptions)
(disable_breakpoint, breakpoint_re_set_one)
(create_thread_event_breakpoint, create_solib_event_breakpoint)
(create_ada_exception_breakpoint): : Don't call check_duplicates.
Call update_global_location_list.
(delete_breakpoint): Don't remove locations and don't
try to reinsert them. Call update_global_location_list.
(update_breakpoint_locations): Likewise.
(restore_always_inserted_mode): New.
(update_breakpoints_after_exec): Temporary disable
always inserted mode.
* Makefile.in: Update dependencies.
* infrun.c (proceed): Remove breakpoints while stepping
over breakpoint.
(handle_inferior_event): Don't remove or insert
breakpoints.
* linux-fork.c (checkpoint_command): Remove breakpoints
before fork and insert after.
(linux_fork_context): Remove breakpoints before switch
and insert after.
* target.c (target_disconnect, target_detach): Remove
breakpoints from target.
---
gdb/Makefile.in | 5 +-
gdb/breakpoint.c | 419 +++++++++++++++++++++++++++++++-----------------------
gdb/breakpoint.h | 5 +
gdb/infrun.c | 27 ++--
gdb/linux-fork.c | 7 +
gdb/target.c | 14 ++-
6 files changed, 281 insertions(+), 196 deletions(-)
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index ba64982..114129f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1951,7 +1951,8 @@ breakpoint.o: breakpoint.c $(defs_h) $(symtab_h) $(frame_h) $(breakpoint_h) \
$(objfiles_h) $(source_h) $(linespec_h) $(completer_h) $(gdb_h) \
$(ui_out_h) $(cli_script_h) $(gdb_assert_h) $(block_h) $(solib_h) \
$(solist_h) $(observer_h) $(exceptions_h) $(gdb_events_h) \
- $(mi_common_h) $(memattr_h) $(ada_lang_h) $(top_h) $(hashtab_h)
+ $(mi_common_h) $(memattr_h) $(ada_lang_h) $(top_h) $(hashtab_h) \
+ $(gdb_stdint_h)
bsd-kvm.o: bsd-kvm.c $(defs_h) $(cli_cmds_h) $(command_h) $(frame_h) \
$(regcache_h) $(target_h) $(value_h) $(gdbcore_h) $(gdb_assert_h) \
$(readline_h) $(bsd_kvm_h)
@@ -2871,7 +2872,7 @@ symtab.o: symtab.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \
target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \
- $(exceptions_h) $(target_descriptions_h)
+ $(exceptions_h) $(target_descriptions_h) $(gdb_stdint_h)
target-descriptions.o: target-descriptions.c $(defs_h) $(arch_utils_h) \
$(target_h) $(target_descriptions_h) $(vec_h) $(xml_tdesc_h) \
$(gdbcmd_h) $(gdb_assert_h) $(gdbtypes_h) $(reggroups_h) \
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index d43a608..fd7364a 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -59,6 +59,8 @@
#include "gdb-events.h"
#include "mi/mi-common.h"
+#include "gdb_stdint.h"
+
/* Prototypes for local functions. */
static void until_break_command_continuation (struct continuation_arg *arg);
@@ -204,11 +206,14 @@ static void mark_breakpoints_out (void);
static struct bp_location *
allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type);
-static void
-unlink_locations_from_global_list (struct breakpoint *bpt);
+static void update_global_location_list (void);
-static int
-is_hardware_watchpoint (struct breakpoint *bpt);
+static void update_global_location_list_nothrow (void);
+
+static int is_hardware_watchpoint (struct breakpoint *bpt);
+
+static void
+insert_breakpoint_locations (void);
/* Prototypes for exported functions. */
@@ -256,6 +261,20 @@ Automatic usage of hardware breakpoints is %s.\n"),
value);
}
+/* If 1, gdb will keep breakpoints inserted even as
+ inferior is stopped, and immediately insert any new
+ breakoints.
+ If 0, gdb will insert breakpoints into inferior only
+ when rusuming it, and will remove breakpoints
+ upon stop. */
+static int always_inserted_mode = 0;
+static void
+show_always_inserted_mode (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("Always inserted breakpoint mode is %s.\n"), value);
+}
+
void _initialize_breakpoint (void);
@@ -831,14 +850,10 @@ update_watchpoint (struct breakpoint *b, int reparse)
struct bp_location *loc;
bpstat bs;
- unlink_locations_from_global_list (b);
- for (loc = b->loc; loc;)
- {
- struct bp_location *loc_next = loc->next;
- remove_breakpoint (loc, mark_uninserted);
- xfree (loc);
- loc = loc_next;
- }
+ /* We don't free locations. They are stored in
+ bp_location_chain and update_global_locations will
+ eventually delete them and remove breakpoints if
+ needed. */
b->loc = NULL;
if (b->disposition == disp_del_at_next_stop)
@@ -983,6 +998,20 @@ in which its expression is valid.\n"),
}
+/* Returns 1 iff breakpoint location should be
+ inserted in the inferior. */
+static int
+should_insert_location (struct bp_location *bpt)
+{
+ if (!breakpoint_enabled (bpt->owner))
+ return 0;
+
+ if (!bpt->enabled || bpt->shlib_disabled || bpt->inserted || bpt->duplicate)
+ return 0;
+
+ return 1;
+}
+
/* Insert a low-level "breakpoint" of some type. BPT is the breakpoint.
Any error messages are printed to TMP_ERROR_STREAM; and DISABLED_BREAKS,
PROCESS_WARNING, and HW_BREAKPOINT_ERROR are used to report problems.
@@ -997,10 +1026,7 @@ insert_bp_location (struct bp_location *bpt,
{
int val = 0;
- if (!breakpoint_enabled (bpt->owner))
- return 0;
-
- if (!bpt->enabled || bpt->shlib_disabled || bpt->inserted || bpt->duplicate)
+ if (!should_insert_location (bpt))
return 0;
/* Initialize the target-specific information. */
@@ -1201,13 +1227,35 @@ Note: automatically using hardware breakpoints for read-only addresses.\n"));
return 0;
}
+/* Make sure all breakpoints are inserted in inferior.
+ Throws exception on any error.
+ A breakpoint that is already inserted won't be inserted
+ again, so calling this function twice is safe. */
+void
+insert_breakpoints (void)
+{
+ struct breakpoint *bpt;
+
+ ALL_BREAKPOINTS (bpt)
+ if (is_hardware_watchpoint (bpt))
+ update_watchpoint (bpt, 0 /* don't reparse. */);
+
+ update_global_location_list ();
+
+ if (!always_inserted_mode && target_has_execution)
+ /* update_global_location_list does not insert breakpoints
+ when always_inserted_mode is not enabled. Explicitly
+ insert them now. */
+ insert_breakpoint_locations ();
+}
+
/* insert_breakpoints is used when starting or continuing the program.
remove_breakpoints is used when the program stops.
Both return zero if successful,
or an `errno' value if could not write the inferior. */
-void
-insert_breakpoints (void)
+static void
+insert_breakpoint_locations (void)
{
struct breakpoint *bpt;
struct bp_location *b, *temp;
@@ -1219,14 +1267,10 @@ insert_breakpoints (void)
struct ui_file *tmp_error_stream = mem_fileopen ();
make_cleanup_ui_file_delete (tmp_error_stream);
-
+
/* Explicitly mark the warning -- this will only be printed if
there was an error. */
fprintf_unfiltered (tmp_error_stream, "Warning:\n");
-
- ALL_BREAKPOINTS (bpt)
- if (is_hardware_watchpoint (bpt))
- update_watchpoint (bpt, 0 /* don't reparse */);
ALL_BP_LOCATIONS_SAFE (b, temp)
{
@@ -1365,17 +1409,31 @@ reattach_breakpoints (int pid)
return 0;
}
+static void
+restore_always_inserted_mode (void *p)
+{
+ always_inserted_mode = (uintptr_t) p;
+}
+
void
update_breakpoints_after_exec (void)
{
struct breakpoint *b;
struct breakpoint *temp;
+ struct cleanup *cleanup;
/* Doing this first prevents the badness of having delete_breakpoint()
write a breakpoint's current "shadow contents" to lift the bp. That
shadow is NOT valid after an exec()! */
mark_breakpoints_out ();
+ /* The binary we used to debug is now gone, and we're updating
+ breakpoints for the new binary. Until we're done, we should not
+ try to insert breakpoints. */
+ cleanup = make_cleanup (restore_always_inserted_mode,
+ (void *) (uintptr_t) always_inserted_mode);
+ always_inserted_mode = 0;
+
ALL_BREAKPOINTS_SAFE (b, temp)
{
/* Solib breakpoints must be explicitly reset after an exec(). */
@@ -1457,6 +1515,7 @@ update_breakpoints_after_exec (void)
}
/* FIXME what about longjmp breakpoints? Re-create them here? */
create_overlay_event_breakpoint ("_ovly_debug_event");
+ do_cleanups (cleanup);
}
int
@@ -1496,9 +1555,9 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is)
/* Permanent breakpoints cannot be inserted or removed. */
return 0;
- if (b->owner->type == bp_none)
- warning (_("attempted to remove apparently deleted breakpoint #%d?"),
- b->owner->number);
+ /* The type of none suggests that owner is actually deleted.
+ This should not ever happen. */
+ gdb_assert (b->owner->type != bp_none);
if (b->loc_type == bp_loc_software_breakpoint
|| b->loc_type == bp_loc_hardware_breakpoint)
@@ -2892,7 +2951,10 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
{
/* We will stop here */
if (b->disposition == disp_disable)
- b->enable_state = bp_disabled;
+ {
+ b->enable_state = bp_disabled;
+ update_global_location_list ();
+ }
if (b->silent)
bs->print = 0;
bs->commands = b->commands;
@@ -4120,18 +4182,6 @@ allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type)
internal_error (__FILE__, __LINE__, _("unknown breakpoint type"));
}
- /* Add this breakpoint to the end of the chain. */
-
- loc_p = bp_location_chain;
- if (loc_p == 0)
- bp_location_chain = loc;
- else
- {
- while (loc_p->global_next)
- loc_p = loc_p->global_next;
- loc_p->global_next = loc;
- }
-
return loc;
}
@@ -4139,6 +4189,10 @@ static void free_bp_location (struct bp_location *loc)
{
if (loc->cond)
xfree (loc->cond);
+
+ if (loc->function_name)
+ xfree (loc->function_name);
+
xfree (loc);
}
@@ -4243,7 +4297,6 @@ set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
set_breakpoint_location_function (b->loc);
- check_duplicates (b);
breakpoints_changed ();
return b;
@@ -4307,6 +4360,7 @@ create_longjmp_breakpoint (char *func_name)
b->silent = 1;
if (func_name)
b->addr_string = xstrdup (func_name);
+ update_global_location_list ();
}
/* Call this routine when stepping and nexting to enable a breakpoint
@@ -4322,7 +4376,7 @@ enable_longjmp_breakpoint (void)
if (b->type == bp_longjmp)
{
b->enable_state = bp_enabled;
- check_duplicates (b);
+ update_global_location_list ();
}
}
@@ -4336,7 +4390,7 @@ disable_longjmp_breakpoint (void)
|| b->type == bp_longjmp_resume)
{
b->enable_state = bp_disabled;
- check_duplicates (b);
+ update_global_location_list ();
}
}
@@ -4363,6 +4417,7 @@ create_overlay_event_breakpoint (char *func_name)
b->enable_state = bp_disabled;
overlay_events_enabled = 0;
}
+ update_global_location_list ();
}
void
@@ -4374,7 +4429,7 @@ enable_overlay_breakpoints (void)
if (b->type == bp_overlay_event)
{
b->enable_state = bp_enabled;
- check_duplicates (b);
+ update_global_location_list ();
overlay_events_enabled = 1;
}
}
@@ -4388,7 +4443,7 @@ disable_overlay_breakpoints (void)
if (b->type == bp_overlay_event)
{
b->enable_state = bp_disabled;
- check_duplicates (b);
+ update_global_location_list ();
overlay_events_enabled = 0;
}
}
@@ -4404,6 +4459,8 @@ create_thread_event_breakpoint (CORE_ADDR address)
/* addr_string has to be used or breakpoint_re_set will delete me. */
b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address));
+ update_global_location_list_nothrow ();
+
return b;
}
@@ -4448,6 +4505,7 @@ create_solib_event_breakpoint (CORE_ADDR address)
struct breakpoint *b;
b = create_internal_breakpoint (address, bp_shlib_event);
+ update_global_location_list_nothrow ();
return b;
}
@@ -4545,6 +4603,8 @@ create_fork_vfork_event_catchpoint (int tempflag, char *cond_string,
b->enable_state = bp_enabled;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->forked_inferior_pid = 0;
+ update_global_location_list ();
+
mention (b);
}
@@ -4582,6 +4642,7 @@ create_exec_event_catchpoint (int tempflag, char *cond_string)
b->addr_string = NULL;
b->enable_state = bp_enabled;
b->disposition = tempflag ? disp_del : disp_donttouch;
+ update_global_location_list ();
mention (b);
}
@@ -4642,7 +4703,7 @@ set_longjmp_resume_breakpoint (CORE_ADDR pc, struct frame_id frame_id)
b->type);
b->enable_state = bp_enabled;
b->frame_id = frame_id;
- check_duplicates (b);
+ update_global_location_list ();
return;
}
}
@@ -4661,7 +4722,7 @@ disable_watchpoints_before_interactive_call_start (void)
&& breakpoint_enabled (b))
{
b->enable_state = bp_call_disabled;
- check_duplicates (b);
+ update_global_location_list ();
}
}
}
@@ -4680,7 +4741,7 @@ enable_watchpoints_after_interactive_call_stop (void)
&& (b->enable_state == bp_call_disabled))
{
b->enable_state = bp_enabled;
- check_duplicates (b);
+ update_global_location_list ();
}
}
}
@@ -4706,6 +4767,8 @@ set_momentary_breakpoint (struct symtab_and_line sal, struct frame_id frame_id,
if (in_thread_list (inferior_ptid))
b->thread = pid_to_thread_id (inferior_ptid);
+ update_global_location_list_nothrow ();
+
return b;
}
@@ -5105,6 +5168,8 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
cond_string, type, disposition,
thread, ignore_count, from_tty);
}
+
+ update_global_location_list ();
}
/* Parse ARG which is assumed to be a SAL specification possibly
@@ -5422,6 +5487,8 @@ break_command_really (char *arg, char *cond_string, int thread,
b->ignore_count = ignore_count;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->condition_not_parsed = 1;
+
+ update_global_location_list ();
mention (b);
}
@@ -5824,6 +5891,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
value_free_to_mark (mark);
mention (b);
+ update_global_location_list ();
}
/* Return count of locations need to be watched and can be handled
@@ -6382,6 +6450,7 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
xfree (sals.sals);
mention (b);
+ update_global_location_list ();
return 1;
}
@@ -6454,6 +6523,7 @@ create_ada_exception_breakpoint (struct symtab_and_line sal,
b->ops = ops;
mention (b);
+ update_global_location_list ();
}
/* Implement the "catch exception" command. */
@@ -6775,33 +6845,105 @@ breakpoint_auto_delete (bpstat bs)
}
}
-/* Remove locations of breakpoint BPT from
- the global list of breakpoint locations. */
-
static void
-unlink_locations_from_global_list (struct breakpoint *bpt)
+update_global_location_list (void)
{
- /* This code assumes that the locations
- of a breakpoint are found in the global list
- in the same order, but not necessary adjacent. */
- struct bp_location **tmp = &bp_location_chain;
- struct bp_location *here = bpt->loc;
+ struct breakpoint *b;
+ struct bp_location **next = &bp_location_chain;
+ struct bp_location *loc;
+ struct bp_location *loc2;
+ struct gdb_exception e;
+ VEC(bp_location_p) *old_locations = NULL;
+ int ret;
+ int ix;
+
+ /* Store old locations for future reference. */
+ for (loc = bp_location_chain; loc; loc = loc->global_next)
+ VEC_safe_push (bp_location_p, old_locations, loc);
- if (here == NULL)
- return;
+ bp_location_chain = NULL;
+ ALL_BREAKPOINTS (b)
+ {
+ for (loc = b->loc; loc; loc = loc->next)
+ {
+ *next = loc;
+ next = &(loc->global_next);
+ *next = NULL;
+ }
+ }
- for (; *tmp && here;)
+ /* Identify bp_location instances that are not
+ longer present in the new list, and therefore should
+ be freed. Note that it's not necessary that those locations
+ should be removed from inferior -- if there's another
+ location at the same address (previously marked as duplicate),
+ we don't need to remove/insert the location. */
+ for (ix = 0; VEC_iterate(bp_location_p, old_locations, ix, loc); ++ix)
{
- if (*tmp == here)
+ int found_object = 0;
+ int found_address = 0;
+ for (loc2 = bp_location_chain; loc2; loc2 = loc2->global_next)
+ if (loc2 == loc)
+ {
+ found_object = 1;
+ break;
+ }
+
+ /* If this location is not longer present, and
+ inserted, look if there's maybe new location
+ at the same address. If so, mark that one
+ inserted, and don't remove this one.
+
+ This is needed so that we don't have a window
+ where a breakpoint at certian location is not
+ inserted. */
+ if (!found_object && loc->inserted)
{
- *tmp = here->global_next;
- here = here->next;
+ /* See if there's another location at the same
+ address, in which case we don't need to
+ remove this one. */
+ if (breakpoint_address_is_meaningful (loc->owner))
+ for (loc2 = bp_location_chain; loc2; loc2 = loc2->global_next)
+ {
+ /* For the sake of should_insert_location. The
+ call the check_duplicates will fix up this later. */
+ loc2->duplicate = 0;
+ if (should_insert_location (loc2)
+ && loc2 != loc && loc2->address == loc->address)
+ {
+ loc2->inserted = 1;
+ loc2->target_info = loc->target_info;
+ found_address = 1;
+ break;
+ }
+ }
}
- else
+
+ if (loc->inserted && !found_object && !found_address)
{
- tmp = &((*tmp)->global_next);
+ /* FIXME? Handle error? */
+ remove_breakpoint (loc, mark_uninserted);
}
+
+ if (!found_object)
+ free_bp_location (loc);
+ }
+
+ ALL_BREAKPOINTS (b)
+ {
+ check_duplicates (b);
}
+
+ if (always_inserted_mode && target_has_execution)
+ insert_breakpoint_locations ();
+}
+
+static void
+update_global_location_list_nothrow (void)
+{
+ struct gdb_exception e;
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ update_global_location_list ();
}
/* Delete a breakpoint and clean up all traces of it in the data
@@ -6812,7 +6954,7 @@ delete_breakpoint (struct breakpoint *bpt)
{
struct breakpoint *b;
bpstat bs;
- struct bp_location *loc;
+ struct bp_location *loc, *next;
gdb_assert (bpt != NULL);
@@ -6836,18 +6978,6 @@ delete_breakpoint (struct breakpoint *bpt)
deprecated_delete_breakpoint_hook (bpt);
breakpoint_delete_event (bpt->number);
- for (loc = bpt->loc; loc; loc = loc->next)
- {
- if (loc->inserted)
- remove_breakpoint (loc, mark_inserted);
-
- if (loc->cond)
- xfree (loc->cond);
-
- if (loc->function_name)
- xfree (loc->function_name);
- }
-
if (breakpoint_chain == bpt)
breakpoint_chain = bpt->next;
@@ -6858,85 +6988,6 @@ delete_breakpoint (struct breakpoint *bpt)
break;
}
- unlink_locations_from_global_list (bpt);
-
- check_duplicates (bpt);
-
- if (bpt->type != bp_hardware_watchpoint
- && bpt->type != bp_read_watchpoint
- && bpt->type != bp_access_watchpoint
- && bpt->type != bp_catch_fork
- && bpt->type != bp_catch_vfork
- && bpt->type != bp_catch_exec)
- for (loc = bpt->loc; loc; loc = loc->next)
- {
- /* If this breakpoint location was inserted, and there is
- another breakpoint at the same address, we need to
- insert the other breakpoint. */
- if (loc->inserted)
- {
- struct bp_location *loc2;
- ALL_BP_LOCATIONS (loc2)
- if (loc2->address == loc->address
- && loc2->section == loc->section
- && !loc->duplicate
- && loc2->owner->enable_state != bp_disabled
- && loc2->enabled
- && !loc2->shlib_disabled
- && loc2->owner->enable_state != bp_call_disabled)
- {
- int val;
-
- /* We should never reach this point if there is a permanent
- breakpoint at the same address as the one being deleted.
- If there is a permanent breakpoint somewhere, it should
- always be the only one inserted. */
- if (loc2->owner->enable_state == bp_permanent)
- internal_error (__FILE__, __LINE__,
- _("another breakpoint was inserted on top of "
- "a permanent breakpoint"));
-
- memset (&loc2->target_info, 0, sizeof (loc2->target_info));
- loc2->target_info.placed_address = loc2->address;
- if (b->type == bp_hardware_breakpoint)
- val = target_insert_hw_breakpoint (&loc2->target_info);
- else
- val = target_insert_breakpoint (&loc2->target_info);
-
- /* If there was an error in the insert, print a message, then stop execution. */
- if (val != 0)
- {
- struct ui_file *tmp_error_stream = mem_fileopen ();
- make_cleanup_ui_file_delete (tmp_error_stream);
-
-
- if (b->type == bp_hardware_breakpoint)
- {
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert hardware breakpoint %d.\n"
- "You may have requested too many hardware breakpoints.\n",
- b->number);
- }
- else
- {
- fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number);
- fprintf_filtered (tmp_error_stream, "Error accessing memory address ");
- fputs_filtered (paddress (loc2->address),
- tmp_error_stream);
- fprintf_filtered (tmp_error_stream, ": %s.\n",
- safe_strerror (val));
- }
-
- fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process.");
- target_terminal_ours_for_output ();
- error_stream(tmp_error_stream);
- }
- else
- loc2->inserted = 1;
- }
- }
- }
-
free_command_lines (&bpt->commands);
if (bpt->cond_string != NULL)
xfree (bpt->cond_string);
@@ -6973,16 +7024,22 @@ delete_breakpoint (struct breakpoint *bpt)
bs->old_val = NULL;
/* bs->commands will be freed later. */
}
+
+ /* Now that breakpoint is removed from breakpoint
+ list, update the global location list. This
+ will remove locations that used to belong to
+ this breakpoint. Do this before freeing
+ the breakpoint itself, since remove_breakpoint
+ looks at location's owner. It might be better
+ design to have location completely self-contained,
+ but it's not the case now. */
+ update_global_location_list ();
+
+
/* On the chance that someone will soon try again to delete this same
bp, we mark it as deleted before freeing its storage. */
bpt->type = bp_none;
- for (loc = bpt->loc; loc;)
- {
- struct bp_location *loc_next = loc->next;
- xfree (loc);
- loc = loc_next;
- }
xfree (bpt);
}
@@ -7114,7 +7171,6 @@ update_breakpoint_locations (struct breakpoint *b,
if (all_locations_are_pending (existing_locations) && sals.nelts == 0)
return;
- unlink_locations_from_global_list (b);
b->loc = NULL;
for (i = 0; i < sals.nelts; ++i)
@@ -7193,12 +7249,7 @@ update_breakpoint_locations (struct breakpoint *b,
}
}
- while (existing_locations)
- {
- struct bp_location *next = existing_locations->next;
- free_bp_location (existing_locations);
- existing_locations = next;
- }
+ update_global_location_list ();
}
@@ -7294,10 +7345,6 @@ breakpoint_re_set_one (void *bint)
expanded = expand_line_sal_maybe (sals.sals[0]);
update_breakpoint_locations (b, expanded);
- /* Now that this is re-enabled, check_duplicates
- can be used. */
- check_duplicates (b);
-
xfree (sals.sals);
break;
@@ -7597,7 +7644,7 @@ disable_breakpoint (struct breakpoint *bpt)
bpt->enable_state = bp_disabled;
- check_duplicates (bpt);
+ update_global_location_list ();
if (deprecated_modify_breakpoint_hook)
deprecated_modify_breakpoint_hook (bpt);
@@ -7636,7 +7683,7 @@ disable_command (char *args, int from_tty)
struct bp_location *loc = find_location_by_number (args);
if (loc)
loc->enabled = 0;
- check_duplicates (loc->owner);
+ update_global_location_list ();
}
else
map_breakpoint_numbers (args, disable_breakpoint);
@@ -7721,7 +7768,7 @@ have been allocated for other watchpoints.\n"), bpt->number);
if (bpt->enable_state != bp_permanent)
bpt->enable_state = bp_enabled;
bpt->disposition = disposition;
- check_duplicates (bpt);
+ update_global_location_list ();
breakpoints_changed ();
if (deprecated_modify_breakpoint_hook)
@@ -7772,7 +7819,7 @@ enable_command (char *args, int from_tty)
struct bp_location *loc = find_location_by_number (args);
if (loc)
loc->enabled = 1;
- check_duplicates (loc->owner);
+ update_global_location_list ();
}
else
map_breakpoint_numbers (args, enable_breakpoint);
@@ -7940,6 +7987,11 @@ single_step_breakpoint_inserted_here_p (CORE_ADDR pc)
return 0;
}
+int breakpoints_always_inserted_mode ()
+{
+ return always_inserted_mode;
+}
+
/* This help string is used for the break, hbreak, tbreak and thbreak commands.
It is defined as a macro to prevent duplication.
@@ -8341,6 +8393,19 @@ a warning will be emitted for such breakpoints."),
show_automatic_hardware_breakpoints,
&breakpoint_set_cmdlist,
&breakpoint_show_cmdlist);
+
+ add_setshow_boolean_cmd ("always-inserted", class_support,
+ &always_inserted_mode, _("\
+Set mode for inserting breakpoints."), _("\
+Show mode for inserting breakpoints."), _("\
+When this mode is off (which is default), breakpoints are inserted in\n\
+inferior when it is resumed, and removed when execution stops. When this\n\
+mode is on, breakpoints are inserted immediately and removed only when\n\
+the user deletes the breakpoint."),
+ NULL,
+ &show_always_inserted_mode,
+ &breakpoint_set_cmdlist,
+ &breakpoint_show_cmdlist);
automatic_hardware_breakpoints = 1;
}
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 159c406..9e719f8 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -331,6 +331,9 @@ enum watchpoint_triggered
watch_triggered_yes
};
+typedef struct bp_location *bp_location_p;
+DEF_VEC_P(bp_location_p);
+
/* Note that the ->silent field is not currently used by any commands
(though the code is in there if it was to be, and set_raw_breakpoint
does set it to 0). I implemented it because I thought it would be
@@ -858,4 +861,6 @@ extern void breakpoint_restore_shadows (gdb_byte *buf,
ULONGEST memaddr,
LONGEST len);
+extern int breakpoints_always_inserted_mode ();
+
#endif /* !defined (BREAKPOINT_H) */
diff --git a/gdb/infrun.c b/gdb/infrun.c
index c863736..6791cb4 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -789,9 +789,17 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
oneproc = 1;
if (oneproc)
- /* We will get a trace trap after one instruction.
- Continue it automatically and insert breakpoints then. */
- stepping_over_breakpoint = 1;
+ {
+ /* We will get a trace trap after one instruction.
+ Continue it automatically and insert breakpoints then. */
+ stepping_over_breakpoint = 1;
+ /* FIXME: if breakpoints are always inserted, we'll trap
+ if trying to single-step over breakpoint. Disable
+ all breakpoints. In future, we'd need to invent some
+ smart way of stepping over breakpoint instruction without
+ hitting breakpoint. */
+ remove_breakpoints ();
+ }
else
insert_breakpoints ();
@@ -1350,10 +1358,6 @@ handle_inferior_event (struct execution_control_state *ecs)
established. */
if (stop_soon == NO_STOP_QUIETLY)
{
- /* Remove breakpoints, SOLIB_ADD might adjust
- breakpoint addresses via breakpoint_re_set. */
- remove_breakpoints ();
-
/* Check for any newly added shared libraries if we're
supposed to be adding them automatically. Switch
terminal for any messages produced by
@@ -1393,9 +1397,6 @@ handle_inferior_event (struct execution_control_state *ecs)
/* NOTE drow/2007-05-11: This might be a good place to check
for "catch load". */
-
- /* Reinsert breakpoints and continue. */
- insert_breakpoints ();
}
/* If we are skipping through a shell, or through shared library
@@ -2235,10 +2236,6 @@ process_event_stop_test:
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CHECK_SHLIBS\n");
- /* Remove breakpoints, we eventually want to step over the
- shlib event breakpoint, and SOLIB_ADD might adjust
- breakpoint addresses via breakpoint_re_set. */
- remove_breakpoints ();
/* Check for any newly added shared libraries if we're
supposed to be adding them automatically. Switch
@@ -3139,7 +3136,7 @@ normal_stop (void)
gdbarch_decr_pc_after_break needs to just go away. */
deprecated_update_frame_pc_hack (get_current_frame (), read_pc ());
- if (target_has_execution)
+ if (!breakpoints_always_inserted_mode () && target_has_execution)
{
if (remove_breakpoints ())
{
diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c
index 8c29827..a9f5fae 100644
--- a/gdb/linux-fork.c
+++ b/gdb/linux-fork.c
@@ -536,6 +536,10 @@ checkpoint_command (char *args, int from_tty)
/* Make this temp var static, 'cause it's used in the error context. */
static int temp_detach_fork;
+ /* Remove breakpoints, so that they are not inserted
+ in the forked process. */
+ remove_breakpoints ();
+
/* Make the inferior fork, record its (and gdb's) state. */
if (lookup_minimal_symbol ("fork", NULL, NULL) != NULL)
@@ -576,6 +580,7 @@ checkpoint_command (char *args, int from_tty)
if (!fp)
error (_("Failed to find new fork"));
fork_save_infrun_state (fp, 1);
+ insert_breakpoints ();
}
static void
@@ -593,7 +598,9 @@ linux_fork_context (struct fork_info *newfp, int from_tty)
oldfp = add_fork (ptid_get_pid (inferior_ptid));
fork_save_infrun_state (oldfp, 1);
+ remove_breakpoints ();
fork_load_infrun_state (newfp);
+ insert_breakpoints ();
printf_filtered (_("Switching to %s\n"),
target_pid_to_str (inferior_ptid));
diff --git a/gdb/target.c b/gdb/target.c
index 32271eb..0dae58c 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -39,6 +39,7 @@
#include "gdbcore.h"
#include "exceptions.h"
#include "target-descriptions.h"
+#include "gdb_stdint.h"
static void target_info (char *, int);
@@ -1120,7 +1121,7 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
static void
restore_show_memory_breakpoints (void *arg)
{
- show_memory_breakpoints = (int)arg;
+ show_memory_breakpoints = (uintptr_t) arg;
}
struct cleanup *
@@ -1129,7 +1130,8 @@ make_show_memory_breakpoints_cleanup (int show)
int current = show_memory_breakpoints;
show_memory_breakpoints = show;
- return make_cleanup (restore_show_memory_breakpoints, (void *)current);
+ return make_cleanup (restore_show_memory_breakpoints,
+ (void *) (uintptr_t) current);
}
static LONGEST
@@ -1682,6 +1684,10 @@ target_preopen (int from_tty)
void
target_detach (char *args, int from_tty)
{
+ /* If we're in breakpoints-always-inserted mode, have to
+ remove them before detaching. */
+ remove_breakpoints ();
+
(current_target.to_detach) (args, from_tty);
}
@@ -1690,6 +1696,10 @@ target_disconnect (char *args, int from_tty)
{
struct target_ops *t;
+ /* If we're in breakpoints-always-inserted mode, have to
+ remove them before disconnecting. */
+ remove_breakpoints ();
+
for (t = current_target.beneath; t != NULL; t = t->beneath)
if (t->to_disconnect != NULL)
{
--
1.5.3.5