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);
return 0;
/* Don't insert a breakpoint if we're trying to step past its
- location. */
+ location, except if the breakpoint is a single-step breakpoint,
+ and the breakpoint's thread is the thread which is stepping past
+ a breakpoint. */
if ((bl->loc_type == bp_loc_software_breakpoint
|| bl->loc_type == bp_loc_hardware_breakpoint)
&& stepping_past_instruction_at (bl->pspace->aspace,
- bl->address))
+ bl->address)
+ /* The single-step breakpoint may be inserted at the location
+ we're trying to step if the instruction branches to itself.
+ However, the instruction won't be executed at all and it may
+ break the semantics of the instruction, for example, the
+ instruction is a conditional branch or updates some flags.
+ We can't fix it unless GDB is able to emulate the instruction
+ or switch to displaced stepping. */
+ && !(bl->owner->type == bp_single_step
+ && thread_is_stepping_over_breakpoint (bl->owner->thread)))
{
if (debug_infrun)
{
need to parse the condition to bytecodes again. */
aexpr = parse_cond_to_aexpr (bl->address, loc->cond);
loc->cond_bytecode = aexpr;
-
- /* Check if we managed to parse the conditional expression
- correctly. If not, we will not send this condition
- to the target. */
- if (aexpr)
- continue;
}
/* If we have a NULL bytecode expression, it means something
aexpr = parse_cmd_to_aexpr (bl->address,
loc->owner->extra_string);
loc->cmd_bytecode = aexpr;
-
- if (!aexpr)
- continue;
}
/* If we have a NULL bytecode expression, it means something
overlay_events_enabled = 0;
}
}
- update_global_location_list (UGLL_MAY_INSERT);
}
static void
}
}
}
- update_global_location_list (UGLL_MAY_INSERT);
do_cleanups (old_chain);
}
}
}
- update_global_location_list (UGLL_MAY_INSERT);
-
do_cleanups (old_chain);
}
b->location = new_explicit_location (&explicit_loc);
b->enable_state = bp_disabled;
}
+}
- update_global_location_list (UGLL_MAY_INSERT);
+/* Does B have a location spec? */
+
+static int
+breakpoint_event_location_empty_p (const struct breakpoint *b)
+{
+ return b->location != NULL && event_location_empty_p (b->location);
}
void
/* Without a symbolic address, we have little hope of the
pre-exec() address meaning the same thing in the post-exec()
a.out. */
- if (event_location_empty_p (b->location))
+ if (breakpoint_event_location_empty_p (b))
{
delete_breakpoint (b);
continue;
}
}
+/* Print the "Thread ID hit" part of "Thread ID hit Breakpoint N" if
+ debugging multiple threads. */
+
+void
+maybe_print_thread_hit_breakpoint (struct ui_out *uiout)
+{
+ if (ui_out_is_mi_like_p (uiout))
+ return;
+
+ ui_out_text (uiout, "\n");
+
+ if (show_thread_that_caused_stop ())
+ {
+ const char *name;
+ struct thread_info *thr = inferior_thread ();
+
+ ui_out_text (uiout, "Thread ");
+ ui_out_field_fmt (uiout, "thread-id", "%s", print_thread_id (thr));
+
+ name = thr->name != NULL ? thr->name : target_thread_name (thr);
+ if (name != NULL)
+ {
+ ui_out_text (uiout, " \"");
+ ui_out_field_fmt (uiout, "name", "%s", name);
+ ui_out_text (uiout, "\"");
+ }
+
+ ui_out_text (uiout, " hit ");
+ }
+}
+
/* Generic routine for printing messages indicating why we
stopped. The behavior of this function depends on the value
'print_it' in the bpstat structure. Under some circumstances we
b->enable_state = bp_enabled;
/* location has to be used or breakpoint_re_set will delete me. */
- b->location = new_address_location (b->loc->address);
+ b->location = new_address_location (b->loc->address, NULL, 0);
update_global_location_list_nothrow (UGLL_MAY_INSERT);
struct breakpoint *
create_jit_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
{
- struct breakpoint *b;
-
- b = create_internal_breakpoint (gdbarch, address, bp_jit_event,
- &internal_breakpoint_ops);
- update_global_location_list_nothrow (UGLL_MAY_INSERT);
- return b;
+ return create_internal_breakpoint (gdbarch, address, bp_jit_event,
+ &internal_breakpoint_ops);
}
/* Remove JIT code registration and unregistration breakpoint(s). */
struct fork_catchpoint *c = (struct fork_catchpoint *) bs->breakpoint_at;
annotate_catchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary catchpoint ");
+ ui_out_text (uiout, "Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
+ ui_out_text (uiout, "Catchpoint ");
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
struct fork_catchpoint *c = (struct fork_catchpoint *) b;
annotate_catchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary catchpoint ");
+ ui_out_text (uiout, "Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
+ ui_out_text (uiout, "Catchpoint ");
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
struct ui_out *uiout = current_uiout;
annotate_catchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary catchpoint ");
+ ui_out_text (uiout, "Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
+ ui_out_text (uiout, "Catchpoint ");
ui_out_field_int (uiout, "bkptno", b->number);
ui_out_text (uiout, "\n");
if (ui_out_is_mi_like_p (uiout))
struct exec_catchpoint *c = (struct exec_catchpoint *) b;
annotate_catchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary catchpoint ");
+ ui_out_text (uiout, "Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
+ ui_out_text (uiout, "Catchpoint ");
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
/* Create a breakpoint with SAL as location. Use LOCATION
as a description of the location, and COND_STRING
- as condition expression. */
+ as condition expression. If LOCATION is NULL then create an
+ "address location" from the address in the SAL. */
static void
init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
if (location != NULL)
b->location = location;
else
- b->location = new_address_location (b->loc->address);
+ {
+ const char *addr_string = NULL;
+ int addr_string_len = 0;
+
+ if (location != NULL)
+ addr_string = event_location_to_string (location);
+ if (addr_string != NULL)
+ addr_string_len = strlen (addr_string);
+
+ b->location = new_address_location (b->loc->address,
+ addr_string, addr_string_len);
+ }
b->filter = filter;
}
&& 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);
}
}
- decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
+ decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL,
cursal.symtab, cursal.line, canonical, NULL, NULL);
}
gdb_assert (bl && bl->next == NULL);
annotate_breakpoint (b->number);
+
+ maybe_print_thread_hit_breakpoint (uiout);
+
if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary ranged breakpoint ");
+ ui_out_text (uiout, "Temporary ranged breakpoint ");
else
- ui_out_text (uiout, "\nRanged breakpoint ");
+ ui_out_text (uiout, "Ranged breakpoint ");
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
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);
stb = mem_fileopen ();
old_chain = make_cleanup_ui_file_delete (stb);
+ annotate_watchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
+
switch (b->type)
{
case bp_watchpoint:
case bp_hardware_watchpoint:
- annotate_watchpoint (b->number);
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
case bp_access_watchpoint:
if (bs->old_val != NULL)
{
- annotate_watchpoint (b->number);
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
/* Masked watchpoints have only one location. */
gdb_assert (b->loc && b->loc->next == NULL);
+ annotate_watchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
+
switch (b->type)
{
case bp_hardware_watchpoint:
- annotate_watchpoint (b->number);
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
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."));
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 ();
bkpt_re_set (struct breakpoint *b)
{
/* FIXME: is this still reachable? */
- if (event_location_empty_p (b->location))
+ if (breakpoint_event_location_empty_p (b))
{
/* Anything without a location can't be re-set. */
delete_breakpoint (b);
bl->address,
b->number, 1);
annotate_breakpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
+
if (bp_temp)
- ui_out_text (uiout, "\nTemporary breakpoint ");
+ ui_out_text (uiout, "Temporary breakpoint ");
else
- ui_out_text (uiout, "\nBreakpoint ");
+ ui_out_text (uiout, "Breakpoint ");
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
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. */
{
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);
}
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"));
}
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;
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;
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;
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;
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))
{
/* Ranged breakpoints have only one start location and one end
location. */
b->enable_state = bp_disabled;
- update_global_location_list (UGLL_MAY_INSERT);
printf_unfiltered (_("Could not reset ranged breakpoint %d: "
"multiple locations found\n"),
b->number);
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)
{
if (!locations_are_equal (existing_locations, b->loc))
observer_notify_breakpoint_modified (b);
-
- update_global_location_list (UGLL_MAY_INSERT);
}
/* Find the SaL locations corresponding to the given LOCATION.
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;
TRY
{
- b->ops->decode_location (b, location, &sals);
+ b->ops->decode_location (b, location, search_pspace, &sals);
}
CATCH (e, RETURN_MASK_ERROR)
{
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))
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);
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);
}
}
- 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
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);
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.
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)
{
save_language = current_language->la_language;
save_input_radix = input_radix;
- old_chain = save_current_program_space ();
+ old_chain = save_current_space_and_thread ();
+
+ /* Note: we must not try to insert locations until after all
+ breakpoints have been re-set. Otherwise, e.g., when re-setting
+ breakpoint 1, we'd insert the locations of breakpoint 2, which
+ hadn't been re-set yet, and thus may have stale locations. */
ALL_BREAKPOINTS_SAFE (b, b_tmp)
{
create_longjmp_master_breakpoint ();
create_std_terminate_master_breakpoint ();
create_exception_master_breakpoint ();
+
+ /* Now we can insert. */
+ update_global_location_list (UGLL_MAY_INSERT);
}
\f
/* Reset the thread number of this breakpoint: