X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fbreakpoint.c;h=3b1367bb4659e5bae9a85161e3fcd7a30f560eeb;hb=fcf250e2bae3e6053af11b2e42bd59dcd3762ab3;hp=c9e149b656b0ba7dcf0d62db500d73910445b855;hpb=3c3fe74c6fe58e9035ff5a045d9497321d3a0d31;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index c9e149b656..3b1367bb46 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -39,6 +39,7 @@ #include "language.h" #include "gdb_string.h" #include "demangle.h" +#include "filenames.h" #include "annotate.h" #include "symfile.h" #include "objfiles.h" @@ -62,6 +63,7 @@ #include "jit.h" #include "xml-syscall.h" #include "parser-defs.h" +#include "cli/cli-utils.h" /* readline include files */ #include "readline/readline.h" @@ -71,6 +73,7 @@ #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) @@ -128,11 +131,16 @@ static int breakpoint_address_match (struct address_space *aspace1, static int watchpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2); +static int breakpoint_location_address_match (struct bp_location *bl, + struct address_space *aspace, + CORE_ADDR addr); + static void breakpoints_info (char *, int); 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 *); @@ -142,8 +150,6 @@ static void commands_command (char *, int); static void condition_command (char *, int); -static int get_number_trailer (char **, int); - typedef enum { mark_inserted, @@ -185,8 +191,6 @@ static void catch_exception_command_1 (enum exception_event_kind ex_event, 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 *, @@ -553,159 +557,6 @@ int default_breakpoint_line; struct program_space *default_breakpoint_pspace; -/* *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"). - - 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 == '$') - { - /* 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 - , 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 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 . */ - -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 ( - ). - 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. */ @@ -798,6 +649,14 @@ condition_command (char *arg, int from_tty) 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; } @@ -1304,6 +1163,25 @@ watchpoint_in_thread_scope (struct breakpoint *b) && !is_executing (inferior_ptid))); } +/* Set watchpoint B to disp_del_at_next_stop, even including its possible + associated bp_watchpoint_scope breakpoint. */ + +static void +watchpoint_del_at_next_stop (struct breakpoint *b) +{ + gdb_assert (is_watchpoint (b)); + + if (b->related_breakpoint != b) + { + gdb_assert (b->related_breakpoint->type == bp_watchpoint_scope); + gdb_assert (b->related_breakpoint->related_breakpoint == b); + b->related_breakpoint->disposition = disp_del_at_next_stop; + b->related_breakpoint->related_breakpoint = b->related_breakpoint; + b->related_breakpoint = b; + } + b->disposition = disp_del_at_next_stop; +} + /* Assuming that B is a watchpoint: - Reparse watchpoint expression, if REPARSE is non-zero - Evaluate expression and store the result in B->val @@ -1363,17 +1241,14 @@ update_watchpoint (struct breakpoint *b, int reparse) struct frame_id saved_frame_id; int frame_saved; + gdb_assert (is_watchpoint (b)); + /* If this is a local watchpoint, we only want to check if the watchpoint frame is in scope if the current thread is the thread that was used to create the watchpoint. */ if (!watchpoint_in_thread_scope (b)) return; - /* 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 (b->disposition == disp_del_at_next_stop) return; @@ -1384,7 +1259,15 @@ update_watchpoint (struct breakpoint *b, int reparse) 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. */ @@ -1400,6 +1283,11 @@ update_watchpoint (struct breakpoint *b, int reparse) 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; @@ -1590,13 +1478,7 @@ update_watchpoint (struct breakpoint *b, int reparse) Watchpoint %d deleted because the program has left the block\n\ in which its expression is valid.\n"), b->number); - if (b->related_breakpoint) - { - b->related_breakpoint->disposition = disp_del_at_next_stop; - b->related_breakpoint->related_breakpoint = NULL; - b->related_breakpoint= NULL; - } - b->disposition = disp_del_at_next_stop; + watchpoint_del_at_next_stop (b); } /* Restore the selected frame. */ @@ -1659,6 +1541,7 @@ insert_bp_location (struct bp_location *bl, memset (&bl->target_info, 0, sizeof (bl->target_info)); bl->target_info.placed_address = bl->address; bl->target_info.placed_address_space = bl->pspace->aspace; + bl->target_info.length = bl->length; if (bl->loc_type == bp_loc_software_breakpoint || bl->loc_type == bp_loc_hardware_breakpoint) @@ -2136,7 +2019,7 @@ reattach_breakpoints (int pid) 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; @@ -2150,6 +2033,7 @@ reattach_breakpoints (int pid) inferior_ptid = tp->ptid; + tmp_error_stream = mem_fileopen (); make_cleanup_ui_file_delete (tmp_error_stream); ALL_BP_LOCATIONS (bl, blp_tmp) @@ -2920,11 +2804,10 @@ breakpoint_here_p (struct address_space *aspace, CORE_ADDR pc) && bl->loc_type != bp_loc_hardware_breakpoint) continue; - /* ALL_BP_LOCATIONS bp_location has bl->OWNER always non-NULL. */ + /* ALL_BP_LOCATIONS bp_location has BL->OWNER always non-NULL. */ if ((breakpoint_enabled (bl->owner) || bl->owner->enable_state == bp_permanent) - && breakpoint_address_match (bl->pspace->aspace, bl->address, - aspace, pc)) + && breakpoint_location_address_match (bl, aspace, pc)) { if (overlay_debugging && section_is_overlay (bl->section) @@ -2949,8 +2832,7 @@ moribund_breakpoint_here_p (struct address_space *aspace, CORE_ADDR pc) int ix; for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix) - if (breakpoint_address_match (loc->pspace->aspace, loc->address, - aspace, pc)) + if (breakpoint_location_address_match (loc, aspace, pc)) return 1; return 0; @@ -2974,8 +2856,7 @@ regular_breakpoint_inserted_here_p (struct address_space *aspace, continue; if (bl->inserted - && breakpoint_address_match (bl->pspace->aspace, bl->address, - aspace, pc)) + && breakpoint_location_address_match (bl, aspace, pc)) { if (overlay_debugging && section_is_overlay (bl->section) @@ -3092,8 +2973,7 @@ breakpoint_thread_match (struct address_space *aspace, CORE_ADDR pc, && bl->owner->enable_state != bp_permanent) continue; - if (!breakpoint_address_match (bl->pspace->aspace, bl->address, - aspace, pc)) + if (!breakpoint_location_address_match (bl, aspace, pc)) continue; if (bl->owner->thread != -1) @@ -3455,11 +3335,6 @@ print_it_typical (bpstat bs) 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; @@ -3630,6 +3505,8 @@ print_it_typical (bpstat bs) case bp_tracepoint: case bp_fast_tracepoint: case bp_jit_event: + case bp_gnu_ifunc_resolver: + case bp_gnu_ifunc_resolver_return: default: result = PRINT_UNKNOWN; break; @@ -3665,10 +3542,14 @@ print_bp_stop_message (bpstat bs) { 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); @@ -3851,6 +3732,8 @@ watchpoint_check (void *p) gdb_assert (bs->breakpoint_at != NULL); b = bs->breakpoint_at; + gdb_assert (is_watchpoint (b)); + /* If this is a local watchpoint, we only want to check if the watchpoint frame is in scope if the current thread is the thread that was used to create the watchpoint. */ @@ -3960,13 +3843,7 @@ watchpoint_check (void *p) " deleted because the program has left the block in\n\ which its expression is valid.\n"); - if (b->related_breakpoint) - { - b->related_breakpoint->disposition = disp_del_at_next_stop; - b->related_breakpoint->related_breakpoint = NULL; - b->related_breakpoint = NULL; - } - b->disposition = disp_del_at_next_stop; + watchpoint_del_at_next_stop (b); return WP_DELETED; } @@ -3984,6 +3861,9 @@ bpstat_check_location (const struct bp_location *bl, /* BL is from existing struct breakpoint. */ gdb_assert (b != NULL); + if (b->ops && b->ops->breakpoint_hit) + return b->ops->breakpoint_hit (bl, aspace, bp_addr); + /* By definition, the inferior does not report stops at tracepoints. */ if (is_tracepoint (b)) @@ -4012,7 +3892,7 @@ bpstat_check_location (const struct bp_location *bl, if (is_hardware_watchpoint (b) && b->watchpoint_triggered == watch_triggered_no) return 0; - + if (b->type == bp_hardware_breakpoint) { if (bl->address != bp_addr) @@ -4023,13 +3903,6 @@ bpstat_check_location (const struct bp_location *bl, return 0; } - if (b->type == bp_catchpoint) - { - gdb_assert (b->ops != NULL && b->ops->breakpoint_hit != NULL); - if (!b->ops->breakpoint_hit (b)) - return 0; - } - return 1; } @@ -4171,9 +4044,7 @@ bpstat_check_watchpoint (bpstat bs) case 0: /* Error from catch_errors. */ printf_filtered (_("Watchpoint %d deleted.\n"), b->number); - if (b->related_breakpoint) - b->related_breakpoint->disposition = disp_del_at_next_stop; - b->disposition = disp_del_at_next_stop; + watchpoint_del_at_next_stop (b); /* We've already printed what needs to be printed. */ bs->print_it = print_it_done; break; @@ -4217,6 +4088,11 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) 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 @@ -4379,15 +4255,14 @@ bpstat_stop_status (struct address_space *aspace, watchpoint as triggered so that we will handle the out-of-scope event. We'll get to the watchpoint next iteration. */ - if (b->type == bp_watchpoint_scope) + if (b->type == bp_watchpoint_scope && b->related_breakpoint != b) b->related_breakpoint->watchpoint_triggered = watch_triggered_yes; } } for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix) { - if (breakpoint_address_match (loc->pspace->aspace, loc->address, - aspace, bp_addr)) + if (breakpoint_location_address_match (loc, aspace, bp_addr)) { bs = bpstat_alloc (loc, &bs_link); /* For hits of moribund locations, we should just proceed. */ @@ -4501,7 +4376,7 @@ handle_jit_event (void) /* Decide what infrun needs to do with this bpstat. */ struct bpstat_what -bpstat_what (bpstat bs) +bpstat_what (bpstat bs_head) { struct bpstat_what retval; /* We need to defer calling `solib_add', as adding new symbols @@ -4509,12 +4384,13 @@ bpstat_what (bpstat bs) and hence may clear unprocessed entries in the BS chain. */ int shlib_event = 0; int jit_event = 0; + bpstat bs; retval.main_action = BPSTAT_WHAT_KEEP_CHECKING; retval.call_dummy = STOP_NONE; retval.is_longjmp = 0; - for (; bs != NULL; bs = bs->next) + for (bs = bs_head; bs != NULL; bs = bs->next) { /* Extract this BS's action. After processing each BS, we check if its action overrides all we've seem so far. */ @@ -4644,6 +4520,16 @@ bpstat_what (bpstat bs) out already. */ internal_error (__FILE__, __LINE__, _("bpstat_what: tracepoint encountered")); + break; + case bp_gnu_ifunc_resolver: + /* Step over it (and insert bp_gnu_ifunc_resolver_return). */ + this_action = BPSTAT_WHAT_SINGLE; + break; + case bp_gnu_ifunc_resolver_return: + /* The breakpoint will be removed, execution will restart from the + PC of the former breakpoint. */ + this_action = BPSTAT_WHAT_KEEP_CHECKING; + break; default: internal_error (__FILE__, __LINE__, _("bpstat_what: unhandled bptype %d"), (int) bptype); @@ -4652,6 +4538,9 @@ bpstat_what (bpstat bs) retval.main_action = max (retval.main_action, this_action); } + /* These operations may affect the bs->breakpoint_at state so they are + delayed after MAIN_ACTION is decided above. */ + if (shlib_event) { if (debug_infrun) @@ -4681,6 +4570,23 @@ bpstat_what (bpstat bs) handle_jit_event (); } + for (bs = bs_head; bs != NULL; bs = bs->next) + { + struct breakpoint *b = bs->breakpoint_at; + + if (b == NULL) + continue; + switch (b->type) + { + case bp_gnu_ifunc_resolver: + gnu_ifunc_resolver_stop (b); + break; + case bp_gnu_ifunc_resolver_return: + gnu_ifunc_resolver_return_stop (b); + break; + } + } + return retval; } @@ -4711,12 +4617,40 @@ bpstat_causes_stop (bpstat bs) +/* 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 (); @@ -4726,7 +4660,9 @@ static void print_breakpoint_location (struct breakpoint *b, if (loc != NULL) set_current_program_space (loc->pspace); - if (b->source_file && loc) + if (b->display_canonical) + ui_out_field_string (uiout, "what", b->addr_string); + else if (b->source_file && loc) { struct symbol *sym = find_pc_sect_function (loc->address, loc->section); @@ -4735,8 +4671,9 @@ static void print_breakpoint_location (struct breakpoint *b, 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, ":"); @@ -4754,9 +4691,14 @@ static void print_breakpoint_location (struct breakpoint *b, } 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); @@ -4802,6 +4744,8 @@ bptype_string (enum bptype type) {bp_fast_tracepoint, "fast tracepoint"}, {bp_static_tracepoint, "static tracepoint"}, {bp_jit_event, "jit events"}, + {bp_gnu_ifunc_resolver, "STT_GNU_IFUNC resolver"}, + {bp_gnu_ifunc_resolver_return, "STT_GNU_IFUNC resolver return"}, }; if (((int) type >= (sizeof (bptypes) / sizeof (bptypes[0]))) @@ -4820,14 +4764,10 @@ print_one_breakpoint_location (struct breakpoint *b, struct bp_location *loc, int loc_number, struct bp_location **last_loc, - int print_address_bits, int allflag) { struct command_line *l; static char bpenables[] = "nynny"; - char wrap_indent[80]; - struct ui_stream *stb = ui_out_stream_new (uiout); - struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb); struct cleanup *bkpt_chain; int header_of_multiple = 0; @@ -4889,15 +4829,6 @@ print_one_breakpoint_location (struct breakpoint *b, /* 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, @@ -4949,6 +4880,8 @@ print_one_breakpoint_location (struct breakpoint *b, case bp_fast_tracepoint: case bp_static_tracepoint: case bp_jit_event: + case bp_gnu_ifunc_resolver: + case bp_gnu_ifunc_resolver_return: if (opts.addressprint) { annotate_field (4); @@ -4962,7 +4895,7 @@ print_one_breakpoint_location (struct breakpoint *b, } 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; @@ -5015,9 +4948,12 @@ print_one_breakpoint_location (struct breakpoint *b, ui_out_field_int (uiout, "task", b->task); } } - + ui_out_text (uiout, "\n"); - + + if (!part_of_multiple && b->ops && b->ops->print_one_detail) + b->ops->print_one_detail (b, uiout); + if (!part_of_multiple && b->static_trace_marker_id) { gdb_assert (b->type == bp_static_tracepoint); @@ -5118,17 +5054,14 @@ print_one_breakpoint_location (struct breakpoint *b, } 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 @@ -5150,8 +5083,7 @@ print_one_breakpoint (struct breakpoint *b, 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); } } } @@ -5195,9 +5127,7 @@ do_captured_breakpoint_query (struct ui_out *uiout, void *data) { 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; } } @@ -5230,7 +5160,8 @@ user_settable_breakpoint (const struct breakpoint *b) || b->type == bp_catchpoint || b->type == bp_hardware_breakpoint || is_tracepoint (b) - || is_watchpoint (b)); + || is_watchpoint (b) + || b->type == bp_gnu_ifunc_resolver); } /* Return true if this breakpoint was set by the user, false if it is @@ -5250,7 +5181,7 @@ user_breakpoint_p (struct breakpoint *b) breakpoints listed. */ static int -breakpoint_1 (int bnum, int allflag, +breakpoint_1 (char *args, int allflag, int (*filter) (const struct breakpoint *)) { struct breakpoint *b; @@ -5267,28 +5198,36 @@ breakpoint_1 (int bnum, int allflag, 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 @@ -5317,16 +5256,16 @@ breakpoint_1 (int bnum, int allflag, 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 */ @@ -5335,22 +5274,34 @@ breakpoint_1 (int bnum, int allflag, 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) @@ -5359,12 +5310,12 @@ breakpoint_1 (int bnum, int allflag, 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 @@ -5400,46 +5351,31 @@ default_collect_info (void) } 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 (); } @@ -5600,6 +5536,39 @@ breakpoint_address_match (struct address_space *aspace1, CORE_ADDR addr1, && addr1 == addr2); } +/* Returns true if {ASPACE2,ADDR2} falls within the range determined by + {ASPACE1,ADDR1,LEN1}. In most targets, this can only be true if ASPACE1 + matches ASPACE2. On targets that have global breakpoints, the address + space doesn't really matter. */ + +static int +breakpoint_address_match_range (struct address_space *aspace1, CORE_ADDR addr1, + int len1, struct address_space *aspace2, + CORE_ADDR addr2) +{ + return ((gdbarch_has_global_breakpoints (target_gdbarch) + || aspace1 == aspace2) + && addr2 >= addr1 && addr2 < addr1 + len1); +} + +/* Returns true if {ASPACE,ADDR} matches the breakpoint BL. BL may be + a ranged breakpoint. In most targets, a match happens only if ASPACE + matches the breakpoint's address space. On targets that have global + breakpoints, the address space doesn't really matter. */ + +static int +breakpoint_location_address_match (struct bp_location *bl, + struct address_space *aspace, + CORE_ADDR addr) +{ + return (breakpoint_address_match (bl->pspace->aspace, bl->address, + aspace, addr) + || (bl->length + && breakpoint_address_match_range (bl->pspace->aspace, + bl->address, bl->length, + aspace, addr))); +} + /* Assuming LOC1 and LOC2's types' have meaningful target addresses (breakpoint_address_is_meaningful), returns true if LOC1 and LOC2 represent the same location. */ @@ -5622,16 +5591,20 @@ breakpoint_locations_match (struct bp_location *loc1, else if (hw_point1) return watchpoint_locations_match (loc1, loc2); else - return breakpoint_address_match (loc1->pspace->aspace, loc1->address, - loc2->pspace->aspace, loc2->address); + /* We compare bp_location.length in order to cover ranged breakpoints. */ + return (breakpoint_address_match (loc1->pspace->aspace, loc1->address, + loc2->pspace->aspace, loc2->address) + && loc1->length == loc2->length); } static void 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)); @@ -5719,6 +5692,8 @@ allocate_bp_location (struct breakpoint *bpt) case bp_longjmp_master: case bp_std_terminate_master: case bp_exception_master: + case bp_gnu_ifunc_resolver: + case bp_gnu_ifunc_resolver_return: loc->loc_type = bp_loc_software_breakpoint; break; case bp_hardware_breakpoint: @@ -5808,6 +5783,7 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, b->ops = NULL; b->condition_not_parsed = 0; b->py_bp_object = NULL; + b->related_breakpoint = b; /* Add this breakpoint to the end of the chain so that a list of breakpoints will come out in order of increasing numbers. */ @@ -5824,9 +5800,12 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, return b; } -/* Initialize loc->function_name. */ +/* Initialize loc->function_name. EXPLICIT_LOC says no indirect function + resolutions should be made as the user specified the location explicitly + enough. */ + static void -set_breakpoint_location_function (struct bp_location *loc) +set_breakpoint_location_function (struct bp_location *loc, int explicit_loc) { gdb_assert (loc->owner != NULL); @@ -5834,8 +5813,33 @@ set_breakpoint_location_function (struct bp_location *loc) || loc->owner->type == bp_hardware_breakpoint || is_tracepoint (loc->owner)) { - find_pc_partial_function (loc->address, &(loc->function_name), - NULL, NULL); + int is_gnu_ifunc; + + find_pc_partial_function_gnu_ifunc (loc->address, &loc->function_name, + NULL, NULL, &is_gnu_ifunc); + + if (is_gnu_ifunc && !explicit_loc) + { + struct breakpoint *b = loc->owner; + + gdb_assert (loc->pspace == current_program_space); + if (gnu_ifunc_resolve_name (loc->function_name, + &loc->requested_address)) + { + /* Recalculate ADDRESS based on new REQUESTED_ADDRESS. */ + loc->address = adjust_breakpoint_address (loc->gdbarch, + loc->requested_address, + b->type); + } + else if (b->type == bp_breakpoint && b->loc == loc + && loc->next == NULL && b->related_breakpoint == b) + { + /* Create only the whole new breakpoint of this type but do not + mess more complicated breakpoints with multiple locations. */ + b->type = bp_gnu_ifunc_resolver; + } + } + if (loc->function_name) loc->function_name = xstrdup (loc->function_name); } @@ -5910,7 +5914,8 @@ set_raw_breakpoint (struct gdbarch *gdbarch, b->loc->section = sal.section; b->line_number = sal.line; - set_breakpoint_location_function (b->loc); + set_breakpoint_location_function (b->loc, + sal.explicit_pc || sal.explicit_line); breakpoints_changed (); @@ -6065,7 +6070,7 @@ struct captured_parse_breakpoint_args { char **arg_p; struct symtabs_and_lines *sals_p; - char ***addr_string_p; + struct linespec_result *canonical_p; int *not_found_ptr; }; @@ -6230,9 +6235,10 @@ remove_catch_fork (struct bp_location *bl) catchpoints. */ static int -breakpoint_hit_catch_fork (struct breakpoint *b) +breakpoint_hit_catch_fork (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) { - return inferior_has_forked (inferior_ptid, &b->forked_inferior_pid); + return inferior_has_forked (inferior_ptid, &bl->owner->forked_inferior_pid); } /* Implement the "print_it" breakpoint_ops method for fork @@ -6301,6 +6307,7 @@ static struct breakpoint_ops catch_fork_breakpoint_ops = NULL, /* resources_needed */ print_it_catch_fork, print_one_catch_fork, + NULL, /* print_one_detail */ print_mention_catch_fork, print_recreate_catch_fork }; @@ -6327,9 +6334,10 @@ remove_catch_vfork (struct bp_location *bl) catchpoints. */ static int -breakpoint_hit_catch_vfork (struct breakpoint *b) +breakpoint_hit_catch_vfork (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) { - return inferior_has_vforked (inferior_ptid, &b->forked_inferior_pid); + return inferior_has_vforked (inferior_ptid, &bl->owner->forked_inferior_pid); } /* Implement the "print_it" breakpoint_ops method for vfork @@ -6397,6 +6405,7 @@ static struct breakpoint_ops catch_vfork_breakpoint_ops = NULL, /* resources_needed */ print_it_catch_vfork, print_one_catch_vfork, + NULL, /* print_one_detail */ print_mention_catch_vfork, print_recreate_catch_vfork }; @@ -6486,12 +6495,14 @@ remove_catch_syscall (struct bp_location *bl) catchpoints. */ static int -breakpoint_hit_catch_syscall (struct breakpoint *b) +breakpoint_hit_catch_syscall (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) { /* We must check if we are catching specific syscalls in this breakpoint. If we are, then we must guarantee that the called syscall is the same syscall we are catching. */ int syscall_number = 0; + const struct breakpoint *b = bl->owner; if (!inferior_has_called_syscall (inferior_ptid, &syscall_number)) return 0; @@ -6560,7 +6571,7 @@ print_it_catch_syscall (struct breakpoint *b) static void print_one_catch_syscall (struct breakpoint *b, - struct bp_location **last_loc) + struct bp_location **last_loc) { struct value_print_options opts; @@ -6681,6 +6692,7 @@ static struct breakpoint_ops catch_syscall_breakpoint_ops = NULL, /* resources_needed */ print_it_catch_syscall, print_one_catch_syscall, + NULL, /* print_one_detail */ print_mention_catch_syscall, print_recreate_catch_syscall }; @@ -6776,9 +6788,10 @@ remove_catch_exec (struct bp_location *bl) } static int -breakpoint_hit_catch_exec (struct breakpoint *b) +breakpoint_hit_catch_exec (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) { - return inferior_has_execd (inferior_ptid, &b->exec_pathname); + return inferior_has_execd (inferior_ptid, &bl->owner->exec_pathname); } static enum print_stop_action @@ -6835,6 +6848,7 @@ static struct breakpoint_ops catch_exec_breakpoint_ops = NULL, /* resources_needed */ print_it_catch_exec, print_one_catch_exec, + NULL, /* print_one_detail */ print_mention_catch_exec, print_recreate_catch_exec }; @@ -6858,13 +6872,22 @@ create_syscall_event_catchpoint (int tempflag, VEC(int) *filter, static int hw_breakpoint_used_count (void) { - struct breakpoint *b; int i = 0; + struct breakpoint *b; + struct bp_location *bl; ALL_BREAKPOINTS (b) { if (b->type == bp_hardware_breakpoint && breakpoint_enabled (b)) - i++; + for (bl = b->loc; bl; bl = bl->next) + { + /* Special types of hardware breakpoints may use more than + one register. */ + if (b->ops && b->ops->resources_needed) + i += b->ops->resources_needed (bl); + else + i++; + } } return i; @@ -7027,7 +7050,7 @@ clone_momentary_breakpoint (struct breakpoint *orig) copy = set_raw_breakpoint_without_location (orig->gdbarch, orig->type); copy->loc = allocate_bp_location (copy); - set_breakpoint_location_function (copy->loc); + set_breakpoint_location_function (copy->loc, 1); copy->loc->gdbarch = orig->loc->gdbarch; copy->loc->requested_address = orig->loc->requested_address; @@ -7127,6 +7150,7 @@ mention (struct breakpoint *b) do_cleanups (ui_out_chain); break; case bp_breakpoint: + case bp_gnu_ifunc_resolver: if (ui_out_is_mi_like_p (uiout)) { say_where = 0; @@ -7137,6 +7161,8 @@ mention (struct breakpoint *b) else printf_filtered (_("Breakpoint")); printf_filtered (_(" %d"), b->number); + if (b->type == bp_gnu_ifunc_resolver) + printf_filtered (_(" at gnu-indirect-function resolver")); say_where = 1; break; case bp_hardware_breakpoint: @@ -7196,6 +7222,7 @@ mention (struct breakpoint *b) case bp_longjmp_master: case bp_std_terminate_master: case bp_exception_master: + case bp_gnu_ifunc_resolver_return: break; } @@ -7256,7 +7283,8 @@ add_location_to_breakpoint (struct breakpoint *b, gdb_assert (loc->pspace != NULL); loc->section = sal->section; - set_breakpoint_location_function (loc); + set_breakpoint_location_function (loc, + sal->explicit_pc || sal->explicit_line); return loc; } @@ -7315,7 +7343,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch, enum bptype type, enum bpdisp disposition, int thread, int task, int ignore_count, struct breakpoint_ops *ops, int from_tty, - int enabled, int internal) + int enabled, int internal, int display_canonical) { struct breakpoint *b = NULL; int i; @@ -7375,12 +7403,9 @@ create_breakpoint_sal (struct gdbarch *gdbarch, 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; @@ -7427,6 +7452,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch, } } + b->display_canonical = display_canonical; if (addr_string) b->addr_string = addr_string; else @@ -7593,7 +7619,8 @@ expand_line_sal_maybe (struct symtab_and_line sal) static void create_breakpoints_sal (struct gdbarch *gdbarch, - struct symtabs_and_lines sals, char **addr_string, + struct symtabs_and_lines sals, + struct linespec_result *canonical, char *cond_string, enum bptype type, enum bpdisp disposition, int thread, int task, int ignore_count, @@ -7607,10 +7634,11 @@ create_breakpoints_sal (struct gdbarch *gdbarch, struct symtabs_and_lines expanded = expand_line_sal_maybe (sals.sals[i]); - create_breakpoint_sal (gdbarch, expanded, addr_string[i], + create_breakpoint_sal (gdbarch, expanded, canonical->canonical[i], cond_string, type, disposition, thread, task, ignore_count, ops, - from_tty, enabled, internal); + from_tty, enabled, internal, + canonical->special_display); } } @@ -7625,12 +7653,11 @@ create_breakpoints_sal (struct gdbarch *gdbarch, static void parse_breakpoint_sals (char **address, struct symtabs_and_lines *sals, - char ***addr_string, + struct linespec_result *canonical, int *not_found_ptr) { char *addr_start = *address; - *addr_string = NULL; /* If no arg given, or if first arg is 'if ', use the default breakpoint. */ if ((*address) == NULL @@ -7679,15 +7706,15 @@ parse_breakpoint_sals (char **address, || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, addr_string, + default_breakpoint_line, canonical, not_found_ptr); else *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, - addr_string, not_found_ptr); + canonical, not_found_ptr); } /* 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 (sals->nelts > 0 && canonical->canonical == NULL) + canonical->canonical = xcalloc (sals->nelts, sizeof (char **)); if (addr_start != (*address)) { int i; @@ -7695,9 +7722,9 @@ parse_breakpoint_sals (char **address, for (i = 0; i < sals->nelts; i++) { /* Add the string if not present. */ - if ((*addr_string)[i] == NULL) - (*addr_string)[i] = savestring (addr_start, - (*address) - addr_start); + if (canonical->canonical[i] == NULL) + canonical->canonical[i] = savestring (addr_start, + (*address) - addr_start); } } } @@ -7752,7 +7779,7 @@ do_captured_parse_breakpoint (struct ui_out *ui, void *data) { struct captured_parse_breakpoint_args *args = data; - parse_breakpoint_sals (args->arg_p, args->sals_p, args->addr_string_p, + parse_breakpoint_sals (args->arg_p, args->sals_p, args->canonical_p, args->not_found_ptr); } @@ -7775,13 +7802,9 @@ find_condition_and_thread (char *tok, CORE_ADDR pc, 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; @@ -7840,12 +7863,9 @@ decode_static_tracepoint_spec (char **arg_p) 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); @@ -7903,7 +7923,7 @@ create_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line pending_sal; char *copy_arg; char *addr_start = arg; - char **addr_string; + struct linespec_result canonical; struct cleanup *old_chain; struct cleanup *bkpt_chain = NULL; struct captured_parse_breakpoint_args parse_args; @@ -7915,11 +7935,11 @@ create_breakpoint (struct gdbarch *gdbarch, sals.sals = NULL; sals.nelts = 0; - addr_string = NULL; + init_linespec_result (&canonical); parse_args.arg_p = &arg; parse_args.sals_p = &sals; - parse_args.addr_string_p = &addr_string; + parse_args.canonical_p = &canonical; parse_args.not_found_ptr = ¬_found; if (type_wanted == bp_static_tracepoint && is_marker_spec (arg)) @@ -7929,9 +7949,9 @@ create_breakpoint (struct gdbarch *gdbarch, sals = decode_static_tracepoint_spec (&arg); copy_arg = savestring (addr_start, arg - addr_start); - addr_string = xcalloc (sals.nelts, sizeof (char **)); + canonical.canonical = xcalloc (sals.nelts, sizeof (char **)); for (i = 0; i < sals.nelts; i++) - addr_string[i] = xstrdup (copy_arg); + canonical.canonical[i] = xstrdup (copy_arg); goto done; } @@ -7968,7 +7988,7 @@ create_breakpoint (struct gdbarch *gdbarch, breakpoint behavior is on and thus a pending breakpoint is defaulted on behalf of the user. */ copy_arg = xstrdup (addr_start); - addr_string = ©_arg; + canonical.canonical = ©_arg; sals.nelts = 1; sals.sals = &pending_sal; pending_sal.pc = 0; @@ -7977,6 +7997,7 @@ create_breakpoint (struct gdbarch *gdbarch, default: throw_exception (e); } + break; default: if (!sals.nelts) return 0; @@ -7992,8 +8013,8 @@ create_breakpoint (struct gdbarch *gdbarch, /* Make sure that all storage allocated to SALS gets freed. */ make_cleanup (xfree, sals.sals); - /* Cleanup the addr_string array but not its contents. */ - make_cleanup (xfree, addr_string); + /* Cleanup the canonical array but not its contents. */ + make_cleanup (xfree, canonical.canonical); } /* ----------------------------- SNIP ----------------------------- @@ -8002,12 +8023,12 @@ create_breakpoint (struct gdbarch *gdbarch, then the memory is not reclaimed. */ bkpt_chain = make_cleanup (null_cleanup, 0); - /* Mark the contents of the addr_string for cleanup. These go on + /* Mark the contents of the canonical for cleanup. These go on the bkpt_chain and only occur if the breakpoint create fails. */ for (i = 0; i < sals.nelts; i++) { - if (addr_string[i] != NULL) - make_cleanup (xfree, addr_string[i]); + if (canonical.canonical[i] != NULL) + make_cleanup (xfree, canonical.canonical[i]); } /* Resolve all line numbers to PC's and verify that the addresses @@ -8054,7 +8075,7 @@ create_breakpoint (struct gdbarch *gdbarch, expand multiple locations for each sal, given than SALS already should contain all sals for MARKER_ID. */ if (type_wanted == bp_static_tracepoint - && is_marker_spec (addr_string[0])) + && is_marker_spec (canonical.canonical[0])) { int i; @@ -8069,11 +8090,12 @@ create_breakpoint (struct gdbarch *gdbarch, expanded.sals[0] = sals.sals[i]; old_chain = make_cleanup (xfree, expanded.sals); - create_breakpoint_sal (gdbarch, expanded, addr_string[i], + create_breakpoint_sal (gdbarch, expanded, canonical.canonical[i], cond_string, type_wanted, tempflag ? disp_del : disp_donttouch, thread, task, ignore_count, ops, - from_tty, enabled, internal); + from_tty, enabled, internal, + canonical.special_display); do_cleanups (old_chain); @@ -8094,7 +8116,7 @@ create_breakpoint (struct gdbarch *gdbarch, } } else - create_breakpoints_sal (gdbarch, sals, addr_string, cond_string, + create_breakpoints_sal (gdbarch, sals, &canonical, cond_string, type_wanted, tempflag ? disp_del : disp_donttouch, thread, task, ignore_count, ops, from_tty, @@ -8109,7 +8131,7 @@ create_breakpoint (struct gdbarch *gdbarch, b = set_raw_breakpoint_without_location (gdbarch, type_wanted); set_breakpoint_number (internal, b); b->thread = -1; - b->addr_string = addr_string[0]; + b->addr_string = canonical.canonical[0]; b->cond_string = NULL; b->ignore_count = ignore_count; b->disposition = tempflag ? disp_del : disp_donttouch; @@ -8333,6 +8355,309 @@ stopat_command (char *arg, int from_tty) break_command_1 (arg, 0, from_tty); } +/* Implement the "breakpoint_hit" breakpoint_ops method for + ranged breakpoints. */ + +static int +breakpoint_hit_ranged_breakpoint (const struct bp_location *bl, + struct address_space *aspace, + CORE_ADDR bp_addr) +{ + return breakpoint_address_match_range (bl->pspace->aspace, bl->address, + bl->length, aspace, bp_addr); +} + +/* Implement the "resources_needed" breakpoint_ops method for + ranged breakpoints. */ + +static int +resources_needed_ranged_breakpoint (const struct bp_location *bl) +{ + return target_ranged_break_num_registers (); +} + +/* Implement the "print_it" breakpoint_ops method for + ranged breakpoints. */ + +static enum print_stop_action +print_it_ranged_breakpoint (struct breakpoint *b) +{ + struct bp_location *bl = b->loc; + + gdb_assert (b->type == bp_hardware_breakpoint); + + /* Ranged breakpoints have only one location. */ + gdb_assert (bl && bl->next == NULL); + + annotate_breakpoint (b->number); + if (b->disposition == disp_del) + ui_out_text (uiout, "\nTemporary ranged breakpoint "); + else + ui_out_text (uiout, "\nRanged breakpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, ", "); + + return PRINT_SRC_AND_LOC; +} + +/* Implement the "print_one" breakpoint_ops method for + ranged breakpoints. */ + +static void +print_one_ranged_breakpoint (struct breakpoint *b, + struct bp_location **last_loc) +{ + struct bp_location *bl = b->loc; + struct value_print_options opts; + + /* Ranged breakpoints have only one location. */ + gdb_assert (bl && bl->next == NULL); + + get_user_print_options (&opts); + + if (opts.addressprint) + /* We don't print the address range here, it will be printed later + by print_one_detail_ranged_breakpoint. */ + ui_out_field_skip (uiout, "addr"); + annotate_field (5); + print_breakpoint_location (b, bl); + *last_loc = bl; +} + +/* Implement the "print_one_detail" breakpoint_ops method for + ranged breakpoints. */ + +static void +print_one_detail_ranged_breakpoint (const struct breakpoint *b, + struct ui_out *uiout) +{ + CORE_ADDR address_start, address_end; + struct bp_location *bl = b->loc; + struct ui_stream *stb = ui_out_stream_new (uiout); + struct cleanup *cleanup = make_cleanup_ui_out_stream_delete (stb); + + gdb_assert (bl); + + address_start = bl->address; + address_end = address_start + bl->length - 1; + + ui_out_text (uiout, "\taddress range: "); + fprintf_unfiltered (stb->stream, "[%s, %s]", + print_core_address (bl->gdbarch, address_start), + print_core_address (bl->gdbarch, address_end)); + ui_out_field_stream (uiout, "addr", stb); + ui_out_text (uiout, "\n"); + + do_cleanups (cleanup); +} + +/* Implement the "print_mention" breakpoint_ops method for + ranged breakpoints. */ + +static void +print_mention_ranged_breakpoint (struct breakpoint *b) +{ + struct bp_location *bl = b->loc; + + gdb_assert (bl); + gdb_assert (b->type == bp_hardware_breakpoint); + + if (ui_out_is_mi_like_p (uiout)) + return; + + printf_filtered (_("Hardware assisted ranged breakpoint %d from %s to %s."), + b->number, paddress (bl->gdbarch, bl->address), + paddress (bl->gdbarch, bl->address + bl->length - 1)); +} + +/* Implement the "print_recreate" breakpoint_ops method for + ranged breakpoints. */ + +static void +print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp) +{ + fprintf_unfiltered (fp, "break-range %s, %s", b->addr_string, + b->addr_string_range_end); +} + +/* The breakpoint_ops structure to be used in ranged breakpoints. */ + +static struct breakpoint_ops ranged_breakpoint_ops = +{ + NULL, /* insert */ + NULL, /* remove */ + breakpoint_hit_ranged_breakpoint, + resources_needed_ranged_breakpoint, + print_it_ranged_breakpoint, + print_one_ranged_breakpoint, + print_one_detail_ranged_breakpoint, + print_mention_ranged_breakpoint, + print_recreate_ranged_breakpoint +}; + +/* Find the address where the end of the breakpoint range should be + placed, given the SAL of the end of the range. This is so that if + the user provides a line number, the end of the range is set to the + last instruction of the given line. */ + +static CORE_ADDR +find_breakpoint_range_end (struct symtab_and_line sal) +{ + CORE_ADDR end; + + /* If the user provided a PC value, use it. Otherwise, + find the address of the end of the given location. */ + if (sal.explicit_pc) + end = sal.pc; + else + { + int ret; + CORE_ADDR start; + + ret = find_line_pc_range (sal, &start, &end); + if (!ret) + error (_("Could not find location of the end of the range.")); + + /* find_line_pc_range returns the start of the next line. */ + end--; + } + + return end; +} + +/* Implement the "break-range" CLI command. */ + +static void +break_range_command (char *arg, int from_tty) +{ + char *arg_start, *addr_string_start, *addr_string_end; + struct linespec_result canonical_start, canonical_end; + int bp_count, can_use_bp, length; + CORE_ADDR end; + struct breakpoint *b; + struct symtab_and_line sal_start, sal_end; + struct symtabs_and_lines sals_start, sals_end; + struct cleanup *cleanup_bkpt; + + /* We don't support software ranged breakpoints. */ + if (target_ranged_break_num_registers () < 0) + error (_("This target does not support hardware ranged breakpoints.")); + + bp_count = hw_breakpoint_used_count (); + bp_count += target_ranged_break_num_registers (); + can_use_bp = target_can_use_hardware_watchpoint (bp_hardware_breakpoint, + bp_count, 0); + if (can_use_bp < 0) + error (_("Hardware breakpoints used exceeds limit.")); + + if (arg == NULL || arg[0] == '\0') + error(_("No address range specified.")); + + sals_start.sals = NULL; + sals_start.nelts = 0; + init_linespec_result (&canonical_start); + + while (*arg == ' ' || *arg == '\t') + arg++; + + parse_breakpoint_sals (&arg, &sals_start, &canonical_start, NULL); + + sal_start = sals_start.sals[0]; + addr_string_start = canonical_start.canonical[0]; + cleanup_bkpt = make_cleanup (xfree, addr_string_start); + xfree (sals_start.sals); + xfree (canonical_start.canonical); + + if (arg[0] != ',') + error (_("Too few arguments.")); + else if (sals_start.nelts == 0) + error (_("Could not find location of the beginning of the range.")); + else if (sals_start.nelts != 1) + error (_("Cannot create a ranged breakpoint with multiple locations.")); + + resolve_sal_pc (&sal_start); + + arg++; /* Skip the comma. */ + while (*arg == ' ' || *arg == '\t') + arg++; + + /* Parse the end location. */ + + sals_end.sals = NULL; + sals_end.nelts = 0; + init_linespec_result (&canonical_end); + arg_start = arg; + + /* We call decode_line_1 directly here instead of using + parse_breakpoint_sals because we need to specify the start location's + symtab and line as the default symtab and line for the end of the + range. This makes it possible to have ranges like "foo.c:27, +14", + where +14 means 14 lines from the start location. */ + sals_end = decode_line_1 (&arg, 1, sal_start.symtab, sal_start.line, + &canonical_end, NULL); + + /* canonical_end can be NULL if it was of the form "*0xdeadbeef". */ + if (canonical_end.canonical == NULL) + canonical_end.canonical = xcalloc (1, sizeof (char **)); + /* Add the string if not present. */ + if (arg_start != arg && canonical_end.canonical[0] == NULL) + canonical_end.canonical[0] = savestring (arg_start, arg - arg_start); + + sal_end = sals_end.sals[0]; + addr_string_end = canonical_end.canonical[0]; + make_cleanup (xfree, addr_string_end); + xfree (sals_end.sals); + xfree (canonical_end.canonical); + + if (sals_end.nelts == 0) + error (_("Could not find location of the end of the range.")); + else if (sals_end.nelts != 1) + error (_("Cannot create a ranged breakpoint with multiple locations.")); + + resolve_sal_pc (&sal_end); + + end = find_breakpoint_range_end (sal_end); + if (sal_start.pc > end) + error (_("Invalid address range, end preceeds start.")); + + length = end - sal_start.pc + 1; + if (length < 0) + /* Length overflowed. */ + error (_("Address range too large.")); + else if (length == 1) + { + /* This range is simple enough to be handled by + the `hbreak' command. */ + hbreak_command (addr_string_start, 1); + + do_cleanups (cleanup_bkpt); + + return; + } + + /* Now set up the breakpoint. */ + b = set_raw_breakpoint (get_current_arch (), sal_start, + bp_hardware_breakpoint); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; + b->disposition = disp_donttouch; + b->addr_string = addr_string_start; + b->addr_string_range_end = addr_string_end; + b->ops = &ranged_breakpoint_ops; + b->loc->length = length; + + discard_cleanups (cleanup_bkpt); + + mention (b); + update_global_location_list (1); +} + /* Return non-zero if EXP is verified as constant. Returned zero means EXP is variable. Also the constant detection may fail for some constant expressions and in such case still falsely return @@ -8485,6 +8810,7 @@ static struct breakpoint_ops watchpoint_breakpoint_ops = resources_needed_watchpoint, NULL, /* print_it */ NULL, /* print_one */ + NULL, /* print_one_detail */ NULL, /* print_mention */ NULL /* print_recreate */ }; @@ -8610,13 +8936,8 @@ watch_command_1 (char *arg, int accessflag, int from_tty, 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) @@ -8900,7 +9221,7 @@ watch_maybe_just_location (char *arg, int accessflag, int from_tty) && (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; } @@ -8982,10 +9303,9 @@ until_break_command (char *arg, int from_tty, int anywhere) if (default_breakpoint_valid) sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, (char ***) NULL, NULL); + default_breakpoint_line, NULL, NULL); else - sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, - 0, (char ***) NULL, NULL); + sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL, NULL); if (sals.nelts != 1) error (_("Couldn't get information on specified line.")); @@ -9057,15 +9377,6 @@ until_break_command (char *arg, int from_tty, int anywhere) 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 " clause from the arg string. If one is not found, it returns NULL. @@ -9087,7 +9398,7 @@ ep_parse_optional_if_clause (char **arg) /* 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 @@ -9122,7 +9433,7 @@ catch_fork_command_1 (char *arg, int from_tty, if (!arg) arg = ""; - ep_skip_leading_whitespace (&arg); + arg = skip_spaces (arg); /* The allowed syntax is: catch [v]fork @@ -9166,7 +9477,7 @@ catch_exec_command_1 (char *arg, int from_tty, if (!arg) arg = ""; - ep_skip_leading_whitespace (&arg); + arg = skip_spaces (arg); /* The allowed syntax is: catch exec @@ -9278,6 +9589,7 @@ static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = { NULL, /* resources_needed */ print_exception_catchpoint, print_one_exception_catchpoint, + NULL, /* print_one_detail */ print_mention_exception_catchpoint, print_recreate_exception_catchpoint }; @@ -9316,7 +9628,7 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg, if (!arg) arg = ""; - ep_skip_leading_whitespace (&arg); + arg = skip_spaces (arg); cond_string = ep_parse_optional_if_clause (&arg); @@ -9502,11 +9814,11 @@ catch_syscall_command_1 (char *arg, int from_tty, /* 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, @@ -9658,8 +9970,8 @@ clear_command (char *arg, int from_tty) && b->source_file != NULL && sal.symtab != NULL && sal.pspace == loc->pspace - && strcmp (b->source_file, - sal.symtab->filename) == 0 + && filename_cmp (b->source_file, + sal.symtab->filename) == 0 && b->line_number == sal.line); if (pc_match || line_match) { @@ -10192,12 +10504,20 @@ delete_breakpoint (struct breakpoint *bpt) /* At least avoid this stale reference until the reference counting of breakpoints gets resolved. */ - if (bpt->related_breakpoint != NULL) + if (bpt->related_breakpoint != bpt) { - gdb_assert (bpt->related_breakpoint->related_breakpoint == bpt); - bpt->related_breakpoint->disposition = disp_del_at_next_stop; - bpt->related_breakpoint->related_breakpoint = NULL; - bpt->related_breakpoint = NULL; + struct breakpoint *related; + + if (bpt->type == bp_watchpoint_scope) + watchpoint_del_at_next_stop (bpt->related_breakpoint); + else if (bpt->related_breakpoint->type == bp_watchpoint_scope) + watchpoint_del_at_next_stop (bpt); + + /* Unlink bpt from the bpt->related_breakpoint ring. */ + for (related = bpt; related->related_breakpoint != bpt; + related = related->related_breakpoint); + related->related_breakpoint = bpt->related_breakpoint; + bpt->related_breakpoint = bpt; } observer_notify_breakpoint_deleted (bpt->number); @@ -10216,6 +10536,7 @@ delete_breakpoint (struct breakpoint *bpt) xfree (bpt->cond_string); xfree (bpt->cond_exp); xfree (bpt->addr_string); + xfree (bpt->addr_string_range_end); xfree (bpt->exp); xfree (bpt->exp_string); xfree (bpt->exp_string_reparse); @@ -10510,14 +10831,21 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal) return sal; } -static void +/* Create new breakpoint locations for B (a hardware or software breakpoint) + based on SALS and SALS_END. If SALS_END.NELTS is not zero, then B is + a ranged breakpoint. */ + +void update_breakpoint_locations (struct breakpoint *b, - struct symtabs_and_lines sals) + struct symtabs_and_lines sals, + struct symtabs_and_lines sals_end) { int i; - char *s; struct bp_location *existing_locations = b->loc; + /* Ranged breakpoints have only one start location and one end location. */ + gdb_assert (sals_end.nelts == 0 || (sals.nelts == 1 && sals_end.nelts == 1)); + /* If there's no new locations, and all existing locations are pending, don't do anything. This optimizes the common case where all locations are in the same shared library, that was unloaded. @@ -10538,6 +10866,7 @@ update_breakpoint_locations (struct breakpoint *b, old symtab. */ if (b->cond_string != NULL) { + char *s; struct gdb_exception e; s = b->cond_string; @@ -10564,6 +10893,13 @@ update_breakpoint_locations (struct breakpoint *b, if (b->line_number == 0) b->line_number = sals.sals[i].line; + + if (sals_end.nelts) + { + CORE_ADDR end = find_breakpoint_range_end (sals_end.sals[0]); + + new_loc->length = end - sals.sals[0].pc + 1; + } } /* Update locations of permanent breakpoints. */ @@ -10589,8 +10925,7 @@ update_breakpoint_locations (struct breakpoint *b, if (have_ambiguous_names) { for (; l; l = l->next) - if (breakpoint_address_match (e->pspace->aspace, e->address, - l->pspace->aspace, l->address)) + if (breakpoint_locations_match (e, l)) { l->enabled = 0; break; @@ -10613,6 +10948,134 @@ update_breakpoint_locations (struct breakpoint *b, update_global_location_list (1); } +/* Find the SaL locations corresponding to the given ADDR_STRING. + On return, FOUND will be 1 if any SaL was found, zero otherwise. */ + +static struct symtabs_and_lines +addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found) +{ + char *s; + int marker_spec, not_found; + struct symtabs_and_lines sals = {0}; + struct gdb_exception e; + + s = addr_string; + marker_spec = b->type == bp_static_tracepoint && is_marker_spec (s); + + TRY_CATCH (e, RETURN_MASK_ERROR) + { + if (marker_spec) + { + sals = decode_static_tracepoint_spec (&s); + if (sals.nelts > b->static_trace_marker_id_idx) + { + sals.sals[0] = sals.sals[b->static_trace_marker_id_idx]; + sals.nelts = 1; + } + else + error (_("marker %s not found"), b->static_trace_marker_id); + } + else + sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, + NULL, ¬_found); + } + if (e.reason < 0) + { + int not_found_and_ok = 0; + /* For pending breakpoints, it's expected that parsing will + fail until the right shared library is loaded. User has + already told to create pending breakpoints and don't need + extra messages. If breakpoint is in bp_shlib_disabled + state, then user already saw the message about that + breakpoint being disabled, and don't want to see more + errors. */ + if (not_found + && (b->condition_not_parsed + || (b->loc && b->loc->shlib_disabled) + || b->enable_state == bp_disabled)) + not_found_and_ok = 1; + + if (!not_found_and_ok) + { + /* We surely don't want to warn about the same breakpoint + 10 times. One solution, implemented here, is disable + the breakpoint on error. Another solution would be to + have separate 'warning emitted' flag. Since this + happens only when a binary has changed, I don't know + which approach is better. */ + b->enable_state = bp_disabled; + throw_exception (e); + } + } + + if (!not_found) + { + gdb_assert (sals.nelts == 1); + + resolve_sal_pc (&sals.sals[0]); + if (b->condition_not_parsed && s && s[0]) + { + char *cond_string = 0; + int thread = -1; + int task = 0; + + find_condition_and_thread (s, sals.sals[0].pc, + &cond_string, &thread, &task); + if (cond_string) + b->cond_string = cond_string; + b->thread = thread; + b->task = task; + b->condition_not_parsed = 0; + } + + if (b->type == bp_static_tracepoint && !marker_spec) + sals.sals[0] = update_static_tracepoint (b, sals.sals[0]); + } + + *found = !not_found; + + return sals; +} + +/* Reevaluate a hardware or software breakpoint and recreate its locations. + This is necessary after symbols are read (e.g., an executable or DSO + was loaded, or the inferior just started). */ + +static void +re_set_breakpoint (struct breakpoint *b) +{ + int found; + struct symtabs_and_lines sals, sals_end; + struct symtabs_and_lines expanded = {0}; + struct symtabs_and_lines expanded_end = {0}; + struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); + + input_radix = b->input_radix; + save_current_space_and_thread (); + switch_to_program_space_and_thread (b->pspace); + set_language (b->language); + + sals = addr_string_to_sals (b, b->addr_string, &found); + if (found) + { + make_cleanup (xfree, sals.sals); + expanded = expand_line_sal_maybe (sals.sals[0]); + } + + if (b->addr_string_range_end) + { + sals_end = addr_string_to_sals (b, b->addr_string_range_end, &found); + if (found) + { + make_cleanup (xfree, sals_end.sals); + expanded_end = expand_line_sal_maybe (sals_end.sals[0]); + } + } + + update_breakpoint_locations (b, expanded, expanded_end); + do_cleanups (cleanups); +} + /* Reset a breakpoint given it's struct breakpoint * BINT. The value we return ends up being the return value from catch_errors. Unused in this case. */ @@ -10622,14 +11085,6 @@ breakpoint_re_set_one (void *bint) { /* Get past catch_errs. */ struct breakpoint *b = (struct breakpoint *) bint; - int not_found = 0; - int *not_found_ptr = ¬_found; - struct symtabs_and_lines sals = {0}; - struct symtabs_and_lines expanded = {0}; - char *s; - struct gdb_exception e; - struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); - int marker_spec = 0; switch (b->type) { @@ -10642,6 +11097,7 @@ breakpoint_re_set_one (void *bint) case bp_tracepoint: case bp_fast_tracepoint: case bp_static_tracepoint: + case bp_gnu_ifunc_resolver: /* Do not attempt to re-set breakpoints disabled during startup. */ if (b->enable_state == bp_startup_disabled) return 0; @@ -10653,89 +11109,7 @@ breakpoint_re_set_one (void *bint) return 0; } - input_radix = b->input_radix; - s = b->addr_string; - - save_current_space_and_thread (); - switch_to_program_space_and_thread (b->pspace); - - marker_spec = b->type == bp_static_tracepoint && is_marker_spec (s); - - set_language (b->language); - TRY_CATCH (e, RETURN_MASK_ERROR) - { - if (marker_spec) - { - sals = decode_static_tracepoint_spec (&s); - if (sals.nelts > b->static_trace_marker_id_idx) - { - sals.sals[0] = sals.sals[b->static_trace_marker_id_idx]; - sals.nelts = 1; - } - else - error (_("marker %s not found"), b->static_trace_marker_id); - } - else - sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, - (char ***) NULL, not_found_ptr); - } - if (e.reason < 0) - { - int not_found_and_ok = 0; - /* For pending breakpoints, it's expected that parsing will - fail until the right shared library is loaded. User has - already told to create pending breakpoints and don't need - extra messages. If breakpoint is in bp_shlib_disabled - state, then user already saw the message about that - breakpoint being disabled, and don't want to see more - errors. */ - if (not_found - && (b->condition_not_parsed - || (b->loc && b->loc->shlib_disabled) - || b->enable_state == bp_disabled)) - not_found_and_ok = 1; - - if (!not_found_and_ok) - { - /* We surely don't want to warn about the same breakpoint - 10 times. One solution, implemented here, is disable - the breakpoint on error. Another solution would be to - have separate 'warning emitted' flag. Since this - happens only when a binary has changed, I don't know - which approach is better. */ - b->enable_state = bp_disabled; - throw_exception (e); - } - } - - if (!not_found) - { - gdb_assert (sals.nelts == 1); - - resolve_sal_pc (&sals.sals[0]); - if (b->condition_not_parsed && s && s[0]) - { - char *cond_string = 0; - int thread = -1; - int task = 0; - - find_condition_and_thread (s, sals.sals[0].pc, - &cond_string, &thread, &task); - if (cond_string) - b->cond_string = cond_string; - b->thread = thread; - b->task = task; - b->condition_not_parsed = 0; - } - - if (b->type == bp_static_tracepoint && !marker_spec) - sals.sals[0] = update_static_tracepoint (b, sals.sals[0]); - - expanded = expand_line_sal_maybe (sals.sals[0]); - } - - make_cleanup (xfree, sals.sals); - update_breakpoint_locations (b, expanded); + re_set_breakpoint (b); break; case bp_watchpoint: @@ -10812,10 +11186,10 @@ breakpoint_re_set_one (void *bint) case bp_exception: case bp_exception_resume: case bp_jit_event: + case bp_gnu_ifunc_resolver_return: break; } - do_cleanups (cleanups); return 0; } @@ -10952,21 +11326,23 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *, 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); @@ -10976,17 +11352,30 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *, ALL_BREAKPOINTS_SAFE (b, tmp) if (b->number == num) { - struct breakpoint *related_breakpoint = b->related_breakpoint; + struct breakpoint *related_breakpoint; + match = 1; - function (b, data); - if (related_breakpoint) - function (related_breakpoint, data); + related_breakpoint = b; + do + { + struct breakpoint *next_related_b; + + /* FUNCTION can be also delete_breakpoint. */ + next_related_b = related_breakpoint->related_breakpoint; + function (related_breakpoint, data); + + /* For delete_breakpoint of the last entry of the ring we + were traversing we would never get back to B. */ + if (next_related_b == related_breakpoint) + break; + related_breakpoint = next_related_b; + } + while (related_breakpoint != b); break; } if (match == 0) printf_unfiltered (_("No breakpoint number %d.\n"), num); } - p = p1; } } @@ -11003,7 +11392,7 @@ find_location_by_number (char *number) *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); @@ -11017,7 +11406,7 @@ find_location_by_number (char *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); @@ -11077,7 +11466,7 @@ disable_command (char *args, int from_tty) 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: @@ -11089,8 +11478,9 @@ disable_command (char *args, int from_tty) case bp_read_watchpoint: case bp_access_watchpoint: disable_breakpoint (bpt); + break; default: - continue; + break; } else if (strchr (args, '.')) { @@ -11178,7 +11568,7 @@ enable_command (char *args, int from_tty) 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: @@ -11190,8 +11580,9 @@ enable_command (char *args, int from_tty) case bp_read_watchpoint: case bp_access_watchpoint: enable_breakpoint (bpt); + break; default: - continue; + break; } else if (strchr (args, '.')) { @@ -11280,10 +11671,10 @@ decode_line_spec_1 (char *string, int funfirstline) sals = decode_line_1 (&string, funfirstline, default_breakpoint_symtab, default_breakpoint_line, - (char ***) NULL, NULL); + NULL, NULL); else sals = decode_line_1 (&string, funfirstline, - (struct symtab *) NULL, 0, (char ***) NULL, NULL); + (struct symtab *) NULL, 0, NULL, NULL); if (*string) error (_("Junk at end of line specification: %s"), string); return sals; @@ -11510,8 +11901,11 @@ catch_syscall_completer (struct cmd_list_element *cmd, 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. */ @@ -11682,21 +12076,18 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) 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 (); @@ -11759,6 +12150,18 @@ delete_trace_command (char *arg, int from_tty) 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. @@ -11768,9 +12171,8 @@ delete_trace_command (char *arg, int from_tty) 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 " @@ -11784,32 +12186,32 @@ trace_pass_command (char *args, int from_tty) 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 * @@ -11841,18 +12243,25 @@ get_tracepoint_by_number_on_target (int num) } /* 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; @@ -11860,7 +12269,7 @@ get_tracepoint_by_number (char **arg, int multi_p, int optional_p) error_no_arg (_("tracepoint number")); } else - tpnum = multi_p ? get_number_or_range (arg) : get_number (arg); + tpnum = get_number (arg); if (tpnum <= 0) { @@ -11879,9 +12288,6 @@ get_tracepoint_by_number (char **arg, int multi_p, int optional_p) 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; } @@ -12082,7 +12488,7 @@ save_tracepoints_command (char *args, int from_tty) /* Create a vector of all tracepoints. */ VEC(breakpoint_p) * -all_tracepoints () +all_tracepoints (void) { VEC(breakpoint_p) *tp_vec = 0; struct breakpoint *tp; @@ -12386,7 +12792,7 @@ breakpoint set.")); } 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\ @@ -12534,9 +12940,7 @@ the memory to which it refers.")); 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. */ @@ -12602,7 +13006,7 @@ Do \"help tracepoints\" for info on other tracepoint commands.")); 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.")); @@ -12712,7 +13116,23 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."), &show_always_inserted_mode, &breakpoint_set_cmdlist, &breakpoint_show_cmdlist); - + + add_com ("break-range", class_breakpoint, break_range_command, _("\ +Set a breakpoint for an address range.\n\ +break-range START-LOCATION, END-LOCATION\n\ +where START-LOCATION and END-LOCATION can be one of the following:\n\ + LINENUM, for that line in the current file,\n\ + FILE:LINENUM, for that line in that file,\n\ + +OFFSET, for that number of lines after the current line\n\ + or the start of the range\n\ + FUNCTION, for the first line in that function,\n\ + FILE:FUNCTION, to distinguish among like-named static functions.\n\ + *ADDRESS, for the instruction at that address.\n\ +\n\ +The breakpoint will stop execution of the inferior whenever it executes\n\ +an instruction at any address within the [START-LOCATION, END-LOCATION]\n\ +range (including START-LOCATION and END-LOCATION).")); + automatic_hardware_breakpoints = 1; observer_attach_about_to_proceed (breakpoint_about_to_proceed);