#include "cli/cli-script.h"
#include "gdb_assert.h"
#include "block.h"
+#include "solist.h"
+#include "observer.h"
#include "gdb-events.h"
extern void tbreak_at_finish_command (char *, int);
-static void break_command_1 (char *, int, int);
+static int break_command_1 (char *, int, int, struct breakpoint *);
static void mention (struct breakpoint *);
static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int);
-static CORE_ADDR adjust_breakpoint_address (CORE_ADDR bpaddr);
+static CORE_ADDR adjust_breakpoint_address (CORE_ADDR bpaddr,
+ enum bptype bptype);
static void describe_other_breakpoints (CORE_ADDR, asection *);
static int get_number_trailer (char **, int);
+static int do_captured_parse_breakpoint (struct ui_out *, void *);
+
void set_breakpoint_count (int);
typedef enum
static char *ep_parse_optional_filename (char **arg);
-#if defined(CHILD_INSERT_EXEC_CATCHPOINT)
-static void catch_exec_command_1 (char *arg, int tempflag, int from_tty);
-#endif
-
static void create_exception_catchpoint (int tempflag, char *cond_string,
enum exception_event_kind ex_event,
struct symtab_and_line *sal);
if such is available. */
static int can_use_hw_watchpoints;
+/* If AUTO_BOOLEAN_FALSE, gdb will not attempt to create pending breakpoints.
+ If AUTO_BOOLEAN_TRUE, gdb will automatically create pending breakpoints
+ for unrecognized breakpoint locations.
+ If AUTO_BOOLEAN_AUTO, gdb will query when breakpoints are unrecognized. */
+static enum auto_boolean pending_break_support;
+
void _initialize_breakpoint (void);
extern int addressprint; /* Print machine addresses? */
/* Pointer to current exception event record */
static struct exception_event_record *current_exception_event;
-/* Indicator of whether exception catchpoints should be nuked
- between runs of a program */
-int exception_catchpoints_are_fragile = 0;
+/* Indicator of whether exception catchpoints should be nuked between
+ runs of a program. */
+int deprecated_exception_catchpoints_are_fragile = 0;
/* Indicator of when exception catchpoints set-up should be
- reinitialized -- e.g. when program is re-run */
-int exception_support_initialized = 0;
+ reinitialized -- e.g. when program is re-run. */
+int deprecated_exception_support_initialized = 0;
/* This function returns a pointer to the string representation of the
pathname of the dynamically-linked library that has just been
static int
breakpoint_enabled (struct breakpoint *b)
{
- return b->enable_state == bp_enabled;
+ return (b->enable_state == bp_enabled && !b->pending);
}
/* Set breakpoint count to NUM. */
/* I don't know if it matters whether this is the string the user
typed in or the decompiled expression. */
b->cond_string = savestring (arg, strlen (arg));
- b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
- if (*arg)
- error ("Junk at end of expression");
+ if (!b->pending)
+ {
+ b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+ if (*arg)
+ error ("Junk at end of expression");
+ }
}
breakpoints_changed ();
breakpoint_modify_event (b->number);
shadow contents, not the breakpoints themselves. From breakpoint.c. */
int
-read_memory_nobpt (CORE_ADDR memaddr, char *myaddr, unsigned len)
+deprecated_read_memory_nobpt (CORE_ADDR memaddr, char *myaddr, unsigned len)
{
int status;
struct bp_location *b;
if (bp_addr > memaddr)
{
/* Copy the section of memory before the breakpoint. */
- status = read_memory_nobpt (memaddr, myaddr, bp_addr - memaddr);
+ status = deprecated_read_memory_nobpt (memaddr, myaddr, bp_addr - memaddr);
if (status != 0)
return status;
}
if (bp_addr + bp_size < memaddr + len)
{
/* Copy the section of memory after the breakpoint. */
- status = read_memory_nobpt (bp_addr + bp_size,
+ status = deprecated_read_memory_nobpt (bp_addr + bp_size,
myaddr + bp_addr + bp_size - memaddr,
memaddr + len - (bp_addr + bp_size));
if (status != 0)
return 0;
}
+/* Helper routine: free the value chain for a breakpoint (watchpoint). */
+
+static void free_valchain (struct bp_location *b)
+{
+ struct value *v;
+ struct value *n;
+
+ /* Free the saved value chain. We will construct a new one
+ the next time the watchpoint is inserted. */
+ for (v = b->owner->val_chain; v; v = n)
+ {
+ n = v->next;
+ value_free (v);
+ }
+ b->owner->val_chain = NULL;
+}
+
/* Insert a low-level "breakpoint" of some type. BPT is the breakpoint.
Any error messages are printed to TMP_ERROR_STREAM; and DISABLED_BREAKS,
PROCESS_WARNING, and HW_BREAKPOINT_ERROR are used to report problems.
must watch. As soon as a many-to-one mapping is available I'll
convert this. */
- struct frame_info *saved_frame;
- int saved_level, within_current_scope;
+ int within_current_scope;
struct value *mark = value_mark ();
struct value *v;
+ struct frame_id saved_frame_id;
- /* Save the current frame and level so we can restore it after
+ /* Save the current frame's ID so we can restore it after
evaluating the watchpoint expression on its own frame. */
/* FIXME drow/2003-09-09: It would be nice if evaluate_expression
took a frame parameter, so that we didn't have to change the
selected frame. */
- saved_frame = deprecated_selected_frame;
- saved_level = frame_relative_level (deprecated_selected_frame);
+ saved_frame_id = get_frame_id (deprecated_selected_frame);
/* Determine if the watchpoint is within scope. */
if (bpt->owner->exp_valid_block == NULL)
if (within_current_scope)
{
+ free_valchain (bpt);
+
/* Evaluate the expression and cut the chain of values
produced off from the value chain.
bpt->owner->disposition = disp_del_at_next_stop;
}
- /* Restore the frame and level. */
- if (saved_frame != deprecated_selected_frame
- || saved_level != frame_relative_level (deprecated_selected_frame))
- select_frame (saved_frame);
+ /* Restore the selected frame. */
+ select_frame (frame_find_by_id (saved_frame_id));
return val;
}
if ((is == mark_uninserted) && (b->inserted))
warning ("Could not remove hardware watchpoint %d.",
b->owner->number);
-
- /* Free the saved value chain. We will construct a new one
- the next time the watchpoint is inserted. */
- for (v = b->owner->val_chain; v; v = n)
- {
- n = v->next;
- value_free (v);
- }
- b->owner->val_chain = NULL;
}
else if ((b->owner->type == bp_catch_fork ||
b->owner->type == bp_catch_vfork ||
default:
/* Likewise for exception catchpoints in dynamic-linked
executables where required */
- if (ep_is_exception_catchpoint (b) &&
- exception_catchpoints_are_fragile)
+ if (ep_is_exception_catchpoint (b)
+ && deprecated_exception_catchpoints_are_fragile)
{
warning_needed = 1;
delete_breakpoint (b);
}
}
- if (exception_catchpoints_are_fragile)
- exception_support_initialized = 0;
+ if (deprecated_exception_catchpoints_are_fragile)
+ deprecated_exception_support_initialized = 0;
/* Don't issue the warning unless it's really needed... */
if (warning_needed && (context != inf_exited))
return 0;
}
-/* Return nonzero if FRAME is a dummy frame. We can't use
- DEPRECATED_PC_IN_CALL_DUMMY because figuring out the saved SP would
- take too much time, at least using frame_register() on the 68k.
- This means that for this function to work right a port must use the
- bp_call_dummy breakpoint. */
+/* This function returns non-zero iff there is a software breakpoint
+ inserted at PC. */
int
-deprecated_frame_in_dummy (struct frame_info *frame)
+software_breakpoint_inserted_here_p (CORE_ADDR pc)
{
- struct breakpoint *b;
+ struct bp_location *bpt;
+ int any_breakpoint_here = 0;
- /* This function is used by two files: get_frame_type(), after first
- checking that !DEPRECATED_USE_GENERIC_DUMMY_FRAMES; and
- sparc-tdep.c, which doesn't yet use generic dummy frames anyway. */
- gdb_assert (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES);
+ ALL_BP_LOCATIONS (bpt)
+ {
+ if (bpt->loc_type != bp_loc_software_breakpoint)
+ continue;
+
+ if ((breakpoint_enabled (bpt->owner)
+ || bpt->owner->enable_state == bp_permanent)
+ && bpt->inserted
+ && bpt->address == pc) /* bp is enabled and matches pc */
+ {
+ if (overlay_debugging
+ && section_is_overlay (bpt->section)
+ && !section_is_mapped (bpt->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else
+ return 1;
+ }
+ }
- ALL_BREAKPOINTS (b)
- {
- if (b->type == bp_call_dummy
- && frame_id_eq (b->frame_id, get_frame_id (frame))
- /* We need to check the PC as well as the frame on the sparc,
- for signals.exp in the testsuite. */
- && (get_frame_pc (frame)
- >= (b->loc->address
- - DEPRECATED_SIZEOF_CALL_DUMMY_WORDS / sizeof (LONGEST) * DEPRECATED_REGISTER_SIZE))
- && get_frame_pc (frame) <= b->loc->address)
- return 1;
- }
return 0;
}
}
}
-/* Get a bpstat associated with having just stopped at address *PC
- and frame address CORE_ADDRESS. Update *PC to point at the
- breakpoint (if we hit a breakpoint). NOT_A_SW_BREAKPOINT is nonzero
- if this is known to not be a real breakpoint (it could still be a
- watchpoint, though). */
+/* Get a bpstat associated with having just stopped at address
+ BP_ADDR in thread PTID. STOPPED_BY_WATCHPOINT is 1 if the
+ target thinks we stopped due to a hardware watchpoint, 0 if we
+ know we did not trigger a hardware watchpoint, and -1 if we do not know. */
/* Determine whether we stopped at a breakpoint, etc, or whether we
don't understand this stop. Result is a chain of bpstat's such that:
commands, FIXME??? fields. */
bpstat
-bpstat_stop_status (CORE_ADDR *pc, int not_a_sw_breakpoint)
+bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid, int stopped_by_watchpoint)
{
struct breakpoint *b, *temp;
- CORE_ADDR bp_addr;
/* True if we've hit a breakpoint (as opposed to a watchpoint). */
int real_breakpoint = 0;
/* Root of the chain of bpstat's */
struct bpstats root_bs[1];
/* Pointer to the last thing in the chain currently. */
bpstat bs = root_bs;
-
- /* Get the address where the breakpoint would have been. The
- "not_a_sw_breakpoint" argument is meant to distinguish between a
- breakpoint trap event and a trace/singlestep trap event. For a
- trace/singlestep trap event, we would not want to subtract
- DECR_PC_AFTER_BREAK from the PC. */
-
- bp_addr = *pc - (not_a_sw_breakpoint ? 0 : DECR_PC_AFTER_BREAK);
+ int thread_id = pid_to_thread_id (ptid);
ALL_BREAKPOINTS_SAFE (b, temp)
{
continue;
}
+ /* Continuable hardware watchpoints are treated as non-existent if the
+ reason we stopped wasn't a hardware watchpoint (we didn't stop on
+ some data address). Otherwise gdb won't stop on a break instruction
+ in the code (not from a breakpoint) when a hardware watchpoint has
+ been defined. */
+
+ if ((b->type == bp_hardware_watchpoint
+ || b->type == bp_read_watchpoint
+ || b->type == bp_access_watchpoint)
+ && !stopped_by_watchpoint)
+ continue;
+
if (b->type == bp_hardware_breakpoint)
{
- if (b->loc->address != *pc)
+ if (b->loc->address != bp_addr)
continue;
if (overlay_debugging /* unmapped overlay section */
&& section_is_overlay (b->loc->section)
/* Don't consider this a hit. */
--(b->hit_count);
}
+ else if (b->thread != -1 && b->thread != thread_id)
+ {
+ bs->stop = 0;
+ /* Don't consider this a hit. */
+ --(b->hit_count);
+ }
else if (b->ignore_count > 0)
{
b->ignore_count--;
bs->next = NULL; /* Terminate the chain */
bs = root_bs->next; /* Re-grab the head of the chain */
- if (real_breakpoint && bs)
- {
- if (bs->breakpoint_at->type != bp_hardware_breakpoint)
- {
- if (DECR_PC_AFTER_BREAK != 0)
- {
- *pc = bp_addr;
- write_pc (bp_addr);
- }
- }
- }
-
/* The value of a hardware watchpoint hasn't changed, but the
intermediate memory locations we are watching may have. */
if (bs && !bs->stop &&
/* step_resume entries: a step resume breakpoint overrides another
breakpoint of signal handling (see comment in wait_for_inferior
- at first PC_IN_SIGTRAMP where we set the step_resume breakpoint). */
+ at where we set the step_resume breakpoint). */
/* We handle the through_sigtramp_breakpoint the same way; having both
one of those and a step_resume_breakpoint is probably very rare (?). */
if (addressprint)
{
annotate_field (4);
- ui_out_field_core_addr (uiout, "addr", b->loc->address);
+ if (b->pending)
+ ui_out_field_string (uiout, "addr", "<PENDING>");
+ else
+ ui_out_field_core_addr (uiout, "addr", b->loc->address);
}
annotate_field (5);
*last_addr = b->loc->address;
ui_out_text (uiout, ":");
ui_out_field_int (uiout, "line", b->line_number);
}
+ else if (b->pending)
+ {
+ ui_out_field_string (uiout, "pending", b->addr_string);
+ }
else
{
print_address_symbolic (b->loc->address, stb->stream, demangle, "");
ui_out_field_stream (uiout, "cond", stb);
ui_out_text (uiout, "\n");
}
-
+
+ if (b->pending && b->cond_string)
+ {
+ annotate_field (7);
+ ui_out_text (uiout, "\tstop only if ");
+ ui_out_field_string (uiout, "cond", b->cond_string);
+ ui_out_text (uiout, "\n");
+ }
+
if (b->thread != -1)
{
/* FIXME should make an annotation for this */
ALL_BREAKPOINTS (b)
if (b->loc->address == pc) /* address match / overlay match */
- if (!overlay_debugging || b->loc->section == section)
+ if (!b->pending && (!overlay_debugging || b->loc->section == section))
others++;
if (others > 0)
{
printf_filtered ("Note: breakpoint%s ", (others > 1) ? "s" : "");
ALL_BREAKPOINTS (b)
if (b->loc->address == pc) /* address match / overlay match */
- if (!overlay_debugging || b->loc->section == section)
+ if (!b->pending && (!overlay_debugging || b->loc->section == section))
{
others--;
printf_filtered ("%d%s%s ",
ALL_BP_LOCATIONS (b)
if (b->owner->enable_state != bp_disabled
&& b->owner->enable_state != bp_shlib_disabled
+ && !b->owner->pending
&& b->owner->enable_state != bp_call_disabled
&& b->address == address /* address / overlay match */
&& (!overlay_debugging || b->section == section)
{
if (b->owner->enable_state != bp_disabled
&& b->owner->enable_state != bp_shlib_disabled
+ && !b->owner->pending
&& b->owner->enable_state != bp_call_disabled
&& b->address == address /* address / overlay match */
&& (!overlay_debugging || b->section == section)
this function is simply the identity function. */
static CORE_ADDR
-adjust_breakpoint_address (CORE_ADDR bpaddr)
+adjust_breakpoint_address (CORE_ADDR bpaddr, enum bptype bptype)
{
if (!gdbarch_adjust_breakpoint_address_p (current_gdbarch))
{
/* Very few targets need any kind of breakpoint adjustment. */
return bpaddr;
}
+ else if (bptype == bp_watchpoint
+ || bptype == bp_hardware_watchpoint
+ || bptype == bp_read_watchpoint
+ || bptype == bp_access_watchpoint
+ || bptype == bp_catch_fork
+ || bptype == bp_catch_vfork
+ || bptype == bp_catch_exec)
+ {
+ /* Watchpoints and the various bp_catch_* eventpoints should not
+ have their addresses modified. */
+ return bpaddr;
+ }
else
{
CORE_ADDR adjusted_bpaddr;
memset (b, 0, sizeof (*b));
b->loc = allocate_bp_location (b, bptype);
b->loc->requested_address = sal.pc;
- b->loc->address = adjust_breakpoint_address (b->loc->requested_address);
+ b->loc->address = adjust_breakpoint_address (b->loc->requested_address,
+ bptype);
if (sal.symtab == NULL)
b->source_file = NULL;
else
b->forked_inferior_pid = 0;
b->exec_pathname = NULL;
b->ops = NULL;
+ b->pending = 0;
/* Add this breakpoint to the end of the chain
so that a list of breakpoints will come out in order
b->enable_state = bp_enabled;
/* addr_string has to be used or breakpoint_re_set will delete me. */
- xasprintf (&b->addr_string, "*0x%s", paddr (b->loc->address));
+ b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address));
return b;
}
delete_breakpoint (b);
}
+struct captured_parse_breakpoint_args
+ {
+ char **arg_p;
+ struct symtabs_and_lines *sals_p;
+ char ***addr_string_p;
+ int *not_found_ptr;
+ };
+
+struct lang_and_radix
+ {
+ enum language lang;
+ int radix;
+ };
+
+/* Cleanup helper routine to restore the current language and
+ input radix. */
+static void
+do_restore_lang_radix_cleanup (void *old)
+{
+ struct lang_and_radix *p = old;
+ set_language (p->lang);
+ input_radix = p->radix;
+}
+
+/* Try and resolve a pending breakpoint. */
+static int
+resolve_pending_breakpoint (struct breakpoint *b)
+{
+ /* Try and reparse the breakpoint in case the shared library
+ is now loaded. */
+ struct symtabs_and_lines sals;
+ struct symtab_and_line pending_sal;
+ char **cond_string = (char **) NULL;
+ char *copy_arg = b->addr_string;
+ char **addr_string;
+ char *errmsg;
+ int rc;
+ int not_found = 0;
+ struct ui_file *old_gdb_stderr;
+ struct lang_and_radix old_lr;
+ struct cleanup *old_chain;
+
+ /* Set language, input-radix, then reissue breakpoint command.
+ Ensure the language and input-radix are restored afterwards. */
+ old_lr.lang = current_language->la_language;
+ old_lr.radix = input_radix;
+ old_chain = make_cleanup (do_restore_lang_radix_cleanup, &old_lr);
+
+ set_language (b->language);
+ input_radix = b->input_radix;
+ rc = break_command_1 (b->addr_string, b->flag, b->from_tty, b);
+
+ if (rc == GDB_RC_OK)
+ /* Pending breakpoint has been resolved. */
+ printf_filtered ("Pending breakpoint \"%s\" resolved\n", b->addr_string);
+
+ do_cleanups (old_chain);
+ return rc;
+}
+
#ifdef SOLIB_ADD
void
remove_solib_event_breakpoints (void)
}
}
-/* Try to reenable any breakpoints in shared libraries. */
+/* Disable any breakpoints that are in in an unloaded shared library. Only
+ apply to enabled breakpoints, disabled ones can just stay disabled. */
+
void
-re_enable_breakpoints_in_shlibs (void)
+disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
{
struct breakpoint *b;
+ int disabled_shlib_breaks = 0;
+#if defined (PC_SOLIB)
+ /* See also: insert_breakpoints, under DISABLE_UNSETTABLE_BREAK. */
ALL_BREAKPOINTS (b)
- if (b->enable_state == bp_shlib_disabled)
- {
- char buf[1], *lib;
+ {
+ if ((b->loc->loc_type == bp_loc_hardware_breakpoint
+ || b->loc->loc_type == bp_loc_software_breakpoint)
+ && breakpoint_enabled (b)
+ && !b->loc->duplicate)
+ {
+ char *so_name = PC_SOLIB (b->loc->address);
+ if (so_name
+ && !strcmp (so_name, solib->so_name))
+ {
+ b->enable_state = bp_shlib_disabled;
+ /* At this point, we cannot rely on remove_breakpoint
+ succeeding so we must mark the breakpoint as not inserted
+ to prevent future errors occurring in remove_breakpoints. */
+ b->loc->inserted = 0;
+ if (!disabled_shlib_breaks)
+ {
+ target_terminal_ours_for_output ();
+ warning ("Temporarily disabling breakpoints for unloaded shared library \"%s\"",
+ so_name);
+ }
+ disabled_shlib_breaks = 1;
+ }
+ }
+ }
+#endif
+}
- /* Do not reenable the breakpoint if the shared library
- is still not mapped in. */
- lib = PC_SOLIB (b->loc->address);
- if (lib != NULL && target_read_memory (b->loc->address, buf, 1) == 0)
- b->enable_state = bp_enabled;
- }
+/* Try to reenable any breakpoints in shared libraries. */
+void
+re_enable_breakpoints_in_shlibs (void)
+{
+ struct breakpoint *b, *tmp;
+
+ ALL_BREAKPOINTS_SAFE (b, tmp)
+ {
+ if (b->enable_state == bp_shlib_disabled)
+ {
+ char buf[1], *lib;
+
+ /* Do not reenable the breakpoint if the shared library
+ is still not mapped in. */
+ lib = PC_SOLIB (b->loc->address);
+ if (lib != NULL && target_read_memory (b->loc->address, buf, 1) == 0)
+ b->enable_state = bp_enabled;
+ }
+ else if (b->pending && (b->enable_state == bp_enabled))
+ {
+ if (resolve_pending_breakpoint (b) == GDB_RC_OK)
+ delete_breakpoint (b);
+ }
+ }
}
#endif
if (b->type == bp_longjmp_resume)
{
b->loc->requested_address = pc;
- b->loc->address = adjust_breakpoint_address (b->loc->requested_address);
+ b->loc->address = adjust_breakpoint_address (b->loc->requested_address,
+ b->type);
b->enable_state = bp_enabled;
b->frame_id = frame_id;
check_duplicates (b);
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
- /* FIXME: This is misplaced; mention() is called by things (like hitting a
- watchpoint) other than breakpoint creation. It should be possible to
- clean this up and at the same time replace the random calls to
- breakpoint_changed with this hook, as has already been done for
- delete_breakpoint_hook and so on. */
- if (create_breakpoint_hook)
- create_breakpoint_hook (b);
+ /* FIXME: This is misplaced; mention() is called by things (like
+ hitting a watchpoint) other than breakpoint creation. It should
+ be possible to clean this up and at the same time replace the
+ random calls to breakpoint_changed with this hook, as has already
+ been done for deprecated_delete_breakpoint_hook and so on. */
+ if (deprecated_create_breakpoint_hook)
+ deprecated_create_breakpoint_hook (b);
breakpoint_create_event (b->number);
if (b->ops != NULL && b->ops->print_mention != NULL)
if (say_where)
{
- if (addressprint || b->source_file == NULL)
+ if (b->pending)
{
- printf_filtered (" at ");
- print_address_numeric (b->loc->address, 1, gdb_stdout);
+ printf_filtered (" (%s) pending.", b->addr_string);
+ }
+ else
+ {
+ if (addressprint || b->source_file == NULL)
+ {
+ printf_filtered (" at ");
+ print_address_numeric (b->loc->address, 1, gdb_stdout);
+ }
+ if (b->source_file)
+ printf_filtered (": file %s, line %d.",
+ b->source_file, b->line_number);
}
- if (b->source_file)
- printf_filtered (": file %s, line %d.",
- b->source_file, b->line_number);
}
do_cleanups (old_chain);
if (ui_out_is_mi_like_p (uiout))
SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i],
COND[i] and COND_STRING[i] values.
+ The parameter PENDING_BP points to a pending breakpoint that is
+ the basis of the breakpoints currently being created. The pending
+ breakpoint may contain a separate condition string or commands
+ that were added after the initial pending breakpoint was created.
+
NOTE: If the function succeeds, the caller is expected to cleanup
the arrays ADDR_STRING, COND_STRING, COND and SALS (but not the
array contents). If the function fails (error() is called), the
create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
struct expression **cond, char **cond_string,
enum bptype type, enum bpdisp disposition,
- int thread, int ignore_count, int from_tty)
+ int thread, int ignore_count, int from_tty,
+ struct breakpoint *pending_bp)
{
if (type == bp_hardware_breakpoint)
{
else
/* addr_string has to be used or breakpoint_re_set will delete
me. */
- xasprintf (&b->addr_string, "*0x%s", paddr (b->loc->address));
+ b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address));
b->cond_string = cond_string[i];
b->ignore_count = ignore_count;
b->enable_state = bp_enabled;
b->disposition = disposition;
+ /* If resolving a pending breakpoint, a check must be made to see if
+ the user has specified a new condition or commands for the
+ breakpoint. A new condition will override any condition that was
+ initially specified with the initial breakpoint command. */
+ if (pending_bp)
+ {
+ char *arg;
+ if (pending_bp->cond_string)
+ {
+ arg = pending_bp->cond_string;
+ b->cond_string = savestring (arg, strlen (arg));
+ b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+ if (*arg)
+ error ("Junk at end of pending breakpoint condition expression");
+ }
+ /* If there are commands associated with the breakpoint, they should
+ be copied too. */
+ if (pending_bp->commands)
+ b->commands = copy_command_lines (pending_bp->commands);
+
+ /* We have to copy over the ignore_count and thread as well. */
+ b->ignore_count = pending_bp->ignore_count;
+ b->thread = pending_bp->thread;
+ }
mention (b);
}
}
static void
parse_breakpoint_sals (char **address,
struct symtabs_and_lines *sals,
- char ***addr_string)
+ char ***addr_string,
+ int *not_found_ptr)
{
char *addr_start = *address;
*addr_string = NULL;
|| ((strchr ("+-", (*address)[0]) != NULL)
&& ((*address)[1] != '['))))
*sals = decode_line_1 (address, 1, default_breakpoint_symtab,
- default_breakpoint_line, addr_string, NULL);
+ default_breakpoint_line, addr_string,
+ not_found_ptr);
else
- *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, addr_string, NULL);
+ *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0,
+ addr_string, not_found_ptr);
}
/* For any SAL that didn't have a canonical string, fill one in. */
if (sals->nelts > 0 && *addr_string == NULL)
Give the target a chance to bless sals.sals[i].pc before we
try to make a breakpoint for it. */
- if (PC_REQUIRES_RUN_BEFORE_USE (sals->sals[i].pc))
+#ifdef DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE
+ if (DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE (sals->sals[i].pc))
{
if (address == NULL)
error ("Cannot break without a running program.");
error ("Cannot break on %s without a running program.",
address);
}
+#endif
}
}
+static int
+do_captured_parse_breakpoint (struct ui_out *ui, void *data)
+{
+ struct captured_parse_breakpoint_args *args = data;
+
+ parse_breakpoint_sals (args->arg_p, args->sals_p, args->addr_string_p,
+ args->not_found_ptr);
+
+ return GDB_RC_OK;
+}
+
/* Set a breakpoint according to ARG (function, linenum or *address)
flag: first bit : 0 non-temporary, 1 temporary.
- second bit : 0 normal breakpoint, 1 hardware breakpoint. */
+ second bit : 0 normal breakpoint, 1 hardware breakpoint.
-static void
-break_command_1 (char *arg, int flag, int from_tty)
+ PENDING_BP is non-NULL when this function is being called to resolve
+ a pending breakpoint. */
+
+static int
+break_command_1 (char *arg, int flag, int from_tty, struct breakpoint *pending_bp)
{
int tempflag, hardwareflag;
struct symtabs_and_lines sals;
struct expression **cond = 0;
- /* Pointers in arg to the start, and one past the end, of the
- condition. */
+ struct symtab_and_line pending_sal;
char **cond_string = (char **) NULL;
+ char *copy_arg;
+ char *err_msg;
char *addr_start = arg;
char **addr_string;
struct cleanup *old_chain;
struct cleanup *breakpoint_chain = NULL;
- int i;
+ struct captured_parse_breakpoint_args parse_args;
+ int i, rc;
+ int pending = 0;
int thread = -1;
int ignore_count = 0;
+ int not_found = 0;
hardwareflag = flag & BP_HARDWAREFLAG;
tempflag = flag & BP_TEMPFLAG;
sals.sals = NULL;
sals.nelts = 0;
addr_string = NULL;
- parse_breakpoint_sals (&arg, &sals, &addr_string);
- if (!sals.nelts)
- return;
+ parse_args.arg_p = &arg;
+ parse_args.sals_p = &sals;
+ parse_args.addr_string_p = &addr_string;
+ parse_args.not_found_ptr = ¬_found;
+
+ rc = catch_exceptions_with_msg (uiout, do_captured_parse_breakpoint,
+ &parse_args, NULL, &err_msg,
+ RETURN_MASK_ALL);
+
+ /* If caller is interested in rc value from parse, set value. */
+
+ if (rc != GDB_RC_OK)
+ {
+ /* Check for file or function not found. */
+ if (not_found)
+ {
+ /* If called to resolve pending breakpoint, just return error code. */
+ if (pending_bp)
+ return rc;
+
+ error_output_message (NULL, err_msg);
+ xfree (err_msg);
+
+ /* If pending breakpoint support is turned off, throw error. */
+
+ if (pending_break_support == AUTO_BOOLEAN_FALSE)
+ throw_exception (RETURN_ERROR);
+
+ /* If pending breakpoint support is auto query and the user selects
+ no, then simply return the error code. */
+ if (pending_break_support == AUTO_BOOLEAN_AUTO &&
+ !nquery ("Make breakpoint pending on future shared library load? "))
+ return rc;
+
+ /* At this point, either the user was queried about setting a
+ pending breakpoint and selected yes, or pending breakpoint
+ behavior is on and thus a pending breakpoint is defaulted
+ on behalf of the user. */
+ copy_arg = xstrdup (addr_start);
+ addr_string = ©_arg;
+ sals.nelts = 1;
+ sals.sals = &pending_sal;
+ pending_sal.pc = 0;
+ pending = 1;
+ }
+ else
+ return rc;
+ }
+ else if (!sals.nelts)
+ return GDB_RC_FAIL;
/* Create a chain of things that always need to be cleaned up. */
old_chain = make_cleanup (null_cleanup, 0);
- /* Make sure that all storage allocated to SALS gets freed. */
- make_cleanup (xfree, sals.sals);
-
- /* Cleanup the addr_string array but not its contents. */
- make_cleanup (xfree, addr_string);
+ if (!pending)
+ {
+ /* Make sure that all storage allocated to SALS gets freed. */
+ make_cleanup (xfree, sals.sals);
+
+ /* Cleanup the addr_string array but not its contents. */
+ make_cleanup (xfree, addr_string);
+ }
/* Allocate space for all the cond expressions. */
cond = xcalloc (sals.nelts, sizeof (struct expression *));
/* Resolve all line numbers to PC's and verify that the addresses
are ok for the target. */
- breakpoint_sals_to_pc (&sals, addr_start);
+ if (!pending)
+ breakpoint_sals_to_pc (&sals, addr_start);
/* Verify that condition can be parsed, before setting any
breakpoints. Allocate a separate condition expression for each
breakpoint. */
thread = -1; /* No specific thread yet */
- for (i = 0; i < sals.nelts; i++)
+ if (!pending)
{
- char *tok = arg;
- while (tok && *tok)
+ for (i = 0; i < sals.nelts; i++)
{
- char *end_tok;
- int toklen;
- char *cond_start = NULL;
- char *cond_end = NULL;
- while (*tok == ' ' || *tok == '\t')
- tok++;
-
- end_tok = tok;
-
- while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
- end_tok++;
-
- toklen = end_tok - tok;
-
- if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
+ char *tok = arg;
+ while (tok && *tok)
{
- tok = cond_start = end_tok + 1;
- cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0);
- make_cleanup (xfree, cond[i]);
- cond_end = tok;
- cond_string[i] = savestring (cond_start, cond_end - cond_start);
- make_cleanup (xfree, cond_string[i]);
- }
- else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
- {
- char *tmptok;
-
- tok = end_tok + 1;
- tmptok = tok;
- thread = strtol (tok, &tok, 0);
- if (tok == tmptok)
- error ("Junk after thread keyword.");
- if (!valid_thread_id (thread))
- error ("Unknown thread %d\n", thread);
+ char *end_tok;
+ int toklen;
+ char *cond_start = NULL;
+ char *cond_end = NULL;
+ while (*tok == ' ' || *tok == '\t')
+ tok++;
+
+ end_tok = tok;
+
+ while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
+ end_tok++;
+
+ toklen = end_tok - tok;
+
+ if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
+ {
+ tok = cond_start = end_tok + 1;
+ cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc),
+ 0);
+ make_cleanup (xfree, cond[i]);
+ cond_end = tok;
+ cond_string[i] = savestring (cond_start,
+ cond_end - cond_start);
+ make_cleanup (xfree, cond_string[i]);
+ }
+ else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
+ {
+ char *tmptok;
+
+ tok = end_tok + 1;
+ tmptok = tok;
+ thread = strtol (tok, &tok, 0);
+ if (tok == tmptok)
+ error ("Junk after thread keyword.");
+ if (!valid_thread_id (thread))
+ error ("Unknown thread %d\n", thread);
+ }
+ else
+ error ("Junk at end of arguments.");
}
- else
- error ("Junk at end of arguments.");
}
+ create_breakpoints (sals, addr_string, cond, cond_string,
+ hardwareflag ? bp_hardware_breakpoint
+ : bp_breakpoint,
+ tempflag ? disp_del : disp_donttouch,
+ thread, ignore_count, from_tty,
+ pending_bp);
}
-
- create_breakpoints (sals, addr_string, cond, cond_string,
- hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
- tempflag ? disp_del : disp_donttouch,
- thread, ignore_count, from_tty);
-
+ else
+ {
+ struct symtab_and_line sal;
+ struct breakpoint *b;
+
+ sal.symtab = NULL;
+ sal.pc = 0;
+
+ make_cleanup (xfree, copy_arg);
+
+ b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint
+ : bp_breakpoint);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->cond = *cond;
+ b->thread = thread;
+ b->addr_string = *addr_string;
+ b->cond_string = *cond_string;
+ b->ignore_count = ignore_count;
+ b->pending = 1;
+ b->disposition = tempflag ? disp_del : disp_donttouch;
+ b->from_tty = from_tty;
+ b->flag = flag;
+ mention (b);
+ }
+
if (sals.nelts > 1)
{
warning ("Multiple breakpoints were set.");
discard_cleanups (breakpoint_chain);
/* But cleanup everything else. */
do_cleanups (old_chain);
+
+ return GDB_RC_OK;
}
/* Set a breakpoint of TYPE/DISPOSITION according to ARG (function,
sals.nelts = 0;
address_end = args->address;
addr_string = NULL;
- parse_breakpoint_sals (&address_end, &sals, &addr_string);
+ parse_breakpoint_sals (&address_end, &sals, &addr_string, 0);
if (!sals.nelts)
return GDB_RC_NONE;
create_breakpoints (sals, addr_string, cond, cond_string,
args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
args->tempflag ? disp_del : disp_donttouch,
- args->thread, args->ignore_count, 0/*from-tty*/);
+ args->thread, args->ignore_count, 0/*from-tty*/,
+ NULL/*pending_bp*/);
/* That's it. Discard the cleanups for data inserted into the
breakpoint. */
addr_string = xstrprintf ("*0x%s %s", paddr_nz (high), extra_args);
else
addr_string = xstrprintf ("*0x%s", paddr_nz (high));
- break_command_1 (addr_string, flag, from_tty);
+ break_command_1 (addr_string, flag, from_tty, NULL);
xfree (addr_string);
}
else
extra_args);
else
break_string = xstrprintf ("*0x%s", paddr_nz (high));
- break_command_1 (break_string, flag, from_tty);
+ break_command_1 (break_string, flag, from_tty, NULL);
xfree (break_string);
}
else
void
break_command (char *arg, int from_tty)
{
- break_command_1 (arg, 0, from_tty);
+ break_command_1 (arg, 0, from_tty, NULL);
}
void
void
tbreak_command (char *arg, int from_tty)
{
- break_command_1 (arg, BP_TEMPFLAG, from_tty);
+ break_command_1 (arg, BP_TEMPFLAG, from_tty, NULL);
}
void
static void
hbreak_command (char *arg, int from_tty)
{
- break_command_1 (arg, BP_HARDWAREFLAG, from_tty);
+ break_command_1 (arg, BP_HARDWAREFLAG, from_tty, NULL);
}
static void
thbreak_command (char *arg, int from_tty)
{
- break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty);
+ break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty, NULL);
}
static void
if (badInput)
printf_filtered ("Usage: stop in <function | address>\n");
else
- break_command_1 (arg, 0, from_tty);
+ break_command_1 (arg, 0, from_tty, NULL);
}
static void
if (badInput)
printf_filtered ("Usage: stop at <line>\n");
else
- break_command_1 (arg, 0, from_tty);
+ break_command_1 (arg, 0, from_tty, NULL);
}
/* accessflag: hw_write: watch write,
scope_breakpoint->loc->requested_address
= get_frame_pc (prev_frame);
scope_breakpoint->loc->address
- = adjust_breakpoint_address (scope_breakpoint->loc->requested_address);
+ = adjust_breakpoint_address (scope_breakpoint->loc->requested_address,
+ scope_breakpoint->type);
/* The scope breakpoint is related to the watchpoint. We
will need to act on them together. */
in hardware. If the watchpoint can not be handled
in hardware return zero. */
-#if !defined(TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT)
-#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(BYTE_SIZE) \
- ((BYTE_SIZE) <= (DEPRECATED_REGISTER_SIZE))
-#endif
-
#if !defined(TARGET_REGION_OK_FOR_HW_WATCHPOINT)
#define TARGET_REGION_OK_FOR_HW_WATCHPOINT(ADDR,LEN) \
(TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(LEN))
}
catch_fork_kind;
-#if defined(CHILD_INSERT_FORK_CATCHPOINT) || defined(CHILD_INSERT_VFORK_CATCHPOINT)
-static void catch_fork_command_1 (catch_fork_kind fork_kind,
- char *arg, int tempflag, int from_tty);
-
static void
catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
int from_tty)
break;
}
}
-#endif
-#if defined(CHILD_INSERT_EXEC_CATCHPOINT)
static void
catch_exec_command_1 (char *arg, int tempflag, int from_tty)
{
and enable reporting of such events. */
create_exec_event_catchpoint (tempflag, cond_string);
}
-#endif
-#if defined(SOLIB_ADD)
static void
catch_load_command_1 (char *arg, int tempflag, int from_tty)
{
SOLIB_CREATE_CATCH_UNLOAD_HOOK (PIDGET (inferior_ptid), tempflag,
dll_pathname, cond_string);
}
-#endif /* SOLIB_ADD */
/* Commands to deal with catching exceptions. */
}
else if (strncmp (arg1_start, "fork", arg1_length) == 0)
{
-#if defined(CHILD_INSERT_FORK_CATCHPOINT)
catch_fork_command_1 (catch_fork, arg1_end + 1, tempflag, from_tty);
-#else
- error ("Catch of fork not yet implemented");
-#endif
}
else if (strncmp (arg1_start, "vfork", arg1_length) == 0)
{
-#if defined(CHILD_INSERT_VFORK_CATCHPOINT)
catch_fork_command_1 (catch_vfork, arg1_end + 1, tempflag, from_tty);
-#else
- error ("Catch of vfork not yet implemented");
-#endif
}
else if (strncmp (arg1_start, "exec", arg1_length) == 0)
{
-#if defined(CHILD_INSERT_EXEC_CATCHPOINT)
catch_exec_command_1 (arg1_end + 1, tempflag, from_tty);
-#else
- error ("Catch of exec not yet implemented");
-#endif
}
else if (strncmp (arg1_start, "load", arg1_length) == 0)
{
-#if defined(SOLIB_ADD)
catch_load_command_1 (arg1_end + 1, tempflag, from_tty);
-#else
- error ("Catch of load not implemented");
-#endif
}
else if (strncmp (arg1_start, "unload", arg1_length) == 0)
{
-#if defined(SOLIB_ADD)
catch_unload_command_1 (arg1_end + 1, tempflag, from_tty);
-#else
- error ("Catch of load not implemented");
-#endif
}
else if (strncmp (arg1_start, "stop", arg1_length) == 0)
{
if (bpt->type == bp_none)
return;
- if (delete_breakpoint_hook)
- delete_breakpoint_hook (bpt);
+ if (deprecated_delete_breakpoint_hook)
+ deprecated_delete_breakpoint_hook (bpt);
breakpoint_delete_event (bpt->number);
if (bpt->loc->inserted)
remove_breakpoint (bpt->loc, mark_inserted);
+ free_valchain (bpt->loc);
+
if (breakpoint_chain == bpt)
breakpoint_chain = bpt->next;
&& !b->loc->duplicate
&& b->enable_state != bp_disabled
&& b->enable_state != bp_shlib_disabled
+ && !b->pending
&& b->enable_state != bp_call_disabled)
{
int val;
struct breakpoint *b = (struct breakpoint *) bint;
struct value *mark;
int i;
+ int not_found;
+ int *not_found_ptr = NULL;
struct symtabs_and_lines sals;
char *s;
enum enable_state save_enable;
shlib_disabled breakpoint though. There's a fair chance we
can't re-set it if the shared library it's in hasn't been
loaded yet. */
+
+ if (b->pending)
+ break;
+
save_enable = b->enable_state;
if (b->enable_state != bp_shlib_disabled)
b->enable_state = bp_disabled;
+ else
+ /* If resetting a shlib-disabled breakpoint, we don't want to
+ see an error message if it is not found since we will expect
+ this to occur until the shared library is finally reloaded.
+ We accomplish this by giving decode_line_1 a pointer to use
+ for silent notification that the symbol is not found. */
+ not_found_ptr = ¬_found;
set_language (b->language);
input_radix = b->input_radix;
s = b->addr_string;
- sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL, NULL);
+ sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
+ not_found_ptr);
for (i = 0; i < sals.nelts; i++)
{
resolve_sal_pc (&sals.sals[i]);
{
s = b->cond_string;
if (b->cond)
- xfree (b->cond);
+ {
+ xfree (b->cond);
+ /* Avoid re-freeing b->exp if an error during the call
+ to parse_exp_1. */
+ b->cond = NULL;
+ }
b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
}
b->line_number = sals.sals[i].line;
b->loc->requested_address = sals.sals[i].pc;
b->loc->address
- = adjust_breakpoint_address (b->loc->requested_address);
+ = adjust_breakpoint_address (b->loc->requested_address,
+ b->type);
/* Used to check for duplicates here, but that can
cause trouble, as it doesn't check for disabled
/* So for now, just use a global context. */
if (b->exp)
- xfree (b->exp);
+ {
+ xfree (b->exp);
+ /* Avoid re-freeing b->exp if an error during the call to
+ parse_expression. */
+ b->exp = NULL;
+ }
b->exp = parse_expression (b->exp_string);
b->exp_valid_block = innermost_block;
mark = value_mark ();
if (b->val)
- value_free (b->val);
+ {
+ value_free (b->val);
+ /* Avoid re-freeing b->val if an error during the call to
+ evaluate_expression. */
+ b->val = NULL;
+ }
b->val = evaluate_expression (b->exp);
release_value (b->val);
if (VALUE_LAZY (b->val) && breakpoint_enabled (b))
{
s = b->cond_string;
if (b->cond)
- xfree (b->cond);
+ {
+ xfree (b->cond);
+ /* Avoid re-freeing b->exp if an error during the call
+ to parse_exp_1. */
+ b->cond = NULL;
+ }
b->cond = parse_exp_1 (&s, (struct block *) 0, 0);
}
if (breakpoint_enabled (b))
check_duplicates (bpt);
- if (modify_breakpoint_hook)
- modify_breakpoint_hook (bpt);
+ if (deprecated_modify_breakpoint_hook)
+ deprecated_modify_breakpoint_hook (bpt);
breakpoint_modify_event (bpt->number);
}
static void
do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
{
- struct frame_info *save_selected_frame = NULL;
- int save_selected_frame_level = -1;
int target_resources_ok, other_type_used;
struct value *mark;
error ("Hardware breakpoints used exceeds limit.");
}
- if (bpt->enable_state != bp_permanent)
- bpt->enable_state = bp_enabled;
- bpt->disposition = disposition;
- check_duplicates (bpt);
- breakpoints_changed ();
-
- if (bpt->type == bp_watchpoint ||
- bpt->type == bp_hardware_watchpoint ||
- bpt->type == bp_read_watchpoint ||
- bpt->type == bp_access_watchpoint)
+ if (bpt->pending)
{
- if (bpt->exp_valid_block != NULL)
+ if (bpt->enable_state != bp_enabled)
{
- struct frame_info *fr =
- fr = frame_find_by_id (bpt->watchpoint_frame);
- if (fr == NULL)
+ /* When enabling a pending breakpoint, we need to check if the breakpoint
+ is resolvable since shared libraries could have been loaded
+ after the breakpoint was disabled. */
+ breakpoints_changed ();
+ if (resolve_pending_breakpoint (bpt) == GDB_RC_OK)
{
- printf_filtered ("\
-Cannot enable watchpoint %d because the block in which its expression\n\
-is valid is not currently in scope.\n", bpt->number);
- bpt->enable_state = bp_disabled;
+ delete_breakpoint (bpt);
return;
}
-
- save_selected_frame = deprecated_selected_frame;
- save_selected_frame_level = frame_relative_level (deprecated_selected_frame);
- select_frame (fr);
+ bpt->enable_state = bp_enabled;
+ bpt->disposition = disposition;
}
-
- value_free (bpt->val);
- mark = value_mark ();
- bpt->val = evaluate_expression (bpt->exp);
- release_value (bpt->val);
- if (VALUE_LAZY (bpt->val))
- value_fetch_lazy (bpt->val);
-
- if (bpt->type == bp_hardware_watchpoint ||
- bpt->type == bp_read_watchpoint ||
+ }
+ else /* Not a pending breakpoint. */
+ {
+ if (bpt->enable_state != bp_permanent)
+ bpt->enable_state = bp_enabled;
+ bpt->disposition = disposition;
+ check_duplicates (bpt);
+ breakpoints_changed ();
+
+ if (bpt->type == bp_watchpoint ||
+ bpt->type == bp_hardware_watchpoint ||
+ bpt->type == bp_read_watchpoint ||
bpt->type == bp_access_watchpoint)
{
- int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
- int mem_cnt = can_use_hardware_watchpoint (bpt->val);
-
- /* Hack around 'unused var' error for some targets here */
- (void) mem_cnt, i;
- target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
- bpt->type, i + mem_cnt, other_type_used);
- /* we can consider of type is bp_hardware_watchpoint, convert to
- bp_watchpoint in the following condition */
- if (target_resources_ok < 0)
+ struct frame_id saved_frame_id;
+
+ saved_frame_id = get_frame_id (get_selected_frame ());
+ if (bpt->exp_valid_block != NULL)
{
- printf_filtered ("\
+ struct frame_info *fr =
+ fr = frame_find_by_id (bpt->watchpoint_frame);
+ if (fr == NULL)
+ {
+ printf_filtered ("\
+Cannot enable watchpoint %d because the block in which its expression\n\
+is valid is not currently in scope.\n", bpt->number);
+ bpt->enable_state = bp_disabled;
+ return;
+ }
+ select_frame (fr);
+ }
+
+ value_free (bpt->val);
+ mark = value_mark ();
+ bpt->val = evaluate_expression (bpt->exp);
+ release_value (bpt->val);
+ if (VALUE_LAZY (bpt->val))
+ value_fetch_lazy (bpt->val);
+
+ if (bpt->type == bp_hardware_watchpoint ||
+ bpt->type == bp_read_watchpoint ||
+ bpt->type == bp_access_watchpoint)
+ {
+ int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
+ int mem_cnt = can_use_hardware_watchpoint (bpt->val);
+
+ /* Hack around 'unused var' error for some targets here */
+ (void) mem_cnt, i;
+ target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
+ bpt->type, i + mem_cnt, other_type_used);
+ /* we can consider of type is bp_hardware_watchpoint, convert to
+ bp_watchpoint in the following condition */
+ if (target_resources_ok < 0)
+ {
+ printf_filtered ("\
Cannot enable watchpoint %d because target watch resources\n\
have been allocated for other watchpoints.\n", bpt->number);
- bpt->enable_state = bp_disabled;
- value_free_to_mark (mark);
- return;
+ bpt->enable_state = bp_disabled;
+ value_free_to_mark (mark);
+ return;
+ }
}
+
+ select_frame (frame_find_by_id (saved_frame_id));
+ value_free_to_mark (mark);
}
-
- if (save_selected_frame_level >= 0)
- select_frame (save_selected_frame);
- value_free_to_mark (mark);
}
- if (modify_breakpoint_hook)
- modify_breakpoint_hook (bpt);
+
+ if (deprecated_modify_breakpoint_hook)
+ deprecated_modify_breakpoint_hook (bpt);
breakpoint_modify_event (bpt->number);
}
map_breakpoint_numbers (args, enable_delete_breakpoint);
}
\f
+static void
+set_breakpoint_cmd (char *args, int from_tty)
+{
+}
+
+static void
+show_breakpoint_cmd (char *args, int from_tty)
+{
+}
+
/* Use default_breakpoint_'s, or nothing if they aren't valid. */
struct symtabs_and_lines
void
_initialize_breakpoint (void)
{
+ static struct cmd_list_element *breakpoint_set_cmdlist;
+ static struct cmd_list_element *breakpoint_show_cmdlist;
struct cmd_list_element *c;
+#ifdef SOLIB_ADD
+ observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
+#endif
+
breakpoint_chain = 0;
/* Don't bother to call set_breakpoint_count. $bpnum isn't useful
before a breakpoint is set. */
created before setting this to nonzero, will continue to use watchpoint\n\
hardware.)",
&setlist);
- add_show_from_set (c, &showlist);
+ deprecated_add_show_from_set (c, &showlist);
can_use_hw_watchpoints = 1;
+
+ add_prefix_cmd ("breakpoint", class_maintenance, set_breakpoint_cmd, "\
+Breakpoint specific settings\n\
+Configure various breakpoint-specific variables such as\n\
+pending breakpoint behavior",
+ &breakpoint_set_cmdlist, "set breakpoint ",
+ 0/*allow-unknown*/, &setlist);
+ add_prefix_cmd ("breakpoint", class_maintenance, show_breakpoint_cmd, "\
+Breakpoint specific settings\n\
+Configure various breakpoint-specific variables such as\n\
+pending breakpoint behavior",
+ &breakpoint_show_cmdlist, "show breakpoint ",
+ 0/*allow-unknown*/, &showlist);
+
+ add_setshow_auto_boolean_cmd ("pending", no_class, &pending_break_support, "\
+Set debugger's behavior regarding pending breakpoints.", "\
+Show debugger's behavior regarding pending breakpoints.", "\
+If on, an unrecognized breakpoint location will cause gdb to create a\n\
+pending breakpoint. If off, an unrecognized breakpoint location results in\n\
+an error. If auto, an unrecognized breakpoint location results in a\n\
+user-query to see if a pending breakpoint should be created.", "\
+Debugger's behavior regarding pending breakpoints is %s.",
+ NULL, NULL,
+ &breakpoint_set_cmdlist,
+ &breakpoint_show_cmdlist);
+
+ pending_break_support = AUTO_BOOLEAN_AUTO;
}