]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Initial publication of breakpoint reset project. users/keiths/intelligent-breakpoint_re_set
authorKeith Seitz <keiths@redhat.com>
Wed, 30 Sep 2015 21:23:12 +0000 (14:23 -0700)
committerKeith Seitz <keiths@redhat.com>
Thu, 1 Oct 2015 18:48:39 +0000 (11:48 -0700)
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

20 files changed:
gdb/ada-lang.c
gdb/ax-gdb.c
gdb/break-catch-throw.c
gdb/breakpoint.c
gdb/breakpoint.h
gdb/cli/cli-cmds.c
gdb/common/gdb_vecs.h
gdb/dwarf2read.c
gdb/infcmd.c
gdb/infrun.c
gdb/linespec.c
gdb/linespec.h
gdb/minsyms.h
gdb/objfiles.c
gdb/python/python.c
gdb/solib.c
gdb/symfile.c
gdb/symtab.c
gdb/symtab.h
gdb/tracepoint.c

index a229fa1243df8fb459a3d64ad610e8cd55cceb75..fd712fe39b165ff88743cb790ac4434148669cc2 100644 (file)
@@ -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);
 }
index 817fa53ed90b2f33f6c54ab79bde707df3976c9f..70c351f6ab8262ffe7cd7e1aec0c92a9c2191bb9 100644 (file)
@@ -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] == ',')
index 1ba505b6e49071c0752763e28c04c2d5624b5ec6..e2668b524a2978b0b7870adf939bb7ace9064a58 100644 (file)
@@ -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);
index 2c901ff5f2fe755026278927db564be939545011..eda45d4f9f41e52322b2c98190608740f49a5427 100644 (file)
@@ -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;
 
index 896d3ebb420ade5761dfddb6a60f29947aa8d779..71875d5d9c1a9217573d64a649e7d593f28e84f0 100644 (file)
@@ -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 *);
 
index 6753c7053dbd86235889a8d9c050d6a7b8bb3662..086bcd922e0261048f826b3396996d67eac8bd40 100644 (file)
@@ -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)
index b3f56f8e0f4dfa3ba9b6a4a7463d46504ffdbc53..892af1f56777145b6c1815ecde7173df448f5387 100644 (file)
 
 #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 *
index 5b1234209486cdc617ae57972648d0fd0d62fb5b..610ddbf7e83cc42fb068a301a3bd6a45e1c8e488 100644 (file)
@@ -74,9 +74,6 @@
 #include <fcntl.h>
 #include <sys/types.h>
 
-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.  */
index 54aa1ef4cc49cfa01669972978bbc3ef33dca442..be31642459c720e97b20446f35634d88e7aead99 100644 (file)
@@ -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);
 }
index cf9137031979b0339c5bc620a3a7f9a68207152e..0b1f451f26f3049ac2bbf41de94ae1e3d3b71152 100644 (file)
@@ -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
index b2233b92d8d263b941914be243be78ccbb43f10f..f1611b3e9b822c79e0c27328f3728f25998d0c6f 100644 (file)
@@ -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));
+}
index 2a76283cfc3cccf3bdaeb80ee3e2d401eba5f650..83f4e9fbffb8586abb314b87239c35c6d38484ee 100644 (file)
 #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.
index 0b9f01225009346ce858f4cd4f5ea5992c1ce3c4..8fdc4eebf79c8227682d339b70e229a87b146921 100644 (file)
@@ -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.
index d33379f58e0c6cac65214c951e306f6389f58709..0ea60f69edcc7018d01b0153d91369916ababd57 100644 (file)
@@ -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);
+    }
 }
 \f
 /* Return non-zero if OBJFILE has partial symbols.  */
index 1c2d5c600e5ec293b04b77e292a4d9f9a902068b..156500ada73974f4d8e24fc999b062b2ead92971 100644 (file)
@@ -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 ();
index 9a6e7dee458ef9923bbe16338f68fe4bd0c4053d..4fca34260e0552345ba40ecb0c9ade27ca665cda 100644 (file)
@@ -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
index 682e3cab6dc7d6665d93c63c6447f05a58412f0e..5980c65df7cc93da386d0cbdacbfa421a5bc0470 100644 (file)
@@ -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
index c95b651f69a09d9579be498a008d6fa04de459f9..f0255b6737514527d4ce6b002db683236d4d25a1 100644 (file)
@@ -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;
 }
 
index d3f6370666b00598f697e07e4ba7fd84fc473aa1..86fcf394547136947bd1aa48808c1fbb8cca53f0 100644 (file)
@@ -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);
index 6ca66e7c8d1849992d03c604d4a2e6b68b164d14..9ff61e3cc9f4207760d85cedb7a0ccfd810e3d2b 100644 (file)
@@ -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.  */