#include "format.h"
#include "location.h"
#include "thread-fsm.h"
+#include "tid-parse.h"
/* readline include files */
#include "readline/readline.h"
#include "mi/mi-common.h"
#include "extension.h"
+#include <algorithm>
/* Enums for exception-handling support. */
enum exception_event_kind
static void enable_command (char *, int);
-static void map_breakpoint_numbers (char *, void (*) (struct breakpoint *,
- void *),
+static void map_breakpoint_numbers (const char *,
+ void (*) (struct breakpoint *,
+ void *),
void *);
static void ignore_command (char *, int);
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);
static void condition_command (char *, int);
-typedef enum
- {
- mark_inserted,
- mark_uninserted
- }
-insertion_state_t;
-
-static int remove_breakpoint (struct bp_location *, insertion_state_t);
-static int remove_breakpoint_1 (struct bp_location *, insertion_state_t);
+static int remove_breakpoint (struct bp_location *);
+static int remove_breakpoint_1 (struct bp_location *, enum remove_bp_reason);
static enum print_stop_action print_bp_stop_message (bpstat bs);
{
struct watchpoint *w = (struct watchpoint *) b;
- xfree (w->cond_exp);
- w->cond_exp = NULL;
+ w->cond_exp.reset ();
}
else
{
for (loc = b->loc; loc; loc = loc->next)
{
- xfree (loc->cond);
- loc->cond = NULL;
+ loc->cond.reset ();
/* No need to free the condition agent expression
bytecode (if we have one). We will handle this
int from_tty;
/* The breakpoint range spec. */
- char *arg;
+ const char *arg;
/* Non-NULL if the body of the commands are being read from this
already-parsed command. */
}
static void
-commands_command_1 (char *arg, int from_tty,
+commands_command_1 (const char *arg, int from_tty,
struct command_line *control)
{
struct cleanup *cleanups;
extra reference to the commands that we must clean up. */
cleanups = make_cleanup_decref_counted_command_line (&info.cmd);
+ std::string new_arg;
+
if (arg == NULL || !*arg)
{
if (breakpoint_count - prev_breakpoint_count > 1)
- arg = xstrprintf ("%d-%d", prev_breakpoint_count + 1,
- breakpoint_count);
+ new_arg = string_printf ("%d-%d", prev_breakpoint_count + 1,
+ breakpoint_count);
else if (breakpoint_count > 0)
- arg = xstrprintf ("%d", breakpoint_count);
- else
- {
- /* So that we don't try to free the incoming non-NULL
- argument in the cleanup below. Mapping breakpoint
- numbers will fail in this case. */
- arg = NULL;
- }
+ new_arg = string_printf ("%d", breakpoint_count);
}
else
- /* The command loop has some static state, so we need to preserve
- our argument. */
- arg = xstrdup (arg);
-
- if (arg != NULL)
- make_cleanup (xfree, arg);
+ new_arg = arg;
- info.arg = arg;
+ info.arg = new_arg.c_str ();
- map_breakpoint_numbers (arg, do_map_commands_command, &info);
+ map_breakpoint_numbers (info.arg, do_map_commands_command, &info);
if (info.cmd == NULL)
error (_("No breakpoints specified."));
This is used by cli-script.c to DTRT with breakpoint commands
that are part of if and while bodies. */
enum command_control_type
-commands_from_control_command (char *arg, struct command_line *cmd)
+commands_from_control_command (const char *arg, struct command_line *cmd)
{
commands_command_1 (arg, 0, cmd);
return simple_control;
/* Left boundary, right boundary and median element of our binary
search. */
unsigned bc_l, bc_r, bc;
- size_t i;
/* Find BC_L which is a leftmost element which may affect BUF
content. It is safe to report lower value but a failure to
for (bc = bc_l; bc < bp_location_count; bc++)
{
struct bp_location *bl = bp_location[bc];
- CORE_ADDR bp_addr = 0;
- int bp_size = 0;
- int bptoffset = 0;
/* bp_location array has BL->OWNER always non-NULL. */
if (bl->owner->type == bp_none)
{
const char *s;
- if (b->exp)
- {
- xfree (b->exp);
- b->exp = NULL;
- }
+ b->exp.reset ();
s = b->exp_string_reparse ? b->exp_string_reparse : b->exp_string;
b->exp = parse_exp_1 (&s, 0, b->exp_valid_block, 0);
/* If the meaning of expression itself changed, the old value is
locations (re)created below. */
if (b->base.cond_string != NULL)
{
- if (b->cond_exp != NULL)
- {
- xfree (b->cond_exp);
- b->cond_exp = NULL;
- }
+ b->cond_exp.reset ();
s = b->base.cond_string;
b->cond_exp = parse_exp_1 (&s, 0, b->cond_exp_valid_block, 0);
struct value *val_chain, *v, *result, *next;
struct program_space *frame_pspace;
- fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain, 0);
+ fetch_subexp_value (b->exp.get (), &pc, &v, &result, &val_chain, 0);
/* Avoid setting b->val if it's already set. The meaning of
b->val is 'the last value' user saw, and we should update
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)
{
by the bytecode interpreter. Return NULL if there was
any error during parsing. */
-static struct agent_expr *
+static agent_expr_up
parse_cond_to_aexpr (CORE_ADDR scope, struct expression *cond)
{
- struct agent_expr *aexpr = NULL;
-
- if (!cond)
+ if (cond == NULL)
return NULL;
+ agent_expr_up aexpr;
+
/* We don't want to stop processing, so catch any errors
that may show up. */
TRY
/* If we got here, it means the condition could not be parsed to a valid
bytecode expression and thus can't be evaluated on the target's side.
It's no use iterating through the conditions. */
- return NULL;
}
END_CATCH
struct bp_location *loc;
/* Release conditions left over from a previous insert. */
- VEC_free (agent_expr_p, bl->target_info.conditions);
+ bl->target_info.conditions.clear ();
/* This is only meaningful if the target is
evaluating conditions and if the user has
{
if (modified)
{
- struct agent_expr *aexpr;
-
/* Re-parse the conditions since something changed. In that
case we already freed the condition bytecodes (see
force_breakpoint_reinsertion). We just
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;
+ loc->cond_bytecode = parse_cond_to_aexpr (bl->address,
+ loc->cond.get ());
}
/* If we have a NULL bytecode expression, it means something
if (!loc->cond_bytecode)
return;
- free_agent_expr (loc->cond_bytecode);
- loc->cond_bytecode = NULL;
+ loc->cond_bytecode.reset ();
}
}
}
&& loc->pspace->num == bl->pspace->num
&& loc->owner->enable_state == bp_enabled
&& loc->enabled)
- /* Add the condition to the vector. This will be used later to send the
- conditions to the target. */
- VEC_safe_push (agent_expr_p, bl->target_info.conditions,
- loc->cond_bytecode);
+ {
+ /* Add the condition to the vector. This will be used later
+ to send the conditions to the target. */
+ bl->target_info.conditions.push_back (loc->cond_bytecode.get ());
+ }
}
return;
bytecode suitable for evaluation by the bytecode interpreter.
Return NULL if there was any error during parsing. */
-static struct agent_expr *
+static agent_expr_up
parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
{
struct cleanup *old_cleanups = 0;
- struct expression *expr, **argvec;
- struct agent_expr *aexpr = NULL;
+ struct expression **argvec;
const char *cmdrest;
const char *format_start, *format_end;
struct format_piece *fpieces;
int nargs;
struct gdbarch *gdbarch = get_current_arch ();
- if (!cmd)
+ if (cmd == NULL)
return NULL;
cmdrest = cmd;
const char *cmd1;
cmd1 = cmdrest;
- expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1);
- argvec[nargs++] = expr;
+ expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1);
+ argvec[nargs++] = expr.release ();
cmdrest = cmd1;
if (*cmdrest == ',')
++cmdrest;
}
+ agent_expr_up aexpr;
+
/* We don't want to stop processing, so catch any errors
that may show up. */
TRY
/* If we got here, it means the command could not be parsed to a valid
bytecode expression and thus can't be evaluated on the target's side.
It's no use iterating through the other commands. */
- aexpr = NULL;
}
END_CATCH
int modified = bl->needs_update;
struct bp_location *loc;
- /* Release commands left over from a previous insert. */
- VEC_free (agent_expr_p, bl->target_info.tcommands);
+ /* Clear commands left over from a previous insert. */
+ bl->target_info.tcommands.clear ();
if (!target_can_run_breakpoint_commands ())
return;
{
if (modified)
{
- struct agent_expr *aexpr;
-
/* Re-parse the commands since something changed. In that
case we already freed the command bytecodes (see
force_breakpoint_reinsertion). We just
need to parse the command to bytecodes again. */
- aexpr = parse_cmd_to_aexpr (bl->address,
- loc->owner->extra_string);
- loc->cmd_bytecode = aexpr;
-
- if (!aexpr)
- continue;
+ loc->cmd_bytecode
+ = parse_cmd_to_aexpr (bl->address,
+ loc->owner->extra_string);
}
/* If we have a NULL bytecode expression, it means something
if (loc->cmd_bytecode == NULL)
return;
- free_agent_expr (loc->cmd_bytecode);
- loc->cmd_bytecode = NULL;
+ loc->cmd_bytecode.reset ();
}
}
}
&& loc->pspace->num == bl->pspace->num
&& loc->owner->enable_state == bp_enabled
&& loc->enabled)
- /* Add the command to the vector. This will be used later
- to send the commands to the target. */
- VEC_safe_push (agent_expr_p, bl->target_info.tcommands,
- loc->cmd_bytecode);
+ {
+ /* Add the command to the vector. This will be used later
+ to send the commands to the target. */
+ bl->target_info.tcommands.push_back (loc->cmd_bytecode.get ());
+ }
}
bl->target_info.persist = 0;
bl->target_info.persist = 1;
}
+/* Return the kind of breakpoint on address *ADDR. Get the kind
+ of breakpoint according to ADDR except single-step breakpoint.
+ Get the kind of single-step breakpoint according to the current
+ registers state. */
+
+static int
+breakpoint_kind (struct bp_location *bl, CORE_ADDR *addr)
+{
+ if (bl->owner->type == bp_single_step)
+ {
+ struct thread_info *thr = find_thread_global_id (bl->owner->thread);
+ struct regcache *regcache;
+
+ regcache = get_thread_regcache (thr->ptid);
+
+ return gdbarch_breakpoint_kind_from_current_state (bl->gdbarch,
+ regcache, addr);
+ }
+ else
+ return gdbarch_breakpoint_kind_from_pc (bl->gdbarch, addr);
+}
+
/* Insert a low-level "breakpoint" of some type. BL is the breakpoint
location. Any error messages are printed to TMP_ERROR_STREAM; and
DISABLED_BREAKS, and HW_BREAKPOINT_ERROR are used to report problems.
{
int val;
+ bl->overlay_target_info.kind
+ = breakpoint_kind (bl, &addr);
+ bl->overlay_target_info.placed_address = addr;
val = target_insert_breakpoint (bl->gdbarch,
&bl->overlay_target_info);
if (val)
the thread no longer exists. ALL_BP_LOCATIONS bp_location
has BL->OWNER always non-NULL. */
if (bl->owner->thread != -1
- && !valid_thread_id (bl->owner->thread))
+ && !valid_global_thread_id (bl->owner->thread))
continue;
switch_to_program_space_and_thread (bl->pspace);
{
for (loc = bpt->loc; loc; loc = loc->next)
if (loc->inserted)
- remove_breakpoint (loc, mark_uninserted);
+ remove_breakpoint (loc);
hw_breakpoint_error = 1;
fprintf_unfiltered (tmp_error_stream,
ALL_BP_LOCATIONS (bl, blp_tmp)
{
if (bl->inserted && !is_tracepoint (bl->owner))
- val |= remove_breakpoint (bl, mark_uninserted);
+ val |= remove_breakpoint (bl);
}
return val;
}
ALL_BREAKPOINTS_SAFE (b, b_tmp)
{
- if (b->thread == tp->num && user_breakpoint_p (b))
+ if (b->thread == tp->global_num && user_breakpoint_p (b))
{
b->disposition = disp_del_at_next_stop;
if (bl->inserted && !bl->target_info.persist)
{
- val = remove_breakpoint (bl, mark_uninserted);
+ val = remove_breakpoint (bl);
if (val != 0)
return val;
}
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;
continue;
if (bl->inserted)
- val |= remove_breakpoint_1 (bl, mark_inserted);
+ val |= remove_breakpoint_1 (bl, DETACH_BREAKPOINT);
}
do_cleanups (old_chain);
*not* look at bl->pspace->aspace here. */
static int
-remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is)
+remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason)
{
int val;
&& !memory_validate_breakpoint (bl->gdbarch, &bl->target_info))
val = 0;
else
- val = bl->owner->ops->remove_location (bl);
+ val = bl->owner->ops->remove_location (bl, reason);
}
else
{
&bl->overlay_target_info);
else
target_remove_breakpoint (bl->gdbarch,
- &bl->overlay_target_info);
+ &bl->overlay_target_info,
+ reason);
}
/* Did we set a breakpoint at the VMA?
If so, we will have marked the breakpoint 'inserted'. */
wrong code with the saved shadow contents. */
if (bl->loc_type == bp_loc_hardware_breakpoint
|| section_is_mapped (bl->section))
- val = bl->owner->ops->remove_location (bl);
+ val = bl->owner->ops->remove_location (bl, reason);
else
val = 0;
}
if (val)
return val;
- bl->inserted = (is == mark_inserted);
+ bl->inserted = (reason == DETACH_BREAKPOINT);
}
else if (bl->loc_type == bp_loc_hardware_watchpoint)
{
gdb_assert (bl->owner->ops != NULL
&& bl->owner->ops->remove_location != NULL);
- bl->inserted = (is == mark_inserted);
- bl->owner->ops->remove_location (bl);
+ bl->inserted = (reason == DETACH_BREAKPOINT);
+ bl->owner->ops->remove_location (bl, reason);
/* Failure to remove any of the hardware watchpoints comes here. */
- if ((is == mark_uninserted) && (bl->inserted))
+ if (reason == REMOVE_BREAKPOINT && bl->inserted)
warning (_("Could not remove hardware watchpoint %d."),
bl->owner->number);
}
gdb_assert (bl->owner->ops != NULL
&& bl->owner->ops->remove_location != NULL);
- val = bl->owner->ops->remove_location (bl);
+ val = bl->owner->ops->remove_location (bl, reason);
if (val)
return val;
- bl->inserted = (is == mark_inserted);
+ bl->inserted = (reason == DETACH_BREAKPOINT);
}
return 0;
}
static int
-remove_breakpoint (struct bp_location *bl, insertion_state_t is)
+remove_breakpoint (struct bp_location *bl)
{
int ret;
struct cleanup *old_chain;
switch_to_program_space_and_thread (bl->pspace);
- ret = remove_breakpoint_1 (bl, is);
+ ret = remove_breakpoint_1 (bl, REMOVE_BREAKPOINT);
do_cleanups (old_chain);
return ret;
breakpoint_init_inferior (enum inf_context context)
{
struct breakpoint *b, *b_tmp;
- struct bp_location *bl, **blp_tmp;
+ struct bp_location *bl;
int ix;
struct program_space *pspace = current_program_space;
/* Likewise for watchpoints on local expressions. */
if (w->exp_valid_block != NULL)
delete_breakpoint (b);
- else if (context == inf_starting)
+ else
{
- /* Reset val field to force reread of starting value in
- insert_breakpoints. */
- if (w->val)
- value_free (w->val);
- w->val = NULL;
- w->val_valid = 0;
- }
+ /* Get rid of existing locations, which are no longer
+ valid. New ones will be created in
+ update_watchpoint, when the inferior is restarted.
+ The next update_global_location_list call will
+ garbage collect them. */
+ b->loc = NULL;
+
+ if (context == inf_starting)
+ {
+ /* Reset val field to force reread of starting value in
+ insert_breakpoints. */
+ if (w->val)
+ value_free (w->val);
+ w->val = NULL;
+ w->val_valid = 0;
+ }
+ }
}
break;
default:
breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc)
{
struct bp_location **blp, **blp_tmp = NULL;
- struct bp_location *bl;
ALL_BP_LOCATIONS_AT_ADDR (blp, blp_tmp, pc)
{
CORE_ADDR pc)
{
struct bp_location **blp, **blp_tmp = NULL;
- struct bp_location *bl;
ALL_BP_LOCATIONS_AT_ADDR (blp, blp_tmp, pc)
{
CORE_ADDR pc)
{
struct bp_location **blp, **blp_tmp = NULL;
- struct bp_location *bl;
ALL_BP_LOCATIONS_AT_ADDR (blp, blp_tmp, pc)
{
CORE_ADDR l, h;
/* Check for intersection. */
- l = max (loc->address, addr);
- h = min (loc->address + loc->length, addr + len);
+ l = std::max<CORE_ADDR> (loc->address, addr);
+ h = std::min<CORE_ADDR> (loc->address + loc->length, addr + len);
if (l < h)
return 1;
}
if (breakpoint_proceeded)
{
- if (interpreter_async)
+ if (current_ui->async)
/* If we are in async mode, then the target might be still
running, not stopped at any breakpoint, so nothing for
us to do here -- just return to the event loop. */
}
}
+/* 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
return WP_VALUE_CHANGED;
mark = value_mark ();
- fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL, 0);
+ fetch_subexp_value (b->exp.get (), &pc, &new_val, NULL, NULL, 0);
if (b->val_bitsize != 0)
new_val = extract_bitfield_from_watchpoint_value (b, new_val);
}
else
{
- struct ui_out *uiout = current_uiout;
-
/* This seems like the only logical thing to do because
if we temporarily ignored the watchpoint, then when
we reenter the block in which it is valid it contains
call breakpoint_ops->print_it this bp will be deleted
already. So we have no choice but print the information
here. */
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string
- (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
- ui_out_text (uiout, "\nWatchpoint ");
- ui_out_field_int (uiout, "wpnum", b->base.number);
- ui_out_text (uiout,
- " deleted because the program has left the block in\n\
-which its expression is valid.\n");
+
+ SWITCH_THRU_ALL_UIS ()
+ {
+ struct ui_out *uiout = current_uiout;
+
+ if (ui_out_is_mi_like_p (uiout))
+ ui_out_field_string
+ (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
+ ui_out_text (uiout, "\nWatchpoint ");
+ ui_out_field_int (uiout, "wpnum", b->base.number);
+ ui_out_text (uiout,
+ " deleted because the program has left the block in\n"
+ "which its expression is valid.\n");
+ }
/* Make sure the watchpoint's commands aren't executed. */
decref_counted_command_line (&b->base.commands);
/* Can't happen. */
case 0:
/* Error from catch_errors. */
- printf_filtered (_("Watchpoint %d deleted.\n"), b->base.number);
- watchpoint_del_at_next_stop (b);
- /* We've already printed what needs to be printed. */
- bs->print_it = print_it_done;
+ {
+ SWITCH_THRU_ALL_UIS ()
+ {
+ printf_filtered (_("Watchpoint %d deleted.\n"),
+ b->base.number);
+ }
+ watchpoint_del_at_next_stop (b);
+ /* We've already printed what needs to be printed. */
+ bs->print_it = print_it_done;
+ }
break;
}
}
/* If this is a thread/task-specific breakpoint, don't waste cpu
evaluating the condition if this isn't the specified
thread/task. */
- if ((b->thread != -1 && b->thread != pid_to_thread_id (ptid))
+ if ((b->thread != -1 && b->thread != ptid_to_global_thread_id (ptid))
|| (b->task != 0 && b->task != ada_get_task_number (ptid)))
{
{
struct watchpoint *w = (struct watchpoint *) b;
- cond = w->cond_exp;
+ cond = w->cond_exp.get ();
}
else
- cond = bl->cond;
+ cond = bl->cond.get ();
if (cond && b->disposition != disp_del_at_next_stop)
{
bpstat_what (bpstat bs_head)
{
struct bpstat_what retval;
- int jit_event = 0;
bpstat bs;
retval.main_action = BPSTAT_WHAT_KEEP_CHECKING;
}
break;
case bp_jit_event:
- jit_event = 1;
this_action = BPSTAT_WHAT_SINGLE;
break;
case bp_call_dummy:
_("bpstat_what: unhandled bptype %d"), (int) bptype);
}
- retval.main_action = max (retval.main_action, this_action);
+ retval.main_action = std::max (retval.main_action, this_action);
}
return retval;
if (!part_of_multiple && b->thread != -1)
{
- struct thread_info *thr = find_thread_id (b->thread);
-
/* FIXME should make an annotation for this. */
ui_out_text (uiout, "\tstop only in thread ");
- ui_out_field_string (uiout, "thread", print_thread_id (thr));
+ if (ui_out_is_mi_like_p (uiout))
+ ui_out_field_int (uiout, "thread", b->thread);
+ else
+ {
+ struct thread_info *thr = find_thread_global_id (b->thread);
+
+ ui_out_field_string (uiout, "thread", print_thread_id (thr));
+ }
ui_out_text (uiout, "\n");
}
return b->number > 0;
}
+/* See breakpoint.h. */
+
+int
+pending_breakpoint_p (struct breakpoint *b)
+{
+ return b->loc == NULL;
+}
+
/* Print information on user settable breakpoint (watchpoint, etc)
number BNUM. If BNUM is -1 print all user-settable breakpoints.
If ALLFLAG is non-zero, include non-user-settable breakpoints. If
if (!filter)
{
if (args == NULL || *args == '\0')
- ui_out_message (uiout, 0, "No breakpoints or watchpoints.\n");
+ ui_out_message (uiout, "No breakpoints or watchpoints.\n");
else
- ui_out_message (uiout, 0,
+ ui_out_message (uiout,
"No breakpoint or watchpoint matching '%s'.\n",
args);
}
if (num_printed == 0)
{
if (args == NULL || *args == '\0')
- ui_out_message (uiout, 0, "No watchpoints.\n");
+ ui_out_message (uiout, "No watchpoints.\n");
else
- ui_out_message (uiout, 0, "No watchpoint matching '%s'.\n", args);
+ ui_out_message (uiout, "No watchpoint matching '%s'.\n", args);
}
}
&& target_can_accel_watchpoint_condition (loc1->address,
loc1->length,
loc1->watchpoint_type,
- w1->cond_exp))
+ w1->cond_exp.get ()))
|| (w2->cond_exp
&& target_can_accel_watchpoint_condition (loc2->address,
loc2->length,
loc2->watchpoint_type,
- w2->cond_exp)))
+ w2->cond_exp.get ())))
return 0;
/* Note that this checks the owner's type, not the location's. In
loc->ops = ops;
loc->owner = owner;
- loc->cond = NULL;
loc->cond_bytecode = NULL;
loc->shlib_disabled = 0;
loc->enabled = 1;
free_bp_location (struct bp_location *loc)
{
loc->ops->dtor (loc);
- xfree (loc);
+ delete loc;
}
/* Increment reference count. */
enum bptype bptype,
const struct breakpoint_ops *ops)
{
- struct breakpoint *b = XNEW (struct breakpoint);
+ struct breakpoint *b = new breakpoint ();
init_raw_breakpoint_without_location (b, gdbarch, bptype, ops);
add_to_breakpoint_chain (b);
struct symtab_and_line sal, enum bptype bptype,
const struct breakpoint_ops *ops)
{
- struct breakpoint *b = XNEW (struct breakpoint);
+ struct breakpoint *b = new breakpoint ();
init_raw_breakpoint (b, gdbarch, sal, bptype, ops);
add_to_breakpoint_chain (b);
set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame)
{
struct breakpoint *b, *b_tmp;
- int thread = tp->num;
+ int thread = tp->global_num;
/* To avoid having to rescan all objfile symbols at every step,
we maintain a list of continually-inserted but always disabled
new_b = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy,
&momentary_breakpoint_ops,
1);
- new_b->thread = pid_to_thread_id (inferior_ptid);
+ new_b->thread = ptid_to_global_thread_id (inferior_ptid);
/* Link NEW_B into the chain of RETVAL breakpoints. */
struct breakpoint *b, *b_tmp;
ALL_BREAKPOINTS_SAFE (b, b_tmp)
- if (b->type == bp_longjmp_call_dummy && b->thread == tp->num)
+ if (b->type == bp_longjmp_call_dummy && b->thread == tp->global_num)
{
struct breakpoint *dummy_b = b->related_breakpoint;
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). */
catchpoints. */
static int
-remove_catch_fork (struct bp_location *bl)
+remove_catch_fork (struct bp_location *bl, enum remove_bp_reason reason)
{
return target_remove_fork_catchpoint (ptid_get_pid (inferior_ptid));
}
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",
catchpoints. */
static int
-remove_catch_vfork (struct bp_location *bl)
+remove_catch_vfork (struct bp_location *bl, enum remove_bp_reason reason)
{
return target_remove_vfork_catchpoint (ptid_get_pid (inferior_ptid));
}
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",
}
static int
-remove_catch_solib (struct bp_location *ignore)
+remove_catch_solib (struct bp_location *ignore, enum remove_bp_reason reason)
{
return 0;
}
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))
arg = "";
arg = skip_spaces (arg);
- c = XCNEW (struct solib_catchpoint);
+ c = new solib_catchpoint ();
cleanup = make_cleanup (xfree, c);
if (*arg != '\0')
int tempflag, char *cond_string,
const struct breakpoint_ops *ops)
{
- struct fork_catchpoint *c = XNEW (struct fork_catchpoint);
+ struct fork_catchpoint *c = new fork_catchpoint ();
init_catchpoint (&c->base, gdbarch, tempflag, cond_string, ops);
}
static int
-remove_catch_exec (struct bp_location *bl)
+remove_catch_exec (struct bp_location *bl, enum remove_bp_reason reason)
{
return target_remove_exec_catchpoint (ptid_get_pid (inferior_ptid));
}
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",
static struct breakpoint *
new_single_step_breakpoint (int thread, struct gdbarch *gdbarch)
{
- struct breakpoint *b = XNEW (struct breakpoint);
+ struct breakpoint *b = new breakpoint ();
init_raw_breakpoint_without_location (b, gdbarch, bp_single_step,
&momentary_breakpoint_ops);
momentary breakpoints to be active in only a single thread of
control. */
if (in_thread_list (inferior_ptid))
- b->thread = pid_to_thread_id (inferior_ptid);
+ b->thread = ptid_to_global_thread_id (inferior_ptid);
update_global_location_list_nothrow (UGLL_MAY_INSERT);
/* 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;
}
{
struct tracepoint *t;
- t = XCNEW (struct tracepoint);
+ t = new tracepoint ();
b = &t->base;
}
else
- b = XNEW (struct breakpoint);
+ b = new breakpoint ();
old_chain = make_cleanup (xfree, b);
&& 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);
}
old_chain = make_cleanup (xfree, msg);
if (!rslt)
- error (_("May not have a fast tracepoint at 0x%s%s"),
+ error (_("May not have a fast tracepoint at %s%s"),
paddress (sarch, sal->pc), (msg ? msg : ""));
do_cleanups (old_chain);
}
}
-/* Issue an invalid thread ID error. */
-
-static void ATTRIBUTE_NORETURN
-invalid_thread_id_error (int id)
-{
- error (_("Unknown thread %d."), id);
-}
-
/* Given TOK, a string specification of condition and thread, as
accepted by the 'break' command, extract the condition
string and thread number and set *COND_STRING and *THREAD.
if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
{
- struct expression *expr;
-
tok = cond_start = end_tok + 1;
- expr = parse_exp_1 (&tok, pc, block_for_pc (pc), 0);
- xfree (expr);
+ parse_exp_1 (&tok, pc, block_for_pc (pc), 0);
cond_end = tok;
*cond_string = savestring (cond_start, cond_end - cond_start);
}
else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
{
- char *tmptok;
+ const char *tmptok;
+ struct thread_info *thr;
tok = end_tok + 1;
- *thread = strtol (tok, &tmptok, 0);
+ thr = parse_thread_id (tok, &tmptok);
if (tok == tmptok)
error (_("Junk after thread keyword."));
- if (!valid_thread_id (*thread))
- invalid_thread_id_error (*thread);
+ *thread = thr->global_num;
tok = tmptok;
}
else if (toklen >= 1 && strncmp (tok, "task", toklen) == 0)
{
struct tracepoint *t;
- t = XCNEW (struct tracepoint);
+ t = new tracepoint ();
b = &t->base;
}
else
- b = XNEW (struct breakpoint);
+ b = new breakpoint ();
init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops);
b->location = copy_event_location (location);
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",
static void
break_range_command (char *arg, int from_tty)
{
- char *arg_start, *addr_string_start, *addr_string_end;
+ char *arg_start, *addr_string_start;
struct linespec_result canonical_start, canonical_end;
int bp_count, can_use_bp, length;
CORE_ADDR end;
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);
{
struct watchpoint *w = (struct watchpoint *) self;
- xfree (w->cond_exp);
- xfree (w->exp);
xfree (w->exp_string);
xfree (w->exp_string_reparse);
value_free (w->val);
int length = w->exact ? 1 : bl->length;
return target_insert_watchpoint (bl->address, length, bl->watchpoint_type,
- w->cond_exp);
+ w->cond_exp.get ());
}
/* Implement the "remove" breakpoint_ops method for hardware watchpoints. */
static int
-remove_watchpoint (struct bp_location *bl)
+remove_watchpoint (struct bp_location *bl, enum remove_bp_reason reason)
{
struct watchpoint *w = (struct watchpoint *) bl->owner;
int length = w->exact ? 1 : bl->length;
return target_remove_watchpoint (bl->address, length, bl->watchpoint_type,
- w->cond_exp);
+ w->cond_exp.get ());
}
static int
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 hardware watchpoints. */
static int
-remove_masked_watchpoint (struct bp_location *bl)
+remove_masked_watchpoint (struct bp_location *bl, enum remove_bp_reason reason)
{
struct watchpoint *w = (struct watchpoint *) bl->owner;
/* 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",
int just_location, int internal)
{
struct breakpoint *b, *scope_breakpoint = NULL;
- struct expression *exp;
const struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
struct value *val, *mark, *result;
int saved_bitpos = 0, saved_bitsize = 0;
if (toklen == 6 && startswith (tok, "thread"))
{
+ struct thread_info *thr;
/* At this point we've found a "thread" token, which means
the user is trying to set a watchpoint that triggers
only in a specific thread. */
- char *endp;
+ const char *endp;
if (thread != -1)
error(_("You can specify only one thread."));
/* Extract the thread ID from the next token. */
- thread = strtol (value_start, &endp, 0);
+ thr = parse_thread_id (value_start, &endp);
- /* Check if the user provided a valid numeric value for the
- thread ID. */
+ /* Check if the user provided a valid thread ID. */
if (*endp != ' ' && *endp != '\t' && *endp != '\0')
- error (_("Invalid thread ID specification %s."), value_start);
+ invalid_thread_id_error (value_start);
- /* Check if the thread actually exists. */
- if (!valid_thread_id (thread))
- invalid_thread_id_error (thread);
+ thread = thr->global_num;
}
else if (toklen == 4 && startswith (tok, "mask"))
{
expression = savestring (arg, exp_end - arg);
back_to = make_cleanup (xfree, expression);
exp_start = arg = expression;
- exp = parse_exp_1 (&arg, 0, 0, 0);
+ expression_up exp = parse_exp_1 (&arg, 0, 0, 0);
exp_end = arg;
/* Remove trailing whitespace from the expression before saving it.
This makes the eventual display of the expression string a bit
--exp_end;
/* Checking if the expression is not constant. */
- if (watchpoint_exp_is_const (exp))
+ if (watchpoint_exp_is_const (exp.get ()))
{
int len;
exp_valid_block = innermost_block;
mark = value_mark ();
- fetch_subexp_value (exp, &pc, &val, &result, NULL, just_location);
+ fetch_subexp_value (exp.get (), &pc, &val, &result, NULL, just_location);
if (val != NULL && just_location)
{
toklen = end_tok - tok;
if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
{
- struct expression *cond;
-
innermost_block = NULL;
tok = cond_start = end_tok + 1;
- cond = parse_exp_1 (&tok, 0, 0, 0);
+ parse_exp_1 (&tok, 0, 0, 0);
/* The watchpoint expression may not be local, but the condition
may still be. E.g.: `watch global if local > 0'. */
cond_exp_valid_block = innermost_block;
- xfree (cond);
cond_end = tok;
}
if (*tok)
else
bp_type = bp_hardware_watchpoint;
- w = XCNEW (struct watchpoint);
+ w = new watchpoint ();
b = &w->base;
if (use_mask)
init_raw_breakpoint_without_location (b, NULL, bp_type,
b->thread = thread;
b->disposition = disp_donttouch;
b->pspace = current_program_space;
- w->exp = exp;
+ w->exp = std::move (exp);
w->exp_valid_block = exp_valid_block;
w->cond_exp_valid_block = cond_exp_valid_block;
if (just_location)
{
struct type *t = value_type (val);
CORE_ADDR addr = value_as_address (val);
- char *name;
t = check_typedef (TYPE_TARGET_TYPE (check_typedef (t)));
- name = type_to_string (t);
- w->exp_string_reparse = xstrprintf ("* (%s *) %s", name,
+ std::string name = type_to_string (t);
+
+ w->exp_string_reparse = xstrprintf ("* (%s *) %s", name.c_str (),
core_addr_to_string (addr));
- xfree (name);
w->exp_string = xstrprintf ("-location %.*s",
(int) (exp_end - exp_start), exp_start);
struct breakpoint *caller_breakpoint;
};
-static void until_break_fsm_clean_up (struct thread_fsm *self);
-static int until_break_fsm_should_stop (struct thread_fsm *self);
+static void until_break_fsm_clean_up (struct thread_fsm *self,
+ struct thread_info *thread);
+static int until_break_fsm_should_stop (struct thread_fsm *self,
+ struct thread_info *thread);
static enum async_reply_reason
until_break_fsm_async_reply_reason (struct thread_fsm *self);
/* Allocate a new until_break_command_fsm. */
static struct until_break_fsm *
-new_until_break_fsm (int thread,
+new_until_break_fsm (struct interp *cmd_interp, int thread,
struct breakpoint *location_breakpoint,
struct breakpoint *caller_breakpoint)
{
struct until_break_fsm *sm;
sm = XCNEW (struct until_break_fsm);
- thread_fsm_ctor (&sm->thread_fsm, &until_break_fsm_ops);
+ thread_fsm_ctor (&sm->thread_fsm, &until_break_fsm_ops, cmd_interp);
sm->thread = thread;
sm->location_breakpoint = location_breakpoint;
until(location)/advance commands. */
static int
-until_break_fsm_should_stop (struct thread_fsm *self)
+until_break_fsm_should_stop (struct thread_fsm *self,
+ struct thread_info *tp)
{
struct until_break_fsm *sm = (struct until_break_fsm *) self;
- struct thread_info *tp = inferior_thread ();
if (bpstat_find_breakpoint (tp->control.stop_bpstat,
sm->location_breakpoint) != NULL
until(location)/advance commands. */
static void
-until_break_fsm_clean_up (struct thread_fsm *self)
+until_break_fsm_clean_up (struct thread_fsm *self,
+ struct thread_info *thread)
{
struct until_break_fsm *sm = (struct until_break_fsm *) self;
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."));
resolve_sal_pc (&sal);
tp = inferior_thread ();
- thread = tp->num;
+ thread = tp->global_num;
old_chain = make_cleanup (null_cleanup, NULL);
stack_frame_id, bp_until);
make_cleanup_delete_breakpoint (location_breakpoint);
- sm = new_until_break_fsm (tp->num, location_breakpoint, caller_breakpoint);
+ sm = new_until_break_fsm (command_interp (), tp->global_num,
+ location_breakpoint, caller_breakpoint);
tp->thread_fsm = &sm->thread_fsm;
discard_cleanups (old_chain);
if ((*arg != '\0') && !isspace (*arg))
error (_("Junk at end of arguments."));
- c = XNEW (struct exec_catchpoint);
+ c = new exec_catchpoint ();
init_catchpoint (&c->base, gdbarch, tempflag, cond_string,
&catch_exec_breakpoint_ops);
c->exec_pathname = NULL;
/* Free the agent expression bytecode as well. We will compute
it later on. */
- if (loc->cond_bytecode)
- {
- free_agent_expr (loc->cond_bytecode);
- loc->cond_bytecode = NULL;
- }
+ loc->cond_bytecode.reset ();
}
}
/* Called whether new breakpoints are created, or existing breakpoints
if (!keep_in_target)
{
- if (remove_breakpoint (old_loc, mark_uninserted))
+ if (remove_breakpoint (old_loc))
{
/* This is just about all we can do. We could keep
this location on the global list, and try to
static void
bp_location_dtor (struct bp_location *self)
{
- xfree (self->cond);
- if (self->cond_bytecode)
- free_agent_expr (self->cond_bytecode);
xfree (self->function_name);
-
- VEC_free (agent_expr_p, self->target_info.conditions);
- VEC_free (agent_expr_p, self->target_info.tcommands);
}
static const struct bp_location_ops bp_location_ops =
{
struct bp_location *loc;
- loc = XNEW (struct bp_location);
+ loc = new struct bp_location ();
init_bp_location (loc, &bp_location_ops, self);
return loc;
}
}
static int
-base_breakpoint_remove_location (struct bp_location *bl)
+base_breakpoint_remove_location (struct bp_location *bl,
+ enum remove_bp_reason reason)
{
internal_error_pure_virtual_called ();
}
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);
static int
bkpt_insert_location (struct bp_location *bl)
{
+ CORE_ADDR addr = bl->target_info.reqstd_address;
+
+ bl->target_info.kind = breakpoint_kind (bl, &addr);
+ bl->target_info.placed_address = addr;
+
if (bl->loc_type == bp_loc_hardware_breakpoint)
return target_insert_hw_breakpoint (bl->gdbarch, &bl->target_info);
else
}
static int
-bkpt_remove_location (struct bp_location *bl)
+bkpt_remove_location (struct bp_location *bl, enum remove_bp_reason reason)
{
if (bl->loc_type == bp_loc_hardware_breakpoint)
return target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info);
else
- return target_remove_breakpoint (bl->gdbarch, &bl->target_info);
+ return target_remove_breakpoint (bl->gdbarch, &bl->target_info, reason);
}
static int
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. */
static void
longjmp_bkpt_dtor (struct breakpoint *self)
{
- struct thread_info *tp = find_thread_id (self->thread);
+ struct thread_info *tp = find_thread_global_id (self->thread);
if (tp)
tp->initiating_frame = null_frame_id;
}
static int
-bkpt_probe_remove_location (struct bp_location *bl)
+bkpt_probe_remove_location (struct bp_location *bl,
+ enum remove_bp_reason reason)
{
/* Let's clear the semaphore before removing the location. */
if (bl->probe.probe->pops->clear_semaphore != NULL)
bl->probe.objfile,
bl->gdbarch);
- return bkpt_remove_location (bl);
+ return bkpt_remove_location (bl, reason);
}
static void
{
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;
location = copy_event_location (canonical->location);
old_chain = make_cleanup_delete_event_location (location);
- tp = XCNEW (struct tracepoint);
+ tp = new tracepoint ();
init_breakpoint_sal (&tp->base, gdbarch, expanded,
location, NULL,
cond_string, extra_string,
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;
/* 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;
- xfree (bpt);
+ delete bpt;
}
static void
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:
if (b->thread != -1)
{
if (in_thread_list (inferior_ptid))
- b->thread = pid_to_thread_id (inferior_ptid);
+ b->thread = ptid_to_global_thread_id (inferior_ptid);
/* We're being called after following a fork. The new fork is
selected as current, and unless this was a vfork will have a
whose numbers are given in ARGS. */
static void
-map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *,
- void *),
+map_breakpoint_numbers (const char *args,
+ void (*function) (struct breakpoint *,
+ void *),
void *data)
{
int num;
struct breakpoint *b, *tmp;
- int match;
- struct get_number_or_range_state state;
if (args == 0 || *args == '\0')
error_no_arg (_("one or more breakpoint numbers"));
- init_number_or_range (&state, args);
+ number_or_range_parser parser (args);
- while (!state.finished)
+ while (!parser.finished ())
{
- const char *p = state.string;
-
- match = 0;
+ const char *p = parser.cur_tok ();
+ bool match = false;
- num = get_number_or_range (&state);
+ num = parser.get_number ();
if (num == 0)
{
warning (_("bad breakpoint number at or near '%s'"), p);
ALL_BREAKPOINTS_SAFE (b, tmp)
if (b->number == num)
{
- match = 1;
+ match = true;
function (b, data);
break;
}
- if (match == 0)
+ if (!match)
printf_unfiltered (_("No breakpoint number %d.\n"), num);
}
}
if (tp->control.single_step_breakpoints == NULL)
{
tp->control.single_step_breakpoints
- = new_single_step_breakpoint (tp->num, gdbarch);
+ = new_single_step_breakpoint (tp->global_num, gdbarch);
}
sal = find_pc_line (pc, 0);
update_global_location_list (UGLL_INSERT);
}
+/* Insert single step breakpoints according to the current state. */
+
+int
+insert_single_step_breakpoints (struct gdbarch *gdbarch)
+{
+ struct regcache *regcache = get_current_regcache ();
+ VEC (CORE_ADDR) * next_pcs;
+
+ next_pcs = gdbarch_software_single_step (gdbarch, regcache);
+
+ if (next_pcs != NULL)
+ {
+ int i;
+ CORE_ADDR pc;
+ struct frame_info *frame = get_current_frame ();
+ struct address_space *aspace = get_frame_address_space (frame);
+
+ for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++)
+ insert_single_step_breakpoint (gdbarch, aspace, pc);
+
+ VEC_free (CORE_ADDR, next_pcs);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
/* See breakpoint.h. */
int
if (num_printed == 0)
{
if (args == NULL || *args == '\0')
- ui_out_message (uiout, 0, "No tracepoints.\n");
+ ui_out_message (uiout, "No tracepoints.\n");
else
- ui_out_message (uiout, 0, "No tracepoint matching '%s'.\n", args);
+ ui_out_message (uiout, "No tracepoint matching '%s'.\n", args);
}
default_collect_info ();
}
else
{
- struct get_number_or_range_state state;
-
- init_number_or_range (&state, args);
- while (!state.finished)
+ number_or_range_parser parser (args);
+ while (!parser.finished ())
{
- t1 = get_tracepoint_by_number (&args, &state);
+ t1 = get_tracepoint_by_number (&args, &parser);
if (t1)
trace_pass_set_count (t1, count, from_tty);
}
struct tracepoint *
get_tracepoint_by_number (char **arg,
- struct get_number_or_range_state *state)
+ number_or_range_parser *parser)
{
struct breakpoint *t;
int tpnum;
char *instring = arg == NULL ? NULL : *arg;
- if (state)
+ if (parser != NULL)
{
- gdb_assert (!state->finished);
- tpnum = get_number_or_range (state);
+ gdb_assert (!parser->finished ());
+ tpnum = parser->get_number ();
}
else if (arg == NULL || *arg == NULL || ! **arg)
tpnum = tracepoint_count;
if (tp->type != bp_dprintf && tp->commands)
{
- struct gdb_exception exception;
-
fprintf_unfiltered (fp, " commands\n");
ui_out_redirect (current_uiout, fp);