gdb: add inferior-specific breakpoints
[binutils-gdb.git] / gdb / breakpoint.c
index 0cdf5a7158b4a6e9ee8d80a99d64beeef84d829f..f88ca1c9b65202a665da1f3ac819f0ab4c16921a 100644 (file)
@@ -83,6 +83,7 @@
 #include "progspace-and-thread.h"
 #include "gdbsupport/array-view.h"
 #include "gdbsupport/gdb_optional.h"
+#include "gdbsupport/common-utils.h"
 
 /* Prototypes for local functions.  */
 
@@ -98,7 +99,7 @@ static void create_breakpoints_sal (struct gdbarch *,
                                    gdb::unique_xmalloc_ptr<char>,
                                    gdb::unique_xmalloc_ptr<char>,
                                    enum bptype,
-                                   enum bpdisp, int, int,
+                                   enum bpdisp, int, int, int,
                                    int,
                                    int, int, int, unsigned);
 
@@ -200,6 +201,68 @@ enum ugll_insert_mode
   UGLL_INSERT
 };
 
+/* Return a textual version of INSERT_MODE.  */
+
+static const char *
+ugll_insert_mode_text (ugll_insert_mode insert_mode)
+{
+/* Make sure the compiler warns if a new ugll_insert_mode enumerator is added
+   but not handled here.  */
+DIAGNOSTIC_PUSH
+DIAGNOSTIC_ERROR_SWITCH
+  switch (insert_mode)
+    {
+    case UGLL_DONT_INSERT:
+      return "UGLL_DONT_INSERT";
+    case UGLL_MAY_INSERT:
+      return "UGLL_MAY_INSERT";
+    case UGLL_INSERT:
+      return "UGLL_INSERT";
+    }
+DIAGNOSTIC_POP
+
+  gdb_assert_not_reached ("must handle all enum values");
+}
+
+/* Return a textual version of REASON.  */
+
+static const char *
+remove_bp_reason_str (remove_bp_reason reason)
+{
+/* Make sure the compiler warns if a new remove_bp_reason enumerator is added
+   but not handled here.  */
+DIAGNOSTIC_PUSH
+DIAGNOSTIC_ERROR_SWITCH
+  switch (reason)
+    {
+    case REMOVE_BREAKPOINT:
+      return "regular remove";
+    case DETACH_BREAKPOINT:
+      return "detach";
+    }
+DIAGNOSTIC_POP
+
+  gdb_assert_not_reached ("must handle all enum values");
+}
+
+/* Return a textual version of breakpoint location BL describing number,
+   location and address.  */
+
+static std::string
+breakpoint_location_address_str (const bp_location *bl)
+{
+  std::string str = string_printf ("Breakpoint %d (%s) at address %s",
+                                  bl->owner->number,
+                                  host_address_to_string (bl),
+                                  paddress (bl->gdbarch, bl->address));
+
+  std::string loc_string = bl->to_string ();
+  if (!loc_string.empty ())
+    str += string_printf (" %s", loc_string.c_str ());
+
+  return str;
+}
+
 static void update_global_location_list (enum ugll_insert_mode);
 
 static void update_global_location_list_nothrow (enum ugll_insert_mode);
@@ -322,6 +385,9 @@ struct momentary_breakpoint : public code_breakpoint
     disposition = disp_donttouch;
     frame_id = frame_id_;
     thread = thread_;
+
+    /* The inferior should have been set by the parent constructor.  */
+    gdb_assert (inferior == -1);
   }
 
   void re_set () override;
@@ -510,6 +576,22 @@ show_always_inserted_mode (struct ui_file *file, int from_tty,
              value);
 }
 
+/* True if breakpoint debug output is enabled.  */
+static bool debug_breakpoint = false;
+
+/* Print a "breakpoint" debug statement.  */
+#define breakpoint_debug_printf(fmt, ...) \
+  debug_prefixed_printf_cond (debug_breakpoint, "breakpoint", fmt, \
+                             ##__VA_ARGS__)
+
+/* "show debug breakpoint" implementation.  */
+static void
+show_debug_breakpoint (struct ui_file *file, int from_tty,
+                      struct cmd_list_element *c, const char *value)
+{
+  gdb_printf (file, _("Breakpoint location debugging is %s.\n"), value);
+}
+
 /* See breakpoint.h.  */
 
 int
@@ -614,14 +696,14 @@ bool target_exact_watchpoints = false;
 
 /* Chains of all breakpoints defined.  */
 
-static struct breakpoint *breakpoint_chain;
+static intrusive_list<breakpoint> breakpoint_chain;
 
 /* See breakpoint.h.  */
 
 breakpoint_range
 all_breakpoints ()
 {
-  return breakpoint_range (breakpoint_chain);
+  return breakpoint_range (breakpoint_chain.begin (), breakpoint_chain.end ());
 }
 
 /* See breakpoint.h.  */
@@ -637,7 +719,8 @@ all_breakpoints_safe ()
 tracepoint_range
 all_tracepoints ()
 {
-  return tracepoint_range (breakpoint_chain);
+  return tracepoint_range (tracepoint_iterator (breakpoint_chain.begin ()),
+                          tracepoint_iterator (breakpoint_chain.end ()));
 }
 
 /* Array is sorted by bp_location_is_less_than - primarily by the ADDRESS.  */
@@ -792,8 +875,8 @@ scoped_rbreak_breakpoints::~scoped_rbreak_breakpoints ()
 void
 clear_breakpoint_hit_counts (void)
 {
-  for (breakpoint *b : all_breakpoints ())
-    b->hit_count = 0;
+  for (breakpoint &b : all_breakpoints ())
+    b.hit_count = 0;
 }
 
 \f
@@ -803,9 +886,9 @@ clear_breakpoint_hit_counts (void)
 struct breakpoint *
 get_breakpoint (int num)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->number == num)
-      return b;
+  for (breakpoint &b : all_breakpoints ())
+    if (b.number == num)
+      return &b;
   
   return nullptr;
 }
@@ -816,9 +899,9 @@ get_breakpoint (int num)
 static bool
 has_multiple_locations (int num)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->number == num)
-      return b->has_multiple_locations ();
+  for (breakpoint &b : all_breakpoints ())
+    if (b.number == num)
+      return b.has_multiple_locations ();
 
   return false;
 }
@@ -994,6 +1077,15 @@ set_breakpoint_location_condition (const char *cond_string, bp_location *loc,
     error (_("Garbage '%s' follows condition"), cond_string);
 }
 
+/* See breakpoint.h.  */
+
+void
+notify_breakpoint_modified (breakpoint *b)
+{
+  interps_notify_breakpoint_modified (b);
+  gdb::observers::breakpoint_modified.notify (b);
+}
+
 void
 set_breakpoint_condition (struct breakpoint *b, const char *exp,
                          int from_tty, bool force)
@@ -1086,7 +1178,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
     }
   mark_breakpoint_modified (b);
 
-  gdb::observers::breakpoint_modified.notify (b);
+  notify_breakpoint_modified (b);
 }
 
 /* See breakpoint.h.  */
@@ -1095,14 +1187,14 @@ void
 set_breakpoint_condition (int bpnum, const char *exp, int from_tty,
                          bool force)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->number == bpnum)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.number == bpnum)
       {
        /* Check if this breakpoint has a "stop" method implemented in an
           extension language.  This method and conditions entered into GDB
           from the CLI are mutually exclusive.  */
        const struct extension_language_defn *extlang
-         = get_breakpoint_cond_ext_lang (b, EXT_LANG_NONE);
+         = get_breakpoint_cond_ext_lang (&b, EXT_LANG_NONE);
 
        if (extlang != NULL)
          {
@@ -1110,9 +1202,9 @@ set_breakpoint_condition (int bpnum, const char *exp, int from_tty,
                     " a %s stop condition defined for this breakpoint."),
                   ext_lang_capitalized_name (extlang));
          }
-       set_breakpoint_condition (b, exp, from_tty, force);
+       set_breakpoint_condition (&b, exp, from_tty, force);
 
-       if (is_breakpoint (b))
+       if (is_breakpoint (&b))
          update_global_location_list (UGLL_MAY_INSERT);
 
        return;
@@ -1187,11 +1279,11 @@ condition_completer (struct cmd_list_element *cmd,
       /* We're completing the breakpoint number.  */
       len = strlen (text);
 
-      for (breakpoint *b : all_breakpoints ())
+      for (breakpoint &b : all_breakpoints ())
        {
          char number[50];
 
-         xsnprintf (number, sizeof (number), "%d", b->number);
+         xsnprintf (number, sizeof (number), "%d", b.number);
 
          if (strncmp (number, text, len) == 0)
            tracker.add_completion (make_unique_xstrdup (number));
@@ -1408,13 +1500,13 @@ static_tracepoints_here (CORE_ADDR addr)
 {
   std::vector<breakpoint *> found;
 
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_static_tracepoint
-       || b->type == bp_static_marker_tracepoint)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_static_tracepoint
+       || b.type == bp_static_marker_tracepoint)
       {
-       for (bp_location &loc : b->locations ())
+       for (bp_location &loc : b.locations ())
          if (loc.address == addr)
-           found.push_back (b);
+           found.push_back (&b);
       }
 
   return found;
@@ -1430,7 +1522,7 @@ breakpoint_set_commands (struct breakpoint *b,
   validate_commands_for_breakpoint (b, commands.get ());
 
   b->commands = std::move (commands);
-  gdb::observers::breakpoint_modified.notify (b);
+  notify_breakpoint_modified (b);
 }
 
 /* Set the internal `silent' flag on the breakpoint.  Note that this
@@ -1444,7 +1536,7 @@ breakpoint_set_silent (struct breakpoint *b, int silent)
 
   b->silent = silent;
   if (old_silent != silent)
-    gdb::observers::breakpoint_modified.notify (b);
+    notify_breakpoint_modified (b);
 }
 
 /* See breakpoint.h.  */
@@ -1452,15 +1544,36 @@ breakpoint_set_silent (struct breakpoint *b, int silent)
 void
 breakpoint_set_thread (struct breakpoint *b, int thread)
 {
-  /* It is invalid to set the thread field to anything other than -1 (which
-     means no thread restriction) if a task restriction is already in
-     place.  */
-  gdb_assert (thread == -1 || b->task == -1);
+  /* THREAD should be -1, meaning no thread restriction, or it should be a
+     valid global thread-id, which are greater than zero.  */
+  gdb_assert (thread == -1 || thread > 0);
 
-  int old_thread = b->thread;
+  /* It is not valid to set a thread restriction for a breakpoint that
+     already has task or inferior restriction.  */
+  gdb_assert (thread == -1 || (b->task == -1 && b->inferior == -1));
 
+  int old_thread = b->thread;
   b->thread = thread;
   if (old_thread != thread)
+    notify_breakpoint_modified (b);
+}
+
+/* See breakpoint.h.  */
+
+void
+breakpoint_set_inferior (struct breakpoint *b, int inferior)
+{
+  /* INFERIOR should be -1, meaning no inferior restriction, or it should
+     be a valid inferior number, which are greater than zero.  */
+  gdb_assert (inferior == -1 || inferior > 0);
+
+  /* It is not valid to set an inferior restriction for a breakpoint that
+     already has a task or thread restriction.  */
+  gdb_assert (inferior == -1 || (b->task == -1 && b->thread == -1));
+
+  int old_inferior = b->inferior;
+  b->inferior = inferior;
+  if (old_inferior != inferior)
     gdb::observers::breakpoint_modified.notify (b);
 }
 
@@ -1469,16 +1582,18 @@ breakpoint_set_thread (struct breakpoint *b, int thread)
 void
 breakpoint_set_task (struct breakpoint *b, int task)
 {
-  /* It is invalid to set the task field to anything other than -1 (which
-     means no task restriction) if a thread restriction is already in
-     place.  */
-  gdb_assert (task == -1 || b->thread == -1);
+  /* TASK should be -1, meaning no task restriction, or it should be a
+     valid task-id, which are greater than zero.  */
+  gdb_assert (task == -1 || task > 0);
 
-  int old_task = b->task;
+  /* It is not valid to set a task restriction for a breakpoint that
+     already has a thread or inferior restriction.  */
+  gdb_assert (task == -1 || (b->thread == -1 && b->inferior == -1));
 
+  int old_task = b->task;
   b->task = task;
   if (old_task != task)
-    gdb::observers::breakpoint_modified.notify (b);
+    notify_breakpoint_modified (b);
 }
 
 static void
@@ -1547,7 +1662,7 @@ commands_command_1 (const char *arg, int from_tty,
         {
           validate_commands_for_breakpoint (b, cmd.get ());
           b->commands = cmd;
-          gdb::observers::breakpoint_modified.notify (b);
+          notify_breakpoint_modified (b);
         }
      });
 }
@@ -2449,7 +2564,7 @@ build_target_condition_list (struct bp_location *bl)
   /* No NULL conditions or failed bytecode generation.  Build a
      condition list for this location's address.  If we have software
      and hardware locations at the same address, they aren't
-     considered duplicates, but we still marge all the conditions
+     considered duplicates, but we still merge all the conditions
      anyway, as it's simpler, and doesn't really make a practical
      difference.  */
   for (bp_location *loc : loc_range)
@@ -2718,6 +2833,8 @@ insert_bp_location (struct bp_location *bl,
   if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update))
     return 0;
 
+  breakpoint_debug_printf ("%s", breakpoint_location_address_str (bl).c_str ());
+
   /* Note we don't initialize bl->target_info, as that wipes out
      the breakpoint location's shadow_contents if the breakpoint
      is still inserted at that location.  This in turn breaks
@@ -2885,7 +3002,7 @@ insert_bp_location (struct bp_location *bl,
            {
              /* See also: disable_breakpoints_in_shlibs.  */
              bl->shlib_disabled = 1;
-             gdb::observers::breakpoint_modified.notify (bl->owner);
+             notify_breakpoint_modified (bl->owner);
              if (!*disabled_breaks)
                {
                  gdb_printf (tmp_error_stream, 
@@ -3022,9 +3139,9 @@ void
 breakpoint_program_space_exit (struct program_space *pspace)
 {
   /* Remove any breakpoint that was set through this program space.  */
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->pspace == pspace)
-      delete_breakpoint (b);
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.pspace == pspace)
+      delete_breakpoint (&b);
 
   /* Breakpoints set through other program spaces could have locations
      bound to PSPACE as well.  Remove those.  */
@@ -3047,12 +3164,12 @@ breakpoint_program_space_exit (struct program_space *pspace)
 void
 insert_breakpoints (void)
 {
-  for (breakpoint *bpt : all_breakpoints ())
-    if (is_hardware_watchpoint (bpt))
+  for (breakpoint &bpt : all_breakpoints ())
+    if (is_hardware_watchpoint (&bpt))
       {
-       struct watchpoint *w = (struct watchpoint *) bpt;
+       watchpoint &w = gdb::checked_static_cast<watchpoint &> (bpt);
 
-       update_watchpoint (w, false /* don't reparse.  */);
+       update_watchpoint (&w, false /* don't reparse.  */);
       }
 
   /* Updating watchpoints creates new locations, so update the global
@@ -3153,6 +3270,12 @@ insert_breakpoint_locations (void)
          && !valid_global_thread_id (bl->owner->thread))
        continue;
 
+      /* Or inferior specific breakpoints if the inferior no longer
+        exists.  */
+      if (bl->owner->inferior != -1
+         && !valid_global_inferior_id (bl->owner->inferior))
+       continue;
+
       switch_to_program_space_and_thread (bl->pspace);
 
       /* For targets that support global breakpoints, there's no need
@@ -3171,20 +3294,20 @@ insert_breakpoint_locations (void)
 
   /* If we failed to insert all locations of a watchpoint, remove
      them, as half-inserted watchpoint is of limited use.  */
-  for (breakpoint *bpt : all_breakpoints ())
+  for (breakpoint &bpt : all_breakpoints ())
     {
       bool some_failed = false;
 
-      if (!is_hardware_watchpoint (bpt))
+      if (!is_hardware_watchpoint (&bpt))
        continue;
 
-      if (!breakpoint_enabled (bpt))
+      if (!breakpoint_enabled (&bpt))
        continue;
 
-      if (bpt->disposition == disp_del_at_next_stop)
+      if (bpt.disposition == disp_del_at_next_stop)
        continue;
 
-      for (bp_location &loc : bpt->locations ())
+      for (bp_location &loc : bpt.locations ())
        if (!loc.inserted && should_be_inserted (&loc))
          {
            some_failed = true;
@@ -3193,14 +3316,14 @@ insert_breakpoint_locations (void)
 
       if (some_failed)
        {
-         for (bp_location &loc : bpt->locations ())
+         for (bp_location &loc : bpt.locations ())
            if (loc.inserted)
              remove_breakpoint (&loc);
 
          hw_breakpoint_error = 1;
          tmp_error_stream.printf ("Could not insert "
                                   "hardware watchpoint %d.\n",
-                                  bpt->number);
+                                  bpt.number);
          error_flag = -1;
        }
     }
@@ -3241,14 +3364,37 @@ remove_breakpoints (void)
 static void
 remove_threaded_breakpoints (struct thread_info *tp, int silent)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
+  for (breakpoint &b : all_breakpoints_safe ())
     {
-      if (b->thread == tp->global_num && user_breakpoint_p (b))
+      if (b.thread == tp->global_num && user_breakpoint_p (&b))
        {
          gdb_printf (_("\
 Thread-specific breakpoint %d deleted - thread %s no longer in the thread list.\n"),
-                     b->number, print_thread_id (tp));
-         delete_breakpoint (b);
+                     b.number, print_thread_id (tp));
+         delete_breakpoint (&b);
+       }
+    }
+}
+
+/* Called when inferior INF has been removed from GDB.  Remove associated
+   per-inferior breakpoints.  */
+
+static void
+remove_inferior_breakpoints (struct inferior *inf)
+{
+  for (breakpoint &b : all_breakpoints_safe ())
+    {
+      if (b.inferior == inf->num && user_breakpoint_p (&b))
+       {
+         /* Tell the user the breakpoint has been deleted.  But only for
+            breakpoints that would not normally have been deleted at the
+            next stop anyway.  */
+         if (b.disposition != disp_del
+             && b.disposition != disp_del_at_next_stop)
+           gdb_printf (_("\
+Inferior-specific breakpoint %d deleted - inferior %d has been removed.\n"),
+                       b.number, inf->num);
+         delete_breakpoint (&b);
        }
     }
 }
@@ -3260,6 +3406,8 @@ remove_breakpoints_inf (inferior *inf)
 {
   int val;
 
+  breakpoint_debug_printf ("inf->num = %d", inf->num);
+
   for (bp_location *bl : all_bp_locations ())
     {
       if (bl->pspace != inf->pspace)
@@ -3757,60 +3905,60 @@ update_breakpoints_after_exec (void)
     if (bploc->pspace == current_program_space)
       gdb_assert (!bploc->inserted);
 
-  for (breakpoint *b : all_breakpoints_safe ())
+  for (breakpoint &b : all_breakpoints_safe ())
     {
-      if (b->pspace != current_program_space)
+      if (b.pspace != current_program_space)
        continue;
 
       /* Solib breakpoints must be explicitly reset after an exec().  */
-      if (b->type == bp_shlib_event)
+      if (b.type == bp_shlib_event)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
       /* JIT breakpoints must be explicitly reset after an exec().  */
-      if (b->type == bp_jit_event)
+      if (b.type == bp_jit_event)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
       /* Thread event breakpoints must be set anew after an exec(),
         as must overlay event and longjmp master breakpoints.  */
-      if (b->type == bp_thread_event || b->type == bp_overlay_event
-         || b->type == bp_longjmp_master || b->type == bp_std_terminate_master
-         || b->type == bp_exception_master)
+      if (b.type == bp_thread_event || b.type == bp_overlay_event
+         || b.type == bp_longjmp_master || b.type == bp_std_terminate_master
+         || b.type == bp_exception_master)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
       /* Step-resume breakpoints are meaningless after an exec().  */
-      if (b->type == bp_step_resume || b->type == bp_hp_step_resume)
+      if (b.type == bp_step_resume || b.type == bp_hp_step_resume)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
       /* Just like single-step breakpoints.  */
-      if (b->type == bp_single_step)
+      if (b.type == bp_single_step)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
       /* Longjmp and longjmp-resume breakpoints are also meaningless
         after an exec.  */
-      if (b->type == bp_longjmp || b->type == bp_longjmp_resume
-         || b->type == bp_longjmp_call_dummy
-         || b->type == bp_exception || b->type == bp_exception_resume)
+      if (b.type == bp_longjmp || b.type == bp_longjmp_resume
+         || b.type == bp_longjmp_call_dummy
+         || b.type == bp_exception || b.type == bp_exception_resume)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
-      if (b->type == bp_catchpoint)
+      if (b.type == bp_catchpoint)
        {
          /* For now, none of the bp_catchpoint breakpoints need to
             do anything at this point.  In the future, if some of
@@ -3845,7 +3993,7 @@ update_breakpoints_after_exec (void)
         address is probably bogus in the new a.out, unlike e.g., the
         solib breakpoints.)  */
 
-      if (b->type == bp_finish)
+      if (b.type == bp_finish)
        {
          continue;
        }
@@ -3853,9 +4001,9 @@ update_breakpoints_after_exec (void)
       /* Without a symbolic address, we have little hope of the
         pre-exec() address meaning the same thing in the post-exec()
         a.out.  */
-      if (breakpoint_location_spec_empty_p (b))
+      if (breakpoint_location_spec_empty_p (&b))
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
     }
@@ -3904,6 +4052,10 @@ detach_breakpoints (ptid_t ptid)
 static int
 remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason)
 {
+  breakpoint_debug_printf ("%s due to %s",
+                          breakpoint_location_address_str (bl).c_str (),
+                          remove_bp_reason_str (reason));
+
   int val;
 
   /* BL is never in moribund_locations by our callers.  */
@@ -4092,12 +4244,12 @@ breakpoint_init_inferior (enum inf_context context)
 
   mark_breakpoints_out ();
 
-  for (breakpoint *b : all_breakpoints_safe ())
+  for (breakpoint &b : all_breakpoints_safe ())
     {
-      if (b->has_locations () && b->first_loc ().pspace != pspace)
+      if (b.has_locations () && b.first_loc ().pspace != pspace)
        continue;
 
-      switch (b->type)
+      switch (b.type)
        {
        case bp_call_dummy:
        case bp_longjmp_call_dummy:
@@ -4134,7 +4286,7 @@ breakpoint_init_inferior (enum inf_context context)
 
          /* Also remove single-step breakpoints.  */
 
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          break;
 
        case bp_watchpoint:
@@ -4142,11 +4294,11 @@ breakpoint_init_inferior (enum inf_context context)
        case bp_read_watchpoint:
        case bp_access_watchpoint:
          {
-           struct watchpoint *w = (struct watchpoint *) b;
+           watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
 
            /* Likewise for watchpoints on local expressions.  */
-           if (w->exp_valid_block != NULL)
-             delete_breakpoint (b);
+           if (w.exp_valid_block != NULL)
+             delete_breakpoint (&b);
            else
              {
                /* Get rid of existing locations, which are no longer
@@ -4154,14 +4306,14 @@ breakpoint_init_inferior (enum inf_context context)
                   update_watchpoint, when the inferior is restarted.
                   The next update_global_location_list call will
                   garbage collect them.  */
-               b->clear_locations ();
+               b.clear_locations ();
 
                if (context == inf_starting)
                  {
                    /* Reset val field to force reread of starting value in
                       insert_breakpoints.  */
-                   w->val.reset (nullptr);
-                   w->val_valid = false;
+                   w.val.reset (nullptr);
+                   w.val_valid = false;
                  }
              }
          }
@@ -4342,16 +4494,16 @@ int
 hardware_watchpoint_inserted_in_range (const address_space *aspace,
                                       CORE_ADDR addr, ULONGEST len)
 {
-  for (breakpoint *bpt : all_breakpoints ())
+  for (breakpoint &bpt : all_breakpoints ())
     {
-      if (bpt->type != bp_hardware_watchpoint
-         && bpt->type != bp_access_watchpoint)
+      if (bpt.type != bp_hardware_watchpoint
+         && bpt.type != bp_access_watchpoint)
        continue;
 
-      if (!breakpoint_enabled (bpt))
+      if (!breakpoint_enabled (&bpt))
        continue;
 
-      for (bp_location &loc : bpt->locations ())
+      for (bp_location &loc : bpt.locations ())
        if (loc.pspace->aspace == aspace && loc.inserted)
          {
            CORE_ADDR l, h;
@@ -5001,12 +5153,12 @@ watchpoints_triggered (const target_waitstatus &ws)
     {
       /* We were not stopped by a watchpoint.  Mark all watchpoints
         as not triggered.  */
-      for (breakpoint *b : all_breakpoints ())
-       if (is_hardware_watchpoint (b))
+      for (breakpoint &b : all_breakpoints ())
+       if (is_hardware_watchpoint (&b))
          {
-           struct watchpoint *w = (struct watchpoint *) b;
+           watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
 
-           w->watchpoint_triggered = watch_triggered_no;
+           w.watchpoint_triggered = watch_triggered_no;
          }
 
       return 0;
@@ -5016,12 +5168,12 @@ watchpoints_triggered (const target_waitstatus &ws)
     {
       /* We were stopped by a watchpoint, but we don't know where.
         Mark all watchpoints as unknown.  */
-      for (breakpoint *b : all_breakpoints ())
-       if (is_hardware_watchpoint (b))
+      for (breakpoint &b : all_breakpoints ())
+       if (is_hardware_watchpoint (&b))
          {
-           struct watchpoint *w = (struct watchpoint *) b;
+           watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
 
-           w->watchpoint_triggered = watch_triggered_unknown;
+           w.watchpoint_triggered = watch_triggered_unknown;
          }
 
       return 1;
@@ -5031,22 +5183,22 @@ watchpoints_triggered (const target_waitstatus &ws)
      affected by this data address as triggered, and all others as not
      triggered.  */
 
-  for (breakpoint *b : all_breakpoints ())
-    if (is_hardware_watchpoint (b))
+  for (breakpoint &b : all_breakpoints ())
+    if (is_hardware_watchpoint (&b))
       {
-       struct watchpoint *w = (struct watchpoint *) b;
+       watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
 
-       w->watchpoint_triggered = watch_triggered_no;
-       for (bp_location &loc : b->locations ())
+       w.watchpoint_triggered = watch_triggered_no;
+       for (bp_location &loc : b.locations ())
          {
-           if (is_masked_watchpoint (b))
+           if (is_masked_watchpoint (&b))
              {
-               CORE_ADDR newaddr = addr & w->hw_wp_mask;
-               CORE_ADDR start = loc.address & w->hw_wp_mask;
+               CORE_ADDR newaddr = addr & w.hw_wp_mask;
+               CORE_ADDR start = loc.address & w.hw_wp_mask;
 
                if (newaddr == start)
                  {
-                   w->watchpoint_triggered = watch_triggered_yes;
+                   w.watchpoint_triggered = watch_triggered_yes;
                    break;
                  }
              }
@@ -5055,7 +5207,7 @@ watchpoints_triggered (const target_waitstatus &ws)
                       (current_inferior ()->top_target (), addr, loc.address,
                        loc.length))
              {
-               w->watchpoint_triggered = watch_triggered_yes;
+               w.watchpoint_triggered = watch_triggered_yes;
                break;
              }
          }
@@ -5355,14 +5507,14 @@ bpstat_check_watchpoint (bpstat *bs)
 
                  if (bl->watchpoint_type == hw_read)
                    {
-                     for (breakpoint *other_b : all_breakpoints ())
-                       if (other_b->type == bp_hardware_watchpoint
-                           || other_b->type == bp_access_watchpoint)
+                     for (breakpoint &other_b : all_breakpoints ())
+                       if (other_b.type == bp_hardware_watchpoint
+                           || other_b.type == bp_access_watchpoint)
                          {
-                           struct watchpoint *other_w =
-                             (struct watchpoint *) other_b;
+                           watchpoint &other_w =
+                             gdb::checked_static_cast<watchpoint &> (other_b);
 
-                           if (other_w->watchpoint_triggered
+                           if (other_w.watchpoint_triggered
                                == watch_triggered_yes)
                              {
                                other_write_watchpoint = 1;
@@ -5457,6 +5609,7 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
      evaluating the condition if this isn't the specified
      thread/task.  */
   if ((b->thread != -1 && b->thread != thread->global_num)
+      || (b->inferior != -1 && b->inferior != thread->inf->num)
       || (b->task != -1 && b->task != ada_get_task_number (thread)))
     {
       infrun_debug_printf ("incorrect thread or task, not stopping");
@@ -5525,7 +5678,6 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
          else
            within_current_scope = false;
        }
-      CORE_ADDR pc_before_check = get_frame_pc (get_selected_frame (nullptr));
       if (within_current_scope)
        {
          try
@@ -5534,20 +5686,17 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
            }
          catch (const gdb_exception_error &ex)
            {
-             exception_fprintf (gdb_stderr, ex,
-                                "Error in testing condition for breakpoint %d:\n",
-                                b->number);
-
-             /* If the pc value changed as a result of evaluating the
-                condition then we probably stopped within an inferior
-                function call due to some unexpected stop, e.g. the thread
-                hit another breakpoint, or the thread received an
-                unexpected signal.  In this case we don't want to also
-                print the information about this breakpoint.  */
-             CORE_ADDR pc_after_check
-               = get_frame_pc (get_selected_frame (nullptr));
-             if (pc_before_check != pc_after_check)
-               bs->print = 0;
+             int locno = bpstat_locno (bs);
+             if (locno != 0)
+               exception_fprintf
+                 (gdb_stderr, ex,
+                  "Error in testing condition for breakpoint %d.%d:\n",
+                  b->number, locno);
+             else
+               exception_fprintf
+                 (gdb_stderr, ex,
+                  "Error in testing condition for breakpoint %d:\n",
+                  b->number);
            }
        }
       else
@@ -5574,7 +5723,7 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
       bs->stop = false;
       /* Increase the hit count even though we don't stop.  */
       ++(b->hit_count);
-      gdb::observers::breakpoint_modified.notify (b);
+      notify_breakpoint_modified (b);
       return;
     }
 
@@ -5604,19 +5753,19 @@ build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
 {
   bpstat *bs_head = nullptr, **bs_link = &bs_head;
 
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
-      if (!breakpoint_enabled (b))
+      if (!breakpoint_enabled (&b))
        continue;
 
-      for (bp_location &bl : b->locations ())
+      for (bp_location &bl : b.locations ())
        {
          /* For hardware watchpoints, we look only at the first
             location.  The watchpoint_check function will work on the
             entire expression, not the individual locations.  For
             read watchpoints, the watchpoints_triggered function has
             checked all locations already.  */
-         if (b->type == bp_hardware_watchpoint && &bl != &b->first_loc ())
+         if (b.type == bp_hardware_watchpoint && &bl != &b.first_loc ())
            break;
 
          if (!bl.enabled || bl.disabled_by_cond || bl.shlib_disabled)
@@ -5641,9 +5790,9 @@ build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
             watchpoint as triggered so that we will handle the
             out-of-scope event.  We'll get to the watchpoint next
             iteration.  */
-         if (b->type == bp_watchpoint_scope && b->related_breakpoint != b)
+         if (b.type == bp_watchpoint_scope && b.related_breakpoint != &b)
            {
-             struct watchpoint *w = (struct watchpoint *) b->related_breakpoint;
+             struct watchpoint *w = (struct watchpoint *) b.related_breakpoint;
 
              w->watchpoint_triggered = watch_triggered_yes;
            }
@@ -5737,7 +5886,7 @@ bpstat_stop_status (const address_space *aspace,
                    b->enable_state = bp_disabled;
                  removed_any = 1;
                }
-             gdb::observers::breakpoint_modified.notify (b);
+             notify_breakpoint_modified (b);
              if (b->silent)
                bs->print = false;
              bs->commands = b->commands;
@@ -6036,10 +6185,10 @@ bpstat_run_callbacks (bpstat *bs_head)
 bool
 bpstat_should_step ()
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (breakpoint_enabled (b)
-       && b->type == bp_watchpoint
-       && b->has_locations ())
+  for (breakpoint &b : all_breakpoints ())
+    if (breakpoint_enabled (&b)
+       && b.type == bp_watchpoint
+       && b.has_locations ())
       return true;
 
   return false;
@@ -6488,6 +6637,8 @@ print_one_breakpoint_location (struct breakpoint *b,
        uiout->field_signed ("thread", b->thread);
       else if (b->task != -1)
        uiout->field_signed ("task", b->task);
+      else if (b->inferior != -1)
+       uiout->field_signed ("inferior", b->inferior);
     }
 
   uiout->text ("\n");
@@ -6550,6 +6701,13 @@ print_one_breakpoint_location (struct breakpoint *b,
       uiout->text ("\n");
     }
 
+  if (!part_of_multiple && b->inferior != -1)
+    {
+      uiout->text ("\tstop only in inferior ");
+      uiout->field_signed ("inferior", b->inferior);
+      uiout->text ("\n");
+    }
+
   if (!part_of_multiple)
     {
       if (b->hit_count)
@@ -6824,31 +6982,31 @@ breakpoint_1 (const char *bp_num_list, bool show_internal,
   /* Compute the number of rows in the table, as well as the size
      required for address fields.  */
   nr_printable_breakpoints = 0;
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
       /* If we have a filter, only list the breakpoints it accepts.  */
-      if (filter && !filter (b))
+      if (filter && !filter (&b))
        continue;
 
       /* If we have a BP_NUM_LIST string, it is a list of breakpoints to
         accept.  Skip the others.  */
       if (bp_num_list != NULL && *bp_num_list != '\0')
        {
-         if (show_internal && parse_and_eval_long (bp_num_list) != b->number)
+         if (show_internal && parse_and_eval_long (bp_num_list) != b.number)
            continue;
-         if (!show_internal && !number_is_in_list (bp_num_list, b->number))
+         if (!show_internal && !number_is_in_list (bp_num_list, b.number))
            continue;
        }
 
-      if (show_internal || user_breakpoint_p (b))
+      if (show_internal || user_breakpoint_p (&b))
        {
          int addr_bit, type_len;
 
-         addr_bit = breakpoint_address_bits (b);
+         addr_bit = breakpoint_address_bits (&b);
          if (addr_bit > print_address_bits)
            print_address_bits = addr_bit;
 
-         type_len = strlen (bptype_string (b->type));
+         type_len = strlen (bptype_string (b.type));
          if (type_len > print_type_col_width)
            print_type_col_width = type_len;
 
@@ -6892,11 +7050,11 @@ breakpoint_1 (const char *bp_num_list, bool show_internal,
     if (nr_printable_breakpoints > 0)
       annotate_breakpoints_table ();
 
-    for (breakpoint *b : all_breakpoints ())
+    for (breakpoint &b : all_breakpoints ())
       {
        QUIT;
        /* If we have a filter, only list the breakpoints it accepts.  */
-       if (filter && !filter (b))
+       if (filter && !filter (&b))
          continue;
 
        /* If we have a BP_NUM_LIST string, it is a list of breakpoints to
@@ -6906,21 +7064,21 @@ breakpoint_1 (const char *bp_num_list, bool show_internal,
          {
            if (show_internal)  /* maintenance info breakpoint */
              {
-               if (parse_and_eval_long (bp_num_list) != b->number)
+               if (parse_and_eval_long (bp_num_list) != b.number)
                  continue;
              }
            else                /* all others */
              {
-               if (!number_is_in_list (bp_num_list, b->number))
+               if (!number_is_in_list (bp_num_list, b.number))
                  continue;
              }
          }
        /* We only print out user settable breakpoints unless the
           show_internal is set.  */
-       if (show_internal || user_breakpoint_p (b))
+       if (show_internal || user_breakpoint_p (&b))
          {
-           print_one_breakpoint (b, &last_loc, show_internal);
-           for (bp_location &loc : b->locations ())
+           print_one_breakpoint (&b, &last_loc, show_internal);
+           for (bp_location &loc : b.locations ())
              if (loc.disabled_by_cond)
                has_disabled_by_cond_location = true;
          }
@@ -7033,9 +7191,9 @@ describe_other_breakpoints (struct gdbarch *gdbarch,
 {
   int others = 0;
 
-  for (breakpoint *b : all_breakpoints ())
-    others += (user_breakpoint_p (b)
-              && breakpoint_has_pc (b, pspace, pc, section));
+  for (breakpoint &b : all_breakpoints ())
+    others += (user_breakpoint_p (&b)
+              && breakpoint_has_pc (&b, pspace, pc, section));
 
   if (others > 0)
     {
@@ -7043,23 +7201,24 @@ describe_other_breakpoints (struct gdbarch *gdbarch,
        gdb_printf (_("Note: breakpoint "));
       else /* if (others == ???) */
        gdb_printf (_("Note: breakpoints "));
-      for (breakpoint *b : all_breakpoints ())
-       if (user_breakpoint_p (b) && breakpoint_has_pc (b, pspace, pc, section))
+      for (breakpoint &b : all_breakpoints ())
+       if (user_breakpoint_p (&b)
+           && breakpoint_has_pc (&b, pspace, pc, section))
          {
            others--;
-           gdb_printf ("%d", b->number);
-           if (b->thread == -1 && thread != -1)
+           gdb_printf ("%d", b.number);
+           if (b.thread == -1 && thread != -1)
              gdb_printf (" (all threads)");
-           else if (b->thread != -1)
+           else if (b.thread != -1)
              {
-               struct thread_info *thr = find_thread_global_id (b->thread);
+               struct thread_info *thr = find_thread_global_id (b.thread);
                gdb_printf (" (thread %s)", print_thread_id (thr));
              }
-           else if (b->task != -1)
-             gdb_printf (" (task %d)", b->task);
+           else if (b.task != -1)
+             gdb_printf (" (task %d)", b.task);
            gdb_printf ("%s%s ",
-                       ((b->enable_state == bp_disabled
-                         || b->enable_state == bp_call_disabled)
+                       ((b.enable_state == bp_disabled
+                         || b.enable_state == bp_call_disabled)
                         ? " (disabled)"
                         : ""),
                        (others > 1) ? "," 
@@ -7413,6 +7572,17 @@ bp_location::bp_location (breakpoint *owner)
 {
 }
 
+/* See breakpoint.h.  */
+
+std::string
+bp_location::to_string () const
+{
+  string_file stb;
+  ui_out_redirect_pop redir (current_uiout, &stb);
+  print_breakpoint_location (this->owner, this);
+  return stb.string ();
+}
+
 /* Decrement reference count.  If the reference count reaches 0,
    destroy the bp_location.  Sets *BLP to NULL.  */
 
@@ -7428,23 +7598,12 @@ decref_bp_location (struct bp_location **blp)
 static breakpoint *
 add_to_breakpoint_chain (std::unique_ptr<breakpoint> &&b)
 {
-  struct breakpoint *b1;
-  struct breakpoint *result = b.get ();
-
   /* Add this breakpoint to the end of the chain so that a list of
      breakpoints will come out in order of increasing numbers.  */
 
-  b1 = breakpoint_chain;
-  if (b1 == 0)
-    breakpoint_chain = b.release ();
-  else
-    {
-      while (b1->next)
-       b1 = b1->next;
-      b1->next = b.release ();
-    }
+  breakpoint_chain.push_back (*b.release ());
 
-  return result;
+  return &breakpoint_chain.back ();
 }
 
 /* Initialize loc->function_name.  */
@@ -7513,15 +7672,15 @@ set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame)
      we maintain a list of continually-inserted but always disabled
      longjmp "master" breakpoints.  Here, we simply create momentary
      clones of those and enable them for the requested thread.  */
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->pspace == current_program_space
-       && (b->type == bp_longjmp_master
-           || b->type == bp_exception_master))
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.pspace == current_program_space
+       && (b.type == bp_longjmp_master
+           || b.type == bp_exception_master))
       {
-       enum bptype type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception;
+       bptype type = b.type == bp_longjmp_master ? bp_longjmp : bp_exception;
        /* longjmp_breakpoint_ops ensures INITIATING_FRAME is cleared again
           after their removal.  */
-       momentary_breakpoint_from_master (b, type, 1, thread);
+       momentary_breakpoint_from_master (&b, type, 1, thread);
       }
 
   tp->initiating_frame = frame;
@@ -7531,22 +7690,28 @@ set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame)
 void
 delete_longjmp_breakpoint (int thread)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_longjmp || b->type == bp_exception)
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_longjmp || b.type == bp_exception)
       {
-       if (b->thread == thread)
-         delete_breakpoint (b);
+       if (b.thread == thread)
+         {
+           gdb_assert (b.inferior == -1);
+           delete_breakpoint (&b);
+         }
       }
 }
 
 void
 delete_longjmp_breakpoint_at_next_stop (int thread)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_longjmp || b->type == bp_exception)
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_longjmp || b.type == bp_exception)
       {
-       if (b->thread == thread)
-         b->disposition = disp_del_at_next_stop;
+       if (b.thread == thread)
+         {
+           gdb_assert (b.inferior == -1);
+           b.disposition = disp_del_at_next_stop;
+         }
       }
 }
 
@@ -7560,12 +7725,12 @@ set_longjmp_breakpoint_for_call_dummy (void)
 {
   breakpoint *retval = nullptr;
 
-  for (breakpoint *b : all_breakpoints ())
-    if (b->pspace == current_program_space && b->type == bp_longjmp_master)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.pspace == current_program_space && b.type == bp_longjmp_master)
       {
        int thread = inferior_thread ()->global_num;
        breakpoint *new_b
-         = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy,
+         = momentary_breakpoint_from_master (&b, bp_longjmp_call_dummy,
                                              1, thread);
 
        /* Link NEW_B into the chain of RETVAL breakpoints.  */
@@ -7599,15 +7764,16 @@ check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
      Save all breakpoints to delete in that set and delete them at the end.  */
   std::unordered_set<breakpoint *> to_delete;
 
-  for (struct breakpoint *b : all_breakpoints ())
+  for (struct breakpoint &b : all_breakpoints ())
     {
-      if (b->type == bp_longjmp_call_dummy && b->thread == tp->global_num)
+      if (b.type == bp_longjmp_call_dummy && b.thread == tp->global_num)
        {
-         struct breakpoint *dummy_b = b->related_breakpoint;
+         gdb_assert (b.inferior == -1);
+         struct breakpoint *dummy_b = b.related_breakpoint;
 
          /* Find the bp_call_dummy breakpoint in the list of breakpoints
             chained off b->related_breakpoint.  */
-         while (dummy_b != b && dummy_b->type != bp_call_dummy)
+         while (dummy_b != &b && dummy_b->type != bp_call_dummy)
            dummy_b = dummy_b->related_breakpoint;
 
          /* If there was no bp_call_dummy breakpoint then there's nothing
@@ -7656,12 +7822,12 @@ check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
 
          dummy_frame_discard (dummy_b->frame_id, tp);
 
-         for (breakpoint *related_breakpoint = b->related_breakpoint;
-              related_breakpoint != b;
+         for (breakpoint *related_breakpoint = b.related_breakpoint;
+              related_breakpoint != &b;
               related_breakpoint = related_breakpoint->related_breakpoint)
-           to_delete.insert (b->related_breakpoint);
+           to_delete.insert (b.related_breakpoint);
 
-         to_delete.insert (b);
+         to_delete.insert (&b);
        }
     }
 
@@ -7672,10 +7838,10 @@ check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
 void
 enable_overlay_breakpoints (void)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_overlay_event)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_overlay_event)
       {
-       b->enable_state = bp_enabled;
+       b.enable_state = bp_enabled;
        update_global_location_list (UGLL_MAY_INSERT);
        overlay_events_enabled = 1;
       }
@@ -7684,10 +7850,10 @@ enable_overlay_breakpoints (void)
 void
 disable_overlay_breakpoints (void)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_overlay_event)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_overlay_event)
       {
-       b->enable_state = bp_disabled;
+       b.enable_state = bp_disabled;
        update_global_location_list (UGLL_DONT_INSERT);
        overlay_events_enabled = 0;
       }
@@ -7698,11 +7864,11 @@ disable_overlay_breakpoints (void)
 void
 set_std_terminate_breakpoint (void)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->pspace == current_program_space
-       && b->type == bp_std_terminate_master)
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.pspace == current_program_space
+       && b.type == bp_std_terminate_master)
       {
-       momentary_breakpoint_from_master (b, bp_std_terminate, 1,
+       momentary_breakpoint_from_master (&b, bp_std_terminate, 1,
                                          inferior_thread ()->global_num);
       }
 }
@@ -7711,9 +7877,9 @@ set_std_terminate_breakpoint (void)
 void
 delete_std_terminate_breakpoint (void)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_std_terminate)
-      delete_breakpoint (b);
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_std_terminate)
+      delete_breakpoint (&b);
 }
 
 struct breakpoint *
@@ -7751,19 +7917,19 @@ create_jit_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
 void
 remove_jit_event_breakpoints (void)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_jit_event
-       && b->first_loc ().pspace == current_program_space)
-      delete_breakpoint (b);
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_jit_event
+       && b.first_loc ().pspace == current_program_space)
+      delete_breakpoint (&b);
 }
 
 void
 remove_solib_event_breakpoints (void)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_shlib_event
-       && b->first_loc ().pspace == current_program_space)
-      delete_breakpoint (b);
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_shlib_event
+       && b.first_loc ().pspace == current_program_space)
+      delete_breakpoint (&b);
 }
 
 /* See breakpoint.h.  */
@@ -7771,10 +7937,10 @@ remove_solib_event_breakpoints (void)
 void
 remove_solib_event_breakpoints_at_next_stop (void)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_shlib_event
-       && b->first_loc ().pspace == current_program_space)
-      b->disposition = disp_del_at_next_stop;
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_shlib_event
+       && b.first_loc ().pspace == current_program_space)
+      b.disposition = disp_del_at_next_stop;
 }
 
 /* Helper for create_solib_event_breakpoint /
@@ -7877,7 +8043,7 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
          loc->inserted = 0;
 
          /* This may cause duplicate notifications for the same breakpoint.  */
-         gdb::observers::breakpoint_modified.notify (b);
+         notify_breakpoint_modified (b);
 
          if (!disabled_shlib_breaks)
            {
@@ -7916,14 +8082,14 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
       || (objfile->flags & OBJF_USERLOADED) == 0)
     return;
 
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
       bool bp_modified = false;
 
-      if (!is_breakpoint (b) && !is_tracepoint (b))
+      if (!is_breakpoint (&b) && !is_tracepoint (&b))
        continue;
 
-      for (bp_location &loc : b->locations ())
+      for (bp_location &loc : b.locations ())
        {
          CORE_ADDR loc_addr = loc.address;
 
@@ -7957,7 +8123,7 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
        }
 
       if (bp_modified)
-       gdb::observers::breakpoint_modified.notify (b);
+       notify_breakpoint_modified (&b);
     }
 }
 
@@ -7988,6 +8154,15 @@ catchpoint::catchpoint (struct gdbarch *gdbarch, bool temp,
   pspace = current_program_space;
 }
 
+/* Notify interpreters and observers that breakpoint B was created.  */
+
+static void
+notify_breakpoint_created (breakpoint *b)
+{
+  interps_notify_breakpoint_created (b);
+  gdb::observers::breakpoint_created.notify (b);
+}
+
 breakpoint *
 install_breakpoint (int internal, std::unique_ptr<breakpoint> &&arg, int update_gll)
 {
@@ -7997,7 +8172,8 @@ install_breakpoint (int internal, std::unique_ptr<breakpoint> &&arg, int update_
     set_tracepoint_count (breakpoint_count);
   if (!internal)
     mention (b);
-  gdb::observers::breakpoint_created.notify (b);
+
+  notify_breakpoint_created (b);
 
   if (update_gll)
     update_global_location_list (UGLL_MAY_INSERT);
@@ -8010,13 +8186,13 @@ hw_breakpoint_used_count (void)
 {
   int i = 0;
 
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_hardware_breakpoint && breakpoint_enabled (b))
-      for (bp_location &bl : b->locations ())
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_hardware_breakpoint && breakpoint_enabled (&b))
+      for (bp_location &bl : b.locations ())
        {
          /* Special types of hardware breakpoints may use more than
             one register.  */
-         i += b->resources_needed (&bl);
+         i += b.resources_needed (&bl);
        }
 
   return i;
@@ -8055,16 +8231,16 @@ hw_watchpoint_used_count_others (struct breakpoint *except,
   int i = 0;
 
   *other_type_used = 0;
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
-      if (b == except)
+      if (&b == except)
        continue;
-      if (!breakpoint_enabled (b))
+      if (!breakpoint_enabled (&b))
        continue;
 
-      if (b->type == type)
-       i += hw_watchpoint_use_count (b);
-      else if (is_hardware_watchpoint (b))
+      if (b.type == type)
+       i += hw_watchpoint_use_count (&b);
+      else if (is_hardware_watchpoint (&b))
        *other_type_used = 1;
     }
 
@@ -8074,10 +8250,10 @@ hw_watchpoint_used_count_others (struct breakpoint *except,
 void
 disable_watchpoints_before_interactive_call_start (void)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (is_watchpoint (b) && breakpoint_enabled (b))
+  for (breakpoint &b : all_breakpoints ())
+    if (is_watchpoint (&b) && breakpoint_enabled (&b))
       {
-       b->enable_state = bp_call_disabled;
+       b.enable_state = bp_call_disabled;
        update_global_location_list (UGLL_DONT_INSERT);
       }
 }
@@ -8085,10 +8261,10 @@ disable_watchpoints_before_interactive_call_start (void)
 void
 enable_watchpoints_after_interactive_call_stop (void)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (is_watchpoint (b) && b->enable_state == bp_call_disabled)
+  for (breakpoint &b : all_breakpoints ())
+    if (is_watchpoint (&b) && b.enable_state == bp_call_disabled)
       {
-       b->enable_state = bp_enabled;
+       b.enable_state = bp_enabled;
        update_global_location_list (UGLL_MAY_INSERT);
       }
 }
@@ -8425,9 +8601,9 @@ static void
 update_dprintf_commands (const char *args, int from_tty,
                         struct cmd_list_element *c)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_dprintf)
-       update_dprintf_command_list (b);
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_dprintf)
+       update_dprintf_command_list (&b);
 }
 
 code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
@@ -8438,7 +8614,8 @@ code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
                                  gdb::unique_xmalloc_ptr<char> cond_string_,
                                  gdb::unique_xmalloc_ptr<char> extra_string_,
                                  enum bpdisp disposition_,
-                                 int thread_, int task_, int ignore_count_,
+                                 int thread_, int task_, int inferior_,
+                                 int ignore_count_,
                                  int from_tty,
                                  int enabled_, unsigned flags,
                                  int display_canonical_)
@@ -8462,10 +8639,14 @@ code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
 
   gdb_assert (!sals.empty ());
 
-  /* At most one of thread or task can be set on any breakpoint.  */
-  gdb_assert (thread == -1 || task == -1);
+  /* At most one of thread, task, or inferior can be set on any breakpoint.  */
+  gdb_assert (((thread == -1 ? 0 : 1)
+              + (task == -1 ? 0 : 1)
+              + (inferior == -1 ? 0 : 1)) <= 1);
+
   thread = thread_;
   task = task_;
+  inferior = inferior_;
 
   cond_string = std::move (cond_string_);
   extra_string = std::move (extra_string_);
@@ -8567,7 +8748,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
                       gdb::unique_xmalloc_ptr<char> cond_string,
                       gdb::unique_xmalloc_ptr<char> extra_string,
                       enum bptype type, enum bpdisp disposition,
-                      int thread, int task, int ignore_count,
+                      int thread, int task, int inferior, int ignore_count,
                       int from_tty,
                       int enabled, int internal, unsigned flags,
                       int display_canonical)
@@ -8581,7 +8762,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
                                std::move (cond_string),
                                std::move (extra_string),
                                disposition,
-                               thread, task, ignore_count,
+                               thread, task, inferior, ignore_count,
                                from_tty,
                                enabled, flags,
                                display_canonical);
@@ -8610,7 +8791,8 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
                        gdb::unique_xmalloc_ptr<char> cond_string,
                        gdb::unique_xmalloc_ptr<char> extra_string,
                        enum bptype type, enum bpdisp disposition,
-                       int thread, int task, int ignore_count,
+                       int thread, int task, int inferior,
+                       int ignore_count,
                        int from_tty,
                        int enabled, int internal, unsigned flags)
 {
@@ -8634,7 +8816,7 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
                             std::move (cond_string),
                             std::move (extra_string),
                             type, disposition,
-                            thread, task, ignore_count,
+                            thread, task, inferior, ignore_count,
                             from_tty, enabled, internal, flags,
                             canonical->special_display);
     }
@@ -8764,21 +8946,26 @@ check_fast_tracepoint_sals (struct gdbarch *gdbarch,
     }
 }
 
-/* Given TOK, a string specification of condition and thread, as
-   accepted by the 'break' command, extract the condition
-   string and thread number and set *COND_STRING and *THREAD.
-   PC identifies the context at which the condition should be parsed.
-   If no condition is found, *COND_STRING is set to NULL.
-   If no thread is found, *THREAD is set to -1.  */
+/* Given TOK, a string specification of condition and thread, as accepted
+   by the 'break' command, extract the condition string into *COND_STRING.
+   If no condition string is found then *COND_STRING is set to nullptr.
+
+   If the breakpoint specification has an associated thread, task, or
+   inferior, these are extracted into *THREAD, *TASK, and *INFERIOR
+   respectively, otherwise these arguments are set to -1 (for THREAD and
+   INFERIOR) or 0 (for TASK).
+
+   PC identifies the context at which the condition should be parsed.  */
 
 static void
 find_condition_and_thread (const char *tok, CORE_ADDR pc,
                           gdb::unique_xmalloc_ptr<char> *cond_string,
-                          int *thread, int *task,
+                          int *thread, int *inferior, int *task,
                           gdb::unique_xmalloc_ptr<char> *rest)
 {
   cond_string->reset ();
   *thread = -1;
+  *inferior = -1;
   *task = -1;
   rest->reset ();
   bool force = false;
@@ -8795,7 +8982,7 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
       if ((*tok == '"' || *tok == ',') && rest)
        {
          rest->reset (savestring (tok, strlen (tok)));
-         return;
+         break;
        }
 
       end_tok = skip_to_space (tok);
@@ -8835,6 +9022,9 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
          if (*task != -1)
            error (_("You can specify only one of thread or task."));
 
+         if (*inferior != -1)
+           error (_("You can specify only one of inferior or thread."));
+
          tok = end_tok + 1;
          thr = parse_thread_id (tok, &tmptok);
          if (tok == tmptok)
@@ -8842,6 +9032,26 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
          *thread = thr->global_num;
          tok = tmptok;
        }
+      else if (toklen >= 1 && strncmp (tok, "inferior", toklen) == 0)
+       {
+         if (*inferior != -1)
+           error(_("You can specify only one inferior."));
+
+         if (*task != -1)
+           error (_("You can specify only one of inferior or task."));
+
+         if (*thread != -1)
+           error (_("You can specify only one of inferior or thread."));
+
+         char *tmptok;
+         tok = end_tok + 1;
+         *inferior = strtol (tok, &tmptok, 0);
+         if (tok == tmptok)
+           error (_("Junk after inferior keyword."));
+         if (!valid_global_inferior_id (*inferior))
+           error (_("Unknown inferior number %d."), *inferior);
+         tok = tmptok;
+       }
       else if (toklen >= 1 && strncmp (tok, "task", toklen) == 0)
        {
          char *tmptok;
@@ -8852,6 +9062,9 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
          if (*thread != -1)
            error (_("You can specify only one of thread or task."));
 
+         if (*inferior != -1)
+           error (_("You can specify only one of inferior or task."));
+
          tok = end_tok + 1;
          *task = strtol (tok, &tmptok, 0);
          if (tok == tmptok)
@@ -8863,7 +9076,7 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
       else if (rest)
        {
          rest->reset (savestring (tok, strlen (tok)));
-         return;
+         break;
        }
       else
        error (_("Junk at end of arguments."));
@@ -8879,7 +9092,7 @@ static void
 find_condition_and_thread_for_sals (const std::vector<symtab_and_line> &sals,
                                    const char *input,
                                    gdb::unique_xmalloc_ptr<char> *cond_string,
-                                   int *thread, int *task,
+                                   int *thread, int *inferior, int *task,
                                    gdb::unique_xmalloc_ptr<char> *rest)
 {
   int num_failures = 0;
@@ -8887,6 +9100,7 @@ find_condition_and_thread_for_sals (const std::vector<symtab_and_line> &sals,
     {
       gdb::unique_xmalloc_ptr<char> cond;
       int thread_id = -1;
+      int inferior_id = -1;
       int task_id = -1;
       gdb::unique_xmalloc_ptr<char> remaining;
 
@@ -8899,11 +9113,16 @@ find_condition_and_thread_for_sals (const std::vector<symtab_and_line> &sals,
       try
        {
          find_condition_and_thread (input, sal.pc, &cond, &thread_id,
-                                    &task_id, &remaining);
+                                    &inferior_id, &task_id, &remaining);
          *cond_string = std::move (cond);
-         /* At most one of thread or task can be set.  */
-         gdb_assert (thread_id == -1 || task_id == -1);
+         /* A value of -1 indicates that these fields are unset.  At most
+            one of these fields should be set (to a value other than -1)
+            at this point.  */
+         gdb_assert (((thread_id == -1 ? 1 : 0)
+                      + (task_id == -1 ? 1 : 0)
+                      + (inferior_id == -1 ? 1 : 0)) >= 2);
          *thread = thread_id;
+         *inferior = inferior_id;
          *task = task_id;
          *rest = std::move (remaining);
          break;
@@ -8993,7 +9212,8 @@ int
 create_breakpoint (struct gdbarch *gdbarch,
                   location_spec *locspec,
                   const char *cond_string,
-                  int thread, const char *extra_string,
+                  int thread, int inferior,
+                  const char *extra_string,
                   bool force_condition, int parse_extra,
                   int tempflag, enum bptype type_wanted,
                   int ignore_count,
@@ -9007,6 +9227,10 @@ create_breakpoint (struct gdbarch *gdbarch,
   int task = -1;
   int prev_bkpt_count = breakpoint_count;
 
+  gdb_assert (thread == -1 || thread > 0);
+  gdb_assert (inferior == -1 || inferior > 0);
+  gdb_assert (thread == -1 || inferior == -1);
+
   gdb_assert (ops != NULL);
 
   /* If extra_string isn't useful, set it to NULL.  */
@@ -9082,7 +9306,8 @@ create_breakpoint (struct gdbarch *gdbarch,
          const linespec_sals &lsal = canonical.lsals[0];
 
          find_condition_and_thread_for_sals (lsal.sals, extra_string,
-                                             &cond, &thread, &task, &rest);
+                                             &cond, &thread, &inferior,
+                                             &task, &rest);
          cond_string_copy = std::move (cond);
          extra_string_copy = std::move (rest);
        }
@@ -9132,7 +9357,7 @@ create_breakpoint (struct gdbarch *gdbarch,
                                   std::move (extra_string_copy),
                                   type_wanted,
                                   tempflag ? disp_del : disp_donttouch,
-                                  thread, task, ignore_count,
+                                  thread, task, inferior, ignore_count,
                                   from_tty, enabled, internal, flags);
     }
   else
@@ -9201,7 +9426,9 @@ break_command_1 (const char *arg, int flag, int from_tty)
 
   create_breakpoint (get_current_arch (),
                     locspec.get (),
-                    NULL, 0, arg, false, 1 /* parse arg */,
+                    NULL,
+                    -1 /* thread */, -1 /* inferior */,
+                    arg, false, 1 /* parse arg */,
                     tempflag, type_wanted,
                     0 /* Ignore count */,
                     pending_break_support,
@@ -9313,7 +9540,8 @@ dprintf_command (const char *arg, int from_tty)
 
   create_breakpoint (get_current_arch (),
                     locspec.get (),
-                    NULL, 0, arg, false, 1 /* parse arg */,
+                    NULL, -1, -1,
+                    arg, false, 1 /* parse arg */,
                     0, bp_dprintf,
                     0 /* Ignore count */,
                     pending_break_support,
@@ -10058,6 +10286,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
   const char *cond_end = NULL;
   enum bptype bp_type;
   int thread = -1;
+  int inferior = -1;
   /* Flag to indicate whether we are going to use masks for
      the hardware watchpoint.  */
   bool use_mask = false;
@@ -10112,12 +10341,13 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
              if (task != -1)
                error (_("You can specify only one of thread or task."));
 
+             if (inferior != -1)
+               error (_("You can specify only one of inferior or thread."));
+
              /* Extract the thread ID from the next token.  */
              thr = parse_thread_id (value_start, &endp);
-
-             /* Check if the user provided a valid thread ID.  */
-             if (*endp != ' ' && *endp != '\t' && *endp != '\0')
-               invalid_thread_id_error (value_start);
+             if (value_start == endp)
+               error (_("Junk after thread keyword."));
 
              thread = thr->global_num;
            }
@@ -10131,12 +10361,20 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
              if (thread != -1)
                error (_("You can specify only one of thread or task."));
 
+             if (inferior != -1)
+               error (_("You can specify only one of inferior or task."));
+
              task = strtol (value_start, &tmp, 0);
              if (tmp == value_start)
                error (_("Junk after task keyword."));
              if (!valid_task_id (task))
                error (_("Unknown task %d."), task);
            }
+         else if (toklen == 8 && startswith (tok, "inferior"))
+           {
+             /* Support for watchpoints will be added in a later commit.  */
+             error (_("Cannot use 'inferior' keyword with watchpoints"));
+           }
          else if (toklen == 4 && startswith (tok, "mask"))
            {
              /* We've found a "mask" token, which means the user wants to
@@ -10309,6 +10547,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
   /* At most one of thread or task can be set on a watchpoint.  */
   gdb_assert (thread == -1 || task == -1);
   w->thread = thread;
+  w->inferior = inferior;
   w->task = task;
   w->disposition = disp_donttouch;
   w->pspace = current_program_space;
@@ -10828,14 +11067,14 @@ clear_command (const char *arg, int from_tty)
                      ? NULL : symtab_to_fullname (sal.symtab));
 
       /* Find all matching breakpoints and add them to 'found'.  */
-      for (breakpoint *b : all_breakpoints ())
+      for (breakpoint &b : all_breakpoints ())
        {
          int match = 0;
          /* Are we going to delete b?  */
-         if (b->type != bp_none && !is_watchpoint (b)
-             && user_breakpoint_p (b))
+         if (b.type != bp_none && !is_watchpoint (&b)
+             && user_breakpoint_p (&b))
            {
-             for (bp_location &loc : b->locations ())
+             for (bp_location &loc : b.locations ())
                {
                  /* If the user specified file:line, don't allow a PC
                     match.  This matches historical gdb behavior.  */
@@ -10865,7 +11104,7 @@ clear_command (const char *arg, int from_tty)
            }
 
          if (match)
-           found.push_back (b);
+           found.push_back (&b);
        }
     }
 
@@ -10924,15 +11163,15 @@ breakpoint_auto_delete (bpstat *bs)
        && bs->stop)
       delete_breakpoint (bs->breakpoint_at);
 
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->disposition == disp_del_at_next_stop)
-      delete_breakpoint (b);
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.disposition == disp_del_at_next_stop)
+      delete_breakpoint (&b);
 }
 
 /* A comparison function for bp_location AP and BP being interfaced to
    std::sort.  Sort elements primarily by their ADDRESS (no matter what
    bl_address_is_meaningful says), secondarily by ordering first
-   permanent elements and terciarily just ensuring the array is sorted
+   permanent elements and tertiarily just ensuring the array is sorted
    stable way despite std::sort being an unstable algorithm.  */
 
 static int
@@ -11017,12 +11256,11 @@ download_tracepoint_locations (void)
 
   scoped_restore_current_pspace_and_thread restore_pspace_thread;
 
-  for (breakpoint *b : all_tracepoints ())
+  for (breakpoint &b : all_tracepoints ())
     {
-      struct tracepoint *t;
       bool bp_location_downloaded = false;
 
-      if ((b->type == bp_fast_tracepoint
+      if ((b.type == bp_fast_tracepoint
           ? !may_insert_fast_tracepoints
           : !may_insert_tracepoints))
        continue;
@@ -11038,7 +11276,7 @@ download_tracepoint_locations (void)
       if (can_download_tracepoint == TRIBOOL_FALSE)
        break;
 
-      for (bp_location &bl : b->locations ())
+      for (bp_location &bl : b.locations ())
        {
          /* In tracepoint, locations are _never_ duplicated, so
             should_be_inserted is equivalent to
@@ -11053,10 +11291,11 @@ download_tracepoint_locations (void)
          bl.inserted = 1;
          bp_location_downloaded = true;
        }
-      t = (struct tracepoint *) b;
-      t->number_on_target = b->number;
+
+      tracepoint &t = gdb::checked_static_cast<tracepoint &> (b);
+      t.number_on_target = b.number;
       if (bp_location_downloaded)
-       gdb::observers::breakpoint_modified.notify (b);
+       notify_breakpoint_modified (&b);
     }
 }
 
@@ -11147,6 +11386,9 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
   /* Last breakpoint location program space that was marked for update.  */
   int last_pspace_num = -1;
 
+  breakpoint_debug_printf ("insert_mode = %s",
+                          ugll_insert_mode_text (insert_mode));
+
   /* Used in the duplicates detection below.  When iterating over all
      bp_locations, points to the first bp_location of a given address.
      Breakpoints and watchpoints of different types are never
@@ -11163,8 +11405,8 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
   std::vector<bp_location *> old_locations = std::move (bp_locations);
   bp_locations.clear ();
 
-  for (breakpoint *b : all_breakpoints ())
-    for (bp_location &loc : b->locations ())
+  for (breakpoint &b : all_breakpoints ())
+    for (bp_location &loc : b.locations ())
       bp_locations.push_back (&loc);
 
   /* See if we need to "upgrade" a software breakpoint to a hardware
@@ -12243,7 +12485,8 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
                                      enum bptype type_wanted,
                                      enum bpdisp disposition,
                                      int thread,
-                                     int task, int ignore_count,
+                                     int task, int inferior,
+                                     int ignore_count,
                                      int from_tty, int enabled,
                                      int internal, unsigned flags)
 {
@@ -12269,7 +12512,7 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
                         std::move (cond_string),
                         std::move (extra_string),
                         disposition,
-                        thread, task, ignore_count,
+                        thread, task, inferior, ignore_count,
                         from_tty, enabled, flags,
                         canonical->special_display));
 
@@ -12315,6 +12558,15 @@ strace_marker_p (struct breakpoint *b)
   return b->type == bp_static_marker_tracepoint;
 }
 
+/* Notify interpreters and observers that breakpoint B was deleted.  */
+
+static void
+notify_breakpoint_deleted (breakpoint *b)
+{
+  interps_notify_breakpoint_deleted (b);
+  gdb::observers::breakpoint_deleted.notify (b);
+}
+
 /* Delete a breakpoint and clean up all traces of it in the data
    structures.  */
 
@@ -12370,17 +12622,9 @@ delete_breakpoint (struct breakpoint *bpt)
      a problem in that process, we'll be asked to delete the half-created
      watchpoint.  In that case, don't announce the deletion.  */
   if (bpt->number)
-    gdb::observers::breakpoint_deleted.notify (bpt);
+    notify_breakpoint_deleted (bpt);
 
-  if (breakpoint_chain == bpt)
-    breakpoint_chain = bpt->next;
-
-  for (breakpoint *b : all_breakpoints ())
-    if (b->next == bpt)
-      {
-       b->next = bpt->next;
-       break;
-      }
+  breakpoint_chain.erase (breakpoint_chain.iterator_to (*bpt));
 
   /* Be sure no bpstat's are pointing at the breakpoint after it's
      been freed.  */
@@ -12459,8 +12703,8 @@ delete_command (const char *arg, int from_tty)
       /* Delete all breakpoints if no argument.  Do not delete
         internal breakpoints, these have to be deleted with an
         explicit breakpoint number argument.  */
-      for (breakpoint *b : all_breakpoints ())
-       if (user_breakpoint_p (b))
+      for (breakpoint &b : all_breakpoints ())
+       if (user_breakpoint_p (&b))
          {
            breaks_to_delete = 1;
            break;
@@ -12469,9 +12713,9 @@ delete_command (const char *arg, int from_tty)
       /* Ask user only if there are some breakpoints to delete.  */
       if (!from_tty
          || (breaks_to_delete && query (_("Delete all breakpoints? "))))
-       for (breakpoint *b : all_breakpoints_safe ())
-         if (user_breakpoint_p (b))
-           delete_breakpoint (b);
+       for (breakpoint &b : all_breakpoints_safe ())
+         if (user_breakpoint_p (&b))
+           delete_breakpoint (&b);
     }
   else
     map_breakpoint_numbers
@@ -12824,7 +13068,7 @@ update_breakpoint_locations (code_breakpoint *b,
   }
 
   if (!locations_are_equal (existing_locations, b->locations ()))
-    gdb::observers::breakpoint_modified.notify (b);
+    notify_breakpoint_modified (b);
 }
 
 /* Find the SaL locations corresponding to the given LOCSPEC.
@@ -12887,10 +13131,11 @@ code_breakpoint::location_spec_to_sals (location_spec *locspec,
       if (condition_not_parsed && extra_string != NULL)
        {
          gdb::unique_xmalloc_ptr<char> local_cond, local_extra;
-         int local_thread, local_task;
+         int local_thread, local_task, local_inferior;
 
          find_condition_and_thread_for_sals (sals, extra_string.get (),
                                              &local_cond, &local_thread,
+                                             &local_inferior,
                                              &local_task, &local_extra);
          gdb_assert (cond_string == nullptr);
          if (local_cond != nullptr)
@@ -12992,17 +13237,17 @@ breakpoint_re_set (void)
        breakpoint 1, we'd insert the locations of breakpoint 2, which
        hadn't been re-set yet, and thus may have stale locations.  */
 
-    for (breakpoint *b : all_breakpoints_safe ())
+    for (breakpoint &b : all_breakpoints_safe ())
       {
        try
          {
-           breakpoint_re_set_one (b);
+           breakpoint_re_set_one (&b);
          }
        catch (const gdb_exception &ex)
          {
            exception_fprintf (gdb_stderr, ex,
                               "Error in re-setting breakpoint %d: ",
-                              b->number);
+                              b.number);
          }
       }
 
@@ -13047,10 +13292,10 @@ set_ignore_count (int bptnum, int count, int from_tty)
   if (count < 0)
     count = 0;
 
-  for (breakpoint *b : all_breakpoints ())
-    if (b->number == bptnum)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.number == bptnum)
       {
-       if (is_tracepoint (b))
+       if (is_tracepoint (&b))
          {
            if (from_tty && count != 0)
              gdb_printf (_("Ignore count ignored for tracepoint %d."),
@@ -13058,7 +13303,7 @@ set_ignore_count (int bptnum, int count, int from_tty)
            return;
          }
 
-       b->ignore_count = count;
+       b.ignore_count = count;
        if (from_tty)
          {
            if (count == 0)
@@ -13073,7 +13318,7 @@ set_ignore_count (int bptnum, int count, int from_tty)
                            "crossings of breakpoint %d."),
                          count, bptnum);
          }
-       gdb::observers::breakpoint_modified.notify (b);
+       notify_breakpoint_modified (&b);
        return;
       }
 
@@ -13123,11 +13368,11 @@ map_breakpoint_number_range (std::pair<int, int> bp_num_range,
        {
          bool match = false;
 
-         for (breakpoint *b : all_breakpoints_safe ())
-           if (b->number == i)
+         for (breakpoint &b : all_breakpoints_safe ())
+           if (b.number == i)
              {
                match = true;
-               function (b);
+               function (&b);
                break;
              }
          if (!match)
@@ -13327,7 +13572,7 @@ enable_disable_bp_num_loc (int bp_num, int loc_num, bool enable)
     }
   update_global_location_list (UGLL_DONT_INSERT);
 
-  gdb::observers::breakpoint_modified.notify (loc->owner);
+  notify_breakpoint_modified (loc->owner);
 }
 
 /* Calculates LOC_NUM for LOC by traversing the bp_location chain of LOC's
@@ -13384,7 +13629,7 @@ enable_disable_bp_location (bp_location *loc, bool enable)
     target_disable_tracepoint (loc);
 
   update_global_location_list (UGLL_DONT_INSERT);
-  gdb::observers::breakpoint_modified.notify (loc->owner);
+  notify_breakpoint_modified (loc->owner);
 }
 
 /* Enable or disable a range of breakpoint locations.  BP_NUM is the
@@ -13429,7 +13674,7 @@ disable_breakpoint (struct breakpoint *bpt)
 
   update_global_location_list (UGLL_DONT_INSERT);
 
-  gdb::observers::breakpoint_modified.notify (bpt);
+  notify_breakpoint_modified (bpt);
 }
 
 /* Enable or disable the breakpoint(s) or breakpoint location(s)
@@ -13442,13 +13687,13 @@ enable_disable_command (const char *args, int from_tty, bool enable)
 {
   if (args == 0)
     {
-      for (breakpoint *bpt : all_breakpoints ())
-       if (user_breakpoint_p (bpt))
+      for (breakpoint &bpt : all_breakpoints ())
+       if (user_breakpoint_p (&bpt))
          {
            if (enable)
-             enable_breakpoint (bpt);
+             enable_breakpoint (&bpt);
            else
-             disable_breakpoint (bpt);
+             disable_breakpoint (&bpt);
          }
     }
   else
@@ -13554,7 +13799,7 @@ enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition,
   bpt->enable_count = count;
   update_global_location_list (UGLL_MAY_INSERT);
 
-  gdb::observers::breakpoint_modified.notify (bpt);
+  notify_breakpoint_modified (bpt);
 }
 
 
@@ -13633,21 +13878,21 @@ invalidate_bp_value_on_memory_change (struct inferior *inferior,
                                      CORE_ADDR addr, ssize_t len,
                                      const bfd_byte *data)
 {
-  for (breakpoint *bp : all_breakpoints ())
-    if (bp->enable_state == bp_enabled
-       && bp->type == bp_hardware_watchpoint)
+  for (breakpoint &bp : all_breakpoints ())
+    if (bp.enable_state == bp_enabled
+       && bp.type == bp_hardware_watchpoint)
       {
-       struct watchpoint *wp = (struct watchpoint *) bp;
+       watchpoint &wp = gdb::checked_static_cast<watchpoint &> (bp);
 
-       if (wp->val_valid && wp->val != nullptr)
+       if (wp.val_valid && wp.val != nullptr)
          {
-           for (bp_location &loc : bp->locations ())
+           for (bp_location &loc : bp.locations ())
              if (loc.loc_type == bp_loc_hardware_watchpoint
                  && loc.address + loc.length > addr
                  && addr + len > loc.address)
                {
-                 wp->val = NULL;
-                 wp->val_valid = false;
+                 wp.val = NULL;
+                 wp.val_valid = false;
                }
          }
       }
@@ -13735,10 +13980,10 @@ int
 single_step_breakpoint_inserted_here_p (const address_space *aspace,
                                        CORE_ADDR pc)
 {
-  for (breakpoint *bpt : all_breakpoints ())
+  for (breakpoint &bpt : all_breakpoints ())
     {
-      if (bpt->type == bp_single_step
-         && breakpoint_has_location_inserted_here (bpt, aspace, pc))
+      if (bpt.type == bp_single_step
+         && breakpoint_has_location_inserted_here (&bpt, aspace, pc))
        return 1;
     }
   return 0;
@@ -13764,7 +14009,7 @@ trace_command (const char *arg, int from_tty)
 
   create_breakpoint (get_current_arch (),
                     locspec.get (),
-                    NULL, 0, arg, false, 1 /* parse arg */,
+                    NULL, -1, -1, arg, false, 1 /* parse arg */,
                     0 /* tempflag */,
                     bp_tracepoint /* type_wanted */,
                     0 /* Ignore count */,
@@ -13782,7 +14027,7 @@ ftrace_command (const char *arg, int from_tty)
                                                      current_language);
   create_breakpoint (get_current_arch (),
                     locspec.get (),
-                    NULL, 0, arg, false, 1 /* parse arg */,
+                    NULL, -1, -1, arg, false, 1 /* parse arg */,
                     0 /* tempflag */,
                     bp_fast_tracepoint /* type_wanted */,
                     0 /* Ignore count */,
@@ -13820,7 +14065,7 @@ strace_command (const char *arg, int from_tty)
 
   create_breakpoint (get_current_arch (),
                     locspec.get (),
-                    NULL, 0, arg, false, 1 /* parse arg */,
+                    NULL, -1, -1, arg, false, 1 /* parse arg */,
                     0 /* tempflag */,
                     type /* type_wanted */,
                     0 /* Ignore count */,
@@ -13889,7 +14134,7 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
                                                      current_language);
   if (!create_breakpoint (get_current_arch (),
                          locspec.get (),
-                         utp->cond_string.get (), -1, addr_str,
+                         utp->cond_string.get (), -1, -1, addr_str,
                          false /* force_condition */,
                          0 /* parse cond/thread */,
                          0 /* tempflag */,
@@ -13995,8 +14240,8 @@ delete_trace_command (const char *arg, int from_tty)
         Do not delete internal or call-dummy breakpoints, these
         have to be deleted with an explicit breakpoint number 
         argument.  */
-      for (breakpoint *tp : all_tracepoints ())
-       if (is_tracepoint (tp) && user_breakpoint_p (tp))
+      for (breakpoint &tp : all_tracepoints ())
+       if (is_tracepoint (&tp) && user_breakpoint_p (&tp))
          {
            breaks_to_delete = 1;
            break;
@@ -14006,9 +14251,9 @@ delete_trace_command (const char *arg, int from_tty)
       if (!from_tty
          || (breaks_to_delete && query (_("Delete all tracepoints? "))))
        {
-         for (breakpoint *b : all_breakpoints_safe ())
-           if (is_tracepoint (b) && user_breakpoint_p (b))
-             delete_breakpoint (b);
+         for (breakpoint &b : all_breakpoints_safe ())
+           if (is_tracepoint (&b) && user_breakpoint_p (&b))
+             delete_breakpoint (&b);
        }
     }
   else
@@ -14025,7 +14270,7 @@ static void
 trace_pass_set_count (struct tracepoint *tp, int count, int from_tty)
 {
   tp->pass_count = count;
-  gdb::observers::breakpoint_modified.notify (tp);
+  notify_breakpoint_modified (tp);
   if (from_tty)
     gdb_printf (_("Setting tracepoint %d's passcount to %d\n"),
                tp->number, count);
@@ -14040,7 +14285,6 @@ trace_pass_set_count (struct tracepoint *tp, int count, int from_tty)
 static void
 trace_pass_command (const char *args, int from_tty)
 {
-  struct tracepoint *t1;
   ULONGEST count;
 
   if (args == 0 || *args == 0)
@@ -14056,15 +14300,15 @@ trace_pass_command (const char *args, int from_tty)
       if (*args)
        error (_("Junk at end of arguments."));
 
-      for (breakpoint *b : all_tracepoints ())
+      for (breakpoint &b : all_tracepoints ())
        {
-         t1 = (struct tracepoint *) b;
-         trace_pass_set_count (t1, count, from_tty);
+         tracepoint &t1 = gdb::checked_static_cast<tracepoint &> (b);
+         trace_pass_set_count (&t1, count, from_tty);
        }
     }
   else if (*args == '\0')
     {
-      t1 = get_tracepoint_by_number (&args, NULL);
+      tracepoint *t1 = get_tracepoint_by_number (&args, NULL);
       if (t1)
        trace_pass_set_count (t1, count, from_tty);
     }
@@ -14073,7 +14317,7 @@ trace_pass_command (const char *args, int from_tty)
       number_or_range_parser parser (args);
       while (!parser.finished ())
        {
-         t1 = get_tracepoint_by_number (&args, &parser);
+         tracepoint *t1 = get_tracepoint_by_number (&args, &parser);
          if (t1)
            trace_pass_set_count (t1, count, from_tty);
        }
@@ -14083,9 +14327,9 @@ trace_pass_command (const char *args, int from_tty)
 struct tracepoint *
 get_tracepoint (int num)
 {
-  for (breakpoint *t : all_tracepoints ())
-    if (t->number == num)
-      return (struct tracepoint *) t;
+  for (breakpoint &t : all_tracepoints ())
+    if (t.number == num)
+      return gdb::checked_static_cast<tracepoint *> (&t);
 
   return NULL;
 }
@@ -14097,12 +14341,12 @@ get_tracepoint (int num)
 struct tracepoint *
 get_tracepoint_by_number_on_target (int num)
 {
-  for (breakpoint *b : all_tracepoints ())
+  for (breakpoint &b : all_tracepoints ())
     {
-      struct tracepoint *t = (struct tracepoint *) b;
+      tracepoint &t = gdb::checked_static_cast<tracepoint &> (b);
 
-      if (t->number_on_target == num)
-       return t;
+      if (t.number_on_target == num)
+       return &t;
     }
 
   return NULL;
@@ -14140,9 +14384,9 @@ get_tracepoint_by_number (const char **arg,
       return NULL;
     }
 
-  for (breakpoint *t : all_tracepoints ())
-    if (t->number == tpnum)
-      return (struct tracepoint *) t;
+  for (breakpoint &t : all_tracepoints ())
+    if (t.number == tpnum)
+      return gdb::checked_static_cast<tracepoint *> (&t);
 
   gdb_printf ("No tracepoint number %d.\n", tpnum);
   return NULL;
@@ -14179,19 +14423,19 @@ save_breakpoints (const char *filename, int from_tty,
     error (_("Argument required (file name in which to save)"));
 
   /* See if we have anything to save.  */
-  for (breakpoint *tp : all_breakpoints ())
+  for (breakpoint &tp : all_breakpoints ())
     {
       /* Skip internal and momentary breakpoints.  */
-      if (!user_breakpoint_p (tp))
+      if (!user_breakpoint_p (&tp))
        continue;
 
       /* If we have a filter, only save the breakpoints it accepts.  */
-      if (filter && !filter (tp))
+      if (filter && !filter (&tp))
        continue;
 
       any = true;
 
-      if (is_tracepoint (tp))
+      if (is_tracepoint (&tp))
        {
          extra_trace_bits = 1;
 
@@ -14217,49 +14461,49 @@ save_breakpoints (const char *filename, int from_tty,
   if (extra_trace_bits)
     save_trace_state_variables (&fp);
 
-  for (breakpoint *tp : all_breakpoints ())
+  for (breakpoint &tp : all_breakpoints ())
     {
       /* Skip internal and momentary breakpoints.  */
-      if (!user_breakpoint_p (tp))
+      if (!user_breakpoint_p (&tp))
        continue;
 
       /* If we have a filter, only save the breakpoints it accepts.  */
-      if (filter && !filter (tp))
+      if (filter && !filter (&tp))
        continue;
 
-      tp->print_recreate (&fp);
+      tp.print_recreate (&fp);
 
       /* Note, we can't rely on tp->number for anything, as we can't
         assume the recreated breakpoint numbers will match.  Use $bpnum
         instead.  */
 
-      if (tp->cond_string)
-       fp.printf ("  condition $bpnum %s\n", tp->cond_string.get ());
+      if (tp.cond_string)
+       fp.printf ("  condition $bpnum %s\n", tp.cond_string.get ());
 
-      if (tp->ignore_count)
-       fp.printf ("  ignore $bpnum %d\n", tp->ignore_count);
+      if (tp.ignore_count)
+       fp.printf ("  ignore $bpnum %d\n", tp.ignore_count);
 
-      if (tp->type != bp_dprintf && tp->commands)
+      if (tp.type != bp_dprintf && tp.commands)
        {
          fp.puts ("  commands\n");
 
          ui_out_redirect_pop redir (current_uiout, &fp);
-         print_command_lines (current_uiout, tp->commands.get (), 2);
+         print_command_lines (current_uiout, tp.commands.get (), 2);
 
          fp.puts ("  end\n");
        }
 
-      if (tp->enable_state == bp_disabled)
+      if (tp.enable_state == bp_disabled)
        fp.puts ("disable $bpnum\n");
 
       /* If this is a multi-location breakpoint, check if the locations
         should be individually disabled.  Watchpoint locations are
         special, and not user visible.  */
-      if (!is_watchpoint (tp) && tp->has_multiple_locations ())
+      if (!is_watchpoint (&tp) && tp.has_multiple_locations ())
        {
          int n = 1;
 
-         for (bp_location &loc : tp->locations ())
+         for (bp_location &loc : tp.locations ())
            {
              if (!loc.enabled)
                fp.printf ("disable $bpnum.%d\n", n);
@@ -14395,12 +14639,12 @@ int
 pc_at_non_inline_function (const address_space *aspace, CORE_ADDR pc,
                           const target_waitstatus &ws)
 {
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
-      if (!is_non_inline_function (b))
+      if (!is_non_inline_function (&b))
        continue;
 
-      for (bp_location &bl : b->locations ())
+      for (bp_location &bl : b.locations ())
        {
          if (!bl.shlib_disabled
              && bpstat_check_location (&bl, aspace, pc, ws))
@@ -14442,7 +14686,6 @@ _initialize_breakpoint ()
   gdb::observers::memory_changed.attach (invalidate_bp_value_on_memory_change,
                                         "breakpoint");
 
-  breakpoint_chain = 0;
   /* Don't bother to call set_breakpoint_count.  $bpnum isn't useful
      before a breakpoint is set.  */
   breakpoint_count = 0;
@@ -14890,6 +15133,15 @@ when execution stops."),
                                &breakpoint_set_cmdlist,
                                &breakpoint_show_cmdlist);
 
+  add_setshow_boolean_cmd ("breakpoint", class_maintenance,
+                          &debug_breakpoint, _("\
+Set breakpoint location debugging."), _("\
+Show breakpoint location debugging."), _("\
+When on, breakpoint location specific debugging is enabled."),
+                          NULL,
+                          show_debug_breakpoint,
+                          &setdebuglist, &showdebuglist);
+
   add_setshow_enum_cmd ("condition-evaluation", class_breakpoint,
                        condition_evaluation_enums,
                        &condition_evaluation_mode_1, _("\
@@ -14979,4 +15231,6 @@ This is useful for formatted output in user-defined commands."));
                                           "breakpoint");
   gdb::observers::thread_exit.attach (remove_threaded_breakpoints,
                                      "breakpoint");
+  gdb::observers::inferior_removed.attach (remove_inferior_breakpoints,
+                                          "breakpoint");
 }