* 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.
This commit is contained in:
Vladimir Prus 2008-04-24 10:21:45 +00:00
parent d24317b480
commit 74960c6002
13 changed files with 475 additions and 212 deletions

View file

@ -1,3 +1,58 @@
2008-04-24 Vladimir Prus <vladimir@codesourcery.com>
* 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.
2008-04-24 Vladimir Prus <vladimir@codesourcery.com>
* breakpoint.c (print_one_breakpoint_location): In MI

View file

@ -1974,7 +1974,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)

View file

@ -43,6 +43,12 @@ show multiple-symbols
when an expression or a breakpoint location contains an ambiguous symbol
name (an overloaded function name, for instance).
set breakpoint always-inserted
show breakpoint always-inserted
Keep breakpoints always inserted in the target, as opposed to inserting
them when resuming the target, and removing them when the target stops.
This option can improve debugger performance on slow remote targets.
*** Changes in GDB 6.8
* New native configurations

View file

@ -60,6 +60,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);
@ -205,11 +207,13 @@ 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);
static const char *
bpdisp_text (enum bpdisp disp)
@ -265,6 +269,18 @@ 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 breakpoints. If 0, gdb will insert
breakpoints into inferior only when resuming 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);
@ -875,14 +891,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)
@ -1020,6 +1032,23 @@ in which its expression is valid.\n"),
}
/* Returns 1 iff breakpoint location should be
inserted in the inferior. */
static int
should_be_inserted (struct bp_location *bpt)
{
if (!breakpoint_enabled (bpt->owner))
return 0;
if (bpt->owner->disposition == disp_del_at_next_stop)
return 0;
if (!bpt->enabled || bpt->shlib_disabled || 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.
@ -1034,10 +1063,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_be_inserted (bpt) || bpt->inserted)
return 0;
/* Initialize the target-specific information. */
@ -1238,13 +1264,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;
@ -1256,18 +1304,14 @@ 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)
{
if (!breakpoint_enabled (b->owner))
if (!should_be_inserted (b) || b->inserted)
continue;
/* There is no point inserting thread-specific breakpoints if the
@ -1295,6 +1339,9 @@ insert_breakpoints (void)
if (bpt->enable_state != bp_enabled)
continue;
if (bpt->disposition == disp_del_at_next_stop)
continue;
for (loc = bpt->loc; loc; loc = loc->next)
if (!loc->inserted)
@ -1402,17 +1449,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(). */
@ -1494,6 +1555,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
@ -1533,9 +1595,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)
@ -2968,7 +3030,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;
@ -4203,18 +4268,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;
}
@ -4222,6 +4275,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);
}
@ -4326,7 +4383,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;
@ -4390,6 +4446,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
@ -4405,7 +4462,7 @@ enable_longjmp_breakpoint (void)
if (b->type == bp_longjmp)
{
b->enable_state = bp_enabled;
check_duplicates (b);
update_global_location_list ();
}
}
@ -4419,7 +4476,7 @@ disable_longjmp_breakpoint (void)
|| b->type == bp_longjmp_resume)
{
b->enable_state = bp_disabled;
check_duplicates (b);
update_global_location_list ();
}
}
@ -4446,6 +4503,7 @@ create_overlay_event_breakpoint (char *func_name)
b->enable_state = bp_disabled;
overlay_events_enabled = 0;
}
update_global_location_list ();
}
void
@ -4457,7 +4515,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;
}
}
@ -4471,7 +4529,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;
}
}
@ -4487,6 +4545,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;
}
@ -4531,6 +4591,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;
}
@ -4628,6 +4689,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);
}
@ -4665,6 +4728,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);
}
@ -4725,7 +4789,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;
}
}
@ -4744,7 +4808,7 @@ disable_watchpoints_before_interactive_call_start (void)
&& breakpoint_enabled (b))
{
b->enable_state = bp_call_disabled;
check_duplicates (b);
update_global_location_list ();
}
}
}
@ -4763,7 +4827,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 ();
}
}
}
@ -4789,6 +4853,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;
}
@ -5192,6 +5258,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
@ -5509,6 +5577,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);
}
@ -5935,6 +6005,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
@ -6493,6 +6564,7 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
xfree (sals.sals);
mention (b);
update_global_location_list ();
return 1;
}
@ -6565,6 +6637,7 @@ create_ada_exception_breakpoint (struct symtab_and_line sal,
b->ops = ops;
mention (b);
update_global_location_list ();
}
/* Implement the "catch exception" command. */
@ -6886,33 +6959,124 @@ 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;
for (; *tmp && here;)
bp_location_chain = NULL;
ALL_BREAKPOINTS (b)
{
if (*tmp == here)
for (loc = b->loc; loc; loc = loc->next)
{
*tmp = here->global_next;
here = here->next;
}
else
{
tmp = &((*tmp)->global_next);
*next = loc;
next = &(loc->global_next);
*next = NULL;
}
}
/* Identify bp_location instances that are no 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)
{
/* Tells if 'loc' is found amoung the new locations. If not, we
have to free it. */
int found_object = 0;
for (loc2 = bp_location_chain; loc2; loc2 = loc2->global_next)
if (loc2 == loc)
{
found_object = 1;
break;
}
/* If this location is no longer present, and inserted, look if there's
maybe a 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 time window where a breakpoint at certain location is not
inserted. */
if (loc->inserted)
{
/* If the location is inserted now, we might have to remove it. */
int keep = 0;
if (found_object && should_be_inserted (loc))
{
/* The location is still present in the location list, and still
should be inserted. Don't do anything. */
keep = 1;
}
else
{
/* The location is either no longer present, or got disabled.
See if there's another location at the same address, in which
case we don't need to remove this one from the target. */
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 to check_duplicates will fix up this later. */
loc2->duplicate = 0;
if (should_be_inserted (loc2)
&& loc2 != loc && loc2->address == loc->address)
{
loc2->inserted = 1;
loc2->target_info = loc->target_info;
keep = 1;
break;
}
}
}
if (!keep)
if (remove_breakpoint (loc, mark_uninserted))
{
/* This is just about all we can do. We could keep this
location on the global list, and try to remove it next
time, but there's no particular reason why we will
succeed next time.
Note that at this point, loc->owner is still valid,
as delete_breakpoint frees the breakpoint only
after calling us. */
printf_filtered (_("warning: Error removing breakpoint %d\n"),
loc->owner->number);
}
}
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
@ -6923,7 +7087,7 @@ delete_breakpoint (struct breakpoint *bpt)
{
struct breakpoint *b;
bpstat bs;
struct bp_location *loc;
struct bp_location *loc, *next;
gdb_assert (bpt != NULL);
@ -6947,18 +7111,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;
@ -6969,85 +7121,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);
@ -7084,16 +7157,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);
}
@ -7225,7 +7304,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)
@ -7304,12 +7382,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 ();
}
@ -7405,10 +7478,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;
@ -7708,7 +7777,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);
@ -7747,7 +7816,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);
@ -7832,7 +7901,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)
@ -7883,7 +7952,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);
@ -8051,6 +8120,11 @@ single_step_breakpoint_inserted_here_p (CORE_ADDR pc)
return 0;
}
int breakpoints_always_inserted_mode (void)
{
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.
@ -8452,6 +8526,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 the 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;
}

View file

@ -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
@ -864,4 +867,6 @@ int watchpoints_triggered (struct target_waitstatus *);
void breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr,
LONGEST len);
extern int breakpoints_always_inserted_mode (void);
#endif /* !defined (BREAKPOINT_H) */

View file

@ -3209,6 +3209,30 @@ type. If the target provides a memory map, @value{GDBN} will warn when
trying to set software breakpoint at a read-only address.
@end table
@value{GDBN} normally implements breakpoints by replacing the program code
at the breakpoint address with a special instruction, which, when
executed, given control to the debugger. By default, the program
code is so modified only when the program is resumed. As soon as
the program stops, @value{GDBN} restores the original instructions. This
behaviour guards against leaving breakpoints inserted in the
target should gdb abrubptly disconnect. However, with slow remote
targets, inserting and removing breakpoint can reduce the performance.
This behavior can be controlled with the following commands::
@kindex set breakpoint always-inserted
@kindex show breakpoint always-inserted
@table @code
@item set breakpoint always-inserted off
This is the default behaviour. All breakpoints, including newly added
by the user, are inserted in the target only when the target is
resumed. All breakpoints are removed from the target when it stops.
@item set breakpoint always-inserted on
Causes all breakpoints to be inserted in the target at all times. If
the user adds a new breakpoint, or changes an existing breakpoint, the
breakpoints in the target are updated immediately. A breakpoint is
removed from the target only when breakpoint itself is removed.
@end table
@cindex negative breakpoint numbers
@cindex internal @value{GDBN} breakpoints

View file

@ -614,19 +614,18 @@ a command like `return' or `jump' to continue execution."));
}
if ((step || singlestep_breakpoints_inserted_p)
&& breakpoint_here_p (read_pc ())
&& !breakpoint_inserted_here_p (read_pc ()))
&& stepping_over_breakpoint)
{
/* We're stepping, have breakpoint at PC, and it's
not inserted. Most likely, proceed has noticed that
we have breakpoint and tries to single-step over it,
so that it's not hit. In which case, we need to
single-step only this thread, and keep others stopped,
as they can miss this breakpoint if allowed to run.
/* We're allowing a thread to run past a breakpoint it has
hit, by single-stepping the thread with the breakpoint
removed. In which case, we need to single-step only this
thread, and keep others stopped, as they can miss this
breakpoint if allowed to run.
The current code either has all breakpoints inserted,
or all removed, so if we let other threads run,
we can actually miss any breakpoint, not the one at PC. */
The current code actually removes all breakpoints when
doing this, not just the one being stepped over, so if we
let other threads run, we can actually miss any
breakpoint, not just the one at PC. */
resume_ptid = inferior_ptid;
}
@ -787,9 +786,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 ();
@ -1348,10 +1355,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
@ -1391,9 +1394,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
@ -1402,6 +1402,10 @@ handle_inferior_event (struct execution_control_state *ecs)
we're attaching or setting up a remote connection. */
if (stop_soon == STOP_QUIETLY || stop_soon == NO_STOP_QUIETLY)
{
/* Loading of shared libraries might have changed breakpoint
addresses. Make sure new breakpoints are inserted. */
if (!breakpoints_always_inserted_mode ())
insert_breakpoints ();
resume (0, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
@ -2039,8 +2043,7 @@ process_event_stop_test:
stop_signal = TARGET_SIGNAL_0;
if (prev_pc == read_pc ()
&& breakpoint_here_p (read_pc ())
&& !breakpoint_inserted_here_p (read_pc ())
&& stepping_over_breakpoint
&& step_resume_breakpoint == NULL)
{
/* We were just starting a new sequence, attempting to
@ -2216,10 +2219,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
@ -3120,7 +3119,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 ())
{

View file

@ -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));

View file

@ -1676,6 +1676,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);
}
@ -1684,6 +1688,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)
{

View file

@ -1,3 +1,10 @@
2008-04-24 Vladimir Prus <vladimir@codesourcery.com>
* lib/gdb.exp (gdb_continue_to_breakpoint): Allow the caller
to specify regexp for the location to stop at.
* gdb.base/break-always.c: New.
* gdb.base/break-always.exp: New.
2008-04-24 Vladimir Prus <vladimir@codesourcery.com>
* lib/mi-support.exp (mi_runto_helper): Adjust

View file

@ -0,0 +1,32 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2008 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
int bar ()
{
return 1; /* break in bar */
}
int foo ()
{
return bar ();
}
int main ()
{
foo ();
return 0;
}

View file

@ -0,0 +1,32 @@
# Copyright 2008 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Test that 'set breakpoint always-inserted 1' is not a brick
if { [prepare_for_testing break-always.exp break-always break-always.c] } {
return -1
}
set bar_location [gdb_get_line_number "break in bar" break-always.c]
gdb_test "set breakpoint always-inserted 1" ""
runto foo
gdb_test "break bar" "Breakpoint 2.*" "set breakpoint on bar"
gdb_continue_to_breakpoint "bar" ".*/break-always.c:$bar_location.*"

View file

@ -432,13 +432,13 @@ proc runto_main { } {
### worked. Use NAME as part of the test name; each call to
### continue_to_breakpoint should use a NAME which is unique within
### that test file.
proc gdb_continue_to_breakpoint {name} {
proc gdb_continue_to_breakpoint {name {location_pattern .*}} {
global gdb_prompt
set full_name "continue to breakpoint: $name"
send_gdb "continue\n"
gdb_expect {
-re "Breakpoint .* at .*\r\n$gdb_prompt $" {
-re "Breakpoint .* at $location_pattern\r\n$gdb_prompt $" {
pass $full_name
}
-re ".*$gdb_prompt $" {