From 23916b7dc0f2f05982da7a76726d931cf738d2cc Mon Sep 17 00:00:00 2001 From: Keith Seitz Date: Wed, 30 Sep 2015 14:23:12 -0700 Subject: Initial publication of breakpoint reset project. This is a work-in-progress publication of an intelligent breakpoint_re_set redesign. See the project wiki page for more information: https://sourceware.org/gdb/wiki/BreakpointReset --- gdb/ada-lang.c | 13 +- gdb/ax-gdb.c | 6 +- gdb/break-catch-throw.c | 9 +- gdb/breakpoint.c | 242 +++++++++++++++++----- gdb/breakpoint.h | 32 ++- gdb/cli/cli-cmds.c | 23 ++- gdb/common/gdb_vecs.h | 4 + gdb/dwarf2read.c | 3 - gdb/infcmd.c | 5 +- gdb/infrun.c | 29 ++- gdb/linespec.c | 525 +++++++++++++++++++++++++++++++++++------------- gdb/linespec.h | 77 ++++++- gdb/minsyms.h | 3 + gdb/objfiles.c | 16 +- gdb/python/python.c | 8 +- gdb/solib.c | 19 +- gdb/symfile.c | 28 ++- gdb/symtab.c | 130 ++++++++++-- gdb/symtab.h | 4 + gdb/tracepoint.c | 4 +- 20 files changed, 917 insertions(+), 263 deletions(-) diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index a229fa1..fd712fe 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -12248,11 +12248,13 @@ allocate_location_exception (enum ada_exception_catchpoint_kind ex, static void re_set_exception (enum ada_exception_catchpoint_kind ex, struct breakpoint *b) { + struct breakpoint_reset_reason reset_reason; struct ada_catchpoint *c = (struct ada_catchpoint *) b; /* Call the base class's method. This updates the catchpoint's locations. */ - bkpt_breakpoint_ops.re_set (b); + init_breakpoint_reset_reason (&reset_reason); + bkpt_breakpoint_ops.re_set (b, &reset_reason); /* Reparse the exception conditional expressions. One for each location. */ @@ -12522,7 +12524,8 @@ allocate_location_catch_exception (struct breakpoint *self) } static void -re_set_catch_exception (struct breakpoint *b) +re_set_catch_exception (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { re_set_exception (ada_catch_exception, b); } @@ -12574,7 +12577,8 @@ allocate_location_catch_exception_unhandled (struct breakpoint *self) } static void -re_set_catch_exception_unhandled (struct breakpoint *b) +re_set_catch_exception_unhandled (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { re_set_exception (ada_catch_exception_unhandled, b); } @@ -12628,7 +12632,8 @@ allocate_location_catch_assert (struct breakpoint *self) } static void -re_set_catch_assert (struct breakpoint *b) +re_set_catch_assert (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { re_set_exception (ada_catch_assert, b); } diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index 817fa53..70c351f 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -2644,14 +2644,14 @@ agent_command_1 (char *exp, int eval) struct linespec_sals *iter; struct cleanup *old_chain; struct event_location *location; + struct decode_line_options opts; exp = skip_spaces (exp); init_linespec_result (&canonical); location = new_linespec_location (&exp); old_chain = make_cleanup_delete_event_location (location); - decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, - (struct symtab *) NULL, 0, &canonical, - NULL, NULL); + init_decode_line_options (&opts); + decode_line_full (location, &canonical, &opts); make_cleanup_destroy_linespec_result (&canonical); exp = skip_spaces (exp); if (exp[0] == ',') diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c index 1ba505b..e2668b5 100644 --- a/gdb/break-catch-throw.c +++ b/gdb/break-catch-throw.c @@ -205,7 +205,8 @@ check_status_exception_catchpoint (struct bpstats *bs) /* Implement the 're_set' method. */ static void -re_set_exception_catchpoint (struct breakpoint *self) +re_set_exception_catchpoint (struct breakpoint *self, + struct breakpoint_reset_reason *reason) { struct symtabs_and_lines sals = {0}; struct symtabs_and_lines sals_end = {0}; @@ -236,7 +237,7 @@ re_set_exception_catchpoint (struct breakpoint *self) = ASTRDUP (exception_functions[kind].function); location = new_explicit_location (&explicit_loc); cleanup = make_cleanup_delete_event_location (location); - self->ops->decode_location (self, location, &sals); + self->ops->decode_location (self, location, NULL, &sals); do_cleanups (cleanup); } CATCH (ex, RETURN_MASK_ERROR) @@ -393,6 +394,7 @@ static void handle_gnu_v3_exceptions (int tempflag, char *except_rx, char *cond_string, enum exception_event_kind ex_event, int from_tty) { + struct breakpoint_reset_reason reset_reason; struct exception_catchpoint *cp; struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); regex_t *pattern = NULL; @@ -418,7 +420,8 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx, char *cond_string, cp->exception_rx = except_rx; cp->pattern = pattern; - re_set_exception_catchpoint (&cp->base); + init_breakpoint_reset_reason (&reset_reason); + re_set_exception_catchpoint (&cp->base, &reset_reason); install_breakpoint (0, &cp->base, 1); discard_cleanups (cleanup); diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 2c901ff..eda45d4 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -80,6 +80,8 @@ #include "mi/mi-common.h" #include "extension.h" +#define DEBUG_ME 0 + /* Enums for exception-handling support. */ enum exception_event_kind { @@ -88,6 +90,17 @@ enum exception_event_kind EX_EVENT_CATCH }; +/* Structure to wrap arguments to breakpoint_reset_one via catch_errors. */ + +struct breakpoint_re_set_one_info +{ + /* The breakpoint to re-set. */ + struct breakpoint *bp; + + /* The reason for re-setting this breakpoint. */ + struct breakpoint_reset_reason *reason; +}; + /* Prototypes for local functions. */ static void enable_delete_command (char *, int); @@ -108,7 +121,8 @@ static void ignore_command (char *, int); static int breakpoint_re_set_one (void *); -static void breakpoint_re_set_default (struct breakpoint *); +static void breakpoint_re_set_default (struct breakpoint *, + struct breakpoint_reset_reason *); static void create_sals_from_location_default (const struct event_location *location, @@ -125,6 +139,7 @@ static void create_breakpoints_sal_default (struct gdbarch *, static void decode_location_default (struct breakpoint *b, const struct event_location *location, + const struct decode_line_limits *, struct symtabs_and_lines *sals); static void clear_command (char *, int); @@ -3101,7 +3116,7 @@ insert_breakpoint_locations (void) struct ui_file *tmp_error_stream = mem_fileopen (); struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_error_stream); - + /* Explicitly mark the warning -- this will only be printed if there was an error. */ fprintf_unfiltered (tmp_error_stream, "Warning:\n"); @@ -8770,8 +8785,12 @@ disable_breakpoints_before_startup (void) void enable_breakpoints_after_startup (void) { + struct breakpoint_reset_reason r; + + init_breakpoint_reset_reason (&r); + r.where = __func__; current_program_space->executing_startup = 0; - breakpoint_re_set (); + breakpoint_re_set (&r); } /* Create a new single-step breakpoint for thread THREAD, with no @@ -9363,6 +9382,7 @@ parse_breakpoint_sals (const struct event_location *location, struct linespec_result *canonical) { struct symtab_and_line cursal; + struct decode_line_options opts; if (event_location_type (location) == LINESPEC_LOCATION) { @@ -9418,6 +9438,12 @@ parse_breakpoint_sals (const struct event_location *location, ObjC: However, don't match an Objective-C method name which may have a '+' or '-' succeeded by a '['. */ cursal = get_current_source_symtab_and_line (); + + init_decode_line_options (&opts); + opts.default_symtab = cursal.symtab; + opts.default_line = cursal.line; + opts.flags |= DECODE_LINE_CREATE_CACHE; + if (last_displayed_sal_is_valid ()) { const char *address = NULL; @@ -9430,16 +9456,19 @@ parse_breakpoint_sals (const struct event_location *location, && strchr ("+-", address[0]) != NULL && address[1] != '[')) { - decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, - get_last_displayed_symtab (), - get_last_displayed_line (), - canonical, NULL, NULL); + opts.default_symtab = get_last_displayed_symtab (); + opts.default_line = get_last_displayed_line (); + decode_line_full (location, canonical, &opts); + return; + } + else + { + decode_line_full (location, canonical, &opts); return; } } - decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, - cursal.symtab, cursal.line, canonical, NULL, NULL); + decode_line_full (location, canonical, &opts); } @@ -9779,6 +9808,17 @@ create_breakpoint (struct gdbarch *gdbarch, tempflag ? disp_del : disp_donttouch, thread, task, ignore_count, ops, from_tty, enabled, internal, flags); + + /* !!keiths; Somewhere here I need to save the linespec cache + into the struct. Umm... Need the breakpoint! LAME! */ + { + struct breakpoint *b, *last; + + ALL_BREAKPOINTS (b) + last = b; + last->linespec_cache = canonical.cache; + canonical.cache = NULL; + } } else { @@ -10283,6 +10323,7 @@ break_range_command (char *arg, int from_tty) struct cleanup *cleanup_bkpt; struct linespec_sals *lsal_start, *lsal_end; struct event_location *start_location, *end_location; + struct decode_line_options opts; /* We don't support software ranged breakpoints. */ if (target_ranged_break_num_registers () < 0) @@ -10337,9 +10378,10 @@ break_range_command (char *arg, int from_tty) where +14 means 14 lines from the start location. */ end_location = string_to_event_location (&arg, current_language); make_cleanup_delete_event_location (end_location); - decode_line_full (end_location, DECODE_LINE_FUNFIRSTLINE, - sal_start.symtab, sal_start.line, - &canonical_end, NULL, NULL); + init_decode_line_options (&opts); + opts.default_symtab = sal_start.symtab; + opts.default_line = sal_start.line; + decode_line_full (end_location, &canonical_end, &opts); make_cleanup_destroy_linespec_result (&canonical_end); @@ -10522,7 +10564,8 @@ dtor_watchpoint (struct breakpoint *self) /* Implement the "re_set" breakpoint_ops method for watchpoints. */ static void -re_set_watchpoint (struct breakpoint *b) +re_set_watchpoint (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { struct watchpoint *w = (struct watchpoint *) b; @@ -11591,6 +11634,7 @@ until_break_command (char *arg, int from_tty, int anywhere) struct thread_info *tp; struct event_location *location; struct until_break_fsm *sm; + struct decode_line_options options; clear_proceed_status (0); @@ -11600,13 +11644,15 @@ until_break_command (char *arg, int from_tty, int anywhere) location = string_to_event_location (&arg, current_language); cleanup = make_cleanup_delete_event_location (location); + init_decode_line_options (&options); if (last_displayed_sal_is_valid ()) - sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE, - get_last_displayed_symtab (), - get_last_displayed_line ()); + { + options.default_symtab = get_last_displayed_symtab (); + options.default_line = get_last_displayed_line (); + sals = decode_line_1 (location, &options); + } else - sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE, - (struct symtab *) NULL, 0); + sals = decode_line_1 (location, &options); if (sals.nelts != 1) error (_("Couldn't get information on specified line.")); @@ -12281,7 +12327,6 @@ force_breakpoint_reinsertion (struct bp_location *bl) /* Called whether new breakpoints are created, or existing breakpoints deleted, to update the global location list and recompute which locations are duplicate of which. - The INSERT_MODE flag determines whether locations may not, may, or shall be inserted now. See 'enum ugll_insert_mode' for more info. */ @@ -12800,7 +12845,8 @@ base_breakpoint_allocate_location (struct breakpoint *self) } static void -base_breakpoint_re_set (struct breakpoint *b) +base_breakpoint_re_set (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { /* Nothing to re-set. */ } @@ -12906,6 +12952,7 @@ base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch, static void base_breakpoint_decode_location (struct breakpoint *b, const struct event_location *location, + const struct decode_line_limits *limits, struct symtabs_and_lines *sals) { internal_error_pure_virtual_called (); @@ -12953,7 +13000,8 @@ struct breakpoint_ops base_breakpoint_ops = /* Default breakpoint_ops methods. */ static void -bkpt_re_set (struct breakpoint *b) +bkpt_re_set (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { /* FIXME: is this still reachable? */ if (event_location_empty_p (b->location)) @@ -12963,7 +13011,7 @@ bkpt_re_set (struct breakpoint *b) return; } - breakpoint_re_set_default (b); + breakpoint_re_set_default (b, reason); } static int @@ -13153,15 +13201,17 @@ bkpt_create_breakpoints_sal (struct gdbarch *gdbarch, static void bkpt_decode_location (struct breakpoint *b, const struct event_location *location, + const struct decode_line_limits *limits, struct symtabs_and_lines *sals) { - decode_location_default (b, location, sals); + decode_location_default (b, location, limits, sals); } /* Virtual table for internal breakpoints. */ static void -internal_bkpt_re_set (struct breakpoint *b) +internal_bkpt_re_set (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { switch (b->type) { @@ -13258,7 +13308,8 @@ internal_bkpt_print_mention (struct breakpoint *b) /* Virtual table for momentary breakpoints */ static void -momentary_bkpt_re_set (struct breakpoint *b) +momentary_bkpt_re_set (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { /* Keep temporary breakpoints, which can be encountered when we step over a dlopen call and solib_add is resetting the breakpoints. @@ -13347,6 +13398,7 @@ bkpt_probe_create_sals_from_location (const struct event_location *location, static void bkpt_probe_decode_location (struct breakpoint *b, const struct event_location *location, + const struct decode_line_limits *limits, struct symtabs_and_lines *sals) { *sals = parse_probes (location, NULL); @@ -13357,9 +13409,10 @@ bkpt_probe_decode_location (struct breakpoint *b, /* The breakpoint_ops structure to be used in tracepoints. */ static void -tracepoint_re_set (struct breakpoint *b) +tracepoint_re_set (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { - breakpoint_re_set_default (b); + breakpoint_re_set_default (b, reason); } static int @@ -13471,9 +13524,10 @@ tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch, static void tracepoint_decode_location (struct breakpoint *b, const struct event_location *location, + const struct decode_line_limits *limits, struct symtabs_and_lines *sals) { - decode_location_default (b, location, sals); + decode_location_default (b, location, limits, sals); } struct breakpoint_ops tracepoint_breakpoint_ops; @@ -13494,10 +13548,11 @@ tracepoint_probe_create_sals_from_location static void tracepoint_probe_decode_location (struct breakpoint *b, const struct event_location *location, + const struct decode_line_limits *limits, struct symtabs_and_lines *sals) { /* We use the same method for breakpoint on probes. */ - bkpt_probe_decode_location (b, location, sals); + bkpt_probe_decode_location (b, location, limits, sals); } static struct breakpoint_ops tracepoint_probe_breakpoint_ops; @@ -13505,9 +13560,10 @@ static struct breakpoint_ops tracepoint_probe_breakpoint_ops; /* Dprintf breakpoint_ops methods. */ static void -dprintf_re_set (struct breakpoint *b) +dprintf_re_set (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { - breakpoint_re_set_default (b); + breakpoint_re_set_default (b, reason); /* extra_string should never be non-NULL for dprintf. */ gdb_assert (b->extra_string != NULL); @@ -13662,6 +13718,7 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch, static void strace_marker_decode_location (struct breakpoint *b, const struct event_location *location, + const struct decode_line_limits *limits, struct symtabs_and_lines *sals) { struct tracepoint *tp = (struct tracepoint *) b; @@ -14129,6 +14186,10 @@ update_breakpoint_locations (struct breakpoint *b, switch_to_program_space_and_thread (sals.sals[i].pspace); +#if DEBUG_ME + printf ("adding location for %s to bp #%d\n", + core_addr_to_string (sals.sals[i].pc), b->number); +#endif new_loc = add_location_to_breakpoint (b, &(sals.sals[i])); /* Reparse conditions, they might contain references to the @@ -14207,12 +14268,18 @@ update_breakpoint_locations (struct breakpoint *b, update_global_location_list (UGLL_MAY_INSERT); } +static int +no_limits_p (const struct decode_line_limits *limits) +{ + return (limits == NULL || limits->objfiles == NULL); +} + /* Find the SaL locations corresponding to the given LOCATION. On return, FOUND will be 1 if any SaL was found, zero otherwise. */ static struct symtabs_and_lines location_to_sals (struct breakpoint *b, struct event_location *location, - int *found) + const struct decode_line_limits *limits, int *found) { struct symtabs_and_lines sals = {0}; struct gdb_exception exception = exception_none; @@ -14221,7 +14288,7 @@ location_to_sals (struct breakpoint *b, struct event_location *location, TRY { - b->ops->decode_location (b, location, &sals); + b->ops->decode_location (b, location, limits, &sals); } CATCH (e, RETURN_MASK_ERROR) { @@ -14240,7 +14307,8 @@ location_to_sals (struct breakpoint *b, struct event_location *location, && (b->condition_not_parsed || (b->loc && b->loc->shlib_disabled) || (b->loc && b->loc->pspace->executing_startup) - || b->enable_state == bp_disabled)) + || b->enable_state == bp_disabled + || !no_limits_p (limits))) not_found_and_ok = 1; if (!not_found_and_ok) @@ -14257,7 +14325,8 @@ location_to_sals (struct breakpoint *b, struct event_location *location, } END_CATCH - if (exception.reason == 0 || exception.error != NOT_FOUND_ERROR) + if (exception.reason == 0 || exception.error != NOT_FOUND_ERROR + /* KEITHS? && sals.nelts > 0*/) { int i; @@ -14300,31 +14369,60 @@ location_to_sals (struct breakpoint *b, struct event_location *location, locations. */ static void -breakpoint_re_set_default (struct breakpoint *b) +breakpoint_re_set_default (struct breakpoint *b, + struct breakpoint_reset_reason *reason) { - int found; + int found, update; struct symtabs_and_lines sals, sals_end; struct symtabs_and_lines expanded = {0}; struct symtabs_and_lines expanded_end = {0}; + struct decode_line_limits limits; + + /* If there is a reset reason, use that to "limit" SaL lookups. */ + update = 0; + init_decode_line_limits (&limits); + switch (reason->reason) + { + case BREAKPOINT_RESET_ADD_OBJFILE: +#if 0 + printf ("ignoring add objfile event\n"); + return; +#endif + limits.objfiles = reason->objfile_list; + break; + + case BREAKPOINT_RESET_NONE: + invalidate_linespec_cache (&(b->linespec_cache)); + /* Always update breakpoint locations in case. */ + update = 1; + break; - sals = location_to_sals (b, b->location, &found); + default: + break; + } + + sals = location_to_sals (b, b->location, &limits, &found); if (found) { make_cleanup (xfree, sals.sals); expanded = sals; + update = 1; } if (b->location_range_end != NULL) { - sals_end = location_to_sals (b, b->location_range_end, &found); + sals_end = location_to_sals (b, b->location_range_end, + &limits, &found); if (found) { make_cleanup (xfree, sals_end.sals); expanded_end = sals_end; + update = 1; } } - update_breakpoint_locations (b, expanded, expanded_end); + if (update) + update_breakpoint_locations (b, expanded, expanded_end); } /* Default method for creating SALs from an address string. It basically @@ -14368,15 +14466,20 @@ create_breakpoints_sal_default (struct gdbarch *gdbarch, static void decode_location_default (struct breakpoint *b, const struct event_location *location, + const struct decode_line_limits *limits, struct symtabs_and_lines *sals) { struct linespec_result canonical; + struct decode_line_options opts; init_linespec_result (&canonical); - decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, - (struct symtab *) NULL, 0, - &canonical, multiple_symbols_all, - b->filter); + init_decode_line_options (&opts); + opts.select_mode = multiple_symbols_all; + opts.filter = b->filter; + opts.limits = limits; + opts.cache = b->linespec_cache; + opts.flags |= DECODE_LINE_CREATE_CACHE; + decode_line_full (location, &canonical, &opts); /* We should get 0 or 1 resulting SALs. */ gdb_assert (VEC_length (linespec_sals, canonical.sals) < 2); @@ -14392,6 +14495,8 @@ decode_location_default (struct breakpoint *b, lsal->sals.sals = NULL; } + b->linespec_cache = canonical.cache; + canonical.cache = NULL; destroy_linespec_result (&canonical); } @@ -14411,26 +14516,38 @@ prepare_re_set_context (struct breakpoint *b) return cleanups; } -/* Reset a breakpoint given it's struct breakpoint * BINT. +/* Reset a breakpoint. DATA contains the information on which breakpoint + to reset and why it is being reset. The value we return ends up being the return value from catch_errors. Unused in this case. */ static int -breakpoint_re_set_one (void *bint) +breakpoint_re_set_one (void *data) { /* Get past catch_errs. */ - struct breakpoint *b = (struct breakpoint *) bint; + struct breakpoint_re_set_one_info *info + = (struct breakpoint_re_set_one_info *) data; struct cleanup *cleanups; - cleanups = prepare_re_set_context (b); - b->ops->re_set (b); + cleanups = prepare_re_set_context (info->bp); + info->bp->ops->re_set (info->bp, info->reason); do_cleanups (cleanups); return 0; } +/* Initialize the given reset reason, R. The reason is initialized + to BREAKPOINT_RESET_NONE. */ + +void +init_breakpoint_reset_reason (struct breakpoint_reset_reason *reason) +{ + memset (reason, 0, sizeof (struct breakpoint_reset_reason)); + reason->reason = BREAKPOINT_RESET_NONE; +} + /* Re-set all breakpoints after symbols have been re-loaded. */ void -breakpoint_re_set (void) +breakpoint_re_set (struct breakpoint_reset_reason *reset_reason) { struct breakpoint *b, *b_tmp; enum language save_language; @@ -14441,15 +14558,38 @@ breakpoint_re_set (void) save_input_radix = input_radix; old_chain = save_current_program_space (); + /* !!keiths; Add a caller string or some way to identify where + the re set came from. */ + { + const char *type; + + switch (reset_reason->reason) + { + case BREAKPOINT_RESET_ADD_OBJFILE: + type = "add objfile"; + break; + + default: + type = "??"; + }; + + //printf ("breakpoint_re_set: %s\n", type); + } + ALL_BREAKPOINTS_SAFE (b, b_tmp) { /* Format possible error msg. */ char *message = xstrprintf ("Error in re-setting breakpoint %d: ", b->number); struct cleanup *cleanups = make_cleanup (xfree, message); - catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL); + struct breakpoint_re_set_one_info info; + + info.bp = b; + info.reason = reset_reason; + catch_errors (breakpoint_re_set_one, &info, message, RETURN_MASK_ALL); do_cleanups (cleanups); } + //printf ("breakpoint_re_set done\n"); set_language (save_language); input_radix = save_input_radix; diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 896d3eb..71875d5 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -26,6 +26,7 @@ #include "command.h" #include "break-common.h" #include "probe.h" +#include "linespec.h" struct value; struct block; @@ -35,9 +36,11 @@ struct get_number_or_range_state; struct thread_info; struct bpstats; struct bp_location; -struct linespec_result; +struct linespec; struct linespec_sals; struct event_location; +struct breakpoint_reset_reason; +struct decode_line_limits; /* This is the maximum number of bytes a breakpoint instruction can take. Feel free to increase it. It's just used in a few places to @@ -508,7 +511,8 @@ struct breakpoint_ops /* Reevaluate a breakpoint. This is necessary after symbols change (e.g., an executable or DSO was loaded, or the inferior just started). */ - void (*re_set) (struct breakpoint *self); + void (*re_set) (struct breakpoint *self, + struct breakpoint_reset_reason *reason); /* Insert the breakpoint or watchpoint or activate the catchpoint. Return 0 for success, 1 if the breakpoint, watchpoint or @@ -606,6 +610,7 @@ struct breakpoint_ops This function is called inside `location_to_sals'. */ void (*decode_location) (struct breakpoint *b, const struct event_location *location, + const struct decode_line_limits *, struct symtabs_and_lines *sals); /* Return true if this breakpoint explains a signal. See @@ -679,6 +684,8 @@ struct breakpoint /* Location(s) associated with this high-level breakpoint. */ struct bp_location *loc; + /* !!keiths: cache */ + struct linespec *linespec_cache; /* Non-zero means a silent breakpoint (don't print frame info if we stop here). */ @@ -1198,7 +1205,26 @@ extern void update_breakpoint_locations (struct breakpoint *b, struct symtabs_and_lines sals, struct symtabs_and_lines sals_end); -extern void breakpoint_re_set (void); +/* Event types that cause breakpoints to re-set. */ +enum breakpoint_reset_type +{ + BREAKPOINT_RESET_NONE, + BREAKPOINT_RESET_ADD_OBJFILE +}; + +struct breakpoint_reset_reason +{ + enum breakpoint_reset_type reason; + VEC (objfilep) *objfile_list; + + /* for debugging */ + const char *where; +}; + +/* Initialize the given reset reason, R. */ +extern void init_breakpoint_reset_reason (struct breakpoint_reset_reason *r); + +extern void breakpoint_re_set (struct breakpoint_reset_reason *r); extern void breakpoint_re_set_thread (struct breakpoint *); diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index 6753c70..086bcd9 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -807,12 +807,15 @@ edit_command (char *arg, int from_tty) struct cleanup *cleanup; struct event_location *location; char *arg1; + struct decode_line_options options; /* Now should only be one argument -- decode it in SAL. */ + init_decode_line_options (&options); + options.flags = DECODE_LINE_LIST_MODE; arg1 = arg; location = string_to_event_location (&arg1, current_language); cleanup = make_cleanup_delete_event_location (location); - sals = decode_line_1 (location, DECODE_LINE_LIST_MODE, 0, 0); + sals = decode_line_1 (location, &options); filter_sals (&sals); if (! sals.nelts) @@ -963,10 +966,13 @@ list_command (char *arg, int from_tty) else { struct event_location *location; + struct decode_line_options options; location = string_to_event_location (&arg1, current_language); make_cleanup_delete_event_location (location); - sals = decode_line_1 (location, DECODE_LINE_LIST_MODE, 0, 0); + init_decode_line_options (&options); + options.flags = DECODE_LINE_LIST_MODE; + sals = decode_line_1 (location, &options); filter_sals (&sals); if (!sals.nelts) @@ -1005,15 +1011,20 @@ list_command (char *arg, int from_tty) else { struct event_location *location; + struct decode_line_options options; location = string_to_event_location (&arg1, current_language); make_cleanup_delete_event_location (location); + init_decode_line_options (&options); + options.flags = DECODE_LINE_LIST_MODE; if (dummy_beg) - sals_end = decode_line_1 (location, - DECODE_LINE_LIST_MODE, 0, 0); + sals_end = decode_line_1 (location, &options); else - sals_end = decode_line_1 (location, DECODE_LINE_LIST_MODE, - sal.symtab, sal.line); + { + options.default_symtab = sal.symtab; + options.default_line = sal.line; + sals_end = decode_line_1 (location, &options); + } filter_sals (&sals_end); if (sals_end.nelts == 0) diff --git a/gdb/common/gdb_vecs.h b/gdb/common/gdb_vecs.h index b3f56f8..892af1f 100644 --- a/gdb/common/gdb_vecs.h +++ b/gdb/common/gdb_vecs.h @@ -22,8 +22,10 @@ #include "vec.h" +struct objfile; typedef char *char_ptr; typedef const char *const_char_ptr; +typedef struct objfile *objfilep; DEF_VEC_P (char_ptr); @@ -31,6 +33,8 @@ DEF_VEC_P (const_char_ptr); DEF_VEC_I (int); +DEF_VEC_P (objfilep); + extern void free_char_ptr_vec (VEC (char_ptr) *char_ptr_vec); extern struct cleanup * diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 5b12342..610ddbf 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -74,9 +74,6 @@ #include #include -typedef struct symbol *symbolp; -DEF_VEC_P (symbolp); - /* When == 1, print basic high level tracing messages. When > 1, be more verbose. This is in contrast to the low level DIE reading of dwarf_die_debug. */ diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 54aa1ef..be31642 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -404,6 +404,7 @@ strip_bg_char (const char *args, int *bg_char_p) void post_create_inferior (struct target_ops *target, int from_tty) { + struct breakpoint_reset_reason r; /* Be sure we own the terminal in case write operations are performed. */ target_terminal_ours (); @@ -466,7 +467,9 @@ post_create_inferior (struct target_ops *target, int from_tty) breakpoint_re_set is never called. Call it now so that software watchpoints get a chance to be promoted to hardware watchpoints if the now pushed target supports hardware watchpoints. */ - breakpoint_re_set (); + init_breakpoint_reset_reason (&r); + r.where = __func__; + breakpoint_re_set (&r); observer_notify_inferior_created (target, from_tty); } diff --git a/gdb/infrun.c b/gdb/infrun.c index cf91370..0b1f451 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -839,6 +839,7 @@ follow_fork (void) static void follow_inferior_reset_breakpoints (void) { + struct breakpoint_reset_reason reset_reason; struct thread_info *tp = inferior_thread (); /* Was there a step_resume breakpoint? (There was if the user @@ -872,7 +873,10 @@ follow_inferior_reset_breakpoints (void) were never set in the child, but only in the parent. This makes sure the inserted breakpoints match the breakpoint list. */ - breakpoint_re_set (); + init_breakpoint_reset_reason (&reset_reason); + /*reset_reason.reason = BREAKPOINT_RESET_???;*/ + reset_reason.where = __func__; + breakpoint_re_set (&reset_reason); insert_breakpoints (); } @@ -1096,6 +1100,7 @@ follow_exec (ptid_t ptid, char *execd_pathname) struct inferior *inf = current_inferior (); int pid = ptid_get_pid (ptid); ptid_t process_ptid; + struct breakpoint_reset_reason reset_reason; /* This is an exec event that we actually wish to pay attention to. Refresh our symbol table to the newly exec'd program, remove any @@ -1246,11 +1251,29 @@ follow_exec (ptid_t ptid, char *execd_pathname) registers. */ target_find_description (); - solib_create_inferior_hook (0); + /* Errors on solib_create_inferior_hook are swallowed. In all likelihood, + the user has a breakpoint on a user function (like `main') which appears + in both the old exec and the new. solib_create_inferior_hook will + may call solib_add, which may call update_global_location_list, which + may attempt to insert the breakpoints. Since we haven't/can't yet + reset all breakpoints, the user's breakpoint may fail to insert. + That does not mean, however, that we should just bail. Any real errors + resetting/inserting breakpoints will also be triggered when we do reset + all the breakpoints, just below. */ + TRY + { + solib_create_inferior_hook (0); + } + CATCH (ex, RETURN_MASK_ERROR) + { + } + END_CATCH jit_inferior_created_hook (); - breakpoint_re_set (); + init_breakpoint_reset_reason (&reset_reason); + reset_reason.where = __func__; + breakpoint_re_set (&reset_reason); /* Reinsert all breakpoints. (Those which were symbolic have been reset to the proper address in the new a.out, thanks diff --git a/gdb/linespec.c b/gdb/linespec.c index b2233b9..f1611b3 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -45,9 +45,6 @@ #include "stack.h" #include "location.h" -typedef struct symbol *symbolp; -DEF_VEC_P (symbolp); - typedef struct type *typep; DEF_VEC_P (typep); @@ -61,10 +58,6 @@ struct address_entry CORE_ADDR addr; }; -typedef struct bound_minimal_symbol bound_minimal_symbol_d; - -DEF_VEC_O (bound_minimal_symbol_d); - /* A linespec. Elements of this structure are filled in by a parser (either parse_linespec or some other function). The structure is then converted into SALs by convert_linespec_to_sals. */ @@ -148,6 +141,9 @@ struct linespec_state /* Are we building a linespec? */ int is_linespec; + + /* !!keiths */ + const struct decode_line_limits *limits; }; /* This is a helper object that is used when collecting symbols into a @@ -244,13 +240,17 @@ struct ls_parser /* Is the entire linespec quote-enclosed? */ int is_quote_enclosed; + /* Did RESULT come from a cache? If so, don't free it when the + parser is deleted. */ + int is_cached; + /* The state of the parse. */ struct linespec_state state; #define PARSER_STATE(PPTR) (&(PPTR)->state) /* The result of the parse. */ - struct linespec result; -#define PARSER_RESULT(PPTR) (&(PPTR)->result) + struct linespec *result; +#define PARSER_RESULT(PPTR) ((PPTR)->result) }; typedef struct ls_parser linespec_parser; @@ -274,7 +274,8 @@ static struct symtabs_and_lines decode_objc (struct linespec_state *self, linespec_p ls, const char *arg); -static VEC (symtab_ptr) *symtabs_from_filename (const char *); +static VEC (symtab_ptr) *symtabs_from_filename (const char *, + VEC (objfilep) *); static VEC (symbolp) *find_label_symbols (struct linespec_state *self, VEC (symbolp) *function_symbols, @@ -302,7 +303,8 @@ static void add_all_symbol_names_from_pspace (struct collect_info *info, struct program_space *pspace, VEC (const_char_ptr) *names); -static VEC (symtab_ptr) *collect_symtabs_from_filename (const char *file); +static VEC (symtab_ptr) *collect_symtabs_from_filename (const char *file, + VEC (objfilep) *); static void decode_digits_ordinary (struct linespec_state *self, linespec_p ls, @@ -323,6 +325,12 @@ static int compare_symbols (const void *a, const void *b); static int compare_msymbols (const void *a, const void *b); +static int classify_mtype (enum minimal_symbol_type t); + +#if MERGED_INTO_COMPARE_MSYMBOLS +static int compare_msyms (const void *a, const void *b); +#endif + /* Permitted quote characters for the parser. This is different from the completer's quote characters to allow backward compatibility with the previous parser. */ @@ -962,6 +970,50 @@ iterate_name_matcher (const char *name, void *d) return 0; /* Skip this symbol. */ } +#define DEBUG_ME 0 +#define USE_RESET_REASON 1 + +static void +do_iterate_over_matching_symtab (struct linespec_state *state, + struct objfile *objfile, + struct symbol_matcher_data *mdata, + const domain_enum domain, + symbol_found_callback_ftype callback, + void *data, int include_inline) +{ + struct compunit_symtab *cu; + + if (objfile->sf) + objfile->sf->qf->expand_symtabs_matching (objfile, NULL, + iterate_name_matcher, + NULL, ALL_DOMAIN, + mdata); + + ALL_OBJFILE_COMPUNITS (objfile, cu) + { + struct symtab *symtab = COMPUNIT_FILETABS (cu); + + iterate_over_file_blocks (symtab, mdata->lookup_name, domain, + callback, data); + + if (include_inline) + { + struct symbol_and_data_callback cad = { callback, data }; + struct block *block; + int i; + + for (i = FIRST_LOCAL_BLOCK; + i < BLOCKVECTOR_NBLOCKS (SYMTAB_BLOCKVECTOR (symtab)); + i++) + { + block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), i); + state->language->la_iterate_over_symbols + (block, mdata->lookup_name, domain, iterate_inline_only, &cad); + } + } + } +} + /* A helper that walks over all matching symtabs in all objfiles and calls CALLBACK for each symbol matching NAME. If SEARCH_PSPACE is not NULL, then the search is restricted to just that program @@ -996,39 +1048,38 @@ iterate_over_all_matching_symtabs (struct linespec_state *state, set_current_program_space (pspace); - ALL_OBJFILES (objfile) - { - struct compunit_symtab *cu; - - if (objfile->sf) - objfile->sf->qf->expand_symtabs_matching (objfile, NULL, - iterate_name_matcher, - NULL, ALL_DOMAIN, - &matcher_data); +#if USE_RESET_REASON + if (state->limits != NULL && state->limits->objfiles != NULL) + { + int i; - ALL_OBJFILE_COMPUNITS (objfile, cu) + for (i = 0; + VEC_iterate (objfilep, state->limits->objfiles, i, objfile); + ++i) + { +#if DEBUG_ME + printf ("(limit) looking for \"%s\" in objfile %s\n", name, + objfile->original_name); +#endif + do_iterate_over_matching_symtab (state, objfile, &matcher_data, + domain, callback, data, + include_inline); + } + } + else +#endif + { + ALL_OBJFILES (objfile) { - struct symtab *symtab = COMPUNIT_FILETABS (cu); - - iterate_over_file_blocks (symtab, name, domain, callback, data); - - if (include_inline) - { - struct symbol_and_data_callback cad = { callback, data }; - struct block *block; - int i; - - for (i = FIRST_LOCAL_BLOCK; - i < BLOCKVECTOR_NBLOCKS (SYMTAB_BLOCKVECTOR (symtab)); - i++) - { - block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), i); - state->language->la_iterate_over_symbols - (block, name, domain, iterate_inline_only, &cad); - } - } +#if DEBUG_ME + printf ("(all) looking for \"%s\" in objfile %s\n", name, + objfile->original_name); +#endif + do_iterate_over_matching_symtab (state, objfile, &matcher_data, + domain, callback, data, + include_inline); } - } + } } } @@ -1833,6 +1884,7 @@ create_sals_line_offset (struct linespec_state *self, && VEC_index (symtab_ptr, ls->file_symtabs, 0) == NULL) { const char *fullname; + VEC (objfilep) *objfiles = NULL; set_current_program_space (self->program_space); @@ -1842,7 +1894,9 @@ create_sals_line_offset (struct linespec_state *self, fullname = symtab_to_fullname (self->default_symtab); VEC_pop (symtab_ptr, ls->file_symtabs); VEC_free (symtab_ptr, ls->file_symtabs); - ls->file_symtabs = collect_symtabs_from_filename (fullname); + if (self->limits != NULL) + objfiles = self->limits->objfiles; + ls->file_symtabs = collect_symtabs_from_filename (fullname, objfiles); use_default = 1; } @@ -2005,7 +2059,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls) else if (ls->function_symbols != NULL || ls->minimal_symbols != NULL) { /* We have just a bunch of functions and/or methods. */ - int i; + int i, classification; struct symtab_and_line sal; struct symbol *sym; bound_minimal_symbol_d *elem; @@ -2032,16 +2086,26 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls) if (ls->minimal_symbols != NULL) { - /* Sort minimal symbols by program space, too. */ + /* Sort minimal symbols by classification and program space. */ qsort (VEC_address (bound_minimal_symbol_d, ls->minimal_symbols), VEC_length (bound_minimal_symbol_d, ls->minimal_symbols), sizeof (bound_minimal_symbol_d), compare_msymbols); + /* Now the minsyms are in classification order with minsyms + of the same program space all adjacent to one another. So, + we walk over them and process just the minsyms with the same + classification as the very first minsym in the list. */ + elem = VEC_index (bound_minimal_symbol_d, ls->minimal_symbols, 0); + classification = classify_mtype (MSYMBOL_TYPE (elem->minsym)); + for (i = 0; VEC_iterate (bound_minimal_symbol_d, ls->minimal_symbols, i, elem); ++i) { + if (classify_mtype (MSYMBOL_TYPE (elem->minsym)) + != classification) + break; pspace = elem->objfile->pspace; set_current_program_space (pspace); minsym_found (state, elem->objfile, elem->minsym, &sals); @@ -2088,31 +2152,55 @@ convert_explicit_location_to_sals (struct linespec_state *self, { VEC (symbolp) *symbols, *labels; VEC (bound_minimal_symbol_d) *minimal_symbols; + VEC (symtab_ptr) *symtabs = NULL; if (explicit_loc->source_filename != NULL) { TRY { - result->file_symtabs - = symtabs_from_filename (explicit_loc->source_filename); + VEC (objfilep) *objfiles = NULL; + + if (self->limits != NULL) + objfiles = self->limits->objfiles; + symtabs + = symtabs_from_filename (explicit_loc->source_filename, objfiles); } CATCH (except, RETURN_MASK_ERROR) { source_file_not_found_error (explicit_loc->source_filename); } END_CATCH - result->explicit_loc.source_filename - = xstrdup (explicit_loc->source_filename); + + /* !!keiths: Really what we want to know is if we are doing this + incrementally, i.e., there are limits. LIMITS is just about + always non-NULL. */ +#define HAS_LIMIT(X) ((X)->limits != NULL && (X)->limits->objfiles != NULL) + if (HAS_LIMIT (self)) + { + int ix; + struct symtab *elt; + + for (ix = 0; VEC_iterate (symtab_ptr, symtabs, ix, elt); ++ix) + VEC_safe_push (symtab_ptr, result->file_symtabs, elt); + } + else + { + result->file_symtabs = symtabs; + result->explicit_loc.source_filename + = xstrdup (explicit_loc->source_filename); + } } else { /* A NULL entry means to use the default symtab. */ - VEC_safe_push (symtab_ptr, result->file_symtabs, NULL); + VEC_safe_push (symtab_ptr, symtabs, NULL); + if (!HAS_LIMIT (self)) + result->file_symtabs = symtabs; } if (explicit_loc->function_name != NULL) { - find_linespec_symbols (self, result->file_symtabs, + find_linespec_symbols (self, symtabs, explicit_loc->function_name, &symbols, &minimal_symbols); @@ -2120,28 +2208,62 @@ convert_explicit_location_to_sals (struct linespec_state *self, symbol_not_found_error (explicit_loc->function_name, result->explicit_loc.source_filename); - result->explicit_loc.function_name - = xstrdup (explicit_loc->function_name); - result->function_symbols = symbols; - result->minimal_symbols = minimal_symbols; + if (HAS_LIMIT (self)) + { + int ix; + bound_minimal_symbol_d *ms_elt; + struct symbol *s_elt; + + /* !!keiths: Ick. VEC_merge? */ + for (ix = 0; VEC_iterate (symbolp, symbols, ix, s_elt); ++ix) + VEC_safe_push (symbolp, result->function_symbols, s_elt); + for (ix = 0; VEC_iterate (bound_minimal_symbol_d, + minimal_symbols, ix, ms_elt); ++ix) + { + VEC_safe_push (bound_minimal_symbol_d, result->minimal_symbols, + ms_elt); + } + } + else + { + result->explicit_loc.function_name + = xstrdup (explicit_loc->function_name); + result->function_symbols = symbols; + result->minimal_symbols = minimal_symbols; + } } if (explicit_loc->label_name != NULL) { - symbols = NULL; - labels = find_label_symbols (self, result->function_symbols, - &symbols, explicit_loc->label_name); + VEC (symbolp) *label_symbols = NULL; + + labels = find_label_symbols (self, symbols, + &label_symbols, explicit_loc->label_name); if (labels == NULL) undefined_label_error (result->explicit_loc.function_name, explicit_loc->label_name); - result->explicit_loc.label_name = xstrdup (explicit_loc->label_name); - result->labels.label_symbols = labels; - result->labels.function_symbols = symbols; + if (HAS_LIMIT (self)) + { + int ix; + struct symbol *elt; + + for (ix = 0; VEC_iterate (symbolp, labels, ix, elt); ++ix) + VEC_safe_push (symbolp, result->labels.label_symbols, elt); + for (ix = 0; VEC_iterate (symbolp, label_symbols, ix, elt); ++ix) + VEC_safe_push (symbolp, result->labels.function_symbols, elt); + } + else + { + result->explicit_loc.label_name = xstrdup (explicit_loc->label_name); + result->labels.label_symbols = labels; + result->labels.function_symbols = label_symbols; + } } - if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN) + if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN + && !HAS_LIMIT (self)) result->explicit_loc.line_offset = explicit_loc->line_offset; return convert_linespec_to_sals (self, result); @@ -2284,8 +2406,15 @@ parse_linespec (linespec_parser *parser, const char *arg) /* Check if the input is a filename. */ TRY { + VEC (objfilep) *objfiles = NULL; + + if (PARSER_STATE (parser)->limits != NULL) + objfiles = PARSER_STATE (parser)->limits->objfiles; + PARSER_RESULT (parser)->file_symtabs - = symtabs_from_filename (user_filename); + = symtabs_from_filename (user_filename, objfiles); + /* !!keiths: From here on out, if file_symtabs does not contain + NULL, objfile limits are ALREADY taken into consideration. */ } CATCH (ex, RETURN_MASK_ERROR) { @@ -2366,19 +2495,19 @@ parse_linespec (linespec_parser *parser, const char *arg) static void linespec_state_constructor (struct linespec_state *self, - int flags, const struct language_defn *language, - struct symtab *default_symtab, - int default_line, - struct linespec_result *canonical) + const struct language_defn *language, + struct linespec_result *canonical, + const struct decode_line_options *options) { memset (self, 0, sizeof (*self)); self->language = language; - self->funfirstline = (flags & DECODE_LINE_FUNFIRSTLINE) ? 1 : 0; - self->list_mode = (flags & DECODE_LINE_LIST_MODE) ? 1 : 0; - self->default_symtab = default_symtab; - self->default_line = default_line; + self->funfirstline = (options->flags & DECODE_LINE_FUNFIRSTLINE) ? 1 : 0; + self->list_mode = (options->flags & DECODE_LINE_LIST_MODE) ? 1 : 0; + self->default_symtab = options->default_symtab; + self->default_line = options->default_line; self->canonical = canonical; self->program_space = current_program_space; + self->limits = options->limits; self->addr_set = htab_create_alloc (10, hash_address_entry, eq_address_entry, xfree, xcalloc, xfree); self->is_linespec = 0; @@ -2388,17 +2517,24 @@ linespec_state_constructor (struct linespec_state *self, static void linespec_parser_new (linespec_parser *parser, - int flags, const struct language_defn *language, - struct symtab *default_symtab, - int default_line, - struct linespec_result *canonical) + const struct language_defn *language, + struct linespec_result *canonical, + const struct decode_line_options *options) { memset (parser, 0, sizeof (linespec_parser)); parser->lexer.current.type = LSTOKEN_CONSUMED; - memset (PARSER_RESULT (parser), 0, sizeof (struct linespec)); - PARSER_EXPLICIT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN; - linespec_state_constructor (PARSER_STATE (parser), flags, language, - default_symtab, default_line, canonical); + if (options->cache == NULL) + { + PARSER_RESULT (parser) = XCNEW (struct linespec); + PARSER_EXPLICIT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN; + } + else + { + PARSER_RESULT (parser) = options->cache; + parser->is_cached = 1; + } + linespec_state_constructor (PARSER_STATE (parser), language, + canonical, options); } /* A destructor for linespec_state. */ @@ -2409,32 +2545,48 @@ linespec_state_destructor (struct linespec_state *self) htab_delete (self->addr_set); } -/* Delete a linespec parser. */ - static void -linespec_parser_delete (void *arg) +free_linespec_result (linespec_p result) { - linespec_parser *parser = (linespec_parser *) arg; + if (result == NULL) + return; - xfree (PARSER_EXPLICIT (parser)->source_filename); - xfree (PARSER_EXPLICIT (parser)->label_name); - xfree (PARSER_EXPLICIT (parser)->function_name); + xfree (result->explicit_loc.source_filename); + xfree (result->explicit_loc.label_name); + xfree (result->explicit_loc.function_name); - if (PARSER_RESULT (parser)->file_symtabs != NULL) - VEC_free (symtab_ptr, PARSER_RESULT (parser)->file_symtabs); + if (result->file_symtabs != NULL) + VEC_free (symtab_ptr, result->file_symtabs); - if (PARSER_RESULT (parser)->function_symbols != NULL) - VEC_free (symbolp, PARSER_RESULT (parser)->function_symbols); + if (result->function_symbols != NULL) + VEC_free (symbolp, result->function_symbols); - if (PARSER_RESULT (parser)->minimal_symbols != NULL) - VEC_free (bound_minimal_symbol_d, PARSER_RESULT (parser)->minimal_symbols); + if (result->minimal_symbols != NULL) + VEC_free (bound_minimal_symbol_d, result->minimal_symbols); - if (PARSER_RESULT (parser)->labels.label_symbols != NULL) - VEC_free (symbolp, PARSER_RESULT (parser)->labels.label_symbols); + if (result->labels.label_symbols != NULL) + VEC_free (symbolp, result->labels.label_symbols); + + if (result->labels.function_symbols != NULL) + VEC_free (symbolp, result->labels.function_symbols); +} - if (PARSER_RESULT (parser)->labels.function_symbols != NULL) - VEC_free (symbolp, PARSER_RESULT (parser)->labels.function_symbols); +void +invalidate_linespec_cache (struct linespec **p) +{ + free_linespec_result (*p); + *p = NULL; +} +/* Delete a linespec parser. */ + +static void +linespec_parser_delete (void *arg) +{ + linespec_parser *parser = (linespec_parser *) arg; + + if (!parser->is_cached) + free_linespec_result (PARSER_RESULT (parser)); linespec_state_destructor (PARSER_STATE (parser)); } @@ -2447,11 +2599,13 @@ linespec_lex_to_end (char **stringp) struct cleanup *cleanup; linespec_token token; const char *orig; + struct decode_line_options opts; if (stringp == NULL || *stringp == NULL) return; - linespec_parser_new (&parser, 0, current_language, NULL, 0, NULL); + init_decode_line_options (&opts); + linespec_parser_new (&parser, current_language, NULL, &opts); cleanup = make_cleanup (linespec_parser_delete, &parser); parser.lexer.saved_arg = *stringp; PARSER_STREAM (&parser) = orig = *stringp; @@ -2526,38 +2680,56 @@ event_location_to_sals (linespec_parser *parser, return result; } +/* Initialize a decode_line_options structure. + OPTS->FLAGS will be initialized to DECODE_LINE_FUNFIRSTLINE. */ + +void +init_decode_line_options (struct decode_line_options *opts) +{ + memset (opts, 0, sizeof (struct decode_line_options)); + opts->flags = DECODE_LINE_FUNFIRSTLINE; +} + /* See linespec.h. */ void -decode_line_full (const struct event_location *location, int flags, - struct symtab *default_symtab, - int default_line, struct linespec_result *canonical, - const char *select_mode, - const char *filter) +decode_line_full (const struct event_location *location, + struct linespec_result *canonical, + const struct decode_line_options *options) { struct symtabs_and_lines result; struct cleanup *cleanups; VEC (const_char_ptr) *filters = NULL; linespec_parser parser; struct linespec_state *state; + const char *copy, *orig; + const char *select_mode = options->select_mode; gdb_assert (canonical != NULL); /* The filter only makes sense for 'all'. */ - gdb_assert (filter == NULL || select_mode == multiple_symbols_all); + gdb_assert (options->filter == NULL || select_mode == multiple_symbols_all); gdb_assert (select_mode == NULL || select_mode == multiple_symbols_all || select_mode == multiple_symbols_ask || select_mode == multiple_symbols_cancel); - gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0); + gdb_assert ((options->flags & DECODE_LINE_LIST_MODE) == 0); - linespec_parser_new (&parser, flags, current_language, default_symtab, - default_line, canonical); +#if DEBUG_ME + if (options->cache != NULL) + printf ("*** got linespec cache ***\n"); +#endif + linespec_parser_new (&parser, current_language, canonical, options); cleanups = make_cleanup (linespec_parser_delete, &parser); save_current_program_space (); result = event_location_to_sals (&parser, location); state = PARSER_STATE (&parser); + if (options->limits != NULL && result.nelts == 0) + { + throw_error (NOT_FOUND_ERROR, _("didn't find function under limits")); + } + gdb_assert (result.nelts == 1 || canonical->pre_expanded); canonical->pre_expanded = 1; @@ -2584,10 +2756,10 @@ decode_line_full (const struct event_location *location, int flags, if (select_mode == multiple_symbols_all) { - if (filter != NULL) + if (options->filter != NULL) { make_cleanup (VEC_cleanup (const_char_ptr), &filters); - VEC_safe_push (const_char_ptr, filters, filter); + VEC_safe_push (const_char_ptr, filters, options->filter); filter_results (state, &result, filters); } else @@ -2596,22 +2768,31 @@ decode_line_full (const struct event_location *location, int flags, else decode_line_2 (state, &result, select_mode); + if (options->flags & DECODE_LINE_CREATE_CACHE) + { +#if DEBUG_ME + printf ("*** creating linespec cache ***\n"); +#endif + canonical->cache = PARSER_RESULT (&parser); + /* !!keiths: Hmm. Pretty sure we don't want to be free'ing + this when the cleanup is called... */ + PARSER_RESULT (&parser) = NULL; + } + do_cleanups (cleanups); } /* See linespec.h. */ struct symtabs_and_lines -decode_line_1 (const struct event_location *location, int flags, - struct symtab *default_symtab, - int default_line) +decode_line_1 (const struct event_location *location, + const struct decode_line_options *options) { struct symtabs_and_lines result; linespec_parser parser; struct cleanup *cleanups; - linespec_parser_new (&parser, flags, current_language, default_symtab, - default_line, NULL); + linespec_parser_new (&parser, current_language, NULL, options); cleanups = make_cleanup (linespec_parser_delete, &parser); save_current_program_space (); @@ -2630,6 +2811,7 @@ decode_line_with_current_source (char *string, int flags) struct symtab_and_line cursal; struct event_location *location; struct cleanup *cleanup; + struct decode_line_options options; if (string == 0) error (_("Empty line specification.")); @@ -2640,8 +2822,11 @@ decode_line_with_current_source (char *string, int flags) location = string_to_event_location (&string, current_language); cleanup = make_cleanup_delete_event_location (location); - sals = decode_line_1 (location, flags, - cursal.symtab, cursal.line); + init_decode_line_options (&options); + options.flags = flags; + options.default_symtab = cursal.symtab; + options.default_line = cursal.line; + sals = decode_line_1 (location, &options); if (*string) error (_("Junk at end of line specification: %s"), string); @@ -2658,18 +2843,23 @@ decode_line_with_last_displayed (char *string, int flags) struct symtabs_and_lines sals; struct event_location *location; struct cleanup *cleanup; + struct decode_line_options options; if (string == 0) error (_("Empty line specification.")); location = string_to_event_location (&string, current_language); cleanup = make_cleanup_delete_event_location (location); + init_decode_line_options (&options); + options.flags = flags; if (last_displayed_sal_is_valid ()) - sals = decode_line_1 (location, flags, - get_last_displayed_symtab (), - get_last_displayed_line ()); + { + options.default_symtab = get_last_displayed_symtab (); + options.default_line = get_last_displayed_line (); + sals = decode_line_1 (location, &options); + } else - sals = decode_line_1 (location, flags, (struct symtab *) NULL, 0); + sals = decode_line_1 (location, &options); if (*string) error (_("Junk at end of line specification: %s"), string); @@ -2831,6 +3021,15 @@ collect_one_symbol (struct symbol *sym, void *d) { *slot = sym; VEC_safe_push (symbolp, collector->symbols, sym); +#if DEBUG_ME + { + struct objfile *_objfile = SYMBOL_OBJFILE_OWNED (sym) ? symbol_objfile (sym) : NULL; + + printf ("(one) found symbol %s in objfile %s\n", + SYMBOL_LINKAGE_NAME (sym), + _objfile ? _objfile->original_name : "arch"); + } +#endif } return 1; /* Continue iterating. */ @@ -2925,7 +3124,15 @@ compare_msymbols (const void *a, const void *b) const struct bound_minimal_symbol *sb = (const struct bound_minimal_symbol *) b; uintptr_t uia, uib; + int ca, cb; + /* !!keiths: First compare by classification... */ + ca = classify_mtype (MSYMBOL_TYPE (sa->minsym)); + cb = classify_mtype (MSYMBOL_TYPE (sb->minsym)); + if (ca - cb != 0) + return ca - cb; + + /* !!keiths; Now compare pspaces. */ uia = (uintptr_t) sa->objfile->pspace; uib = (uintptr_t) sa->objfile->pspace; @@ -3120,7 +3327,7 @@ add_symtabs_to_list (struct symtab *symtab, void *d) /* Given a file name, return a VEC of all matching symtabs. */ static VEC (symtab_ptr) * -collect_symtabs_from_filename (const char *file) +collect_symtabs_from_filename (const char *file, VEC (objfilep) *objfiles) { struct symtab_collector collector; struct cleanup *cleanups; @@ -3138,7 +3345,7 @@ collect_symtabs_from_filename (const char *file) continue; set_current_program_space (pspace); - iterate_over_symtabs (file, add_symtabs_to_list, &collector); + iterate_over_symtabs (file, objfiles, add_symtabs_to_list, &collector); } do_cleanups (cleanups); @@ -3148,11 +3355,11 @@ collect_symtabs_from_filename (const char *file) /* Return all the symtabs associated to the FILENAME. */ static VEC (symtab_ptr) * -symtabs_from_filename (const char *filename) +symtabs_from_filename (const char *filename, VEC (objfilep) *objfiles) { VEC (symtab_ptr) *result; - result = collect_symtabs_from_filename (filename); + result = collect_symtabs_from_filename (filename, objfiles); if (VEC_empty (symtab_ptr, result)) { @@ -3532,7 +3739,18 @@ collect_symbols (struct symbol *sym, void *data) /* In list mode, add all matching symbols, regardless of class. This allows the user to type "list a_global_variable". */ if (SYMBOL_CLASS (sym) == LOC_BLOCK || info->state->list_mode) - VEC_safe_push (symbolp, info->result.symbols, sym); + { + VEC_safe_push (symbolp, info->result.symbols, sym); +#if DEBUG_ME + { + struct objfile *_objfile = SYMBOL_OBJFILE_OWNED (sym) ? symbol_objfile (sym) : NULL; + + printf ("found symbol %s in objfile %s\n", + SYMBOL_LINKAGE_NAME (sym), + _objfile ? _objfile->original_name : "arch"); + } +#endif + } return 1; /* Continue iterating. */ } @@ -3630,6 +3848,7 @@ classify_mtype (enum minimal_symbol_type t) } } +#if MERGED_INTO_COMPARE_MSYMBOLS /* Callback for qsort that sorts symbols by priority. */ static int @@ -3642,6 +3861,7 @@ compare_msyms (const void *a, const void *b) return classify_mtype (ta) - classify_mtype (tb); } +#endif /* Callback for iterate_over_minimal_symbols that adds the symbol to the result. */ @@ -3697,6 +3917,10 @@ add_minsym (struct minimal_symbol *minsym, void *d) } VEC_safe_push (bound_minimal_symbol_d, info->msyms, &mo); +#if DEBUG_ME + printf ("found minsym %s in objfile %s\n", + MSYMBOL_LINKAGE_NAME (minsym), mo.objfile->original_name); +#endif } /* Search for minimal symbols called NAME. If SEARCH_PSPACE @@ -3736,11 +3960,30 @@ search_minsyms_for_name (struct collect_info *info, const char *name, set_current_program_space (pspace); - ALL_OBJFILES (objfile) - { - local.objfile = objfile; - iterate_over_minimal_symbols (objfile, name, add_minsym, &local); - } +#if USE_RESET_REASON + if (info->state->limits != NULL + && info->state->limits->objfiles != NULL) + { + int i; + + for (i = 0; + VEC_iterate (objfilep, info->state->limits->objfiles, i, + objfile); ++i) + { + local.objfile = objfile; + iterate_over_minimal_symbols (objfile, name, add_minsym, + &local); + } + } + else +#endif + { + ALL_OBJFILES (objfile) + { + local.objfile = objfile; + iterate_over_minimal_symbols (objfile, name, add_minsym, &local); + } + } } } else @@ -3756,28 +3999,17 @@ search_minsyms_for_name (struct collect_info *info, const char *name, if (!VEC_empty (bound_minimal_symbol_d, local.msyms)) { - int classification; int ix; bound_minimal_symbol_d *item; - qsort (VEC_address (bound_minimal_symbol_d, local.msyms), - VEC_length (bound_minimal_symbol_d, local.msyms), - sizeof (bound_minimal_symbol_d), - compare_msyms); - - /* Now the minsyms are in classification order. So, we walk - over them and process just the minsyms with the same - classification as the very first minsym in the list. */ - item = VEC_index (bound_minimal_symbol_d, local.msyms, 0); - classification = classify_mtype (MSYMBOL_TYPE (item->minsym)); - + /* !!keiths: This pushes ALL minsyms up. This is a small + internal API change, but is needed in order to cache the + linespec result. Lower priority minsym classes will be + filtered when the SaLs are actually created. */ for (ix = 0; VEC_iterate (bound_minimal_symbol_d, local.msyms, ix, item); ++ix) { - if (classify_mtype (MSYMBOL_TYPE (item->minsym)) != classification) - break; - VEC_safe_push (bound_minimal_symbol_d, info->result.minimal_symbols, item); } @@ -3896,6 +4128,7 @@ destroy_linespec_result (struct linespec_result *ls) xfree (lsal->sals.sals); } VEC_free (linespec_sals, ls->sals); + free_linespec_result (ls->cache); } /* Cleanup function for a linespec_result. */ @@ -3921,3 +4154,9 @@ get_gdb_linespec_parser_quote_characters (void) { return linespec_quote_characters; } + +void +init_decode_line_limits (struct decode_line_limits *limits) +{ + memset (limits, 0, sizeof (struct decode_line_limits)); +} diff --git a/gdb/linespec.h b/gdb/linespec.h index 2a76283..83f4e9f 100644 --- a/gdb/linespec.h +++ b/gdb/linespec.h @@ -18,8 +18,27 @@ #define LINESPEC_H 1 struct symtab; +struct bp_location; +struct symbol; +struct linespec; -#include "vec.h" +#include "gdb_vecs.h" + +enum decode_line_limits_op + { + DECODE_LINE_LIMITS_ADD, + DECODE_LINE_LIMITS_REMOVE, + DECODE_LINE_LIMITS_INVALIDATE + }; + +struct decode_line_limits +{ + enum decode_line_limits_op op; + /* !!keiths: union? */ + VEC (objfilep) *objfiles; +}; + +extern void init_decode_line_limits (struct decode_line_limits *); /* Flags to pass to decode_line_1 and decode_line_full. */ @@ -32,9 +51,38 @@ enum decode_line_flags /* Set this flag if you want "list mode". In this mode, a FILE:LINE linespec will always return a result, and such linespecs will not be expanded to all matches. */ - DECODE_LINE_LIST_MODE = 2 + DECODE_LINE_LIST_MODE = 2, + + DECODE_LINE_CREATE_CACHE = 4 }; +/* Options for how decode_line_full and decode_line_1 behave. + Use init_decode_line_options to initialize it. */ + +struct decode_line_options +{ + /* One of the above decode_line_flags. */ + int flags; + + /* The default location. If NULL, use the current symtab + and line. */ + struct symtab *default_symtab; + int default_line; + + /* One of the multiple_symbols_* constants or NULL, in which case + the appropriate CLI value is used. */ + const char *select_mode; + + /* A string holding a canonical name used for (post-) filtering. + If NULL, no filtering is done. Only valid when SELECT_MODE + is multiple_symbols_all. */ + const char *filter; + + /* !!keiths */ + const struct decode_line_limits *limits; + struct linespec *cache; +}; + /* decode_line_full returns a vector of these. */ struct linespec_sals @@ -78,6 +126,9 @@ struct linespec_result /* The sals. The vector will be freed by destroy_linespec_result. */ VEC (linespec_sals) *sals; + + /* Cache used to generate the above SaLs. */ + struct linespec *cache; }; /* Initialize a linespec_result. */ @@ -93,11 +144,21 @@ extern void destroy_linespec_result (struct linespec_result *); extern struct cleanup * make_cleanup_destroy_linespec_result (struct linespec_result *); -/* Decode a linespec using the provided default symtab and line. */ +/* Invalidate the linespec cache pointed to by P. */ + +extern void invalidate_linespec_cache (struct linespec **p); + +/* Initialize a decode_line_options structure. + OPTS->FLAGS will be initialized to DECODE_LINE_FUNFIRSTLINE. */ + +extern void init_decode_line_options (struct decode_line_options *opts); + +/* Decode a linespec using the provided OPTIONS. The only valid + members are OPTIONS->default_symtab and OPTIONS->default_line. */ extern struct symtabs_and_lines - decode_line_1 (const struct event_location *location, int flags, - struct symtab *default_symtab, int default_line); + decode_line_1 (const struct event_location *location, + const struct decode_line_options *options); /* Parse LOCATION and return results. This is the "full" interface to this module, which handles multiple results @@ -135,11 +196,9 @@ extern struct symtabs_and_lines strcmp sense) to FILTER will be returned; all others will be filtered out. */ -extern void decode_line_full (const struct event_location *location, int flags, - struct symtab *default_symtab, int default_line, +extern void decode_line_full (const struct event_location *location, struct linespec_result *canonical, - const char *select_mode, - const char *filter); + const struct decode_line_options *options); /* Given a string, return the line specified by it, using the current source symtab and line as defaults. diff --git a/gdb/minsyms.h b/gdb/minsyms.h index 0b9f012..8fdc4ee 100644 --- a/gdb/minsyms.h +++ b/gdb/minsyms.h @@ -37,6 +37,9 @@ struct bound_minimal_symbol struct objfile *objfile; }; +typedef struct bound_minimal_symbol bound_minimal_symbol_d; +DEF_VEC_O (bound_minimal_symbol_d); + /* This header declares most of the API for dealing with minimal symbols and minimal symbol tables. A few things are declared elsewhere; see below. diff --git a/gdb/objfiles.c b/gdb/objfiles.c index d33379f..0ea60f6 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -971,7 +971,13 @@ objfile_relocate (struct objfile *objfile, /* Relocate breakpoints as necessary, after things are relocated. */ if (changed) - breakpoint_re_set (); + { + struct breakpoint_reset_reason r; + + init_breakpoint_reset_reason (&r); + r.where = __func__; + breakpoint_re_set (&r); + } } /* Rebase (add to the offsets) OBJFILE by SLIDE. SEPARATE_DEBUG_OBJFILE is @@ -1010,7 +1016,13 @@ objfile_rebase (struct objfile *objfile, CORE_ADDR slide) /* Relocate breakpoints as necessary, after things are relocated. */ if (changed) - breakpoint_re_set (); + { + struct breakpoint_reset_reason r; + + init_breakpoint_reset_reason (&r); + r.where = __func__; + breakpoint_re_set (&r); + } } /* Return non-zero if OBJFILE has partial symbols. */ diff --git a/gdb/python/python.c b/gdb/python/python.c index 1c2d5c6..156500a 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -748,7 +748,13 @@ gdbpy_decode_line (PyObject *self, PyObject *args) TRY { if (location != NULL) - sals = decode_line_1 (location, 0, 0, 0); + { + struct decode_line_options options; + + init_decode_line_options (&options); + options.flags = 0; + sals = decode_line_1 (location, &options); + } else { set_default_source_symtab_and_line (); diff --git a/gdb/solib.c b/gdb/solib.c index 9a6e7de..4fca342 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -969,6 +969,11 @@ solib_add (const char *pattern, int from_tty, struct target_ops *target, int readsyms) { struct so_list *gdb; + struct breakpoint_reset_reason reset_reason; + + init_breakpoint_reset_reason (&reset_reason); + reset_reason.reason = BREAKPOINT_RESET_ADD_OBJFILE; + reset_reason.where = __func__; if (print_symbol_loading_p (from_tty, 0, 0)) { @@ -1025,12 +1030,16 @@ solib_add (const char *pattern, int from_tty, gdb->so_name); } else if (solib_read_symbols (gdb, flags)) - loaded_any_symbols = 1; + { + VEC_safe_push (objfilep, reset_reason.objfile_list, + gdb->objfile); + loaded_any_symbols = 1; + } } } if (loaded_any_symbols) - breakpoint_re_set (); + breakpoint_re_set (&reset_reason); if (from_tty && pattern && ! any_matches) printf_unfiltered @@ -1423,6 +1432,7 @@ reload_shared_libraries (char *ignored, int from_tty, struct cmd_list_element *e) { const struct target_so_ops *ops; + struct breakpoint_reset_reason reset_reason; reload_shared_libraries_1 (from_tty); @@ -1460,7 +1470,10 @@ reload_shared_libraries (char *ignored, int from_tty, solib_add (NULL, 0, NULL, auto_solib_add); - breakpoint_re_set (); + init_breakpoint_reset_reason (&reset_reason); + /*reset_reason.reason = BREAKPOINT_RESET_???;*/ + reset_reason.where = __func__; + breakpoint_re_set (&reset_reason); /* We may have loaded or unloaded debug info for some (or all) shared libraries. However, frames may still reference them. For diff --git a/gdb/symfile.c b/gdb/symfile.c index 682e3ca..5980c65 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -1114,7 +1114,13 @@ finish_new_objfile (struct objfile *objfile, int add_flags) } else if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) { - breakpoint_re_set (); + struct breakpoint_reset_reason r; + + init_breakpoint_reset_reason (&r); + /*r.reason = BREAKPOINT_RESET_???;*/ + /*VEC_safe_push (objfilep, &(r.objfile_list), objfile);*/ + r.where = __func__; + breakpoint_re_set (&r); } /* We're done reading the symbol file; finish off complaints. */ @@ -2072,6 +2078,7 @@ generic_load (const char *args, int from_tty) struct load_section_data cbdata; struct load_progress_data total_progress; struct ui_out *uiout = current_uiout; + struct breakpoint_reset_reason reset_reason; CORE_ADDR entry; char **argv; @@ -2154,7 +2161,11 @@ generic_load (const char *args, int from_tty) breakpoint locations. Loading has changed the contents of that memory. */ - breakpoint_re_set (); + init_breakpoint_reset_reason (&reset_reason); + reset_reason.reason = BREAKPOINT_RESET_ADD_OBJFILE; + /*VEC_safe_push (objfilep, &(reset_reason.objfile_list), ???); */ + reset_reason.where = __func__; + breakpoint_re_set (&reset_reason); /* FIXME: are we supposed to call symbol_file_add or not? According to a comment from remote-mips.c (where a call to symbol_file_add @@ -2458,10 +2469,6 @@ remove_symbol_file_command (char *args, int from_tty) do_cleanups (my_cleanups); } -typedef struct objfile *objfilep; - -DEF_VEC_P (objfilep); - /* Re-read symbols if a symbol-file has changed. */ void @@ -3022,7 +3029,14 @@ clear_symtab_users (int add_flags) /* Now that the various caches have been cleared, we can re_set our breakpoints without risking it using stale data. */ if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) - breakpoint_re_set (); + { + struct breakpoint_reset_reason r; + + init_breakpoint_reset_reason (&r); + /*r.reason = BREAKPOINT_RESET_???;*/ + r.where = __func__; + breakpoint_re_set (&r); + } } static void diff --git a/gdb/symtab.c b/gdb/symtab.c index c95b651..f0255b6 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -416,11 +416,16 @@ iterate_over_some_symtabs (const char *name, psymtabs. *If* there is no '/' in the name, a match after a '/' in the symtab filename will also work. + If OBJFILES is NULL, iterate over all objfiles; otherwise, limit + the search to those listed in OBJFILES. + Calls CALLBACK with each symtab that is found and with the supplied DATA. If CALLBACK returns true, the search stops. */ +#define DEBUG_ME 0 + void -iterate_over_symtabs (const char *name, +iterate_over_symtabs (const char *name, VEC (objfilep) *objfiles, int (*callback) (struct symtab *symtab, void *data), void *data) @@ -438,32 +443,117 @@ iterate_over_symtabs (const char *name, gdb_assert (IS_ABSOLUTE_PATH (real_path)); } - ALL_OBJFILES (objfile) - { - if (iterate_over_some_symtabs (name, real_path, callback, data, - objfile->compunit_symtabs, NULL)) + if (objfiles == NULL) + { + ALL_OBJFILES (objfile) { - do_cleanups (cleanups); - return; +#if DEBUG_ME + printf ("(all) looking for '%s' symtabs in %s ... ", name, + objfile->original_name); +#endif + if (iterate_over_some_symtabs (name, real_path, callback, data, + objfile->compunit_symtabs, NULL)) + { +#if DEBUG_ME + printf ("*** found ***\n"); +#endif + do_cleanups (cleanups); + return; + } +#if DEBUG_ME + else + printf ("not found\n"); +#endif } - } + } + else + { + int i; + struct objfile *elt; + + for (i = 0; VEC_iterate (objfilep, objfiles, i, elt); ++i) + { +#if DEBUG_ME + printf ("(limit) looking for '%s' symtabs in %s ... ", name, + elt->original_name); +#endif + if (iterate_over_some_symtabs (name, real_path, callback, + data, elt->compunit_symtabs, NULL)) + { +#if DEBUG_ME + printf ("found\n"); +#endif + do_cleanups (cleanups); + return; + } +#if DEBUG_ME + else + printf ("not found\n"); +#endif + } + } /* Same search rules as above apply here, but now we look thru the psymtabs. */ - ALL_OBJFILES (objfile) - { - if (objfile->sf - && objfile->sf->qf->map_symtabs_matching_filename (objfile, - name, - real_path, - callback, - data)) + if (objfiles == NULL) + { + ALL_OBJFILES (objfile) { - do_cleanups (cleanups); - return; +#if DEBUG_ME + printf ("(all) looking for '%s' psymtabs in %s ... ", name, + objfile->original_name); +#endif + if (objfile->sf + && objfile->sf->qf->map_symtabs_matching_filename (objfile, + name, + real_path, + callback, + data)) + { +#if DEBUG_ME + printf ("found\n"); +#endif + do_cleanups (cleanups); + return; + } +#if DEBUG_ME + else + printf ("not found\n"); +#endif + } - } + } + else + { + int i; + struct objfile *elt; + + for (i = 0; VEC_iterate (objfilep, objfiles, i, elt); ++i) + { +#if DEBUG_ME + printf ("(limit) looking for '%s' psymtabs in %s ... ", name, + elt->original_name); +#endif + if (elt->sf != NULL + && elt->sf->qf->map_symtabs_matching_filename (elt, + name, + real_path, + callback, + data)) + { +#if DEBUG_ME + printf ("found\n"); +#endif + do_cleanups (cleanups); + return; + } +#if DEBUG_ME + else + printf ("not found\n"); +#endif + } + } do_cleanups (cleanups); } @@ -487,7 +577,7 @@ lookup_symtab (const char *name) { struct symtab *result = NULL; - iterate_over_symtabs (name, lookup_symtab_callback, &result); + iterate_over_symtabs (name, NULL, lookup_symtab_callback, &result); return result; } diff --git a/gdb/symtab.h b/gdb/symtab.h index d3f6370..86fcf39 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -816,6 +816,9 @@ struct symbol struct symbol *hash_next; }; +typedef struct symbol *symbolp; +DEF_VEC_P (symbolp); + /* Several lookup functions return both a symbol and the block in which the symbol is found. This structure is used in these cases. */ @@ -1603,6 +1606,7 @@ int iterate_over_some_symtabs (const char *name, struct compunit_symtab *after_last); void iterate_over_symtabs (const char *name, + VEC (objfilep) *objfiles, int (*callback) (struct symtab *symtab, void *data), void *data); diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 6ca66e7..9ff61e3 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -2713,6 +2713,7 @@ scope_info (char *args, int from_tty) int regno; struct event_location *location; struct cleanup *back_to; + struct decode_line_options options; if (args == 0 || *args == 0) error (_("requires an argument (function, " @@ -2720,7 +2721,8 @@ scope_info (char *args, int from_tty) location = string_to_event_location (&args, current_language); back_to = make_cleanup_delete_event_location (location); - sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE, NULL, 0); + init_decode_line_options (&options); + sals = decode_line_1 (location, &options); if (sals.nelts == 0) { /* Presumably decode_line_1 has already warned. */ -- cgit v1.1