[RFA]: pending breakpoint support [1/3]

Jeff Johnston
2004-01-21T20:52:45Z

[-- Attachment #1: Type: text/plain, Size: 1877 bytes --]

This is the first of the last 3 patches for pending breakpoint support.
This patch adds the actual support. The other two patches are the
documentation (previously approved, but before code was accepted) and
changes to the testsuite.

This patch accounts for previous comments on the breakpoint code.

Ok to commit?

-- Jeff J.

2004-01-21 Jeff Johnston <jjohnstn@redhat.com>

* breakpoint.h (struct breakpoint): Add new flag, from_tty,
and pending fields for pending breakpoint support.
* breakpoint.c (breakpoint_enabled): Add check for not pending.
(condition_command): Only parse condition if not a pending
breakpoint.
(print_one_breakpoint): Add support for pending breakpoints.
(describe_other_breakpoints): Add checks to verify we are not
dealing with pending breakpoints.
(check_duplicates): Don't check pending breakpoints.
(set_raw_breakpoint): Initialize pending flag.
(do_restore_lang_radix_cleanup): New cleanup routine.
(resolve_pending_breakpoint): New function.
(re_enable_breakpoints_in_shlibs): Try and resolve any
pending breakpoints via resolve_pending_breakpoint.
(mention): Add pending breakpoint support.
(parse_breakpoint_sals): Add new parameter to pass to
decode_line_1 to indicate silent errors when files or functions
are not found. Change all callers.
(do_captured_parse_breakpoint): New function.
(break_command_1): Catch errors when parsing the breakpoint.
If a "not found" error occurs, offer to make the breakpoint
pending on a future shared library load. Do not parse any
conditional if breakpoint is pending.
(delete_breakpoint): Add appropriate check for pending.
(breakpoint_re_set_one): Ditto.
(do_enable_breakpoint): Ditto.

[-- Attachment #2: pbreak.patch1 --]
[-- Type: text/plain, Size: 23745 bytes --]

Index: breakpoint.h
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.26
diff -u -p -r1.26 breakpoint.h
--- breakpoint.h 6 Nov 2003 18:24:55 -0000 1.26
+++ breakpoint.h 21 Jan 2004 02:34:10 -0000
@@ -385,6 +385,15 @@ struct breakpoint

/* Methods associated with this breakpoint. */
struct breakpoint_ops *ops;
+
+ /* Initial from_tty value. */
+ int from_tty;
+
+ /* Initial flag value. */
+ int flag;
+
+ /* Is breakpoint pending on shlib loads? */
+ int pending;
};
\f
/* The following stuff is an abstract data type "bpstat" ("breakpoint
Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.149
diff -u -p -r1.149 breakpoint.c
--- breakpoint.c 17 Jan 2004 21:56:12 -0000 1.149
+++ breakpoint.c 21 Jan 2004 02:34:10 -0000
@@ -119,6 +119,8 @@ static void condition_command (char *, i

static int get_number_trailer (char **, int);

+static int do_captured_parse_breakpoint (struct ui_out *, void *);
+
void set_breakpoint_count (int);

typedef enum
@@ -326,7 +328,7 @@ int exception_support_initialized = 0;
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. */
@@ -560,9 +562,12 @@ condition_command (char *arg, int from_t
/* 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);
@@ -3458,7 +3463,15 @@ print_one_breakpoint (struct breakpoint
if (addressprint)
{
annotate_field (4);
- ui_out_field_core_addr (uiout, "addr", b->loc->address);
+ if (b->pending)
+ {
+ if (TARGET_ADDR_BIT <= 32)
+ ui_out_field_string (uiout, "addr", "<PENDING> ");
+ else
+ 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;
@@ -3477,6 +3490,10 @@ print_one_breakpoint (struct breakpoint
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, "");
@@ -3513,7 +3530,15 @@ print_one_breakpoint (struct breakpoint
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 */
@@ -3744,14 +3769,14 @@ describe_other_breakpoints (CORE_ADDR pc

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 ",
@@ -3840,6 +3865,7 @@ check_duplicates (struct breakpoint *bpt
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)
@@ -3874,6 +3900,7 @@ check_duplicates (struct breakpoint *bpt
{
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)
@@ -4050,6 +4077,7 @@ set_raw_breakpoint (struct symtab_and_li
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
@@ -4288,23 +4316,139 @@ disable_breakpoints_in_shlibs (int silen
}
}

+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 struct breakpoint *
+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;
+ /* Pointers in arg to the start, and one past the end, of the
+ condition. */
+ char **cond_string = (char **) NULL;
+ char *copy_arg = b->addr_string;
+ char **addr_string;
+ char *errmsg;
+ struct captured_parse_breakpoint_args parse_args;
+ int rc;
+ int not_found = 0;
+ struct ui_file *old_gdb_stderr;
+
+ sals.sals = NULL;
+ sals.nelts = 0;
+ addr_string = NULL;
+
+ parse_args.arg_p = &copy_arg;
+ parse_args.sals_p = &sals;
+ parse_args.addr_string_p = &addr_string;
+ parse_args.not_found_ptr = &not_found;
+
+ rc = catch_exceptions (uiout, do_captured_parse_breakpoint,
+ &parse_args, NULL, RETURN_MASK_ALL);
+
+ if (rc == GDB_RC_OK)
+ {
+ struct lang_and_radix old_lr;
+ struct cleanup *old_chain;
+ char *arg;
+ struct breakpoint *b1;
+
+ printf_filtered ("Pending breakpoint \"%s\" resolved\n", b->addr_string);
+
+ /* 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;
+ break_command_1 (b->addr_string, b->flag, b->from_tty);
+ b1 = breakpoint_chain;
+ while (b1->next)
+ b1 = b1->next;
+ /* If there is condition specified, it should be copied over. */
+ if (b->cond_string)
+ {
+ arg = b->cond_string;
+ b1->cond_string = savestring (arg, strlen (arg));
+ b1->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+ if (*arg)
+ error ("Junk at end of expression");
+ }
+ /* If there are commands associated with the breakpoint, they should
+ be copied too. */
+ if (b->commands)
+ {
+ b1->commands = copy_command_lines (b->commands);
+ }
+
+ do_cleanups (old_chain);
+ return b1; /* Pending breakpoint resolved. */
+ }
+
+ /* Otherwise, we didn't successfully resolve pending breakpoint. */
+ return NULL;
+}
+
/* Try to reenable any breakpoints in shared libraries. */
void
re_enable_breakpoints_in_shlibs (void)
{
struct breakpoint *b;
+ struct breakpoint *del_b = NULL;

ALL_BREAKPOINTS (b)
+ {
+ if (del_b)
+ {
+ delete_breakpoint (del_b);
+ del_b = NULL;
+ }
if (b->enable_state == bp_shlib_disabled)
- {
- char buf[1], *lib;
+ {
+ 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) != NULL)
+ del_b = b; /* Mark pending breakpoint for deletion. */
+ }
+ }

- /* 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;
- }
+ if (del_b)
+ delete_breakpoint (del_b);
}

#endif
@@ -4716,14 +4860,21 @@ mention (struct breakpoint *b)

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))
@@ -4799,7 +4950,8 @@ create_breakpoints (struct symtabs_and_l
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;
@@ -4840,9 +4992,11 @@ parse_breakpoint_sals (char **address,
|| ((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)
@@ -4896,6 +5050,17 @@ breakpoint_sals_to_pc (struct symtabs_an
}
}

+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. */
@@ -4906,16 +5071,22 @@ break_command_1 (char *arg, int flag, in
int tempflag, hardwareflag;
struct symtabs_and_lines sals;
struct expression **cond = 0;
+ struct symtab_and_line pending_sal;
/* Pointers in arg to the start, and one past the end, of the
condition. */
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;
@@ -4923,19 +5094,51 @@ break_command_1 (char *arg, int flag, in
sals.sals = NULL;
sals.nelts = 0;
addr_string = NULL;
- parse_breakpoint_sals (&arg, &sals, &addr_string);

- if (!sals.nelts)
+ parse_args.arg_p = &arg;
+ parse_args.sals_p = &sals;
+ parse_args.addr_string_p = &addr_string;
+ parse_args.not_found_ptr = &not_found;
+
+ rc = catch_exceptions_with_msg (uiout, do_captured_parse_breakpoint,
+ &parse_args, NULL, &err_msg,
+ RETURN_MASK_ALL);
+
+ if (rc != GDB_RC_OK)
+ {
+ /* Check for file or function not found. */
+ if (not_found)
+ {
+ error_output_message (NULL, err_msg);
+ xfree (err_msg);
+ if (!query ("Make breakpoint pending on future shared library load? "))
+ return;
+ copy_arg = (char *)xmalloc (strlen (addr_start));
+ strcpy (copy_arg, addr_start);
+ addr_string = &copy_arg;
+ sals.nelts = 1;
+ sals.sals = &pending_sal;
+ pending_sal.pc = 0;
+ pending = 1;
+ }
+ else
+ return;
+ }
+ else if (!sals.nelts)
return;

+
/* 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 *));
@@ -4962,62 +5165,91 @@ break_command_1 (char *arg, int flag, in

/* 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)
- {
- 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 *tok = arg;
+ while (tok && *tok)
{
- 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);
}
+ else
+ {
+ struct symtab_and_line sal;
+ struct breakpoint *b;

- create_breakpoints (sals, addr_string, cond, cond_string,
- hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
- tempflag ? disp_del : disp_donttouch,
- thread, ignore_count, from_tty);
+ sal.symtab = NULL;
+ sal.pc = 0;

+ 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.");
@@ -5064,7 +5296,7 @@ do_captured_breakpoint (void *data)
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;
@@ -6763,6 +6995,7 @@ delete_breakpoint (struct breakpoint *bp
&& !b->loc->duplicate
&& b->enable_state != bp_disabled
&& b->enable_state != bp_shlib_disabled
+ && !b->pending
&& b->enable_state != bp_call_disabled)
{
int val;
@@ -6968,6 +7201,10 @@ breakpoint_re_set_one (void *bint)
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;
@@ -7363,70 +7600,92 @@ do_enable_breakpoint (struct breakpoint
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->exp_valid_block != NULL)
- {
- struct frame_info *fr =
- fr = frame_find_by_id (bpt->watchpoint_frame);
- if (fr == NULL)
+ if (bpt->pending)
+ {
+ if (bpt->enable_state != bp_enabled)
+ {
+ /* 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. */
+ struct breakpoint *new_bp;
+ breakpoints_changed ();
+ if ((new_bp = resolve_pending_breakpoint (bpt)) != 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;
+ 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)
+ 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;
+ }
+
+ save_selected_frame = deprecated_selected_frame;
+ save_selected_frame_level = frame_relative_level (deprecated_selected_frame);
+ 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;
+ }
}
+
+ if (save_selected_frame_level >= 0)
+ select_frame (save_selected_frame);
+ 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);
breakpoint_modify_event (bpt->number);