#include "mi/mi-common.h"
#include "extension.h"
#include <algorithm>
+#include "progspace-and-thread.h"
/* Enums for exception-handling support. */
enum exception_event_kind
/* 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;
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. */
}
}
+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. */
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)
{
/* 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)
{
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."));
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);
}
there was an error. */
tmp_error_stream.puts ("Warning:\n");
- struct cleanup *cleanups = save_current_space_and_thread ();
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
ALL_BP_LOCATIONS (bl, blp_tmp)
{
target_terminal_ours_for_output ();
error_stream (tmp_error_stream);
}
-
- do_cleanups (cleanups);
}
/* Used when starting or continuing the program. */
there was an error. */
tmp_error_stream.puts ("Warning:\n");
- struct cleanup *cleanups = save_current_space_and_thread ();
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
ALL_BP_LOCATIONS (bl, blp_tmp)
{
target_terminal_ours_for_output ();
error_stream (tmp_error_stream);
}
-
- do_cleanups (cleanups);
}
/* Used when the program stops.
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)
{
}
}
}
-
- 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;
}
}
-
- do_cleanups (old_chain);
}
/* Install a master breakpoint on the unwinder's debug hook. */
static int
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, REMOVE_BREAKPOINT);
-
- do_cleanups (old_chain);
- return ret;
+ return remove_breakpoint_1 (bl, REMOVE_BREAKPOINT);
}
/* Clear the "inserted" flag in all breakpoints. */
if (any_deleted)
{
- struct cleanup *cleanup;
char *name;
int ix;
current_uiout->text (_(" Inferior unloaded "));
- cleanup = make_cleanup_ui_out_list_begin_end (current_uiout,
- "removed");
+ ui_out_emit_list list_emitter (current_uiout, "removed");
for (ix = 0;
VEC_iterate (char_ptr, current_program_space->deleted_solibs,
ix, name);
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;
current_uiout->text (_(" Inferior loaded "));
- cleanup = make_cleanup_ui_out_list_begin_end (current_uiout,
- "added");
+ ui_out_emit_list list_emitter (current_uiout, "added");
for (ix = 0;
VEC_iterate (so_list_ptr, current_program_space->added_solibs,
ix, iter);
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. */
uiout->field_string
("reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
uiout->text ("\nWatchpoint ");
- uiout->field_int ("wpnum", b->base.number);
+ 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. */
SWITCH_THRU_ALL_UIS ()
{
printf_filtered (_("Watchpoint %d deleted.\n"),
- b->base.number);
+ b->number);
}
watchpoint_del_at_next_stop (b);
/* We've already printed what needs to be printed. */
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;
bp_location_condition_evaluator (loc));
uiout->text (")");
}
-
- do_cleanups (old_chain);
}
static const char *
VEC(int) *inf_num,
int mi_only)
{
- struct cleanup *back_to;
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)
{
uiout->text (plongest (inf));
}
}
-
- do_cleanups (back_to);
}
/* Print B to gdb_stdout. */
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))
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);
}
}
}
}
}
-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);
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 = new 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 = new 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
/* 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;
}
/* 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. */
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
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)
}
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
{
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
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
int enabled, int internal, unsigned flags,
int display_canonical)
{
- struct breakpoint *b;
- struct cleanup *old_chain;
-
- if (is_tracepoint_type (type))
- {
- struct tracepoint *t;
-
- t = new tracepoint ();
- b = &t->base;
- }
- else
- b = new breakpoint ();
+ std::unique_ptr<breakpoint> b = new_breakpoint_from_type (type);
- old_chain = make_cleanup (xfree, b);
-
- init_breakpoint_sal (b, gdbarch,
+ init_breakpoint_sal (b.get (), gdbarch,
sals, std::move (location),
filter, cond_string, extra_string,
type, disposition,
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
}
else
{
- struct breakpoint *b;
+ std::unique_ptr <breakpoint> b = new_breakpoint_from_type (type_wanted);
- if (is_tracepoint_type (type_wanted))
- {
- struct tracepoint *t;
-
- t = new tracepoint ();
- b = &t->base;
- }
- else
- b = new breakpoint ();
-
- 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)
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);
}
}
}
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->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. */
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:
uiout->text ("Watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
+ tuple_name = "wpt";
break;
case bp_hardware_watchpoint:
uiout->text ("Hardware watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
+ tuple_name = "wpt";
break;
case bp_read_watchpoint:
uiout->text ("Hardware read watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt");
+ tuple_name = "hw-rwpt";
break;
case bp_access_watchpoint:
uiout->text ("Hardware access (read/write) watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt");
+ tuple_name = "hw-awpt";
break;
default:
internal_error (__FILE__, __LINE__,
_("Invalid hardware watchpoint type."));
}
+ ui_out_emit_tuple tuple_emitter (uiout, tuple_name);
uiout->field_int ("number", b->number);
uiout->text (": ");
uiout->field_string ("exp", w->exp_string);
- do_cleanups (ui_out_chain);
}
/* Implement the "print_recreate" 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:
uiout->text ("Masked hardware watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
+ tuple_name = "wpt";
break;
case bp_read_watchpoint:
uiout->text ("Masked hardware read watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt");
+ tuple_name = "hw-rwpt";
break;
case bp_access_watchpoint:
uiout->text ("Masked hardware access (read/write) watchpoint ");
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt");
+ tuple_name = "hw-awpt";
break;
default:
internal_error (__FILE__, __LINE__,
_("Invalid hardware watchpoint type."));
}
+ ui_out_emit_tuple tuple_emitter (uiout, tuple_name);
uiout->field_int ("number", b->number);
uiout->text (": ");
uiout->field_string ("exp", w->exp_string);
- do_cleanups (ui_out_chain);
}
/* 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 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 (*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,
bp_type = bp_hardware_watchpoint;
w = new watchpoint ();
- b = &w->base;
+
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->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;
struct type *t = value_type (val);
CORE_ADDR addr = value_as_address (val);
- t = check_typedef (TYPE_TARGET_TYPE (check_typedef (t)));
-
- std::string name = type_to_string (t);
-
- w->exp_string_reparse = xstrprintf ("* (%s *) %s", name.c_str (),
- core_addr_to_string (addr));
+ 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);
}
error (_("Junk at end of arguments."));
c = new exec_catchpoint ();
- init_catchpoint (&c->base, gdbarch, tempflag, cond_string,
+ 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
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. */
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);
+ 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 = new struct bp_location ();
- init_bp_location (loc, &bp_location_ops, self);
- return loc;
+ return new bp_location (&bp_location_ops, self);
}
static void
struct breakpoint_ops base_breakpoint_ops =
{
- base_breakpoint_dtor,
base_breakpoint_allocate_location,
base_breakpoint_re_set,
base_breakpoint_insert_location,
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_global_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. */
location = copy_event_location (canonical->location.get ());
tp = new tracepoint ();
- init_breakpoint_sal (&tp->base, gdbarch, expanded,
+ init_breakpoint_sal (tp, gdbarch, expanded,
std::move (location), NULL,
cond_string, extra_string,
type_wanted, disposition,
corresponds to this one */
tp->static_trace_marker_id_idx = i;
- install_breakpoint (internal, &tp->base, 0);
+ install_breakpoint (internal, tp, 0);
}
}
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;
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_space_and_thread ();
-
- /* Note: we must not try to insert locations until after all
- breakpoints have been re-set. Otherwise, e.g., when re-setting
- breakpoint 1, we'd insert the locations of breakpoint 2, which
- hadn't been re-set yet, and thus may have stale locations. */
- ALL_BREAKPOINTS_SAFE (b, b_tmp)
{
- /* 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 ();
insert_single_step_breakpoints (struct gdbarch *gdbarch)
{
struct regcache *regcache = get_current_regcache ();
- VEC (CORE_ADDR) * next_pcs;
+ std::vector<CORE_ADDR> next_pcs;
next_pcs = gdbarch_software_single_step (gdbarch, regcache);
- if (next_pcs != NULL)
+ if (!next_pcs.empty ())
{
- int i;
- CORE_ADDR pc;
struct frame_info *frame = get_current_frame ();
struct address_space *aspace = get_frame_address_space (frame);
- for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++)
+ for (CORE_ADDR pc : next_pcs)
insert_single_step_breakpoint (gdbarch, aspace, pc);
- VEC_free (CORE_ADDR, next_pcs);
-
return 1;
}
else
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);
}
cmd_list = read_command_lines_1 (read_uploaded_action, 1, NULL, NULL);
- breakpoint_set_commands (&tp->base, std::move (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;
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.
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;