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
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 @@
 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 @@
 }
 
 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 @@
 }
 
 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 @@
 }
 
 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 @@
       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 @@
 /* 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 @@
 	    = 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 @@
 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 @@
   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 @@
   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 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 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 @@
 
   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 @@
 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 @@
 		       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 @@
      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 @@
 	      && 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 @@
 				   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 @@
   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 @@
      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 @@
 /* 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 @@
   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 @@
   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 @@
 /* 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 @@
 }
 
 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 @@
 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 @@
 /* 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 @@
       return;
     }
 
-  breakpoint_re_set_default (b);
+  breakpoint_re_set_default (b, reason);
 }
 
 static int
@@ -13153,15 +13201,17 @@
 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 @@
 /* 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 @@
 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 @@
 /* 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 @@
 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 @@
 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 @@
 /* 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 @@
 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 @@
 
       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_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 @@
 
   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 @@
 	  && (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 @@
     }
   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 @@
    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;
 
-  sals = location_to_sals (b, b->location, &found);
+  /* 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;
+
+    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 @@
 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 @@
       lsal->sals.sals = NULL;
     }
 
+  b->linespec_cache = canonical.cache;
+  canonical.cache = NULL;
   destroy_linespec_result (&canonical);
 }
 
@@ -14411,26 +14516,38 @@
   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 @@
   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 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 @@
   /* 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 @@
      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 @@
 
     /* 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 @@
 					 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 @@
       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 @@
   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 @@
       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_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 <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.  */
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 @@
 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 @@
      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 @@
 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 @@
      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 @@
   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 @@
      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 @@
   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 @@
 
   /* 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 @@
   /* 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 @@
 					     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 @@
 					      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_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 @@
   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 @@
 
     set_current_program_space (pspace);
 
-    ALL_OBJFILES (objfile)
-    {
-      struct compunit_symtab *cu;
+#if USE_RESET_REASON
+    if (state->limits != NULL && state->limits->objfiles != NULL)
+      {
+	int i;
 
-      if (objfile->sf)
-	objfile->sf->qf->expand_symtabs_matching (objfile, NULL,
-						  iterate_name_matcher,
-						  NULL, ALL_DOMAIN,
-						  &matcher_data);
-
-      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 @@
       && 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 @@
       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 @@
   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 @@
 
       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 @@
 {
   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 @@
 	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 @@
       /* 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 @@
 
 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 @@
 
 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,6 +2545,39 @@
   htab_delete (self->addr_set);
 }
 
+static void
+free_linespec_result (linespec_p result)
+{
+  if (result == NULL)
+    return;
+
+  xfree (result->explicit_loc.source_filename);
+  xfree (result->explicit_loc.label_name);
+  xfree (result->explicit_loc.function_name);
+
+  if (result->file_symtabs != NULL)
+    VEC_free (symtab_ptr, result->file_symtabs);
+
+  if (result->function_symbols != NULL)
+    VEC_free (symbolp, result->function_symbols);
+
+  if (result->minimal_symbols != NULL)
+    VEC_free (bound_minimal_symbol_d, result->minimal_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);
+}
+
+void
+invalidate_linespec_cache (struct linespec **p)
+{
+  free_linespec_result (*p);
+  *p = NULL;
+}
+
 /* Delete a linespec parser.  */
 
 static void
@@ -2416,25 +2585,8 @@
 {
   linespec_parser *parser = (linespec_parser *) arg;
 
-  xfree (PARSER_EXPLICIT (parser)->source_filename);
-  xfree (PARSER_EXPLICIT (parser)->label_name);
-  xfree (PARSER_EXPLICIT (parser)->function_name);
-
-  if (PARSER_RESULT (parser)->file_symtabs != NULL)
-    VEC_free (symtab_ptr, PARSER_RESULT (parser)->file_symtabs);
-
-  if (PARSER_RESULT (parser)->function_symbols != NULL)
-    VEC_free (symbolp, PARSER_RESULT (parser)->function_symbols);
-
-  if (PARSER_RESULT (parser)->minimal_symbols != NULL)
-    VEC_free (bound_minimal_symbol_d, PARSER_RESULT (parser)->minimal_symbols);
-
-  if (PARSER_RESULT (parser)->labels.label_symbols != NULL)
-    VEC_free (symbolp, PARSER_RESULT (parser)->labels.label_symbols);
-
-  if (PARSER_RESULT (parser)->labels.function_symbols != NULL)
-    VEC_free (symbolp, PARSER_RESULT (parser)->labels.function_symbols);
-
+  if (!parser->is_cached)
+    free_linespec_result (PARSER_RESULT (parser));
   linespec_state_destructor (PARSER_STATE (parser));
 }
 
@@ -2447,11 +2599,13 @@
   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 @@
   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 @@
 
   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 @@
   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 @@
   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 @@
 
   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 @@
   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 @@
     {
       *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 @@
   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 @@
 /* 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 @@
       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 @@
 /* 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 @@
   /* 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 @@
     }
 }
 
+#if MERGED_INTO_COMPARE_MSYMBOLS
 /* Callback for qsort that sorts symbols by priority.  */
 
 static int
@@ -3642,6 +3861,7 @@
 
   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 @@
       }
 
   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 @@
 
 	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 @@
 
     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 @@
       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 @@
 {
   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 @@
     /* 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 @@
   /* 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 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 @@
    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 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 @@
 
   /* 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 @@
 
   /* 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 @@
   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 @@
 	   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 @@
 				       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 @@
 			 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 @@
 
   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 @@
     }
   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 @@
   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 @@
      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 @@
   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 @@
   /* 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 @@
    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 @@
       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 @@
 {
   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 *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 @@
 			       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 @@
   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 @@
 
   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.  */