#include "annotate.h"
#include "symfile.h"
#include "objfiles.h"
+#ifdef UI_OUT
+#include "ui-out.h"
+#endif
+
+#include "gdb-events.h"
/* Prototypes for local functions. */
-static void
-catch_command_1 PARAMS ((char *, int, int));
+static void until_break_command_continuation (struct continuation_arg *arg);
-static void
-enable_delete_command PARAMS ((char *, int));
+static void catch_command_1 (char *, int, int);
-static void
-enable_delete_breakpoint PARAMS ((struct breakpoint *));
+static void enable_delete_command (char *, int);
-static void
-enable_once_command PARAMS ((char *, int));
+static void enable_delete_breakpoint (struct breakpoint *);
-static void
-enable_once_breakpoint PARAMS ((struct breakpoint *));
+static void enable_once_command (char *, int);
-static void
-disable_command PARAMS ((char *, int));
+static void enable_once_breakpoint (struct breakpoint *);
-static void
-enable_command PARAMS ((char *, int));
+static void disable_command (char *, int);
-static void
-map_breakpoint_numbers PARAMS ((char *, void (*)(struct breakpoint *)));
+static void enable_command (char *, int);
-static void
-ignore_command PARAMS ((char *, int));
+static void map_breakpoint_numbers (char *, void (*)(struct breakpoint *));
-static int breakpoint_re_set_one PARAMS ((PTR));
+static void ignore_command (char *, int);
-static void
-clear_command PARAMS ((char *, int));
+static int breakpoint_re_set_one (PTR);
-static void
-catch_command PARAMS ((char *, int));
+static void clear_command (char *, int);
-static void
-handle_gnu_4_16_catch_command PARAMS ((char *, int, int));
+static void catch_command (char *, int);
-static struct symtabs_and_lines
-get_catch_sals PARAMS ((int));
+static void handle_gnu_4_16_catch_command (char *, int, int);
-static void
-watch_command PARAMS ((char *, int));
+static struct symtabs_and_lines get_catch_sals (int);
-static int
-can_use_hardware_watchpoint PARAMS ((struct value *));
+static void watch_command (char *, int);
-static void break_at_finish_command PARAMS ((char *, int));
-static void break_at_finish_at_depth_command PARAMS ((char *, int));
+static int can_use_hardware_watchpoint (struct value *);
-void
-tbreak_command PARAMS ((char *, int));
+static void break_at_finish_command (char *, int);
+static void break_at_finish_at_depth_command (char *, int);
-static void tbreak_at_finish_command PARAMS ((char *, int));
+void tbreak_command (char *, int);
-static void
-break_command_1 PARAMS ((char *, int, int));
+static void tbreak_at_finish_command (char *, int);
-static void
-mention PARAMS ((struct breakpoint *));
+static void break_command_1 (char *, int, int);
-struct breakpoint *
- set_raw_breakpoint PARAMS ((struct symtab_and_line));
+static void mention (struct breakpoint *);
-static void
-check_duplicates PARAMS ((CORE_ADDR, asection *));
+struct breakpoint *set_raw_breakpoint (struct symtab_and_line);
-static void
-describe_other_breakpoints PARAMS ((CORE_ADDR, asection *));
+static void check_duplicates (CORE_ADDR, asection *);
-static void
-breakpoints_info PARAMS ((char *, int));
+static void describe_other_breakpoints (CORE_ADDR, asection *);
-static void
-breakpoint_1 PARAMS ((int, int));
+static void breakpoints_info (char *, int);
-static bpstat
- bpstat_alloc PARAMS ((struct breakpoint *, bpstat));
+static void breakpoint_1 (int, int);
-static int breakpoint_cond_eval PARAMS ((PTR));
+static bpstat bpstat_alloc (struct breakpoint *, bpstat);
-static void
-cleanup_executing_breakpoints PARAMS ((PTR));
+static int breakpoint_cond_eval (PTR);
-static void
-commands_command PARAMS ((char *, int));
+static void cleanup_executing_breakpoints (PTR);
-static void
-condition_command PARAMS ((char *, int));
+static void commands_command (char *, int);
-static int
-get_number PARAMS ((char **));
+static void condition_command (char *, int);
-void
-set_breakpoint_count PARAMS ((int));
+static int get_number_trailer (char **, int);
+
+void set_breakpoint_count (int);
#if 0
-static struct breakpoint *
- create_temp_exception_breakpoint PARAMS ((CORE_ADDR));
+static struct breakpoint *create_temp_exception_breakpoint (CORE_ADDR);
#endif
typedef enum
}
insertion_state_t;
-static int
-remove_breakpoint PARAMS ((struct breakpoint *, insertion_state_t));
+static int remove_breakpoint (struct breakpoint *, insertion_state_t);
-static int print_it_normal PARAMS ((bpstat));
+static enum print_stop_action print_it_typical (bpstat);
+
+static enum print_stop_action print_bp_stop_message (bpstat bs);
typedef struct
{
}
args_for_catchpoint_enable;
-static int watchpoint_check PARAMS ((PTR));
-
-static int cover_target_enable_exception_callback PARAMS ((PTR));
+static int watchpoint_check (PTR);
-static int print_it_done PARAMS ((bpstat));
+static int cover_target_enable_exception_callback (PTR);
-static int print_it_noop PARAMS ((bpstat));
-
-static void maintenance_info_breakpoints PARAMS ((char *, int));
+static void maintenance_info_breakpoints (char *, int);
#ifdef GET_LONGJMP_TARGET
-static void create_longjmp_breakpoint PARAMS ((char *));
+static void create_longjmp_breakpoint (char *);
#endif
-static int hw_breakpoint_used_count PARAMS ((void));
+static int hw_breakpoint_used_count (void);
-static int hw_watchpoint_used_count PARAMS ((enum bptype, int *));
+static int hw_watchpoint_used_count (enum bptype, int *);
-static void hbreak_command PARAMS ((char *, int));
+static void hbreak_command (char *, int);
-static void thbreak_command PARAMS ((char *, int));
+static void thbreak_command (char *, int);
-static void watch_command_1 PARAMS ((char *, int, int));
+static void watch_command_1 (char *, int, int);
-static void rwatch_command PARAMS ((char *, int));
+static void rwatch_command (char *, int);
-static void awatch_command PARAMS ((char *, int));
+static void awatch_command (char *, int);
-static void do_enable_breakpoint PARAMS ((struct breakpoint *, enum bpdisp));
+static void do_enable_breakpoint (struct breakpoint *, enum bpdisp);
-static void create_solib_load_unload_event_breakpoint PARAMS ((char *hookname, int tempflag, char *dll_pathname, char *cond_string, enum bptype bp_kind));
+static void solib_load_unload_1 (char *hookname,
+ int tempflag,
+ char *dll_pathname,
+ char *cond_string, enum bptype bp_kind);
-static void create_fork_vfork_event_catchpoint PARAMS ((int tempflag, char *cond_string, enum bptype bp_kind));
+static void create_fork_vfork_event_catchpoint (int tempflag,
+ char *cond_string,
+ enum bptype bp_kind);
-static void break_at_finish_at_depth_command_1 PARAMS ((char *arg, int flag, int from_tty));
+static void break_at_finish_at_depth_command_1 (char *arg,
+ int flag, int from_tty);
-static void break_at_finish_command_1 PARAMS ((char *arg, int flag, int from_tty));
+static void break_at_finish_command_1 (char *arg, int flag, int from_tty);
-static void stop_command PARAMS ((char *arg, int from_tty));
+static void stop_command (char *arg, int from_tty);
-static void stopin_command PARAMS ((char *arg, int from_tty));
+static void stopin_command (char *arg, int from_tty);
-static void stopat_command PARAMS ((char *arg, int from_tty));
+static void stopat_command (char *arg, int from_tty);
-static char *ep_find_event_name_end PARAMS ((char *arg));
+static char *ep_find_event_name_end (char *arg);
-static char *ep_parse_optional_if_clause PARAMS ((char **arg));
+static char *ep_parse_optional_if_clause (char **arg);
-static char *ep_parse_optional_filename PARAMS ((char **arg));
+static char *ep_parse_optional_filename (char **arg);
-static void catch_exec_command_1 PARAMS ((char *arg, int tempflag, int from_tty));
+#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 PARAMS ((int tempflag, char *cond_string, enum exception_event_kind ex_event, struct symtab_and_line * sal));
+static void create_exception_catchpoint
+ (int tempflag, char *cond_string,
+ enum exception_event_kind ex_event, struct symtab_and_line *sal);
-static void catch_exception_command_1 PARAMS ((enum exception_event_kind ex_event, char *arg, int tempflag, int from_tty));
+static void catch_exception_command_1
+ (enum exception_event_kind ex_event, char *arg, int tempflag, int from_tty);
-static void tcatch_command PARAMS ((char *arg, int from_tty));
+static void tcatch_command (char *arg, int from_tty);
-static void ep_skip_leading_whitespace PARAMS ((char **s));
+static void ep_skip_leading_whitespace (char **s);
/* Prototypes for exported functions. */
-static void
-awatch_command PARAMS ((char *, int));
+static void awatch_command (char *, int);
-static void
-do_enable_breakpoint PARAMS ((struct breakpoint *, enum bpdisp));
+static void do_enable_breakpoint (struct breakpoint *, enum bpdisp);
/* If FALSE, gdb will not use hardware support for watchpoints, even
if such is available. */
static int can_use_hw_watchpoints;
-void delete_command PARAMS ((char *, int));
-
-void _initialize_breakpoint PARAMS ((void));
+void _initialize_breakpoint (void);
-void set_breakpoint_count PARAMS ((int));
+void set_breakpoint_count (int);
extern int addressprint; /* Print machine addresses? */
-#if defined (GET_LONGJMP_TARGET) || defined (SOLIB_ADD)
static int internal_breakpoint_number = -1;
-#endif
/* Are we executing breakpoint commands? */
static int executing_breakpoint_commands;
ALL_BREAKPOINTS_SAFE does so even if the statment deletes the current
breakpoint. */
-#define ALL_BREAKPOINTS(b) for (b = breakpoint_chain; b; b = b->next)
+#define ALL_BREAKPOINTS(B) for (B = breakpoint_chain; B; B = B->next)
-#define ALL_BREAKPOINTS_SAFE(b,tmp) \
- for (b = breakpoint_chain; \
- b? (tmp=b->next, 1): 0; \
- b = tmp)
+#define ALL_BREAKPOINTS_SAFE(B,TMP) \
+ for (B = breakpoint_chain; \
+ B ? (TMP=B->next, 1): 0; \
+ B = TMP)
/* True if SHIFT_INST_REGS defined, false otherwise. */
Currently the string can either be a number or "$" followed by the name
of a convenience variable. Making it an expression wouldn't work well
- for map_breakpoint_numbers (e.g. "4 + 5 + 6"). */
+ for map_breakpoint_numbers (e.g. "4 + 5 + 6").
+
+ TRAILER is a character which can be found after the number; most
+ commonly this is `-'. If you don't want a trailer, use \0. */
static int
-get_number (pp)
+get_number_trailer (pp, trailer)
char **pp;
+ int trailer;
{
- int retval;
+ int retval = 0; /* default */
char *p = *pp;
if (p == NULL)
strncpy (varname, start, p - start);
varname[p - start] = '\0';
val = value_of_internalvar (lookup_internalvar (varname));
- if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_INT)
- error (
- "Convenience variables used to specify breakpoints must have integer values."
- );
- retval = (int) value_as_long (val);
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT)
+ retval = (int) value_as_long (val);
+ else
+ {
+ printf_filtered ("Convenience variable must have integer value.\n");
+ retval = 0;
+ }
}
else
{
++p;
if (p == *pp)
/* There is no number here. (e.g. "cond a == b"). */
- error_no_arg ("breakpoint number");
- retval = atoi (*pp);
+ {
+ /* Skip non-numeric token */
+ while (*p && !isspace((int) *p))
+ ++p;
+ /* Return zero, which caller must interpret as error. */
+ retval = 0;
+ }
+ else
+ retval = atoi (*pp);
+ }
+ if (!(isspace (*p) || *p == '\0' || *p == trailer))
+ {
+ /* Trailing junk: return 0 and let caller print error msg. */
+ while (!(isspace (*p) || *p == '\0' || *p == trailer))
+ ++p;
+ retval = 0;
}
- if (!(isspace (*p) || *p == '\0'))
- error ("breakpoint number expected");
while (isspace (*p))
p++;
*pp = p;
return retval;
}
+
+
+/* Like get_number_trailer, but don't allow a trailer. */
+int
+get_number (pp)
+ char **pp;
+{
+ return get_number_trailer (pp, '\0');
+}
+
+/* Parse a number or a range.
+ * A number will be of the form handled by get_number.
+ * A range will be of the form <number1> - <number2>, and
+ * will represent all the integers between number1 and number2,
+ * inclusive.
+ *
+ * While processing a range, this fuction is called iteratively;
+ * At each call it will return the next value in the range.
+ *
+ * At the beginning of parsing a range, the char pointer PP will
+ * be advanced past <number1> and left pointing at the '-' token.
+ * Subsequent calls will not advance the pointer until the range
+ * is completed. The call that completes the range will advance
+ * pointer PP past <number2>.
+ */
+
+int
+get_number_or_range (pp)
+ char **pp;
+{
+ static int last_retval, end_value;
+ static char *end_ptr;
+ static int in_range = 0;
+
+ if (**pp != '-')
+ {
+ /* Default case: pp is pointing either to a solo number,
+ or to the first number of a range. */
+ last_retval = get_number_trailer (pp, '-');
+ if (**pp == '-')
+ {
+ char **temp;
+
+ /* This is the start of a range (<number1> - <number2>).
+ Skip the '-', parse and remember the second number,
+ and also remember the end of the final token. */
+
+ temp = &end_ptr;
+ end_ptr = *pp + 1;
+ while (isspace ((int) *end_ptr))
+ end_ptr++; /* skip white space */
+ end_value = get_number (temp);
+ if (end_value < last_retval)
+ {
+ error ("inverted range");
+ }
+ else if (end_value == last_retval)
+ {
+ /* degenerate range (number1 == number2). Advance the
+ token pointer so that the range will be treated as a
+ single number. */
+ *pp = end_ptr;
+ }
+ else
+ in_range = 1;
+ }
+ }
+ else if (! in_range)
+ error ("negative value");
+ else
+ {
+ /* pp points to the '-' that betokens a range. All
+ number-parsing has already been done. Return the next
+ integer value (one greater than the saved previous value).
+ Do not advance the token pointer 'pp' until the end of range
+ is reached. */
+
+ if (++last_retval == end_value)
+ {
+ /* End of range reached; advance token pointer. */
+ *pp = end_ptr;
+ in_range = 0;
+ }
+ }
+ return last_retval;
+}
+
+
\f
/* condition N EXP -- set break condition of breakpoint N to EXP. */
p = arg;
bnum = get_number (&p);
+ if (bnum == 0)
+ error ("Bad breakpoint argument: '%s'", arg);
ALL_BREAKPOINTS (b)
if (b->number == bnum)
p = arg;
bnum = get_number (&p);
+
if (p && *p)
error ("Unexpected extra arguments following breakpoint number.");
if (b->number == bnum)
{
char tmpbuf[128];
- sprintf (tmpbuf, "Type commands for when breakpoint %d is hit, one per line.", bnum);
+ sprintf (tmpbuf,
+ "Type commands for when breakpoint %d is hit, one per line.",
+ bnum);
l = read_command_lines (tmpbuf, from_tty);
free_command_lines (&b->commands);
b->commands = l;
ALL_BREAKPOINTS (b)
{
if (b->type == bp_none)
- warning ("attempted to read through apparently deleted breakpoint #%d?\n", b->number);
+ warning ("reading through apparently deleted breakpoint #%d?",
+ b->number);
/* memory breakpoint? */
if (b->type == bp_watchpoint
insert_breakpoints ()
{
register struct breakpoint *b, *temp;
+ int return_val = 0; /* return success code. */
int val = 0;
int disabled_breaks = 0;
ALL_BREAKPOINTS_SAFE (b, temp)
{
- if (b->type != bp_watchpoint
+ if (b->enable == permanent)
+ /* Permanent breakpoints cannot be inserted or removed. */
+ continue;
+ else if (b->type != bp_watchpoint
&& b->type != bp_hardware_watchpoint
&& b->type != bp_read_watchpoint
&& b->type != bp_access_watchpoint
if (!disabled_breaks)
{
target_terminal_ours_for_output ();
- fprintf_unfiltered (gdb_stderr,
- "Cannot insert breakpoint %d:\n", b->number);
- printf_filtered ("Temporarily disabling shared library breakpoints:\n");
+ warning ("Cannot insert breakpoint %d:", b->number);
+ warning ("Temporarily disabling shared library breakpoints:");
}
disabled_breaks = 1;
- printf_filtered ("%d ", b->number);
+ warning ("breakpoint #%d ", b->number);
}
else
#endif
{
target_terminal_ours_for_output ();
- fprintf_unfiltered (gdb_stderr, "Cannot insert breakpoint %d:\n", b->number);
+ warning ("Cannot insert breakpoint %d:", b->number);
#ifdef ONE_PROCESS_WRITETEXT
- fprintf_unfiltered (gdb_stderr,
- "The same program may be running in another process.\n");
+ warning ("The same program may be running in another process.");
#endif
- memory_error (val, b->address); /* which bombs us out */
+ memory_error (val, b->address); /* which bombs us out */
}
}
else
b->inserted = 1;
+
+ if (val)
+ return_val = val; /* remember failure */
}
else if (ep_is_exception_catchpoint (b)
&& b->enable != disabled
/* If we get here, we must have a callback mechanism for exception
events -- with g++ style embedded label support, we insert
ordinary breakpoints and not catchpoints. */
- sprintf (message, message1, b->number); /* Format possible error message */
+ /* Format possible error message */
+ sprintf (message, message1, b->number);
val = target_insert_breakpoint (b->address, b->shadow_contents);
if (val)
{
/* Couldn't set breakpoint for some reason */
target_terminal_ours_for_output ();
- fprintf_unfiltered (gdb_stderr,
- "Cannot insert catchpoint %d; disabling it\n", b->number);
+ warning ("Cannot insert catchpoint %d; disabling it.",
+ b->number);
b->enable = disabled;
}
else
/* Bp set, now make sure callbacks are enabled */
int val;
args_for_catchpoint_enable args;
- args.kind = b->type == bp_catch_catch ? EX_EVENT_CATCH : EX_EVENT_THROW;
+ args.kind = b->type == bp_catch_catch ?
+ EX_EVENT_CATCH : EX_EVENT_THROW;
args.enable = 1;
val = catch_errors (cover_target_enable_exception_callback,
&args,
{
/* something went wrong */
target_terminal_ours_for_output ();
- fprintf_unfiltered (gdb_stderr, "Cannot insert catchpoint %d; disabling it\n", b->number);
+ warning ("Cannot insert catchpoint %d; disabling it.",
+ b->number);
b->enable = disabled;
}
}
+
+ if (val)
+ return_val = val; /* remember failure */
}
else if ((b->type == bp_hardware_watchpoint ||
b->type == bp_read_watchpoint ||
b->type == bp_access_watchpoint)
&& b->enable == enabled
+ && b->disposition != del_at_next_stop
&& !b->inserted
&& !b->duplicate)
{
if (within_current_scope)
{
/* Evaluate the expression and cut the chain of values
- produced off from the value chain. */
+ produced off from the value chain.
+
+ Make sure the value returned isn't lazy; we use
+ laziness to determine what memory GDB actually needed
+ in order to compute the value of the expression. */
v = evaluate_expression (b->exp);
+ VALUE_CONTENTS(v);
value_release_to_mark (mark);
b->val_chain = v;
/* Look at each value on the value chain. */
for (; v; v = v->next)
{
- /* If it's a memory location, then we must watch it. */
- if (v->lval == lval_memory)
+ /* If it's a memory location, and GDB actually needed
+ its contents to evaluate the expression, then we
+ must watch it. */
+ if (VALUE_LVAL (v) == lval_memory
+ && ! VALUE_LAZY (v))
{
- int addr, len, type;
-
- addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
- len = TYPE_LENGTH (VALUE_TYPE (v));
- type = 0;
- if (b->type == bp_read_watchpoint)
- type = 1;
- else if (b->type == bp_access_watchpoint)
- type = 2;
-
- val = target_insert_watchpoint (addr, len, type);
- if (val == -1)
+ struct type *vtype = check_typedef (VALUE_TYPE (v));
+
+ /* We only watch structs and arrays if user asked
+ for it explicitly, never if they just happen to
+ appear in the middle of some value chain. */
+ if (v == b->val_chain
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
{
- b->inserted = 0;
- break;
+ CORE_ADDR addr;
+ int len, type;
+
+ addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ len = TYPE_LENGTH (VALUE_TYPE (v));
+ type = hw_write;
+ if (b->type == bp_read_watchpoint)
+ type = hw_read;
+ else if (b->type == bp_access_watchpoint)
+ type = hw_access;
+
+ val = target_insert_watchpoint (addr, len, type);
+ if (val == -1)
+ {
+ /* Don't exit the loop, try to insert
+ every value on the value chain. That's
+ because we will be removing all the
+ watches below, and removing a
+ watchpoint we didn't insert could have
+ adverse effects. */
+ b->inserted = 0;
+ }
+ val = 0;
}
- val = 0;
}
}
/* Failure to insert a watchpoint on any memory value in the
value chain brings us here. */
if (!b->inserted)
- warning ("Hardware watchpoint %d: Could not insert watchpoint\n",
- b->number);
+ {
+ remove_breakpoint (b, mark_uninserted);
+ warning ("Could not insert hardware watchpoint %d.",
+ b->number);
+ val = -1;
+ }
}
else
{
- printf_filtered ("\
-Hardware watchpoint %d deleted because the program has left the block in\n\
-which its expression is valid.\n", b->number);
+ printf_filtered ("Hardware watchpoint %d deleted ", b->number);
+ printf_filtered ("because the program has left the block \n");
+ printf_filtered ("in which its expression is valid.\n");
if (b->related_breakpoint)
b->related_breakpoint->disposition = del_at_next_stop;
b->disposition = del_at_next_stop;
/* Restore the frame and level. */
if ((saved_frame != selected_frame) ||
(saved_level != selected_frame_level))
- select_and_print_frame (saved_frame, saved_level);
+ select_frame (saved_frame, saved_level);
+
+ if (val)
+ return_val = val; /* remember failure */
}
else if ((b->type == bp_catch_fork
|| b->type == bp_catch_vfork
val = target_insert_exec_catchpoint (inferior_pid);
break;
default:
- warning ("GDB bug: breakpoint.c (insert_breakpoints): enclosing `if' does not protect `switch'");
+ warning ("Internal error, %s line %d.", __FILE__, __LINE__);
break;
}
if (val < 0)
{
target_terminal_ours_for_output ();
- fprintf_unfiltered (gdb_stderr, "Cannot insert catchpoint %d:\n", b->number);
+ warning ("Cannot insert catchpoint %d.", b->number);
}
else
b->inserted = 1;
+
+ if (val)
+ return_val = val; /* remember failure */
}
}
- if (disabled_breaks)
- printf_filtered ("\n");
- return val;
+ return return_val;
}
return 0;
}
+int
+remove_hw_watchpoints (void)
+{
+ register struct breakpoint *b;
+ int val;
+
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->inserted
+ && (b->type == bp_hardware_watchpoint
+ || b->type == bp_read_watchpoint
+ || b->type == bp_access_watchpoint))
+ {
+ val = remove_breakpoint (b, mark_uninserted);
+ if (val != 0)
+ return val;
+ }
+ }
+ return 0;
+}
+
int
reattach_breakpoints (pid)
int pid;
int val;
int saved_inferior_pid = inferior_pid;
- inferior_pid = pid; /* Because remove_breakpoint will use this global. */
+ /* FIXME: use a cleanup, to insure that inferior_pid gets replaced! */
+ inferior_pid = pid; /* Because remove_breakpoint will use this global. */
ALL_BREAKPOINTS (b)
{
if (b->inserted)
continue;
}
+ /* Thread event breakpoints must be set anew after an exec(). */
+ if (b->type == bp_thread_event)
+ {
+ delete_breakpoint (b);
+ continue;
+ }
+
/* Step-resume breakpoints are meaningless after an exec(). */
if (b->type == bp_step_resume)
{
won't stop when it ought!
Similarly, we probably ought to keep vfork catchpoints, 'cause
- on this target, we may not be able to stop when the vfork is seen,
- but only when the subsequent exec is seen. (And because deleting
- fork catchpoints here but not vfork catchpoints will seem mysterious
- to users, keep those too.)
+ on this target, we may not be able to stop when the vfork is
+ seen, but only when the subsequent exec is seen. (And because
+ deleting fork catchpoints here but not vfork catchpoints will
+ seem mysterious to users, keep those too.)
??rehrauer: Let's hope that merely clearing out this catchpoint's
target address field, if any, is sufficient to have it be reset
gets 'round to deleting the "use to be a bp_finish" breakpoint.
We really must allow finish_command to delete a bp_finish.
- In the absense of a general solution for the "how do we know it's
- safe to delete something others may have handles to?" problem, what
- we'll do here is just uninsert the bp_finish, and let finish_command
- delete it.
+ In the absense of a general solution for the "how do we know
+ it's safe to delete something others may have handles to?"
+ problem, what we'll do here is just uninsert the bp_finish, and
+ let finish_command delete it.
+
+ (We know the bp_finish is "doomed" in the sense that it's
+ momentary, and will be deleted as soon as finish_command sees
+ the inferior stopped. So it doesn't matter that the bp's
+ address is probably bogus in the new a.out, unlike e.g., the
+ solib breakpoints.) */
- (We know the bp_finish is "doomed" in the sense that it's momentary,
- and will be deleted as soon as finish_command sees the inferior stopped.
- So it doesn't matter that the bp's address is probably bogus in the
- new a.out, unlike e.g., the solib breakpoints.) */
if (b->type == bp_finish)
{
continue;
if (pid == inferior_pid)
error ("Cannot detach breakpoints of inferior_pid");
- inferior_pid = pid; /* Because remove_breakpoint will use this global. */
+ /* FIXME: use a cleanup, to insure that inferior_pid gets replaced! */
+ inferior_pid = pid; /* Because remove_breakpoint will use this global. */
ALL_BREAKPOINTS (b)
{
if (b->inserted)
{
int val;
+ if (b->enable == permanent)
+ /* Permanent breakpoints cannot be inserted or removed. */
+ return 0;
+
if (b->type == bp_none)
- warning ("attempted to remove apparently deleted breakpoint #%d?\n", b->number);
+ warning ("attempted to remove apparently deleted breakpoint #%d?",
+ b->number);
if (b->type != bp_watchpoint
&& b->type != bp_hardware_watchpoint
&& b->type != bp_catch_exec
&& b->type != bp_catch_catch
&& b->type != bp_catch_throw)
-
{
if (b->type == bp_hardware_breakpoint)
val = target_remove_hw_breakpoint (b->address, b->shadow_contents);
{
/* For each memory reference remove the watchpoint
at that address. */
- if (v->lval == lval_memory)
+ if (VALUE_LVAL (v) == lval_memory
+ && ! VALUE_LAZY (v))
{
- int addr, len, type;
+ struct type *vtype = check_typedef (VALUE_TYPE (v));
- addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
- len = TYPE_LENGTH (VALUE_TYPE (v));
- type = 0;
- if (b->type == bp_read_watchpoint)
- type = 1;
- else if (b->type == bp_access_watchpoint)
- type = 2;
-
- val = target_remove_watchpoint (addr, len, type);
- if (val == -1)
- b->inserted = 1;
- val = 0;
+ if (v == b->val_chain
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ {
+ CORE_ADDR addr;
+ int len, type;
+
+ addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ len = TYPE_LENGTH (VALUE_TYPE (v));
+ type = hw_write;
+ if (b->type == bp_read_watchpoint)
+ type = hw_read;
+ else if (b->type == bp_access_watchpoint)
+ type = hw_access;
+
+ val = target_remove_watchpoint (addr, len, type);
+ if (val == -1)
+ b->inserted = 1;
+ val = 0;
+ }
}
}
/* Failure to remove any of the hardware watchpoints comes here. */
if ((is == mark_uninserted) && (b->inserted))
- warning ("Hardware watchpoint %d: Could not remove watchpoint\n",
+ warning ("Could not remove hardware watchpoint %d.",
b->number);
/* Free the saved value chain. We will construct a new one
val = target_remove_exec_catchpoint (inferior_pid);
break;
default:
- warning ("GDB bug: breakpoint.c (remove_breakpoint): enclosing `if' does not protect `switch'");
+ warning ("Internal error, %s line %d.", __FILE__, __LINE__);
break;
}
if (val)
b->inserted = 0;
}
-/* Clear the "inserted" flag in all breakpoints and delete any breakpoints
- which should go away between runs of the program.
+/* Clear the "inserted" flag in all breakpoints and delete any
+ breakpoints which should go away between runs of the program.
Plus other such housekeeping that has to be done for breakpoints
between runs.
- Note: this function gets called at the end of a run (by generic_mourn_inferior)
- and when a run begins (by init_wait_for_inferior). */
+ Note: this function gets called at the end of a run (by
+ generic_mourn_inferior) and when a run begins (by
+ init_wait_for_inferior). */
/* Don't issue the warning unless it's really needed... */
if (warning_needed && (context != inf_exited))
{
- warning ("Exception catchpoints from last run were deleted, you must reinsert them explicitly");
+ warning ("Exception catchpoints from last run were deleted.");
+ warning ("You must reinsert them explicitly.");
warning_needed = 0;
}
}
-/* breakpoint_here_p (PC) returns 1 if an enabled breakpoint exists at PC.
- When continuing from a location with a breakpoint,
- we actually single step once before calling insert_breakpoints. */
+/* breakpoint_here_p (PC) returns non-zero if an enabled breakpoint
+ exists at PC. It returns ordinary_breakpoint_here if it's an
+ ordinary breakpoint, or permanent_breakpoint_here if it's a
+ permanent breakpoint.
+ - When continuing from a location with an ordinary breakpoint, we
+ actually single step once before calling insert_breakpoints.
+ - When continuing from a localion with a permanent breakpoint, we
+ need to use the `SKIP_PERMANENT_BREAKPOINT' macro, provided by
+ the target, to advance the PC past the breakpoint. */
-int
+enum breakpoint_here
breakpoint_here_p (pc)
CORE_ADDR pc;
{
register struct breakpoint *b;
+ int any_breakpoint_here = 0;
ALL_BREAKPOINTS (b)
- if (b->enable == enabled
- && b->enable != shlib_disabled
- && b->enable != call_disabled
+ if ((b->enable == enabled
+ || b->enable == permanent)
&& b->address == pc) /* bp is enabled and matches pc */
- {
- if (overlay_debugging &&
- section_is_overlay (b->section) &&
- !section_is_mapped (b->section))
- continue; /* unmapped overlay -- can't be a match */
- else
- return 1;
- }
+ {
+ if (overlay_debugging &&
+ section_is_overlay (b->section) &&
+ !section_is_mapped (b->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else if (b->enable == permanent)
+ return permanent_breakpoint_here;
+ else
+ any_breakpoint_here = 1;
+ }
- return 0;
+ return any_breakpoint_here ? ordinary_breakpoint_here : 0;
}
-/* breakpoint_inserted_here_p (PC) is just like breakpoint_here_p(), but it
- only returns true if there is actually a breakpoint inserted at PC. */
+
+/* breakpoint_inserted_here_p (PC) is just like breakpoint_here_p(),
+ but it only returns true if there is actually a breakpoint inserted
+ at PC. */
int
breakpoint_inserted_here_p (pc)
return 0;
}
-/* Return nonzero if FRAME is a dummy frame. We can't use PC_IN_CALL_DUMMY
- because figuring out the saved SP would take too much time, at least using
- get_saved_register on the 68k. This means that for this function to
- work right a port must use the bp_call_dummy breakpoint. */
+/* Return nonzero if FRAME is a dummy frame. We can't use
+ PC_IN_CALL_DUMMY because figuring out the saved SP would take too
+ much time, at least using get_saved_register on the 68k. This
+ means that for this function to work right a port must use the
+ bp_call_dummy breakpoint. */
int
frame_in_dummy (frame)
discard_cleanups (old_chain);
}
-/* This is the normal print_it function for a bpstat. In the future,
+/* This is the normal print function for a bpstat. In the future,
much of this logic could (should?) be moved to bpstat_stop_status,
- by having it set different print_it functions.
-
- Current scheme: When we stop, bpstat_print() is called.
- It loops through the bpstat list of things causing this stop,
- calling the print_it function for each one. The default
- print_it function, used for breakpoints, is print_it_normal().
- (Also see print_it_noop() and print_it_done()).
-
- Return values from this routine (used by bpstat_print() to
- decide what to do):
- 1: Means we printed something, and we do *not* desire that
- something to be followed by a location.
- 0: Means we printed something, and we *do* desire that
- something to be followed by a location.
- -1: Means we printed nothing. */
-
-static int
-print_it_normal (bs)
+ by having it set different print_it values.
+
+ Current scheme: When we stop, bpstat_print() is called. It loops
+ through the bpstat list of things causing this stop, calling the
+ print_bp_stop_message function on each one. The behavior of the
+ print_bp_stop_message function depends on the print_it field of
+ bpstat. If such field so indicates, call this function here.
+
+ Return values from this routine (ultimately used by bpstat_print()
+ and normal_stop() to decide what to do):
+ PRINT_NOTHING: Means we already printed all we needed to print,
+ don't print anything else.
+ PRINT_SRC_ONLY: Means we printed something, and we do *not* desire
+ that something to be followed by a location.
+ PRINT_SCR_AND_LOC: Means we printed something, and we *do* desire
+ that something to be followed by a location.
+ PRINT_UNKNOWN: Means we printed nothing or we need to do some more
+ analysis. */
+
+static enum print_stop_action
+print_it_typical (bs)
bpstat bs;
{
+#ifdef UI_OUT
+ struct cleanup *old_chain;
+ struct ui_stream *stb;
+ stb = ui_out_stream_new (uiout);
+ old_chain = make_cleanup_ui_out_stream_delete (stb);
+#endif /* UI_OUT */
/* bs->breakpoint_at can be NULL if it was a momentary breakpoint
which has since been deleted. */
- if (bs->breakpoint_at == NULL
- || (bs->breakpoint_at->type != bp_breakpoint
- && bs->breakpoint_at->type != bp_catch_load
- && bs->breakpoint_at->type != bp_catch_unload
- && bs->breakpoint_at->type != bp_catch_fork
- && bs->breakpoint_at->type != bp_catch_vfork
- && bs->breakpoint_at->type != bp_catch_exec
- && bs->breakpoint_at->type != bp_catch_catch
- && bs->breakpoint_at->type != bp_catch_throw
- && bs->breakpoint_at->type != bp_hardware_breakpoint
- && bs->breakpoint_at->type != bp_watchpoint
- && bs->breakpoint_at->type != bp_read_watchpoint
- && bs->breakpoint_at->type != bp_access_watchpoint
- && bs->breakpoint_at->type != bp_hardware_watchpoint))
- return -1;
+ if (bs->breakpoint_at == NULL)
+ return PRINT_UNKNOWN;
- if (ep_is_shlib_catchpoint (bs->breakpoint_at))
+ switch (bs->breakpoint_at->type)
{
+ case bp_breakpoint:
+ case bp_hardware_breakpoint:
+#ifdef UI_OUT
+ annotate_breakpoint (bs->breakpoint_at->number);
+ ui_out_text (uiout, "\nBreakpoint ");
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "breakpoint-hit");
+ ui_out_field_int (uiout, "bkptno", bs->breakpoint_at->number);
+ ui_out_text (uiout, ", ");
+ return PRINT_SRC_AND_LOC;
+#else
+ /* I think the user probably only wants to see one breakpoint
+ number, not all of them. */
+ annotate_breakpoint (bs->breakpoint_at->number);
+ printf_filtered ("\nBreakpoint %d, ", bs->breakpoint_at->number);
+ return PRINT_SRC_AND_LOC;
+#endif
+ break;
+
+ case bp_shlib_event:
+ /* Did we stop because the user set the stop_on_solib_events
+ variable? (If so, we report this as a generic, "Stopped due
+ to shlib event" message.) */
+ printf_filtered ("Stopped due to shared library event\n");
+ return PRINT_NOTHING;
+ break;
+
+ case bp_thread_event:
+ /* Not sure how we will get here.
+ GDB should not stop for these breakpoints. */
+ printf_filtered ("Thread Event Breakpoint: gdb should not stop!\n");
+ return PRINT_NOTHING;
+ break;
+
+ case bp_catch_load:
annotate_catchpoint (bs->breakpoint_at->number);
printf_filtered ("\nCatchpoint %d (", bs->breakpoint_at->number);
- if (bs->breakpoint_at->type == bp_catch_load)
- printf_filtered ("loaded");
- else if (bs->breakpoint_at->type == bp_catch_unload)
- printf_filtered ("unloaded");
+ printf_filtered ("loaded");
printf_filtered (" %s), ", bs->breakpoint_at->triggered_dll_pathname);
- return 0;
- }
- else if (bs->breakpoint_at->type == bp_catch_fork ||
- bs->breakpoint_at->type == bp_catch_vfork)
- {
+ return PRINT_SRC_AND_LOC;
+ break;
+
+ case bp_catch_unload:
annotate_catchpoint (bs->breakpoint_at->number);
printf_filtered ("\nCatchpoint %d (", bs->breakpoint_at->number);
- if (bs->breakpoint_at->type == bp_catch_fork)
- printf_filtered ("forked");
- else if (bs->breakpoint_at->type == bp_catch_vfork)
- printf_filtered ("vforked");
- printf_filtered (" process %d), ", bs->breakpoint_at->forked_inferior_pid);
- return 0;
- }
- else if (bs->breakpoint_at->type == bp_catch_exec)
- {
+ printf_filtered ("unloaded");
+ printf_filtered (" %s), ", bs->breakpoint_at->triggered_dll_pathname);
+ return PRINT_SRC_AND_LOC;
+ break;
+
+ case bp_catch_fork:
+ annotate_catchpoint (bs->breakpoint_at->number);
+ printf_filtered ("\nCatchpoint %d (", bs->breakpoint_at->number);
+ printf_filtered ("forked");
+ printf_filtered (" process %d), ",
+ bs->breakpoint_at->forked_inferior_pid);
+ return PRINT_SRC_AND_LOC;
+ break;
+
+ case bp_catch_vfork:
+ annotate_catchpoint (bs->breakpoint_at->number);
+ printf_filtered ("\nCatchpoint %d (", bs->breakpoint_at->number);
+ printf_filtered ("vforked");
+ printf_filtered (" process %d), ",
+ bs->breakpoint_at->forked_inferior_pid);
+ return PRINT_SRC_AND_LOC;
+ break;
+
+ case bp_catch_exec:
annotate_catchpoint (bs->breakpoint_at->number);
printf_filtered ("\nCatchpoint %d (exec'd %s), ",
bs->breakpoint_at->number,
bs->breakpoint_at->exec_pathname);
- return 0;
- }
- else if (bs->breakpoint_at->type == bp_catch_catch)
- {
- if (current_exception_event && (CURRENT_EXCEPTION_KIND == EX_EVENT_CATCH))
+ return PRINT_SRC_AND_LOC;
+ break;
+
+ case bp_catch_catch:
+ if (current_exception_event &&
+ (CURRENT_EXCEPTION_KIND == EX_EVENT_CATCH))
{
annotate_catchpoint (bs->breakpoint_at->number);
- printf_filtered ("\nCatchpoint %d (exception caught), ", bs->breakpoint_at->number);
+ printf_filtered ("\nCatchpoint %d (exception caught), ",
+ bs->breakpoint_at->number);
printf_filtered ("throw location ");
if (CURRENT_EXCEPTION_THROW_PC && CURRENT_EXCEPTION_THROW_LINE)
printf_filtered ("%s:%d",
printf_filtered ("unknown");
printf_filtered ("\n");
- return 1; /* don't bother to print location frame info */
+ /* don't bother to print location frame info */
+ return PRINT_SRC_ONLY;
}
else
{
- return -1; /* really throw, some other bpstat will handle it */
+ /* really throw, some other bpstat will handle it */
+ return PRINT_UNKNOWN;
}
- }
- else if (bs->breakpoint_at->type == bp_catch_throw)
- {
- if (current_exception_event && (CURRENT_EXCEPTION_KIND == EX_EVENT_THROW))
+ break;
+
+ case bp_catch_throw:
+ if (current_exception_event &&
+ (CURRENT_EXCEPTION_KIND == EX_EVENT_THROW))
{
annotate_catchpoint (bs->breakpoint_at->number);
- printf_filtered ("\nCatchpoint %d (exception thrown), ", bs->breakpoint_at->number);
+ printf_filtered ("\nCatchpoint %d (exception thrown), ",
+ bs->breakpoint_at->number);
printf_filtered ("throw location ");
if (CURRENT_EXCEPTION_THROW_PC && CURRENT_EXCEPTION_THROW_LINE)
printf_filtered ("%s:%d",
printf_filtered ("unknown");
printf_filtered ("\n");
- return 1; /* don't bother to print location frame info */
+ /* don't bother to print location frame info */
+ return PRINT_SRC_ONLY;
}
else
{
- return -1; /* really catch, some other bpstat willhandle it */
+ /* really catch, some other bpstat will handle it */
+ return PRINT_UNKNOWN;
}
- }
+ break;
- else if (bs->breakpoint_at->type == bp_breakpoint ||
- bs->breakpoint_at->type == bp_hardware_breakpoint)
- {
- /* I think the user probably only wants to see one breakpoint
- number, not all of them. */
- annotate_breakpoint (bs->breakpoint_at->number);
- printf_filtered ("\nBreakpoint %d, ", bs->breakpoint_at->number);
- return 0;
- }
- else if ((bs->old_val != NULL) &&
- (bs->breakpoint_at->type == bp_watchpoint ||
- bs->breakpoint_at->type == bp_access_watchpoint ||
- bs->breakpoint_at->type == bp_hardware_watchpoint))
- {
- annotate_watchpoint (bs->breakpoint_at->number);
- mention (bs->breakpoint_at);
- printf_filtered ("\nOld value = ");
- value_print (bs->old_val, gdb_stdout, 0, Val_pretty_default);
- printf_filtered ("\nNew value = ");
- value_print (bs->breakpoint_at->val, gdb_stdout, 0,
- Val_pretty_default);
- printf_filtered ("\n");
- value_free (bs->old_val);
- bs->old_val = NULL;
+ case bp_watchpoint:
+ case bp_hardware_watchpoint:
+ if (bs->old_val != NULL)
+ {
+ annotate_watchpoint (bs->breakpoint_at->number);
+#ifdef UI_OUT
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "watchpoint-trigger");
+ mention (bs->breakpoint_at);
+ ui_out_list_begin (uiout, "value");
+ ui_out_text (uiout, "\nOld value = ");
+ value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
+ ui_out_field_stream (uiout, "old", stb);
+ ui_out_text (uiout, "\nNew value = ");
+ value_print (bs->breakpoint_at->val, stb->stream, 0, Val_pretty_default);
+ ui_out_field_stream (uiout, "new", stb);
+ ui_out_list_end (uiout);
+ ui_out_text (uiout, "\n");
+#else
+ mention (bs->breakpoint_at);
+ printf_filtered ("\nOld value = ");
+ value_print (bs->old_val, gdb_stdout, 0, Val_pretty_default);
+ printf_filtered ("\nNew value = ");
+ value_print (bs->breakpoint_at->val, gdb_stdout, 0,
+ Val_pretty_default);
+ printf_filtered ("\n");
+#endif
+ value_free (bs->old_val);
+ bs->old_val = NULL;
+ }
/* More than one watchpoint may have been triggered. */
- return -1;
- }
- else if (bs->breakpoint_at->type == bp_access_watchpoint ||
- bs->breakpoint_at->type == bp_read_watchpoint)
- {
+ return PRINT_UNKNOWN;
+ break;
+
+ case bp_read_watchpoint:
+#ifdef UI_OUT
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "read-watchpoint-trigger");
+ mention (bs->breakpoint_at);
+ ui_out_list_begin (uiout, "value");
+ ui_out_text (uiout, "\nValue = ");
+ value_print (bs->breakpoint_at->val, stb->stream, 0, Val_pretty_default);
+ ui_out_field_stream (uiout, "value", stb);
+ ui_out_list_end (uiout);
+ ui_out_text (uiout, "\n");
+#else
mention (bs->breakpoint_at);
printf_filtered ("\nValue = ");
value_print (bs->breakpoint_at->val, gdb_stdout, 0,
Val_pretty_default);
printf_filtered ("\n");
- return -1;
- }
- /* We can't deal with it. Maybe another member of the bpstat chain can. */
- return -1;
-}
+#endif
+ return PRINT_UNKNOWN;
+ break;
-/* Print a message indicating what happened.
- This is called from normal_stop().
- The input to this routine is the head of the bpstat list - a list
- of the eventpoints that caused this stop.
- This routine calls the "print_it" routine(s) associated
- with these eventpoints. This will print (for example)
- the "Breakpoint n," part of the output.
- The return value of this routine is one of:
+ case bp_access_watchpoint:
+#ifdef UI_OUT
+ if (bs->old_val != NULL)
+ {
+ annotate_watchpoint (bs->breakpoint_at->number);
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "access-watchpoint-trigger");
+ mention (bs->breakpoint_at);
+ ui_out_list_begin (uiout, "value");
+ ui_out_text (uiout, "\nOld value = ");
+ value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
+ ui_out_field_stream (uiout, "old", stb);
+ value_free (bs->old_val);
+ bs->old_val = NULL;
+ ui_out_text (uiout, "\nNew value = ");
+ }
+ else
+ {
+ mention (bs->breakpoint_at);
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_list_begin (uiout, "value");
+ ui_out_field_string (uiout, "reason", "access-watchpoint-trigger");
+ ui_out_text (uiout, "\nValue = ");
+ }
+ value_print (bs->breakpoint_at->val, stb->stream, 0,Val_pretty_default);
+ ui_out_field_stream (uiout, "new", stb);
+ ui_out_list_end (uiout);
+ ui_out_text (uiout, "\n");
+#else
+ if (bs->old_val != NULL)
+ {
+ annotate_watchpoint (bs->breakpoint_at->number);
+ mention (bs->breakpoint_at);
+ printf_filtered ("\nOld value = ");
+ value_print (bs->old_val, gdb_stdout, 0, Val_pretty_default);
+ value_free (bs->old_val);
+ bs->old_val = NULL;
+ printf_filtered ("\nNew value = ");
+ }
+ else
+ {
+ mention (bs->breakpoint_at);
+ printf_filtered ("\nValue = ");
+ }
+ value_print (bs->breakpoint_at->val, gdb_stdout, 0,
+ Val_pretty_default);
+ printf_filtered ("\n");
+#endif
+ return PRINT_UNKNOWN;
+ break;
- -1: Means we printed nothing
- 0: Means we printed something, and expect subsequent
- code to print the location. An example is
- "Breakpoint 1, " which should be followed by
- the location.
- 1 : Means we printed something, but there is no need
- to also print the location part of the message.
- An example is the catch/throw messages, which
- don't require a location appended to the end. */
+ /* Fall through, we don't deal with these types of breakpoints
+ here. */
-int
+ case bp_finish:
+#ifdef UI_OUT
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "function-finished");
+#endif
+ return PRINT_UNKNOWN;
+ break;
+
+ case bp_until:
+#ifdef UI_OUT
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "location-reached");
+#endif
+ return PRINT_UNKNOWN;
+ break;
+
+ case bp_none:
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ case bp_step_resume:
+ case bp_through_sigtramp:
+ case bp_watchpoint_scope:
+ case bp_call_dummy:
+ default:
+ return PRINT_UNKNOWN;
+ }
+}
+
+/* Generic routine for printing messages indicating why we
+ stopped. The behavior of this function depends on the value
+ 'print_it' in the bpstat structure. Under some circumstances we
+ may decide not to print anything here and delegate the task to
+ normal_stop(). */
+
+static enum print_stop_action
+print_bp_stop_message (bpstat bs)
+{
+ switch (bs->print_it)
+ {
+ case print_it_noop:
+ /* Nothing should be printed for this bpstat entry. */
+ return PRINT_UNKNOWN;
+ break;
+
+ case print_it_done:
+ /* We still want to print the frame, but we already printed the
+ relevant messages. */
+ return PRINT_SRC_AND_LOC;
+ break;
+
+ case print_it_normal:
+ /* Normal case, we handle everything in print_it_typical. */
+ return print_it_typical (bs);
+ break;
+ default:
+ internal_error ("print_bp_stop_message: unrecognized enum value");
+ break;
+ }
+}
+
+/* Print a message indicating what happened. This is called from
+ normal_stop(). The input to this routine is the head of the bpstat
+ list - a list of the eventpoints that caused this stop. This
+ routine calls the generic print routine for printing a message
+ about reasons for stopping. This will print (for example) the
+ "Breakpoint n," part of the output. The return value of this
+ routine is one of:
+
+ PRINT_UNKNOWN: Means we printed nothing
+ PRINT_SRC_AND_LOC: Means we printed something, and expect subsequent
+ code to print the location. An example is
+ "Breakpoint 1, " which should be followed by
+ the location.
+ PRINT_SRC_ONLY: Means we printed something, but there is no need
+ to also print the location part of the message.
+ An example is the catch/throw messages, which
+ don't require a location appended to the end.
+ PRINT_NOTHING: We have done some printing and we don't need any
+ further info to be printed.*/
+
+enum print_stop_action
bpstat_print (bs)
bpstat bs;
{
int val;
- if (bs == NULL)
- return -1;
-
- val = (*bs->print_it) (bs);
- if (val >= 0)
- return val;
-
/* Maybe another breakpoint in the chain caused us to stop.
- (Currently all watchpoints go on the bpstat whether hit or
- not. That probably could (should) be changed, provided care is taken
+ (Currently all watchpoints go on the bpstat whether hit or not.
+ That probably could (should) be changed, provided care is taken
with respect to bpstat_explains_signal). */
- if (bs->next)
- return bpstat_print (bs->next);
+ for (; bs; bs = bs->next)
+ {
+ val = print_bp_stop_message (bs);
+ if (val == PRINT_SRC_ONLY
+ || val == PRINT_SRC_AND_LOC
+ || val == PRINT_NOTHING)
+ return val;
+ }
- /* We reached the end of the chain without printing anything. */
- return -1;
+ /* We reached the end of the chain, or we got a null BS to start
+ with and nothing was printed. */
+ return PRINT_UNKNOWN;
}
/* Evaluate the expression EXP and return 1 if value is zero.
So we can't even detect the first assignment to it and
watch after that (since the garbage may or may not equal
the first value assigned). */
+ /* We print all the stop information in print_it_typical(), but
+ in this case, by the time we call print_it_typical() this bp
+ will be deleted already. So we have no choice but print the
+ information here. */
+#ifdef UI_OUT
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "watchpoint-scope");
+ ui_out_text (uiout, "\nWatchpoint ");
+ ui_out_field_int (uiout, "wpnum", bs->breakpoint_at->number);
+ ui_out_text (uiout, " deleted because the program has left the block in\n\
+which its expression is valid.\n");
+#else
printf_filtered ("\
Watchpoint %d deleted because the program has left the block in\n\
which its expression is valid.\n", bs->breakpoint_at->number);
+#endif
+
if (b->related_breakpoint)
b->related_breakpoint->disposition = del_at_next_stop;
b->disposition = del_at_next_stop;
}
}
-/* This is used when everything which needs to be printed has
- already been printed. But we still want to print the frame. */
-
-/* Background: When we stop, bpstat_print() is called.
- It loops through the bpstat list of things causing this stop,
- calling the print_it function for each one. The default
- print_it function, used for breakpoints, is print_it_normal().
- Also see print_it_noop() and print_it_done() are the other
- two possibilities. See comments in bpstat_print() and
- in header of print_it_normal() for more detail. */
-
-static int
-print_it_done (bs)
- bpstat bs;
-{
- return 0;
-}
-
-/* This is used when nothing should be printed for this bpstat entry. */
-/* Background: When we stop, bpstat_print() is called.
- It loops through the bpstat list of things causing this stop,
- calling the print_it function for each one. The default
- print_it function, used for breakpoints, is print_it_normal().
- Also see print_it_noop() and print_it_done() are the other
- two possibilities. See comments in bpstat_print() and
- in header of print_it_normal() for more detail. */
-
-static int
-print_it_noop (bs)
- bpstat bs;
-{
- return -1;
-}
-
/* 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_BREAKPOINT is nonzero
char message[sizeof (message1) + 30 /* slop */ ];
/* Get the address where the breakpoint would have been. */
- bp_addr = *pc - DECR_PC_AFTER_BREAK;
+ bp_addr = *pc - (not_a_breakpoint && !SOFTWARE_SINGLE_STEP_P ?
+ 0 : DECR_PC_AFTER_BREAK);
ALL_BREAKPOINTS_SAFE (b, temp)
{
&& b->address != (*pc - DECR_PC_AFTER_HW_BREAK))
continue;
- if (b->type != bp_watchpoint
- && b->type != bp_hardware_watchpoint
- && b->type != bp_read_watchpoint
- && b->type != bp_access_watchpoint
- && not_a_breakpoint)
- continue;
-
/* Is this a catchpoint of a load or unload? If so, did we
get a load or unload of the specified library? If not,
ignore it. */
#if defined(SOLIB_HAVE_LOAD_EVENT)
&& (!SOLIB_HAVE_LOAD_EVENT (inferior_pid)
|| ((b->dll_pathname != NULL)
- && (strcmp (b->dll_pathname, SOLIB_LOADED_LIBRARY_PATHNAME (inferior_pid)) != 0)))
+ && (strcmp (b->dll_pathname,
+ SOLIB_LOADED_LIBRARY_PATHNAME (inferior_pid))
+ != 0)))
#endif
)
continue;
#if defined(SOLIB_HAVE_UNLOAD_EVENT)
&& (!SOLIB_HAVE_UNLOAD_EVENT (inferior_pid)
|| ((b->dll_pathname != NULL)
- && (strcmp (b->dll_pathname, SOLIB_UNLOADED_LIBRARY_PATHNAME (inferior_pid)) != 0)))
+ && (strcmp (b->dll_pathname,
+ SOLIB_UNLOADED_LIBRARY_PATHNAME (inferior_pid))
+ != 0)))
#endif
)
continue;
bs->print = 1;
sprintf (message, message1, b->number);
- if (b->type == bp_watchpoint || b->type == bp_hardware_watchpoint)
+ if (b->type == bp_watchpoint ||
+ b->type == bp_hardware_watchpoint)
{
- switch (catch_errors (watchpoint_check, bs, message, RETURN_MASK_ALL))
+ switch (catch_errors (watchpoint_check, bs, message,
+ RETURN_MASK_ALL))
{
case WP_DELETED:
/* We've already printed what needs to be printed. */
+ /* Actually this is superfluous, because by the time we
+ call print_it_typical() the wp will be already deleted,
+ and the function will return immediately. */
bs->print_it = print_it_done;
/* Stop. */
break;
/* Don't stop. */
bs->print_it = print_it_noop;
bs->stop = 0;
- /* Don't consider this a hit. */
- --(b->hit_count);
continue;
default:
/* Can't happen. */
break;
}
}
- else if (b->type == bp_read_watchpoint || b->type == bp_access_watchpoint)
+ else if (b->type == bp_read_watchpoint ||
+ b->type == bp_access_watchpoint)
{
CORE_ADDR addr;
value_ptr v;
continue;
for (v = b->val_chain; v; v = v->next)
{
- if (v->lval == lval_memory)
+ if (VALUE_LVAL (v) == lval_memory
+ && ! VALUE_LAZY (v))
{
- CORE_ADDR vaddr;
+ struct type *vtype = check_typedef (VALUE_TYPE (v));
- vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
- if (addr == vaddr)
- found = 1;
+ if (v == b->val_chain
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ {
+ CORE_ADDR vaddr;
+
+ vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ /* Exact match not required. Within range is
+ sufficient. */
+ if (addr >= vaddr &&
+ addr < vaddr + TYPE_LENGTH (VALUE_TYPE (v)))
+ found = 1;
+ }
}
}
if (found)
- switch (catch_errors (watchpoint_check, bs, message, RETURN_MASK_ALL))
+ switch (catch_errors (watchpoint_check, bs, message,
+ RETURN_MASK_ALL))
{
case WP_DELETED:
/* We've already printed what needs to be printed. */
/* Stop. */
break;
case WP_VALUE_CHANGED:
+ if (b->type == bp_read_watchpoint)
+ {
+ /* Don't stop: read watchpoints shouldn't fire if
+ the value has changed. This is for targets which
+ cannot set read-only watchpoints. */
+ bs->print_it = print_it_noop;
+ bs->stop = 0;
+ continue;
+ }
+ ++(b->hit_count);
+ break;
case WP_VALUE_NOT_CHANGED:
/* Stop. */
++(b->hit_count);
bs->print_it = print_it_done;
break;
}
+ else /* found == 0 */
+ {
+ /* This is a case where some watchpoint(s) triggered,
+ but not at the address of this watchpoint (FOUND
+ was left zero). So don't print anything for this
+ watchpoint. */
+ bs->print_it = print_it_noop;
+ bs->stop = 0;
+ continue;
+ }
}
else
{
real_breakpoint = 1;
}
- if (b->frame && b->frame != (get_current_frame ())->frame &&
- (b->type == bp_step_resume &&
- (INNER_THAN (get_current_frame ()->frame, b->frame))))
+ if (b->frame &&
+ b->frame != (get_current_frame ())->frame)
bs->stop = 0;
else
{
else if (b->ignore_count > 0)
{
b->ignore_count--;
+ annotate_ignore_count_change ();
bs->stop = 0;
}
else
as bp_silent and wp_noisy is the same as bp_noisy. That is because
after stopping, the check for whether to step over a breakpoint
(BPSTAT_WHAT_SINGLE type stuff) is handled in proceed() without
- reference to how we stopped. We retain separate wp_silent and bp_silent
- codes in case we want to change that someday.
+ reference to how we stopped. We retain separate wp_silent and
+ bp_silent codes in case we want to change that someday.
Another possibly interesting property of this table is that
there's a partial ordering, priority-like, of the actions. Once
bs_class = wp_silent;
}
else
- /* There was a watchpoint, but we're not stopping. This requires
- no further action. */
+ /* There was a watchpoint, but we're not stopping.
+ This requires no further action. */
bs_class = no_effect;
break;
case bp_longjmp:
case bp_shlib_event:
bs_class = shlib_event;
break;
+ case bp_thread_event:
+ bs_class = bp_nostop;
+ break;
case bp_catch_load:
case bp_catch_unload:
/* Only if this catchpoint triggered should we cause the
bs_class = bp_silent;
}
else
- /* There was a catchpoint, but we're not stopping. This requires
- no further action. */
+ /* There was a catchpoint, but we're not stopping.
+ This requires no further action. */
bs_class = no_effect;
break;
case bp_catch_catch:
bs_class = bs->print ? bp_noisy : bp_silent;
break;
case bp_call_dummy:
- /* Make sure the action is stop (silent or noisy), so infrun.c
- pops the dummy frame. */
+ /* Make sure the action is stop (silent or noisy),
+ so infrun.c pops the dummy frame. */
bs_class = bp_silent;
retval.call_dummy = 1;
break;
if ((ep->type != bp_catch_load) &&
(ep->type != bp_catch_unload) &&
(ep->type != bp_catch_catch) &&
- (ep->type != bp_catch_throw)) /* pai: (temp) ADD fork/vfork here!! */
+ (ep->type != bp_catch_throw))
+ /* pai: (temp) ADD fork/vfork here!! */
continue;
/* Yes; add it to the list. */
#endif
if (dll_pathname)
{
- ep->triggered_dll_pathname = (char *) xmalloc (strlen (dll_pathname) + 1);
+ ep->triggered_dll_pathname = (char *)
+ xmalloc (strlen (dll_pathname) + 1);
strcpy (ep->triggered_dll_pathname, dll_pathname);
}
else
*cp_list = bs;
}
-/* Print information on breakpoint number BNUM, or -1 if all.
- If WATCHPOINTS is zero, process only breakpoints; if WATCHPOINTS
- is nonzero, process only watchpoints. */
-
-typedef struct
-{
- enum bptype type;
- char *description;
-}
-ep_type_description_t;
-
+/* Print B to gdb_stdout. */
static void
-breakpoint_1 (bnum, allflag)
- int bnum;
- int allflag;
+print_one_breakpoint (struct breakpoint *b,
+ CORE_ADDR *last_addr)
{
- register struct breakpoint *b;
register struct command_line *l;
register struct symbol *sym;
- CORE_ADDR last_addr = (CORE_ADDR) - 1;
- int found_a_breakpoint = 0;
- static ep_type_description_t bptypes[] =
+ struct ep_type_description
+ {
+ enum bptype type;
+ char *description;
+ };
+ static struct ep_type_description bptypes[] =
{
{bp_none, "?deleted?"},
{bp_breakpoint, "breakpoint"},
{bp_watchpoint_scope, "watchpoint scope"},
{bp_call_dummy, "call dummy"},
{bp_shlib_event, "shlib events"},
+ {bp_thread_event, "thread events"},
{bp_catch_load, "catch load"},
{bp_catch_unload, "catch unload"},
{bp_catch_fork, "catch fork"},
{bp_catch_catch, "catch catch"},
{bp_catch_throw, "catch throw"}
};
-
+
static char *bpdisps[] =
{"del", "dstp", "dis", "keep"};
- static char bpenables[] = "nyn";
+ static char bpenables[] = "nynny";
char wrap_indent[80];
+#ifdef UI_OUT
+ struct ui_stream *stb = ui_out_stream_new (uiout);
+ struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
+#endif
+ annotate_record ();
+#ifdef UI_OUT
+ ui_out_list_begin (uiout, "bkpt");
+#endif
- ALL_BREAKPOINTS (b)
- if (bnum == -1
- || bnum == b->number)
+ /* 1 */
+ annotate_field (0);
+#ifdef UI_OUT
+ ui_out_field_int (uiout, "number", b->number);
+#else
+ printf_filtered ("%-3d ", b->number);
+#endif
+
+ /* 2 */
+ annotate_field (1);
+ if (((int) b->type > (sizeof (bptypes) / sizeof (bptypes[0])))
+ || ((int) b->type != bptypes[(int) b->type].type))
+ internal_error ("bptypes table does not describe type #%d.",
+ (int) b->type);
+#ifdef UI_OUT
+ ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
+#else
+ printf_filtered ("%-14s ", bptypes[(int) b->type].description);
+#endif
+
+ /* 3 */
+ annotate_field (2);
+#ifdef UI_OUT
+ ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
+#else
+ printf_filtered ("%-4s ", bpdisps[(int) b->disposition]);
+#endif
+
+ /* 4 */
+ annotate_field (3);
+#ifdef UI_OUT
+ ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int) b->enable]);
+ ui_out_spaces (uiout, 2);
+#else
+ printf_filtered ("%-3c ", bpenables[(int) b->enable]);
+#endif
+
+ /* 5 and 6 */
+ strcpy (wrap_indent, " ");
+ if (addressprint)
+ strcat (wrap_indent, " ");
+ switch (b->type)
{
-/* We only print out user settable breakpoints unless the allflag is set. */
- if (!allflag
- && b->type != bp_breakpoint
- && b->type != bp_catch_load
- && b->type != bp_catch_unload
- && b->type != bp_catch_fork
- && b->type != bp_catch_vfork
- && b->type != bp_catch_exec
- && b->type != bp_catch_catch
- && b->type != bp_catch_throw
- && b->type != bp_hardware_breakpoint
- && b->type != bp_watchpoint
- && b->type != bp_read_watchpoint
- && b->type != bp_access_watchpoint
- && b->type != bp_hardware_watchpoint)
- continue;
+ case bp_none:
+ internal_error ("print_one_breakpoint: bp_none encountered\n");
+ break;
- if (!found_a_breakpoint++)
+ case bp_watchpoint:
+ case bp_hardware_watchpoint:
+ case bp_read_watchpoint:
+ case bp_access_watchpoint:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+#ifdef UI_OUT
+ if (addressprint)
+ ui_out_field_skip (uiout, "addr");
+ annotate_field (5);
+ print_expression (b->exp, stb->stream);
+ ui_out_field_stream (uiout, "what", stb);
+#else
+ annotate_field (5);
+ print_expression (b->exp, gdb_stdout);
+#endif
+ break;
+
+ case bp_catch_load:
+ case bp_catch_unload:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+#ifdef UI_OUT
+ if (addressprint)
+ ui_out_field_skip (uiout, "addr");
+ annotate_field (5);
+ if (b->dll_pathname == NULL)
{
- annotate_breakpoints_headers ();
-
- annotate_field (0);
- printf_filtered ("Num ");
- annotate_field (1);
- printf_filtered ("Type ");
- annotate_field (2);
- printf_filtered ("Disp ");
- annotate_field (3);
- printf_filtered ("Enb ");
- if (addressprint)
- {
- annotate_field (4);
- printf_filtered ("Address ");
- }
- annotate_field (5);
- printf_filtered ("What\n");
-
- annotate_breakpoints_table ();
+ ui_out_field_string (uiout, "what", "<any library>");
+ ui_out_spaces (uiout, 1);
}
-
- annotate_record ();
- annotate_field (0);
- printf_filtered ("%-3d ", b->number);
- annotate_field (1);
- if ((int) b->type > (sizeof (bptypes) / sizeof (bptypes[0])))
- error ("bptypes table does not describe type #%d.", (int) b->type);
- if ((int) b->type != bptypes[(int) b->type].type)
- error ("bptypes table does not describe type #%d?", (int) b->type);
- printf_filtered ("%-14s ", bptypes[(int) b->type].description);
- annotate_field (2);
- printf_filtered ("%-4s ", bpdisps[(int) b->disposition]);
- annotate_field (3);
- printf_filtered ("%-3c ", bpenables[(int) b->enable]);
-
- strcpy (wrap_indent, " ");
+ else
+ {
+ ui_out_text (uiout, "library \"");
+ ui_out_field_string (uiout, "what", b->dll_pathname);
+ ui_out_text (uiout, "\" ");
+ }
+#else
+ annotate_field (5);
+ if (b->dll_pathname == NULL)
+ printf_filtered ("<any library> ");
+ else
+ printf_filtered ("library \"%s\" ", b->dll_pathname);
+#endif
+ break;
+
+ case bp_catch_fork:
+ case bp_catch_vfork:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+#ifdef UI_OUT
if (addressprint)
- strcat (wrap_indent, " ");
- switch (b->type)
+ ui_out_field_skip (uiout, "addr");
+ annotate_field (5);
+ if (b->forked_inferior_pid != 0)
{
- case bp_watchpoint:
- case bp_hardware_watchpoint:
- case bp_read_watchpoint:
- case bp_access_watchpoint:
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- annotate_field (5);
- print_expression (b->exp, gdb_stdout);
- break;
-
- case bp_catch_load:
- case bp_catch_unload:
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- annotate_field (5);
- if (b->dll_pathname == NULL)
- printf_filtered ("<any library> ");
- else
- printf_filtered ("library \"%s\" ", b->dll_pathname);
- break;
-
- case bp_catch_fork:
- case bp_catch_vfork:
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- annotate_field (5);
- if (b->forked_inferior_pid != 0)
- printf_filtered ("process %d ", b->forked_inferior_pid);
- break;
-
- case bp_catch_exec:
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- annotate_field (5);
- if (b->exec_pathname != NULL)
- printf_filtered ("program \"%s\" ", b->exec_pathname);
- break;
- case bp_catch_catch:
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- annotate_field (5);
- printf_filtered ("exception catch ");
- break;
- case bp_catch_throw:
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- annotate_field (5);
- printf_filtered ("exception throw ");
- break;
-
- case bp_breakpoint:
- case bp_hardware_breakpoint:
- case bp_until:
- case bp_finish:
- case bp_longjmp:
- case bp_longjmp_resume:
- case bp_step_resume:
- case bp_through_sigtramp:
- case bp_watchpoint_scope:
- case bp_call_dummy:
- case bp_shlib_event:
- if (addressprint)
- {
- annotate_field (4);
- /* FIXME-32x64: need a print_address_numeric with
- field width */
- printf_filtered
- ("%s ",
- local_hex_string_custom
- ((unsigned long) b->address, "08l"));
- }
+ ui_out_text (uiout, "process ");
+ ui_out_field_int (uiout, "what", b->forked_inferior_pid);
+ ui_out_spaces (uiout, 1);
+ }
+#else
+ annotate_field (5);
+ if (b->forked_inferior_pid != 0)
+ printf_filtered ("process %d ", b->forked_inferior_pid);
+ break;
+#endif
+
+ case bp_catch_exec:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+#ifdef UI_OUT
+ if (addressprint)
+ ui_out_field_skip (uiout, "addr");
+ annotate_field (5);
+ if (b->exec_pathname != NULL)
+ {
+ ui_out_text (uiout, "program \"");
+ ui_out_field_string (uiout, "what", b->exec_pathname);
+ ui_out_text (uiout, "\" ");
+ }
+#else
+ annotate_field (5);
+ if (b->exec_pathname != NULL)
+ printf_filtered ("program \"%s\" ", b->exec_pathname);
+#endif
+ break;
- annotate_field (5);
+ case bp_catch_catch:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+#ifdef UI_OUT
+ if (addressprint)
+ ui_out_field_skip (uiout, "addr");
+ annotate_field (5);
+ ui_out_field_string (uiout, "what", "exception catch");
+ ui_out_spaces (uiout, 1);
+#else
+ annotate_field (5);
+ printf_filtered ("exception catch ");
+#endif
+ break;
- last_addr = b->address;
- if (b->source_file)
+ case bp_catch_throw:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+#ifdef UI_OUT
+ if (addressprint)
+ ui_out_field_skip (uiout, "addr");
+ annotate_field (5);
+ ui_out_field_string (uiout, "what", "exception throw");
+ ui_out_spaces (uiout, 1);
+#else
+ annotate_field (5);
+ printf_filtered ("exception throw ");
+#endif
+ break;
+
+ case bp_breakpoint:
+ case bp_hardware_breakpoint:
+ case bp_until:
+ case bp_finish:
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ case bp_step_resume:
+ case bp_through_sigtramp:
+ case bp_watchpoint_scope:
+ case bp_call_dummy:
+ case bp_shlib_event:
+ case bp_thread_event:
+#ifdef UI_OUT
+ if (addressprint)
+ {
+ annotate_field (4);
+ ui_out_field_core_addr (uiout, "addr", b->address);
+ }
+ annotate_field (5);
+ *last_addr = b->address;
+ if (b->source_file)
+ {
+ sym = find_pc_sect_function (b->address, b->section);
+ if (sym)
{
- sym = find_pc_sect_function (b->address, b->section);
- if (sym)
- {
- fputs_filtered ("in ", gdb_stdout);
- fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
- wrap_here (wrap_indent);
- fputs_filtered (" at ", gdb_stdout);
- }
- fputs_filtered (b->source_file, gdb_stdout);
- printf_filtered (":%d", b->line_number);
+ ui_out_text (uiout, "in ");
+ ui_out_field_string (uiout, "func",
+ SYMBOL_SOURCE_NAME (sym));
+ ui_out_wrap_hint (uiout, wrap_indent);
+ ui_out_text (uiout, " at ");
}
- else
- print_address_symbolic (b->address, gdb_stdout, demangle, " ");
- break;
+ ui_out_field_string (uiout, "file", b->source_file);
+ ui_out_text (uiout, ":");
+ ui_out_field_int (uiout, "line", b->line_number);
}
-
- if (b->thread != -1)
- printf_filtered (" thread %d", b->thread);
-
- printf_filtered ("\n");
-
- if (b->frame)
+ else
{
- annotate_field (6);
-
- printf_filtered ("\tstop only in stack frame at ");
- print_address_numeric (b->frame, 1, gdb_stdout);
- printf_filtered ("\n");
+ print_address_symbolic (b->address, stb->stream, demangle, "");
+ ui_out_field_stream (uiout, "at", stb);
}
-
- if (b->cond)
+#else
+ if (addressprint)
{
- annotate_field (7);
-
- printf_filtered ("\tstop only if ");
- print_expression (b->cond, gdb_stdout);
- printf_filtered ("\n");
+ annotate_field (4);
+ /* FIXME-32x64: need a print_address_numeric with
+ field width */
+ printf_filtered
+ ("%s ",
+ local_hex_string_custom
+ ((unsigned long) b->address, "08l"));
}
-
- if (b->thread != -1)
+ annotate_field (5);
+ *last_addr = b->address;
+ if (b->source_file)
{
- /* FIXME should make an annotation for this */
- printf_filtered ("\tstop only in thread %d\n", b->thread);
+ sym = find_pc_sect_function (b->address, b->section);
+ if (sym)
+ {
+ fputs_filtered ("in ", gdb_stdout);
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
+ wrap_here (wrap_indent);
+ fputs_filtered (" at ", gdb_stdout);
+ }
+ fputs_filtered (b->source_file, gdb_stdout);
+ printf_filtered (":%d", b->line_number);
}
+ else
+ print_address_symbolic (b->address, gdb_stdout, demangle, " ");
+#endif
+ break;
+ }
+
+ if (b->thread != -1)
+ {
+#ifdef UI_OUT
+ /* FIXME: This seems to be redundant and lost here; see the
+ "stop only in" line a little further down. */
+ ui_out_text (uiout, " thread ");
+ ui_out_field_int (uiout, "thread", b->thread);
+#else
+ printf_filtered (" thread %d", b->thread);
+#endif
+ }
+
+#ifdef UI_OUT
+ ui_out_text (uiout, "\n");
+#else
+ printf_filtered ("\n");
+#endif
+
+ if (b->frame)
+ {
+ annotate_field (6);
+#ifdef UI_OUT
+ ui_out_text (uiout, "\tstop only in stack frame at ");
+ ui_out_field_core_addr (uiout, "frame", b->frame);
+ ui_out_text (uiout, "\n");
+#else
+ printf_filtered ("\tstop only in stack frame at ");
+ print_address_numeric (b->frame, 1, gdb_stdout);
+ printf_filtered ("\n");
+#endif
+ }
+
+ if (b->cond)
+ {
+ annotate_field (7);
+#ifdef UI_OUT
+ ui_out_text (uiout, "\tstop only if ");
+ print_expression (b->cond, stb->stream);
+ ui_out_field_stream (uiout, "cond", stb);
+ ui_out_text (uiout, "\n");
+#else
+ printf_filtered ("\tstop only if ");
+ print_expression (b->cond, gdb_stdout);
+ printf_filtered ("\n");
+#endif
+ }
+
+ if (b->thread != -1)
+ {
+ /* FIXME should make an annotation for this */
+#ifdef UI_OUT
+ ui_out_text (uiout, "\tstop only in thread ");
+ ui_out_field_int (uiout, "thread", b->thread);
+ ui_out_text (uiout, "\n");
+#else
+ printf_filtered ("\tstop only in thread %d\n", b->thread);
+#endif
+ }
+
+ if (show_breakpoint_hit_counts && b->hit_count)
+ {
+ /* FIXME should make an annotation for this */
+#ifdef UI_OUT
+ if (ep_is_catchpoint (b))
+ ui_out_text (uiout, "\tcatchpoint");
+ else
+ ui_out_text (uiout, "\tbreakpoint");
+ ui_out_text (uiout, " already hit ");
+ ui_out_field_int (uiout, "times", b->hit_count);
+ if (b->hit_count == 1)
+ ui_out_text (uiout, " time\n");
+ else
+ ui_out_text (uiout, " times\n");
+#else
+ if (ep_is_catchpoint (b))
+ printf_filtered ("\tcatchpoint");
+ else
+ printf_filtered ("\tbreakpoint");
+ printf_filtered (" already hit %d time%s\n",
+ b->hit_count, (b->hit_count == 1 ? "" : "s"));
+#endif
+ }
+
+#ifdef UI_OUT
+ /* Output the count also if it is zero, but only if this is
+ mi. FIXME: Should have a better test for this. */
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ if (show_breakpoint_hit_counts && b->hit_count == 0)
+ ui_out_field_int (uiout, "times", b->hit_count);
+#endif
- if (show_breakpoint_hit_counts && b->hit_count)
+ if (b->ignore_count)
+ {
+ annotate_field (8);
+#ifdef UI_OUT
+ ui_out_text (uiout, "\tignore next ");
+ ui_out_field_int (uiout, "ignore", b->ignore_count);
+ ui_out_text (uiout, " hits\n");
+#else
+ printf_filtered ("\tignore next %d hits\n", b->ignore_count);
+#endif
+ }
+
+ if ((l = b->commands))
+ {
+ annotate_field (9);
+#ifdef UI_OUT
+ ui_out_list_begin (uiout, "script");
+ print_command_lines (uiout, l, 4);
+ ui_out_list_end (uiout);
+#else
+ while (l)
{
- /* FIXME should make an annotation for this */
- if (ep_is_catchpoint (b))
- printf_filtered ("\tcatchpoint");
- else
- printf_filtered ("\tbreakpoint");
- printf_filtered (" already hit %d time%s\n",
- b->hit_count, (b->hit_count == 1 ? "" : "s"));
+ print_command_line (l, 4, gdb_stdout);
+ l = l->next;
}
+#endif
+ }
+#ifdef UI_OUT
+ ui_out_list_end (uiout);
+ do_cleanups (old_chain);
+#endif
+}
- if (b->ignore_count)
- {
- annotate_field (8);
-
- printf_filtered ("\tignore next %d hits\n", b->ignore_count);
- }
+struct captured_breakpoint_query_args
+ {
+ int bnum;
+ };
- if ((l = b->commands))
+static int
+do_captured_breakpoint_query (void *data)
+{
+ struct captured_breakpoint_query_args *args = data;
+ register struct breakpoint *b;
+ CORE_ADDR dummy_addr = 0;
+ ALL_BREAKPOINTS (b)
+ {
+ if (args->bnum == b->number)
{
- annotate_field (9);
-
- while (l)
- {
- print_command_line (l, 4, gdb_stdout);
- l = l->next;
- }
+ print_one_breakpoint (b, &dummy_addr);
+ return GDB_RC_OK;
}
}
+ return GDB_RC_NONE;
+}
+
+enum gdb_rc
+gdb_breakpoint_query (/* output object, */ int bnum)
+{
+ struct captured_breakpoint_query_args args;
+ args.bnum = bnum;
+ /* For the moment we don't trust print_one_breakpoint() to not throw
+ an error. */
+ return catch_errors (do_captured_breakpoint_query, &args,
+ NULL, RETURN_MASK_ALL);
+}
+
+/* Print information on breakpoint number BNUM, or -1 if all.
+ If WATCHPOINTS is zero, process only breakpoints; if WATCHPOINTS
+ is nonzero, process only watchpoints. */
+
+static void
+breakpoint_1 (bnum, allflag)
+ int bnum;
+ int allflag;
+{
+ register struct breakpoint *b;
+ CORE_ADDR last_addr = (CORE_ADDR) -1;
+ int found_a_breakpoint = 0;
+
+#ifdef UI_OUT
+ if (addressprint)
+ ui_out_table_begin (uiout, 6, "BreakpointTable");
+ else
+ ui_out_table_begin (uiout, 5, "BreakpointTable");
+#endif /* UI_OUT */
+ ALL_BREAKPOINTS (b)
+ if (bnum == -1
+ || bnum == b->number)
+ {
+ /* We only print out user settable breakpoints unless the
+ allflag is set. */
+ if (!allflag
+ && b->type != bp_breakpoint
+ && b->type != bp_catch_load
+ && b->type != bp_catch_unload
+ && b->type != bp_catch_fork
+ && b->type != bp_catch_vfork
+ && b->type != bp_catch_exec
+ && b->type != bp_catch_catch
+ && b->type != bp_catch_throw
+ && b->type != bp_hardware_breakpoint
+ && b->type != bp_watchpoint
+ && b->type != bp_read_watchpoint
+ && b->type != bp_access_watchpoint
+ && b->type != bp_hardware_watchpoint)
+ continue;
+
+ if (!found_a_breakpoint++)
+ {
+ annotate_breakpoints_headers ();
+#ifdef UI_OUT
+ annotate_field (0);
+ ui_out_table_header (uiout, 3, ui_left, "Num"); /* 1 */
+ annotate_field (1);
+ ui_out_table_header (uiout, 14, ui_left, "Type"); /* 2 */
+ annotate_field (2);
+ ui_out_table_header (uiout, 4, ui_left, "Disp"); /* 3 */
+ annotate_field (3);
+ ui_out_table_header (uiout, 3, ui_left, "Enb"); /* 4 */
+ if (addressprint)
+ {
+ annotate_field (4);
+ ui_out_table_header (uiout, 10, ui_left, "Address"); /* 5 */
+ }
+ annotate_field (5);
+ ui_out_table_header (uiout, 40, ui_noalign, "What"); /* 6 */
+ ui_out_table_body (uiout);
+#else
+ annotate_field (0);
+ printf_filtered ("Num ");
+ annotate_field (1);
+ printf_filtered ("Type ");
+ annotate_field (2);
+ printf_filtered ("Disp ");
+ annotate_field (3);
+ printf_filtered ("Enb ");
+ if (addressprint)
+ {
+ annotate_field (4);
+ printf_filtered ("Address ");
+ }
+ annotate_field (5);
+ printf_filtered ("What\n");
+#endif /* UI_OUT */
+ annotate_breakpoints_table ();
+ }
+
+ print_one_breakpoint (b, &last_addr);
+ }
+
if (!found_a_breakpoint)
{
+#ifdef UI_OUT
+ if (bnum == -1)
+ ui_out_message (uiout, 0, "No breakpoints or watchpoints.\n");
+ else
+ ui_out_message (uiout, 0, "No breakpoint or watchpoint number %d.\n",
+ bnum);
+#else
if (bnum == -1)
printf_filtered ("No breakpoints or watchpoints.\n");
else
printf_filtered ("No breakpoint or watchpoint number %d.\n", bnum);
+#endif /* UI_OUT */
}
else
- /* Compare against (CORE_ADDR)-1 in case some compiler decides
- that a comparison of an unsigned with -1 is always false. */
- if (last_addr != (CORE_ADDR) - 1)
- set_next_address (last_addr);
+ {
+ /* Compare against (CORE_ADDR)-1 in case some compiler decides
+ that a comparison of an unsigned with -1 is always false. */
+ if (last_addr != (CORE_ADDR) -1)
+ set_next_address (last_addr);
+ }
+#ifdef UI_OUT
+ ui_out_table_end (uiout);
+#endif /* UI_OUT */
+ /* FIXME? Should this be moved up so that it is only called when
+ there have been breakpoints? */
annotate_breakpoints_table_end ();
}
printf_filtered
("%d%s%s ",
b->number,
- ((b->enable == disabled || b->enable == shlib_disabled || b->enable == call_disabled)
- ? " (disabled)" : ""),
+ ((b->enable == disabled ||
+ b->enable == shlib_disabled ||
+ b->enable == call_disabled) ? " (disabled)"
+ : b->enable == permanent ? " (permanent)"
+ : ""),
(others > 1) ? "," : ((others == 1) ? " and" : ""));
}
printf_filtered ("also set at pc ");
/* Rescan breakpoints at address ADDRESS,
marking the first one as "first" and any others as "duplicates".
- This is so that the bpt instruction is only inserted once. */
+ This is so that the bpt instruction is only inserted once.
+ If we have a permanent breakpoint at ADDRESS, make that one
+ the official one, and the rest as duplicates. */
static void
check_duplicates (address, section)
{
register struct breakpoint *b;
register int count = 0;
+ struct breakpoint *perm_bp = 0;
if (address == 0) /* Watchpoints are uninteresting */
return;
&& b->address == address
&& (overlay_debugging == 0 || b->section == section))
{
+ /* Have we found a permanent breakpoint? */
+ if (b->enable == permanent)
+ {
+ perm_bp = b;
+ break;
+ }
+
count++;
b->duplicate = count > 1;
}
+
+ /* If we found a permanent breakpoint at this address, go over the
+ list again and declare all the other breakpoints there to be the
+ duplicates. */
+ if (perm_bp)
+ {
+ perm_bp->duplicate = 0;
+
+ /* Permanent breakpoint should always be inserted. */
+ if (! perm_bp->inserted)
+ internal_error ("allegedly permanent breakpoint is not "
+ "actually inserted");
+
+ ALL_BREAKPOINTS (b)
+ if (b != perm_bp)
+ {
+ if (b->inserted)
+ internal_error ("another breakpoint was inserted on top of "
+ "a permanent breakpoint");
+
+ if (b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->enable != call_disabled
+ && b->address == address
+ && (overlay_debugging == 0 || b->section == section))
+ b->duplicate = 1;
+ }
+ }
}
/* Low level routine to set a breakpoint.
return b;
}
+
+/* Note that the breakpoint object B describes a permanent breakpoint
+ instruction, hard-wired into the inferior's code. */
+void
+make_breakpoint_permanent (struct breakpoint *b)
+{
+ b->enable = permanent;
+
+ /* By definition, permanent breakpoints are already present in the code. */
+ b->inserted = 1;
+}
+
#ifdef GET_LONGJMP_TARGET
static void
{
struct minimal_symbol *m;
- m = lookup_minimal_symbol_text (func_name, NULL, (struct objfile *) NULL);
+ m = lookup_minimal_symbol_text (func_name, NULL,
+ (struct objfile *) NULL);
if (m)
sal.pc = SYMBOL_VALUE_ADDRESS (m);
else
#endif /* #ifdef GET_LONGJMP_TARGET */
-/* Call this routine when stepping and nexting to enable a breakpoint if we do
- a longjmp(). When we hit that breakpoint, call
+/* Call this routine when stepping and nexting to enable a breakpoint
+ if we do a longjmp(). When we hit that breakpoint, call
set_longjmp_resume_breakpoint() to figure out where we are going. */
void
}
}
+struct breakpoint *
+create_thread_event_breakpoint (address)
+ CORE_ADDR address;
+{
+ struct breakpoint *b;
+ struct symtab_and_line sal;
+ char addr_string[80]; /* Surely an addr can't be longer than that. */
+
+ INIT_SAL (&sal); /* initialize to zeroes */
+ sal.pc = address;
+ sal.section = find_pc_overlay (sal.pc);
+ if ((b = set_raw_breakpoint (sal)) == NULL)
+ return NULL;
+
+ b->number = internal_breakpoint_number--;
+ b->disposition = donttouch;
+ b->type = bp_thread_event; /* XXX: do we need a new type?
+ bp_thread_event */
+ b->enable = enabled;
+ /* addr_string has to be used or breakpoint_re_set will delete me. */
+ sprintf (addr_string, "*0x%s", paddr (b->address));
+ b->addr_string = strsave (addr_string);
+
+ return b;
+}
+
+void
+remove_thread_event_breakpoints (void)
+{
+ struct breakpoint *b, *temp;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ if (b->type == bp_thread_event)
+ delete_breakpoint (b);
+}
+
#ifdef SOLIB_ADD
void
remove_solib_event_breakpoints ()
delete_breakpoint (b);
}
-void
+struct breakpoint *
create_solib_event_breakpoint (address)
CORE_ADDR address;
{
b->number = internal_breakpoint_number--;
b->disposition = donttouch;
b->type = bp_shlib_event;
+
+ return b;
}
+/* Disable any breakpoints that are on code in shared libraries. Only
+ apply to enabled breakpoints, disabled ones can just stay disabled. */
+
void
disable_breakpoints_in_shlibs (silent)
int silent;
#if defined (PC_SOLIB)
if (((b->type == bp_breakpoint) ||
(b->type == bp_hardware_breakpoint)) &&
- (b->enable != shlib_disabled) &&
- (b->enable != call_disabled) &&
+ b->enable == enabled &&
!b->duplicate &&
PC_SOLIB (b->address))
{
if (!disabled_shlib_breaks)
{
target_terminal_ours_for_output ();
- printf_filtered ("Temporarily disabling shared library breakpoints:\n");
+ warning ("Temporarily disabling shared library breakpoints:");
}
disabled_shlib_breaks = 1;
- printf_filtered ("%d ", b->number);
+ warning ("breakpoint #%d ", b->number);
}
}
#endif
}
- if (disabled_shlib_breaks && !silent)
- printf_filtered ("\n");
}
/* Try to reenable any breakpoints in shared libraries. */
#endif
static void
-create_solib_load_unload_event_breakpoint (hookname, tempflag, dll_pathname, cond_string, bp_kind)
+solib_load_unload_1 (hookname, tempflag, dll_pathname, cond_string, bp_kind)
char *hookname;
int tempflag;
char *dll_pathname;
{
struct breakpoint *b;
struct symtabs_and_lines sals;
- struct symtab_and_line sal;
struct cleanup *old_chain;
struct cleanup *canonical_strings_chain = NULL;
- int i;
char *addr_start = hookname;
char *addr_end = NULL;
char **canonical = (char **) NULL;
}
if (sals.nelts != 1)
{
- warning ("Unable to set a unique breakpoint on dynamic linker callback.");
+ warning ("Unable to set unique breakpoint on dynamic linker callback.");
warning ("GDB will be unable to track shl_load/shl_unload calls");
return;
}
- /* Make sure that all storage allocated in decode_line_1 gets freed in case
- the following errors out. */
+ /* Make sure that all storage allocated in decode_line_1 gets freed
+ in case the following errors out. */
old_chain = make_cleanup (free, sals.sals);
if (canonical != (char **) NULL)
{
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
b->cond = NULL;
- b->cond_string = (cond_string == NULL) ? NULL : savestring (cond_string, strlen (cond_string));
+ b->cond_string = (cond_string == NULL) ?
+ NULL : savestring (cond_string, strlen (cond_string));
b->thread = thread;
if (canonical != (char **) NULL && canonical[0] != NULL)
}
void
-create_solib_load_event_breakpoint (hookname, tempflag, dll_pathname, cond_string)
+create_solib_load_event_breakpoint (hookname, tempflag,
+ dll_pathname, cond_string)
char *hookname;
int tempflag;
char *dll_pathname;
char *cond_string;
{
- create_solib_load_unload_event_breakpoint (hookname,
- tempflag,
- dll_pathname,
- cond_string,
- bp_catch_load);
+ solib_load_unload_1 (hookname, tempflag, dll_pathname,
+ cond_string, bp_catch_load);
}
void
-create_solib_unload_event_breakpoint (hookname, tempflag, dll_pathname, cond_string)
+create_solib_unload_event_breakpoint (hookname, tempflag,
+ dll_pathname, cond_string)
char *hookname;
int tempflag;
char *dll_pathname;
char *cond_string;
{
- create_solib_load_unload_event_breakpoint (hookname,
- tempflag,
- dll_pathname,
- cond_string,
- bp_catch_unload);
+ solib_load_unload_1 (hookname,tempflag, dll_pathname,
+ cond_string, bp_catch_unload);
}
static void
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
b->cond = NULL;
- b->cond_string = (cond_string == NULL) ? NULL : savestring (cond_string, strlen (cond_string));
+ b->cond_string = (cond_string == NULL) ?
+ NULL : savestring (cond_string, strlen (cond_string));
b->thread = thread;
b->addr_string = NULL;
b->enable = enabled;
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
b->cond = NULL;
- b->cond_string = (cond_string == NULL) ? NULL : savestring (cond_string, strlen (cond_string));
+ b->cond_string = (cond_string == NULL) ?
+ NULL : savestring (cond_string, strlen (cond_string));
b->thread = thread;
b->addr_string = NULL;
b->enable = enabled;
return i;
}
-/* Call this after hitting the longjmp() breakpoint. Use this to set a new
- breakpoint at the target of the jmp_buf.
+/* Call this after hitting the longjmp() breakpoint. Use this to set
+ a new breakpoint at the target of the jmp_buf.
- FIXME - This ought to be done by setting a temporary breakpoint that gets
- deleted automatically... */
+ FIXME - This ought to be done by setting a temporary breakpoint
+ that gets deleted automatically... */
void
set_longjmp_resume_breakpoint (pc, frame)
struct breakpoint *b;
{
int say_where = 0;
+#ifdef UI_OUT
+ struct cleanup *old_chain;
+ struct ui_stream *stb;
+
+ stb = ui_out_stream_new (uiout);
+ old_chain = make_cleanup_ui_out_stream_delete (stb);
+#endif /* UI_OUT */
/* FIXME: This is misplaced; mention() is called by things (like hitting a
watchpoint) other than breakpoint creation. It should be possible to
delete_breakpoint_hook and so on. */
if (create_breakpoint_hook)
create_breakpoint_hook (b);
+ breakpoint_create_event (b->number);
switch (b->type)
{
case bp_none:
printf_filtered ("(apparently deleted?) Eventpoint %d: ", b->number);
break;
+#ifdef UI_OUT
+ case bp_watchpoint:
+ ui_out_text (uiout, "Watchpoint ");
+ ui_out_list_begin (uiout, "wpt");
+ ui_out_field_int (uiout, "number", b->number);
+ ui_out_text (uiout, ": ");
+ print_expression (b->exp, stb->stream);
+ ui_out_field_stream (uiout, "exp", stb);
+ ui_out_list_end (uiout);
+ break;
+ case bp_hardware_watchpoint:
+ ui_out_text (uiout, "Hardware watchpoint ");
+ ui_out_list_begin (uiout, "wpt");
+ ui_out_field_int (uiout, "number", b->number);
+ ui_out_text (uiout, ": ");
+ print_expression (b->exp, stb->stream);
+ ui_out_field_stream (uiout, "exp", stb);
+ ui_out_list_end (uiout);
+ break;
+#else
case bp_watchpoint:
printf_filtered ("Watchpoint %d: ", b->number);
print_expression (b->exp, gdb_stdout);
printf_filtered ("Hardware watchpoint %d: ", b->number);
print_expression (b->exp, gdb_stdout);
break;
+#endif
+#ifdef UI_OUT
+ case bp_read_watchpoint:
+ ui_out_text (uiout, "Hardware read watchpoint ");
+ ui_out_list_begin (uiout, "hw-rwpt");
+ ui_out_field_int (uiout, "number", b->number);
+ ui_out_text (uiout, ": ");
+ print_expression (b->exp, stb->stream);
+ ui_out_field_stream (uiout, "exp", stb);
+ ui_out_list_end (uiout);
+ break;
+ case bp_access_watchpoint:
+ ui_out_text (uiout, "Hardware access (read/write) watchpoint ");
+ ui_out_list_begin (uiout, "hw-awpt");
+ ui_out_field_int (uiout, "number", b->number);
+ ui_out_text (uiout, ": ");
+ print_expression (b->exp, stb->stream);
+ ui_out_field_stream (uiout, "exp", stb);
+ ui_out_list_end (uiout);
+ break;
+#else
case bp_read_watchpoint:
printf_filtered ("Hardware read watchpoint %d: ", b->number);
print_expression (b->exp, gdb_stdout);
break;
case bp_access_watchpoint:
- printf_filtered ("Hardware access (read/write) watchpoint %d: ", b->number);
+ printf_filtered ("Hardware access (read/write) watchpoint %d: ",
+ b->number);
print_expression (b->exp, gdb_stdout);
break;
+#endif
case bp_breakpoint:
+#ifdef UI_OUT
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ {
+ say_where = 0;
+ break;
+ }
+#endif
printf_filtered ("Breakpoint %d", b->number);
say_where = 1;
break;
case bp_hardware_breakpoint:
+#ifdef UI_OUT
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ {
+ say_where = 0;
+ break;
+ }
+#endif
printf_filtered ("Hardware assisted breakpoint %d", b->number);
say_where = 1;
break;
printf_filtered ("Catchpoint %d (%s %s)",
b->number,
(b->type == bp_catch_load) ? "load" : "unload",
- (b->dll_pathname != NULL) ? b->dll_pathname : "<any library>");
+ (b->dll_pathname != NULL) ?
+ b->dll_pathname : "<any library>");
break;
case bp_catch_fork:
case bp_catch_vfork:
case bp_call_dummy:
case bp_watchpoint_scope:
case bp_shlib_event:
+ case bp_thread_event:
break;
}
if (say_where)
TUIDO (((TuiOpaqueFuncPtr) tui_vAllSetHasBreakAt, b, 1));
TUIDO (((TuiOpaqueFuncPtr) tuiUpdateAllExecInfos));
}
+#ifdef UI_OUT
+ do_cleanups (old_chain);
+#endif
+#ifdef UI_OUT
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ return;
+#endif
printf_filtered ("\n");
}
\f
-/* 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. */
+/* Add SALS.nelts breakpoints to the breakpoint table. For each
+ SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i],
+ COND[i] and COND_STRING[i] values.
+
+ 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
+ caller is expected to cleanups both the ADDR_STRING, COND_STRING,
+ COND and SALS arrays and each of those arrays contents. */
static void
-break_command_1 (arg, flag, from_tty)
- char *arg;
- int flag, from_tty;
+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 tempflag, hardwareflag;
- struct symtabs_and_lines sals;
- struct symtab_and_line sal;
- register struct expression *cond = 0;
- register struct breakpoint *b;
-
- /* Pointers in arg to the start, and one past the end, of the condition. */
- char *cond_start = NULL;
- char *cond_end = NULL;
- /* Pointers in arg to the start, and one past the end,
- of the address part. */
- char *addr_start = NULL;
- char *addr_end = NULL;
- struct cleanup *old_chain;
- struct cleanup *canonical_strings_chain = NULL;
- char **canonical = (char **) NULL;
- int i;
- int thread;
-
- hardwareflag = flag & BP_HARDWAREFLAG;
- tempflag = flag & BP_TEMPFLAG;
-
- sals.sals = NULL;
- sals.nelts = 0;
+ if (type == bp_hardware_breakpoint)
+ {
+ int i = hw_breakpoint_used_count ();
+ int target_resources_ok =
+ TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint,
+ i + sals.nelts, 0);
+ if (target_resources_ok == 0)
+ error ("No hardware breakpoint support in the target.");
+ else if (target_resources_ok < 0)
+ error ("Hardware breakpoints used exceeds limit.");
+ }
- INIT_SAL (&sal); /* initialize to zeroes */
+ /* Now set all the breakpoints. */
+ {
+ int i;
+ for (i = 0; i < sals.nelts; i++)
+ {
+ struct breakpoint *b;
+ struct symtab_and_line sal = sals.sals[i];
+
+ if (from_tty)
+ describe_other_breakpoints (sal.pc, sal.section);
+
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->type = type;
+ b->cond = cond[i];
+ b->thread = thread;
+ b->addr_string = addr_string[i];
+ b->cond_string = cond_string[i];
+ b->ignore_count = ignore_count;
+ b->enable = enabled;
+ b->disposition = disposition;
+ mention (b);
+ }
+ }
+}
- /* If no arg given, or if first arg is 'if ', use the default breakpoint. */
+/* Parse ARG which is assumed to be a SAL specification possibly
+ followed by conditionals. On return, SALS contains an array of SAL
+ addresses found. ADDR_STRING contains a vector of (canonical)
+ address strings. ARG points to the end of the SAL. */
- if (!arg || (arg[0] == 'i' && arg[1] == 'f'
- && (arg[2] == ' ' || arg[2] == '\t')))
+void
+parse_breakpoint_sals (char **address,
+ struct symtabs_and_lines *sals,
+ char ***addr_string)
+{
+ char *addr_start = *address;
+ *addr_string = NULL;
+ /* If no arg given, or if first arg is 'if ', use the default
+ breakpoint. */
+ if ((*address) == NULL
+ || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2])))
{
if (default_breakpoint_valid)
{
- sals.sals = (struct symtab_and_line *)
+ struct symtab_and_line sal;
+ INIT_SAL (&sal); /* initialize to zeroes */
+ sals->sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
sal.pc = default_breakpoint_address;
sal.line = default_breakpoint_line;
sal.symtab = default_breakpoint_symtab;
sal.section = find_pc_overlay (sal.pc);
- sals.sals[0] = sal;
- sals.nelts = 1;
+ sals->sals[0] = sal;
+ sals->nelts = 1;
}
else
error ("No default breakpoint address now.");
}
else
{
- addr_start = arg;
-
/* Force almost all breakpoints to be in terms of the
current_source_symtab (which is decode_line_1's default). This
should produce the results we want almost all of the time while
leaving default_breakpoint_* alone. */
if (default_breakpoint_valid
&& (!current_source_symtab
- || (arg && (*arg == '+' || *arg == '-'))))
- sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
- default_breakpoint_line, &canonical);
+ || (strchr ("+-", (*address)[0]) != NULL)))
+ *sals = decode_line_1 (address, 1, default_breakpoint_symtab,
+ default_breakpoint_line, addr_string);
else
- sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, &canonical);
-
- addr_end = arg;
+ *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, addr_string);
}
-
- if (!sals.nelts)
- return;
-
- /* Make sure that all storage allocated in decode_line_1 gets freed in case
- the following `for' loop errors out. */
- old_chain = make_cleanup (free, sals.sals);
- if (canonical != (char **) NULL)
+ /* For any SAL that didn't have a canonical string, fill one in. */
+ if (sals->nelts > 0 && *addr_string == NULL)
+ *addr_string = xcalloc (sals->nelts, sizeof (char **));
+ if (addr_start != (*address))
{
- make_cleanup (free, canonical);
- canonical_strings_chain = make_cleanup (null_cleanup, 0);
- for (i = 0; i < sals.nelts; i++)
+ int i;
+ for (i = 0; i < sals->nelts; i++)
{
- if (canonical[i] != NULL)
- make_cleanup (free, canonical[i]);
+ /* Add the string if not present. */
+ if ((*addr_string)[i] == NULL)
+ (*addr_string)[i] = savestring (addr_start, (*address) - addr_start);
}
}
+}
- thread = -1; /* No specific thread yet */
- /* Resolve all line numbers to PC's, and verify that conditions
- can be parsed, before setting any breakpoints. */
- for (i = 0; i < sals.nelts; i++)
- {
- char *tok, *end_tok;
- int toklen;
+/* Convert each SAL into a real PC. Verify that the PC can be
+ inserted as a breakpoint. If it can't throw an error. */
- resolve_sal_pc (&sals.sals[i]);
+void
+breakpoint_sals_to_pc (struct symtabs_and_lines *sals,
+ char *address)
+{
+ int i;
+ for (i = 0; i < sals->nelts; i++)
+ {
+ resolve_sal_pc (&sals->sals[i]);
/* It's possible for the PC to be nonzero, but still an illegal
value on some targets.
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))
+ if (PC_REQUIRES_RUN_BEFORE_USE (sals->sals[i].pc))
{
- error ("Cannot break on %s without a running program.", addr_start);
+ if (address == NULL)
+ error ("Cannot break without a running program.");
+ else
+ error ("Cannot break on %s without a running program.",
+ address);
}
+ }
+}
+
+/* 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. */
+
+static void
+break_command_1 (arg, flag, from_tty)
+ char *arg;
+ int flag, from_tty;
+{
+ int tempflag, hardwareflag;
+ struct symtabs_and_lines sals;
+ register struct expression **cond = 0;
+ /* Pointers in arg to the start, and one past the end, of the
+ condition. */
+ char **cond_string = (char **) NULL;
+ char *addr_start = arg;
+ char **addr_string;
+ struct cleanup *old_chain;
+ struct cleanup *breakpoint_chain = NULL;
+ int i;
+ int thread = -1;
+ int ignore_count = 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;
+
+ /* 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 (free, sals.sals);
+
+ /* Cleanup the addr_string array but not its contents. */
+ make_cleanup (free, addr_string);
+
+ /* Allocate space for all the cond expressions. */
+ cond = xcalloc (sals.nelts, sizeof (struct expression *));
+ make_cleanup (free, cond);
+
+ /* Allocate space for all the cond strings. */
+ cond_string = xcalloc (sals.nelts, sizeof (char **));
+ make_cleanup (free, cond_string);
+
+ /* ----------------------------- SNIP -----------------------------
+ Anything added to the cleanup chain beyond this point is assumed
+ to be part of a breakpoint. If the breakpoint create succeeds
+ then the memory is not reclaimed. */
+ breakpoint_chain = make_cleanup (null_cleanup, 0);
- tok = arg;
+ /* Mark the contents of the addr_string for cleanup. These go on
+ the breakpoint_chain and only occure if the breakpoint create
+ fails. */
+ for (i = 0; i < sals.nelts; i++)
+ {
+ if (addr_string[i] != NULL)
+ make_cleanup (free, addr_string[i]);
+ }
+
+ /* Resolve all line numbers to PC's and verify that the addresses
+ are ok for the target. */
+ 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++)
+ {
+ char *tok = arg;
while (tok && *tok)
{
+ char *end_tok;
+ int toklen;
+ char *cond_start = NULL;
+ char *cond_end = NULL;
while (*tok == ' ' || *tok == '\t')
tok++;
if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
{
tok = cond_start = end_tok + 1;
- cond = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0);
+ cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0);
+ make_cleanup (free, cond[i]);
cond_end = tok;
+ cond_string[i] = savestring (cond_start, cond_end - cond_start);
+ make_cleanup (free, cond_string[i]);
}
else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
{
error ("Junk at end of arguments.");
}
}
- if (hardwareflag)
- {
- int i, target_resources_ok;
- i = hw_breakpoint_used_count ();
- target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
- bp_hardware_breakpoint, i + sals.nelts, 0);
- if (target_resources_ok == 0)
- error ("No hardware breakpoint support in the target.");
- else if (target_resources_ok < 0)
- error ("Hardware breakpoints used exceeds limit.");
+ create_breakpoints (sals, addr_string, cond, cond_string,
+ hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
+ tempflag ? del : donttouch,
+ thread, ignore_count, from_tty);
+
+ if (sals.nelts > 1)
+ {
+ warning ("Multiple breakpoints were set.");
+ warning ("Use the \"delete\" command to delete unwanted breakpoints.");
}
+ /* That's it. Discard the cleanups for data inserted into the
+ breakpoint. */
+ discard_cleanups (breakpoint_chain);
+ /* But cleanup everything else. */
+ do_cleanups (old_chain);
+}
- /* Remove the canonical strings from the cleanup, they are needed below. */
- if (canonical != (char **) NULL)
- discard_cleanups (canonical_strings_chain);
+/* Set a breakpoint of TYPE/DISPOSITION according to ARG (function,
+ linenum or *address) with COND and IGNORE_COUNT. */
- /* Now set all the breakpoints. */
- for (i = 0; i < sals.nelts; i++)
- {
- sal = sals.sals[i];
+struct captured_breakpoint_args
+ {
+ char *address;
+ char *condition;
+ int hardwareflag;
+ int tempflag;
+ int thread;
+ int ignore_count;
+ };
- if (from_tty)
- describe_other_breakpoints (sal.pc, sal.section);
+static int
+do_captured_breakpoint (void *data)
+{
+ struct captured_breakpoint_args *args = data;
+ struct symtabs_and_lines sals;
+ register struct expression **cond;
+ struct cleanup *old_chain;
+ struct cleanup *breakpoint_chain = NULL;
+ int i;
+ char **addr_string;
+ char **cond_string;
- b = set_raw_breakpoint (sal);
- set_breakpoint_count (breakpoint_count + 1);
- b->number = breakpoint_count;
- b->type = hardwareflag ? bp_hardware_breakpoint : bp_breakpoint;
- b->cond = cond;
- b->thread = thread;
+ char *address_end;
+
+ /* Parse the source and lines spec. Delay check that the expression
+ didn't contain trailing garbage until after cleanups are in
+ place. */
+ sals.sals = NULL;
+ sals.nelts = 0;
+ address_end = args->address;
+ addr_string = NULL;
+ parse_breakpoint_sals (&address_end, &sals, &addr_string);
- /* If a canonical line spec is needed use that instead of the
- command string. */
- if (canonical != (char **) NULL && canonical[i] != NULL)
- b->addr_string = canonical[i];
- else if (addr_start)
- b->addr_string = savestring (addr_start, addr_end - addr_start);
- if (cond_start)
- b->cond_string = savestring (cond_start, cond_end - cond_start);
+ if (!sals.nelts)
+ return GDB_RC_NONE;
- b->enable = enabled;
- b->disposition = tempflag ? del : donttouch;
- mention (b);
+ /* Create a chain of things at always need to be cleaned up. */
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ /* Always have a addr_string array, even if it is empty. */
+ make_cleanup (free, addr_string);
+
+ /* Make sure that all storage allocated to SALS gets freed. */
+ make_cleanup (free, sals.sals);
+
+ /* Allocate space for all the cond expressions. */
+ cond = xcalloc (sals.nelts, sizeof (struct expression *));
+ make_cleanup (free, cond);
+
+ /* Allocate space for all the cond strings. */
+ cond_string = xcalloc (sals.nelts, sizeof (char **));
+ make_cleanup (free, cond_string);
+
+ /* ----------------------------- SNIP -----------------------------
+ Anything added to the cleanup chain beyond this point is assumed
+ to be part of a breakpoint. If the breakpoint create goes
+ through then that memory is not cleaned up. */
+ breakpoint_chain = make_cleanup (null_cleanup, 0);
+
+ /* Mark the contents of the addr_string for cleanup. These go on
+ the breakpoint_chain and only occure if the breakpoint create
+ fails. */
+ for (i = 0; i < sals.nelts; i++)
+ {
+ if (addr_string[i] != NULL)
+ make_cleanup (free, addr_string[i]);
}
- if (sals.nelts > 1)
+ /* Wait until now before checking for garbage at the end of the
+ address. That way cleanups can take care of freeing any
+ memory. */
+ if (*address_end != '\0')
+ error ("Garbage %s following breakpoint address", address_end);
+
+ /* Resolve all line numbers to PC's. */
+ breakpoint_sals_to_pc (&sals, args->address);
+
+ /* Verify that conditions can be parsed, before setting any
+ breakpoints. */
+ for (i = 0; i < sals.nelts; i++)
{
- printf_filtered ("Multiple breakpoints were set.\n");
- printf_filtered ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+ if (args->condition != NULL)
+ {
+ char *tok = args->condition;
+ cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0);
+ if (*tok != '\0')
+ error ("Garbage %s follows condition", tok);
+ make_cleanup (free, cond[i]);
+ cond_string[i] = xstrdup (args->condition);
+ }
}
+
+ create_breakpoints (sals, addr_string, cond, cond_string,
+ args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
+ args->tempflag ? del : donttouch,
+ args->thread, args->ignore_count, 0/*from-tty*/);
+
+ /* That's it. Discard the cleanups for data inserted into the
+ breakpoint. */
+ discard_cleanups (breakpoint_chain);
+ /* But cleanup everything else. */
do_cleanups (old_chain);
+ return GDB_RC_OK;
+}
+
+enum gdb_rc
+gdb_breakpoint (char *address, char *condition,
+ int hardwareflag, int tempflag,
+ int thread, int ignore_count)
+{
+ struct captured_breakpoint_args args;
+ args.address = address;
+ args.condition = condition;
+ args.hardwareflag = hardwareflag;
+ args.tempflag = tempflag;
+ args.thread = thread;
+ args.ignore_count = ignore_count;
+ return catch_errors (do_captured_breakpoint, &args,
+ NULL, RETURN_MASK_ALL);
}
+
static void
break_at_finish_at_depth_command_1 (arg, flag, from_tty)
char *arg;
{
addr_string = (char *) xmalloc (26 + extra_args_len);
if (extra_args_len)
- sprintf (addr_string, "*0x%x %s", high, extra_args);
+ sprintf (addr_string, "*0x%s %s", paddr_nz (high), extra_args);
else
- sprintf (addr_string, "*0x%x", high);
+ sprintf (addr_string, "*0x%s", paddr_nz (high));
break_command_1 (addr_string, flag, from_tty);
free (addr_string);
}
if (selected_frame)
{
addr_string = (char *) xmalloc (15);
- sprintf (addr_string, "*0x%x", selected_frame->pc);
+ sprintf (addr_string, "*0x%s", paddr_nz (selected_frame->pc));
if (arg)
if_arg = 1;
}
{
break_string = (char *) xmalloc (extra_args_len + 26);
if (extra_args_len)
- sprintf (break_string, "*0x%x %s", high, extra_args);
+ sprintf (break_string, "*0x%s %s", paddr_nz (high), extra_args);
else
- sprintf (break_string, "*0x%x", high);
+ sprintf (break_string, "*0x%s", paddr_nz (high));
break_command_1 (break_string, flag, from_tty);
free (break_string);
}
}
if (sals.nelts > 1)
{
- printf_filtered ("Multiple breakpoints were set.\n");
- printf_filtered ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+ warning ("Multiple breakpoints were set.\n");
+ warning ("Use the \"delete\" command to delete unwanted breakpoints.");
}
do_cleanups (old_chain);
}
char *argptr = arg;
int hasColon = 0;
- /* look for a ':'. If this is a line number specification, then say
- it is bad, otherwise, it should be an address or function/method
- name */
+ /* look for a ':'. If this is a line number specification, then
+ say it is bad, otherwise, it should be an address or
+ function/method name */
while (*argptr && !hasColon)
{
hasColon = (*argptr == ':');
}
/* ARGSUSED */
-/* accessflag: 0: watch write, 1: watch read, 2: watch access(read or write) */
+/* accessflag: hw_write: watch write,
+ hw_read: watch read,
+ hw_access: watch access (read or write) */
static void
watch_command_1 (arg, accessflag, from_tty)
char *arg;
if (*tok)
error ("Junk at end of command.");
- if (accessflag == 1)
+ if (accessflag == hw_read)
bp_type = bp_read_watchpoint;
- else if (accessflag == 2)
+ else if (accessflag == hw_access)
bp_type = bp_access_watchpoint;
else
bp_type = bp_hardware_watchpoint;
if (mem_cnt != 0)
{
i = hw_watchpoint_used_count (bp_type, &other_type_used);
- target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
- bp_type, i + mem_cnt, other_type_used);
+ target_resources_ok =
+ TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_type, i + mem_cnt,
+ other_type_used);
if (target_resources_ok == 0 && bp_type != bp_hardware_watchpoint)
- error ("Target does not have this type of hardware watchpoint support.");
+ error ("Target does not support this type of hardware watchpoint.");
+
if (target_resources_ok < 0 && bp_type != bp_hardware_watchpoint)
- error ("Target resources have been allocated for other types of watchpoints.");
+ error ("Target can only support one kind of HW watchpoint at a time.");
}
#if defined(HPUXHPPA)
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) <= (REGISTER_SIZE))
+#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(BYTE_SIZE) \
+ ((BYTE_SIZE) <= (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)
#endif
static int
struct value *v;
{
int found_memory_cnt = 0;
+ struct value *head = v;
/* Did the user specifically forbid us to use hardware watchpoints? */
if (!can_use_hw_watchpoints)
return 0;
- /* Make sure all the intermediate values are in memory. Also make sure
- we found at least one memory expression. Guards against watch 0x12345,
- which is meaningless, but could cause errors if one tries to insert a
- hardware watchpoint for the constant expression. */
+ /* Make sure that the value of the expression depends only upon
+ memory contents, and values computed from them within GDB. If we
+ find any register references or function calls, we can't use a
+ hardware watchpoint.
+
+ The idea here is that evaluating an expression generates a series
+ of values, one holding the value of every subexpression. (The
+ expression a*b+c has five subexpressions: a, b, a*b, c, and
+ a*b+c.) GDB's values hold almost enough information to establish
+ the criteria given above --- they identify memory lvalues,
+ register lvalues, computed values, etcetera. So we can evaluate
+ the expression, and then scan the chain of values that leaves
+ behind to decide whether we can detect any possible change to the
+ expression's final value using only hardware watchpoints.
+
+ However, I don't think that the values returned by inferior
+ function calls are special in any way. So this function may not
+ notice that an expression involving an inferior function call
+ can't be watched with hardware watchpoints. FIXME. */
for (; v; v = v->next)
{
- if (v->lval == lval_memory)
+ if (VALUE_LVAL (v) == lval_memory)
{
- if (TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT (TYPE_LENGTH (VALUE_TYPE (v))))
- found_memory_cnt++;
+ 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'). */
+ ;
+ else
+ {
+ /* Ahh, memory we actually used! Check if we can cover
+ it with hardware watchpoints. */
+ struct type *vtype = check_typedef (VALUE_TYPE (v));
+
+ /* We only watch structs and arrays if user asked for it
+ explicitly, never if they just happen to appear in a
+ middle of some value chain. */
+ if (v == head
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ {
+ CORE_ADDR vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ int len = TYPE_LENGTH (VALUE_TYPE (v));
+
+ if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (vaddr, len))
+ return 0;
+ else
+ found_memory_cnt++;
+ }
+ }
}
else if (v->lval != not_lval && v->modifiable == 0)
- return 0;
+ return 0; /* ??? What does this represent? */
+ else if (v->lval == lval_register)
+ return 0; /* cannot watch a register with a HW watchpoint */
}
/* The expression itself looks suitable for using a hardware
return found_memory_cnt;
}
+#ifdef UI_OUT
+void
+watch_command_wrapper (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ watch_command (arg, from_tty);
+}
+#endif
static void
watch_command (arg, from_tty)
char *arg;
int from_tty;
{
- watch_command_1 (arg, 0, from_tty);
+ watch_command_1 (arg, hw_write, from_tty);
}
+#ifdef UI_OUT
+void
+rwatch_command_wrapper (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ rwatch_command (arg, from_tty);
+}
+#endif
static void
rwatch_command (arg, from_tty)
char *arg;
int from_tty;
{
- watch_command_1 (arg, 1, from_tty);
+ watch_command_1 (arg, hw_read, from_tty);
}
+#ifdef UI_OUT
+void
+awatch_command_wrapper (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ awatch_command (arg, from_tty);
+}
+#endif
static void
awatch_command (arg, from_tty)
char *arg;
int from_tty;
{
- watch_command_1 (arg, 2, from_tty);
+ watch_command_1 (arg, hw_access, from_tty);
}
\f
cmd_continuation pointer, to complete the until command. It takes
care of cleaning up the temporary breakpoints set up by the until
command. */
-void
-until_break_command_continuation (arg)
- struct continuation_arg *arg;
+static void
+until_break_command_continuation (struct continuation_arg *arg)
{
- /* Do all the exec cleanups, which at this point should only be the
- one set up in the first part of the until_break_command
- function. */
- do_exec_cleanups (ALL_CLEANUPS);
+ struct cleanup *cleanups;
+
+ cleanups = (struct cleanup *) arg->data.pointer;
+ do_exec_cleanups (cleanups);
}
/* ARGSUSED */
struct frame_info *prev_frame = get_prev_frame (selected_frame);
struct breakpoint *breakpoint;
struct cleanup *old_chain;
- struct continuation_arg *arg1, *arg2;
+ struct continuation_arg *arg1;
+
clear_proceed_status ();
sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
default_breakpoint_line, (char ***) NULL);
else
- sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, (char ***) NULL);
+ sals = decode_line_1 (&arg, 1, (struct symtab *) NULL,
+ 0, (char ***) NULL);
if (sals.nelts != 1)
error ("Couldn't get information on specified line.");
breakpoint = set_momentary_breakpoint (sal, selected_frame, bp_until);
- if (!async_p || !target_has_async)
- old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
+ if (!event_loop_p || !target_can_async_p ())
+ old_chain = make_cleanup_delete_breakpoint (breakpoint);
else
- make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
+ old_chain = make_exec_cleanup_delete_breakpoint (breakpoint);
/* If we are running asynchronously, and the target supports async
execution, we are not waiting for the target to stop, in the call
where we get a chance to do that is in fetch_inferior_event, so
we must set things up for that. */
- if (async_p && target_has_async)
+ if (event_loop_p && target_can_async_p ())
{
- /* In this case we don't need args for the continuation, because
- all it needs to do is do the cleanups in the
- exec_cleanup_chain, which will be only those inserted by this
- function. We can get away by using ALL_CLEANUPS. */
- add_continuation (until_break_command_continuation, NULL);
+ /* In this case the arg for the continuation is just the point
+ in the exec_cleanups chain from where to start doing
+ cleanups, because all the continuation does is the cleanups in
+ the exec_cleanup_chain. */
+ arg1 =
+ (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+ arg1->next = NULL;
+ arg1->data.pointer = old_chain;
+
+ add_continuation (until_break_command_continuation, arg1);
}
/* Keep within the current frame */
sal = find_pc_line (prev_frame->pc, 0);
sal.pc = prev_frame->pc;
breakpoint = set_momentary_breakpoint (sal, prev_frame, bp_until);
- if (!async_p || !target_has_async)
- make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
+ if (!event_loop_p || !target_can_async_p ())
+ make_cleanup_delete_breakpoint (breakpoint);
else
- make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
+ make_exec_cleanup_delete_breakpoint (breakpoint);
}
proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
/* Do the cleanups now, anly if we are not running asynchronously,
of if we are, but the target is still synchronous. */
- if (!async_p || !target_has_async)
+ if (!event_loop_p || !target_can_async_p ())
do_cleanups (old_chain);
}
\f
struct sal_chain *next = (struct sal_chain *)
alloca (sizeof (struct sal_chain));
next->next = sal_chain;
- next->sal = find_pc_line (SYMBOL_VALUE_ADDRESS (sym), 0);
+ next->sal = find_pc_line (SYMBOL_VALUE_ADDRESS (sym),
+ 0);
sal_chain = next;
}
}
that might be an event name in the leading characters. If a
possible match is found, a pointer to the last character of
the token is returned. Else, NULL is returned. */
+
static char *
ep_find_event_name_end (arg)
char *arg;
attempt to evaluate the string against a particular block.) And,
it updates arg to point to the first character following the parsed
if clause in the arg string. */
+
static char *
ep_parse_optional_if_clause (arg)
char **arg;
}
catch_fork_kind;
-static void catch_fork_command_1 PARAMS ((catch_fork_kind fork_kind, char *arg, int tempflag, int from_tty));
+#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 (fork_kind, arg, tempflag, from_tty)
break;
}
}
+#endif
+#if defined(CHILD_INSERT_EXEC_CATCHPOINT)
static void
catch_exec_command_1 (arg, tempflag, from_tty)
char *arg;
and enable reporting of such events. */
create_exec_event_catchpoint (tempflag, cond_string);
}
+#endif
#if defined(SOLIB_ADD)
static void
/* Create a load breakpoint that only triggers when a load of
the specified dll (or any dll, if no pathname was specified)
occurs. */
- SOLIB_CREATE_CATCH_LOAD_HOOK (inferior_pid, tempflag, dll_pathname, cond_string);
+ SOLIB_CREATE_CATCH_LOAD_HOOK (inferior_pid, tempflag,
+ dll_pathname, cond_string);
}
static void
/* Create an unload breakpoint that only triggers when an unload of
the specified dll (or any dll, if no pathname was specified)
occurs. */
- SOLIB_CREATE_CATCH_UNLOAD_HOOK (inferior_pid, tempflag, dll_pathname, cond_string);
+ SOLIB_CREATE_CATCH_UNLOAD_HOOK (inferior_pid, tempflag,
+ dll_pathname, cond_string);
}
#endif /* SOLIB_ADD */
struct symtab_and_line *sal;
{
struct breakpoint *b;
- int i;
int thread = -1; /* All threads. */
if (!sal) /* no exception support? */
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
b->cond = NULL;
- b->cond_string = (cond_string == NULL) ? NULL : savestring (cond_string, strlen (cond_string));
+ b->cond_string = (cond_string == NULL) ?
+ NULL : savestring (cond_string, strlen (cond_string));
b->thread = thread;
b->addr_string = NULL;
b->enable = enabled;
if (sal != (struct symtab_and_line *) -1)
create_exception_catchpoint (tempflag, cond_string, ex_event, sal);
else
- return; /* something went wrong with setting up callbacks */
+ return; /* something went wrong with setting up callbacks */
}
else
{
{
/* Set a breakpoint on __raise_exception () */
- fprintf_filtered (gdb_stderr, "Unsupported with this platform/compiler combination.\n");
- fprintf_filtered (gdb_stderr, "Perhaps you can achieve the effect you want by setting\n");
- fprintf_filtered (gdb_stderr, "a breakpoint on __raise_exception().\n");
+ warning ("Unsupported with this platform/compiler combination.");
+ warning ("Perhaps you can achieve the effect you want by setting");
+ warning ("a breakpoint on __raise_exception().");
}
}
}
b = set_raw_breakpoint (sal);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->type = bp_breakpoint; /* Important -- this is an ordinary breakpoint.
- For platforms with callback support for exceptions,
- create_exception_catchpoint() will create special
- bp types (bp_catch_catch and bp_catch_throw), and
- there is code in insert_breakpoints() and elsewhere
- that depends on that. */
+
+ /* Important -- this is an ordinary breakpoint. For platforms
+ with callback support for exceptions,
+ create_exception_catchpoint() will create special bp types
+ (bp_catch_catch and bp_catch_throw), and there is code in
+ insert_breakpoints() and elsewhere that depends on that. */
+ b->type = bp_breakpoint;
b->cond = cond;
b->enable = enabled;
if (sals.nelts > 1)
{
- printf_unfiltered ("Multiple breakpoints were set.\n");
- printf_unfiltered ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+ warning ("Multiple breakpoints were set.");
+ warning ("Use the \"delete\" command to delete unwanted breakpoints.");
}
free ((PTR) sals.sals);
}
}
else if (strncmp (arg1_start, "catch", arg1_length) == 0)
{
- catch_exception_command_1 (EX_EVENT_CATCH, arg1_end + 1, tempflag, from_tty);
+ catch_exception_command_1 (EX_EVENT_CATCH, arg1_end + 1,
+ tempflag, from_tty);
}
else if (strncmp (arg1_start, "throw", arg1_length) == 0)
{
- catch_exception_command_1 (EX_EVENT_THROW, arg1_end + 1, tempflag, from_tty);
+ catch_exception_command_1 (EX_EVENT_THROW, arg1_end + 1,
+ tempflag, from_tty);
}
else if (strncmp (arg1_start, "thread_start", arg1_length) == 0)
{
}
}
-/* Delete a breakpoint and clean up all traces of it in the data structures. */
+/* Delete a breakpoint and clean up all traces of it in the data
+ structures. */
void
delete_breakpoint (bpt)
if (delete_breakpoint_hook)
delete_breakpoint_hook (bpt);
+ breakpoint_delete_event (bpt->number);
if (bpt->inserted)
remove_breakpoint (bpt, mark_uninserted);
static char message[sizeof (message1) + 30];
args_for_catchpoint_enable args;
- sprintf (message, message1, bpt->number); /* Format possible error msg */
- args.kind = bpt->type == bp_catch_catch ? EX_EVENT_CATCH : EX_EVENT_THROW;
+ /* Format possible error msg */
+ sprintf (message, message1, bpt->number);
+ args.kind = bpt->type == bp_catch_catch ?
+ EX_EVENT_CATCH : EX_EVENT_THROW;
args.enable = 0;
catch_errors (cover_target_enable_exception_callback, &args,
message, RETURN_MASK_ALL);
&& b->enable != call_disabled)
{
int val;
- val = target_insert_breakpoint (b->address, b->shadow_contents);
+
+ /* We should never reach this point if there is a permanent
+ breakpoint at the same address as the one being deleted.
+ If there is a permanent breakpoint somewhere, it should
+ always be the only one inserted. */
+ if (b->enable == permanent)
+ internal_error ("another breakpoint was inserted on top of "
+ "a permanent breakpoint");
+
+ if (b->type == bp_hardware_breakpoint)
+ val = target_insert_hw_breakpoint (b->address, b->shadow_contents);
+ else
+ val = target_insert_breakpoint (b->address, b->shadow_contents);
+
if (val != 0)
{
target_terminal_ours_for_output ();
- fprintf_unfiltered (gdb_stderr, "Cannot insert breakpoint %d:\n", b->number);
+ warning ("Cannot insert breakpoint %d:", b->number);
memory_error (val, b->address); /* which bombs us out */
}
else
free ((PTR) bpt);
}
+static void
+do_delete_breakpoint_cleanup (void *b)
+{
+ delete_breakpoint (b);
+}
+
+struct cleanup *
+make_cleanup_delete_breakpoint (struct breakpoint *b)
+{
+ return make_cleanup (do_delete_breakpoint_cleanup, b);
+}
+
+struct cleanup *
+make_exec_cleanup_delete_breakpoint (struct breakpoint *b)
+{
+ return make_exec_cleanup (do_delete_breakpoint_cleanup, b);
+}
+
void
delete_command (arg, from_tty)
char *arg;
{
if (b->type != bp_call_dummy &&
b->type != bp_shlib_event &&
+ b->type != bp_thread_event &&
b->number >= 0)
breaks_to_delete = 1;
}
{
if (b->type != bp_call_dummy &&
b->type != bp_shlib_event &&
+ b->type != bp_thread_event &&
b->number >= 0)
delete_breakpoint (b);
}
breakpoint_re_set_one (bint)
PTR bint;
{
- struct breakpoint *b = (struct breakpoint *) bint; /* get past catch_errs */
+ /* get past catch_errs */
+ struct breakpoint *b = (struct breakpoint *) bint;
struct value *mark;
int i;
struct symtabs_and_lines sals;
switch (b->type)
{
case bp_none:
- warning ("attempted to reset apparently deleted breakpoint #%d?\n", b->number);
+ warning ("attempted to reset apparently deleted breakpoint #%d?",
+ b->number);
return 0;
case bp_breakpoint:
case bp_hardware_breakpoint:
case bp_read_watchpoint:
case bp_access_watchpoint:
innermost_block = NULL;
- /* The issue arises of what context to evaluate this in. The same
- one as when it was set, but what does that mean when symbols have
- been re-read? We could save the filename and functionname, but
- if the context is more local than that, the best we could do would
- be something like how many levels deep and which index at that
- particular level, but that's going to be less stable than filenames
- or functionnames. */
+ /* The issue arises of what context to evaluate this in. The
+ same one as when it was set, but what does that mean when
+ symbols have been re-read? We could save the filename and
+ functionname, but if the context is more local than that, the
+ best we could do would be something like how many levels deep
+ and which index at that particular level, but that's going to
+ be less stable than filenames or function names. */
+
/* So for now, just use a global context. */
if (b->exp)
free ((PTR) b->exp);
starts and we really don't want to touch it. */
case bp_shlib_event:
+ /* Like bp_shlib_event, this breakpoint type is special.
+ Once it is set up, we do not want to touch it. */
+ case bp_thread_event:
+
/* Keep temporary breakpoints, which can be encountered when we step
over a dlopen call and SOLIB_ADD is resetting the breakpoints.
Otherwise these should have been blown away via the cleanup chain
save_input_radix = input_radix;
ALL_BREAKPOINTS_SAFE (b, temp)
{
- sprintf (message, message1, b->number); /* Format possible error msg */
+ /* Format possible error msg */
+ sprintf (message, message1, b->number);
catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL);
}
set_language (save_language);
error_no_arg ("a breakpoint number");
num = get_number (&p);
-
+ if (num == 0)
+ error ("bad breakpoint number: '%s'", args);
if (*p == 0)
error ("Second argument (specified ignore-count) is missing.");
register char *p = args;
char *p1;
register int num;
- register struct breakpoint *b;
+ register struct breakpoint *b, *tmp;
+ int match;
if (p == 0)
error_no_arg ("one or more breakpoint numbers");
while (*p)
{
+ match = 0;
p1 = p;
- num = get_number (&p1);
-
- ALL_BREAKPOINTS (b)
- if (b->number == num)
+ num = get_number_or_range (&p1);
+ if (num == 0)
{
- struct breakpoint *related_breakpoint = b->related_breakpoint;
- function (b);
- if (related_breakpoint)
- function (related_breakpoint);
- goto win;
+ warning ("bad breakpoint number at or near '%s'", p);
+ }
+ else
+ {
+ ALL_BREAKPOINTS_SAFE (b, tmp)
+ if (b->number == num)
+ {
+ struct breakpoint *related_breakpoint = b->related_breakpoint;
+ match = 1;
+ function (b);
+ if (related_breakpoint)
+ function (related_breakpoint);
+ break;
+ }
+ if (match == 0)
+ printf_unfiltered ("No breakpoint number %d.\n", num);
}
- printf_unfiltered ("No breakpoint number %d.\n", num);
- win:
p = p1;
}
}
if (bpt->type == bp_watchpoint_scope)
return;
+ /* You can't disable permanent breakpoints. */
+ if (bpt->enable == permanent)
+ return;
+
bpt->enable = disabled;
check_duplicates (bpt->address, bpt->section);
if (modify_breakpoint_hook)
modify_breakpoint_hook (bpt);
+ breakpoint_modify_event (bpt->number);
}
/* ARGSUSED */
switch (bpt->type)
{
case bp_none:
- warning ("attempted to disable apparently deleted breakpoint #%d?\n", bpt->number);
+ warning ("attempted to disable apparently deleted breakpoint #%d?",
+ bpt->number);
continue;
case bp_breakpoint:
case bp_catch_load:
{
int i;
i = hw_breakpoint_used_count ();
- target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
- bp_hardware_breakpoint, i + 1, 0);
+ target_resources_ok =
+ TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint,
+ i + 1, 0);
if (target_resources_ok == 0)
error ("No hardware breakpoint support in the target.");
else if (target_resources_ok < 0)
error ("Hardware breakpoints used exceeds limit.");
}
- bpt->enable = enabled;
+ if (bpt->enable != permanent)
+ bpt->enable = enabled;
bpt->disposition = disposition;
check_duplicates (bpt->address, bpt->section);
breakpoints_changed ();
- if (bpt->type == bp_watchpoint || bpt->type == bp_hardware_watchpoint ||
- bpt->type == bp_read_watchpoint || bpt->type == bp_access_watchpoint)
+ 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)
{
}
if (save_selected_frame_level >= 0)
- select_and_print_frame (save_selected_frame, save_selected_frame_level);
+ select_frame (save_selected_frame, save_selected_frame_level);
value_free_to_mark (mark);
}
if (modify_breakpoint_hook)
modify_breakpoint_hook (bpt);
+ breakpoint_modify_event (bpt->number);
}
void
switch (bpt->type)
{
case bp_none:
- warning ("attempted to enable apparently deleted breakpoint #%d?\n", bpt->number);
+ warning ("attempted to enable apparently deleted breakpoint #%d?",
+ bpt->number);
continue;
case bp_breakpoint:
case bp_catch_load:
error ("Empty line specification.");
if (default_breakpoint_valid)
sals = decode_line_1 (&string, funfirstline,
- default_breakpoint_symtab, default_breakpoint_line,
+ default_breakpoint_symtab,
+ default_breakpoint_line,
(char ***) NULL);
else
sals = decode_line_1 (&string, funfirstline,
by using \"enable delete\" on the catchpoint number.");
add_com ("watch", class_breakpoint, watch_command,
-
"Set a watchpoint for an expression.\n\
A watchpoint stops execution of your program whenever the value of\n\
an expression changes.");