static void catch_command (char *, int);
-static void watch_command (char *, int);
-
static int can_use_hardware_watchpoint (struct value *);
static void break_command_1 (char *, int, int);
static int breakpoint_1 (int, int, int (*) (const struct breakpoint *));
-static bpstat bpstat_alloc (const struct bp_location *, bpstat);
-
static int breakpoint_cond_eval (void *);
static void cleanup_executing_breakpoints (void *);
static void thbreak_command (char *, int);
-static void watch_command_1 (char *, int, int);
-
-static void rwatch_command (char *, int);
-
-static void awatch_command (char *, int);
-
static void do_enable_breakpoint (struct breakpoint *, enum bpdisp);
static void stop_command (char *arg, int from_tty);
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);
static struct bp_location *allocate_bp_location (struct breakpoint *bpt);
static void update_global_location_list_nothrow (int);
-static int bpstat_remove_bp_location_callback (struct thread_info *th,
- void *data);
-
static int is_hardware_watchpoint (const struct breakpoint *bpt);
static int is_watchpoint (const struct breakpoint *bpt);
{
/* NOTE: the following values are a part of MI protocol and represent
values of 'disp' field returned when inferior stops at a breakpoint. */
- static char *bpdisps[] = {"del", "dstp", "dis", "keep"};
+ static const char * const bpdisps[] = {"del", "dstp", "dis", "keep"};
return bpdisps[(int) disp];
}
static struct cmd_list_element *breakpoint_set_cmdlist;
static struct cmd_list_element *breakpoint_show_cmdlist;
-static struct cmd_list_element *save_cmdlist;
+struct cmd_list_element *save_cmdlist;
/* Return whether a breakpoint is an active enabled breakpoint. */
static int
|| bpt->type == bp_watchpoint);
}
-/* Find the current value of a watchpoint on EXP. Return the value in
- *VALP and *RESULTP and the chain of intermediate and final values
- in *VAL_CHAIN. RESULTP and VAL_CHAIN may be NULL if the caller does
- not need them.
-
- If a memory error occurs while evaluating the expression, *RESULTP will
- be set to NULL. *RESULTP may be a lazy value, if the result could
- not be read from memory. It is used to determine whether a value
- is user-specified (we should watch the whole value) or intermediate
- (we should watch only the bit used to locate the final value).
-
- If the final value, or any intermediate value, could not be read
- from memory, *VALP will be set to NULL. *VAL_CHAIN will still be
- set to any referenced values. *VALP will never be a lazy value.
- This is the value which we store in struct breakpoint.
-
- If VAL_CHAIN is non-NULL, *VAL_CHAIN will be released from the
- value chain. The caller must free the values individually. If
- VAL_CHAIN is NULL, all generated values will be left on the value
- chain. */
-
-static void
-fetch_watchpoint_value (struct expression *exp, struct value **valp,
- struct value **resultp, struct value **val_chain)
-{
- struct value *mark, *new_mark, *result;
- volatile struct gdb_exception ex;
-
- *valp = NULL;
- if (resultp)
- *resultp = NULL;
- if (val_chain)
- *val_chain = NULL;
-
- /* Evaluate the expression. */
- mark = value_mark ();
- result = NULL;
-
- TRY_CATCH (ex, RETURN_MASK_ALL)
- {
- result = evaluate_expression (exp);
- }
- if (ex.reason < 0)
- {
- /* Ignore memory errors, we want watchpoints pointing at
- inaccessible memory to still be created; otherwise, throw the
- error to some higher catcher. */
- switch (ex.error)
- {
- case MEMORY_ERROR:
- break;
- default:
- throw_exception (ex);
- break;
- }
- }
-
- new_mark = value_mark ();
- if (mark == new_mark)
- return;
- if (resultp)
- *resultp = result;
-
- /* Make sure it's not lazy, so that after the target stops again we
- have a non-lazy previous value to compare with. */
- if (result != NULL
- && (!value_lazy (result) || gdb_value_fetch_lazy (result)))
- *valp = result;
-
- if (val_chain)
- {
- /* Return the chain of intermediate values. We use this to
- decide which addresses to watch. */
- *val_chain = new_mark;
- value_release_to_mark (mark);
- }
-}
-
/* Assuming that B is a watchpoint: returns true if the current thread
and its running state are safe to evaluate or update watchpoint B.
Watchpoints on local expressions need to be evaluated in the
if (within_current_scope && reparse)
{
char *s;
+
if (b->exp)
{
xfree (b->exp);
b->exp = NULL;
}
- s = b->exp_string;
+ s = b->exp_string_reparse ? b->exp_string_reparse : b->exp_string;
b->exp = parse_exp_1 (&s, b->exp_valid_block, 0);
/* If the meaning of expression itself changed, the old value is
no longer relevant. We don't want to report a watchpoint hit
}
else if (within_current_scope && b->exp)
{
+ int pc = 0;
struct value *val_chain, *v, *result, *next;
struct program_space *frame_pspace;
- fetch_watchpoint_value (b->exp, &v, &result, &val_chain);
+ fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain);
/* Avoid setting b->val if it's already set. The meaning of
b->val is 'the last value' user saw, and we should update
{
val = target_insert_watchpoint (bpt->address,
bpt->length,
- bpt->watchpoint_type);
+ bpt->watchpoint_type,
+ bpt->owner->cond_exp);
/* If trying to set a read-watchpoint, and it turns out it's not
supported, try emulating one with an access watchpoint. */
{
val = target_insert_watchpoint (bpt->address,
bpt->length,
- hw_access);
+ hw_access,
+ bpt->owner->cond_exp);
if (val == 0)
bpt->watchpoint_type = hw_access;
}
else if (b->loc_type == bp_loc_hardware_watchpoint)
{
b->inserted = (is == mark_inserted);
- val = target_remove_watchpoint (b->address, b->length,
- b->watchpoint_type);
+ val = target_remove_watchpoint (b->address, b->length,
+ b->watchpoint_type, b->owner->cond_exp);
/* Failure to remove any of the hardware watchpoints comes here. */
if ((is == mark_uninserted) && (b->inserted))
/* Get rid of the moribund locations. */
for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, bpt); ++ix)
- free_bp_location (bpt);
+ decref_bp_location (&bpt);
VEC_free (bp_location_p, moribund_locations);
}
return (ep->type == bp_catchpoint);
}
-void
+/* Frees any storage that is part of a bpstat. Does not walk the
+ 'next' chain. */
+
+static void
bpstat_free (bpstat bs)
{
if (bs->old_val != NULL)
value_free (bs->old_val);
decref_counted_command_line (&bs->commands);
+ decref_bp_location (&bs->bp_location_at);
xfree (bs);
}
tmp = (bpstat) xmalloc (sizeof (*tmp));
memcpy (tmp, bs, sizeof (*tmp));
incref_counted_command_line (tmp->commands);
+ incref_bp_location (tmp->bp_location_at);
if (bs->old_val != NULL)
{
tmp->old_val = value_copy (bs->old_val);
for (; bsp != NULL; bsp = bsp->next)
{
- if (bsp->breakpoint_at && bsp->breakpoint_at->owner == breakpoint)
+ if (bsp->breakpoint_at == breakpoint)
return bsp;
}
return NULL;
correspond to a single breakpoint -- otherwise,
this function might return the same number more
than once and this will look ugly. */
- b = (*bsp)->breakpoint_at ? (*bsp)->breakpoint_at->owner : NULL;
+ b = (*bsp)->breakpoint_at;
*bsp = (*bsp)->next;
if (b == NULL)
return -1; /* breakpoint that's been deleted since */
which has since been deleted. */
if (bs->breakpoint_at == NULL)
return PRINT_UNKNOWN;
- bl = bs->breakpoint_at;
- /* bl->owner can be NULL if it was a momentary breakpoint
- which has since been placed into moribund_locations. */
- if (bl->owner == NULL)
- return PRINT_UNKNOWN;
- b = bl->owner;
+ gdb_assert (bs->bp_location_at != NULL);
+
+ bl = bs->bp_location_at;
+ b = bs->breakpoint_at;
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
{
case bp_breakpoint:
case bp_hardware_breakpoint:
- bp_temp = bs->breakpoint_at->owner->disposition == disp_del;
+ bp_temp = b->disposition == disp_del;
if (bl->address != bl->requested_address)
breakpoint_adjustment_warning (bl->requested_address,
bl->address,
case print_it_normal:
{
- const struct bp_location *bl = bs->breakpoint_at;
- struct breakpoint *b = bl ? bl->owner : NULL;
-
+ struct breakpoint *b = bs->breakpoint_at;
+
/* Normal case. Call the breakpoint's print_it method, or
print_it_typical. */
/* FIXME: how breakpoint can ever be NULL here? */
return i;
}
-/* Allocate a new bpstat and chain it to the current one. */
+/* Allocate a new bpstat. Link it to the FIFO list by BS_LINK_POINTER. */
static bpstat
-bpstat_alloc (const struct bp_location *bl, bpstat cbs /* Current "bs" value */ )
+bpstat_alloc (struct bp_location *bl, bpstat **bs_link_pointer)
{
bpstat bs;
bs = (bpstat) xmalloc (sizeof (*bs));
- cbs->next = bs;
- bs->breakpoint_at = bl;
+ bs->next = NULL;
+ **bs_link_pointer = bs;
+ *bs_link_pointer = &bs->next;
+ bs->breakpoint_at = bl->owner;
+ bs->bp_location_at = bl;
+ incref_bp_location (bl);
/* If the condition is false, etc., don't do the commands. */
bs->commands = NULL;
bs->commands_left = NULL;
struct frame_info *fr;
int within_current_scope;
- /* BS is built for existing struct breakpoint. */
+ /* BS is built from an existing struct breakpoint. */
gdb_assert (bs->breakpoint_at != NULL);
- gdb_assert (bs->breakpoint_at->owner != NULL);
- b = bs->breakpoint_at->owner;
+ b = bs->breakpoint_at;
/* If this is a local watchpoint, we only want to check if the
watchpoint frame is in scope if the current thread is the thread
call free_all_values. We can't call free_all_values because
we might be in the middle of evaluating a function call. */
+ int pc = 0;
struct value *mark = value_mark ();
struct value *new_val;
- fetch_watchpoint_value (b->exp, &new_val, NULL, NULL);
+ fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL);
/* We use value_equal_contents instead of value_equal because the latter
coerces an array to a pointer, thus comparing just the address of the
struct breakpoint *b;
/* BS is built for existing struct breakpoint. */
- bl = bs->breakpoint_at;
+ bl = bs->bp_location_at;
gdb_assert (bl != NULL);
- b = bl->owner;
+ b = bs->breakpoint_at;
gdb_assert (b != NULL);
if (is_watchpoint (b))
/* 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)
{
struct breakpoint *b;
/* BS is built for existing struct breakpoint. */
- bl = bs->breakpoint_at;
+ bl = bs->bp_location_at;
gdb_assert (bl != NULL);
- b = bl->owner;
+ b = bs->breakpoint_at;
gdb_assert (b != NULL);
if (frame_id_p (b->frame_id)
int value_is_zero = 0;
struct expression *cond;
- /* If this is a scope breakpoint, mark the associated
- watchpoint as triggered so that we will handle the
- out-of-scope event. We'll get to the watchpoint next
- iteration. */
- if (b->type == bp_watchpoint_scope)
- b->related_breakpoint->watchpoint_triggered = watch_triggered_yes;
-
if (is_watchpoint (b))
cond = b->cond_exp;
else
cond = bl->cond;
- if (cond && bl->owner->disposition != disp_del_at_next_stop)
+ if (cond && b->disposition != disp_del_at_next_stop)
{
int within_current_scope = 1;
struct breakpoint *b = NULL;
struct bp_location *bl;
struct bp_location *loc;
- /* Root of the chain of bpstat's */
- struct bpstats root_bs[1];
+ /* First item of allocated bpstat's. */
+ bpstat bs_head = NULL, *bs_link = &bs_head;
/* Pointer to the last thing in the chain currently. */
- bpstat bs = root_bs;
+ bpstat bs;
int ix;
int need_remove_insert;
+ int removed_any;
- /* ALL_BP_LOCATIONS iteration would break across
- update_global_location_list possibly executed by
- bpstat_check_breakpoint_conditions's inferior call. */
+ /* First, build the bpstat chain with locations that explain a
+ target stop, while being careful to not set the target running,
+ as that may invalidate locations (in particular watchpoint
+ locations are recreated). Resuming will happen here with
+ breakpoint conditions or watchpoint expressions that include
+ inferior function calls. */
ALL_BREAKPOINTS (b)
{
/* Come here if it's a watchpoint, or if the break address matches */
- bs = bpstat_alloc (bl, bs); /* Alloc a bpstat to explain stop */
+ bs = bpstat_alloc (bl, &bs_link); /* Alloc a bpstat to explain stop */
- /* Assume we stop. Should we find watchpoint that is not actually
- triggered, or if condition of breakpoint is false, we'll reset
- 'stop' to 0. */
+ /* Assume we stop. Should we find a watchpoint that is not
+ actually triggered, or if the condition of the breakpoint
+ evaluates as false, we'll reset 'stop' to 0. */
bs->stop = 1;
bs->print = 1;
- bpstat_check_watchpoint (bs);
- if (!bs->stop)
- continue;
+ /* If this is a scope breakpoint, mark the associated
+ watchpoint as triggered so that we will handle the
+ out-of-scope event. We'll get to the watchpoint next
+ iteration. */
+ if (b->type == bp_watchpoint_scope)
+ b->related_breakpoint->watchpoint_triggered = watch_triggered_yes;
+ }
+ }
+
+ for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
+ {
+ if (breakpoint_address_match (loc->pspace->aspace, loc->address,
+ aspace, bp_addr))
+ {
+ bs = bpstat_alloc (loc, &bs_link);
+ /* For hits of moribund locations, we should just proceed. */
+ bs->stop = 0;
+ bs->print = 0;
+ bs->print_it = print_it_noop;
+ }
+ }
+
+ /* Now go through the locations that caused the target to stop, and
+ check whether we're interested in reporting this stop to higher
+ layers, or whether we should resume the target transparently. */
+
+ removed_any = 0;
+
+ for (bs = bs_head; bs != NULL; bs = bs->next)
+ {
+ if (!bs->stop)
+ continue;
+
+ bpstat_check_watchpoint (bs);
+ if (!bs->stop)
+ continue;
+
+ b = bs->breakpoint_at;
if (b->type == bp_thread_event || b->type == bp_overlay_event
|| b->type == bp_longjmp_master
bs->stop = 0;
else
bpstat_check_breakpoint_conditions (bs, ptid);
-
+
if (bs->stop)
{
++(b->hit_count);
{
if (b->enable_state != bp_permanent)
b->enable_state = bp_disabled;
- update_global_location_list (0);
+ removed_any = 1;
}
if (b->silent)
bs->print = 0;
/* Print nothing for this entry if we dont stop or dont print. */
if (bs->stop == 0 || bs->print == 0)
bs->print_it = print_it_noop;
- }
- }
-
- for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
- {
- if (breakpoint_address_match (loc->pspace->aspace, loc->address,
- aspace, bp_addr))
- {
- bs = bpstat_alloc (loc, bs);
- /* For hits of moribund locations, we should just proceed. */
- bs->stop = 0;
- bs->print = 0;
- bs->print_it = print_it_noop;
- }
}
- bs->next = NULL; /* Terminate the chain */
-
/* If we aren't stopping, the value of some hardware watchpoint may
not have changed, but the intermediate memory locations we are
watching may have. Don't bother if we're stopping; this will get
done later. */
need_remove_insert = 0;
- if (! bpstat_causes_stop (root_bs->next))
- for (bs = root_bs->next; bs != NULL; bs = bs->next)
+ if (! bpstat_causes_stop (bs_head))
+ for (bs = bs_head; bs != NULL; bs = bs->next)
if (!bs->stop
- && bs->breakpoint_at->owner
- && is_hardware_watchpoint (bs->breakpoint_at->owner))
+ && bs->breakpoint_at
+ && is_hardware_watchpoint (bs->breakpoint_at))
{
- update_watchpoint (bs->breakpoint_at->owner, 0 /* don't reparse. */);
- /* Updating watchpoints invalidates bs->breakpoint_at.
- Prevent further code from trying to use it. */
- bs->breakpoint_at = NULL;
+ update_watchpoint (bs->breakpoint_at, 0 /* don't reparse. */);
need_remove_insert = 1;
}
if (need_remove_insert)
update_global_location_list (1);
+ else if (removed_any)
+ update_global_location_list (0);
- return root_bs->next;
+ return bs_head;
}
static void
breakpoint which has since been deleted. */
bptype = bp_none;
}
- else if (bs->breakpoint_at->owner == NULL)
+ else if (bs->breakpoint_at == NULL)
bptype = bp_none;
else
- bptype = bs->breakpoint_at->owner->type;
+ bptype = bs->breakpoint_at->type;
switch (bptype)
{
do_cleanups (old_chain);
}
-/* Print B to gdb_stdout. */
-static void
-print_one_breakpoint_location (struct breakpoint *b,
- struct bp_location *loc,
- int loc_number,
- struct bp_location **last_loc,
- int print_address_bits,
- int allflag)
+static const char *
+bptype_string (enum bptype type)
{
- struct command_line *l;
struct ep_type_description
{
enum bptype type;
{bp_static_tracepoint, "static tracepoint"},
{bp_jit_event, "jit events"},
};
-
+
+ if (((int) type >= (sizeof (bptypes) / sizeof (bptypes[0])))
+ || ((int) type != bptypes[(int) type].type))
+ internal_error (__FILE__, __LINE__,
+ _("bptypes table does not describe type #%d."),
+ (int) type);
+
+ return bptypes[(int) type].description;
+}
+
+/* Print B to gdb_stdout. */
+
+static void
+print_one_breakpoint_location (struct breakpoint *b,
+ struct bp_location *loc,
+ int loc_number,
+ struct bp_location **last_loc,
+ int print_address_bits,
+ int allflag)
+{
+ struct command_line *l;
static char bpenables[] = "nynny";
char wrap_indent[80];
struct ui_stream *stb = ui_out_stream_new (uiout);
annotate_field (1);
if (part_of_multiple)
ui_out_field_skip (uiout, "type");
- else
- {
- if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0])))
- || ((int) b->type != bptypes[(int) b->type].type))
- internal_error (__FILE__, __LINE__,
- _("bptypes table does not describe type #%d."),
- (int) b->type);
- ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
- }
+ else
+ ui_out_field_string (uiout, "type", bptype_string (b->type));
/* 3 */
annotate_field (2);
struct cleanup *bkpttbl_chain;
struct value_print_options opts;
int print_address_bits = 0;
-
+ int print_type_col_width = 14;
+
get_user_print_options (&opts);
/* Compute the number of rows in the table, as well as the
if (allflag || user_settable_breakpoint (b))
{
- int addr_bit = breakpoint_address_bits (b);
+ int addr_bit, type_len;
+
+ addr_bit = breakpoint_address_bits (b);
if (addr_bit > print_address_bits)
print_address_bits = addr_bit;
+ type_len = strlen (bptype_string (b->type));
+ if (type_len > print_type_col_width)
+ print_type_col_width = type_len;
+
nr_printable_breakpoints++;
}
}
ui_out_table_header (uiout, 7, ui_left, "number", "Num"); /* 1 */
if (nr_printable_breakpoints > 0)
annotate_field (1);
- ui_out_table_header (uiout, 14, ui_left, "type", "Type"); /* 2 */
+ ui_out_table_header (uiout, print_type_col_width, ui_left,
+ "type", "Type"); /* 2 */
if (nr_printable_breakpoints > 0)
annotate_field (2);
ui_out_table_header (uiout, 4, ui_left, "disp", "Disp"); /* 3 */
gdb_assert (loc1->owner != NULL);
gdb_assert (loc2->owner != NULL);
+ /* If the target can evaluate the condition expression in hardware, then we
+ we need to insert both watchpoints even if they are at the same place.
+ Otherwise the watchpoint will only trigger when the condition of whichever
+ watchpoint was inserted evaluates to true, not giving a chance for GDB to
+ check the condition of the other watchpoint. */
+ if ((loc1->owner->cond_exp
+ && target_can_accel_watchpoint_condition (loc1->address, loc1->length,
+ loc1->watchpoint_type,
+ loc1->owner->cond_exp))
+ || (loc2->owner->cond_exp
+ && target_can_accel_watchpoint_condition (loc2->address, loc2->length,
+ loc2->watchpoint_type,
+ loc2->owner->cond_exp)))
+ return 0;
+
/* Note that this checks the owner's type, not the location's. In
case the target does not support read watchpoints, but does
support access watchpoints, we'll have bp_read_watchpoint
internal_error (__FILE__, __LINE__, _("unknown breakpoint type"));
}
+ loc->refc = 1;
return loc;
}
-static void free_bp_location (struct bp_location *loc)
+static void
+free_bp_location (struct bp_location *loc)
{
- /* Be sure no bpstat's are pointing at it after it's been freed. */
- /* FIXME, how can we find all bpstat's?
- We just check stop_bpstat for now. Note that we cannot just
- remove bpstats pointing at bpt from the stop_bpstat list
- entirely, as breakpoint commands are associated with the bpstat;
- if we remove it here, then the later call to
- bpstat_do_actions (&stop_bpstat);
- in event-top.c won't do anything, and temporary breakpoints
- with commands won't work. */
-
- iterate_over_threads (bpstat_remove_bp_location_callback, loc);
-
if (loc->cond)
xfree (loc->cond);
if (loc->function_name)
xfree (loc->function_name);
-
+
xfree (loc);
}
+/* Increment reference count. */
+
+static void
+incref_bp_location (struct bp_location *bl)
+{
+ ++bl->refc;
+}
+
+/* Decrement reference count. If the reference count reaches 0,
+ destroy the bp_location. Sets *BLP to NULL. */
+
+static void
+decref_bp_location (struct bp_location **blp)
+{
+ gdb_assert ((*blp)->refc > 0);
+
+ if (--(*blp)->refc == 0)
+ free_bp_location (*blp);
+ *blp = NULL;
+}
+
/* Helper to set_raw_breakpoint below. Creates a breakpoint
that has type BPTYPE and has no locations as yet. */
/* This function is used in gdbtk sources and thus can not be made static. */
/* 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? "))
+ && !nquery (_("Make breakpoint pending on future shared library load? ")))
return 0;
/* At this point, either the user was queried about setting
hw_read: watch read,
hw_access: watch access (read or write) */
static void
-watch_command_1 (char *arg, int accessflag, int from_tty)
+watch_command_1 (char *arg, int accessflag, int from_tty, int just_location)
{
struct breakpoint *b, *scope_breakpoint = NULL;
struct expression *exp;
enum bptype bp_type;
int mem_cnt = 0;
int thread = -1;
+ int pc = 0;
/* Make sure that we actually have parameters to parse. */
if (arg != NULL && arg[0] != '\0')
exp_valid_block = innermost_block;
mark = value_mark ();
- fetch_watchpoint_value (exp, &val, NULL, NULL);
- if (val != NULL)
+ fetch_subexp_value (exp, &pc, &val, NULL, NULL);
+
+ if (just_location)
+ {
+ exp_valid_block = NULL;
+ val = value_addr (val);
+ release_value (val);
+ value_free_to_mark (mark);
+ }
+ else if (val != NULL)
release_value (val);
tok = arg;
b->exp = exp;
b->exp_valid_block = exp_valid_block;
b->cond_exp_valid_block = cond_exp_valid_block;
- b->exp_string = savestring (exp_start, exp_end - exp_start);
+ if (just_location)
+ {
+ struct type *t = value_type (val);
+ CORE_ADDR addr = value_as_address (val);
+ char *name;
+
+ t = check_typedef (TYPE_TARGET_TYPE (check_typedef (t)));
+ name = type_to_string (t);
+
+ b->exp_string_reparse = xstrprintf ("* (%s *) %s", name,
+ core_addr_to_string (addr));
+ xfree (name);
+
+ b->exp_string = xstrprintf ("-location: %.*s",
+ (int) (exp_end - exp_start), exp_start);
+
+ /* The above expression is in C. */
+ b->language = language_c;
+ }
+ else
+ b->exp_string = savestring (exp_start, exp_end - exp_start);
b->val = val;
b->val_valid = 1;
if (cond_start)
scope_breakpoint->related_breakpoint = b;
}
- value_free_to_mark (mark);
+ if (!just_location)
+ value_free_to_mark (mark);
/* Finally update the new watchpoint. This creates the locations
that should be inserted. */
{
if (VALUE_LVAL (v) == lval_memory)
{
- if (value_lazy (v))
- /* A lazy memory lvalue is one that GDB never needed to fetch;
- we either just used its address (e.g., `a' in `a.b') or
- we never needed it at all (e.g., `a' in `a,b'). */
+ if (v != head && value_lazy (v))
+ /* A lazy memory lvalue in the chain is one that GDB never
+ needed to fetch; we either just used its address (e.g.,
+ `a' in `a.b') or we never needed it at all (e.g., `a'
+ in `a,b'). This doesn't apply to HEAD; if that is
+ lazy then it was not readable, but watch it anyway. */
;
else
{
}
else if (VALUE_LVAL (v) != not_lval
&& deprecated_value_modifiable (v) == 0)
- return 0; /* ??? What does this represent? */
+ return 0; /* These are values from the history (e.g., $1). */
else if (VALUE_LVAL (v) == lval_register)
- return 0; /* cannot watch a register with a HW watchpoint */
+ return 0; /* Cannot watch a register with a HW watchpoint. */
}
/* The expression itself looks suitable for using a hardware
void
watch_command_wrapper (char *arg, int from_tty)
{
- watch_command (arg, from_tty);
+ watch_command_1 (arg, hw_write, from_tty, 0);
+}
+
+/* A helper function that looks for an argument at the start of a
+ string. The argument must also either be at the end of the string,
+ or be followed by whitespace. Returns 1 if it finds the argument,
+ 0 otherwise. If the argument is found, it updates *STR. */
+
+static int
+check_for_argument (char **str, char *arg, int arg_len)
+{
+ if (strncmp (*str, arg, arg_len) == 0
+ && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
+ {
+ *str += arg_len;
+ return 1;
+ }
+ return 0;
+}
+
+/* A helper function that looks for the "-location" argument and then
+ calls watch_command_1. */
+
+static void
+watch_maybe_just_location (char *arg, int accessflag, int from_tty)
+{
+ int just_location = 0;
+
+ if (arg
+ && (check_for_argument (&arg, "-location", sizeof ("-location") - 1)
+ || check_for_argument (&arg, "-l", sizeof ("-l") - 1)))
+ {
+ ep_skip_leading_whitespace (&arg);
+ just_location = 1;
+ }
+
+ watch_command_1 (arg, accessflag, from_tty, just_location);
}
static void
watch_command (char *arg, int from_tty)
{
- watch_command_1 (arg, hw_write, from_tty);
+ watch_maybe_just_location (arg, hw_write, from_tty);
}
void
rwatch_command_wrapper (char *arg, int from_tty)
{
- rwatch_command (arg, from_tty);
+ watch_command_1 (arg, hw_read, from_tty, 0);
}
static void
rwatch_command (char *arg, int from_tty)
{
- watch_command_1 (arg, hw_read, from_tty);
+ watch_maybe_just_location (arg, hw_read, from_tty);
}
void
awatch_command_wrapper (char *arg, int from_tty)
{
- awatch_command (arg, from_tty);
+ watch_command_1 (arg, hw_access, from_tty, 0);
}
static void
awatch_command (char *arg, int from_tty)
{
- watch_command_1 (arg, hw_access, from_tty);
+ watch_maybe_just_location (arg, hw_access, from_tty);
}
\f
struct breakpoint *b, *temp;
for (; bs; bs = bs->next)
- if (bs->breakpoint_at
- && bs->breakpoint_at->owner
- && bs->breakpoint_at->owner->disposition == disp_del
+ if (bs->breakpoint_at
+ && bs->breakpoint_at->disposition == disp_del
&& bs->stop)
- delete_breakpoint (bs->breakpoint_at->owner);
+ delete_breakpoint (bs->breakpoint_at);
ALL_BREAKPOINTS_SAFE (b, temp)
{
VEC_safe_push (bp_location_p, moribund_locations, old_loc);
}
else
- free_bp_location (old_loc);
+ {
+ old_loc->owner = NULL;
+ decref_bp_location (&old_loc);
+ }
}
}
for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
if (--(loc->events_till_retirement) == 0)
{
- free_bp_location (loc);
+ decref_bp_location (&loc);
VEC_unordered_remove (bp_location_p, moribund_locations, ix);
--ix;
}
update_global_location_list (inserting);
}
-/* Clear LOC from a BPS. */
+/* Clear BKP from a BPS. */
+
static void
-bpstat_remove_bp_location (bpstat bps, struct bp_location *loc)
+bpstat_remove_bp_location (bpstat bps, struct breakpoint *bpt)
{
bpstat bs;
for (bs = bps; bs; bs = bs->next)
- if (bs->breakpoint_at == loc)
+ if (bs->breakpoint_at == bpt)
{
bs->breakpoint_at = NULL;
bs->old_val = NULL;
/* Callback for iterate_over_threads. */
static int
-bpstat_remove_bp_location_callback (struct thread_info *th, void *data)
+bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
{
- struct bp_location *loc = data;
+ struct breakpoint *bpt = data;
- bpstat_remove_bp_location (th->stop_bpstat, loc);
+ bpstat_remove_bp_location (th->stop_bpstat, bpt);
return 0;
}
/* Delete a breakpoint and clean up all traces of it in the data
- structures. */
+ structures. */
void
delete_breakpoint (struct breakpoint *bpt)
xfree (bpt->addr_string);
xfree (bpt->exp);
xfree (bpt->exp_string);
+ xfree (bpt->exp_string_reparse);
value_free (bpt->val);
xfree (bpt->source_file);
xfree (bpt->exec_pathname);
clean_up_filters (&bpt->syscalls_to_be_caught);
+
+ /* Be sure no bpstat's are pointing at the breakpoint after it's
+ been freed. */
+ /* FIXME, how can we find all bpstat's? We just check stop_bpstat
+ in all threeds for now. Note that we cannot just remove bpstats
+ pointing at bpt from the stop_bpstat list entirely, as breakpoint
+ commands are associated with the bpstat; if we remove it here,
+ then the later call to bpstat_do_actions (&stop_bpstat); in
+ event-top.c won't do anything, and temporary breakpoints with
+ commands won't work. */
+
+ iterate_over_threads (bpstat_remove_breakpoint_callback, bpt);
+
/* Now that breakpoint is removed from breakpoint
list, update the global location list. This
will remove locations that used to belong to
return 0;
}
- set_language (b->language);
input_radix = b->input_radix;
s = b->addr_string;
marker_spec = b->type == bp_static_tracepoint && is_marker_spec (s);
+ set_language (b->language);
TRY_CATCH (e, RETURN_MASK_ERROR)
{
if (marker_spec)
paddress (gdbarch, next_pc));
}
+/* Check if the breakpoints used for software single stepping
+ were inserted or not. */
+
+int
+single_step_breakpoints_inserted (void)
+{
+ return (single_step_breakpoints[0] != NULL
+ || single_step_breakpoints[1] != NULL);
+}
+
/* Remove and delete any breakpoints used for software single step. */
void
fprintf_unfiltered (fp, " commands\n");
ui_out_redirect (uiout, fp);
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY_CATCH (ex, RETURN_MASK_ALL)
{
print_command_lines (uiout, tp->commands->commands, 2);
}
THREADNUM is the number from \"info threads\".\n\
CONDITION is a boolean expression.\n\
\n\
-Multiple breakpoints at one place are permitted, and useful if conditional.\n\
+Multiple breakpoints at one place are permitted, and useful if their\n\
+conditions are different.\n\
\n\
Do \"help breakpoints\" for info on other commands dealing with breakpoints."
is executing in.\n\
\n\
See also the \"delete\" command which clears breakpoints by number."));
+ add_com_alias ("cl", "clear", class_breakpoint, 1);
c = add_com ("break", class_breakpoint, break_command, _("\
Set breakpoint at specified line or function.\n"
c = add_com ("watch", class_breakpoint, watch_command, _("\
Set a watchpoint for an expression.\n\
+Usage: watch [-l|-location] EXPRESSION\n\
A watchpoint stops execution of your program whenever the value of\n\
-an expression changes."));
+an expression changes.\n\
+If -l or -location is given, this evaluates EXPRESSION and watches\n\
+the memory to which it refers."));
set_cmd_completer (c, expression_completer);
c = add_com ("rwatch", class_breakpoint, rwatch_command, _("\
Set a read watchpoint for an expression.\n\
+Usage: rwatch [-l|-location] EXPRESSION\n\
A watchpoint stops execution of your program whenever the value of\n\
-an expression is read."));
+an expression is read.\n\
+If -l or -location is given, this evaluates EXPRESSION and watches\n\
+the memory to which it refers."));
set_cmd_completer (c, expression_completer);
c = add_com ("awatch", class_breakpoint, awatch_command, _("\
Set a watchpoint for an expression.\n\
+Usage: awatch [-l|-location] EXPRESSION\n\
A watchpoint stops execution of your program whenever the value of\n\
-an expression is either read or written."));
+an expression is either read or written.\n\
+If -l or -location is given, this evaluates EXPRESSION and watches\n\
+the memory to which it refers."));
set_cmd_completer (c, expression_completer);
add_info ("watchpoints", watchpoints_info, _("\
\n\
CONDITION is a boolean expression.\n\
\n\
-Multiple tracepoints at one place are permitted, and useful if conditional.\n\
+Multiple tracepoints at one place are permitted, and useful if their\n\
+conditions are different.\n\
\n\
Do \"help breakpoints\" for info on other commands dealing with breakpoints.\n\
Do \"help tracepoints\" for info on other tracepoint commands."));