/* 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
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))
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
{
- 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);
+ 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);
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 = MSYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym.minsym);
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_overlay_event,
&internal_breakpoint_ops);
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 = MSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i].minsym);
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 = MSYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym.minsym);
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_std_terminate_master,
&internal_breakpoint_ops);
/* 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 = MSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym.minsym);
addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
¤t_target);
b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
/* 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
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;
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)))
+
+ {
+ bs->stop = 0;
+ return;
+ }
+
+ /* Evaluate extension language breakpoints that have a "stop" method
+ implemented. */
+ bs->stop = breakpoint_ext_lang_cond_says_stop (b);
if (is_watchpoint (b))
{
{
bs->stop = 0;
}
- else if (b->thread != -1 && b->thread != thread_id)
- {
- bs->stop = 0;
- }
else if (b->ignore_count > 0)
{
b->ignore_count--;
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);
}
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;
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. */
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 =
/* 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. */
{
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;