#include "jit.h"
#include "xml-syscall.h"
#include "parser-defs.h"
+#include "cli/cli-utils.h"
/* readline include files */
#include "readline/readline.h"
#undef savestring
#include "mi/mi-common.h"
+#include "python/python.h"
/* Arguments to pass as context to some catch command handlers. */
#define CATCH_PERMANENT ((void *) (uintptr_t) 0)
static void watchpoints_info (char *, int);
-static int breakpoint_1 (int, int, int (*) (const struct breakpoint *));
+static int breakpoint_1 (char *, int,
+ int (*) (const struct breakpoint *));
static int breakpoint_cond_eval (void *);
static void condition_command (char *, int);
-static int get_number_trailer (char **, int);
-
typedef enum
{
mark_inserted,
static void tcatch_command (char *arg, int from_tty);
-static void ep_skip_leading_whitespace (char **s);
-
static void detach_single_step_breakpoints (void);
static int single_step_breakpoint_inserted_here_p (struct address_space *,
struct program_space *default_breakpoint_pspace;
\f
-/* *PP is a string denoting a breakpoint. Get the number of the
- breakpoint. Advance *PP after the string and any trailing
- whitespace.
-
- 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").
-
- If the string is a NULL pointer, that denotes the last breakpoint.
-
- 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_trailer (char **pp, int trailer)
-{
- int retval = 0; /* default */
- char *p = *pp;
-
- if (p == NULL)
- /* Empty line means refer to the last breakpoint. */
- return breakpoint_count;
- else if (*p == '$')
- {
- /* Make a copy of the name, so we can null-terminate it
- to pass to lookup_internalvar(). */
- char *varname;
- char *start = ++p;
- LONGEST val;
-
- while (isalnum (*p) || *p == '_')
- p++;
- varname = (char *) alloca (p - start + 1);
- strncpy (varname, start, p - start);
- varname[p - start] = '\0';
- if (get_internalvar_integer (lookup_internalvar (varname), &val))
- retval = (int) val;
- else
- {
- printf_filtered (_("Convenience variable must "
- "have integer value.\n"));
- retval = 0;
- }
- }
- else
- {
- if (*p == '-')
- ++p;
- while (*p >= '0' && *p <= '9')
- ++p;
- if (p == *pp)
- /* There is no number here. (e.g. "cond a == b"). */
- {
- /* 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;
- }
- while (isspace (*p))
- p++;
- *pp = p;
- return retval;
-}
-
-
-/* Like get_number_trailer, but don't allow a trailer. */
-int
-get_number (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 (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;
-}
-
/* Return the breakpoint with the specified number, or NULL
if the number does not refer to an existing breakpoint. */
ALL_BREAKPOINTS (b)
if (b->number == bnum)
{
+ /* Check if this breakpoint has a Python object assigned to
+ it, and if it has a definition of the "stop"
+ method. This method and conditions entered into GDB from
+ the CLI are mutually exclusive. */
+ if (b->py_bp_object
+ && gdbpy_breakpoint_has_py_cond (b->py_bp_object))
+ error (_("Cannot set a condition where a Python 'stop' "
+ "method has been defined in the breakpoint."));
set_breakpoint_condition (b, p, from_tty);
return;
}
observer_notify_breakpoint_modified (b->number);
}
+/* Set the internal `silent' flag on the breakpoint. Note that this
+ is not the same as the "silent" that may appear in the breakpoint's
+ commands. */
+
+void
+breakpoint_set_silent (struct breakpoint *b, int silent)
+{
+ int old_silent = b->silent;
+
+ b->silent = silent;
+ if (old_silent != silent)
+ observer_notify_breakpoint_modified (b->number);
+}
+
+/* Set the thread for this breakpoint. If THREAD is -1, make the
+ breakpoint work for any thread. */
+
+void
+breakpoint_set_thread (struct breakpoint *b, int thread)
+{
+ int old_thread = b->thread;
+
+ b->thread = thread;
+ if (old_thread != thread)
+ observer_notify_breakpoint_modified (b->number);
+}
+
+/* Set the task for this breakpoint. If TASK is 0, make the
+ breakpoint work for any task. */
+
+void
+breakpoint_set_task (struct breakpoint *b, int task)
+{
+ int old_task = b->task;
+
+ b->task = task;
+ if (old_task != task)
+ observer_notify_breakpoint_modified (b->number);
+}
+
void
check_tracepoint_command (char *line, void *closure)
{
if (!watchpoint_in_thread_scope (b))
return;
- /* We don't free locations. They are stored in bp_location array
- and update_global_locations will eventually delete them and
- remove breakpoints if needed. */
- b->loc = NULL;
-
if (b->disposition == disp_del_at_next_stop)
return;
within_current_scope = 1;
else
{
- struct frame_info *fi;
+ struct frame_info *fi = get_current_frame ();
+ struct gdbarch *frame_arch = get_frame_arch (fi);
+ CORE_ADDR frame_pc = get_frame_pc (fi);
+
+ /* If we're in a function epilogue, unwinding may not work
+ properly, so do not attempt to recreate locations at this
+ point. See similar comments in watchpoint_check. */
+ if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc))
+ return;
/* Save the current frame's ID so we can restore it after
evaluating the watchpoint expression on its own frame. */
select_frame (fi);
}
+ /* We don't free locations. They are stored in the bp_location array
+ and update_global_location_list will eventually delete them and
+ remove breakpoints if needed. */
+ b->loc = NULL;
+
if (within_current_scope && reparse)
{
char *s;
struct cleanup *old_chain;
struct bp_location *bl, **blp_tmp;
int val;
- struct ui_file *tmp_error_stream = mem_fileopen ();
+ struct ui_file *tmp_error_stream;
int dummy1 = 0, dummy2 = 0;
struct inferior *inf;
struct thread_info *tp;
inferior_ptid = tp->ptid;
+ tmp_error_stream = mem_fileopen ();
make_cleanup_ui_file_delete (tmp_error_stream);
ALL_BP_LOCATIONS (bl, blp_tmp)
return b;
}
+static const char *const longjmp_names[] =
+ {
+ "longjmp", "_longjmp", "siglongjmp", "_siglongjmp"
+ };
+#define NUM_LONGJMP_NAMES ARRAY_SIZE(longjmp_names)
+
+/* Per-objfile data private to breakpoint.c. */
+struct breakpoint_objfile_data
+{
+ /* Minimal symbol for "_ovly_debug_event" (if any). */
+ struct minimal_symbol *overlay_msym;
+
+ /* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */
+ struct minimal_symbol *longjmp_msym[NUM_LONGJMP_NAMES];
+
+ /* Minimal symbol for "std::terminate()" (if any). */
+ struct minimal_symbol *terminate_msym;
+
+ /* Minimal symbol for "_Unwind_DebugHook" (if any). */
+ struct minimal_symbol *exception_msym;
+};
+
+static const struct objfile_data *breakpoint_objfile_key;
+
+/* Minimal symbol not found sentinel. */
+static struct minimal_symbol msym_not_found;
+
+/* Returns TRUE if MSYM point to the "not found" sentinel. */
+
+static int
+msym_not_found_p (const struct minimal_symbol *msym)
+{
+ return msym == &msym_not_found;
+}
+
+/* Return per-objfile data needed by breakpoint.c.
+ Allocate the data if necessary. */
+
+static struct breakpoint_objfile_data *
+get_breakpoint_objfile_data (struct objfile *objfile)
+{
+ struct breakpoint_objfile_data *bp_objfile_data;
+
+ bp_objfile_data = objfile_data (objfile, breakpoint_objfile_key);
+ if (bp_objfile_data == NULL)
+ {
+ bp_objfile_data = obstack_alloc (&objfile->objfile_obstack,
+ sizeof (*bp_objfile_data));
+
+ memset (bp_objfile_data, 0, sizeof (*bp_objfile_data));
+ set_objfile_data (objfile, breakpoint_objfile_key, bp_objfile_data);
+ }
+ return bp_objfile_data;
+}
+
static void
-create_overlay_event_breakpoint (char *func_name)
+create_overlay_event_breakpoint (void)
{
struct objfile *objfile;
+ const char *const func_name = "_ovly_debug_event";
ALL_OBJFILES (objfile)
{
struct breakpoint *b;
- struct minimal_symbol *m;
+ struct breakpoint_objfile_data *bp_objfile_data;
+ CORE_ADDR addr;
- m = lookup_minimal_symbol_text (func_name, objfile);
- if (m == NULL)
- continue;
+ bp_objfile_data = get_breakpoint_objfile_data (objfile);
+
+ if (msym_not_found_p (bp_objfile_data->overlay_msym))
+ continue;
- b = create_internal_breakpoint (get_objfile_arch (objfile),
- SYMBOL_VALUE_ADDRESS (m),
+ if (bp_objfile_data->overlay_msym == NULL)
+ {
+ struct minimal_symbol *m;
+
+ m = lookup_minimal_symbol_text (func_name, objfile);
+ if (m == NULL)
+ {
+ /* Avoid future lookups in this objfile. */
+ bp_objfile_data->overlay_msym = &msym_not_found;
+ continue;
+ }
+ bp_objfile_data->overlay_msym = m;
+ }
+
+ addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym);
+ b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_overlay_event);
b->addr_string = xstrdup (func_name);
}
static void
-create_longjmp_master_breakpoint (char *func_name)
+create_longjmp_master_breakpoint (void)
{
struct program_space *pspace;
- struct objfile *objfile;
struct cleanup *old_chain;
old_chain = save_current_program_space ();
ALL_PSPACES (pspace)
- ALL_OBJFILES (objfile)
+ {
+ struct objfile *objfile;
+
+ set_current_program_space (pspace);
+
+ ALL_OBJFILES (objfile)
{
- struct breakpoint *b;
- struct minimal_symbol *m;
+ int i;
+ struct gdbarch *gdbarch;
+ struct breakpoint_objfile_data *bp_objfile_data;
- if (!gdbarch_get_longjmp_target_p (get_objfile_arch (objfile)))
+ gdbarch = get_objfile_arch (objfile);
+ if (!gdbarch_get_longjmp_target_p (gdbarch))
continue;
- set_current_program_space (pspace);
+ bp_objfile_data = get_breakpoint_objfile_data (objfile);
- m = lookup_minimal_symbol_text (func_name, objfile);
- if (m == NULL)
- continue;
+ for (i = 0; i < NUM_LONGJMP_NAMES; i++)
+ {
+ struct breakpoint *b;
+ const char *func_name;
+ CORE_ADDR addr;
- b = create_internal_breakpoint (get_objfile_arch (objfile),
- SYMBOL_VALUE_ADDRESS (m),
- bp_longjmp_master);
- b->addr_string = xstrdup (func_name);
- b->enable_state = bp_disabled;
+ if (msym_not_found_p (bp_objfile_data->longjmp_msym[i]))
+ continue;
+
+ func_name = longjmp_names[i];
+ if (bp_objfile_data->longjmp_msym[i] == NULL)
+ {
+ struct minimal_symbol *m;
+
+ m = lookup_minimal_symbol_text (func_name, objfile);
+ if (m == NULL)
+ {
+ /* Prevent future lookups in this objfile. */
+ bp_objfile_data->longjmp_msym[i] = &msym_not_found;
+ continue;
+ }
+ bp_objfile_data->longjmp_msym[i] = m;
+ }
+
+ addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
+ b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master);
+ b->addr_string = xstrdup (func_name);
+ b->enable_state = bp_disabled;
+ }
}
+ }
update_global_location_list (1);
do_cleanups (old_chain);
}
-/* Create a master std::terminate breakpoint. The actual function
- looked for is named FUNC_NAME. */
+/* Create a master std::terminate breakpoint. */
static void
-create_std_terminate_master_breakpoint (const char *func_name)
+create_std_terminate_master_breakpoint (void)
{
struct program_space *pspace;
- struct objfile *objfile;
struct cleanup *old_chain;
+ const char *const func_name = "std::terminate()";
old_chain = save_current_program_space ();
ALL_PSPACES (pspace)
+ {
+ struct objfile *objfile;
+ CORE_ADDR addr;
+
+ set_current_program_space (pspace);
+
ALL_OBJFILES (objfile)
{
struct breakpoint *b;
- struct minimal_symbol *m;
+ struct breakpoint_objfile_data *bp_objfile_data;
- set_current_program_space (pspace);
+ bp_objfile_data = get_breakpoint_objfile_data (objfile);
- m = lookup_minimal_symbol (func_name, NULL, objfile);
- if (m == NULL || (MSYMBOL_TYPE (m) != mst_text
- && MSYMBOL_TYPE (m) != mst_file_text))
- continue;
+ if (msym_not_found_p (bp_objfile_data->terminate_msym))
+ continue;
+
+ if (bp_objfile_data->terminate_msym == NULL)
+ {
+ struct minimal_symbol *m;
- b = create_internal_breakpoint (get_objfile_arch (objfile),
- SYMBOL_VALUE_ADDRESS (m),
+ m = lookup_minimal_symbol (func_name, NULL, objfile);
+ if (m == NULL || (MSYMBOL_TYPE (m) != mst_text
+ && MSYMBOL_TYPE (m) != mst_file_text))
+ {
+ /* Prevent future lookups in this objfile. */
+ bp_objfile_data->terminate_msym = &msym_not_found;
+ continue;
+ }
+ bp_objfile_data->terminate_msym = m;
+ }
+
+ addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym);
+ b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_std_terminate_master);
b->addr_string = xstrdup (func_name);
b->enable_state = bp_disabled;
}
+ }
+
update_global_location_list (1);
do_cleanups (old_chain);
create_exception_master_breakpoint (void)
{
struct objfile *objfile;
+ const char *const func_name = "_Unwind_DebugHook";
ALL_OBJFILES (objfile)
{
- struct minimal_symbol *debug_hook;
+ struct breakpoint *b;
+ struct gdbarch *gdbarch;
+ struct breakpoint_objfile_data *bp_objfile_data;
+ CORE_ADDR addr;
+
+ bp_objfile_data = get_breakpoint_objfile_data (objfile);
+
+ if (msym_not_found_p (bp_objfile_data->exception_msym))
+ continue;
+
+ gdbarch = get_objfile_arch (objfile);
- debug_hook = lookup_minimal_symbol ("_Unwind_DebugHook", NULL, objfile);
- if (debug_hook != NULL)
+ if (bp_objfile_data->exception_msym == NULL)
{
- struct breakpoint *b;
- CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (debug_hook);
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct minimal_symbol *debug_hook;
- addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
- ¤t_target);
- b = create_internal_breakpoint (gdbarch, addr, bp_exception_master);
- b->addr_string = xstrdup ("_Unwind_DebugHook");
- b->enable_state = bp_disabled;
+ debug_hook = lookup_minimal_symbol (func_name, NULL, objfile);
+ if (debug_hook == NULL)
+ {
+ bp_objfile_data->exception_msym = &msym_not_found;
+ continue;
+ }
+
+ bp_objfile_data->exception_msym = debug_hook;
}
+
+ addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
+ addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
+ ¤t_target);
+ b = create_internal_breakpoint (gdbarch, addr, bp_exception_master);
+ b->addr_string = xstrdup (func_name);
+ b->enable_state = bp_disabled;
}
update_global_location_list (1);
}
}
/* FIXME what about longjmp breakpoints? Re-create them here? */
- create_overlay_event_breakpoint ("_ovly_debug_event");
- create_longjmp_master_breakpoint ("longjmp");
- create_longjmp_master_breakpoint ("_longjmp");
- create_longjmp_master_breakpoint ("siglongjmp");
- create_longjmp_master_breakpoint ("_siglongjmp");
- create_std_terminate_master_breakpoint ("std::terminate()");
+ create_overlay_event_breakpoint ();
+ create_longjmp_master_breakpoint ();
+ create_std_terminate_master_breakpoint ();
create_exception_master_breakpoint ();
}
int bp_temp = 0;
enum print_stop_action result;
- /* bs->breakpoint_at can be NULL if it was a momentary breakpoint
- which has since been deleted. */
- if (bs->breakpoint_at == NULL)
- return PRINT_UNKNOWN;
-
gdb_assert (bs->bp_location_at != NULL);
bl = bs->bp_location_at;
{
struct breakpoint *b = bs->breakpoint_at;
+ /* bs->breakpoint_at can be NULL if it was a momentary breakpoint
+ which has since been deleted. */
+ if (b == NULL)
+ return PRINT_UNKNOWN;
+
/* Normal case. Call the breakpoint's print_it method, or
print_it_typical. */
- /* FIXME: how breakpoint can ever be NULL here? */
- if (b != NULL && b->ops != NULL && b->ops->print_it != NULL)
+ if (b->ops != NULL && b->ops->print_it != NULL)
return b->ops->print_it (b);
else
return print_it_typical (bs);
int value_is_zero = 0;
struct expression *cond;
+ /* Evaluate Python breakpoints that have a "stop"
+ method implemented. */
+ if (b->py_bp_object)
+ bs->stop = gdbpy_should_stop (b->py_bp_object);
+
if (is_watchpoint (b))
cond = b->cond_exp;
else
\f
+/* Compute a string of spaces suitable to indent the next line
+ so it starts at the position corresponding to the table column
+ named COL_NAME in the currently active table of UIOUT. */
+
+static char *
+wrap_indent_at_field (struct ui_out *uiout, const char *col_name)
+{
+ static char wrap_indent[80];
+ int i, total_width, width, align;
+ char *text;
+
+ total_width = 0;
+ for (i = 1; ui_out_query_field (uiout, i, &width, &align, &text); i++)
+ {
+ if (strcmp (text, col_name) == 0)
+ {
+ gdb_assert (total_width < sizeof wrap_indent);
+ memset (wrap_indent, ' ', total_width);
+ wrap_indent[total_width] = 0;
+
+ return wrap_indent;
+ }
+
+ total_width += width + 1;
+ }
+
+ return NULL;
+}
+
/* Print the LOC location out of the list of B->LOC locations. */
-static void print_breakpoint_location (struct breakpoint *b,
- struct bp_location *loc,
- char *wrap_indent,
- struct ui_stream *stb)
+static void
+print_breakpoint_location (struct breakpoint *b,
+ struct bp_location *loc)
{
struct cleanup *old_chain = save_current_program_space ();
ui_out_text (uiout, "in ");
ui_out_field_string (uiout, "func",
SYMBOL_PRINT_NAME (sym));
- ui_out_wrap_hint (uiout, wrap_indent);
- ui_out_text (uiout, " at ");
+ ui_out_text (uiout, " ");
+ ui_out_wrap_hint (uiout, wrap_indent_at_field (uiout, "what"));
+ ui_out_text (uiout, "at ");
}
ui_out_field_string (uiout, "file", b->source_file);
ui_out_text (uiout, ":");
}
else if (loc)
{
+ struct ui_stream *stb = ui_out_stream_new (uiout);
+ struct cleanup *stb_chain = make_cleanup_ui_out_stream_delete (stb);
+
print_address_symbolic (loc->gdbarch, loc->address, stb->stream,
demangle, "");
ui_out_field_stream (uiout, "at", stb);
+
+ do_cleanups (stb_chain);
}
else
ui_out_field_string (uiout, "pending", b->addr_string);
struct bp_location *loc,
int loc_number,
struct bp_location **last_loc,
- int print_address_bits,
int allflag)
{
struct command_line *l;
static char bpenables[] = "nynny";
- char wrap_indent[80];
- struct ui_stream *stb = ui_out_stream_new (uiout);
- struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
struct cleanup *bkpt_chain;
int header_of_multiple = 0;
/* 5 and 6 */
- strcpy (wrap_indent, " ");
- if (opts.addressprint)
- {
- if (print_address_bits <= 32)
- strcat (wrap_indent, " ");
- else
- strcat (wrap_indent, " ");
- }
-
if (b->ops != NULL && b->ops->print_one != NULL)
{
/* Although the print_one can possibly print all locations,
}
annotate_field (5);
if (!header_of_multiple)
- print_breakpoint_location (b, loc, wrap_indent, stb);
+ print_breakpoint_location (b, loc);
if (b->loc)
*last_loc = b->loc;
break;
}
do_cleanups (bkpt_chain);
- do_cleanups (old_chain);
}
static void
print_one_breakpoint (struct breakpoint *b,
struct bp_location **last_loc,
- int print_address_bits,
int allflag)
{
- print_one_breakpoint_location (b, NULL, 0, last_loc,
- print_address_bits, allflag);
+ print_one_breakpoint_location (b, NULL, 0, last_loc, allflag);
/* If this breakpoint has custom print function,
it's already printed. Otherwise, print individual
situation.
Note that while hardware watchpoints have several locations
- internally, that's no a property exposed to user. */
+ internally, that's not a property exposed to user. */
if (b->loc
&& !is_hardware_watchpoint (b)
&& (b->loc->next || !b->loc->enabled)
struct bp_location *loc;
int n = 1;
for (loc = b->loc; loc; loc = loc->next, ++n)
- print_one_breakpoint_location (b, loc, n, last_loc,
- print_address_bits, allflag);
+ print_one_breakpoint_location (b, loc, n, last_loc, allflag);
}
}
}
{
if (args->bnum == b->number)
{
- int print_address_bits = breakpoint_address_bits (b);
-
- print_one_breakpoint (b, &dummy_loc, print_address_bits, 0);
+ print_one_breakpoint (b, &dummy_loc, 0);
return GDB_RC_OK;
}
}
breakpoints listed. */
static int
-breakpoint_1 (int bnum, int allflag,
+breakpoint_1 (char *args, int allflag,
int (*filter) (const struct breakpoint *))
{
struct breakpoint *b;
required for address fields. */
nr_printable_breakpoints = 0;
ALL_BREAKPOINTS (b)
- if (bnum == -1
- || bnum == b->number)
- {
- /* If we have a filter, only list the breakpoints it accepts. */
- if (filter && !filter (b))
- continue;
-
- if (allflag || user_breakpoint_p (b))
- {
- int addr_bit, type_len;
+ {
+ /* If we have a filter, only list the breakpoints it accepts. */
+ if (filter && !filter (b))
+ continue;
- addr_bit = breakpoint_address_bits (b);
- if (addr_bit > print_address_bits)
- print_address_bits = addr_bit;
+ /* If we have an "args" string, it is a list of breakpoints to
+ accept. Skip the others. */
+ if (args != NULL && *args != '\0')
+ {
+ if (allflag && parse_and_eval_long (args) != b->number)
+ continue;
+ if (!allflag && !number_is_in_list (args, b->number))
+ continue;
+ }
- type_len = strlen (bptype_string (b->type));
- if (type_len > print_type_col_width)
- print_type_col_width = type_len;
+ if (allflag || user_breakpoint_p (b))
+ {
+ int addr_bit, type_len;
- nr_printable_breakpoints++;
- }
- }
+ addr_bit = breakpoint_address_bits (b);
+ if (addr_bit > print_address_bits)
+ print_address_bits = addr_bit;
+
+ type_len = strlen (bptype_string (b->type));
+ if (type_len > print_type_col_width)
+ print_type_col_width = type_len;
+
+ nr_printable_breakpoints++;
+ }
+ }
if (opts.addressprint)
bkpttbl_chain
annotate_field (3);
ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); /* 4 */
if (opts.addressprint)
- {
- if (nr_printable_breakpoints > 0)
- annotate_field (4);
- if (print_address_bits <= 32)
- ui_out_table_header (uiout, 10, ui_left,
- "addr", "Address"); /* 5 */
- else
- ui_out_table_header (uiout, 18, ui_left,
- "addr", "Address"); /* 5 */
- }
+ {
+ if (nr_printable_breakpoints > 0)
+ annotate_field (4);
+ if (print_address_bits <= 32)
+ ui_out_table_header (uiout, 10, ui_left,
+ "addr", "Address"); /* 5 */
+ else
+ ui_out_table_header (uiout, 18, ui_left,
+ "addr", "Address"); /* 5 */
+ }
if (nr_printable_breakpoints > 0)
annotate_field (5);
ui_out_table_header (uiout, 40, ui_noalign, "what", "What"); /* 6 */
annotate_breakpoints_table ();
ALL_BREAKPOINTS (b)
- {
- QUIT;
- if (bnum == -1
- || bnum == b->number)
- {
- /* If we have a filter, only list the breakpoints it accepts. */
- if (filter && !filter (b))
- continue;
-
- /* We only print out user settable breakpoints unless the
- allflag is set. */
- if (allflag || user_breakpoint_p (b))
- print_one_breakpoint (b, &last_loc, print_address_bits, allflag);
- }
- }
-
+ {
+ QUIT;
+ /* If we have a filter, only list the breakpoints it accepts. */
+ if (filter && !filter (b))
+ continue;
+
+ /* If we have an "args" string, it is a list of breakpoints to
+ accept. Skip the others. */
+
+ if (args != NULL && *args != '\0')
+ {
+ if (allflag) /* maintenance info breakpoint */
+ {
+ if (parse_and_eval_long (args) != b->number)
+ continue;
+ }
+ else /* all others */
+ {
+ if (!number_is_in_list (args, b->number))
+ continue;
+ }
+ }
+ /* We only print out user settable breakpoints unless the
+ allflag is set. */
+ if (allflag || user_breakpoint_p (b))
+ print_one_breakpoint (b, &last_loc, allflag);
+ }
+
do_cleanups (bkpttbl_chain);
if (nr_printable_breakpoints == 0)
empty list. */
if (!filter)
{
- if (bnum == -1)
+ if (args == NULL || *args == '\0')
ui_out_message (uiout, 0, "No breakpoints or watchpoints.\n");
else
ui_out_message (uiout, 0,
- "No breakpoint or watchpoint number %d.\n",
- bnum);
+ "No breakpoint or watchpoint matching '%s'.\n",
+ args);
}
}
else
}
static void
-breakpoints_info (char *bnum_exp, int from_tty)
+breakpoints_info (char *args, int from_tty)
{
- int bnum = -1;
-
- if (bnum_exp)
- bnum = parse_and_eval_long (bnum_exp);
-
- breakpoint_1 (bnum, 0, NULL);
+ breakpoint_1 (args, 0, NULL);
default_collect_info ();
}
static void
-watchpoints_info (char *wpnum_exp, int from_tty)
+watchpoints_info (char *args, int from_tty)
{
- int wpnum = -1, num_printed;
-
- if (wpnum_exp)
- wpnum = parse_and_eval_long (wpnum_exp);
-
- num_printed = breakpoint_1 (wpnum, 0, is_watchpoint);
+ int num_printed = breakpoint_1 (args, 0, is_watchpoint);
if (num_printed == 0)
{
- if (wpnum == -1)
+ if (args == NULL || *args == '\0')
ui_out_message (uiout, 0, "No watchpoints.\n");
else
- ui_out_message (uiout, 0, "No watchpoint number %d.\n", wpnum);
+ ui_out_message (uiout, 0, "No watchpoint matching '%s'.\n", args);
}
}
static void
-maintenance_info_breakpoints (char *bnum_exp, int from_tty)
+maintenance_info_breakpoints (char *args, int from_tty)
{
- int bnum = -1;
-
- if (bnum_exp)
- bnum = parse_and_eval_long (bnum_exp);
-
- breakpoint_1 (bnum, 1, NULL);
+ breakpoint_1 (args, 1, NULL);
default_collect_info ();
}
breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr,
int bnum, int have_bnum)
{
- char astr1[40];
- char astr2[40];
+ /* The longest string possibly returned by hex_string_custom
+ is 50 chars. These must be at least that big for safety. */
+ char astr1[64];
+ char astr2[64];
strcpy (astr1, hex_string_custom ((unsigned long) from_addr, 8));
strcpy (astr2, hex_string_custom ((unsigned long) to_addr, 8));
return b;
}
+/* Remove JIT code registration and unregistration breakpoint(s). */
+
+void
+remove_jit_event_breakpoints (void)
+{
+ struct breakpoint *b, *b_tmp;
+
+ ALL_BREAKPOINTS_SAFE (b, b_tmp)
+ if (b->type == bp_jit_event
+ && b->loc->pspace == current_program_space)
+ delete_breakpoint (b);
+}
+
void
remove_solib_event_breakpoints (void)
{
char *marker_str;
int i;
- while (*p == ' ' || *p == '\t')
- p++;
+ p = skip_spaces (p);
- endp = p;
- while (*endp != ' ' && *endp != '\t' && *endp != '\0')
- endp++;
+ endp = skip_to_space (p);
marker_str = savestring (p, endp - p);
b->static_trace_marker_id = marker_str;
}
}
-/* Parse ARG which is assumed to be a SAL specification possibly
+/* Parse ADDRESS 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. */
+ address strings. ADDRESS points to the end of the SAL.
+
+ The array and the line spec strings are allocated on the heap, it is
+ the caller's responsibility to free them. */
static void
parse_breakpoint_sals (char **address,
char *cond_start = NULL;
char *cond_end = NULL;
- while (*tok == ' ' || *tok == '\t')
- tok++;
-
- end_tok = tok;
+ tok = skip_spaces (tok);
- while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
- end_tok++;
+ end_tok = skip_to_space (tok);
toklen = end_tok - tok;
char *marker_str;
int i;
- while (*p == ' ' || *p == '\t')
- p++;
+ p = skip_spaces (p);
- endp = p;
- while (*endp != ' ' && *endp != '\t' && *endp != '\0')
- endp++;
+ endp = skip_to_space (p);
marker_str = savestring (p, endp - p);
old_chain = make_cleanup (xfree, marker_str);
default:
throw_exception (e);
}
+ break;
default:
if (!sals.nelts)
return 0;
else if (val != NULL)
release_value (val);
- tok = arg;
- while (*tok == ' ' || *tok == '\t')
- tok++;
- end_tok = tok;
-
- while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
- end_tok++;
+ tok = skip_spaces (arg);
+ end_tok = skip_to_space (tok);
toklen = end_tok - tok;
if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
&& (check_for_argument (&arg, "-location", sizeof ("-location") - 1)
|| check_for_argument (&arg, "-l", sizeof ("-l") - 1)))
{
- ep_skip_leading_whitespace (&arg);
+ arg = skip_spaces (arg);
just_location = 1;
}
do_cleanups (old_chain);
}
-static void
-ep_skip_leading_whitespace (char **s)
-{
- if ((s == NULL) || (*s == NULL))
- return;
- while (isspace (**s))
- *s += 1;
-}
-
/* This function attempts to parse an optional "if <cond>" clause
from the arg string. If one is not found, it returns NULL.
/* Skip any extra leading whitespace, and record the start of the
condition string. */
- ep_skip_leading_whitespace (arg);
+ *arg = skip_spaces (*arg);
cond_string = *arg;
/* Assume that the condition occupies the remainder of the arg
if (!arg)
arg = "";
- ep_skip_leading_whitespace (&arg);
+ arg = skip_spaces (arg);
/* The allowed syntax is:
catch [v]fork
if (!arg)
arg = "";
- ep_skip_leading_whitespace (&arg);
+ arg = skip_spaces (arg);
/* The allowed syntax is:
catch exec
if (!arg)
arg = "";
- ep_skip_leading_whitespace (&arg);
+ arg = skip_spaces (arg);
cond_string = ep_parse_optional_if_clause (&arg);
/* Checking if the feature if supported. */
if (gdbarch_get_syscall_number_p (gdbarch) == 0)
error (_("The feature 'catch syscall' is not supported on \
-this architeture yet."));
+this architecture yet."));
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
- ep_skip_leading_whitespace (&arg);
+ arg = skip_spaces (arg);
/* We need to do this first "dummy" translation in order
to get the syscall XML file loaded or, most important,
do_cleanups (old_chain);
- create_overlay_event_breakpoint ("_ovly_debug_event");
- create_longjmp_master_breakpoint ("longjmp");
- create_longjmp_master_breakpoint ("_longjmp");
- create_longjmp_master_breakpoint ("siglongjmp");
- create_longjmp_master_breakpoint ("_siglongjmp");
- create_std_terminate_master_breakpoint ("std::terminate()");
+ create_overlay_event_breakpoint ();
+ create_longjmp_master_breakpoint ();
+ create_std_terminate_master_breakpoint ();
create_exception_master_breakpoint ();
}
\f
error (_("No breakpoint number %d."), bptnum);
}
-void
-make_breakpoint_silent (struct breakpoint *b)
-{
- /* Silence the breakpoint. */
- b->silent = 1;
-}
-
/* Command to set ignore-count of breakpoint N to COUNT. */
static void
void *),
void *data)
{
- char *p = args;
- char *p1;
int num;
struct breakpoint *b, *tmp;
int match;
+ struct get_number_or_range_state state;
- if (p == 0)
+ if (args == 0)
error_no_arg (_("one or more breakpoint numbers"));
- while (*p)
+ init_number_or_range (&state, args);
+
+ while (!state.finished)
{
+ char *p = state.string;
+
match = 0;
- p1 = p;
- num = get_number_or_range (&p1);
+ num = get_number_or_range (&state);
if (num == 0)
{
warning (_("bad breakpoint number at or near '%s'"), p);
if (match == 0)
printf_unfiltered (_("No breakpoint number %d.\n"), num);
}
- p = p1;
}
}
*dot = '\0';
p1 = number;
- bp_num = get_number_or_range (&p1);
+ bp_num = get_number (&p1);
if (bp_num == 0)
error (_("Bad breakpoint number '%s'"), number);
error (_("Bad breakpoint number '%s'"), number);
p1 = dot+1;
- loc_num = get_number_or_range (&p1);
+ loc_num = get_number (&p1);
if (loc_num == 0)
error (_("Bad breakpoint location number '%s'"), number);
case bp_none:
warning (_("attempted to disable apparently deleted breakpoint #%d?"),
bpt->number);
- continue;
+ break;
case bp_breakpoint:
case bp_tracepoint:
case bp_fast_tracepoint:
case bp_read_watchpoint:
case bp_access_watchpoint:
disable_breakpoint (bpt);
+ break;
default:
- continue;
+ break;
}
else if (strchr (args, '.'))
{
case bp_none:
warning (_("attempted to enable apparently deleted breakpoint #%d?"),
bpt->number);
- continue;
+ break;
case bp_breakpoint:
case bp_tracepoint:
case bp_fast_tracepoint:
case bp_read_watchpoint:
case bp_access_watchpoint:
enable_breakpoint (bpt);
+ break;
default:
- continue;
+ break;
}
else if (strchr (args, '.'))
{
char *text, char *word)
{
const char **list = get_syscall_names ();
+ char **retlist
+ = (list == NULL) ? NULL : complete_on_enum (list, text, word);
- return (list == NULL) ? NULL : complete_on_enum (list, text, word);
+ xfree (list);
+ return retlist;
}
/* Tracepoint-specific operations. */
omitted. */
static void
-tracepoints_info (char *tpnum_exp, int from_tty)
+tracepoints_info (char *args, int from_tty)
{
- int tpnum = -1, num_printed;
-
- if (tpnum_exp)
- tpnum = parse_and_eval_long (tpnum_exp);
+ int num_printed;
- num_printed = breakpoint_1 (tpnum, 0, is_tracepoint);
+ num_printed = breakpoint_1 (args, 0, is_tracepoint);
if (num_printed == 0)
{
- if (tpnum == -1)
+ if (args == NULL || *args == '\0')
ui_out_message (uiout, 0, "No tracepoints.\n");
else
- ui_out_message (uiout, 0, "No tracepoint number %d.\n", tpnum);
+ ui_out_message (uiout, 0, "No tracepoint matching '%s'.\n", args);
}
default_collect_info ();
map_breakpoint_numbers (arg, do_delete_breakpoint, NULL);
}
+/* Helper function for trace_pass_command. */
+
+static void
+trace_pass_set_count (struct breakpoint *bp, int count, int from_tty)
+{
+ bp->pass_count = count;
+ observer_notify_tracepoint_modified (bp->number);
+ if (from_tty)
+ printf_filtered (_("Setting tracepoint %d's passcount to %d\n"),
+ bp->number, count);
+}
+
/* Set passcount for tracepoint.
First command argument is passcount, second is tracepoint number.
static void
trace_pass_command (char *args, int from_tty)
{
- struct breakpoint *t1 = (struct breakpoint *) -1, *t2;
+ struct breakpoint *t1;
unsigned int count;
- int all = 0;
if (args == 0 || *args == 0)
error (_("passcount command requires an "
if (*args && strncasecmp (args, "all", 3) == 0)
{
args += 3; /* Skip special argument "all". */
- all = 1;
if (*args)
error (_("Junk at end of arguments."));
- }
- else
- t1 = get_tracepoint_by_number (&args, 1, 1);
- do
+ ALL_TRACEPOINTS (t1)
+ {
+ trace_pass_set_count (t1, count, from_tty);
+ }
+ }
+ else if (*args == '\0')
{
+ t1 = get_tracepoint_by_number (&args, NULL, 1);
if (t1)
+ trace_pass_set_count (t1, count, from_tty);
+ }
+ else
+ {
+ struct get_number_or_range_state state;
+
+ init_number_or_range (&state, args);
+ while (!state.finished)
{
- ALL_TRACEPOINTS (t2)
- if (t1 == (struct breakpoint *) -1 || t1 == t2)
- {
- t2->pass_count = count;
- observer_notify_tracepoint_modified (t2->number);
- if (from_tty)
- printf_filtered (_("Setting tracepoint %d's "
- "passcount to %d\n"),
- t2->number, count);
- }
- if (! all && *args)
- t1 = get_tracepoint_by_number (&args, 1, 0);
+ t1 = get_tracepoint_by_number (&args, &state, 1);
+ if (t1)
+ trace_pass_set_count (t1, count, from_tty);
}
}
- while (*args);
}
struct breakpoint *
}
/* Utility: parse a tracepoint number and look it up in the list.
- If MULTI_P is true, there might be a range of tracepoints in ARG.
- if OPTIONAL_P is true, then if the argument is missing, the most
+ If STATE is not NULL, use, get_number_or_range_state and ignore ARG.
+ If OPTIONAL_P is true, then if the argument is missing, the most
recent tracepoint (tracepoint_count) is returned. */
struct breakpoint *
-get_tracepoint_by_number (char **arg, int multi_p, int optional_p)
+get_tracepoint_by_number (char **arg,
+ struct get_number_or_range_state *state,
+ int optional_p)
{
extern int tracepoint_count;
struct breakpoint *t;
int tpnum;
char *instring = arg == NULL ? NULL : *arg;
- if (arg == NULL || *arg == NULL || ! **arg)
+ if (state)
+ {
+ gdb_assert (!state->finished);
+ tpnum = get_number_or_range (state);
+ }
+ else if (arg == NULL || *arg == NULL || ! **arg)
{
if (optional_p)
tpnum = tracepoint_count;
error_no_arg (_("tracepoint number"));
}
else
- tpnum = multi_p ? get_number_or_range (arg) : get_number (arg);
+ tpnum = get_number (arg);
if (tpnum <= 0)
{
return t;
}
- /* FIXME: if we are in the middle of a range we don't want to give
- a message. The current interface to get_number_or_range doesn't
- allow us to discover this. */
printf_unfiltered ("No tracepoint number %d.\n", tpnum);
return NULL;
}
/* Create a vector of all tracepoints. */
VEC(breakpoint_p) *
-all_tracepoints ()
+all_tracepoints (void)
{
VEC(breakpoint_p) *tp_vec = 0;
struct breakpoint *tp;
observer_attach_inferior_exit (clear_syscall_counts);
observer_attach_memory_changed (invalidate_bp_value_on_memory_change);
+ breakpoint_objfile_key = register_objfile_data ();
+
breakpoint_chain = 0;
/* Don't bother to call set_breakpoint_count. $bpnum isn't useful
before a breakpoint is set. */
set_cmd_completer (c, location_completer);
c = add_com ("hbreak", class_breakpoint, hbreak_command, _("\
-Set a hardware assisted breakpoint.\n\
+Set a hardware assisted breakpoint.\n\
Like \"break\" except the breakpoint requires hardware support,\n\
some target hardware may not have this support.\n\
\n"
}
add_info ("breakpoints", breakpoints_info, _("\
-Status of user-settable breakpoints, or breakpoint number NUMBER.\n\
+Status of specified breakpoints (all user-settable breakpoints if no argument).\n\
The \"Type\" column indicates one of:\n\
\tbreakpoint - normal breakpoint\n\
\twatchpoint - watchpoint\n\
set_cmd_completer (c, expression_completer);
add_info ("watchpoints", watchpoints_info, _("\
-Status of watchpoints, or watchpoint number NUMBER."));
-
-
+Status of specified watchpoints (all watchpoints if no argument)."));
/* XXX: cagney/2005-02-23: This should be a boolean, and should
respond to changes - contrary to the description. */
set_cmd_completer (c, location_completer);
add_info ("tracepoints", tracepoints_info, _("\
-Status of tracepoints, or tracepoint number NUMBER.\n\
+Status of specified tracepoints (all tracepoints if no argument).\n\
Convenience variable \"$tpnum\" contains the number of the\n\
last tracepoint set."));