/* Everything about breakpoints, for GDB.
- Copyright (C) 1986-2016 Free Software Foundation, Inc.
+ Copyright (C) 1986-2017 Free Software Foundation, Inc.
This file is part of GDB.
#include "dummy-frame.h"
#include "interps.h"
#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>
+#include "progspace-and-thread.h"
/* 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);
/* Momentary breakpoints class type. */
static struct breakpoint_ops momentary_breakpoint_ops;
-/* Momentary breakpoints for bp_longjmp and bp_exception class type. */
-static struct breakpoint_ops longjmp_breakpoint_ops;
-
/* The breakpoint_ops structure to be used in regular user created
breakpoints. */
struct breakpoint_ops bkpt_breakpoint_ops;
copied into the command, so it can be anything that GDB can
evaluate to a callable address, not necessarily a function name. */
-static char *dprintf_function = "";
+static char *dprintf_function;
/* The channel to use for dynamic printf if the preferred style is to
call into the inferior; if a nonempty string, it will be passed to
"stderr", this could be an app-specific expression like
"mystreams[curlogger]". */
-static char *dprintf_channel = "";
+static char *dprintf_channel;
/* True if dprintf commands should continue to operate even if GDB
has disconnected. */
while executing the block of ALL_BP_LOCATIONS. */
#define ALL_BP_LOCATIONS(B,BP_TMP) \
- for (BP_TMP = bp_location; \
- BP_TMP < bp_location + bp_location_count && (B = *BP_TMP); \
+ for (BP_TMP = bp_locations; \
+ BP_TMP < bp_locations + bp_locations_count && (B = *BP_TMP);\
BP_TMP++)
/* Iterates through locations with address ADDRESS for the currently selected
for (BP_LOCP_START = BP_LOCP_START == NULL ? get_first_locp_gte_addr (ADDRESS) : BP_LOCP_START, \
BP_LOCP_TMP = BP_LOCP_START; \
BP_LOCP_START \
- && (BP_LOCP_TMP < bp_location + bp_location_count \
+ && (BP_LOCP_TMP < bp_locations + bp_locations_count \
&& (*BP_LOCP_TMP)->address == ADDRESS); \
BP_LOCP_TMP++)
struct breakpoint *breakpoint_chain;
-/* Array is sorted by bp_location_compare - primarily by the ADDRESS. */
+/* Array is sorted by bp_locations_compare - primarily by the ADDRESS. */
-static struct bp_location **bp_location;
+static struct bp_location **bp_locations;
-/* Number of elements of BP_LOCATION. */
+/* Number of elements of BP_LOCATIONS. */
-static unsigned bp_location_count;
+static unsigned bp_locations_count;
/* Maximum alignment offset between bp_target_info.PLACED_ADDRESS and
- ADDRESS for the current elements of BP_LOCATION which get a valid
+ ADDRESS for the current elements of BP_LOCATIONS which get a valid
result from bp_location_has_shadow. You can use it for roughly
- limiting the subrange of BP_LOCATION to scan for shadow bytes for
+ limiting the subrange of BP_LOCATIONS to scan for shadow bytes for
an address you need to read. */
-static CORE_ADDR bp_location_placed_address_before_address_max;
+static CORE_ADDR bp_locations_placed_address_before_address_max;
/* Maximum offset plus alignment between bp_target_info.PLACED_ADDRESS
+ bp_target_info.SHADOW_LEN and ADDRESS for the current elements of
- BP_LOCATION which get a valid result from bp_location_has_shadow.
- You can use it for roughly limiting the subrange of BP_LOCATION to
+ BP_LOCATIONS which get a valid result from bp_location_has_shadow.
+ You can use it for roughly limiting the subrange of BP_LOCATIONS to
scan for shadow bytes for an address you need to read. */
-static CORE_ADDR bp_location_shadow_len_after_address_max;
+static CORE_ADDR bp_locations_shadow_len_after_address_max;
/* The locations that no longer correspond to any breakpoint, unlinked
- from bp_location array, but for which a hit may still be reported
- by a target. */
+ from the bp_locations array, but for which a hit may still be
+ reported by a target. */
VEC(bp_location_p) *moribund_locations = NULL;
/* Number of last breakpoint made. */
/* A comparison function for bp_location AP and BP that is used by
bsearch. This comparison function only cares about addresses, unlike
- the more general bp_location_compare function. */
+ the more general bp_locations_compare function. */
static int
-bp_location_compare_addrs (const void *ap, const void *bp)
+bp_locations_compare_addrs (const void *ap, const void *bp)
{
const struct bp_location *a = *(const struct bp_location **) ap;
const struct bp_location *b = *(const struct bp_location **) bp;
struct bp_location **locp_found = NULL;
/* Initialize the dummy location's address field. */
- memset (&dummy_loc, 0, sizeof (struct bp_location));
dummy_loc.address = address;
/* Find a close match to the first location at ADDRESS. */
locp_found = ((struct bp_location **)
- bsearch (&dummy_locp, bp_location, bp_location_count,
+ bsearch (&dummy_locp, bp_locations, bp_locations_count,
sizeof (struct bp_location **),
- bp_location_compare_addrs));
+ bp_locations_compare_addrs));
/* Nothing was found, nothing left to do. */
if (locp_found == NULL)
/* We may have found a location that is at ADDRESS but is not the first in the
location's list. Go backwards (if possible) and locate the first one. */
- while ((locp_found - 1) >= bp_location
+ while ((locp_found - 1) >= bp_locations
&& (*(locp_found - 1))->address == address)
locp_found--;
{
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
}
}
+struct longjmp_breakpoint : public breakpoint
+{
+ ~longjmp_breakpoint () override;
+};
+
/* Encapsulate tests for different types of tracepoints. */
-static int
-is_tracepoint_type (enum bptype type)
+static bool
+is_tracepoint_type (bptype type)
{
return (type == bp_tracepoint
|| type == bp_fast_tracepoint
|| type == bp_static_tracepoint);
}
+static bool
+is_longjmp_type (bptype type)
+{
+ return type == bp_longjmp || type == bp_exception;
+}
+
int
is_tracepoint (const struct breakpoint *b)
{
return is_tracepoint_type (b->type);
}
+/* Factory function to create an appropriate instance of breakpoint given
+ TYPE. */
+
+static std::unique_ptr<breakpoint>
+new_breakpoint_from_type (bptype type)
+{
+ breakpoint *b;
+
+ if (is_tracepoint_type (type))
+ b = new tracepoint ();
+ else if (is_longjmp_type (type))
+ b = new longjmp_breakpoint ();
+ else
+ b = new breakpoint ();
+
+ return std::unique_ptr<breakpoint> (b);
+}
+
/* A helper function that validates that COMMANDS are valid for a
breakpoint. This function will throw an exception if a problem is
found. */
void
breakpoint_set_commands (struct breakpoint *b,
- struct command_line *commands)
+ command_line_up &&commands)
{
- validate_commands_for_breakpoint (b, commands);
+ validate_commands_for_breakpoint (b, commands.get ());
decref_counted_command_line (&b->commands);
- b->commands = alloc_counted_command_line (commands);
+ b->commands = alloc_counted_command_line (commands.release ());
observer_notify_breakpoint_modified (b);
}
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. */
if (info->cmd == NULL)
{
- struct command_line *l;
+ command_line_up l;
if (info->control != NULL)
l = copy_command_lines (info->control->body_list[0]);
do_cleanups (old_chain);
}
- info->cmd = alloc_counted_command_line (l);
+ info->cmd = alloc_counted_command_line (l.release ());
}
/* If a breakpoint was on the list more than once, we don't need to
}
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;
a failed assertion internal error will be raised.
The range of shadowed area by each bp_location is:
- bl->address - bp_location_placed_address_before_address_max
- up to bl->address + bp_location_shadow_len_after_address_max
+ bl->address - bp_locations_placed_address_before_address_max
+ up to bl->address + bp_locations_shadow_len_after_address_max
The range we were requested to resolve shadows for is:
memaddr ... memaddr + len
Thus the safe cutoff boundaries for performance optimization are
memaddr + len <= (bl->address
- - bp_location_placed_address_before_address_max)
+ - bp_locations_placed_address_before_address_max)
and:
- bl->address + bp_location_shadow_len_after_address_max <= memaddr */
+ bl->address + bp_locations_shadow_len_after_address_max <= memaddr */
void
breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
/* 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
report higher one. */
bc_l = 0;
- bc_r = bp_location_count;
+ bc_r = bp_locations_count;
while (bc_l + 1 < bc_r)
{
struct bp_location *bl;
bc = (bc_l + bc_r) / 2;
- bl = bp_location[bc];
+ bl = bp_locations[bc];
/* Check first BL->ADDRESS will not overflow due to the added
constant. Then advance the left boundary only if we are sure
the BC element can in no way affect the BUF content (MEMADDR
to MEMADDR + LEN range).
- Use the BP_LOCATION_SHADOW_LEN_AFTER_ADDRESS_MAX safety
+ Use the BP_LOCATIONS_SHADOW_LEN_AFTER_ADDRESS_MAX safety
offset so that we cannot miss a breakpoint with its shadow
range tail still reaching MEMADDR. */
- if ((bl->address + bp_location_shadow_len_after_address_max
+ if ((bl->address + bp_locations_shadow_len_after_address_max
>= bl->address)
- && (bl->address + bp_location_shadow_len_after_address_max
+ && (bl->address + bp_locations_shadow_len_after_address_max
<= memaddr))
bc_l = bc;
else
on "master" locations, we'd forget to restore the shadow of L1
and L2. */
while (bc_l > 0
- && bp_location[bc_l]->address == bp_location[bc_l - 1]->address)
+ && bp_locations[bc_l]->address == bp_locations[bc_l - 1]->address)
bc_l--;
/* Now do full processing of the found relevant range of elements. */
- for (bc = bc_l; bc < bp_location_count; bc++)
+ for (bc = bc_l; bc < bp_locations_count; bc++)
{
- struct bp_location *bl = bp_location[bc];
- CORE_ADDR bp_addr = 0;
- int bp_size = 0;
- int bptoffset = 0;
+ struct bp_location *bl = bp_locations[bc];
/* bp_location array has BL->OWNER always non-NULL. */
if (bl->owner->type == bp_none)
/* Performance optimization: any further element can no longer affect BUF
content. */
- if (bl->address >= bp_location_placed_address_before_address_max
- && memaddr + len <= (bl->address
- - bp_location_placed_address_before_address_max))
+ if (bl->address >= bp_locations_placed_address_before_address_max
+ && memaddr + len <= (bl->address
+ - bp_locations_placed_address_before_address_max))
break;
if (!bp_location_has_shadow (bl))
static int
watchpoint_in_thread_scope (struct watchpoint *b)
{
- return (b->base.pspace == current_program_space
+ return (b->pspace == current_program_space
&& (ptid_equal (b->watchpoint_thread, null_ptid)
|| (ptid_equal (inferior_ptid, b->watchpoint_thread)
&& !is_executing (inferior_ptid))));
static void
watchpoint_del_at_next_stop (struct watchpoint *w)
{
- struct breakpoint *b = &w->base;
-
- if (b->related_breakpoint != b)
+ if (w->related_breakpoint != w)
{
- gdb_assert (b->related_breakpoint->type == bp_watchpoint_scope);
- gdb_assert (b->related_breakpoint->related_breakpoint == b);
- b->related_breakpoint->disposition = disp_del_at_next_stop;
- b->related_breakpoint->related_breakpoint = b->related_breakpoint;
- b->related_breakpoint = b;
+ gdb_assert (w->related_breakpoint->type == bp_watchpoint_scope);
+ gdb_assert (w->related_breakpoint->related_breakpoint == w);
+ w->related_breakpoint->disposition = disp_del_at_next_stop;
+ w->related_breakpoint->related_breakpoint = w->related_breakpoint;
+ w->related_breakpoint = w;
}
- b->disposition = disp_del_at_next_stop;
+ w->disposition = disp_del_at_next_stop;
}
/* Extract a bitfield value from value VAL using the bit parameters contained in
if (!watchpoint_in_thread_scope (b))
return;
- if (b->base.disposition == disp_del_at_next_stop)
+ if (b->disposition == disp_del_at_next_stop)
return;
frame_saved = 0;
/* We don't free locations. They are stored in the bp_location array
and update_global_location_list will eventually delete them and
remove breakpoints if needed. */
- b->base.loc = NULL;
+ b->loc = NULL;
if (within_current_scope && reparse)
{
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
/* Note that unlike with breakpoints, the watchpoint's condition
expression is stored in the breakpoint object, not in the
locations (re)created below. */
- if (b->base.cond_string != NULL)
+ if (b->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;
+ s = b->cond_string;
b->cond_exp = parse_exp_1 (&s, 0, b->cond_exp_valid_block, 0);
}
}
the target gains execution, through breakpoint_re_set. */
if (!can_use_hw_watchpoints)
{
- if (b->base.ops->works_in_software_mode (&b->base))
- b->base.type = bp_watchpoint;
+ if (b->ops->works_in_software_mode (b))
+ b->type = bp_watchpoint;
else
error (_("Can't set read/access watchpoint when "
"hardware watchpoints are disabled."));
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
happens, the code that reports it updates b->val directly.
We don't keep track of the memory value for masked
watchpoints. */
- if (!b->val_valid && !is_masked_watchpoint (&b->base))
+ if (!b->val_valid && !is_masked_watchpoint (b))
{
if (b->val_bitsize != 0)
{
}
type = hw_write;
- if (b->base.type == bp_read_watchpoint)
+ if (b->type == bp_read_watchpoint)
type = hw_read;
- else if (b->base.type == bp_access_watchpoint)
+ else if (b->type == bp_access_watchpoint)
type = hw_access;
- loc = allocate_bp_location (&b->base);
- for (tmp = &(b->base.loc); *tmp != NULL; tmp = &((*tmp)->next))
+ loc = allocate_bp_location (b);
+ for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
;
*tmp = loc;
loc->gdbarch = get_type_arch (value_type (v));
/* If this is a software watchpoint, we try to turn it
to a hardware one -- count resources as if B was of
hardware watchpoint type. */
- type = b->base.type;
+ type = b->type;
if (type == bp_watchpoint)
type = bp_hardware_watchpoint;
manually. */
/* Count resources used by all watchpoints except B. */
- i = hw_watchpoint_used_count_others (&b->base, type, &other_type_used);
+ i = hw_watchpoint_used_count_others (b, type, &other_type_used);
/* Add in the resources needed for B. */
- i += hw_watchpoint_use_count (&b->base);
+ i += hw_watchpoint_use_count (b);
target_resources_ok
= target_can_use_hardware_watchpoint (type, i, other_type_used);
if (target_resources_ok <= 0)
{
- int sw_mode = b->base.ops->works_in_software_mode (&b->base);
+ int sw_mode = b->ops->works_in_software_mode (b);
if (target_resources_ok == 0 && !sw_mode)
error (_("Target does not support this type of "
"resources for this watchpoint."));
/* Downgrade to software watchpoint. */
- b->base.type = bp_watchpoint;
+ b->type = bp_watchpoint;
}
else
{
found we have enough resources to turn it to a
hardware watchpoint. Otherwise, this is a
nop. */
- b->base.type = type;
+ b->type = type;
}
}
- else if (!b->base.ops->works_in_software_mode (&b->base))
+ else if (!b->ops->works_in_software_mode (b))
{
if (!can_use_hw_watchpoints)
error (_("Can't set read/access watchpoint when "
"read/access watchpoint."));
}
else
- b->base.type = bp_watchpoint;
+ b->type = bp_watchpoint;
- loc_type = (b->base.type == bp_watchpoint? bp_loc_other
+ loc_type = (b->type == bp_watchpoint? bp_loc_other
: bp_loc_hardware_watchpoint);
- for (bl = b->base.loc; bl; bl = bl->next)
+ for (bl = b->loc; bl; bl = bl->next)
bl->loc_type = loc_type;
}
above left it without any location set up. But,
bpstat_stop_status requires a location to be able to report
stops, so make sure there's at least a dummy one. */
- if (b->base.type == bp_watchpoint && b->base.loc == NULL)
- software_watchpoint_add_no_memory_location (&b->base, frame_pspace);
+ if (b->type == bp_watchpoint && b->loc == NULL)
+ software_watchpoint_add_no_memory_location (b, frame_pspace);
}
else if (!within_current_scope)
{
printf_filtered (_("\
Watchpoint %d deleted because the program has left the block\n\
in which its expression is valid.\n"),
- b->base.number);
+ b->number);
watchpoint_del_at_next_stop (b);
}
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)
int hw_breakpoint_error = 0;
int hw_bp_details_reported = 0;
- struct ui_file *tmp_error_stream = mem_fileopen ();
- struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_error_stream);
+ string_file tmp_error_stream;
/* Explicitly mark the warning -- this will only be printed if
there was an error. */
- fprintf_unfiltered (tmp_error_stream, "Warning:\n");
+ tmp_error_stream.puts ("Warning:\n");
- save_current_space_and_thread ();
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
ALL_BP_LOCATIONS (bl, blp_tmp)
{
&& ptid_equal (inferior_ptid, null_ptid))
continue;
- val = insert_bp_location (bl, tmp_error_stream, &disabled_breaks,
+ val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
&hw_breakpoint_error, &hw_bp_details_reported);
if (val)
error_flag = val;
target_terminal_ours_for_output ();
error_stream (tmp_error_stream);
}
-
- do_cleanups (cleanups);
}
/* Used when starting or continuing the program. */
int hw_breakpoint_error = 0;
int hw_bp_error_explained_already = 0;
- struct ui_file *tmp_error_stream = mem_fileopen ();
- struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_error_stream);
-
+ string_file tmp_error_stream;
+
/* Explicitly mark the warning -- this will only be printed if
there was an error. */
- fprintf_unfiltered (tmp_error_stream, "Warning:\n");
+ tmp_error_stream.puts ("Warning:\n");
- save_current_space_and_thread ();
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
ALL_BP_LOCATIONS (bl, blp_tmp)
{
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);
&& ptid_equal (inferior_ptid, null_ptid))
continue;
- val = insert_bp_location (bl, tmp_error_stream, &disabled_breaks,
+ val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
&hw_breakpoint_error, &hw_bp_error_explained_already);
if (val)
error_flag = val;
{
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,
- "Could not insert hardware watchpoint %d.\n",
- bpt->number);
+ tmp_error_stream.printf ("Could not insert "
+ "hardware watchpoint %d.\n",
+ bpt->number);
error_flag = -1;
}
}
message about possibly exhausted resources. */
if (hw_breakpoint_error && !hw_bp_error_explained_already)
{
- fprintf_unfiltered (tmp_error_stream,
- "Could not insert hardware breakpoints:\n\
+ tmp_error_stream.printf ("Could not insert hardware breakpoints:\n\
You may have requested too many hardware breakpoints/watchpoints.\n");
}
target_terminal_ours_for_output ();
error_stream (tmp_error_stream);
}
-
- do_cleanups (cleanups);
}
/* Used when the program stops.
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;
}
struct cleanup *old_chain;
struct bp_location *bl, **blp_tmp;
int val;
- struct ui_file *tmp_error_stream;
int dummy1 = 0, dummy2 = 0, dummy3 = 0;
struct inferior *inf;
struct thread_info *tp;
inferior_ptid = tp->ptid;
- tmp_error_stream = mem_fileopen ();
- make_cleanup_ui_file_delete (tmp_error_stream);
+ string_file tmp_error_stream;
ALL_BP_LOCATIONS (bl, blp_tmp)
{
if (bl->inserted)
{
bl->inserted = 0;
- val = insert_bp_location (bl, tmp_error_stream, &dummy1, &dummy2, &dummy3);
+ val = insert_bp_location (bl, &tmp_error_stream, &dummy1, &dummy2, &dummy3);
if (val != 0)
{
do_cleanups (old_chain);
overlay_events_enabled = 0;
}
}
- update_global_location_list (UGLL_MAY_INSERT);
}
static void
create_longjmp_master_breakpoint (void)
{
struct program_space *pspace;
- struct cleanup *old_chain;
- old_chain = save_current_program_space ();
+ scoped_restore_current_program_space restore_pspace;
ALL_PSPACES (pspace)
{
objfile),
bp_longjmp_master,
&internal_breakpoint_ops);
- b->location
- = new_probe_location ("-probe-stap libc:longjmp");
+ b->location = new_probe_location ("-probe-stap libc:longjmp");
b->enable_state = bp_disabled;
}
}
}
}
- update_global_location_list (UGLL_MAY_INSERT);
-
- do_cleanups (old_chain);
}
/* Create a master std::terminate breakpoint. */
create_std_terminate_master_breakpoint (void)
{
struct program_space *pspace;
- struct cleanup *old_chain;
const char *const func_name = "std::terminate()";
- old_chain = save_current_program_space ();
+ scoped_restore_current_program_space restore_pspace;
ALL_PSPACES (pspace)
{
b->enable_state = bp_disabled;
}
}
-
- update_global_location_list (UGLL_MAY_INSERT);
-
- do_cleanups (old_chain);
}
/* Install a master breakpoint on the unwinder's debug hook. */
objfile),
bp_exception_master,
&internal_breakpoint_ops);
- b->location
- = new_probe_location ("-probe-stap libgcc:unwind");
+ b->location = new_probe_location ("-probe-stap libgcc:unwind");
b->enable_state = bp_disabled;
}
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.get ());
}
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;
-
/* BL is never in moribund_locations by our callers. */
gdb_assert (bl->owner != NULL);
This should not ever happen. */
gdb_assert (bl->owner->type != bp_none);
- old_chain = save_current_space_and_thread ();
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
switch_to_program_space_and_thread (bl->pspace);
- ret = remove_breakpoint_1 (bl, is);
-
- do_cleanups (old_chain);
- return ret;
+ return remove_breakpoint_1 (bl, REMOVE_BREAKPOINT);
}
/* Clear the "inserted" flag in all breakpoints. */
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;
}
executing_breakpoint_commands = 1;
old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
- prevent_dont_repeat ();
+ scoped_restore preventer = prevent_dont_repeat ();
/* This pointer will iterate over the list of bpstat's. */
bs = *bsp;
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 (uiout->is_mi_like_p ())
+ return;
+
+ uiout->text ("\n");
+
+ if (show_thread_that_caused_stop ())
+ {
+ const char *name;
+ struct thread_info *thr = inferior_thread ();
+
+ uiout->text ("Thread ");
+ uiout->field_fmt ("thread-id", "%s", print_thread_id (thr));
+
+ name = thr->name != NULL ? thr->name : target_thread_name (thr);
+ if (name != NULL)
+ {
+ uiout->text (" \"");
+ uiout->field_fmt ("name", "%s", name);
+ uiout->text ("\"");
+ }
+
+ uiout->text (" 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
if (!is_catchpoint)
{
if (any_added || any_deleted)
- ui_out_text (current_uiout,
- _("Stopped due to shared library event:\n"));
+ current_uiout->text (_("Stopped due to shared library event:\n"));
else
- ui_out_text (current_uiout,
- _("Stopped due to shared library event (no "
- "libraries added or removed)\n"));
+ current_uiout->text (_("Stopped due to shared library event (no "
+ "libraries added or removed)\n"));
}
- if (ui_out_is_mi_like_p (current_uiout))
- ui_out_field_string (current_uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT));
+ if (current_uiout->is_mi_like_p ())
+ current_uiout->field_string ("reason",
+ async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT));
if (any_deleted)
{
- struct cleanup *cleanup;
char *name;
int ix;
- ui_out_text (current_uiout, _(" Inferior unloaded "));
- cleanup = make_cleanup_ui_out_list_begin_end (current_uiout,
- "removed");
+ current_uiout->text (_(" Inferior unloaded "));
+ ui_out_emit_list list_emitter (current_uiout, "removed");
for (ix = 0;
VEC_iterate (char_ptr, current_program_space->deleted_solibs,
ix, name);
++ix)
{
if (ix > 0)
- ui_out_text (current_uiout, " ");
- ui_out_field_string (current_uiout, "library", name);
- ui_out_text (current_uiout, "\n");
+ current_uiout->text (" ");
+ current_uiout->field_string ("library", name);
+ current_uiout->text ("\n");
}
-
- do_cleanups (cleanup);
}
if (any_added)
{
struct so_list *iter;
int ix;
- struct cleanup *cleanup;
- ui_out_text (current_uiout, _(" Inferior loaded "));
- cleanup = make_cleanup_ui_out_list_begin_end (current_uiout,
- "added");
+ current_uiout->text (_(" Inferior loaded "));
+ ui_out_emit_list list_emitter (current_uiout, "added");
for (ix = 0;
VEC_iterate (so_list_ptr, current_program_space->added_solibs,
ix, iter);
++ix)
{
if (ix > 0)
- ui_out_text (current_uiout, " ");
- ui_out_field_string (current_uiout, "library", iter->so_name);
- ui_out_text (current_uiout, "\n");
+ current_uiout->text (" ");
+ current_uiout->field_string ("library", iter->so_name);
+ current_uiout->text ("\n");
}
-
- do_cleanups (cleanup);
}
}
struct value *mark;
struct value *new_val;
- if (is_masked_watchpoint (&b->base))
+ if (is_masked_watchpoint (b))
/* Since we don't know the exact trigger address (from
stopped_data_address), just tell the user we've triggered
a mask watchpoint. */
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 (uiout->is_mi_like_p ())
+ uiout->field_string
+ ("reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
+ uiout->text ("\nWatchpoint ");
+ uiout->field_int ("wpnum", b->number);
+ uiout->text (" 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);
+ decref_counted_command_line (&b->commands);
watchpoint_del_at_next_stop (b);
return WP_DELETED;
{
int must_check_value = 0;
- if (b->base.type == bp_watchpoint)
+ if (b->type == bp_watchpoint)
/* For a software watchpoint, we must always check the
watched value. */
must_check_value = 1;
this watchpoint. */
must_check_value = 1;
else if (b->watchpoint_triggered == watch_triggered_unknown
- && b->base.type == bp_hardware_watchpoint)
+ && b->type == bp_hardware_watchpoint)
/* We were stopped by a hardware watchpoint, but the target could
not report the data address. We must check the watchpoint's
value. Access and read watchpoints are out of luck; without
{
char *message
= xstrprintf ("Error evaluating expression for watchpoint %d\n",
- b->base.number);
+ b->number);
struct cleanup *cleanups = make_cleanup (xfree, message);
int e = catch_errors (watchpoint_check, bs, message,
RETURN_MASK_ALL);
bs->stop = 0;
break;
case WP_VALUE_CHANGED:
- if (b->base.type == bp_read_watchpoint)
+ if (b->type == bp_read_watchpoint)
{
/* There are two cases to consider here:
}
break;
case WP_VALUE_NOT_CHANGED:
- if (b->base.type == bp_hardware_watchpoint
- || b->base.type == bp_watchpoint)
+ if (b->type == bp_hardware_watchpoint
+ || b->type == bp_watchpoint)
{
/* Don't stop: write watchpoints shouldn't fire if
the value hasn't changed. */
/* 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->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;
{
static char wrap_indent[80];
int i, total_width, width, align;
- char *text;
+ const char *text;
total_width = 0;
- for (i = 1; ui_out_query_field (uiout, i, &width, &align, &text); i++)
+ for (i = 1; uiout->query_table_field (i, &width, &align, &text); i++)
{
if (strcmp (text, col_name) == 0)
{
struct bp_location *loc)
{
struct ui_out *uiout = current_uiout;
- struct cleanup *old_chain = save_current_program_space ();
+
+ scoped_restore_current_program_space restore_pspace;
if (loc != NULL && loc->shlib_disabled)
loc = NULL;
set_current_program_space (loc->pspace);
if (b->display_canonical)
- ui_out_field_string (uiout, "what",
- event_location_to_string (b->location));
+ uiout->field_string ("what", event_location_to_string (b->location.get ()));
else if (loc && loc->symtab)
{
struct symbol *sym
= find_pc_sect_function (loc->address, loc->section);
if (sym)
{
- ui_out_text (uiout, "in ");
- ui_out_field_string (uiout, "func",
- SYMBOL_PRINT_NAME (sym));
- ui_out_text (uiout, " ");
- ui_out_wrap_hint (uiout, wrap_indent_at_field (uiout, "what"));
- ui_out_text (uiout, "at ");
+ uiout->text ("in ");
+ uiout->field_string ("func", SYMBOL_PRINT_NAME (sym));
+ uiout->text (" ");
+ uiout->wrap_hint (wrap_indent_at_field (uiout, "what"));
+ uiout->text ("at ");
}
- ui_out_field_string (uiout, "file",
+ uiout->field_string ("file",
symtab_to_filename_for_display (loc->symtab));
- ui_out_text (uiout, ":");
+ uiout->text (":");
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "fullname",
- symtab_to_fullname (loc->symtab));
+ if (uiout->is_mi_like_p ())
+ uiout->field_string ("fullname", symtab_to_fullname (loc->symtab));
- ui_out_field_int (uiout, "line", loc->line_number);
+ uiout->field_int ("line", loc->line_number);
}
else if (loc)
{
- struct ui_file *stb = mem_fileopen ();
- struct cleanup *stb_chain = make_cleanup_ui_file_delete (stb);
+ string_file stb;
- print_address_symbolic (loc->gdbarch, loc->address, stb,
+ print_address_symbolic (loc->gdbarch, loc->address, &stb,
demangle, "");
- ui_out_field_stream (uiout, "at", stb);
-
- do_cleanups (stb_chain);
+ uiout->field_stream ("at", stb);
}
else
{
- ui_out_field_string (uiout, "pending",
- event_location_to_string (b->location));
+ uiout->field_string ("pending",
+ event_location_to_string (b->location.get ()));
/* If extra_string is available, it could be holding a condition
or dprintf arguments. In either case, make sure it is printed,
too, but only for non-MI streams. */
- if (!ui_out_is_mi_like_p (uiout) && b->extra_string != NULL)
+ if (!uiout->is_mi_like_p () && b->extra_string != NULL)
{
if (b->type == bp_dprintf)
- ui_out_text (uiout, ",");
+ uiout->text (",");
else
- ui_out_text (uiout, " ");
- ui_out_text (uiout, b->extra_string);
+ uiout->text (" ");
+ uiout->text (b->extra_string);
}
}
&& breakpoint_condition_evaluation_mode () == condition_evaluation_target
&& bp_condition_evaluator (b) == condition_evaluation_both)
{
- ui_out_text (uiout, " (");
- ui_out_field_string (uiout, "evaluated-by",
+ uiout->text (" (");
+ uiout->field_string ("evaluated-by",
bp_location_condition_evaluator (loc));
- ui_out_text (uiout, ")");
+ uiout->text (")");
}
-
- do_cleanups (old_chain);
}
static const char *
struct ep_type_description
{
enum bptype type;
- char *description;
+ const char *description;
};
static struct ep_type_description bptypes[] =
{
VEC(int) *inf_num,
int mi_only)
{
- struct cleanup *back_to;
- int is_mi = ui_out_is_mi_like_p (uiout);
+ int is_mi = uiout->is_mi_like_p ();
int inf;
int i;
if (!is_mi && mi_only)
return;
- back_to = make_cleanup_ui_out_list_begin_end (uiout, field_name);
+ ui_out_emit_list list_emitter (uiout, field_name);
for (i = 0; VEC_iterate (int, inf_num, i, inf); ++i)
{
char mi_group[10];
xsnprintf (mi_group, sizeof (mi_group), "i%d", inf);
- ui_out_field_string (uiout, NULL, mi_group);
+ uiout->field_string (NULL, mi_group);
}
else
{
if (i == 0)
- ui_out_text (uiout, " inf ");
+ uiout->text (" inf ");
else
- ui_out_text (uiout, ", ");
+ uiout->text (", ");
- ui_out_text (uiout, plongest (inf));
+ uiout->text (plongest (inf));
}
}
-
- do_cleanups (back_to);
}
/* Print B to gdb_stdout. */
{
char *formatted;
formatted = xstrprintf ("%d.%d", b->number, loc_number);
- ui_out_field_string (uiout, "number", formatted);
+ uiout->field_string ("number", formatted);
xfree (formatted);
}
else
{
- ui_out_field_int (uiout, "number", b->number);
+ uiout->field_int ("number", b->number);
}
/* 2 */
annotate_field (1);
if (part_of_multiple)
- ui_out_field_skip (uiout, "type");
+ uiout->field_skip ("type");
else
- ui_out_field_string (uiout, "type", bptype_string (b->type));
+ uiout->field_string ("type", bptype_string (b->type));
/* 3 */
annotate_field (2);
if (part_of_multiple)
- ui_out_field_skip (uiout, "disp");
+ uiout->field_skip ("disp");
else
- ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+ uiout->field_string ("disp", bpdisp_text (b->disposition));
/* 4 */
annotate_field (3);
if (part_of_multiple)
- ui_out_field_string (uiout, "enabled", loc->enabled ? "y" : "n");
+ uiout->field_string ("enabled", loc->enabled ? "y" : "n");
else
- ui_out_field_fmt (uiout, "enabled", "%c",
- bpenables[(int) b->enable_state]);
- ui_out_spaces (uiout, 2);
+ uiout->field_fmt ("enabled", "%c", bpenables[(int) b->enable_state]);
+ uiout->spaces (2);
/* 5 and 6 */
not line up too nicely with the headers, but the effect
is relatively readable). */
if (opts.addressprint)
- ui_out_field_skip (uiout, "addr");
+ uiout->field_skip ("addr");
annotate_field (5);
- ui_out_field_string (uiout, "what", w->exp_string);
+ uiout->field_string ("what", w->exp_string);
}
break;
{
annotate_field (4);
if (header_of_multiple)
- ui_out_field_string (uiout, "addr", "<MULTIPLE>");
+ uiout->field_string ("addr", "<MULTIPLE>");
else if (b->loc == NULL || loc->shlib_disabled)
- ui_out_field_string (uiout, "addr", "<PENDING>");
+ uiout->field_string ("addr", "<PENDING>");
else
- ui_out_field_core_addr (uiout, "addr",
+ uiout->field_core_addr ("addr",
loc->gdbarch, loc->address);
}
annotate_field (5);
{
/* FIXME: This seems to be redundant and lost here; see the
"stop only in" line a little further down. */
- ui_out_text (uiout, " thread ");
- ui_out_field_int (uiout, "thread", b->thread);
+ uiout->text (" thread ");
+ uiout->field_int ("thread", b->thread);
}
else if (b->task != 0)
{
- ui_out_text (uiout, " task ");
- ui_out_field_int (uiout, "task", b->task);
+ uiout->text (" task ");
+ uiout->field_int ("task", b->task);
}
}
- ui_out_text (uiout, "\n");
+ uiout->text ("\n");
if (!part_of_multiple)
b->ops->print_one_detail (b, uiout);
if (part_of_multiple && frame_id_p (b->frame_id))
{
annotate_field (6);
- ui_out_text (uiout, "\tstop only in stack frame at ");
+ uiout->text ("\tstop only in stack frame at ");
/* FIXME: cagney/2002-12-01: Shouldn't be poking around inside
the frame ID. */
- ui_out_field_core_addr (uiout, "frame",
+ uiout->field_core_addr ("frame",
b->gdbarch, b->frame_id.stack_addr);
- ui_out_text (uiout, "\n");
+ uiout->text ("\n");
}
if (!part_of_multiple && b->cond_string)
{
annotate_field (7);
if (is_tracepoint (b))
- ui_out_text (uiout, "\ttrace only if ");
+ uiout->text ("\ttrace only if ");
else
- ui_out_text (uiout, "\tstop only if ");
- ui_out_field_string (uiout, "cond", b->cond_string);
+ uiout->text ("\tstop only if ");
+ uiout->field_string ("cond", b->cond_string);
/* Print whether the target is doing the breakpoint's condition
evaluation. If GDB is doing the evaluation, don't print anything. */
&& breakpoint_condition_evaluation_mode ()
== condition_evaluation_target)
{
- ui_out_text (uiout, " (");
- ui_out_field_string (uiout, "evaluated-by",
+ uiout->text (" (");
+ uiout->field_string ("evaluated-by",
bp_condition_evaluator (b));
- ui_out_text (uiout, " evals)");
+ uiout->text (" evals)");
}
- ui_out_text (uiout, "\n");
+ uiout->text ("\n");
}
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));
- ui_out_text (uiout, "\n");
+ uiout->text ("\tstop only in thread ");
+ if (uiout->is_mi_like_p ())
+ uiout->field_int ("thread", b->thread);
+ else
+ {
+ struct thread_info *thr = find_thread_global_id (b->thread);
+
+ uiout->field_string ("thread", print_thread_id (thr));
+ }
+ uiout->text ("\n");
}
if (!part_of_multiple)
{
/* FIXME should make an annotation for this. */
if (is_catchpoint (b))
- ui_out_text (uiout, "\tcatchpoint");
+ uiout->text ("\tcatchpoint");
else if (is_tracepoint (b))
- ui_out_text (uiout, "\ttracepoint");
+ uiout->text ("\ttracepoint");
else
- ui_out_text (uiout, "\tbreakpoint");
- ui_out_text (uiout, " already hit ");
- ui_out_field_int (uiout, "times", b->hit_count);
+ uiout->text ("\tbreakpoint");
+ uiout->text (" already hit ");
+ uiout->field_int ("times", b->hit_count);
if (b->hit_count == 1)
- ui_out_text (uiout, " time\n");
+ uiout->text (" time\n");
else
- ui_out_text (uiout, " times\n");
+ uiout->text (" times\n");
}
else
{
/* Output the count also if it is zero, but only if this is mi. */
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_int (uiout, "times", b->hit_count);
+ if (uiout->is_mi_like_p ())
+ uiout->field_int ("times", b->hit_count);
}
}
if (!part_of_multiple && b->ignore_count)
{
annotate_field (8);
- ui_out_text (uiout, "\tignore next ");
- ui_out_field_int (uiout, "ignore", b->ignore_count);
- ui_out_text (uiout, " hits\n");
+ uiout->text ("\tignore next ");
+ uiout->field_int ("ignore", b->ignore_count);
+ uiout->text (" hits\n");
}
/* Note that an enable count of 1 corresponds to "enable once"
if (!part_of_multiple && b->enable_count > 1)
{
annotate_field (8);
- ui_out_text (uiout, "\tdisable after ");
+ uiout->text ("\tdisable after ");
/* Tweak the wording to clarify that ignore and enable counts
are distinct, and have additive effect. */
if (b->ignore_count)
- ui_out_text (uiout, "additional ");
+ uiout->text ("additional ");
else
- ui_out_text (uiout, "next ");
- ui_out_field_int (uiout, "enable", b->enable_count);
- ui_out_text (uiout, " hits\n");
+ uiout->text ("next ");
+ uiout->field_int ("enable", b->enable_count);
+ uiout->text (" hits\n");
}
if (!part_of_multiple && is_tracepoint (b))
if (tp->traceframe_usage)
{
- ui_out_text (uiout, "\ttrace buffer usage ");
- ui_out_field_int (uiout, "traceframe-usage", tp->traceframe_usage);
- ui_out_text (uiout, " bytes\n");
+ uiout->text ("\ttrace buffer usage ");
+ uiout->field_int ("traceframe-usage", tp->traceframe_usage);
+ uiout->text (" bytes\n");
}
}
l = b->commands ? b->commands->commands : NULL;
if (!part_of_multiple && l)
{
- struct cleanup *script_chain;
-
annotate_field (9);
- script_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "script");
+ ui_out_emit_tuple tuple_emitter (uiout, "script");
print_command_lines (uiout, l, 4);
- do_cleanups (script_chain);
}
if (is_tracepoint (b))
if (!part_of_multiple && t->pass_count)
{
annotate_field (10);
- ui_out_text (uiout, "\tpass count ");
- ui_out_field_int (uiout, "pass", t->pass_count);
- ui_out_text (uiout, " \n");
+ uiout->text ("\tpass count ");
+ uiout->field_int ("pass", t->pass_count);
+ uiout->text (" \n");
}
/* Don't display it when tracepoint or tracepoint location is
{
annotate_field (11);
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "installed",
+ if (uiout->is_mi_like_p ())
+ uiout->field_string ("installed",
loc->inserted ? "y" : "n");
else
{
if (loc->inserted)
- ui_out_text (uiout, "\t");
+ uiout->text ("\t");
else
- ui_out_text (uiout, "\tnot ");
- ui_out_text (uiout, "installed on target\n");
+ uiout->text ("\tnot ");
+ uiout->text ("installed on target\n");
}
}
}
- if (ui_out_is_mi_like_p (uiout) && !part_of_multiple)
+ if (uiout->is_mi_like_p () && !part_of_multiple)
{
if (is_watchpoint (b))
{
struct watchpoint *w = (struct watchpoint *) b;
- ui_out_field_string (uiout, "original-location", w->exp_string);
+ uiout->field_string ("original-location", w->exp_string);
}
else if (b->location != NULL
- && event_location_to_string (b->location) != NULL)
- ui_out_field_string (uiout, "original-location",
- event_location_to_string (b->location));
+ && event_location_to_string (b->location.get ()) != NULL)
+ uiout->field_string ("original-location",
+ event_location_to_string (b->location.get ()));
}
}
struct bp_location **last_loc,
int allflag)
{
- struct cleanup *bkpt_chain;
struct ui_out *uiout = current_uiout;
- bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt");
+ {
+ ui_out_emit_tuple tuple_emitter (uiout, "bkpt");
- print_one_breakpoint_location (b, NULL, 0, last_loc, allflag);
- do_cleanups (bkpt_chain);
+ print_one_breakpoint_location (b, NULL, 0, last_loc, allflag);
+ }
/* If this breakpoint has custom print function,
it's already printed. Otherwise, print individual
for (loc = b->loc; loc; loc = loc->next, ++n)
{
- struct cleanup *inner2 =
- make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+ ui_out_emit_tuple tuple_emitter (uiout, NULL);
print_one_breakpoint_location (b, loc, n, last_loc, allflag);
- do_cleanups (inner2);
}
}
}
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
annotate_breakpoints_headers ();
if (nr_printable_breakpoints > 0)
annotate_field (0);
- ui_out_table_header (uiout, 7, ui_left, "number", "Num"); /* 1 */
+ uiout->table_header (7, ui_left, "number", "Num"); /* 1 */
if (nr_printable_breakpoints > 0)
annotate_field (1);
- ui_out_table_header (uiout, print_type_col_width, ui_left,
- "type", "Type"); /* 2 */
+ uiout->table_header (print_type_col_width, ui_left, "type", "Type"); /* 2 */
if (nr_printable_breakpoints > 0)
annotate_field (2);
- ui_out_table_header (uiout, 4, ui_left, "disp", "Disp"); /* 3 */
+ uiout->table_header (4, ui_left, "disp", "Disp"); /* 3 */
if (nr_printable_breakpoints > 0)
annotate_field (3);
- ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); /* 4 */
+ uiout->table_header (3, ui_left, "enabled", "Enb"); /* 4 */
if (opts.addressprint)
{
if (nr_printable_breakpoints > 0)
annotate_field (4);
if (print_address_bits <= 32)
- ui_out_table_header (uiout, 10, ui_left,
- "addr", "Address"); /* 5 */
+ uiout->table_header (10, ui_left, "addr", "Address"); /* 5 */
else
- ui_out_table_header (uiout, 18, ui_left,
- "addr", "Address"); /* 5 */
+ uiout->table_header (18, ui_left, "addr", "Address"); /* 5 */
}
if (nr_printable_breakpoints > 0)
annotate_field (5);
- ui_out_table_header (uiout, 40, ui_noalign, "what", "What"); /* 6 */
- ui_out_table_body (uiout);
+ uiout->table_header (40, ui_noalign, "what", "What"); /* 6 */
+ uiout->table_body ();
if (nr_printable_breakpoints > 0)
annotate_breakpoints_table ();
if (!filter)
{
if (args == NULL || *args == '\0')
- ui_out_message (uiout, 0, "No breakpoints or watchpoints.\n");
+ uiout->message ("No breakpoints or watchpoints.\n");
else
- ui_out_message (uiout, 0,
- "No breakpoint or watchpoint matching '%s'.\n",
+ uiout->message ("No breakpoint or watchpoint matching '%s'.\n",
args);
}
}
/* The following phrase lines up nicely with per-tracepoint collect
actions. */
- ui_out_text (uiout, "default collect ");
- ui_out_field_string (uiout, "default-collect", default_collect);
- ui_out_text (uiout, " \n");
+ uiout->text ("default collect ");
+ uiout->field_string ("default-collect", default_collect);
+ uiout->text (" \n");
}
static void
if (num_printed == 0)
{
if (args == NULL || *args == '\0')
- ui_out_message (uiout, 0, "No watchpoints.\n");
+ uiout->message ("No watchpoints.\n");
else
- ui_out_message (uiout, 0, "No watchpoint matching '%s'.\n", args);
+ uiout->message ("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
}
}
-void
-init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops,
- struct breakpoint *owner)
+bp_location::bp_location (const bp_location_ops *ops, breakpoint *owner)
{
- memset (loc, 0, sizeof (*loc));
+ bp_location *loc = this;
gdb_assert (ops != NULL);
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)
{
- memset (b, 0, sizeof (*b));
-
gdb_assert (ops != NULL);
b->ops = ops;
b->gdbarch = gdbarch;
b->language = current_language->la_language;
b->input_radix = input_radix;
- b->thread = -1;
- b->enable_state = bp_enabled;
- b->next = 0;
- b->silent = 0;
- b->ignore_count = 0;
- b->commands = NULL;
- b->frame_id = null_frame_id;
- b->condition_not_parsed = 0;
- b->py_bp_object = NULL;
b->related_breakpoint = b;
- b->location = NULL;
}
/* Helper to set_raw_breakpoint below. Creates a breakpoint
enum bptype bptype,
const struct breakpoint_ops *ops)
{
- struct breakpoint *b = XNEW (struct breakpoint);
+ std::unique_ptr<breakpoint> b = new_breakpoint_from_type (bptype);
- init_raw_breakpoint_without_location (b, gdbarch, bptype, ops);
- add_to_breakpoint_chain (b);
- return b;
+ init_raw_breakpoint_without_location (b.get (), gdbarch, bptype, ops);
+ add_to_breakpoint_chain (b.get ());
+
+ return b.release ();
}
/* Initialize loc->function_name. EXPLICIT_LOC says no indirect function
struct symtab_and_line sal, enum bptype bptype,
const struct breakpoint_ops *ops)
{
- struct breakpoint *b = XNEW (struct breakpoint);
+ std::unique_ptr<breakpoint> b = new_breakpoint_from_type (bptype);
- init_raw_breakpoint (b, gdbarch, sal, bptype, ops);
- add_to_breakpoint_chain (b);
- return b;
+ init_raw_breakpoint (b.get (), gdbarch, sal, bptype, ops);
+ add_to_breakpoint_chain (b.get ());
+
+ return b.release ();
}
/* Call this routine when stepping and nexting to enable a breakpoint
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
/* longjmp_breakpoint_ops ensures INITIATING_FRAME is cleared again
after their removal. */
clone = momentary_breakpoint_from_master (b, type,
- &longjmp_breakpoint_ops, 1);
+ &momentary_breakpoint_ops, 1);
clone->thread = thread;
}
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). */
struct bp_location *loc, **locp_tmp;
int disabled_shlib_breaks = 0;
- /* SunOS a.out shared libraries are always mapped, so do not
- disable breakpoints; they will only be reported as unloaded
- through clear_solib when GDB discards its shared library
- list. See clear_solib for more information. */
- if (exec_bfd != NULL
- && bfd_get_flavour (exec_bfd) == bfd_target_aout_flavour)
- return;
-
ALL_BP_LOCATIONS (loc, locp_tmp)
{
/* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */
/* FORK & VFORK catchpoints. */
/* An instance of this type is used to represent a fork or vfork
- catchpoint. It includes a "struct breakpoint" as a kind of base
- class; users downcast to "struct breakpoint *" when needed. A
- breakpoint is really of this type iff its ops pointer points to
- CATCH_FORK_BREAKPOINT_OPS. */
+ catchpoint. A breakpoint is really of this type iff its ops pointer points
+ to CATCH_FORK_BREAKPOINT_OPS. */
-struct fork_catchpoint
+struct fork_catchpoint : public breakpoint
{
- /* The base class. */
- struct breakpoint base;
-
/* Process id of a child process whose forking triggered this
catchpoint. This field is only valid immediately after this
catchpoint has triggered. */
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 ");
+ uiout->text ("Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
- if (ui_out_is_mi_like_p (uiout))
+ uiout->text ("Catchpoint ");
+ if (uiout->is_mi_like_p ())
{
- ui_out_field_string (uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_FORK));
- ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+ uiout->field_string ("reason", async_reason_lookup (EXEC_ASYNC_FORK));
+ uiout->field_string ("disp", bpdisp_text (b->disposition));
}
- ui_out_field_int (uiout, "bkptno", b->number);
- ui_out_text (uiout, " (forked process ");
- ui_out_field_int (uiout, "newpid", ptid_get_pid (c->forked_inferior_pid));
- ui_out_text (uiout, "), ");
+ uiout->field_int ("bkptno", b->number);
+ uiout->text (" (forked process ");
+ uiout->field_int ("newpid", ptid_get_pid (c->forked_inferior_pid));
+ uiout->text ("), ");
return PRINT_SRC_AND_LOC;
}
line up too nicely with the headers, but the effect is relatively
readable). */
if (opts.addressprint)
- ui_out_field_skip (uiout, "addr");
+ uiout->field_skip ("addr");
annotate_field (5);
- ui_out_text (uiout, "fork");
+ uiout->text ("fork");
if (!ptid_equal (c->forked_inferior_pid, null_ptid))
{
- ui_out_text (uiout, ", process ");
- ui_out_field_int (uiout, "what",
- ptid_get_pid (c->forked_inferior_pid));
- ui_out_spaces (uiout, 1);
+ uiout->text (", process ");
+ uiout->field_int ("what", ptid_get_pid (c->forked_inferior_pid));
+ uiout->spaces (1);
}
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "catch-type", "fork");
+ if (uiout->is_mi_like_p ())
+ uiout->field_string ("catch-type", "fork");
}
/* Implement the "print_mention" breakpoint_ops method for fork
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 ");
+ uiout->text ("Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
- if (ui_out_is_mi_like_p (uiout))
+ uiout->text ("Catchpoint ");
+ if (uiout->is_mi_like_p ())
{
- ui_out_field_string (uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_VFORK));
- ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+ uiout->field_string ("reason", async_reason_lookup (EXEC_ASYNC_VFORK));
+ uiout->field_string ("disp", bpdisp_text (b->disposition));
}
- ui_out_field_int (uiout, "bkptno", b->number);
- ui_out_text (uiout, " (vforked process ");
- ui_out_field_int (uiout, "newpid", ptid_get_pid (c->forked_inferior_pid));
- ui_out_text (uiout, "), ");
+ uiout->field_int ("bkptno", b->number);
+ uiout->text (" (vforked process ");
+ uiout->field_int ("newpid", ptid_get_pid (c->forked_inferior_pid));
+ uiout->text ("), ");
return PRINT_SRC_AND_LOC;
}
line up too nicely with the headers, but the effect is relatively
readable). */
if (opts.addressprint)
- ui_out_field_skip (uiout, "addr");
+ uiout->field_skip ("addr");
annotate_field (5);
- ui_out_text (uiout, "vfork");
+ uiout->text ("vfork");
if (!ptid_equal (c->forked_inferior_pid, null_ptid))
{
- ui_out_text (uiout, ", process ");
- ui_out_field_int (uiout, "what",
- ptid_get_pid (c->forked_inferior_pid));
- ui_out_spaces (uiout, 1);
+ uiout->text (", process ");
+ uiout->field_int ("what", ptid_get_pid (c->forked_inferior_pid));
+ uiout->spaces (1);
}
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "catch-type", "vfork");
+ if (uiout->is_mi_like_p ())
+ uiout->field_string ("catch-type", "vfork");
}
/* Implement the "print_mention" breakpoint_ops method for vfork
static struct breakpoint_ops catch_vfork_breakpoint_ops;
/* An instance of this type is used to represent an solib catchpoint.
- It includes a "struct breakpoint" as a kind of base class; users
- downcast to "struct breakpoint *" when needed. A breakpoint is
- really of this type iff its ops pointer points to
+ A breakpoint is really of this type iff its ops pointer points to
CATCH_SOLIB_BREAKPOINT_OPS. */
-struct solib_catchpoint
+struct solib_catchpoint : public breakpoint
{
- /* The base class. */
- struct breakpoint base;
+ ~solib_catchpoint () override;
/* True for "catch load", false for "catch unload". */
unsigned char is_load;
regex_t compiled;
};
-static void
-dtor_catch_solib (struct breakpoint *b)
+solib_catchpoint::~solib_catchpoint ()
{
- struct solib_catchpoint *self = (struct solib_catchpoint *) b;
-
- if (self->regex)
- regfree (&self->compiled);
- xfree (self->regex);
-
- base_breakpoint_ops.dtor (b);
+ if (this->regex)
+ regfree (&this->compiled);
+ xfree (this->regex);
}
static int
}
static int
-remove_catch_solib (struct bp_location *ignore)
+remove_catch_solib (struct bp_location *ignore, enum remove_bp_reason reason)
{
return 0;
}
if (other->type != bp_shlib_event)
continue;
- if (self->base.pspace != NULL && other->pspace != self->base.pspace)
+ if (self->pspace != NULL && other->pspace != self->pspace)
continue;
for (other_bl = other->loc; other_bl != NULL; other_bl = other_bl->next)
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 ");
+ uiout->text ("Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
- ui_out_field_int (uiout, "bkptno", b->number);
- ui_out_text (uiout, "\n");
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+ uiout->text ("Catchpoint ");
+ uiout->field_int ("bkptno", b->number);
+ uiout->text ("\n");
+ if (uiout->is_mi_like_p ())
+ uiout->field_string ("disp", bpdisp_text (b->disposition));
print_solib_event (1);
return PRINT_SRC_AND_LOC;
}
if (opts.addressprint)
{
annotate_field (4);
- ui_out_field_skip (uiout, "addr");
+ uiout->field_skip ("addr");
}
annotate_field (5);
else
msg = xstrdup (_("unload of library"));
}
- ui_out_field_string (uiout, "what", msg);
+ uiout->field_string ("what", msg);
xfree (msg);
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "catch-type",
- self->is_load ? "load" : "unload");
+ if (uiout->is_mi_like_p ())
+ uiout->field_string ("catch-type", self->is_load ? "load" : "unload");
}
static void
created in an enabled state. */
void
-add_solib_catchpoint (char *arg, int is_load, int is_temp, int enabled)
+add_solib_catchpoint (const char *arg, int is_load, int is_temp, int enabled)
{
struct solib_catchpoint *c;
struct gdbarch *gdbarch = get_current_arch ();
if (!arg)
arg = "";
- arg = skip_spaces (arg);
+ arg = skip_spaces_const (arg);
- c = XCNEW (struct solib_catchpoint);
+ c = new solib_catchpoint ();
cleanup = make_cleanup (xfree, c);
if (*arg != '\0')
}
c->is_load = is_load;
- init_catchpoint (&c->base, gdbarch, is_temp, NULL,
+ init_catchpoint (c, gdbarch, is_temp, NULL,
&catch_solib_breakpoint_ops);
- c->base.enable_state = enabled ? bp_enabled : bp_disabled;
+ c->enable_state = enabled ? bp_enabled : bp_disabled;
discard_cleanups (cleanup);
- install_breakpoint (0, &c->base, 1);
+ install_breakpoint (0, c, 1);
}
/* A helper function that does all the work for "catch load" and
void
init_catchpoint (struct breakpoint *b,
struct gdbarch *gdbarch, int tempflag,
- char *cond_string,
+ const char *cond_string,
const struct breakpoint_ops *ops)
{
struct symtab_and_line sal;
static void
create_fork_vfork_event_catchpoint (struct gdbarch *gdbarch,
- int tempflag, char *cond_string,
+ int tempflag, const 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);
+ init_catchpoint (c, gdbarch, tempflag, cond_string, ops);
c->forked_inferior_pid = null_ptid;
- install_breakpoint (0, &c->base, 1);
+ install_breakpoint (0, c, 1);
}
/* Exec catchpoints. */
/* An instance of this type is used to represent an exec catchpoint.
- It includes a "struct breakpoint" as a kind of base class; users
- downcast to "struct breakpoint *" when needed. A breakpoint is
- really of this type iff its ops pointer points to
+ A breakpoint is really of this type iff its ops pointer points to
CATCH_EXEC_BREAKPOINT_OPS. */
-struct exec_catchpoint
+struct exec_catchpoint : public breakpoint
{
- /* The base class. */
- struct breakpoint base;
+ ~exec_catchpoint () override;
/* Filename of a program whose exec triggered this catchpoint.
This field is only valid immediately after this catchpoint has
char *exec_pathname;
};
-/* Implement the "dtor" breakpoint_ops method for exec
- catchpoints. */
+/* Exec catchpoint destructor. */
-static void
-dtor_catch_exec (struct breakpoint *b)
+exec_catchpoint::~exec_catchpoint ()
{
- struct exec_catchpoint *c = (struct exec_catchpoint *) b;
-
- xfree (c->exec_pathname);
-
- base_breakpoint_ops.dtor (b);
+ xfree (this->exec_pathname);
}
static int
}
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 ");
+ uiout->text ("Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
- if (ui_out_is_mi_like_p (uiout))
+ uiout->text ("Catchpoint ");
+ if (uiout->is_mi_like_p ())
{
- ui_out_field_string (uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_EXEC));
- ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+ uiout->field_string ("reason", async_reason_lookup (EXEC_ASYNC_EXEC));
+ uiout->field_string ("disp", bpdisp_text (b->disposition));
}
- ui_out_field_int (uiout, "bkptno", b->number);
- ui_out_text (uiout, " (exec'd ");
- ui_out_field_string (uiout, "new-exec", c->exec_pathname);
- ui_out_text (uiout, "), ");
+ uiout->field_int ("bkptno", b->number);
+ uiout->text (" (exec'd ");
+ uiout->field_string ("new-exec", c->exec_pathname);
+ uiout->text ("), ");
return PRINT_SRC_AND_LOC;
}
not line up too nicely with the headers, but the effect
is relatively readable). */
if (opts.addressprint)
- ui_out_field_skip (uiout, "addr");
+ uiout->field_skip ("addr");
annotate_field (5);
- ui_out_text (uiout, "exec");
+ uiout->text ("exec");
if (c->exec_pathname != NULL)
{
- ui_out_text (uiout, ", program \"");
- ui_out_field_string (uiout, "what", c->exec_pathname);
- ui_out_text (uiout, "\" ");
+ uiout->text (", program \"");
+ uiout->field_string ("what", c->exec_pathname);
+ uiout->text ("\" ");
}
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "catch-type", "exec");
+ if (uiout->is_mi_like_p ())
+ uiout->field_string ("catch-type", "exec");
}
static void
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);
mention (struct breakpoint *b)
{
b->ops->print_mention (b);
- if (ui_out_is_mi_like_p (current_uiout))
+ if (current_uiout->is_mi_like_p ())
return;
printf_filtered ("\n");
}
static int
bp_loc_is_permanent (struct bp_location *loc)
{
- struct cleanup *cleanup;
- int retval;
-
gdb_assert (loc != NULL);
/* If we have a catchpoint or a watchpoint, just return 0. We should not
if (!breakpoint_address_is_meaningful (loc->owner))
return 0;
- cleanup = save_current_space_and_thread ();
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
switch_to_program_space_and_thread (loc->pspace);
-
- retval = program_breakpoint_here_p (loc->gdbarch, loc->address);
-
- do_cleanups (cleanup);
-
- return retval;
+ return program_breakpoint_here_p (loc->gdbarch, loc->address);
}
/* Build a command list for the dprintf corresponding to the current
printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
- breakpoint_set_commands (b, printf_cmd_line);
+ breakpoint_set_commands (b, command_line_up (printf_cmd_line));
}
}
/* 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,
struct symtabs_and_lines sals,
- struct event_location *location,
+ event_location_up &&location,
char *filter, char *cond_string,
char *extra_string,
enum bptype type, enum bpdisp disposition,
{
/* We already know the marker exists, otherwise, we
wouldn't see a sal for it. */
- const char *p = &event_location_to_string (b->location)[3];
+ const char *p
+ = &event_location_to_string (b->location.get ())[3];
const char *endp;
char *marker_str;
b->display_canonical = display_canonical;
if (location != NULL)
- b->location = location;
+ b->location = std::move (location);
else
- b->location = new_address_location (b->loc->address);
+ b->location = new_address_location (b->loc->address, NULL, 0);
b->filter = filter;
}
static void
create_breakpoint_sal (struct gdbarch *gdbarch,
struct symtabs_and_lines sals,
- struct event_location *location,
+ event_location_up &&location,
char *filter, char *cond_string,
char *extra_string,
enum bptype type, enum bpdisp disposition,
int enabled, int internal, unsigned flags,
int display_canonical)
{
- struct breakpoint *b;
- struct cleanup *old_chain;
+ std::unique_ptr<breakpoint> b = new_breakpoint_from_type (type);
- if (is_tracepoint_type (type))
- {
- struct tracepoint *t;
-
- t = XCNEW (struct tracepoint);
- b = &t->base;
- }
- else
- b = XNEW (struct breakpoint);
-
- old_chain = make_cleanup (xfree, b);
-
- init_breakpoint_sal (b, gdbarch,
- sals, location,
+ init_breakpoint_sal (b.get (), gdbarch,
+ sals, std::move (location),
filter, cond_string, extra_string,
type, disposition,
thread, task, ignore_count,
ops, from_tty,
enabled, internal, flags,
display_canonical);
- discard_cleanups (old_chain);
- install_breakpoint (internal, b, 0);
+ install_breakpoint (internal, b.release (), 0);
}
/* Add SALS.nelts breakpoints to the breakpoint table. For each
{
/* Note that 'location' can be NULL in the case of a plain
'break', without arguments. */
- struct event_location *location
+ event_location_up location
= (canonical->location != NULL
- ? copy_event_location (canonical->location) : NULL);
+ ? copy_event_location (canonical->location.get ()) : NULL);
char *filter_string = lsal->canonical ? xstrdup (lsal->canonical) : NULL;
- struct cleanup *inner = make_cleanup_delete_event_location (location);
make_cleanup (xfree, filter_string);
create_breakpoint_sal (gdbarch, lsal->sals,
- location,
+ std::move (location),
filter_string,
cond_string, extra_string,
type, disposition,
thread, task, ignore_count, ops,
from_tty, enabled, internal, flags,
canonical->special_display);
- discard_cleanups (inner);
}
}
&& 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)
unsigned flags)
{
struct linespec_result canonical;
- struct cleanup *old_chain;
struct cleanup *bkpt_chain = NULL;
int pending = 0;
int task = 0;
if (extra_string != NULL && *extra_string == '\0')
extra_string = NULL;
- init_linespec_result (&canonical);
-
TRY
{
ops->create_sals_from_location (location, &canonical, type_wanted);
if (!pending && VEC_empty (linespec_sals, canonical.sals))
return 0;
- /* Create a chain of things that always need to be cleaned up. */
- old_chain = make_cleanup_destroy_linespec_result (&canonical);
-
/* ----------------------------- SNIP -----------------------------
Anything added to the cleanup chain beyond this point is assumed
to be part of a breakpoint. If the breakpoint create succeeds
}
else
{
- struct breakpoint *b;
-
- if (is_tracepoint_type (type_wanted))
- {
- struct tracepoint *t;
-
- t = XCNEW (struct tracepoint);
- b = &t->base;
- }
- else
- b = XNEW (struct breakpoint);
+ std::unique_ptr <breakpoint> b = new_breakpoint_from_type (type_wanted);
- init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops);
+ init_raw_breakpoint_without_location (b.get (), gdbarch, type_wanted, ops);
b->location = copy_event_location (location);
if (parse_extra)
&& type_wanted != bp_hardware_breakpoint) || thread != -1)
b->pspace = current_program_space;
- install_breakpoint (internal, b, 0);
+ install_breakpoint (internal, b.release (), 0);
}
if (VEC_length (linespec_sals, canonical.sals) > 1)
/* That's it. Discard the cleanups for data inserted into the
breakpoint. */
discard_cleanups (bkpt_chain);
- /* But cleanup everything else. */
- do_cleanups (old_chain);
/* error call may happen here - have BKPT_CHAIN already discarded. */
update_global_location_list (UGLL_MAY_INSERT);
? bp_hardware_breakpoint
: bp_breakpoint);
struct breakpoint_ops *ops;
- struct event_location *location;
- struct cleanup *cleanup;
- location = string_to_event_location (&arg, current_language);
- cleanup = make_cleanup_delete_event_location (location);
+ event_location_up location = string_to_event_location (&arg, current_language);
/* Matching breakpoints on probes. */
if (location != NULL
- && event_location_type (location) == PROBE_LOCATION)
+ && event_location_type (location.get ()) == PROBE_LOCATION)
ops = &bkpt_probe_breakpoint_ops;
else
ops = &bkpt_breakpoint_ops;
create_breakpoint (get_current_arch (),
- location,
+ location.get (),
NULL, 0, arg, 1 /* parse arg */,
tempflag, type_wanted,
0 /* Ignore count */,
1 /* enabled */,
0 /* internal */,
0);
- do_cleanups (cleanup);
}
/* Helper function for break_command_1 and disassemble_command. */
if we have line numbers but no functions (as can
happen in assembly source). */
- struct bound_minimal_symbol msym;
- struct cleanup *old_chain = save_current_space_and_thread ();
-
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
switch_to_program_space_and_thread (sal->pspace);
- msym = lookup_minimal_symbol_by_pc (sal->pc);
+ bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (sal->pc);
if (msym.minsym)
sal->section = MSYMBOL_OBJ_SECTION (msym.objfile, msym.minsym);
-
- do_cleanups (old_chain);
}
}
}
static void
dprintf_command (char *arg, int from_tty)
{
- struct event_location *location;
- struct cleanup *cleanup;
-
- location = string_to_event_location (&arg, current_language);
- cleanup = make_cleanup_delete_event_location (location);
+ event_location_up location = string_to_event_location (&arg, current_language);
/* If non-NULL, ARG should have been advanced past the location;
the next character must be ','. */
}
create_breakpoint (get_current_arch (),
- location,
+ location.get (),
NULL, 0, arg, 1 /* parse arg */,
0, bp_dprintf,
0 /* Ignore count */,
1 /* enabled */,
0 /* internal */,
0);
- do_cleanups (cleanup);
}
static void
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 ");
+ uiout->text ("Temporary ranged breakpoint ");
else
- ui_out_text (uiout, "\nRanged breakpoint ");
- if (ui_out_is_mi_like_p (uiout))
+ uiout->text ("Ranged breakpoint ");
+ if (uiout->is_mi_like_p ())
{
- ui_out_field_string (uiout, "reason",
+ uiout->field_string ("reason",
async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
- ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+ uiout->field_string ("disp", bpdisp_text (b->disposition));
}
- ui_out_field_int (uiout, "bkptno", b->number);
- ui_out_text (uiout, ", ");
+ uiout->field_int ("bkptno", b->number);
+ uiout->text (", ");
return PRINT_SRC_AND_LOC;
}
if (opts.addressprint)
/* We don't print the address range here, it will be printed later
by print_one_detail_ranged_breakpoint. */
- ui_out_field_skip (uiout, "addr");
+ uiout->field_skip ("addr");
annotate_field (5);
print_breakpoint_location (b, bl);
*last_loc = bl;
{
CORE_ADDR address_start, address_end;
struct bp_location *bl = b->loc;
- struct ui_file *stb = mem_fileopen ();
- struct cleanup *cleanup = make_cleanup_ui_file_delete (stb);
+ string_file stb;
gdb_assert (bl);
address_start = bl->address;
address_end = address_start + bl->length - 1;
- ui_out_text (uiout, "\taddress range: ");
- fprintf_unfiltered (stb, "[%s, %s]",
- print_core_address (bl->gdbarch, address_start),
- print_core_address (bl->gdbarch, address_end));
- ui_out_field_stream (uiout, "addr", stb);
- ui_out_text (uiout, "\n");
-
- do_cleanups (cleanup);
+ uiout->text ("\taddress range: ");
+ stb.printf ("[%s, %s]",
+ print_core_address (bl->gdbarch, address_start),
+ print_core_address (bl->gdbarch, address_end));
+ uiout->field_stream ("addr", stb);
+ uiout->text ("\n");
}
/* Implement the "print_mention" breakpoint_ops method for
gdb_assert (bl);
gdb_assert (b->type == bp_hardware_breakpoint);
- if (ui_out_is_mi_like_p (uiout))
+ if (uiout->is_mi_like_p ())
return;
printf_filtered (_("Hardware assisted ranged breakpoint %d from %s to %s."),
print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp)
{
fprintf_unfiltered (fp, "break-range %s, %s",
- event_location_to_string (b->location),
- event_location_to_string (b->location_range_end));
+ event_location_to_string (b->location.get ()),
+ event_location_to_string (b->location_range_end.get ()));
print_recreate_thread (b, fp);
}
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;
struct symtab_and_line sal_start, sal_end;
struct cleanup *cleanup_bkpt;
struct linespec_sals *lsal_start, *lsal_end;
- struct event_location *start_location, *end_location;
/* We don't support software ranged breakpoints. */
if (target_ranged_break_num_registers () < 0)
if (arg == NULL || arg[0] == '\0')
error(_("No address range specified."));
- init_linespec_result (&canonical_start);
-
arg_start = arg;
- start_location = string_to_event_location (&arg, current_language);
- cleanup_bkpt = make_cleanup_delete_event_location (start_location);
- parse_breakpoint_sals (start_location, &canonical_start);
- make_cleanup_destroy_linespec_result (&canonical_start);
+ event_location_up start_location = string_to_event_location (&arg,
+ current_language);
+ parse_breakpoint_sals (start_location.get (), &canonical_start);
if (arg[0] != ',')
error (_("Too few arguments."));
sal_start = lsal_start->sals.sals[0];
addr_string_start = savestring (arg_start, arg - arg_start);
- make_cleanup (xfree, addr_string_start);
+ cleanup_bkpt = make_cleanup (xfree, addr_string_start);
arg++; /* Skip the comma. */
arg = skip_spaces (arg);
/* Parse the end location. */
- init_linespec_result (&canonical_end);
arg_start = arg;
/* We call decode_line_full directly here instead of using
symtab and line as the default symtab and line for the end of the
range. This makes it possible to have ranges like "foo.c:27, +14",
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,
+ event_location_up end_location = string_to_event_location (&arg,
+ current_language);
+ decode_line_full (end_location.get (), DECODE_LINE_FUNFIRSTLINE, NULL,
sal_start.symtab, sal_start.line,
&canonical_end, NULL, NULL);
- make_cleanup_destroy_linespec_result (&canonical_end);
-
if (VEC_empty (linespec_sals, canonical_end.sals))
error (_("Could not find location of the end of the range."));
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
b->disposition = disp_donttouch;
- b->location = copy_event_location (start_location);
- b->location_range_end = copy_event_location (end_location);
+ b->location = std::move (start_location);
+ b->location_range_end = std::move (end_location);
b->loc->length = length;
do_cleanups (cleanup_bkpt);
return 1;
}
-/* Implement the "dtor" breakpoint_ops method for watchpoints. */
+/* Watchpoint destructor. */
-static void
-dtor_watchpoint (struct breakpoint *self)
+watchpoint::~watchpoint ()
{
- 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);
-
- base_breakpoint_ops.dtor (self);
+ xfree (this->exp_string);
+ xfree (this->exp_string_reparse);
+ value_free (this->val);
}
/* Implement the "re_set" breakpoint_ops method for watchpoints. */
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
{
struct cleanup *old_chain;
struct breakpoint *b;
- struct ui_file *stb;
enum print_stop_action result;
struct watchpoint *w;
struct ui_out *uiout = current_uiout;
b = bs->breakpoint_at;
w = (struct watchpoint *) b;
- stb = mem_fileopen ();
- old_chain = make_cleanup_ui_file_delete (stb);
+ old_chain = make_cleanup (null_cleanup, NULL);
+
+ annotate_watchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
+
+ string_file stb;
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",
- async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
+ if (uiout->is_mi_like_p ())
+ uiout->field_string
+ ("reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
mention (b);
make_cleanup_ui_out_tuple_begin_end (uiout, "value");
- ui_out_text (uiout, "\nOld value = ");
- watchpoint_value_print (bs->old_val, stb);
- ui_out_field_stream (uiout, "old", stb);
- ui_out_text (uiout, "\nNew value = ");
- watchpoint_value_print (w->val, stb);
- ui_out_field_stream (uiout, "new", stb);
- ui_out_text (uiout, "\n");
+ uiout->text ("\nOld value = ");
+ watchpoint_value_print (bs->old_val, &stb);
+ uiout->field_stream ("old", stb);
+ uiout->text ("\nNew value = ");
+ watchpoint_value_print (w->val, &stb);
+ uiout->field_stream ("new", stb);
+ uiout->text ("\n");
/* More than one watchpoint may have been triggered. */
result = PRINT_UNKNOWN;
break;
case bp_read_watchpoint:
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string
- (uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
+ if (uiout->is_mi_like_p ())
+ uiout->field_string
+ ("reason", async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
mention (b);
make_cleanup_ui_out_tuple_begin_end (uiout, "value");
- ui_out_text (uiout, "\nValue = ");
- watchpoint_value_print (w->val, stb);
- ui_out_field_stream (uiout, "value", stb);
- ui_out_text (uiout, "\n");
+ uiout->text ("\nValue = ");
+ watchpoint_value_print (w->val, &stb);
+ uiout->field_stream ("value", stb);
+ uiout->text ("\n");
result = PRINT_UNKNOWN;
break;
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",
+ if (uiout->is_mi_like_p ())
+ uiout->field_string
+ ("reason",
async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
mention (b);
make_cleanup_ui_out_tuple_begin_end (uiout, "value");
- ui_out_text (uiout, "\nOld value = ");
- watchpoint_value_print (bs->old_val, stb);
- ui_out_field_stream (uiout, "old", stb);
- ui_out_text (uiout, "\nNew value = ");
+ uiout->text ("\nOld value = ");
+ watchpoint_value_print (bs->old_val, &stb);
+ uiout->field_stream ("old", stb);
+ uiout->text ("\nNew value = ");
}
else
{
mention (b);
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string
- (uiout, "reason",
+ if (uiout->is_mi_like_p ())
+ uiout->field_string
+ ("reason",
async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
make_cleanup_ui_out_tuple_begin_end (uiout, "value");
- ui_out_text (uiout, "\nValue = ");
+ uiout->text ("\nValue = ");
}
- watchpoint_value_print (w->val, stb);
- ui_out_field_stream (uiout, "new", stb);
- ui_out_text (uiout, "\n");
+ watchpoint_value_print (w->val, &stb);
+ uiout->field_stream ("new", stb);
+ uiout->text ("\n");
result = PRINT_UNKNOWN;
break;
default:
static void
print_mention_watchpoint (struct breakpoint *b)
{
- struct cleanup *ui_out_chain;
struct watchpoint *w = (struct watchpoint *) b;
struct ui_out *uiout = current_uiout;
+ const char *tuple_name;
switch (b->type)
{
case bp_watchpoint:
- ui_out_text (uiout, "Watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
+ uiout->text ("Watchpoint ");
+ tuple_name = "wpt";
break;
case bp_hardware_watchpoint:
- ui_out_text (uiout, "Hardware watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
+ uiout->text ("Hardware watchpoint ");
+ tuple_name = "wpt";
break;
case bp_read_watchpoint:
- ui_out_text (uiout, "Hardware read watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt");
+ uiout->text ("Hardware read watchpoint ");
+ tuple_name = "hw-rwpt";
break;
case bp_access_watchpoint:
- ui_out_text (uiout, "Hardware access (read/write) watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt");
+ uiout->text ("Hardware access (read/write) watchpoint ");
+ tuple_name = "hw-awpt";
break;
default:
internal_error (__FILE__, __LINE__,
_("Invalid hardware watchpoint type."));
}
- ui_out_field_int (uiout, "number", b->number);
- ui_out_text (uiout, ": ");
- ui_out_field_string (uiout, "exp", w->exp_string);
- do_cleanups (ui_out_chain);
+ ui_out_emit_tuple tuple_emitter (uiout, tuple_name);
+ uiout->field_int ("number", b->number);
+ uiout->text (": ");
+ uiout->field_string ("exp", w->exp_string);
}
/* Implement the "print_recreate" breakpoint_ops method for
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",
- async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
+ if (uiout->is_mi_like_p ())
+ uiout->field_string
+ ("reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
break;
case bp_read_watchpoint:
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string
- (uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
+ if (uiout->is_mi_like_p ())
+ uiout->field_string
+ ("reason", async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
break;
case bp_access_watchpoint:
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string
- (uiout, "reason",
+ if (uiout->is_mi_like_p ())
+ uiout->field_string
+ ("reason",
async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
break;
default:
}
mention (b);
- ui_out_text (uiout, _("\n\
+ uiout->text (_("\n\
Check the underlying instruction at PC for the memory\n\
address and value which triggered this watchpoint.\n"));
- ui_out_text (uiout, "\n");
+ uiout->text ("\n");
/* More than one watchpoint may have been triggered. */
return PRINT_UNKNOWN;
/* Masked watchpoints have only one location. */
gdb_assert (b->loc && b->loc->next == NULL);
- ui_out_text (uiout, "\tmask ");
- ui_out_field_core_addr (uiout, "mask", b->loc->gdbarch, w->hw_wp_mask);
- ui_out_text (uiout, "\n");
+ uiout->text ("\tmask ");
+ uiout->field_core_addr ("mask", b->loc->gdbarch, w->hw_wp_mask);
+ uiout->text ("\n");
}
/* Implement the "print_mention" breakpoint_ops method for
{
struct watchpoint *w = (struct watchpoint *) b;
struct ui_out *uiout = current_uiout;
- struct cleanup *ui_out_chain;
+ const char *tuple_name;
switch (b->type)
{
case bp_hardware_watchpoint:
- ui_out_text (uiout, "Masked hardware watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
+ uiout->text ("Masked hardware watchpoint ");
+ tuple_name = "wpt";
break;
case bp_read_watchpoint:
- ui_out_text (uiout, "Masked hardware read watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt");
+ uiout->text ("Masked hardware read watchpoint ");
+ tuple_name = "hw-rwpt";
break;
case bp_access_watchpoint:
- ui_out_text (uiout, "Masked hardware access (read/write) watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt");
+ uiout->text ("Masked hardware access (read/write) watchpoint ");
+ tuple_name = "hw-awpt";
break;
default:
internal_error (__FILE__, __LINE__,
_("Invalid hardware watchpoint type."));
}
- ui_out_field_int (uiout, "number", b->number);
- ui_out_text (uiout, ": ");
- ui_out_field_string (uiout, "exp", w->exp_string);
- do_cleanups (ui_out_chain);
+ ui_out_emit_tuple tuple_emitter (uiout, tuple_name);
+ uiout->field_int ("number", b->number);
+ uiout->text (": ");
+ uiout->field_string ("exp", w->exp_string);
}
/* Implement the "print_recreate" breakpoint_ops method for
watch_command_1 (const char *arg, int accessflag, int from_tty,
int just_location, int internal)
{
- struct breakpoint *b, *scope_breakpoint = NULL;
- struct expression *exp;
+ struct breakpoint *scope_breakpoint = NULL;
const struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
struct value *val, *mark, *result;
int saved_bitpos = 0, saved_bitsize = 0;
- struct frame_info *frame;
const char *exp_start = NULL;
const char *exp_end = NULL;
const char *tok, *end_tok;
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)
error (_("Junk at end of command."));
- frame = block_innermost_frame (exp_valid_block);
+ frame_info *wp_frame = block_innermost_frame (exp_valid_block);
+
+ /* Save this because create_internal_breakpoint below invalidates
+ 'wp_frame'. */
+ frame_id watchpoint_frame = get_frame_id (wp_frame);
/* If the expression is "local", then set up a "watchpoint scope"
breakpoint at the point where we've left the scope of the watchpoint
expression. Create the scope breakpoint before the watchpoint, so
that we will encounter it first in bpstat_stop_status. */
- if (exp_valid_block && frame)
+ if (exp_valid_block != NULL && wp_frame != NULL)
{
- if (frame_id_p (frame_unwind_caller_id (frame)))
+ frame_id caller_frame_id = frame_unwind_caller_id (wp_frame);
+
+ if (frame_id_p (caller_frame_id))
{
+ gdbarch *caller_arch = frame_unwind_caller_arch (wp_frame);
+ CORE_ADDR caller_pc = frame_unwind_caller_pc (wp_frame);
+
scope_breakpoint
- = create_internal_breakpoint (frame_unwind_caller_arch (frame),
- frame_unwind_caller_pc (frame),
+ = create_internal_breakpoint (caller_arch, caller_pc,
bp_watchpoint_scope,
&momentary_breakpoint_ops);
+ /* create_internal_breakpoint could invalidate WP_FRAME. */
+ wp_frame = NULL;
+
scope_breakpoint->enable_state = bp_enabled;
/* Automatically delete the breakpoint when it hits. */
scope_breakpoint->disposition = disp_del;
/* Only break in the proper frame (help with recursion). */
- scope_breakpoint->frame_id = frame_unwind_caller_id (frame);
+ scope_breakpoint->frame_id = caller_frame_id;
/* Set the address at which we will stop. */
- scope_breakpoint->loc->gdbarch
- = frame_unwind_caller_arch (frame);
- scope_breakpoint->loc->requested_address
- = frame_unwind_caller_pc (frame);
+ scope_breakpoint->loc->gdbarch = caller_arch;
+ scope_breakpoint->loc->requested_address = caller_pc;
scope_breakpoint->loc->address
= adjust_breakpoint_address (scope_breakpoint->loc->gdbarch,
scope_breakpoint->loc->requested_address,
else
bp_type = bp_hardware_watchpoint;
- w = XCNEW (struct watchpoint);
- b = &w->base;
+ w = new watchpoint ();
+
if (use_mask)
- init_raw_breakpoint_without_location (b, NULL, bp_type,
+ init_raw_breakpoint_without_location (w, NULL, bp_type,
&masked_watchpoint_breakpoint_ops);
else
- init_raw_breakpoint_without_location (b, NULL, bp_type,
+ init_raw_breakpoint_without_location (w, NULL, bp_type,
&watchpoint_breakpoint_ops);
- b->thread = thread;
- b->disposition = disp_donttouch;
- b->pspace = current_program_space;
- w->exp = exp;
+ w->thread = thread;
+ w->disposition = disp_donttouch;
+ w->pspace = current_program_space;
+ 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,
- core_addr_to_string (addr));
- xfree (name);
+ w->exp_string_reparse
+ = current_language->la_watch_location_expression (t, addr).release ();
w->exp_string = xstrprintf ("-location %.*s",
(int) (exp_end - exp_start), exp_start);
-
- /* The above expression is in C. */
- b->language = language_c;
}
else
w->exp_string = savestring (exp_start, exp_end - exp_start);
}
if (cond_start)
- b->cond_string = savestring (cond_start, cond_end - cond_start);
+ w->cond_string = savestring (cond_start, cond_end - cond_start);
else
- b->cond_string = 0;
+ w->cond_string = 0;
- if (frame)
+ if (frame_id_p (watchpoint_frame))
{
- w->watchpoint_frame = get_frame_id (frame);
+ w->watchpoint_frame = watchpoint_frame;
w->watchpoint_thread = inferior_ptid;
}
else
{
/* The scope breakpoint is related to the watchpoint. We will
need to act on them together. */
- b->related_breakpoint = scope_breakpoint;
- scope_breakpoint->related_breakpoint = b;
+ w->related_breakpoint = scope_breakpoint;
+ scope_breakpoint->related_breakpoint = w;
}
if (!just_location)
}
CATCH (e, RETURN_MASK_ALL)
{
- delete_breakpoint (b);
+ delete_breakpoint (w);
throw_exception (e);
}
END_CATCH
- install_breakpoint (internal, b, 1);
+ install_breakpoint (internal, w, 1);
do_cleanups (back_to);
}
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;
struct frame_id caller_frame_id;
struct breakpoint *location_breakpoint;
struct breakpoint *caller_breakpoint = NULL;
- struct cleanup *old_chain, *cleanup;
+ struct cleanup *old_chain;
int thread;
struct thread_info *tp;
- struct event_location *location;
struct until_break_fsm *sm;
clear_proceed_status (0);
/* Set a breakpoint where the user wants it and at return from
this function. */
- location = string_to_event_location (&arg, current_language);
- cleanup = make_cleanup_delete_event_location (location);
+ event_location_up location = string_to_event_location (&arg, current_language);
if (last_displayed_sal_is_valid ())
- sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE,
+ sals = decode_line_1 (location.get (), 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);
+ sals = decode_line_1 (location.get (), DECODE_LINE_FUNFIRSTLINE,
+ 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);
proceed (-1, GDB_SIGNAL_DEFAULT);
-
- do_cleanups (cleanup);
}
/* This function attempts to parse an optional "if <cond>" clause
it updates arg to point to the first character following the parsed
if clause in the arg string. */
-char *
-ep_parse_optional_if_clause (char **arg)
+const char *
+ep_parse_optional_if_clause (const char **arg)
{
- char *cond_string;
+ const char *cond_string;
if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace ((*arg)[2]))
return NULL;
/* Skip any extra leading whitespace, and record the start of the
condition string. */
- *arg = skip_spaces (*arg);
+ *arg = skip_spaces_const (*arg);
cond_string = *arg;
/* Assume that the condition occupies the remainder of the arg
catch_fork_kind;
static void
-catch_fork_command_1 (char *arg, int from_tty,
+catch_fork_command_1 (char *arg_entry, int from_tty,
struct cmd_list_element *command)
{
+ const char *arg = arg_entry;
struct gdbarch *gdbarch = get_current_arch ();
- char *cond_string = NULL;
+ const char *cond_string = NULL;
catch_fork_kind fork_kind;
int tempflag;
if (!arg)
arg = "";
- arg = skip_spaces (arg);
+ arg = skip_spaces_const (arg);
/* The allowed syntax is:
catch [v]fork
}
static void
-catch_exec_command_1 (char *arg, int from_tty,
+catch_exec_command_1 (char *arg_entry, int from_tty,
struct cmd_list_element *command)
{
+ const char *arg = arg_entry;
struct exec_catchpoint *c;
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
- char *cond_string = NULL;
+ const char *cond_string = NULL;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
if (!arg)
arg = "";
- arg = skip_spaces (arg);
+ arg = skip_spaces_const (arg);
/* The allowed syntax is:
catch exec
if ((*arg != '\0') && !isspace (*arg))
error (_("Junk at end of arguments."));
- c = XNEW (struct exec_catchpoint);
- init_catchpoint (&c->base, gdbarch, tempflag, cond_string,
+ c = new exec_catchpoint ();
+ init_catchpoint (c, gdbarch, tempflag, cond_string,
&catch_exec_breakpoint_ops);
c->exec_pathname = NULL;
- install_breakpoint (0, &c->base, 1);
+ install_breakpoint (0, c, 1);
}
void
qsort being an unstable algorithm. */
static int
-bp_location_compare (const void *ap, const void *bp)
+bp_locations_compare (const void *ap, const void *bp)
{
const struct bp_location *a = *(const struct bp_location **) ap;
const struct bp_location *b = *(const struct bp_location **) bp;
return (a > b) - (a < b);
}
-/* Set bp_location_placed_address_before_address_max and
- bp_location_shadow_len_after_address_max according to the current
- content of the bp_location array. */
+/* Set bp_locations_placed_address_before_address_max and
+ bp_locations_shadow_len_after_address_max according to the current
+ content of the bp_locations array. */
static void
-bp_location_target_extensions_update (void)
+bp_locations_target_extensions_update (void)
{
struct bp_location *bl, **blp_tmp;
- bp_location_placed_address_before_address_max = 0;
- bp_location_shadow_len_after_address_max = 0;
+ bp_locations_placed_address_before_address_max = 0;
+ bp_locations_shadow_len_after_address_max = 0;
ALL_BP_LOCATIONS (bl, blp_tmp)
{
gdb_assert (bl->address >= start);
addr = bl->address - start;
- if (addr > bp_location_placed_address_before_address_max)
- bp_location_placed_address_before_address_max = addr;
+ if (addr > bp_locations_placed_address_before_address_max)
+ bp_locations_placed_address_before_address_max = addr;
/* Zero SHADOW_LEN would not pass bp_location_has_shadow. */
gdb_assert (bl->address < end);
addr = end - bl->address;
- if (addr > bp_location_shadow_len_after_address_max)
- bp_location_shadow_len_after_address_max = addr;
+ if (addr > bp_locations_shadow_len_after_address_max)
+ bp_locations_shadow_len_after_address_max = addr;
}
}
download_tracepoint_locations (void)
{
struct breakpoint *b;
- struct cleanup *old_chain;
enum tribool can_download_tracepoint = TRIBOOL_UNKNOWN;
- old_chain = save_current_space_and_thread ();
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
ALL_TRACEPOINTS (b)
{
if (bp_location_downloaded)
observer_notify_breakpoint_modified (b);
}
-
- do_cleanups (old_chain);
}
/* Swap the insertion/duplication state between two locations. */
/* 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
struct bp_location *awp_loc_first; /* access watchpoint */
struct bp_location *rwp_loc_first; /* read watchpoint */
- /* Saved former bp_location array which we compare against the newly
- built bp_location from the current state of ALL_BREAKPOINTS. */
- struct bp_location **old_location, **old_locp;
- unsigned old_location_count;
+ /* Saved former bp_locations array which we compare against the newly
+ built bp_locations from the current state of ALL_BREAKPOINTS. */
+ struct bp_location **old_locations, **old_locp;
+ unsigned old_locations_count;
- old_location = bp_location;
- old_location_count = bp_location_count;
- bp_location = NULL;
- bp_location_count = 0;
- cleanups = make_cleanup (xfree, old_location);
+ old_locations = bp_locations;
+ old_locations_count = bp_locations_count;
+ bp_locations = NULL;
+ bp_locations_count = 0;
+ cleanups = make_cleanup (xfree, old_locations);
ALL_BREAKPOINTS (b)
for (loc = b->loc; loc; loc = loc->next)
- bp_location_count++;
+ bp_locations_count++;
- bp_location = XNEWVEC (struct bp_location *, bp_location_count);
- locp = bp_location;
+ bp_locations = XNEWVEC (struct bp_location *, bp_locations_count);
+ locp = bp_locations;
ALL_BREAKPOINTS (b)
for (loc = b->loc; loc; loc = loc->next)
*locp++ = loc;
- qsort (bp_location, bp_location_count, sizeof (*bp_location),
- bp_location_compare);
+ qsort (bp_locations, bp_locations_count, sizeof (*bp_locations),
+ bp_locations_compare);
- bp_location_target_extensions_update ();
+ bp_locations_target_extensions_update ();
/* Identify bp_location instances that are no longer present in the
new list, and therefore should be freed. Note that it's not
LOCP is kept in sync with OLD_LOCP, each pointing to the current
and former bp_location array state respectively. */
- locp = bp_location;
- for (old_locp = old_location; old_locp < old_location + old_location_count;
+ locp = bp_locations;
+ for (old_locp = old_locations;
+ old_locp < old_locations + old_locations_count;
old_locp++)
{
struct bp_location *old_loc = *old_locp;
/* Skip LOCP entries which will definitely never be needed.
Stop either at or being the one matching OLD_LOC. */
- while (locp < bp_location + bp_location_count
+ while (locp < bp_locations + bp_locations_count
&& (*locp)->address < old_loc->address)
locp++;
for (loc2p = locp;
- (loc2p < bp_location + bp_location_count
+ (loc2p < bp_locations + bp_locations_count
&& (*loc2p)->address == old_loc->address);
loc2p++)
{
if (breakpoint_address_is_meaningful (old_loc->owner))
{
for (loc2p = locp;
- (loc2p < bp_location + bp_location_count
+ (loc2p < bp_locations + bp_locations_count
&& (*loc2p)->address == old_loc->address);
loc2p++)
{
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
if (b->extra_string == NULL)
{
printf_filtered (_(" (%s) pending."),
- event_location_to_string (b->location));
+ event_location_to_string (b->location.get ()));
}
else if (b->type == bp_dprintf)
{
printf_filtered (_(" (%s,%s) pending."),
- event_location_to_string (b->location),
+ event_location_to_string (b->location.get ()),
b->extra_string);
}
else
{
printf_filtered (_(" (%s %s) pending."),
- event_location_to_string (b->location),
+ event_location_to_string (b->location.get ()),
b->extra_string);
}
}
different file name, and this at least reflects the
real situation somewhat. */
printf_filtered (": %s.",
- event_location_to_string (b->location));
+ event_location_to_string (b->location.get ()));
}
if (b->loc->next)
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 =
bp_location_dtor
};
-/* Default breakpoint_ops methods all breakpoint_ops ultimately
- inherit from. */
+/* Destructor for the breakpoint base class. */
-static void
-base_breakpoint_dtor (struct breakpoint *self)
+breakpoint::~breakpoint ()
{
- decref_counted_command_line (&self->commands);
- xfree (self->cond_string);
- xfree (self->extra_string);
- xfree (self->filter);
- delete_event_location (self->location);
- delete_event_location (self->location_range_end);
+ decref_counted_command_line (&this->commands);
+ xfree (this->cond_string);
+ xfree (this->extra_string);
+ xfree (this->filter);
}
static struct bp_location *
base_breakpoint_allocate_location (struct breakpoint *self)
{
- struct bp_location *loc;
-
- loc = XNEW (struct bp_location);
- init_bp_location (loc, &bp_location_ops, self);
- return loc;
+ return new bp_location (&bp_location_ops, self);
}
static void
}
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 ();
struct breakpoint_ops base_breakpoint_ops =
{
- base_breakpoint_dtor,
base_breakpoint_allocate_location,
base_breakpoint_re_set,
base_breakpoint_insert_location,
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 ");
+ uiout->text ("Temporary breakpoint ");
else
- ui_out_text (uiout, "\nBreakpoint ");
- if (ui_out_is_mi_like_p (uiout))
+ uiout->text ("Breakpoint ");
+ if (uiout->is_mi_like_p ())
{
- ui_out_field_string (uiout, "reason",
+ uiout->field_string ("reason",
async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
- ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+ uiout->field_string ("disp", bpdisp_text (b->disposition));
}
- ui_out_field_int (uiout, "bkptno", b->number);
- ui_out_text (uiout, ", ");
+ uiout->field_int ("bkptno", b->number);
+ uiout->text (", ");
return PRINT_SRC_AND_LOC;
}
static void
bkpt_print_mention (struct breakpoint *b)
{
- if (ui_out_is_mi_like_p (current_uiout))
+ if (current_uiout->is_mi_like_p ())
return;
switch (b->type)
_("unhandled breakpoint type %d"), (int) tp->type);
fprintf_unfiltered (fp, " %s",
- event_location_to_string (tp->location));
+ event_location_to_string (tp->location.get ()));
/* Print out extra_string if this breakpoint is pending. It might
contain, for example, conditions that were set by the user. */
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. */
It gets cleared already on the removal of the first one of such placed
breakpoints. This is OK as they get all removed altogether. */
-static void
-longjmp_bkpt_dtor (struct breakpoint *self)
+longjmp_breakpoint::~longjmp_breakpoint ()
{
- struct thread_info *tp = find_thread_id (self->thread);
+ thread_info *tp = find_thread_global_id (this->thread);
- if (tp)
+ if (tp != NULL)
tp->initiating_frame = null_frame_id;
-
- momentary_breakpoint_ops.dtor (self);
}
/* Specific methods for probe breakpoints. */
}
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.canonical = xstrdup (event_location_to_string (canonical->location));
+ lsal.sals = parse_probes (location, NULL, canonical);
+ lsal.canonical
+ = xstrdup (event_location_to_string (canonical->location.get ()));
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"));
}
{
gdb_assert (self->type == bp_static_tracepoint);
- ui_out_text (uiout, "\tmarker id is ");
- ui_out_field_string (uiout, "static-tracepoint-marker-string-id",
+ uiout->text ("\tmarker id is ");
+ uiout->field_string ("static-tracepoint-marker-string-id",
tp->static_trace_marker_id);
- ui_out_text (uiout, "\n");
+ uiout->text ("\n");
}
}
static void
tracepoint_print_mention (struct breakpoint *b)
{
- if (ui_out_is_mi_like_p (current_uiout))
+ if (current_uiout->is_mi_like_p ())
return;
switch (b->type)
_("unhandled tracepoint type %d"), (int) self->type);
fprintf_unfiltered (fp, " %s",
- event_location_to_string (self->location));
+ event_location_to_string (self->location.get ()));
print_recreate_thread (self, fp);
if (tp->pass_count)
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;
dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp)
{
fprintf_unfiltered (fp, "dprintf %s,%s",
- event_location_to_string (tp->location),
+ event_location_to_string (tp->location.get ()),
tp->extra_string);
print_recreate_thread (tp, fp);
}
canonical->location = new_linespec_location (&str);
do_cleanups (cleanup);
- lsal.canonical = xstrdup (event_location_to_string (canonical->location));
+ lsal.canonical
+ = xstrdup (event_location_to_string (canonical->location.get ()));
VEC_safe_push (linespec_sals, canonical->sals, &lsal);
}
{
struct symtabs_and_lines expanded;
struct tracepoint *tp;
- struct cleanup *old_chain;
- struct event_location *location;
+ event_location_up location;
expanded.nelts = 1;
expanded.sals = &lsal->sals.sals[i];
- location = copy_event_location (canonical->location);
- old_chain = make_cleanup_delete_event_location (location);
+ location = copy_event_location (canonical->location.get ());
- tp = XCNEW (struct tracepoint);
- init_breakpoint_sal (&tp->base, gdbarch, expanded,
- location, NULL,
+ tp = new tracepoint ();
+ init_breakpoint_sal (tp, gdbarch, expanded,
+ std::move (location), NULL,
cond_string, extra_string,
type_wanted, disposition,
thread, task, ignore_count, ops,
corresponds to this one */
tp->static_trace_marker_id_idx = i;
- install_breakpoint (internal, &tp->base, 0);
-
- discard_cleanups (old_chain);
+ install_breakpoint (internal, tp, 0);
}
}
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;
self-contained, but it's not the case now. */
update_global_location_list (UGLL_DONT_INSERT);
- bpt->ops->dtor (bpt);
/* 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;
sal2 = find_pc_line (tpmarker->address, 0);
sym = find_pc_sect_function (tpmarker->address, NULL);
- ui_out_text (uiout, "Now in ");
+ uiout->text ("Now in ");
if (sym)
{
- ui_out_field_string (uiout, "func",
- SYMBOL_PRINT_NAME (sym));
- ui_out_text (uiout, " at ");
+ uiout->field_string ("func", SYMBOL_PRINT_NAME (sym));
+ uiout->text (" at ");
}
- ui_out_field_string (uiout, "file",
+ uiout->field_string ("file",
symtab_to_filename_for_display (sal2.symtab));
- ui_out_text (uiout, ":");
+ uiout->text (":");
- if (ui_out_is_mi_like_p (uiout))
+ if (uiout->is_mi_like_p ())
{
const char *fullname = symtab_to_fullname (sal2.symtab);
- ui_out_field_string (uiout, "fullname", fullname);
+ uiout->field_string ("fullname", fullname);
}
- ui_out_field_int (uiout, "line", sal2.line);
- ui_out_text (uiout, "\n");
+ uiout->field_int ("line", sal2.line);
+ uiout->text ("\n");
b->loc->line_number = sal2.line;
b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
- delete_event_location (b->location);
+ b->location.reset (NULL);
initialize_explicit_location (&explicit_loc);
explicit_loc.source_filename
= ASTRDUP (symtab_to_filename_for_display (sal2.symtab));
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.get (), 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.get (),
+ 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);
contents. */
lsal->sals.sals = NULL;
}
-
- destroy_linespec_result (&canonical);
}
/* Prepare the global context for a re-set of 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.
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)
{
struct breakpoint *b, *b_tmp;
enum language save_language;
int save_input_radix;
- struct cleanup *old_chain;
save_language = current_language->la_language;
save_input_radix = input_radix;
- old_chain = save_current_program_space ();
- ALL_BREAKPOINTS_SAFE (b, b_tmp)
{
- /* Format possible error msg. */
- char *message = xstrprintf ("Error in re-setting breakpoint %d: ",
- b->number);
- struct cleanup *cleanups = make_cleanup (xfree, message);
- catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL);
- do_cleanups (cleanups);
- }
- set_language (save_language);
- input_radix = save_input_radix;
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
- jit_breakpoint_re_set ();
+ /* 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. */
- do_cleanups (old_chain);
+ ALL_BREAKPOINTS_SAFE (b, b_tmp)
+ {
+ /* Format possible error msg. */
+ char *message = xstrprintf ("Error in re-setting breakpoint %d: ",
+ b->number);
+ struct cleanup *cleanups = make_cleanup (xfree, message);
+ catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL);
+ do_cleanups (cleanups);
+ }
+ set_language (save_language);
+ input_radix = save_input_radix;
+
+ jit_breakpoint_re_set ();
+ }
create_overlay_event_breakpoint ();
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 ();
+ std::vector<CORE_ADDR> next_pcs;
+
+ next_pcs = gdbarch_software_single_step (gdbarch, regcache);
+
+ if (!next_pcs.empty ())
+ {
+ struct frame_info *frame = get_current_frame ();
+ struct address_space *aspace = get_frame_address_space (frame);
+
+ for (CORE_ADDR pc : next_pcs)
+ insert_single_step_breakpoint (gdbarch, aspace, pc);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
/* See breakpoint.h. */
int
trace_command (char *arg, int from_tty)
{
struct breakpoint_ops *ops;
- struct event_location *location;
- struct cleanup *back_to;
- location = string_to_event_location (&arg, current_language);
- back_to = make_cleanup_delete_event_location (location);
+ event_location_up location = string_to_event_location (&arg,
+ current_language);
if (location != NULL
- && event_location_type (location) == PROBE_LOCATION)
+ && event_location_type (location.get ()) == PROBE_LOCATION)
ops = &tracepoint_probe_breakpoint_ops;
else
ops = &tracepoint_breakpoint_ops;
create_breakpoint (get_current_arch (),
- location,
+ location.get (),
NULL, 0, arg, 1 /* parse arg */,
0 /* tempflag */,
bp_tracepoint /* type_wanted */,
from_tty,
1 /* enabled */,
0 /* internal */, 0);
- do_cleanups (back_to);
}
static void
ftrace_command (char *arg, int from_tty)
{
- struct event_location *location;
- struct cleanup *back_to;
-
- location = string_to_event_location (&arg, current_language);
- back_to = make_cleanup_delete_event_location (location);
+ event_location_up location = string_to_event_location (&arg,
+ current_language);
create_breakpoint (get_current_arch (),
- location,
+ location.get (),
NULL, 0, arg, 1 /* parse arg */,
0 /* tempflag */,
bp_fast_tracepoint /* type_wanted */,
from_tty,
1 /* enabled */,
0 /* internal */, 0);
- do_cleanups (back_to);
}
/* strace command implementation. Creates a static tracepoint. */
strace_command (char *arg, int from_tty)
{
struct breakpoint_ops *ops;
- struct event_location *location;
+ event_location_up location;
struct cleanup *back_to;
/* Decide if we are dealing with a static tracepoint marker (`-m'),
location = string_to_event_location (&arg, current_language);
}
- back_to = make_cleanup_delete_event_location (location);
create_breakpoint (get_current_arch (),
- location,
+ location.get (),
NULL, 0, arg, 1 /* parse arg */,
0 /* tempflag */,
bp_static_tracepoint /* type_wanted */,
from_tty,
1 /* enabled */,
0 /* internal */, 0);
- do_cleanups (back_to);
}
/* Set up a fake reader function that gets command lines from a linked
{
char *addr_str, small_buf[100];
struct tracepoint *tp;
- struct event_location *location;
- struct cleanup *cleanup;
if (utp->at_string)
addr_str = utp->at_string;
"has no source form, ignoring it"),
utp->number);
- location = string_to_event_location (&addr_str, current_language);
- cleanup = make_cleanup_delete_event_location (location);
+ event_location_up location = string_to_event_location (&addr_str,
+ current_language);
if (!create_breakpoint (get_current_arch (),
- location,
+ location.get (),
utp->cond_string, -1, addr_str,
0 /* parse cond/thread */,
0 /* tempflag */,
utp->enabled /* enabled */,
0 /* internal */,
CREATE_BREAKPOINT_FLAGS_INSERTED))
- {
- do_cleanups (cleanup);
- return NULL;
- }
-
- do_cleanups (cleanup);
+ return NULL;
/* Get the tracepoint we just created. */
tp = get_tracepoint (tracepoint_count);
if (utp->pass > 0)
{
xsnprintf (small_buf, sizeof (small_buf), "%d %d", utp->pass,
- tp->base.number);
+ tp->number);
trace_pass_command (small_buf, 0);
}
function. */
if (!VEC_empty (char_ptr, utp->cmd_strings))
{
- struct command_line *cmd_list;
+ command_line_up cmd_list;
this_utp = utp;
next_cmd = 0;
cmd_list = read_command_lines_1 (read_uploaded_action, 1, NULL, NULL);
- breakpoint_set_commands (&tp->base, cmd_list);
+ breakpoint_set_commands (tp, std::move (cmd_list));
}
else if (!VEC_empty (char_ptr, utp->actions)
|| !VEC_empty (char_ptr, utp->step_actions))
utp->number);
/* Copy any status information that might be available. */
- tp->base.hit_count = utp->hit_count;
+ tp->hit_count = utp->hit_count;
tp->traceframe_usage = utp->traceframe_usage;
return tp;
if (num_printed == 0)
{
if (args == NULL || *args == '\0')
- ui_out_message (uiout, 0, "No tracepoints.\n");
+ uiout->message ("No tracepoints.\n");
else
- ui_out_message (uiout, 0, "No tracepoint matching '%s'.\n", args);
+ uiout->message ("No tracepoint matching '%s'.\n", args);
}
default_collect_info ();
trace_pass_set_count (struct tracepoint *tp, int count, int from_tty)
{
tp->pass_count = count;
- observer_notify_breakpoint_modified (&tp->base);
+ observer_notify_breakpoint_modified (tp);
if (from_tty)
printf_filtered (_("Setting tracepoint %d's passcount to %d\n"),
- tp->base.number, count);
+ tp->number, count);
}
/* Set passcount for tracepoint.
}
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;
struct breakpoint *tp;
int any = 0;
struct cleanup *cleanup;
- struct ui_file *fp;
int extra_trace_bits = 0;
if (filename == 0 || *filename == 0)
filename = tilde_expand (filename);
cleanup = make_cleanup (xfree, filename);
- fp = gdb_fopen (filename, "w");
- if (!fp)
+
+ stdio_file fp;
+
+ if (!fp.open (filename, "w"))
error (_("Unable to open file '%s' for saving (%s)"),
filename, safe_strerror (errno));
- make_cleanup_ui_file_delete (fp);
if (extra_trace_bits)
- save_trace_state_variables (fp);
+ save_trace_state_variables (&fp);
ALL_BREAKPOINTS (tp)
{
if (filter && !filter (tp))
continue;
- tp->ops->print_recreate (tp, fp);
+ tp->ops->print_recreate (tp, &fp);
/* Note, we can't rely on tp->number for anything, as we can't
assume the recreated breakpoint numbers will match. Use $bpnum
instead. */
if (tp->cond_string)
- fprintf_unfiltered (fp, " condition $bpnum %s\n", tp->cond_string);
+ fp.printf (" condition $bpnum %s\n", tp->cond_string);
if (tp->ignore_count)
- fprintf_unfiltered (fp, " ignore $bpnum %d\n", tp->ignore_count);
+ fp.printf (" ignore $bpnum %d\n", tp->ignore_count);
if (tp->type != bp_dprintf && tp->commands)
{
- struct gdb_exception exception;
-
- fprintf_unfiltered (fp, " commands\n");
+ fp.puts (" commands\n");
- ui_out_redirect (current_uiout, fp);
+ current_uiout->redirect (&fp);
TRY
{
print_command_lines (current_uiout, tp->commands->commands, 2);
}
CATCH (ex, RETURN_MASK_ALL)
{
- ui_out_redirect (current_uiout, NULL);
+ current_uiout->redirect (NULL);
throw_exception (ex);
}
END_CATCH
- ui_out_redirect (current_uiout, NULL);
- fprintf_unfiltered (fp, " end\n");
+ current_uiout->redirect (NULL);
+ fp.puts (" end\n");
}
if (tp->enable_state == bp_disabled)
- fprintf_unfiltered (fp, "disable $bpnum\n");
+ fp.puts ("disable $bpnum\n");
/* If this is a multi-location breakpoint, check if the locations
should be individually disabled. Watchpoint locations are
for (loc = tp->loc; loc != NULL; loc = loc->next, n++)
if (!loc->enabled)
- fprintf_unfiltered (fp, "disable $bpnum.%d\n", n);
+ fp.printf ("disable $bpnum.%d\n", n);
}
}
if (extra_trace_bits && *default_collect)
- fprintf_unfiltered (fp, "set default-collect %s\n", default_collect);
+ fp.printf ("set default-collect %s\n", default_collect);
if (from_tty)
printf_filtered (_("Saved to file '%s'.\n"), filename);
static struct cmd_list_element *tcatch_cmdlist;
void
-add_catch_command (char *name, char *docstring,
+add_catch_command (const char *name, const char *docstring,
cmd_sfunc_ftype *sfunc,
completer_ftype *completer,
void *user_data_catch,
ops->print_it = momentary_bkpt_print_it;
ops->print_mention = momentary_bkpt_print_mention;
- /* Momentary breakpoints for bp_longjmp and bp_exception. */
- ops = &longjmp_breakpoint_ops;
- *ops = momentary_breakpoint_ops;
- ops->dtor = longjmp_bkpt_dtor;
-
/* Probe breakpoints. */
ops = &bkpt_probe_breakpoint_ops;
*ops = bkpt_breakpoint_ops;
/* Watchpoints. */
ops = &watchpoint_breakpoint_ops;
*ops = base_breakpoint_ops;
- ops->dtor = dtor_watchpoint;
ops->re_set = re_set_watchpoint;
ops->insert_location = insert_watchpoint;
ops->remove_location = remove_watchpoint;
/* Exec catchpoints. */
ops = &catch_exec_breakpoint_ops;
*ops = base_breakpoint_ops;
- ops->dtor = dtor_catch_exec;
ops->insert_location = insert_catch_exec;
ops->remove_location = remove_catch_exec;
ops->breakpoint_hit = breakpoint_hit_catch_exec;
/* Solib-related catchpoints. */
ops = &catch_solib_breakpoint_ops;
*ops = base_breakpoint_ops;
- ops->dtor = dtor_catch_solib;
ops->insert_location = insert_catch_solib;
ops->remove_location = remove_catch_solib;
ops->breakpoint_hit = breakpoint_hit_catch_solib;
Usage is `ignore N COUNT'."));
add_com ("commands", class_breakpoint, commands_command, _("\
-Set commands to be executed when a breakpoint is hit.\n\
-Give breakpoint number as argument after \"commands\".\n\
+Set commands to be executed when the given breakpoints are hit.\n\
+Give a space-separated breakpoint list as argument after \"commands\".\n\
+A list element can be a breakpoint number (e.g. `5') or a range of numbers\n\
+(e.g. `5-7').\n\
With no argument, the targeted breakpoint is the last one set.\n\
The commands themselves follow starting on the next line.\n\
Type a line containing \"end\" to indicate the end of them.\n\