Limit breakpoint re-set to the current program space

Currently, we always re-set all locations of all breakpoints.  This
commit makes us re-set only locations of the current program space.

If we loaded symbols to a program space (e.g., "file" command or some
shared library was loaded), GDB must run through all breakpoints and
determine if any new locations need to be added to the breakpoint.
However, there's no reason to recreate locations for _other_ program
spaces, as those haven't changed.

Similarly, when we create a new inferior, through e.g., a fork, GDB
must run through all breakpoints and determine if any new locations
need to be added to the breakpoint.  There's no reason to destroy the
locations of the parent inferior and other inferiors.  We know those
won't change.

In addition to being inneficient, resetting breakpoints of inferiors
that are currently running is problematic, because:

 - some targets can't read memory while the inferior is running.

 - the inferior might exit while we're re-setting its breakpoints,
   which may confuse prologue skipping.

I went through all the places where we call breakpoint_re_set, and it
seems to me that all can be changed to only re-set locations of the
current program space.

The patch that reversed threads order in "info threads" etc. happened
to make gdb.threads/fork-plus-thread.exp expose this problem when
testing on x86/-m32.  The problem was latent and masked out by chance
by the code-cache:

 https://sourceware.org/ml/gdb-patches/2016-01/msg00213.html

Tested on x86-64 F20, native (-m64/-m32) and extended-remote
gdbserver.

Fixes the regression discussed in the url above with --target_board=unix/-m32:

 -FAIL: gdb.threads/fork-plus-threads.exp: detach-on-fork=off: inferior 1 exited
 +PASS: gdb.threads/fork-plus-threads.exp: detach-on-fork=off: inferior 1 exited
 -FAIL: gdb.threads/fork-plus-threads.exp: detach-on-fork=off: no threads left (timeout)
 -FAIL: gdb.threads/fork-plus-threads.exp: detach-on-fork=off: only inferior 1 left (the program exited)
 +PASS: gdb.threads/fork-plus-threads.exp: detach-on-fork=off: no threads left
 +PASS: gdb.threads/fork-plus-threads.exp: detach-on-fork=off: only inferior 1 left

gdb/ChangeLog:
2016-01-19  Pedro Alves  <palves@redhat.com>

	* ax-gdb.c (agent_command_1): Adjust call to decode_line_full.
	* break-catch-throw.c (re_set_exception_catchpoint): Pass the
	current program space down to linespec decoding and breakpoint
	location updating.
	* breakpoint.c (parse_breakpoint_sals): Adjust calls to
	decode_line_full.
	(until_break_command): Adjust calls to decode_line_1.
	(base_breakpoint_decode_location, bkpt_decode_location): Add
	'search_pspace' parameter.  Pass it along.
	(bkpt_probe_create_sals_from_location): Adjust calls to
	parse_probes.
	(tracepoint_decode_location, tracepoint_probe_decode_location)
	(strace_marker_decode_location): Add 'search_pspace' parameter.
	Pass it along.
	(all_locations_are_pending): Rewrite to take a breakpoint and
	program space as arguments instead.
	(hoist_existing_locations): New function.
	(update_breakpoint_locations): Add 'filter_pspace' parameter.  Use
	hoist_existing_locations instead of always removing all locations,
	and adjust to all_locations_are_pending change.
	(location_to_sals): Add 'search_pspace' parameter.  Pass it along.
	Don't disable the breakpoint if there are other locations in
	another program space.
	(breakpoint_re_set_default): Adjust to pass down the current
	program space as filter program space.
	(decode_location_default): Add 'search_pspace' parameter and pass
	it along.
	(prepare_re_set_context): Don't switch program space here.
	(breakpoint_re_set): Use save_current_space_and_thread instead of
	save_current_program_space.
	* breakpoint.h (struct breakpoint_ops) <decode_location>: Add
	'search_pspace' parameter.
	(update_breakpoint_locations): Add 'filter_pspace' parameter.
	* cli/cli-cmds.c (edit_command, list_command): Adjust calls to
	decode_line_1.
	* elfread.c (elf_gnu_ifunc_resolver_return_stop): Pass the current
	program space as filter program space.
	* linespec.c (struct linespec_state) <search_pspace>: New field.
	(create_sals_line_offset, convert_explicit_location_to_sals)
	(parse_linespec): Pass the search program space down.
	(linespec_state_constructor): Add 'search_pspace' parameter.
	Store it.
	(linespec_parser_new): Add 'search_pspace' parameter and pass it
	along.
	(linespec_lex_to_end): Adjust.
	(decode_line_full, decode_line_1): Add 'search_pspace' parameter
	and pass it along.
	(decode_line_with_last_displayed): Adjust.
	(collect_symtabs_from_filename, symtabs_from_filename): New
	'search_pspace' parameter.  Use it.
	(find_function_symbols): Pass the search program space down.
	* linespec.h (decode_line_1, decode_line_full): Add
	'search_pspace' parameter.
	* probe.c (parse_probes_in_pspace): New function, factored out
	from ...
	(parse_probes): ... this.  Add 'search_pspace' parameter and use
	it.
	* probe.h (parse_probes): Add pspace' parameter.
	* python/python.c (gdbpy_decode_line): Adjust.
	* tracepoint.c (scope_info): Adjust.
This commit is contained in:
Pedro Alves
2016-01-19 12:18:14 +00:00
parent bd0a71fa16
commit c2f4122d5c
13 changed files with 310 additions and 121 deletions

View File

@@ -126,6 +126,7 @@ static void create_breakpoints_sal_default (struct gdbarch *,
static void decode_location_default (struct breakpoint *b,
const struct event_location *location,
struct program_space *search_pspace,
struct symtabs_and_lines *sals);
static void clear_command (char *, int);
@@ -9545,7 +9546,7 @@ parse_breakpoint_sals (const struct event_location *location,
&& strchr ("+-", address[0]) != NULL
&& address[1] != '['))
{
decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL,
get_last_displayed_symtab (),
get_last_displayed_line (),
canonical, NULL, NULL);
@@ -9553,7 +9554,7 @@ parse_breakpoint_sals (const struct event_location *location,
}
}
decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL,
cursal.symtab, cursal.line, canonical, NULL, NULL);
}
@@ -10447,7 +10448,7 @@ break_range_command (char *arg, int from_tty)
where +14 means 14 lines from the start location. */
end_location = string_to_event_location (&arg, current_language);
make_cleanup_delete_event_location (end_location);
decode_line_full (end_location, DECODE_LINE_FUNFIRSTLINE,
decode_line_full (end_location, DECODE_LINE_FUNFIRSTLINE, NULL,
sal_start.symtab, sal_start.line,
&canonical_end, NULL, NULL);
@@ -11712,12 +11713,12 @@ until_break_command (char *arg, int from_tty, int anywhere)
cleanup = make_cleanup_delete_event_location (location);
if (last_displayed_sal_is_valid ())
sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE,
sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE, NULL,
get_last_displayed_symtab (),
get_last_displayed_line ());
else
sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE,
(struct symtab *) NULL, 0);
NULL, (struct symtab *) NULL, 0);
if (sals.nelts != 1)
error (_("Couldn't get information on specified line."));
@@ -13018,6 +13019,7 @@ base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch,
static void
base_breakpoint_decode_location (struct breakpoint *b,
const struct event_location *location,
struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
internal_error_pure_virtual_called ();
@@ -13267,9 +13269,10 @@ bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
static void
bkpt_decode_location (struct breakpoint *b,
const struct event_location *location,
struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
decode_location_default (b, location, sals);
decode_location_default (b, location, search_pspace, sals);
}
/* Virtual table for internal breakpoints. */
@@ -13453,7 +13456,7 @@ bkpt_probe_create_sals_from_location (const struct event_location *location,
{
struct linespec_sals lsal;
lsal.sals = parse_probes (location, canonical);
lsal.sals = parse_probes (location, NULL, canonical);
lsal.canonical = xstrdup (event_location_to_string (canonical->location));
VEC_safe_push (linespec_sals, canonical->sals, &lsal);
}
@@ -13461,9 +13464,10 @@ bkpt_probe_create_sals_from_location (const struct event_location *location,
static void
bkpt_probe_decode_location (struct breakpoint *b,
const struct event_location *location,
struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
*sals = parse_probes (location, NULL);
*sals = parse_probes (location, search_pspace, NULL);
if (!sals->sals)
error (_("probe not found"));
}
@@ -13585,9 +13589,10 @@ tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
static void
tracepoint_decode_location (struct breakpoint *b,
const struct event_location *location,
struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
decode_location_default (b, location, sals);
decode_location_default (b, location, search_pspace, sals);
}
struct breakpoint_ops tracepoint_breakpoint_ops;
@@ -13608,10 +13613,11 @@ tracepoint_probe_create_sals_from_location
static void
tracepoint_probe_decode_location (struct breakpoint *b,
const struct event_location *location,
struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
/* We use the same method for breakpoint on probes. */
bkpt_probe_decode_location (b, location, sals);
bkpt_probe_decode_location (b, location, search_pspace, sals);
}
static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
@@ -13776,6 +13782,7 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
static void
strace_marker_decode_location (struct breakpoint *b,
const struct event_location *location,
struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
struct tracepoint *tp = (struct tracepoint *) b;
@@ -13993,11 +14000,19 @@ delete_command (char *arg, int from_tty)
map_breakpoint_numbers (arg, do_map_delete_breakpoint, NULL);
}
/* Return true if all locations of B bound to PSPACE are pending. If
PSPACE is NULL, all locations of all program spaces are
considered. */
static int
all_locations_are_pending (struct bp_location *loc)
all_locations_are_pending (struct breakpoint *b, struct program_space *pspace)
{
for (; loc; loc = loc->next)
if (!loc->shlib_disabled
struct bp_location *loc;
for (loc = b->loc; loc != NULL; loc = loc->next)
if ((pspace == NULL
|| loc->pspace == pspace)
&& !loc->shlib_disabled
&& !loc->pspace->executing_startup)
return 0;
return 1;
@@ -14202,17 +14217,58 @@ locations_are_equal (struct bp_location *a, struct bp_location *b)
return 1;
}
/* Create new breakpoint locations for B (a hardware or software breakpoint)
based on SALS and SALS_END. If SALS_END.NELTS is not zero, then B is
a ranged breakpoint. */
/* Split all locations of B that are bound to PSPACE out of B's
location list to a separate list and return that list's head. If
PSPACE is NULL, hoist out all locations of B. */
static struct bp_location *
hoist_existing_locations (struct breakpoint *b, struct program_space *pspace)
{
struct bp_location head;
struct bp_location *i = b->loc;
struct bp_location **i_link = &b->loc;
struct bp_location *hoisted = &head;
if (pspace == NULL)
{
i = b->loc;
b->loc = NULL;
return i;
}
head.next = NULL;
while (i != NULL)
{
if (i->pspace == pspace)
{
*i_link = i->next;
i->next = NULL;
hoisted->next = i;
hoisted = i;
}
else
i_link = &i->next;
i = *i_link;
}
return head.next;
}
/* Create new breakpoint locations for B (a hardware or software
breakpoint) based on SALS and SALS_END. If SALS_END.NELTS is not
zero, then B is a ranged breakpoint. Only recreates locations for
FILTER_PSPACE. Locations of other program spaces are left
untouched. */
void
update_breakpoint_locations (struct breakpoint *b,
struct program_space *filter_pspace,
struct symtabs_and_lines sals,
struct symtabs_and_lines sals_end)
{
int i;
struct bp_location *existing_locations = b->loc;
struct bp_location *existing_locations;
if (sals_end.nelts != 0 && (sals.nelts != 1 || sals_end.nelts != 1))
{
@@ -14232,10 +14288,10 @@ update_breakpoint_locations (struct breakpoint *b,
We'd like to retain the location, so that when the library is
loaded again, we don't loose the enabled/disabled status of the
individual locations. */
if (all_locations_are_pending (existing_locations) && sals.nelts == 0)
if (all_locations_are_pending (b, filter_pspace) && sals.nelts == 0)
return;
b->loc = NULL;
existing_locations = hoist_existing_locations (b, filter_pspace);
for (i = 0; i < sals.nelts; ++i)
{
@@ -14326,7 +14382,7 @@ update_breakpoint_locations (struct breakpoint *b,
static struct symtabs_and_lines
location_to_sals (struct breakpoint *b, struct event_location *location,
int *found)
struct program_space *search_pspace, int *found)
{
struct symtabs_and_lines sals = {0};
struct gdb_exception exception = exception_none;
@@ -14335,7 +14391,7 @@ location_to_sals (struct breakpoint *b, struct event_location *location,
TRY
{
b->ops->decode_location (b, location, &sals);
b->ops->decode_location (b, location, search_pspace, &sals);
}
CATCH (e, RETURN_MASK_ERROR)
{
@@ -14351,7 +14407,10 @@ location_to_sals (struct breakpoint *b, struct event_location *location,
breakpoint being disabled, and don't want to see more
errors. */
if (e.error == NOT_FOUND_ERROR
&& (b->condition_not_parsed
&& (b->condition_not_parsed
|| (b->loc != NULL
&& search_pspace != NULL
&& b->loc->pspace != search_pspace)
|| (b->loc && b->loc->shlib_disabled)
|| (b->loc && b->loc->pspace->executing_startup)
|| b->enable_state == bp_disabled))
@@ -14420,8 +14479,9 @@ breakpoint_re_set_default (struct breakpoint *b)
struct symtabs_and_lines sals, sals_end;
struct symtabs_and_lines expanded = {0};
struct symtabs_and_lines expanded_end = {0};
struct program_space *filter_pspace = current_program_space;
sals = location_to_sals (b, b->location, &found);
sals = location_to_sals (b, b->location, filter_pspace, &found);
if (found)
{
make_cleanup (xfree, sals.sals);
@@ -14430,7 +14490,8 @@ breakpoint_re_set_default (struct breakpoint *b)
if (b->location_range_end != NULL)
{
sals_end = location_to_sals (b, b->location_range_end, &found);
sals_end = location_to_sals (b, b->location_range_end,
filter_pspace, &found);
if (found)
{
make_cleanup (xfree, sals_end.sals);
@@ -14438,7 +14499,7 @@ breakpoint_re_set_default (struct breakpoint *b)
}
}
update_breakpoint_locations (b, expanded, expanded_end);
update_breakpoint_locations (b, filter_pspace, expanded, expanded_end);
}
/* Default method for creating SALs from an address string. It basically
@@ -14482,12 +14543,13 @@ create_breakpoints_sal_default (struct gdbarch *gdbarch,
static void
decode_location_default (struct breakpoint *b,
const struct event_location *location,
struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
struct linespec_result canonical;
init_linespec_result (&canonical);
decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, search_pspace,
(struct symtab *) NULL, 0,
&canonical, multiple_symbols_all,
b->filter);
@@ -14514,15 +14576,10 @@ decode_location_default (struct breakpoint *b,
static struct cleanup *
prepare_re_set_context (struct breakpoint *b)
{
struct cleanup *cleanups;
input_radix = b->input_radix;
cleanups = save_current_space_and_thread ();
if (b->pspace != NULL)
switch_to_program_space_and_thread (b->pspace);
set_language (b->language);
return cleanups;
return make_cleanup (null_cleanup, NULL);
}
/* Reset a breakpoint given it's struct breakpoint * BINT.
@@ -14542,7 +14599,9 @@ breakpoint_re_set_one (void *bint)
return 0;
}
/* Re-set all breakpoints after symbols have been re-loaded. */
/* Re-set breakpoint locations for the current program space.
Locations bound to other program spaces are left untouched. */
void
breakpoint_re_set (void)
{
@@ -14553,7 +14612,7 @@ breakpoint_re_set (void)
save_language = current_language->la_language;
save_input_radix = input_radix;
old_chain = save_current_program_space ();
old_chain = save_current_space_and_thread ();
ALL_BREAKPOINTS_SAFE (b, b_tmp)
{