/* Everything about breakpoints, for GDB.
- Copyright (C) 1986-2013 Free Software Foundation, Inc.
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbthread.h"
#include "target.h"
#include "language.h"
-#include "gdb_string.h"
+#include <string.h>
#include "gdb-demangle.h"
#include "filenames.h"
#include "annotate.h"
#include "continuations.h"
#include "stack.h"
#include "skip.h"
-#include "gdb_regex.h"
#include "ax-gdb.h"
#include "dummy-frame.h"
#undef savestring
#include "mi/mi-common.h"
-#include "python/python.h"
+#include "extension.h"
/* Enums for exception-handling support. */
enum exception_event_kind
static void create_breakpoints_sal_default (struct gdbarch *,
struct linespec_result *,
- struct linespec_sals *,
char *, char *, enum bptype,
enum bpdisp, int, int,
int,
struct program_space *, CORE_ADDR,
struct obj_section *, int);
-static int breakpoint_address_match (struct address_space *aspace1,
- CORE_ADDR addr1,
- struct address_space *aspace2,
- CORE_ADDR addr2);
-
static int watchpoint_locations_match (struct bp_location *loc1,
struct bp_location *loc2);
static void detach_single_step_breakpoints (void);
-static int single_step_breakpoint_inserted_here_p (struct address_space *,
- CORE_ADDR pc);
-
static void free_bp_location (struct bp_location *loc);
static void incref_bp_location (struct bp_location *loc);
static void decref_bp_location (struct bp_location **loc);
ALL_BREAKPOINTS (b)
if (b->number == bnum)
{
- /* Check if this breakpoint has a Python object assigned to
- it, and if it has a definition of the "stop"
- method. This method and conditions entered into GDB from
- the CLI are mutually exclusive. */
- if (b->py_bp_object
- && gdbpy_breakpoint_has_py_cond (b->py_bp_object))
- error (_("Cannot set a condition where a Python 'stop' "
- "method has been defined in the breakpoint."));
+ /* Check if this breakpoint has a "stop" method implemented in an
+ extension language. This method and conditions entered into GDB
+ from the CLI are mutually exclusive. */
+ const struct extension_language_defn *extlang
+ = get_breakpoint_cond_ext_lang (b, EXT_LANG_NONE);
+
+ if (extlang != NULL)
+ {
+ error (_("Only one stop condition allowed. There is currently"
+ " a %s stop condition defined for this breakpoint."),
+ ext_lang_capitalized_name (extlang));
+ }
set_breakpoint_condition (b, p, from_tty);
if (is_breakpoint (b))
don't try to insert watchpoint. We don't automatically delete
such watchpoint, though, since failure to parse expression
is different from out-of-scope watchpoint. */
- if ( !target_has_execution)
+ if (!target_has_execution)
{
/* Without execution, memory can't change. No use to try and
set watchpoint locations. The watchpoint will be reset when
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;
+ else
+ error (_("Can't set read/access watchpoint when "
+ "hardware watchpoints are disabled."));
+ }
}
else if (within_current_scope && b->exp)
{
struct value *val_chain, *v, *result, *next;
struct program_space *frame_pspace;
- fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain);
+ fetch_subexp_value (b->exp, &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
}
}
else if (!b->base.ops->works_in_software_mode (&b->base))
- error (_("Expression cannot be implemented with "
- "read/access watchpoint."));
+ {
+ if (!can_use_hw_watchpoints)
+ error (_("Can't set read/access watchpoint when "
+ "hardware watchpoints are disabled."));
+ else
+ error (_("Expression cannot be implemented with "
+ "read/access watchpoint."));
+ }
else
b->base.type = bp_watchpoint;
if (bl->pspace->breakpoints_not_allowed)
return 0;
+ /* Don't insert a breakpoint if we're trying to step past its
+ location. */
+ if ((bl->loc_type == bp_loc_software_breakpoint
+ || bl->loc_type == bp_loc_hardware_breakpoint)
+ && stepping_past_instruction_at (bl->pspace->aspace,
+ bl->address))
+ return 0;
+
return 1;
}
int modified = bl->needs_update;
struct bp_location *loc;
+ /* Release conditions left over from a previous insert. */
+ VEC_free (agent_expr_p, bl->target_info.conditions);
+
/* This is only meaningful if the target is
evaluating conditions and if the user has
opted for condition evaluation on the target's
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);
+
/* For now, limit to agent-style dprintf breakpoints. */
if (bl->owner->type != bp_dprintf
|| strcmp (dprintf_style, dprintf_style_agent) != 0)
int *hw_breakpoint_error,
int *hw_bp_error_explained_already)
{
- int val = 0;
- char *hw_bp_err_string = NULL;
- struct gdb_exception e;
+ enum errors bp_err = GDB_NO_ERROR;
+ const char *bp_err_message = NULL;
+ volatile struct gdb_exception e;
if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update))
return 0;
/* No overlay handling: just set the breakpoint. */
TRY_CATCH (e, RETURN_MASK_ALL)
{
+ int val;
+
val = bl->owner->ops->insert_location (bl);
+ if (val)
+ bp_err = GENERIC_ERROR;
}
if (e.reason < 0)
{
- val = 1;
- hw_bp_err_string = (char *) e.message;
+ bp_err = e.error;
+ bp_err_message = e.message;
}
}
else
/* Set a software (trap) breakpoint at the LMA. */
bl->overlay_target_info = bl->target_info;
bl->overlay_target_info.placed_address = addr;
- val = target_insert_breakpoint (bl->gdbarch,
- &bl->overlay_target_info);
- if (val != 0)
+
+ /* No overlay handling: just set the breakpoint. */
+ TRY_CATCH (e, RETURN_MASK_ALL)
+ {
+ int val;
+
+ val = target_insert_breakpoint (bl->gdbarch,
+ &bl->overlay_target_info);
+ if (val)
+ bp_err = GENERIC_ERROR;
+ }
+ if (e.reason < 0)
+ {
+ bp_err = e.error;
+ bp_err_message = e.message;
+ }
+
+ if (bp_err != GDB_NO_ERROR)
fprintf_unfiltered (tmp_error_stream,
"Overlay breakpoint %d "
"failed: in ROM?\n",
/* Yes. This overlay section is mapped into memory. */
TRY_CATCH (e, RETURN_MASK_ALL)
{
+ int val;
+
val = bl->owner->ops->insert_location (bl);
+ if (val)
+ bp_err = GENERIC_ERROR;
}
if (e.reason < 0)
{
- val = 1;
- hw_bp_err_string = (char *) e.message;
+ bp_err = e.error;
+ bp_err_message = e.message;
}
}
else
}
}
- if (val)
+ if (bp_err != GDB_NO_ERROR)
{
/* Can't set the breakpoint. */
- if (solib_name_from_address (bl->pspace, bl->address))
+
+ /* In some cases, we might not be able to insert a
+ breakpoint in a shared library that has already been
+ removed, but we have not yet processed the shlib unload
+ event. Unfortunately, some targets that implement
+ breakpoint insertion themselves (necessary if this is a
+ HW breakpoint, but SW breakpoints likewise) can't tell
+ why the breakpoint insertion failed (e.g., the remote
+ target doesn't define error codes), so we must treat
+ generic errors as memory errors. */
+ if ((bp_err == GENERIC_ERROR || bp_err == MEMORY_ERROR)
+ && solib_name_from_address (bl->pspace, bl->address))
{
/* See also: disable_breakpoints_in_shlibs. */
- val = 0;
bl->shlib_disabled = 1;
observer_notify_breakpoint_modified (bl->owner);
if (!*disabled_breaks)
*disabled_breaks = 1;
fprintf_unfiltered (tmp_error_stream,
"breakpoint #%d\n", bl->owner->number);
+ return 0;
}
else
{
if (bl->loc_type == bp_loc_hardware_breakpoint)
{
- *hw_breakpoint_error = 1;
- *hw_bp_error_explained_already = hw_bp_err_string != NULL;
+ *hw_breakpoint_error = 1;
+ *hw_bp_error_explained_already = bp_err_message != NULL;
fprintf_unfiltered (tmp_error_stream,
"Cannot insert hardware breakpoint %d%s",
- bl->owner->number, hw_bp_err_string ? ":" : ".\n");
- if (hw_bp_err_string)
- fprintf_unfiltered (tmp_error_stream, "%s.\n", hw_bp_err_string);
+ bl->owner->number, bp_err_message ? ":" : ".\n");
+ if (bp_err_message != NULL)
+ fprintf_unfiltered (tmp_error_stream, "%s.\n", bp_err_message);
}
else
{
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert breakpoint %d.\n",
- bl->owner->number);
- fprintf_filtered (tmp_error_stream,
- "Error accessing memory address ");
- fputs_filtered (paddress (bl->gdbarch, bl->address),
- tmp_error_stream);
- fprintf_filtered (tmp_error_stream, ": %s.\n",
- safe_strerror (val));
+ if (bp_err_message == NULL)
+ {
+ char *message
+ = memory_error_message (TARGET_XFER_E_IO,
+ bl->gdbarch, bl->address);
+ struct cleanup *old_chain = make_cleanup (xfree, message);
+
+ fprintf_unfiltered (tmp_error_stream,
+ "Cannot insert breakpoint %d.\n"
+ "%s\n",
+ bl->owner->number, message);
+ do_cleanups (old_chain);
+ }
+ else
+ {
+ fprintf_unfiltered (tmp_error_stream,
+ "Cannot insert breakpoint %d: %s\n",
+ bl->owner->number,
+ bp_err_message);
+ }
}
+ return 1;
}
}
else
bl->inserted = 1;
- return val;
+ return 0;
}
else if (bl->loc_type == bp_loc_hardware_watchpoint
watchpoints. It's not clear that it's necessary... */
&& bl->owner->disposition != disp_del_at_next_stop)
{
+ int val;
+
gdb_assert (bl->owner->ops != NULL
&& bl->owner->ops->insert_location != NULL);
else if (bl->owner->type == bp_catchpoint)
{
+ int val;
+
gdb_assert (bl->owner->ops != NULL
&& bl->owner->ops->insert_location != NULL);
return val;
}
+/* When a thread exits, remove breakpoints that are related to
+ that thread. */
+
+static void
+remove_threaded_breakpoints (struct thread_info *tp, int silent)
+{
+ struct breakpoint *b, *b_tmp;
+
+ ALL_BREAKPOINTS_SAFE (b, b_tmp)
+ {
+ if (b->thread == tp->num && user_breakpoint_p (b))
+ {
+ b->disposition = disp_del_at_next_stop;
+
+ printf_filtered (_("\
+Thread-specific breakpoint %d deleted - thread %d no longer in the thread list.\n"),
+ b->number, tp->num);
+
+ /* Hide it from the user. */
+ b->number = 0;
+ }
+ }
+}
+
/* Remove breakpoints of process PID. */
int
struct breakpoint_objfile_data
{
/* Minimal symbol for "_ovly_debug_event" (if any). */
- struct minimal_symbol *overlay_msym;
+ struct bound_minimal_symbol overlay_msym;
/* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */
- struct minimal_symbol *longjmp_msym[NUM_LONGJMP_NAMES];
+ struct bound_minimal_symbol longjmp_msym[NUM_LONGJMP_NAMES];
/* True if we have looked for longjmp probes. */
int longjmp_searched;
VEC (probe_p) *longjmp_probes;
/* Minimal symbol for "std::terminate()" (if any). */
- struct minimal_symbol *terminate_msym;
+ struct bound_minimal_symbol terminate_msym;
/* Minimal symbol for "_Unwind_DebugHook" (if any). */
- struct minimal_symbol *exception_msym;
+ struct bound_minimal_symbol exception_msym;
/* True if we have looked for exception probes. */
int exception_searched;
bp_objfile_data = get_breakpoint_objfile_data (objfile);
- if (msym_not_found_p (bp_objfile_data->overlay_msym))
+ if (msym_not_found_p (bp_objfile_data->overlay_msym.minsym))
continue;
- if (bp_objfile_data->overlay_msym == NULL)
+ if (bp_objfile_data->overlay_msym.minsym == NULL)
{
- struct minimal_symbol *m;
+ struct bound_minimal_symbol m;
m = lookup_minimal_symbol_text (func_name, objfile);
- if (m == NULL)
+ if (m.minsym == NULL)
{
/* Avoid future lookups in this objfile. */
- bp_objfile_data->overlay_msym = &msym_not_found;
+ bp_objfile_data->overlay_msym.minsym = &msym_not_found;
continue;
}
bp_objfile_data->overlay_msym = m;
}
- addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym);
+ addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym);
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_overlay_event,
&internal_breakpoint_ops);
struct breakpoint_objfile_data *bp_objfile_data;
gdbarch = get_objfile_arch (objfile);
- if (!gdbarch_get_longjmp_target_p (gdbarch))
- continue;
bp_objfile_data = get_breakpoint_objfile_data (objfile);
if (!bp_objfile_data->longjmp_searched)
{
- bp_objfile_data->longjmp_probes
- = find_probes_in_objfile (objfile, "libc", "longjmp");
+ VEC (probe_p) *ret;
+
+ ret = find_probes_in_objfile (objfile, "libc", "longjmp");
+ if (ret != NULL)
+ {
+ /* We are only interested in checking one element. */
+ struct probe *p = VEC_index (probe_p, ret, 0);
+
+ if (!can_evaluate_probe_arguments (p))
+ {
+ /* We cannot use the probe interface here, because it does
+ not know how to evaluate arguments. */
+ VEC_free (probe_p, ret);
+ ret = NULL;
+ }
+ }
+ bp_objfile_data->longjmp_probes = ret;
bp_objfile_data->longjmp_searched = 1;
}
{
struct breakpoint *b;
- b = create_internal_breakpoint (gdbarch, probe->address,
+ b = create_internal_breakpoint (gdbarch,
+ get_probe_address (probe,
+ objfile),
bp_longjmp_master,
&internal_breakpoint_ops);
b->addr_string = xstrdup ("-probe-stap libc:longjmp");
continue;
}
+ if (!gdbarch_get_longjmp_target_p (gdbarch))
+ continue;
+
for (i = 0; i < NUM_LONGJMP_NAMES; i++)
{
struct breakpoint *b;
const char *func_name;
CORE_ADDR addr;
- if (msym_not_found_p (bp_objfile_data->longjmp_msym[i]))
+ if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
continue;
func_name = longjmp_names[i];
- if (bp_objfile_data->longjmp_msym[i] == NULL)
+ if (bp_objfile_data->longjmp_msym[i].minsym == NULL)
{
- struct minimal_symbol *m;
+ struct bound_minimal_symbol m;
m = lookup_minimal_symbol_text (func_name, objfile);
- if (m == NULL)
+ if (m.minsym == NULL)
{
/* Prevent future lookups in this objfile. */
- bp_objfile_data->longjmp_msym[i] = &msym_not_found;
+ bp_objfile_data->longjmp_msym[i].minsym = &msym_not_found;
continue;
}
bp_objfile_data->longjmp_msym[i] = m;
}
- addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
+ addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
&internal_breakpoint_ops);
b->addr_string = xstrdup (func_name);
bp_objfile_data = get_breakpoint_objfile_data (objfile);
- if (msym_not_found_p (bp_objfile_data->terminate_msym))
+ if (msym_not_found_p (bp_objfile_data->terminate_msym.minsym))
continue;
- if (bp_objfile_data->terminate_msym == NULL)
+ if (bp_objfile_data->terminate_msym.minsym == NULL)
{
- struct minimal_symbol *m;
+ struct bound_minimal_symbol m;
m = lookup_minimal_symbol (func_name, NULL, objfile);
- if (m == NULL || (MSYMBOL_TYPE (m) != mst_text
- && MSYMBOL_TYPE (m) != mst_file_text))
+ if (m.minsym == NULL || (MSYMBOL_TYPE (m.minsym) != mst_text
+ && MSYMBOL_TYPE (m.minsym) != mst_file_text))
{
/* Prevent future lookups in this objfile. */
- bp_objfile_data->terminate_msym = &msym_not_found;
+ bp_objfile_data->terminate_msym.minsym = &msym_not_found;
continue;
}
bp_objfile_data->terminate_msym = m;
}
- addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym);
+ addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym);
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_std_terminate_master,
&internal_breakpoint_ops);
/* We prefer the SystemTap probe point if it exists. */
if (!bp_objfile_data->exception_searched)
{
- bp_objfile_data->exception_probes
- = find_probes_in_objfile (objfile, "libgcc", "unwind");
+ VEC (probe_p) *ret;
+
+ ret = find_probes_in_objfile (objfile, "libgcc", "unwind");
+
+ if (ret != NULL)
+ {
+ /* We are only interested in checking one element. */
+ struct probe *p = VEC_index (probe_p, ret, 0);
+
+ if (!can_evaluate_probe_arguments (p))
+ {
+ /* We cannot use the probe interface here, because it does
+ not know how to evaluate arguments. */
+ VEC_free (probe_p, ret);
+ ret = NULL;
+ }
+ }
+ bp_objfile_data->exception_probes = ret;
bp_objfile_data->exception_searched = 1;
}
{
struct breakpoint *b;
- b = create_internal_breakpoint (gdbarch, probe->address,
+ b = create_internal_breakpoint (gdbarch,
+ get_probe_address (probe,
+ objfile),
bp_exception_master,
&internal_breakpoint_ops);
b->addr_string = xstrdup ("-probe-stap libgcc:unwind");
/* Otherwise, try the hook function. */
- if (msym_not_found_p (bp_objfile_data->exception_msym))
+ if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
continue;
gdbarch = get_objfile_arch (objfile);
- if (bp_objfile_data->exception_msym == NULL)
+ if (bp_objfile_data->exception_msym.minsym == NULL)
{
- struct minimal_symbol *debug_hook;
+ struct bound_minimal_symbol debug_hook;
debug_hook = lookup_minimal_symbol (func_name, NULL, objfile);
- if (debug_hook == NULL)
+ if (debug_hook.minsym == NULL)
{
- bp_objfile_data->exception_msym = &msym_not_found;
+ bp_objfile_data->exception_msym.minsym = &msym_not_found;
continue;
}
bp_objfile_data->exception_msym = debug_hook;
}
- addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
+ addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
¤t_target);
b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
struct cleanup *old_chain = save_inferior_ptid ();
struct inferior *inf = current_inferior ();
- if (PIDGET (ptid) == PIDGET (inferior_ptid))
+ if (ptid_get_pid (ptid) == ptid_get_pid (inferior_ptid))
error (_("Cannot detach breakpoints of inferior_ptid"));
/* Set inferior_ptid; remove_breakpoint_1 uses this global. */
/* See breakpoint.h. */
-enum bpstat_signal_value
+int
bpstat_explains_signal (bpstat bsp, enum gdb_signal sig)
{
- enum bpstat_signal_value result = BPSTAT_SIGNAL_NO;
-
for (; bsp != NULL; bsp = bsp->next)
{
- /* Ensure that, if we ever entered this loop, then we at least
- return BPSTAT_SIGNAL_HIDE. */
- enum bpstat_signal_value newval;
-
if (bsp->breakpoint_at == NULL)
{
/* A moribund location can never explain a signal other than
GDB_SIGNAL_TRAP. */
if (sig == GDB_SIGNAL_TRAP)
- newval = BPSTAT_SIGNAL_HIDE;
- else
- newval = BPSTAT_SIGNAL_NO;
+ return 1;
}
else
- newval = bsp->breakpoint_at->ops->explains_signal (bsp->breakpoint_at,
- sig);
-
- if (newval > result)
- result = newval;
+ {
+ if (bsp->breakpoint_at->ops->explains_signal (bsp->breakpoint_at,
+ sig))
+ return 1;
+ }
}
- return result;
+ return 0;
}
/* Put in *NUM the breakpoint number of the first breakpoint we are
return PRINT_UNKNOWN;
}
-/* Evaluate the expression EXP and return 1 if value is zero. This is
- used inside a catch_errors to evaluate the breakpoint condition.
+/* Evaluate the expression EXP and return 1 if value is zero.
+ This returns the inverse of the condition because it is called
+ from catch_errors which returns 0 if an exception happened, and if an
+ exception happens we want execution to stop.
The argument is a "struct expression *" that has been cast to a
- "char *" to make it pass through catch_errors. */
+ "void *" to make it pass through catch_errors. */
static int
breakpoint_cond_eval (void *exp)
w->watchpoint_triggered = watch_triggered_unknown;
}
- return stopped_by_watchpoint;
+ return 1;
}
/* The target could report the data address. Mark watchpoints
return WP_VALUE_CHANGED;
mark = value_mark ();
- fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL);
+ fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL, 0);
/* We use value_equal_contents instead of value_equal because
the latter coerces an array to a pointer, thus comparing just
}
}
-
-/* Check conditions (condition proper, frame, thread and ignore count)
+/* For breakpoints that are currently marked as telling gdb to stop,
+ check conditions (condition proper, frame, thread and ignore count)
of breakpoint referred to by BS. If we should not stop for this
breakpoint, set BS->stop to 0. */
static void
bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
{
- int thread_id = pid_to_thread_id (ptid);
const struct bp_location *bl;
struct breakpoint *b;
+ int value_is_zero = 0;
+ struct expression *cond;
+
+ gdb_assert (bs->stop);
/* BS is built for existing struct breakpoint. */
bl = bs->bp_location_at;
if (frame_id_p (b->frame_id)
&& !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ())))
- bs->stop = 0;
- else if (bs->stop)
{
- int value_is_zero = 0;
- struct expression *cond;
+ bs->stop = 0;
+ return;
+ }
- /* Evaluate Python breakpoints that have a "stop"
- method implemented. */
- if (b->py_bp_object)
- bs->stop = gdbpy_should_stop (b->py_bp_object);
+ /* 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))
+ || (b->task != 0 && b->task != ada_get_task_number (ptid)))
- if (is_watchpoint (b))
- {
- struct watchpoint *w = (struct watchpoint *) b;
+ {
+ bs->stop = 0;
+ return;
+ }
- cond = w->cond_exp;
- }
+ /* Evaluate extension language breakpoints that have a "stop" method
+ implemented. */
+ bs->stop = breakpoint_ext_lang_cond_says_stop (b);
+
+ if (is_watchpoint (b))
+ {
+ struct watchpoint *w = (struct watchpoint *) b;
+
+ cond = w->cond_exp;
+ }
+ else
+ cond = bl->cond;
+
+ if (cond && b->disposition != disp_del_at_next_stop)
+ {
+ int within_current_scope = 1;
+ struct watchpoint * w;
+
+ /* We use value_mark and value_free_to_mark because it could
+ be a long time before we return to the command level and
+ call free_all_values. We can't call free_all_values
+ because we might be in the middle of evaluating a
+ function call. */
+ struct value *mark = value_mark ();
+
+ if (is_watchpoint (b))
+ w = (struct watchpoint *) b;
else
- cond = bl->cond;
+ w = NULL;
- if (cond && b->disposition != disp_del_at_next_stop)
+ /* Need to select the frame, with all that implies so that
+ the conditions will have the right context. Because we
+ use the frame, we will not see an inlined function's
+ variables when we arrive at a breakpoint at the start
+ of the inlined function; the current frame will be the
+ call site. */
+ if (w == NULL || w->cond_exp_valid_block == NULL)
+ select_frame (get_current_frame ());
+ else
{
- int within_current_scope = 1;
- struct watchpoint * w;
-
- /* We use value_mark and value_free_to_mark because it could
- be a long time before we return to the command level and
- call free_all_values. We can't call free_all_values
- because we might be in the middle of evaluating a
- function call. */
- struct value *mark = value_mark ();
-
- if (is_watchpoint (b))
- w = (struct watchpoint *) b;
- else
- w = NULL;
-
- /* Need to select the frame, with all that implies so that
- the conditions will have the right context. Because we
- use the frame, we will not see an inlined function's
- variables when we arrive at a breakpoint at the start
- of the inlined function; the current frame will be the
- call site. */
- if (w == NULL || w->cond_exp_valid_block == NULL)
- select_frame (get_current_frame ());
+ struct frame_info *frame;
+
+ /* For local watchpoint expressions, which particular
+ instance of a local is being watched matters, so we
+ keep track of the frame to evaluate the expression
+ in. To evaluate the condition however, it doesn't
+ really matter which instantiation of the function
+ where the condition makes sense triggers the
+ watchpoint. This allows an expression like "watch
+ global if q > 10" set in `func', catch writes to
+ global on all threads that call `func', or catch
+ writes on all recursive calls of `func' by a single
+ thread. We simply always evaluate the condition in
+ the innermost frame that's executing where it makes
+ sense to evaluate the condition. It seems
+ intuitive. */
+ frame = block_innermost_frame (w->cond_exp_valid_block);
+ if (frame != NULL)
+ select_frame (frame);
else
- {
- struct frame_info *frame;
-
- /* For local watchpoint expressions, which particular
- instance of a local is being watched matters, so we
- keep track of the frame to evaluate the expression
- in. To evaluate the condition however, it doesn't
- really matter which instantiation of the function
- where the condition makes sense triggers the
- watchpoint. This allows an expression like "watch
- global if q > 10" set in `func', catch writes to
- global on all threads that call `func', or catch
- writes on all recursive calls of `func' by a single
- thread. We simply always evaluate the condition in
- the innermost frame that's executing where it makes
- sense to evaluate the condition. It seems
- intuitive. */
- frame = block_innermost_frame (w->cond_exp_valid_block);
- if (frame != NULL)
- select_frame (frame);
- else
- within_current_scope = 0;
- }
- if (within_current_scope)
- value_is_zero
- = catch_errors (breakpoint_cond_eval, cond,
- "Error in testing breakpoint condition:\n",
- RETURN_MASK_ALL);
- else
- {
- warning (_("Watchpoint condition cannot be tested "
- "in the current scope"));
- /* If we failed to set the right context for this
- watchpoint, unconditionally report it. */
- value_is_zero = 0;
- }
- /* FIXME-someday, should give breakpoint #. */
- value_free_to_mark (mark);
- }
-
- if (cond && value_is_zero)
- {
- bs->stop = 0;
+ within_current_scope = 0;
}
- else if (b->thread != -1 && b->thread != thread_id)
+ if (within_current_scope)
+ value_is_zero
+ = catch_errors (breakpoint_cond_eval, cond,
+ "Error in testing breakpoint condition:\n",
+ RETURN_MASK_ALL);
+ else
{
- bs->stop = 0;
+ warning (_("Watchpoint condition cannot be tested "
+ "in the current scope"));
+ /* If we failed to set the right context for this
+ watchpoint, unconditionally report it. */
+ value_is_zero = 0;
}
- else if (b->ignore_count > 0)
- {
- b->ignore_count--;
- bs->stop = 0;
- /* Increase the hit count even though we don't stop. */
- ++(b->hit_count);
- observer_notify_breakpoint_modified (b);
- }
+ /* FIXME-someday, should give breakpoint #. */
+ value_free_to_mark (mark);
+ }
+
+ if (cond && value_is_zero)
+ {
+ bs->stop = 0;
}
+ else if (b->ignore_count > 0)
+ {
+ b->ignore_count--;
+ bs->stop = 0;
+ /* Increase the hit count even though we don't stop. */
+ ++(b->hit_count);
+ observer_notify_breakpoint_modified (b);
+ }
}
if (command_line_is_silent (bs->commands
? bs->commands->commands : NULL))
bs->print = 0;
+
+ b->ops->after_condition_true (bs);
}
}
return bptypes[(int) type].description;
}
-DEF_VEC_I(int);
-
/* For MI, output a field named 'thread-groups' with a list as the value.
For CLI, prefix the list with the string 'inf'. */
&& loc1->length == loc2->length);
}
-/* Returns true if {ASPACE1,ADDR1} and {ASPACE2,ADDR2} represent the
- same breakpoint location. In most targets, this can only be true
- if ASPACE1 matches ASPACE2. On targets that have global
- breakpoints, the address space doesn't really matter. */
+/* See breakpoint.h. */
-static int
+int
breakpoint_address_match (struct address_space *aspace1, CORE_ADDR addr1,
struct address_space *aspace2, CORE_ADDR addr2)
{
}
}
-/* Disable any breakpoints and tracepoints that are in an unloaded shared
- library. Only apply to enabled breakpoints, disabled ones can just stay
- disabled. */
+/* Disable any breakpoints and tracepoints that are in SOLIB upon
+ notification of unloaded_shlib. Only apply to enabled breakpoints,
+ disabled ones can just stay disabled. */
static void
disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
}
}
+/* Disable any breakpoints and tracepoints in OBJFILE upon
+ notification of free_objfile. Only apply to enabled breakpoints,
+ disabled ones can just stay disabled. */
+
+static void
+disable_breakpoints_in_freed_objfile (struct objfile *objfile)
+{
+ struct breakpoint *b;
+
+ if (objfile == NULL)
+ return;
+
+ /* If the file is a shared library not loaded by the user then
+ solib_unloaded was notified and disable_breakpoints_in_unloaded_shlib
+ was called. In that case there is no need to take action again. */
+ if ((objfile->flags & OBJF_SHARED) && !(objfile->flags & OBJF_USERLOADED))
+ return;
+
+ ALL_BREAKPOINTS (b)
+ {
+ struct bp_location *loc;
+ int bp_modified = 0;
+
+ if (!is_breakpoint (b) && !is_tracepoint (b))
+ continue;
+
+ for (loc = b->loc; loc != NULL; loc = loc->next)
+ {
+ CORE_ADDR loc_addr = loc->address;
+
+ if (loc->loc_type != bp_loc_hardware_breakpoint
+ && loc->loc_type != bp_loc_software_breakpoint)
+ continue;
+
+ if (loc->shlib_disabled != 0)
+ continue;
+
+ if (objfile->pspace != loc->pspace)
+ continue;
+
+ if (loc->loc_type != bp_loc_hardware_breakpoint
+ && loc->loc_type != bp_loc_software_breakpoint)
+ continue;
+
+ if (is_addr_in_objfile (loc_addr, objfile))
+ {
+ loc->shlib_disabled = 1;
+ loc->inserted = 0;
+
+ mark_breakpoint_location_modified (loc);
+
+ bp_modified = 1;
+ }
+ }
+
+ if (bp_modified)
+ observer_notify_breakpoint_modified (b);
+ }
+}
+
/* FORK & VFORK catchpoints. */
/* An instance of this type is used to represent a fork or vfork
static int
insert_catch_fork (struct bp_location *bl)
{
- return target_insert_fork_catchpoint (PIDGET (inferior_ptid));
+ return target_insert_fork_catchpoint (ptid_get_pid (inferior_ptid));
}
/* Implement the "remove" breakpoint_ops method for fork
static int
remove_catch_fork (struct bp_location *bl)
{
- return target_remove_fork_catchpoint (PIDGET (inferior_ptid));
+ return target_remove_fork_catchpoint (ptid_get_pid (inferior_ptid));
}
/* Implement the "breakpoint_hit" breakpoint_ops method for fork
static int
insert_catch_vfork (struct bp_location *bl)
{
- return target_insert_vfork_catchpoint (PIDGET (inferior_ptid));
+ return target_insert_vfork_catchpoint (ptid_get_pid (inferior_ptid));
}
/* Implement the "remove" breakpoint_ops method for vfork
static int
remove_catch_vfork (struct bp_location *bl)
{
- return target_remove_vfork_catchpoint (PIDGET (inferior_ptid));
+ return target_remove_vfork_catchpoint (ptid_get_pid (inferior_ptid));
}
/* Implement the "breakpoint_hit" breakpoint_ops method for vfork
inf_data = inferior_data (inf, catch_syscall_inferior_data);
if (inf_data == NULL)
{
- inf_data = XZALLOC (struct catch_syscall_inferior_data);
+ inf_data = XCNEW (struct catch_syscall_inferior_data);
set_inferior_data (inf, catch_syscall_inferior_data, inf_data);
}
}
}
- return target_set_syscall_catchpoint (PIDGET (inferior_ptid),
+ return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid),
inf_data->total_syscalls_count != 0,
inf_data->any_syscall_count,
VEC_length (int,
}
}
- return target_set_syscall_catchpoint (PIDGET (inferior_ptid),
+ return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid),
inf_data->total_syscalls_count != 0,
inf_data->any_syscall_count,
VEC_length (int,
VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
i++)
if (syscall_number == iter)
- break;
- /* Not the same. */
- if (!iter)
- return 0;
+ return 1;
+
+ return 0;
}
return 1;
static int
insert_catch_exec (struct bp_location *bl)
{
- return target_insert_exec_catchpoint (PIDGET (inferior_ptid));
+ return target_insert_exec_catchpoint (ptid_get_pid (inferior_ptid));
}
static int
remove_catch_exec (struct bp_location *bl)
{
- return target_remove_exec_catchpoint (PIDGET (inferior_ptid));
+ return target_remove_exec_catchpoint (ptid_get_pid (inferior_ptid));
}
static int
loc->requested_address = sal->pc;
loc->address = adjusted_address;
loc->pspace = sal->pspace;
- loc->probe = sal->probe;
+ loc->probe.probe = sal->probe;
+ loc->probe.objfile = sal->objfile;
gdb_assert (loc->pspace != NULL);
loc->section = sal->section;
loc->gdbarch = loc_gdbarch;
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
breakpoint. */
if (!pending)
{
- struct linespec_sals *lsal;
-
- lsal = VEC_index (linespec_sals, canonical.sals, 0);
-
if (parse_arg)
{
- char *rest;
- /* Here we only parse 'arg' to separate condition
- from thread number, so parsing in context of first
- sal is OK. When setting the breakpoint we'll
- re-parse it in context of each sal. */
-
- find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
- &thread, &task, &rest);
- if (cond_string)
- make_cleanup (xfree, cond_string);
- if (rest)
- make_cleanup (xfree, rest);
- if (rest)
- extra_string = rest;
+ char *rest;
+ struct linespec_sals *lsal;
+
+ lsal = VEC_index (linespec_sals, canonical.sals, 0);
+
+ /* Here we only parse 'arg' to separate condition
+ from thread number, so parsing in context of first
+ sal is OK. When setting the breakpoint we'll
+ re-parse it in context of each sal. */
+
+ find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
+ &thread, &task, &rest);
+ if (cond_string)
+ make_cleanup (xfree, cond_string);
+ if (rest)
+ make_cleanup (xfree, rest);
+ if (rest)
+ extra_string = rest;
}
else
{
- if (*arg != '\0')
- error (_("Garbage '%s' at end of location"), arg);
-
- /* Create a private copy of condition string. */
- if (cond_string)
- {
- cond_string = xstrdup (cond_string);
- make_cleanup (xfree, cond_string);
- }
- /* Create a private copy of any extra string. */
- if (extra_string)
- {
- extra_string = xstrdup (extra_string);
- make_cleanup (xfree, extra_string);
- }
+ if (*arg != '\0')
+ error (_("Garbage '%s' at end of location"), arg);
+
+ /* Create a private copy of condition string. */
+ if (cond_string)
+ {
+ cond_string = xstrdup (cond_string);
+ make_cleanup (xfree, cond_string);
+ }
+ /* Create a private copy of any extra string. */
+ if (extra_string)
+ {
+ extra_string = xstrdup (extra_string);
+ make_cleanup (xfree, extra_string);
+ }
}
- ops->create_breakpoints_sal (gdbarch, &canonical, lsal,
+ ops->create_breakpoints_sal (gdbarch, &canonical,
cond_string, extra_string, type_wanted,
tempflag ? disp_del : disp_donttouch,
thread, task, ignore_count, ops,
msym = lookup_minimal_symbol_by_pc (sal->pc);
if (msym.minsym)
- sal->section = SYMBOL_OBJ_SECTION (msym.objfile, msym.minsym);
+ sal->section = MSYMBOL_OBJ_SECTION (msym.objfile, msym.minsym);
do_cleanups (old_chain);
}
/* Implement the "explains_signal" breakpoint_ops method for
watchpoints. */
-static enum bpstat_signal_value
+static int
explains_signal_watchpoint (struct breakpoint *b, enum gdb_signal sig)
{
/* A software watchpoint cannot cause a signal other than
GDB_SIGNAL_TRAP. */
if (b->type == bp_watchpoint && sig != GDB_SIGNAL_TRAP)
- return BPSTAT_SIGNAL_NO;
+ return 0;
- return BPSTAT_SIGNAL_HIDE;
+ return 1;
}
/* The breakpoint_ops structure to be used in hardware watchpoints. */
exp_valid_block = innermost_block;
mark = value_mark ();
- fetch_subexp_value (exp, &pc, &val, &result, NULL);
+ fetch_subexp_value (exp, &pc, &val, &result, NULL, just_location);
if (just_location)
{
if (*tok)
error (_("Junk at end of command."));
- if (accessflag == hw_read)
- bp_type = bp_read_watchpoint;
- else if (accessflag == hw_access)
- bp_type = bp_access_watchpoint;
- else
- bp_type = bp_hardware_watchpoint;
-
frame = block_innermost_frame (exp_valid_block);
/* If the expression is "local", then set up a "watchpoint scope"
}
}
- /* Now set up the breakpoint. */
+ /* Now set up the breakpoint. We create all watchpoints as hardware
+ watchpoints here even if hardware watchpoints are turned off, a call
+ to update_watchpoint later in this function will cause the type to
+ drop back to bp_watchpoint (software watchpoint) if required. */
+
+ if (accessflag == hw_read)
+ bp_type = bp_read_watchpoint;
+ else if (accessflag == hw_access)
+ bp_type = bp_access_watchpoint;
+ else
+ bp_type = bp_hardware_watchpoint;
w = XCNEW (struct watchpoint);
b = &w->base;
char *addr_string,
const struct breakpoint_ops *ops,
int tempflag,
+ int enabled,
int from_tty)
{
if (from_tty)
init_raw_breakpoint (b, gdbarch, sal, bp_breakpoint, ops);
- b->enable_state = bp_enabled;
+ b->enable_state = enabled ? bp_enabled : bp_disabled;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->addr_string = addr_string;
b->language = language_ada;
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 =
static void
base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch,
struct linespec_result *c,
- struct linespec_sals *lsal,
char *cond_string,
char *extra_string,
enum bptype type_wanted,
/* The default 'explains_signal' method. */
-static enum bpstat_signal_value
+static int
base_breakpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
{
- return BPSTAT_SIGNAL_HIDE;
+ return 1;
+}
+
+/* The default "after_condition_true" method. */
+
+static void
+base_breakpoint_after_condition_true (struct bpstats *bs)
+{
+ /* Nothing to do. */
}
struct breakpoint_ops base_breakpoint_ops =
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
- base_breakpoint_explains_signal
+ base_breakpoint_explains_signal,
+ base_breakpoint_after_condition_true,
};
/* Default breakpoint_ops methods. */
static void
bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
struct linespec_result *canonical,
- struct linespec_sals *lsal,
char *cond_string,
char *extra_string,
enum bptype type_wanted,
int from_tty, int enabled,
int internal, unsigned flags)
{
- create_breakpoints_sal_default (gdbarch, canonical, lsal,
+ create_breakpoints_sal_default (gdbarch, canonical,
cond_string, extra_string,
type_wanted,
disposition, thread, task,
{
/* The insertion was successful, now let's set the probe's semaphore
if needed. */
- bl->probe->pops->set_semaphore (bl->probe, bl->gdbarch);
+ bl->probe.probe->pops->set_semaphore (bl->probe.probe,
+ bl->probe.objfile,
+ bl->gdbarch);
}
return v;
bkpt_probe_remove_location (struct bp_location *bl)
{
/* Let's clear the semaphore before removing the location. */
- bl->probe->pops->clear_semaphore (bl->probe, bl->gdbarch);
+ bl->probe.probe->pops->clear_semaphore (bl->probe.probe,
+ bl->probe.objfile,
+ bl->gdbarch);
return bkpt_remove_location (bl);
}
static void
tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
struct linespec_result *canonical,
- struct linespec_sals *lsal,
char *cond_string,
char *extra_string,
enum bptype type_wanted,
int from_tty, int enabled,
int internal, unsigned flags)
{
- create_breakpoints_sal_default (gdbarch, canonical, lsal,
+ create_breakpoints_sal_default (gdbarch, canonical,
cond_string, extra_string,
type_wanted,
disposition, thread, task,
print_recreate_thread (tp, fp);
}
+/* Implement the "after_condition_true" breakpoint_ops method for
+ dprintf.
+
+ dprintf's are implemented with regular commands in their command
+ list, but we run the commands here instead of before presenting the
+ stop to the user, as dprintf's don't actually cause a stop. This
+ also makes it so that the commands of multiple dprintfs at the same
+ address are all handled. */
+
+static void
+dprintf_after_condition_true (struct bpstats *bs)
+{
+ struct cleanup *old_chain;
+ struct bpstats tmp_bs = { NULL };
+ struct bpstats *tmp_bs_p = &tmp_bs;
+
+ /* dprintf's never cause a stop. This wasn't set in the
+ check_status hook instead because that would make the dprintf's
+ condition not be evaluated. */
+ bs->stop = 0;
+
+ /* Run the command list here. Take ownership of it instead of
+ copying. We never want these commands to run later in
+ bpstat_do_actions, if a breakpoint that causes a stop happens to
+ be set at same address as this dprintf, or even if running the
+ commands here throws. */
+ tmp_bs.commands = bs->commands;
+ bs->commands = NULL;
+ old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands);
+
+ bpstat_do_actions_1 (&tmp_bs_p);
+
+ /* 'tmp_bs.commands' will usually be NULL by now, but
+ bpstat_do_actions_1 may return early without processing the whole
+ list. */
+ do_cleanups (old_chain);
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
static void
strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
struct linespec_result *canonical,
- struct linespec_sals *lsal,
char *cond_string,
char *extra_string,
enum bptype type_wanted,
int internal, unsigned flags)
{
int i;
+ struct linespec_sals *lsal = VEC_index (linespec_sals,
+ canonical->sals, 0);
/* If the user is creating a static tracepoint by marker id
(strace -m MARKER_ID), then store the sals index, so that
static void
create_breakpoints_sal_default (struct gdbarch *gdbarch,
struct linespec_result *canonical,
- struct linespec_sals *lsal,
char *cond_string,
char *extra_string,
enum bptype type_wanted,
if (user_breakpoint_p (bpt))
disable_breakpoint (bpt);
}
- else if (strchr (args, '.'))
+ else
{
- struct bp_location *loc = find_location_by_number (args);
- if (loc)
+ char *num = extract_arg (&args);
+
+ while (num)
{
- if (loc->enabled)
+ if (strchr (num, '.'))
{
- loc->enabled = 0;
- mark_breakpoint_location_modified (loc);
+ struct bp_location *loc = find_location_by_number (num);
+
+ if (loc)
+ {
+ if (loc->enabled)
+ {
+ loc->enabled = 0;
+ mark_breakpoint_location_modified (loc);
+ }
+ if (target_supports_enable_disable_tracepoint ()
+ && current_trace_status ()->running && loc->owner
+ && is_tracepoint (loc->owner))
+ target_disable_tracepoint (loc);
+ }
+ update_global_location_list (0);
}
- if (target_supports_enable_disable_tracepoint ()
- && current_trace_status ()->running && loc->owner
- && is_tracepoint (loc->owner))
- target_disable_tracepoint (loc);
+ else
+ map_breakpoint_numbers (num, do_map_disable_breakpoint, NULL);
+ num = extract_arg (&args);
}
- update_global_location_list (0);
}
- else
- map_breakpoint_numbers (args, do_map_disable_breakpoint, NULL);
}
static void
if (user_breakpoint_p (bpt))
enable_breakpoint (bpt);
}
- else if (strchr (args, '.'))
+ else
{
- struct bp_location *loc = find_location_by_number (args);
- if (loc)
+ char *num = extract_arg (&args);
+
+ while (num)
{
- if (!loc->enabled)
+ if (strchr (num, '.'))
{
- loc->enabled = 1;
- mark_breakpoint_location_modified (loc);
+ struct bp_location *loc = find_location_by_number (num);
+
+ if (loc)
+ {
+ if (!loc->enabled)
+ {
+ loc->enabled = 1;
+ mark_breakpoint_location_modified (loc);
+ }
+ if (target_supports_enable_disable_tracepoint ()
+ && current_trace_status ()->running && loc->owner
+ && is_tracepoint (loc->owner))
+ target_enable_tracepoint (loc);
+ }
+ update_global_location_list (1);
}
- if (target_supports_enable_disable_tracepoint ()
- && current_trace_status ()->running && loc->owner
- && is_tracepoint (loc->owner))
- target_enable_tracepoint (loc);
+ else
+ map_breakpoint_numbers (num, do_map_enable_breakpoint, NULL);
+ num = extract_arg (&args);
}
- update_global_location_list (1);
}
- else
- map_breakpoint_numbers (args, do_map_enable_breakpoint, NULL);
}
/* This struct packages up disposition data for application to multiple
{
struct bp_target_info *bp_tgt;
- bp_tgt = XZALLOC (struct bp_target_info);
+ bp_tgt = XCNEW (struct bp_target_info);
bp_tgt->placed_address_space = aspace;
bp_tgt->placed_address = pc;
/* Check whether a software single-step breakpoint is inserted at
PC. */
-static int
+int
single_step_breakpoint_inserted_here_p (struct address_space *aspace,
CORE_ADDR pc)
{
}
else if (*args == '\0')
{
- t1 = get_tracepoint_by_number (&args, NULL, 1);
+ t1 = get_tracepoint_by_number (&args, NULL);
if (t1)
trace_pass_set_count (t1, count, from_tty);
}
init_number_or_range (&state, args);
while (!state.finished)
{
- t1 = get_tracepoint_by_number (&args, &state, 1);
+ t1 = get_tracepoint_by_number (&args, &state);
if (t1)
trace_pass_set_count (t1, count, from_tty);
}
/* Utility: parse a tracepoint number and look it up in the list.
If STATE is not NULL, use, get_number_or_range_state and ignore ARG.
- If OPTIONAL_P is true, then if the argument is missing, the most
- recent tracepoint (tracepoint_count) is returned. */
+ If the argument is missing, the most recent tracepoint
+ (tracepoint_count) is returned. */
+
struct tracepoint *
get_tracepoint_by_number (char **arg,
- struct get_number_or_range_state *state,
- int optional_p)
+ struct get_number_or_range_state *state)
{
struct breakpoint *t;
int tpnum;
tpnum = get_number_or_range (state);
}
else if (arg == NULL || *arg == NULL || ! **arg)
- {
- if (optional_p)
- tpnum = tracepoint_count;
- else
- error_no_arg (_("tracepoint number"));
- }
+ tpnum = tracepoint_count;
else
tpnum = get_number (arg);
printf_filtered (_("bad tracepoint number at or near '%s'\n"),
instring);
else
- printf_filtered (_("Tracepoint argument missing "
- "and no previous tracepoint\n"));
+ printf_filtered (_("No previous tracepoint\n"));
return NULL;
}
{
struct breakpoint *tp;
int any = 0;
- char *pathname;
struct cleanup *cleanup;
struct ui_file *fp;
int extra_trace_bits = 0;
return;
}
- pathname = tilde_expand (filename);
- cleanup = make_cleanup (xfree, pathname);
- fp = gdb_fopen (pathname, "w");
+ filename = tilde_expand (filename);
+ cleanup = make_cleanup (xfree, filename);
+ fp = gdb_fopen (filename, "w");
if (!fp)
error (_("Unable to open file '%s' for saving (%s)"),
filename, safe_strerror (errno));
if (extra_trace_bits && *default_collect)
fprintf_unfiltered (fp, "set default-collect %s\n", default_collect);
- do_cleanups (cleanup);
if (from_tty)
printf_filtered (_("Saved to file '%s'.\n"), filename);
+ do_cleanups (cleanup);
}
/* The `save breakpoints' command. */
ops->print_it = bkpt_print_it;
ops->print_mention = bkpt_print_mention;
ops->print_recreate = dprintf_print_recreate;
+ ops->after_condition_true = dprintf_after_condition_true;
}
/* Chain containing all defined "enable breakpoint" subcommands. */
initialize_breakpoint_ops ();
observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
+ observer_attach_free_objfile (disable_breakpoints_in_freed_objfile);
observer_attach_inferior_exit (clear_syscall_counts);
observer_attach_memory_changed (invalidate_bp_value_on_memory_change);
automatic_hardware_breakpoints = 1;
observer_attach_about_to_proceed (breakpoint_about_to_proceed);
+ observer_attach_thread_exit (remove_threaded_breakpoints);
}