Fix automatic restoration of breakpoints memory for ia64.
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index 737558e4b3b95c0b7af91dd3a5181bee3d7931cf..617a5389634c77392d9f15b0b9fae7007c76472b 100644 (file)
 #include "ada-lang.h"
 #include "top.h"
 #include "wrapper.h"
+#include "valprint.h"
 
-#include "gdb-events.h"
 #include "mi/mi-common.h"
 
-#include "gdb_stdint.h"
+/* Arguments to pass as context to some catch command handlers.  */
+#define CATCH_PERMANENT ((void *) (uintptr_t) 0)
+#define CATCH_TEMPORARY ((void *) (uintptr_t) 1)
 
 /* Prototypes for local functions. */
 
-static void until_break_command_continuation (struct continuation_arg *arg, 
-                                             int error);
-
-static void catch_command_1 (char *, int, int);
-
 static void enable_delete_command (char *, int);
 
 static void enable_delete_breakpoint (struct breakpoint *);
@@ -108,7 +105,7 @@ static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int);
 static CORE_ADDR adjust_breakpoint_address (CORE_ADDR bpaddr,
                                             enum bptype bptype);
 
-static void describe_other_breakpoints (CORE_ADDR, asection *, int);
+static void describe_other_breakpoints (CORE_ADDR, struct obj_section *, int);
 
 static void breakpoints_info (char *, int);
 
@@ -145,8 +142,6 @@ static int watchpoint_check (void *);
 
 static void maintenance_info_breakpoints (char *, int);
 
-static void create_longjmp_breakpoint (char *);
-
 static void create_overlay_event_breakpoint (char *);
 
 static int hw_breakpoint_used_count (void);
@@ -165,18 +160,12 @@ static void awatch_command (char *, int);
 
 static void do_enable_breakpoint (struct breakpoint *, enum bpdisp);
 
-static void create_fork_vfork_event_catchpoint (int tempflag,
-                                               char *cond_string,
-                                               enum bptype bp_kind);
-
 static void stop_command (char *arg, int from_tty);
 
 static void stopin_command (char *arg, int from_tty);
 
 static void stopat_command (char *arg, int from_tty);
 
-static char *ep_find_event_name_end (char *arg);
-
 static char *ep_parse_optional_if_clause (char **arg);
 
 static char *ep_parse_optional_filename (char **arg);
@@ -192,14 +181,12 @@ static int single_step_breakpoint_inserted_here_p (CORE_ADDR pc);
 
 static void free_bp_location (struct bp_location *loc);
 
-static void mark_breakpoints_out (void);
-
 static struct bp_location *
 allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type);
 
-static void update_global_location_list (void);
+static void update_global_location_list (int);
 
-static void update_global_location_list_nothrow (void);
+static void update_global_location_list_nothrow (int);
 
 static int is_hardware_watchpoint (struct breakpoint *bpt);
 
@@ -259,23 +246,44 @@ Automatic usage of hardware breakpoints is %s.\n"),
                    value);
 }
 
-/* If 1, gdb will keep breakpoints inserted even as inferior is stopped, 
-   and immediately insert any new breakpoints.  If 0, gdb will insert 
-   breakpoints into inferior only when resuming it, and will remove 
-   breakpoints upon stop.  */
-static int always_inserted_mode = 0;
-static void 
+/* If on, gdb will keep breakpoints inserted even as inferior is
+   stopped, and immediately insert any new breakpoints.  If off, gdb
+   will insert breakpoints into inferior only when resuming it, and
+   will remove breakpoints upon stop.  If auto, GDB will behave as ON
+   if in non-stop mode, and as OFF if all-stop mode.*/
+
+static const char always_inserted_auto[] = "auto";
+static const char always_inserted_on[] = "on";
+static const char always_inserted_off[] = "off";
+static const char *always_inserted_enums[] = {
+  always_inserted_auto,
+  always_inserted_off,
+  always_inserted_on,
+  NULL
+};
+static const char *always_inserted_mode = always_inserted_auto;
+static void
 show_always_inserted_mode (struct ui_file *file, int from_tty,
-                          struct cmd_list_element *c, const char *value)
+                    struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("Always inserted breakpoint mode is %s.\n"), value);
+  if (always_inserted_mode == always_inserted_auto)
+    fprintf_filtered (file, _("\
+Always inserted breakpoint mode is %s (currently %s).\n"),
+                     value,
+                     breakpoints_always_inserted_mode () ? "on" : "off");
+  else
+    fprintf_filtered (file, _("Always inserted breakpoint mode is %s.\n"), value);
 }
 
+int
+breakpoints_always_inserted_mode (void)
+{
+  return (always_inserted_mode == always_inserted_on
+         || (always_inserted_mode == always_inserted_auto && non_stop));
+}
 
 void _initialize_breakpoint (void);
 
-extern int addressprint;       /* Print machine addresses? */
-
 /* Are we executing breakpoint commands?  */
 static int executing_breakpoint_commands;
 
@@ -302,73 +310,21 @@ static int overlay_events_enabled;
             B ? (TMP=B->global_next, 1): 0;    \
             B = TMP)
 
-/* True if breakpoint hit counts should be displayed in breakpoint info.  */
-
-int show_breakpoint_hit_counts = 1;
-
 /* Chains of all breakpoints defined.  */
 
 struct breakpoint *breakpoint_chain;
 
 struct bp_location *bp_location_chain;
 
+/* The locations that no longer correspond to any breakpoint,
+   unlinked from bp_location_chain, but for which a hit
+   may still be reported by a target.  */
+VEC(bp_location_p) *moribund_locations = NULL;
+
 /* Number of last breakpoint made.  */
 
 int breakpoint_count;
 
-/* This function returns a pointer to the string representation of the
-   pathname of the dynamically-linked library that has just been
-   loaded.
-
-   This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
-   or undefined results are guaranteed.
-
-   This string's contents are only valid immediately after the
-   inferior has stopped in the dynamic linker hook, and becomes
-   invalid as soon as the inferior is continued.  Clients should make
-   a copy of this string if they wish to continue the inferior and
-   then access the string.  */
-
-#ifndef SOLIB_LOADED_LIBRARY_PATHNAME
-#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) ""
-#endif
-
-/* This function returns a pointer to the string representation of the
-   pathname of the dynamically-linked library that has just been
-   unloaded.
-
-   This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is
-   TRUE, or undefined results are guaranteed.
-
-   This string's contents are only valid immediately after the
-   inferior has stopped in the dynamic linker hook, and becomes
-   invalid as soon as the inferior is continued.  Clients should make
-   a copy of this string if they wish to continue the inferior and
-   then access the string.  */
-
-#ifndef SOLIB_UNLOADED_LIBRARY_PATHNAME
-#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) ""
-#endif
-
-/* This function is called by the "catch load" command.  It allows the
-   debugger to be notified by the dynamic linker when a specified
-   library file (or any library file, if filename is NULL) is loaded.  */
-
-#ifndef SOLIB_CREATE_CATCH_LOAD_HOOK
-#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
-   error (_("catch of library loads not yet implemented on this platform"))
-#endif
-
-/* This function is called by the "catch unload" command.  It allows
-   the debugger to be notified by the dynamic linker when a specified
-   library file (or any library file, if filename is NULL) is
-   unloaded.  */
-
-#ifndef SOLIB_CREATE_CATCH_UNLOAD_HOOK
-#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid, tempflag, filename, cond_string) \
-   error (_("catch of library unloads not yet implemented on this platform"))
-#endif
-
 /* Return whether a breakpoint is an active enabled breakpoint.  */
 static int
 breakpoint_enabled (struct breakpoint *b)
@@ -383,7 +339,7 @@ set_breakpoint_count (int num)
 {
   breakpoint_count = num;
   set_internalvar (lookup_internalvar ("bpnum"),
-                  value_from_longest (builtin_type_int, (LONGEST) num));
+                  value_from_longest (builtin_type_int32, (LONGEST) num));
 }
 
 /* Used in run_command to zero the hit count when a new run starts. */
@@ -623,7 +579,7 @@ condition_command (char *arg, int from_tty)
              }
          }
        breakpoints_changed ();
-       breakpoint_modify_event (b->number);
+       observer_notify_breakpoint_modified (b->number);
        return;
       }
 
@@ -657,12 +613,12 @@ commands_command (char *arg, int from_tty)
        char *tmpbuf = xstrprintf ("Type commands for when breakpoint %d is hit, one per line.", 
                                 bnum);
        struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
-       l = read_command_lines (tmpbuf, from_tty);
+       l = read_command_lines (tmpbuf, from_tty, 1);
        do_cleanups (cleanups);
        free_command_lines (&b->commands);
        b->commands = l;
        breakpoints_changed ();
-       breakpoint_modify_event (b->number);
+       observer_notify_breakpoint_modified (b->number);
        return;
     }
   error (_("No breakpoint number %d."), bnum);
@@ -708,7 +664,7 @@ commands_from_control_command (char *arg, struct command_line *cmd)
           list after it finishes execution.  */
        b->commands = copy_command_lines (cmd->body_list[0]);
        breakpoints_changed ();
-       breakpoint_modify_event (b->number);
+       observer_notify_breakpoint_modified (b->number);
        return simple_control;
       }
   error (_("No breakpoint number %d."), bnum);
@@ -781,21 +737,10 @@ insert_catchpoint (struct ui_out *uo, void *args)
   struct breakpoint *b = (struct breakpoint *) args;
   int val = -1;
 
-  switch (b->type)
-    {
-    case bp_catch_fork:
-      target_insert_fork_catchpoint (PIDGET (inferior_ptid));
-      break;
-    case bp_catch_vfork:
-      target_insert_vfork_catchpoint (PIDGET (inferior_ptid));
-      break;
-    case bp_catch_exec:
-      target_insert_exec_catchpoint (PIDGET (inferior_ptid));
-      break;
-    default:
-      internal_error (__FILE__, __LINE__, _("unknown breakpoint type"));
-      break;
-    }
+  gdb_assert (b->type == bp_catchpoint);
+  gdb_assert (b->ops != NULL && b->ops->insert != NULL);
+
+  b->ops->insert (b);
 }
 
 static int
@@ -1230,9 +1175,7 @@ Note: automatically using hardware breakpoints for read-only addresses.\n"));
       bpt->inserted = (val != -1);
     }
 
-  else if (bpt->owner->type == bp_catch_fork
-          || bpt->owner->type == bp_catch_vfork
-          || bpt->owner->type == bp_catch_exec)
+  else if (bpt->owner->type == bp_catchpoint)
     {
       struct gdb_exception e = catch_exception (uiout, insert_catchpoint,
                                                bpt->owner, RETURN_MASK_ERROR);
@@ -1265,9 +1208,12 @@ insert_breakpoints (void)
     if (is_hardware_watchpoint (bpt))
       update_watchpoint (bpt, 0 /* don't reparse. */);
 
-  update_global_location_list ();
+  update_global_location_list (1);
 
-  if (!always_inserted_mode && target_has_execution)
+  if (!breakpoints_always_inserted_mode ()
+      && (target_has_execution
+         || (gdbarch_has_global_solist (target_gdbarch)
+             && target_supports_multi_process ())))
     /* update_global_location_list does not insert breakpoints
        when always_inserted_mode is not enabled.  Explicitly
        insert them now.  */
@@ -1325,7 +1271,7 @@ insert_breakpoint_locations (void)
       if (!is_hardware_watchpoint (bpt))
        continue;
 
-      if (bpt->enable_state != bp_enabled)
+      if (!breakpoint_enabled (bpt))
        continue;
 
       if (bpt->disposition == disp_del_at_next_stop)
@@ -1437,30 +1383,23 @@ reattach_breakpoints (int pid)
   return 0;
 }
 
-static void
-restore_always_inserted_mode (void *p)
-{
-  always_inserted_mode = (uintptr_t) p;
-}
-
 void
 update_breakpoints_after_exec (void)
 {
   struct breakpoint *b;
   struct breakpoint *temp;
-  struct cleanup *cleanup;
-
-  /* Doing this first prevents the badness of having delete_breakpoint()
-     write a breakpoint's current "shadow contents" to lift the bp.  That
-     shadow is NOT valid after an exec()! */
-  mark_breakpoints_out ();
-
-  /* The binary we used to debug is now gone, and we're updating
-     breakpoints for the new binary.  Until we're done, we should not
-     try to insert breakpoints.  */
-  cleanup = make_cleanup (restore_always_inserted_mode, 
-                         (void *) (uintptr_t) always_inserted_mode);
-  always_inserted_mode = 0;
+  struct bp_location *bploc;
+
+  /* We're about to delete breakpoints from GDB's lists.  If the
+     INSERTED flag is true, GDB will try to lift the breakpoints by
+     writing the breakpoints' "shadow contents" back into memory.  The
+     "shadow contents" are NOT valid after an exec, so GDB should not
+     do that.  Instead, the target is responsible from marking
+     breakpoints out as soon as it detects an exec.  We don't do that
+     here instead, because there may be other attempts to delete
+     breakpoints after detecting an exec and before reaching here.  */
+  ALL_BP_LOCATIONS (bploc)
+    gdb_assert (!bploc->inserted);
 
   ALL_BREAKPOINTS_SAFE (b, temp)
   {
@@ -1486,21 +1425,23 @@ update_breakpoints_after_exec (void)
        continue;
       }
 
-    /* Don't delete an exec catchpoint, because else the inferior
-       won't stop when it ought!
-
-       Similarly, we probably ought to keep vfork catchpoints, 'cause
-       on this target, we may not be able to stop when the vfork is
-       seen, but only when the subsequent exec is seen.  (And because
-       deleting fork catchpoints here but not vfork catchpoints will
-       seem mysterious to users, keep those too.)  */
-    if ((b->type == bp_catch_exec) ||
-       (b->type == bp_catch_vfork) ||
-       (b->type == bp_catch_fork))
+    /* Longjmp and longjmp-resume breakpoints are also meaningless
+       after an exec.  */
+    if (b->type == bp_longjmp || b->type == bp_longjmp_resume)
       {
+       delete_breakpoint (b);
        continue;
       }
 
+    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
+           the catchpoints need to something, we will need to add
+           a new method, and call this method from here.  */
+        continue;
+      }
+
     /* bp_finish is a special case.  The only way we ought to be able
        to see one of these when an exec() has happened, is if the user
        caught a vfork, and then said "finish".  Ordinarily a finish just
@@ -1543,7 +1484,6 @@ update_breakpoints_after_exec (void)
   }
   /* FIXME what about longjmp breakpoints?  Re-create them here?  */
   create_overlay_event_breakpoint ("_ovly_debug_event");
-  do_cleanups (cleanup);
 }
 
 int
@@ -1647,6 +1587,13 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is)
              val = 0;
            }
        }
+
+      /* In some cases, we might not be able to remove a breakpoint
+        in a shared library that has already been removed, but we
+        have not yet processed the shlib unload event.  */
+      if (val && solib_address (b->address))
+       val = 0;
+
       if (val)
        return val;
       b->inserted = (is == mark_inserted);
@@ -1665,28 +1612,13 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is)
        warning (_("Could not remove hardware watchpoint %d."),
                 b->owner->number);
     }
-  else if ((b->owner->type == bp_catch_fork ||
-           b->owner->type == bp_catch_vfork ||
-           b->owner->type == bp_catch_exec)
-          && breakpoint_enabled (b->owner)
-          && !b->duplicate)
+  else if (b->owner->type == bp_catchpoint
+           && breakpoint_enabled (b->owner)
+           && !b->duplicate)
     {
-      val = -1;
-      switch (b->owner->type)
-       {
-       case bp_catch_fork:
-         val = target_remove_fork_catchpoint (PIDGET (inferior_ptid));
-         break;
-       case bp_catch_vfork:
-         val = target_remove_vfork_catchpoint (PIDGET (inferior_ptid));
-         break;
-       case bp_catch_exec:
-         val = target_remove_exec_catchpoint (PIDGET (inferior_ptid));
-         break;
-       default:
-         warning (_("Internal error, %s line %d."), __FILE__, __LINE__);
-         break;
-       }
+      gdb_assert (b->owner->ops != NULL && b->owner->ops->remove != NULL);
+
+      val = b->owner->ops->remove (b->owner);
       if (val)
        return val;
       b->inserted = (is == mark_inserted);
@@ -1697,7 +1629,7 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is)
 
 /* Clear the "inserted" flag in all breakpoints.  */
 
-static void
+void
 mark_breakpoints_out (void)
 {
   struct bp_location *bpt;
@@ -1723,9 +1655,16 @@ breakpoint_init_inferior (enum inf_context context)
 {
   struct breakpoint *b, *temp;
   struct bp_location *bpt;
+  int ix;
+
+  /* If breakpoint locations are shared across processes, then there's
+     nothing to do.  */
+  if (gdbarch_has_global_solist (target_gdbarch))
+    return;
 
   ALL_BP_LOCATIONS (bpt)
-    bpt->inserted = 0;
+    if (bpt->owner->enable_state != bp_permanent)
+      bpt->inserted = 0;
 
   ALL_BREAKPOINTS_SAFE (b, temp)
   {
@@ -1764,6 +1703,11 @@ breakpoint_init_inferior (enum inf_context context)
        break;
       }
   }
+
+  /* Get rid of the moribund locations.  */
+  for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, bpt); ++ix)
+    free_bp_location (bpt);
+  VEC_free (bp_location_p, moribund_locations);
 }
 
 /* breakpoint_here_p (PC) returns non-zero if an enabled breakpoint
@@ -1806,6 +1750,20 @@ breakpoint_here_p (CORE_ADDR pc)
   return any_breakpoint_here ? ordinary_breakpoint_here : 0;
 }
 
+/* Return true if there's a moribund breakpoint at PC.  */
+
+int
+moribund_breakpoint_here_p (CORE_ADDR pc)
+{
+  struct bp_location *loc;
+  int ix;
+
+  for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
+    if (loc->address == pc)
+      return 1;
+
+  return 0;
+}
 
 /* Returns non-zero if there's a breakpoint inserted at PC, which is
    inserted using regular breakpoint_chain/bp_location_chain mechanism.
@@ -1926,22 +1884,7 @@ breakpoint_thread_match (CORE_ADDR pc, ptid_t ptid)
 int
 ep_is_catchpoint (struct breakpoint *ep)
 {
-  return
-    (ep->type == bp_catch_load)
-    || (ep->type == bp_catch_unload)
-    || (ep->type == bp_catch_fork)
-    || (ep->type == bp_catch_vfork)
-    || (ep->type == bp_catch_exec);
-
-  /* ??rehrauer: Add more kinds here, as are implemented... */
-}
-
-int
-ep_is_shlib_catchpoint (struct breakpoint *ep)
-{
-  return
-    (ep->type == bp_catch_load)
-    || (ep->type == bp_catch_unload);
+  return (ep->type == bp_catchpoint);
 }
 
 void 
@@ -1994,7 +1937,10 @@ bpstat_copy (bpstat bs)
       if (bs->commands != NULL)
        tmp->commands = copy_command_lines (bs->commands);
       if (bs->old_val != NULL)
-       tmp->old_val = value_copy (bs->old_val);
+       {
+         tmp->old_val = value_copy (bs->old_val);
+         release_value (tmp->old_val);
+       }
 
       if (p == NULL)
        /* This is the first thing in the chain.  */
@@ -2109,31 +2055,27 @@ cleanup_executing_breakpoints (void *ignore)
 /* Execute all the commands associated with all the breakpoints at this
    location.  Any of these commands could cause the process to proceed
    beyond this point, etc.  We look out for such changes by checking
-   the global "breakpoint_proceeded" after each command.  */
+   the global "breakpoint_proceeded" after each command.
 
-void
-bpstat_do_actions (bpstat *bsp)
+   Returns true if a breakpoint command resumed the inferior.  In that
+   case, it is the caller's responsibility to recall it again with the
+   bpstat of the current thread.  */
+
+static int
+bpstat_do_actions_1 (bpstat *bsp)
 {
   bpstat bs;
   struct cleanup *old_chain;
+  int again = 0;
 
   /* Avoid endless recursion if a `source' command is contained
      in bs->commands.  */
   if (executing_breakpoint_commands)
-    return;
+    return 0;
 
   executing_breakpoint_commands = 1;
   old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
 
-top:
-  /* Note that (as of this writing), our callers all appear to
-     be passing us the address of global stop_bpstat.  And, if
-     our calls to execute_control_command cause the inferior to
-     proceed, that global (and hence, *bsp) will change.
-
-     We must be careful to not touch *bsp unless the inferior
-     has not proceeded. */
-
   /* This pointer will iterate over the list of bpstat's. */
   bs = *bsp;
 
@@ -2173,30 +2115,46 @@ top:
       if (breakpoint_proceeded)
        {
          if (target_can_async_p ())
-         /* If we are in async mode, then the target might
-            be still running, not stopped at any breakpoint,
-            so nothing for us to do here -- just return to
-            the event loop.  */
-           break;
+           /* If we are in async mode, then the target might be still
+              running, not stopped at any breakpoint, so nothing for
+              us to do here -- just return to the event loop.  */
+           ;
          else
            /* In sync mode, when execute_control_command returns
               we're already standing on the next breakpoint.
-              Breakpoint commands for that stop were not run,
-              since execute_command does not run breakpoint
-              commands -- only command_line_handler does, but
-              that one is not involved in execution of breakpoint
-              commands.  So, we can now execute breakpoint commands.
-              There's an implicit assumption that we're called with
-              stop_bpstat, so our parameter is the new bpstat to
-              handle.  
-              It should be noted that making execute_command do
-              bpstat actions is not an option -- in this case we'll
-              have recursive invocation of bpstat for each breakpoint
-              with a command, and can easily blow up GDB stack.  */
-           goto top;
+              Breakpoint commands for that stop were not run, since
+              execute_command does not run breakpoint commands --
+              only command_line_handler does, but that one is not
+              involved in execution of breakpoint commands.  So, we
+              can now execute breakpoint commands.  It should be
+              noted that making execute_command do bpstat actions is
+              not an option -- in this case we'll have recursive
+              invocation of bpstat for each breakpoint with a
+              command, and can easily blow up GDB stack.  Instead, we
+              return true, which will trigger the caller to recall us
+              with the new stop_bpstat.  */
+           again = 1;
+         break;
        }
     }
   do_cleanups (old_chain);
+  return again;
+}
+
+void
+bpstat_do_actions (void)
+{
+  /* Do any commands attached to breakpoint we are stopped at.  */
+  while (!ptid_equal (inferior_ptid, null_ptid)
+        && target_has_execution
+        && !is_exited (inferior_ptid)
+        && !is_executing (inferior_ptid))
+    /* Since in sync mode, bpstat_do_actions may resume the inferior,
+       and only return when it is stopped at the next breakpoint, we
+       keep doing breakpoint actions until it returns false to
+       indicate the inferior was not resumed.  */
+    if (!bpstat_do_actions_1 (&inferior_thread ()->stop_bpstat))
+      break;
 }
 
 /* Print out the (old or new) value associated with a watchpoint.  */
@@ -2207,7 +2165,11 @@ watchpoint_value_print (struct value *val, struct ui_file *stream)
   if (val == NULL)
     fprintf_unfiltered (stream, _("<unreadable>"));
   else
-    value_print (val, stream, 0, Val_pretty_default);
+    {
+      struct value_print_options opts;
+      get_user_print_options (&opts);
+      value_print (val, stream, &opts);
+    }
 }
 
 /* This is the normal print function for a bpstat.  In the future,
@@ -2294,46 +2256,6 @@ print_it_typical (bpstat bs)
       return PRINT_NOTHING;
       break;
 
-    case bp_catch_load:
-      annotate_catchpoint (b->number);
-      printf_filtered (_("\nCatchpoint %d (loaded %s), "),
-                      b->number,
-                      b->triggered_dll_pathname);
-      return PRINT_SRC_AND_LOC;
-      break;
-
-    case bp_catch_unload:
-      annotate_catchpoint (b->number);
-      printf_filtered (_("\nCatchpoint %d (unloaded %s), "),
-                      b->number,
-                      b->triggered_dll_pathname);
-      return PRINT_SRC_AND_LOC;
-      break;
-
-    case bp_catch_fork:
-      annotate_catchpoint (b->number);
-      printf_filtered (_("\nCatchpoint %d (forked process %d), "),
-                      b->number, 
-                      b->forked_inferior_pid);
-      return PRINT_SRC_AND_LOC;
-      break;
-
-    case bp_catch_vfork:
-      annotate_catchpoint (b->number);
-      printf_filtered (_("\nCatchpoint %d (vforked process %d), "),
-                      b->number, 
-                      b->forked_inferior_pid);
-      return PRINT_SRC_AND_LOC;
-      break;
-
-    case bp_catch_exec:
-      annotate_catchpoint (b->number);
-      printf_filtered (_("\nCatchpoint %d (exec'd %s), "),
-                      b->number,
-                      b->exec_pathname);
-      return PRINT_SRC_AND_LOC;
-      break;
-
     case bp_watchpoint:
     case bp_hardware_watchpoint:
       annotate_watchpoint (b->number);
@@ -2652,7 +2574,8 @@ watchpoint_check (void *p)
       /* If we've gotten confused in the unwinder, we might have
         returned a frame that can't describe this variable.  */
       if (within_current_scope
-         && block_function (b->exp_valid_block) != get_frame_function (fr))
+         && (block_linkage_function (b->exp_valid_block)
+             != get_frame_function (fr)))
        within_current_scope = 0;
 
       /* in_function_epilogue_p() returns a non-zero value if we're still
@@ -2751,9 +2674,7 @@ bpstat_check_location (const struct bp_location *bl, CORE_ADDR bp_addr)
       && b->type != bp_read_watchpoint
       && b->type != bp_access_watchpoint
       && b->type != bp_hardware_breakpoint
-      && b->type != bp_catch_fork
-      && b->type != bp_catch_vfork
-      && b->type != bp_catch_exec)     /* a non-watchpoint bp */
+      && b->type != bp_catchpoint)     /* a non-watchpoint bp */
     {
       if (bl->address != bp_addr)      /* address doesn't match */
        return 0;
@@ -2785,48 +2706,14 @@ bpstat_check_location (const struct bp_location *bl, CORE_ADDR bp_addr)
          && !section_is_mapped (bl->section))
        return 0;
     }
-  
-  /* Is this a catchpoint of a load or unload?  If so, did we
-     get a load or unload of the specified library?  If not,
-     ignore it. */
-  if ((b->type == bp_catch_load)
-#if defined(SOLIB_HAVE_LOAD_EVENT)
-      && (!SOLIB_HAVE_LOAD_EVENT (PIDGET (inferior_ptid))
-         || ((b->dll_pathname != NULL)
-             && (strcmp (b->dll_pathname, 
-                         SOLIB_LOADED_LIBRARY_PATHNAME (
-                           PIDGET (inferior_ptid)))
-                 != 0)))
-#endif
-      )
-    return 0;
-  
-  if ((b->type == bp_catch_unload)
-#if defined(SOLIB_HAVE_UNLOAD_EVENT)
-      && (!SOLIB_HAVE_UNLOAD_EVENT (PIDGET (inferior_ptid))
-         || ((b->dll_pathname != NULL)
-             && (strcmp (b->dll_pathname, 
-                         SOLIB_UNLOADED_LIBRARY_PATHNAME (
-                           PIDGET (inferior_ptid)))
-                 != 0)))
-#endif
-      )
-    return 0;
-
-  if ((b->type == bp_catch_fork)
-      && !inferior_has_forked (PIDGET (inferior_ptid),
-                              &b->forked_inferior_pid))
-    return 0;
-  
-  if ((b->type == bp_catch_vfork)
-      && !inferior_has_vforked (PIDGET (inferior_ptid),
-                               &b->forked_inferior_pid))
-    return 0;
-  
-  if ((b->type == bp_catch_exec)
-      && !inferior_has_execd (PIDGET (inferior_ptid), &b->exec_pathname))
-    return 0;
 
+  if (b->type == bp_catchpoint)
+    {
+      gdb_assert (b->ops != NULL && b->ops->breakpoint_hit != NULL);
+      if (!b->ops->breakpoint_hit (b))
+        return 0;
+    }
+     
   return 1;
 }
 
@@ -3006,10 +2893,13 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
 {
   struct breakpoint *b = NULL;
   const struct bp_location *bl;
+  struct bp_location *loc;
   /* Root of the chain of bpstat's */
   struct bpstats root_bs[1];
   /* Pointer to the last thing in the chain currently.  */
   bpstat bs = root_bs;
+  int ix;
+  int need_remove_insert;
 
   ALL_BP_LOCATIONS (bl)
   {
@@ -3057,8 +2947,9 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
        /* We will stop here */
        if (b->disposition == disp_disable)
          {
-           b->enable_state = bp_disabled;
-           update_global_location_list ();
+           if (b->enable_state != bp_permanent)
+             b->enable_state = bp_disabled;
+           update_global_location_list (0);
          }
        if (b->silent)
          bs->print = 0;
@@ -3078,6 +2969,18 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
       bs->print_it = print_it_noop;
   }
 
+  for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
+    {
+      if (loc->address == bp_addr)
+       {
+         bs = bpstat_alloc (loc, bs);
+         /* For hits of moribund locations, we should just proceed.  */
+         bs->stop = 0;
+         bs->print = 0;
+         bs->print_it = print_it_noop;
+       }
+    }
+
   bs->next = NULL;             /* Terminate the chain */
   bs = root_bs->next;          /* Re-grab the head of the chain */
 
@@ -3089,9 +2992,11 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
     if (bs->stop)
       break;
 
+  need_remove_insert = 0;
   if (bs == NULL)
     for (bs = root_bs->next; bs != NULL; bs = bs->next)
       if (!bs->stop
+         && bs->breakpoint_at->owner
          && (bs->breakpoint_at->owner->type == bp_hardware_watchpoint
              || bs->breakpoint_at->owner->type == bp_read_watchpoint
              || bs->breakpoint_at->owner->type == bp_access_watchpoint))
@@ -3100,11 +3005,15 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
             location is no longer used by the watchpoint.  Prevent
             further code from trying to use it.  */
          bs->breakpoint_at = NULL;
-         remove_breakpoints ();
-         insert_breakpoints ();
-         break;
+         need_remove_insert = 1;
        }
 
+  if (need_remove_insert)
+    {
+      remove_breakpoints ();
+      insert_breakpoints ();
+    }
+
   return root_bs->next;
 }
 \f
@@ -3145,9 +3054,6 @@ bpstat_what (bpstat bs)
       /* We hit the shared library event breakpoint.  */
       shlib_event,
 
-      /* We caught a shared library event.  */
-      catch_shlib_event,
-
       /* This is just used to count how many enums there are.  */
       class_last
     };
@@ -3163,7 +3069,6 @@ bpstat_what (bpstat bs)
 #define clr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
 #define sr BPSTAT_WHAT_STEP_RESUME
 #define shl BPSTAT_WHAT_CHECK_SHLIBS
-#define shlr BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK
 
 /* "Can't happen."  Might want to print an error message.
    abort() is not out of the question, but chances are GDB is just
@@ -3184,14 +3089,13 @@ bpstat_what (bpstat bs)
      back and decide something of a lower priority is better.  The
      ordering is:
 
-     kc   < clr sgl shl shlr slr sn sr ss
-     sgl  < shl shlr slr sn sr ss
-     slr  < err shl shlr sn sr ss
-     clr  < err shl shlr sn sr ss
-     ss   < shl shlr sn sr
-     sn   < shl shlr sr
-     shl  < shlr sr
-     shlr < sr
+     kc   < clr sgl shl slr sn sr ss
+     sgl  < shl slr sn sr ss
+     slr  < err shl sn sr ss
+     clr  < err shl sn sr ss
+     ss   < shl sn sr
+     sn   < shl sr
+     shl  < sr
      sr   <
 
      What I think this means is that we don't need a damned table
@@ -3208,30 +3112,28 @@ bpstat_what (bpstat bs)
     table[(int) class_last][(int) BPSTAT_WHAT_LAST] =
   {
   /*                              old action */
-  /*       kc    ss    sn    sgl    slr   clr   sr   shl   shlr
+  /*       kc    ss    sn    sgl    slr   clr   sr   shl
    */
 /*no_effect */
-    {kc, ss, sn, sgl, slr, clr, sr, shl, shlr},
+    {kc, ss, sn, sgl, slr, clr, sr, shl},
 /*wp_silent */
-    {ss, ss, sn, ss, ss, ss, sr, shl, shlr},
+    {ss, ss, sn, ss, ss, ss, sr, shl},
 /*wp_noisy */
-    {sn, sn, sn, sn, sn, sn, sr, shl, shlr},
+    {sn, sn, sn, sn, sn, sn, sr, shl},
 /*bp_nostop */
-    {sgl, ss, sn, sgl, slr, slr, sr, shl, shlr},
+    {sgl, ss, sn, sgl, slr, slr, sr, shl},
 /*bp_silent */
-    {ss, ss, sn, ss, ss, ss, sr, shl, shlr},
+    {ss, ss, sn, ss, ss, ss, sr, shl},
 /*bp_noisy */
-    {sn, sn, sn, sn, sn, sn, sr, shl, shlr},
+    {sn, sn, sn, sn, sn, sn, sr, shl},
 /*long_jump */
-    {slr, ss, sn, slr, slr, err, sr, shl, shlr},
+    {slr, ss, sn, slr, slr, err, sr, shl},
 /*long_resume */
-    {clr, ss, sn, err, err, err, sr, shl, shlr},
+    {clr, ss, sn, err, err, err, sr, shl},
 /*step_resume */
-    {sr, sr, sr, sr, sr, sr, sr, sr, sr},
+    {sr, sr, sr, sr, sr, sr, sr, sr},
 /*shlib */
-    {shl, shl, shl, shl, shl, shl, sr, shl, shlr},
-/*catch_shlib */
-    {shlr, shlr, shlr, shlr, shlr, shlr, sr, shlr, shlr}
+    {shl, shl, shl, shl, shl, shl, sr, shl}
   };
 
 #undef kc
@@ -3244,7 +3146,6 @@ bpstat_what (bpstat bs)
 #undef sr
 #undef ts
 #undef shl
-#undef shlr
   enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
   struct bpstat_what retval;
 
@@ -3256,6 +3157,9 @@ bpstat_what (bpstat bs)
        /* I suspect this can happen if it was a momentary breakpoint
           which has since been deleted.  */
        continue;
+      if (bs->breakpoint_at->owner == NULL)
+       bs_class = bp_nostop;
+      else
       switch (bs->breakpoint_at->owner->type)
        {
        case bp_none:
@@ -3316,19 +3220,7 @@ bpstat_what (bpstat bs)
        case bp_overlay_event:
          bs_class = bp_nostop;
          break;
-       case bp_catch_load:
-       case bp_catch_unload:
-         /* Only if this catchpoint triggered should we cause the
-            step-out-of-dld behaviour.  Otherwise, we ignore this
-            catchpoint.  */
-         if (bs->stop)
-           bs_class = catch_shlib_event;
-         else
-           bs_class = no_effect;
-         break;
-       case bp_catch_fork:
-       case bp_catch_vfork:
-       case bp_catch_exec:
+       case bp_catchpoint:
          if (bs->stop)
            {
              if (bs->print)
@@ -3370,67 +3262,6 @@ bpstat_should_step (void)
 
 \f
 
-/* Given a bpstat that records zero or more triggered eventpoints, this
-   function returns another bpstat which contains only the catchpoints
-   on that first list, if any. */
-void
-bpstat_get_triggered_catchpoints (bpstat ep_list, bpstat *cp_list)
-{
-  struct bpstats root_bs[1];
-  bpstat bs = root_bs;
-  struct breakpoint *ep;
-  char *dll_pathname;
-
-  bpstat_clear (cp_list);
-  root_bs->next = NULL;
-
-  for (; ep_list != NULL; ep_list = ep_list->next)
-    {
-      /* Is this eventpoint a catchpoint?  If not, ignore it. */
-      ep = ep_list->breakpoint_at->owner;
-      if (ep == NULL)
-       break;
-      if ((ep->type != bp_catch_load) &&
-         (ep->type != bp_catch_unload))
-       /* pai: (temp) ADD fork/vfork here!!  */
-       continue;
-
-      /* Yes; add it to the list. */
-      bs = bpstat_alloc (ep_list->breakpoint_at, bs);
-      *bs = *ep_list;
-      bs->next = NULL;
-      bs = root_bs->next;
-
-#if defined(SOLIB_ADD)
-      /* Also, for each triggered catchpoint, tag it with the name of
-         the library that caused this trigger.  (We copy the name now,
-         because it's only guaranteed to be available NOW, when the
-         catchpoint triggers.  Clients who may wish to know the name
-         later must get it from the catchpoint itself.) */
-      if (ep->triggered_dll_pathname != NULL)
-       xfree (ep->triggered_dll_pathname);
-      if (ep->type == bp_catch_load)
-       dll_pathname = SOLIB_LOADED_LIBRARY_PATHNAME (
-                        PIDGET (inferior_ptid));
-      else
-       dll_pathname = SOLIB_UNLOADED_LIBRARY_PATHNAME (
-                        PIDGET (inferior_ptid));
-#else
-      dll_pathname = NULL;
-#endif
-      if (dll_pathname)
-       {
-         ep->triggered_dll_pathname = (char *) 
-           xmalloc (strlen (dll_pathname) + 1);
-         strcpy (ep->triggered_dll_pathname, dll_pathname);
-       }
-      else
-       ep->triggered_dll_pathname = NULL;
-    }
-
-  *cp_list = bs;
-}
-
 static void print_breakpoint_location (struct breakpoint *b,
                                       struct bp_location *loc,
                                       char *wrap_indent,
@@ -3506,11 +3337,7 @@ print_one_breakpoint_location (struct breakpoint *b,
     {bp_shlib_event, "shlib events"},
     {bp_thread_event, "thread events"},
     {bp_overlay_event, "overlay events"},
-    {bp_catch_load, "catch load"},
-    {bp_catch_unload, "catch unload"},
-    {bp_catch_fork, "catch fork"},
-    {bp_catch_vfork, "catch vfork"},
-    {bp_catch_exec, "catch exec"}
+    {bp_catchpoint, "catchpoint"},
   };
   
   static char bpenables[] = "nynny";
@@ -3521,6 +3348,9 @@ print_one_breakpoint_location (struct breakpoint *b,
 
   int header_of_multiple = 0;
   int part_of_multiple = (loc != NULL);
+  struct value_print_options opts;
+
+  get_user_print_options (&opts);
 
   gdb_assert (!loc || loc_number != 0);
   /* See comment in print_one_breakpoint concerning
@@ -3584,7 +3414,7 @@ print_one_breakpoint_location (struct breakpoint *b,
   
   /* 5 and 6 */
   strcpy (wrap_indent, "                           ");
-  if (addressprint)
+  if (opts.addressprint)
     {
       if (gdbarch_addr_bit (current_gdbarch) <= 32)
        strcat (wrap_indent, "           ");
@@ -3616,65 +3446,13 @@ print_one_breakpoint_location (struct breakpoint *b,
        /* Field 4, the address, is omitted (which makes the columns
           not line up too nicely with the headers, but the effect
           is relatively readable).  */
-       if (addressprint)
+       if (opts.addressprint)
          ui_out_field_skip (uiout, "addr");
        annotate_field (5);
        print_expression (b->exp, stb->stream);
        ui_out_field_stream (uiout, "what", stb);
        break;
 
-      case bp_catch_load:
-      case bp_catch_unload:
-       /* Field 4, the address, is omitted (which makes the columns
-          not line up too nicely with the headers, but the effect
-          is relatively readable).  */
-       if (addressprint)
-         ui_out_field_skip (uiout, "addr");
-       annotate_field (5);
-       if (b->dll_pathname == NULL)
-         {
-           ui_out_field_string (uiout, "what", "<any library>");
-           ui_out_spaces (uiout, 1);
-         }
-       else
-         {
-           ui_out_text (uiout, "library \"");
-           ui_out_field_string (uiout, "what", b->dll_pathname);
-           ui_out_text (uiout, "\" ");
-         }
-       break;
-
-      case bp_catch_fork:
-      case bp_catch_vfork:
-       /* Field 4, the address, is omitted (which makes the columns
-          not line up too nicely with the headers, but the effect
-          is relatively readable).  */
-       if (addressprint)
-         ui_out_field_skip (uiout, "addr");
-       annotate_field (5);
-       if (b->forked_inferior_pid != 0)
-         {
-           ui_out_text (uiout, "process ");
-           ui_out_field_int (uiout, "what", b->forked_inferior_pid);
-           ui_out_spaces (uiout, 1);
-         }
-       break;
-
-      case bp_catch_exec:
-       /* Field 4, the address, is omitted (which makes the columns
-          not line up too nicely with the headers, but the effect
-          is relatively readable).  */
-       if (addressprint)
-         ui_out_field_skip (uiout, "addr");
-       annotate_field (5);
-       if (b->exec_pathname != NULL)
-         {
-           ui_out_text (uiout, "program \"");
-           ui_out_field_string (uiout, "what", b->exec_pathname);
-           ui_out_text (uiout, "\" ");
-         }
-       break;
-
       case bp_breakpoint:
       case bp_hardware_breakpoint:
       case bp_until:
@@ -3687,7 +3465,7 @@ print_one_breakpoint_location (struct breakpoint *b,
       case bp_shlib_event:
       case bp_thread_event:
       case bp_overlay_event:
-       if (addressprint)
+       if (opts.addressprint)
          {
            annotate_field (4);
            if (header_of_multiple)
@@ -3744,7 +3522,7 @@ print_one_breakpoint_location (struct breakpoint *b,
       ui_out_text (uiout, "\n");
     }
   
-  if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count)
+  if (!part_of_multiple && b->hit_count)
     {
       /* FIXME should make an annotation for this */
       if (ep_is_catchpoint (b))
@@ -3762,7 +3540,7 @@ print_one_breakpoint_location (struct breakpoint *b,
   /* Output the count also if it is zero, but only if this is
      mi. FIXME: Should have a better test for this. */
   if (ui_out_is_mi_like_p (uiout))
-    if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count == 0)
+    if (!part_of_multiple && b->hit_count == 0)
       ui_out_field_int (uiout, "times", b->hit_count);
 
   if (!part_of_multiple && b->ignore_count)
@@ -3871,11 +3649,7 @@ static int
 user_settable_breakpoint (const struct breakpoint *b)
 {
   return (b->type == bp_breakpoint
-         || b->type == bp_catch_load
-         || b->type == bp_catch_unload
-         || b->type == bp_catch_fork
-         || b->type == bp_catch_vfork
-         || b->type == bp_catch_exec
+         || b->type == bp_catchpoint
          || b->type == bp_hardware_breakpoint
          || b->type == bp_watchpoint
          || b->type == bp_read_watchpoint
@@ -3894,7 +3668,10 @@ breakpoint_1 (int bnum, int allflag)
   CORE_ADDR last_addr = (CORE_ADDR) -1;
   int nr_printable_breakpoints;
   struct cleanup *bkpttbl_chain;
+  struct value_print_options opts;
   
+  get_user_print_options (&opts);
+
   /* Compute the number of rows in the table. */
   nr_printable_breakpoints = 0;
   ALL_BREAKPOINTS (b)
@@ -3905,7 +3682,7 @@ breakpoint_1 (int bnum, int allflag)
          nr_printable_breakpoints++;
       }
 
-  if (addressprint)
+  if (opts.addressprint)
     bkpttbl_chain 
       = make_cleanup_ui_out_table_begin_end (uiout, 6, nr_printable_breakpoints,
                                              "BreakpointTable");
@@ -3928,7 +3705,7 @@ breakpoint_1 (int bnum, int allflag)
   if (nr_printable_breakpoints > 0)
     annotate_field (3);
   ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb");   /* 4 */
-  if (addressprint)
+  if (opts.addressprint)
        {
          if (nr_printable_breakpoints > 0)
            annotate_field (4);
@@ -3969,7 +3746,7 @@ breakpoint_1 (int bnum, int allflag)
       /* Compare against (CORE_ADDR)-1 in case some compiler decides
         that a comparison of an unsigned with -1 is always false.  */
       if (last_addr != (CORE_ADDR) -1 && !server_command)
-       set_next_address (last_addr);
+       set_next_address (current_gdbarch, last_addr);
     }
 
   /* FIXME? Should this be moved up so that it is only called when
@@ -4000,7 +3777,8 @@ maintenance_info_breakpoints (char *bnum_exp, int from_tty)
 }
 
 static int
-breakpoint_has_pc (struct breakpoint *b, CORE_ADDR pc, asection *section)
+breakpoint_has_pc (struct breakpoint *b,
+                  CORE_ADDR pc, struct obj_section *section)
 {
   struct bp_location *bl = b->loc;
   for (; bl; bl = bl->next)
@@ -4015,7 +3793,8 @@ breakpoint_has_pc (struct breakpoint *b, CORE_ADDR pc, asection *section)
 /* Print a message describing any breakpoints set at PC.  */
 
 static void
-describe_other_breakpoints (CORE_ADDR pc, asection *section, int thread)
+describe_other_breakpoints (CORE_ADDR pc, struct obj_section *section,
+                           int thread)
 {
   int others = 0;
   struct breakpoint *b;
@@ -4080,10 +3859,7 @@ set_default_breakpoint (int valid, CORE_ADDR addr, struct symtab *symtab,
       bp_hardware_watchpoint
       bp_read_watchpoint
       bp_access_watchpoint
-      bp_catch_exec
-      bp_longjmp_resume
-      bp_catch_fork
-      bp_catch_vork */
+      bp_catchpoint */
 
 static int
 breakpoint_address_is_meaningful (struct breakpoint *bpt)
@@ -4094,10 +3870,7 @@ breakpoint_address_is_meaningful (struct breakpoint *bpt)
          && type != bp_hardware_watchpoint
          && type != bp_read_watchpoint
          && type != bp_access_watchpoint
-         && type != bp_catch_exec
-         && type != bp_longjmp_resume
-         && type != bp_catch_fork
-         && type != bp_catch_vfork);
+         && type != bp_catchpoint);
 }
 
 /* Rescan breakpoints at the same address and section as BPT,
@@ -4107,7 +3880,7 @@ breakpoint_address_is_meaningful (struct breakpoint *bpt)
    that one the official one, and the rest as duplicates.  */
 
 static void
-check_duplicates_for (CORE_ADDR address, asection *section)
+check_duplicates_for (CORE_ADDR address, struct obj_section *section)
 {
   struct bp_location *b;
   int count = 0;
@@ -4212,9 +3985,7 @@ adjust_breakpoint_address (CORE_ADDR bpaddr, enum bptype bptype)
            || bptype == bp_hardware_watchpoint
            || bptype == bp_read_watchpoint
            || bptype == bp_access_watchpoint
-           || bptype == bp_catch_fork
-           || bptype == bp_catch_vfork
-           || bptype == bp_catch_exec)
+           || bptype == bp_catchpoint)
     {
       /* Watchpoints and the various bp_catch_* eventpoints should not
          have their addresses modified.  */
@@ -4267,8 +4038,6 @@ allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type)
     case bp_shlib_event:
     case bp_thread_event:
     case bp_overlay_event:
-    case bp_catch_load:
-    case bp_catch_unload:
       loc->loc_type = bp_loc_software_breakpoint;
       break;
     case bp_hardware_breakpoint:
@@ -4280,9 +4049,7 @@ allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type)
       loc->loc_type = bp_loc_hardware_watchpoint;
       break;
     case bp_watchpoint:
-    case bp_catch_fork:
-    case bp_catch_vfork:
-    case bp_catch_exec:
+    case bp_catchpoint:
       loc->loc_type = bp_loc_other;
       break;
     default:
@@ -4324,9 +4091,7 @@ set_raw_breakpoint_without_location (enum bptype bptype)
   b->ignore_count = 0;
   b->commands = NULL;
   b->frame_id = null_frame_id;
-  b->dll_pathname = NULL;
-  b->triggered_dll_pathname = NULL;
-  b->forked_inferior_pid = 0;
+  b->forked_inferior_pid = null_ptid;
   b->exec_pathname = NULL;
   b->ops = NULL;
   b->condition_not_parsed = 0;
@@ -4450,24 +4215,12 @@ create_internal_breakpoint (CORE_ADDR address, enum bptype type)
 static void
 create_longjmp_breakpoint (char *func_name)
 {
-  struct breakpoint *b;
   struct minimal_symbol *m;
 
-  if (func_name == NULL)
-    b = create_internal_breakpoint (0, bp_longjmp_resume);
-  else
-    {
-      if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL)
-       return;
-      b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m), bp_longjmp);
-    }
-
-  b->enable_state = bp_disabled;
-  b->silent = 1;
-  if (func_name)
-    b->addr_string = xstrdup (func_name);
-  update_global_location_list ();
+  if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL)
+    return;
+  set_momentary_breakpoint_at_pc (SYMBOL_VALUE_ADDRESS (m), bp_longjmp);
+  update_global_location_list (1);
 }
 
 /* Call this routine when stepping and nexting to enable a breakpoint
@@ -4475,39 +4228,38 @@ create_longjmp_breakpoint (char *func_name)
    set_longjmp_resume_breakpoint() to figure out where we are going. */
 
 void
-enable_longjmp_breakpoint (void)
+set_longjmp_breakpoint (void)
 {
-  struct breakpoint *b;
-
-  ALL_BREAKPOINTS (b)
-    if (b->type == bp_longjmp)
+  if (gdbarch_get_longjmp_target_p (current_gdbarch))
     {
-      b->enable_state = bp_enabled;
-      update_global_location_list ();
+      create_longjmp_breakpoint ("longjmp");
+      create_longjmp_breakpoint ("_longjmp");
+      create_longjmp_breakpoint ("siglongjmp");
+      create_longjmp_breakpoint ("_siglongjmp");
     }
 }
 
+/* Delete all longjmp breakpoints from THREAD.  */
 void
-disable_longjmp_breakpoint (void)
+delete_longjmp_breakpoint (int thread)
 {
-  struct breakpoint *b;
+  struct breakpoint *b, *temp;
 
-  ALL_BREAKPOINTS (b)
-    if (b->type == bp_longjmp
-       || b->type == bp_longjmp_resume)
-    {
-      b->enable_state = bp_disabled;
-      update_global_location_list ();
-    }
+  ALL_BREAKPOINTS_SAFE (b, temp)
+    if (b->type == bp_longjmp)
+      {
+       if (b->thread == thread)
+         delete_breakpoint (b);
+      }
 }
 
 static void
-create_overlay_event_breakpoint (char *func_name)
+create_overlay_event_breakpoint_1 (char *func_name, struct objfile *objfile)
 {
   struct breakpoint *b;
   struct minimal_symbol *m;
 
-  if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL)
+  if ((m = lookup_minimal_symbol_text (func_name, objfile)) == NULL)
     return;
  
   b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m), 
@@ -4524,7 +4276,15 @@ create_overlay_event_breakpoint (char *func_name)
       b->enable_state = bp_disabled;
       overlay_events_enabled = 0;
     }
-  update_global_location_list ();
+  update_global_location_list (1);
+}
+
+static void
+create_overlay_event_breakpoint (char *func_name)
+{
+  struct objfile *objfile;
+  ALL_OBJFILES (objfile)
+    create_overlay_event_breakpoint_1 (func_name, objfile);
 }
 
 void
@@ -4536,7 +4296,7 @@ enable_overlay_breakpoints (void)
     if (b->type == bp_overlay_event)
     {
       b->enable_state = bp_enabled;
-      update_global_location_list ();
+      update_global_location_list (1);
       overlay_events_enabled = 1;
     }
 }
@@ -4550,7 +4310,7 @@ disable_overlay_breakpoints (void)
     if (b->type == bp_overlay_event)
     {
       b->enable_state = bp_disabled;
-      update_global_location_list ();
+      update_global_location_list (0);
       overlay_events_enabled = 0;
     }
 }
@@ -4566,7 +4326,7 @@ create_thread_event_breakpoint (CORE_ADDR address)
   /* addr_string has to be used or breakpoint_re_set will delete me.  */
   b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address));
 
-  update_global_location_list_nothrow ();
+  update_global_location_list_nothrow (1);
 
   return b;
 }
@@ -4612,7 +4372,7 @@ create_solib_event_breakpoint (CORE_ADDR address)
   struct breakpoint *b;
 
   b = create_internal_breakpoint (address, bp_shlib_event);
-  update_global_location_list_nothrow ();
+  update_global_location_list_nothrow (1);
   return b;
 }
 
@@ -4687,73 +4447,286 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
   }
 }
 
+/* FORK & VFORK catchpoints.  */
+
+/* Implement the "insert" breakpoint_ops method for fork catchpoints.  */
+
 static void
-create_fork_vfork_event_catchpoint (int tempflag, char *cond_string,
-                                   enum bptype bp_kind)
+insert_catch_fork (struct breakpoint *b)
 {
-  struct symtab_and_line sal;
-  struct breakpoint *b;
-  int thread = -1;             /* All threads. */
+  target_insert_fork_catchpoint (PIDGET (inferior_ptid));
+}
 
-  init_sal (&sal);
-  sal.pc = 0;
-  sal.symtab = NULL;
-  sal.line = 0;
+/* Implement the "remove" breakpoint_ops method for fork catchpoints.  */
 
-  b = set_raw_breakpoint (sal, bp_kind);
-  set_breakpoint_count (breakpoint_count + 1);
-  b->number = breakpoint_count;
-  b->cond_string = (cond_string == NULL) ? 
-    NULL : savestring (cond_string, strlen (cond_string));
-  b->thread = thread;
-  b->addr_string = NULL;
-  b->enable_state = bp_enabled;
-  b->disposition = tempflag ? disp_del : disp_donttouch;
-  b->forked_inferior_pid = 0;
-  update_global_location_list ();
+static int
+remove_catch_fork (struct breakpoint *b)
+{
+  return target_remove_fork_catchpoint (PIDGET (inferior_ptid));
+}
 
+/* Implement the "breakpoint_hit" breakpoint_ops method for fork
+   catchpoints.  */
 
-  mention (b);
+static int
+breakpoint_hit_catch_fork (struct breakpoint *b)
+{
+  return inferior_has_forked (inferior_ptid, &b->forked_inferior_pid);
 }
 
+/* Implement the "print_it" breakpoint_ops method for fork catchpoints.  */
+
+static enum print_stop_action
+print_it_catch_fork (struct breakpoint *b)
+{
+  annotate_catchpoint (b->number);
+  printf_filtered (_("\nCatchpoint %d (forked process %d), "),
+                  b->number, ptid_get_pid (b->forked_inferior_pid));
+  return PRINT_SRC_AND_LOC;
+}
+
+/* Implement the "print_one" breakpoint_ops method for fork catchpoints.  */
+
 static void
-create_fork_event_catchpoint (int tempflag, char *cond_string)
+print_one_catch_fork (struct breakpoint *b, CORE_ADDR *last_addr)
 {
-  create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_fork);
+  struct value_print_options opts;
+
+  get_user_print_options (&opts);
+
+  /* Field 4, the address, is omitted (which makes the columns
+     not line up too nicely with the headers, but the effect
+     is relatively readable).  */
+  if (opts.addressprint)
+    ui_out_field_skip (uiout, "addr");
+  annotate_field (5);
+  ui_out_text (uiout, "fork");
+  if (!ptid_equal (b->forked_inferior_pid, null_ptid))
+    {
+      ui_out_text (uiout, ", process ");
+      ui_out_field_int (uiout, "what",
+                        ptid_get_pid (b->forked_inferior_pid));
+      ui_out_spaces (uiout, 1);
+    }
 }
 
+/* Implement the "print_mention" breakpoint_ops method for fork
+   catchpoints.  */
+
 static void
-create_vfork_event_catchpoint (int tempflag, char *cond_string)
+print_mention_catch_fork (struct breakpoint *b)
 {
-  create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_vfork);
+  printf_filtered (_("Catchpoint %d (fork)"), b->number);
 }
 
+/* The breakpoint_ops structure to be used in fork catchpoints.  */
+
+static struct breakpoint_ops catch_fork_breakpoint_ops =
+{
+  insert_catch_fork,
+  remove_catch_fork,
+  breakpoint_hit_catch_fork,
+  print_it_catch_fork,
+  print_one_catch_fork,
+  print_mention_catch_fork
+};
+
+/* Implement the "insert" breakpoint_ops method for vfork catchpoints.  */
+
 static void
-create_exec_event_catchpoint (int tempflag, char *cond_string)
+insert_catch_vfork (struct breakpoint *b)
+{
+  target_insert_vfork_catchpoint (PIDGET (inferior_ptid));
+}
+
+/* Implement the "remove" breakpoint_ops method for vfork catchpoints.  */
+
+static int
+remove_catch_vfork (struct breakpoint *b)
+{
+  return target_remove_vfork_catchpoint (PIDGET (inferior_ptid));
+}
+
+/* Implement the "breakpoint_hit" breakpoint_ops method for vfork
+   catchpoints.  */
+
+static int
+breakpoint_hit_catch_vfork (struct breakpoint *b)
+{
+  return inferior_has_vforked (inferior_ptid, &b->forked_inferior_pid);
+}
+
+/* Implement the "print_it" breakpoint_ops method for vfork catchpoints.  */
+
+static enum print_stop_action
+print_it_catch_vfork (struct breakpoint *b)
+{
+  annotate_catchpoint (b->number);
+  printf_filtered (_("\nCatchpoint %d (vforked process %d), "),
+                  b->number, ptid_get_pid (b->forked_inferior_pid));
+  return PRINT_SRC_AND_LOC;
+}
+
+/* Implement the "print_one" breakpoint_ops method for vfork catchpoints.  */
+
+static void
+print_one_catch_vfork (struct breakpoint *b, CORE_ADDR *last_addr)
+{
+  struct value_print_options opts;
+
+  get_user_print_options (&opts);
+  /* Field 4, the address, is omitted (which makes the columns
+     not line up too nicely with the headers, but the effect
+     is relatively readable).  */
+  if (opts.addressprint)
+    ui_out_field_skip (uiout, "addr");
+  annotate_field (5);
+  ui_out_text (uiout, "vfork");
+  if (!ptid_equal (b->forked_inferior_pid, null_ptid))
+    {
+      ui_out_text (uiout, ", process ");
+      ui_out_field_int (uiout, "what",
+                        ptid_get_pid (b->forked_inferior_pid));
+      ui_out_spaces (uiout, 1);
+    }
+}
+
+/* Implement the "print_mention" breakpoint_ops method for vfork
+   catchpoints.  */
+
+static void
+print_mention_catch_vfork (struct breakpoint *b)
+{
+  printf_filtered (_("Catchpoint %d (vfork)"), b->number);
+}
+
+/* The breakpoint_ops structure to be used in vfork catchpoints.  */
+
+static struct breakpoint_ops catch_vfork_breakpoint_ops =
+{
+  insert_catch_vfork,
+  remove_catch_vfork,
+  breakpoint_hit_catch_vfork,
+  print_it_catch_vfork,
+  print_one_catch_vfork,
+  print_mention_catch_vfork
+};
+
+/* Create a new breakpoint of the bp_catchpoint kind and return it.
+   If TEMPFLAG is non-zero, then make the breakpoint temporary.
+   If COND_STRING is not NULL, then store it in the breakpoint.
+   OPS, if not NULL, is the breakpoint_ops structure associated
+   to the catchpoint.  */
+
+static struct breakpoint *
+create_catchpoint (int tempflag, char *cond_string,
+                   struct breakpoint_ops *ops)
 {
   struct symtab_and_line sal;
   struct breakpoint *b;
-  int thread = -1;             /* All threads. */
 
   init_sal (&sal);
   sal.pc = 0;
   sal.symtab = NULL;
   sal.line = 0;
 
-  b = set_raw_breakpoint (sal, bp_catch_exec);
+  b = set_raw_breakpoint (sal, bp_catchpoint);
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
-  b->cond_string = (cond_string == NULL) ?
+
+  b->cond_string = (cond_string == NULL) ? 
     NULL : savestring (cond_string, strlen (cond_string));
-  b->thread = thread;
+  b->thread = -1;
   b->addr_string = NULL;
   b->enable_state = bp_enabled;
   b->disposition = tempflag ? disp_del : disp_donttouch;
-  update_global_location_list ();
+  b->ops = ops;
 
   mention (b);
+  update_global_location_list (1);
+
+  return b;
+}
+
+static void
+create_fork_vfork_event_catchpoint (int tempflag, char *cond_string,
+                                    struct breakpoint_ops *ops)
+{
+  struct breakpoint *b = create_catchpoint (tempflag, cond_string, ops);
+
+  /* FIXME: We should put this information in a breakpoint private data
+     area.  */
+  b->forked_inferior_pid = null_ptid;
+}
+
+/* Exec catchpoints.  */
+
+static void
+insert_catch_exec (struct breakpoint *b)
+{
+  target_insert_exec_catchpoint (PIDGET (inferior_ptid));
+}
+
+static int
+remove_catch_exec (struct breakpoint *b)
+{
+  return target_remove_exec_catchpoint (PIDGET (inferior_ptid));
+}
+
+static int
+breakpoint_hit_catch_exec (struct breakpoint *b)
+{
+  return inferior_has_execd (inferior_ptid, &b->exec_pathname);
 }
 
+static enum print_stop_action
+print_it_catch_exec (struct breakpoint *b)
+{
+  annotate_catchpoint (b->number);
+  printf_filtered (_("\nCatchpoint %d (exec'd %s), "), b->number,
+                  b->exec_pathname);
+  return PRINT_SRC_AND_LOC;
+}
+
+static void
+print_one_catch_exec (struct breakpoint *b, CORE_ADDR *last_addr)
+{
+  struct value_print_options opts;
+
+  get_user_print_options (&opts);
+
+  /* Field 4, the address, is omitted (which makes the columns
+     not line up too nicely with the headers, but the effect
+     is relatively readable).  */
+  if (opts.addressprint)
+    ui_out_field_skip (uiout, "addr");
+  annotate_field (5);
+  ui_out_text (uiout, "exec");
+  if (b->exec_pathname != NULL)
+    {
+      ui_out_text (uiout, ", program \"");
+      ui_out_field_string (uiout, "what", b->exec_pathname);
+      ui_out_text (uiout, "\" ");
+    }
+}
+
+static void
+print_mention_catch_exec (struct breakpoint *b)
+{
+  printf_filtered (_("Catchpoint %d (exec)"), b->number);
+}
+
+static struct breakpoint_ops catch_exec_breakpoint_ops =
+{
+  insert_catch_exec,
+  remove_catch_exec,
+  breakpoint_hit_catch_exec,
+  print_it_catch_exec,
+  print_one_catch_exec,
+  print_mention_catch_exec
+};
+
 static int
 hw_breakpoint_used_count (void)
 {
@@ -4762,7 +4735,7 @@ hw_breakpoint_used_count (void)
 
   ALL_BREAKPOINTS (b)
   {
-    if (b->type == bp_hardware_breakpoint && b->enable_state == bp_enabled)
+    if (b->type == bp_hardware_breakpoint && breakpoint_enabled (b))
       i++;
   }
 
@@ -4791,30 +4764,6 @@ hw_watchpoint_used_count (enum bptype type, int *other_type_used)
   return i;
 }
 
-/* Call this after hitting the longjmp() breakpoint.  Use this to set
-   a new breakpoint at the target of the jmp_buf.
-
-   FIXME - This ought to be done by setting a temporary breakpoint
-   that gets deleted automatically... */
-
-void
-set_longjmp_resume_breakpoint (CORE_ADDR pc, struct frame_id frame_id)
-{
-  struct breakpoint *b;
-
-  ALL_BREAKPOINTS (b)
-    if (b->type == bp_longjmp_resume)
-    {
-      b->loc->requested_address = pc;
-      b->loc->address = adjust_breakpoint_address (b->loc->requested_address,
-                                                   b->type);
-      b->enable_state = bp_enabled;
-      b->frame_id = frame_id;
-      update_global_location_list ();
-      return;
-    }
-}
-
 void
 disable_watchpoints_before_interactive_call_start (void)
 {
@@ -4829,7 +4778,7 @@ disable_watchpoints_before_interactive_call_start (void)
        && breakpoint_enabled (b))
       {
        b->enable_state = bp_call_disabled;
-       update_global_location_list ();
+       update_global_location_list (0);
       }
   }
 }
@@ -4848,7 +4797,7 @@ enable_watchpoints_after_interactive_call_stop (void)
        && (b->enable_state == bp_call_disabled))
       {
        b->enable_state = bp_enabled;
-       update_global_location_list ();
+       update_global_location_list (1);
       }
   }
 }
@@ -4874,10 +4823,23 @@ set_momentary_breakpoint (struct symtab_and_line sal, struct frame_id frame_id,
   if (in_thread_list (inferior_ptid))
     b->thread = pid_to_thread_id (inferior_ptid);
 
-  update_global_location_list_nothrow ();
+  update_global_location_list_nothrow (1);
 
   return b;
 }
+
+struct breakpoint *
+set_momentary_breakpoint_at_pc (CORE_ADDR pc, enum bptype type)
+{
+  struct symtab_and_line sal;
+
+  sal = find_pc_line (pc, 0);
+  sal.pc = pc;
+  sal.section = find_pc_overlay (pc);
+  sal.explicit_pc = 1;
+
+  return set_momentary_breakpoint (sal, null_frame_id, type);
+}
 \f
 
 /* Tell the user we have just set a breakpoint B.  */
@@ -4888,6 +4850,9 @@ mention (struct breakpoint *b)
   int say_where = 0;
   struct cleanup *old_chain, *ui_out_chain;
   struct ui_stream *stb;
+  struct value_print_options opts;
+
+  get_user_print_options (&opts);
 
   stb = ui_out_stream_new (uiout);
   old_chain = make_cleanup_ui_out_stream_delete (stb);
@@ -4895,11 +4860,8 @@ mention (struct breakpoint *b)
   /* FIXME: This is misplaced; mention() is called by things (like
      hitting a watchpoint) other than breakpoint creation.  It should
      be possible to clean this up and at the same time replace the
-     random calls to breakpoint_changed with this hook, as has already
-     been done for deprecated_delete_breakpoint_hook and so on.  */
-  if (deprecated_create_breakpoint_hook)
-    deprecated_create_breakpoint_hook (b);
-  breakpoint_create_event (b->number);
+     random calls to breakpoint_changed with this hook.  */
+  observer_notify_breakpoint_created (b->number);
 
   if (b->ops != NULL && b->ops->print_mention != NULL)
     b->ops->print_mention (b);
@@ -4967,24 +4929,6 @@ mention (struct breakpoint *b)
        printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
        say_where = 1;
        break;
-      case bp_catch_load:
-      case bp_catch_unload:
-       printf_filtered (_("Catchpoint %d (%s %s)"),
-                        b->number,
-                        (b->type == bp_catch_load) ? "load" : "unload",
-                        (b->dll_pathname != NULL) ? 
-                        b->dll_pathname : "<any library>");
-       break;
-      case bp_catch_fork:
-      case bp_catch_vfork:
-       printf_filtered (_("Catchpoint %d (%s)"),
-                        b->number,
-                        (b->type == bp_catch_fork) ? "fork" : "vfork");
-       break;
-      case bp_catch_exec:
-       printf_filtered (_("Catchpoint %d (exec)"),
-                        b->number);
-       break;
 
       case bp_until:
       case bp_finish:
@@ -5009,7 +4953,7 @@ mention (struct breakpoint *b)
        }
       else
        {
-         if (addressprint || b->source_file == NULL)
+         if (opts.addressprint || b->source_file == NULL)
            {
              printf_filtered (" at ");
              fputs_filtered (paddress (b->loc->address), gdb_stdout);
@@ -5054,6 +4998,47 @@ add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype,
   set_breakpoint_location_function (loc);
   return loc;
 }
+\f
+
+/* Return 1 if LOC is pointing to a permanent breakpoint, 
+   return 0 otherwise.  */
+
+static int
+bp_loc_is_permanent (struct bp_location *loc)
+{
+  int len;
+  CORE_ADDR addr;
+  const gdb_byte *brk;
+  gdb_byte *target_mem;
+  struct cleanup *cleanup;
+  int retval = 0;
+
+  gdb_assert (loc != NULL);
+
+  addr = loc->address;
+  brk = gdbarch_breakpoint_from_pc (current_gdbarch, &addr, &len);
+
+  /* Software breakpoints unsupported?  */
+  if (brk == NULL)
+    return 0;
+
+  target_mem = alloca (len);
+
+  /* Enable the automatic memory restoration from breakpoints while
+     we read the memory.  Otherwise we could say about our temporary
+     breakpoints they are permanent.  */
+  cleanup = make_show_memory_breakpoints_cleanup (0);
+
+  if (target_read_memory (loc->address, target_mem, len) == 0
+      && memcmp (target_mem, brk, len) == 0)
+    retval = 1;
+
+  do_cleanups (cleanup);
+
+  return retval;
+}
+
+
 
 /* Create a breakpoint with SAL as location.  Use ADDR_STRING
    as textual description of the location, and COND_STRING
@@ -5108,6 +5093,9 @@ create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
          loc = add_location_to_breakpoint (b, type, &sal);
        }
 
+      if (bp_loc_is_permanent (loc))
+       make_breakpoint_permanent (b);
+
       if (b->cond_string)
        {
          char *arg = b->cond_string;
@@ -5283,7 +5271,7 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
                         thread, ignore_count, ops, from_tty);
     }
 
-  update_global_location_list ();
+  update_global_location_list (1);
 }
 
 /* Parse ARG which is assumed to be a SAL specification possibly
@@ -5604,7 +5592,7 @@ break_command_really (char *arg, char *cond_string, int thread,
       b->condition_not_parsed = 1;
       b->ops = ops;
 
-      update_global_location_list ();
+      update_global_location_list (1);
       mention (b);
     }
   
@@ -5705,11 +5693,11 @@ resolve_sal_pc (struct symtab_and_line *sal)
       bv = blockvector_for_pc_sect (sal->pc, 0, &b, sal->symtab);
       if (bv != NULL)
        {
-         sym = block_function (b);
+         sym = block_linkage_function (b);
          if (sym != NULL)
            {
              fixup_symbol_section (sym, sal->symtab->objfile);
-             sal->section = SYMBOL_BFD_SECTION (sym);
+             sal->section = SYMBOL_OBJ_SECTION (sym);
            }
          else
            {
@@ -5722,7 +5710,7 @@ resolve_sal_pc (struct symtab_and_line *sal)
 
              msym = lookup_minimal_symbol_by_pc (sal->pc);
              if (msym)
-               sal->section = SYMBOL_BFD_SECTION (msym);
+               sal->section = SYMBOL_OBJ_SECTION (msym);
            }
        }
     }
@@ -6033,7 +6021,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
 
   value_free_to_mark (mark);
   mention (b);
-  update_global_location_list ();
+  update_global_location_list (1);
 }
 
 /* Return count of locations need to be watched and can be handled
@@ -6153,16 +6141,24 @@ awatch_command (char *arg, int from_tty)
 /* Helper routines for the until_command routine in infcmd.c.  Here
    because it uses the mechanisms of breakpoints.  */
 
+struct until_break_command_continuation_args
+{
+  struct breakpoint *breakpoint;
+  struct breakpoint *breakpoint2;
+};
+
 /* This function is called by fetch_inferior_event via the
    cmd_continuation pointer, to complete the until command. It takes
    care of cleaning up the temporary breakpoints set up by the until
    command. */
 static void
-until_break_command_continuation (struct continuation_arg *arg, int error)
+until_break_command_continuation (void *arg)
 {
-  delete_breakpoint ((struct breakpoint *)(arg->data.pointer));
-  if (arg->next)
-    delete_breakpoint ((struct breakpoint *)(arg->next->data.pointer));
+  struct until_break_command_continuation_args *a = arg;
+
+  delete_breakpoint (a->breakpoint);
+  if (a->breakpoint2)
+    delete_breakpoint (a->breakpoint2);
 }
 
 void
@@ -6175,9 +6171,6 @@ until_break_command (char *arg, int from_tty, int anywhere)
   struct breakpoint *breakpoint;
   struct breakpoint *breakpoint2 = NULL;
   struct cleanup *old_chain;
-  struct continuation_arg *arg1;
-  struct continuation_arg *arg2;
-
 
   clear_proceed_status ();
 
@@ -6232,24 +6225,18 @@ until_break_command (char *arg, int from_tty, int anywhere)
      deleted when the target stops.  Otherwise, we're already stopped and
      delete breakpoints via cleanup chain.  */
 
-  if (target_can_async_p () && target_executing)
+  if (target_can_async_p () && is_running (inferior_ptid))
     {
-      arg1 =
-       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
-      arg1->next         = NULL;
-      arg1->data.pointer = breakpoint;
+      struct until_break_command_continuation_args *args;
+      args = xmalloc (sizeof (*args));
 
-      if (breakpoint2)
-       {
-         arg2 = (struct continuation_arg *)
-           xmalloc ( sizeof (struct continuation_arg));
-         arg2->next         = NULL;
-         arg2->data.pointer = breakpoint2;
-         arg1->next = arg2;       
-       }
+      args->breakpoint = breakpoint;
+      args->breakpoint2 = breakpoint2;
 
       discard_cleanups (old_chain);
-      add_continuation (until_break_command_continuation, arg1);
+      add_continuation (inferior_thread (),
+                       until_break_command_continuation, args,
+                       xfree);
     }
   else
     do_cleanups (old_chain);
@@ -6264,36 +6251,6 @@ ep_skip_leading_whitespace (char **s)
     *s += 1;
 }
 
-/* This function examines a string, and attempts to find a token
-   that might be an event name in the leading characters.  If a
-   possible match is found, a pointer to the last character of
-   the token is returned.  Else, NULL is returned. */
-
-static char *
-ep_find_event_name_end (char *arg)
-{
-  char *s = arg;
-  char *event_name_end = NULL;
-
-  /* If we could depend upon the presense of strrpbrk, we'd use that... */
-  if (arg == NULL)
-    return NULL;
-
-  /* We break out of the loop when we find a token delimiter.
-     Basically, we're looking for alphanumerics and underscores;
-     anything else delimites the token. */
-  while (*s != '\0')
-    {
-      if (!isalnum (*s) && (*s != '_'))
-       break;
-      event_name_end = s;
-      s++;
-    }
-
-  return event_name_end;
-}
-
-
 /* This function attempts to parse an optional "if <cond>" clause
    from the arg string.  If one is not found, it returns NULL.
 
@@ -6365,16 +6322,24 @@ ep_parse_optional_filename (char **arg)
 
 typedef enum
 {
-  catch_fork, catch_vfork
+  catch_fork_temporary, catch_vfork_temporary,
+  catch_fork_permanent, catch_vfork_permanent
 }
 catch_fork_kind;
 
 static void
-catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
-                     int from_tty)
+catch_fork_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
 {
   char *cond_string = NULL;
+  catch_fork_kind fork_kind;
+  int tempflag;
+
+  fork_kind = (catch_fork_kind) (uintptr_t) get_cmd_context (command);
+  tempflag = (fork_kind == catch_fork_temporary
+             || fork_kind == catch_vfork_temporary);
 
+  if (!arg)
+    arg = "";
   ep_skip_leading_whitespace (&arg);
 
   /* The allowed syntax is:
@@ -6391,11 +6356,15 @@ catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
      and enable reporting of such events. */
   switch (fork_kind)
     {
-    case catch_fork:
-      create_fork_event_catchpoint (tempflag, cond_string);
+    case catch_fork_temporary:
+    case catch_fork_permanent:
+      create_fork_vfork_event_catchpoint (tempflag, cond_string,
+                                          &catch_fork_breakpoint_ops);
       break;
-    case catch_vfork:
-      create_vfork_event_catchpoint (tempflag, cond_string);
+    case catch_vfork_temporary:
+    case catch_vfork_permanent:
+      create_fork_vfork_event_catchpoint (tempflag, cond_string,
+                                          &catch_vfork_breakpoint_ops);
       break;
     default:
       error (_("unsupported or unknown fork kind; cannot catch it"));
@@ -6404,10 +6373,15 @@ catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
 }
 
 static void
-catch_exec_command_1 (char *arg, int tempflag, int from_tty)
+catch_exec_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
 {
+  int tempflag;
   char *cond_string = NULL;
 
+  tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+  if (!arg)
+    arg = "";
   ep_skip_leading_whitespace (&arg);
 
   /* The allowed syntax is:
@@ -6422,112 +6396,46 @@ catch_exec_command_1 (char *arg, int tempflag, int from_tty)
 
   /* If this target supports it, create an exec catchpoint
      and enable reporting of such events. */
-  create_exec_event_catchpoint (tempflag, cond_string);
-}
-
-static void
-catch_load_command_1 (char *arg, int tempflag, int from_tty)
-{
-  char *dll_pathname = NULL;
-  char *cond_string = NULL;
-
-  ep_skip_leading_whitespace (&arg);
-
-  /* The allowed syntax is:
-     catch load
-     catch load if <cond>
-     catch load <filename>
-     catch load <filename> if <cond>
-
-     The user is not allowed to specify the <filename> after an
-     if clause.
-
-     We'll ignore the pathological case of a file named "if".
-
-     First, check if there's an if clause.  If so, then there
-     cannot be a filename. */
-  cond_string = ep_parse_optional_if_clause (&arg);
-
-  /* If there was an if clause, then there cannot be a filename.
-     Else, there might be a filename and an if clause. */
-  if (cond_string == NULL)
-    {
-      dll_pathname = ep_parse_optional_filename (&arg);
-      ep_skip_leading_whitespace (&arg);
-      cond_string = ep_parse_optional_if_clause (&arg);
-    }
-
-  if ((*arg != '\0') && !isspace (*arg))
-    error (_("Junk at end of arguments."));
-
-  /* Create a load breakpoint that only triggers when a load of
-     the specified dll (or any dll, if no pathname was specified)
-     occurs. */
-  SOLIB_CREATE_CATCH_LOAD_HOOK (PIDGET (inferior_ptid), tempflag, 
-                               dll_pathname, cond_string);
-}
-
-static void
-catch_unload_command_1 (char *arg, int tempflag, int from_tty)
-{
-  char *dll_pathname = NULL;
-  char *cond_string = NULL;
-
-  ep_skip_leading_whitespace (&arg);
-
-  /* The allowed syntax is:
-     catch unload
-     catch unload if <cond>
-     catch unload <filename>
-     catch unload <filename> if <cond>
-
-     The user is not allowed to specify the <filename> after an
-     if clause.
-
-     We'll ignore the pathological case of a file named "if".
-
-     First, check if there's an if clause.  If so, then there
-     cannot be a filename. */
-  cond_string = ep_parse_optional_if_clause (&arg);
-
-  /* If there was an if clause, then there cannot be a filename.
-     Else, there might be a filename and an if clause. */
-  if (cond_string == NULL)
-    {
-      dll_pathname = ep_parse_optional_filename (&arg);
-      ep_skip_leading_whitespace (&arg);
-      cond_string = ep_parse_optional_if_clause (&arg);
-    }
-
-  if ((*arg != '\0') && !isspace (*arg))
-    error (_("Junk at end of arguments."));
-
-  /* Create an unload breakpoint that only triggers when an unload of
-     the specified dll (or any dll, if no pathname was specified)
-     occurs. */
-  SOLIB_CREATE_CATCH_UNLOAD_HOOK (PIDGET (inferior_ptid), tempflag, 
-                                 dll_pathname, cond_string);
+  create_catchpoint (tempflag, cond_string, &catch_exec_breakpoint_ops);
 }
 
 static enum print_stop_action
 print_exception_catchpoint (struct breakpoint *b)
 {
-  annotate_catchpoint (b->number);
+  int bp_temp, bp_throw;
 
-  if (strstr (b->addr_string, "throw") != NULL)
-    printf_filtered (_("\nCatchpoint %d (exception thrown)\n"),
-                    b->number);
-  else
-    printf_filtered (_("\nCatchpoint %d (exception caught)\n"),
-                    b->number);
+  annotate_catchpoint (b->number);
 
+  bp_throw = strstr (b->addr_string, "throw") != NULL;
+  if (b->loc->address != b->loc->requested_address)
+    breakpoint_adjustment_warning (b->loc->requested_address,
+                                  b->loc->address,
+                                  b->number, 1);
+  bp_temp = b->loc->owner->disposition == disp_del;
+  ui_out_text (uiout, 
+              bp_temp ? "Temporary catchpoint "
+                      : "Catchpoint ");
+  if (!ui_out_is_mi_like_p (uiout))
+    ui_out_field_int (uiout, "bkptno", b->number);
+  ui_out_text (uiout,
+              bp_throw ? " (exception thrown), "
+                       : " (exception caught), ");
+  if (ui_out_is_mi_like_p (uiout))
+    {
+      ui_out_field_string (uiout, "reason", 
+                          async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
+      ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+      ui_out_field_int (uiout, "bkptno", b->number);
+    }
   return PRINT_SRC_AND_LOC;
 }
 
 static void
 print_one_exception_catchpoint (struct breakpoint *b, CORE_ADDR *last_addr)
 {
-  if (addressprint)
+  struct value_print_options opts;
+  get_user_print_options (&opts);
+  if (opts.addressprint)
     {
       annotate_field (4);
       if (b->loc == NULL || b->loc->shlib_disabled)
@@ -6547,13 +6455,22 @@ print_one_exception_catchpoint (struct breakpoint *b, CORE_ADDR *last_addr)
 static void
 print_mention_exception_catchpoint (struct breakpoint *b)
 {
-  if (strstr (b->addr_string, "throw") != NULL)
-    printf_filtered (_("Catchpoint %d (throw)"), b->number);
-  else
-    printf_filtered (_("Catchpoint %d (catch)"), b->number);
+  int bp_temp;
+  int bp_throw;
+
+  bp_temp = b->loc->owner->disposition == disp_del;
+  bp_throw = strstr (b->addr_string, "throw") != NULL;
+  ui_out_text (uiout, bp_temp ? _("Temporary catchpoint ")
+                             : _("Catchpoint "));
+  ui_out_field_int (uiout, "bkptno", b->number);
+  ui_out_text (uiout, bp_throw ? _(" (throw)")
+                              : _(" (catch)"));
 }
 
 static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = {
+  NULL, /* insert */
+  NULL, /* remove */
+  NULL, /* breakpoint_hit */
   print_exception_catchpoint,
   print_one_exception_catchpoint,
   print_mention_exception_catchpoint
@@ -6572,7 +6489,7 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
 
   break_command_really (trigger_func_name, cond_string, -1,
                        0 /* condition and thread are valid.  */,
-                       0, 0,
+                       tempflag, 0,
                        0,
                        AUTO_BOOLEAN_TRUE /* pending */,
                        &gnu_v3_exception_catchpoint_ops, from_tty);
@@ -6589,6 +6506,8 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
   char *cond_string = NULL;
   struct symtab_and_line *sal = NULL;
 
+  if (!arg)
+    arg = "";
   ep_skip_leading_whitespace (&arg);
 
   cond_string = ep_parse_optional_if_clause (&arg);
@@ -6606,6 +6525,24 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
   warning (_("Unsupported with this platform/compiler combination."));
 }
 
+/* Implementation of "catch catch" command.  */
+
+static void
+catch_catch_command (char *arg, int from_tty, struct cmd_list_element *command)
+{
+  int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+  catch_exception_command_1 (EX_EVENT_CATCH, arg, tempflag, from_tty);
+}
+
+/* Implementation of "catch throw" command.  */
+
+static void
+catch_throw_command (char *arg, int from_tty, struct cmd_list_element *command)
+{
+  int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+  catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
+}
+
 /* Create a breakpoint struct for Ada exception catchpoints.  */
 
 static void
@@ -6649,14 +6586,16 @@ create_ada_exception_breakpoint (struct symtab_and_line sal,
   b->ops = ops;
 
   mention (b);
-  update_global_location_list ();
+  update_global_location_list (1);
 }
 
 /* Implement the "catch exception" command.  */
 
 static void
-catch_ada_exception_command (char *arg, int tempflag, int from_tty)
+catch_ada_exception_command (char *arg, int from_tty,
+                            struct cmd_list_element *command)
 {
+  int tempflag;
   struct symtab_and_line sal;
   enum bptype type;
   char *addr_string = NULL;
@@ -6665,6 +6604,10 @@ catch_ada_exception_command (char *arg, int tempflag, int from_tty)
   struct expression *cond = NULL;
   struct breakpoint_ops *ops = NULL;
 
+  tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+  if (!arg)
+    arg = "";
   sal = ada_decode_exception_location (arg, &addr_string, &exp_string,
                                        &cond_string, &cond, &ops);
   create_ada_exception_breakpoint (sal, addr_string, exp_string,
@@ -6675,138 +6618,33 @@ catch_ada_exception_command (char *arg, int tempflag, int from_tty)
 /* Implement the "catch assert" command.  */
 
 static void
-catch_assert_command (char *arg, int tempflag, int from_tty)
+catch_assert_command (char *arg, int from_tty, struct cmd_list_element *command)
 {
+  int tempflag;
   struct symtab_and_line sal;
   char *addr_string = NULL;
   struct breakpoint_ops *ops = NULL;
 
+  tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+  if (!arg)
+    arg = "";
   sal = ada_decode_assert_location (arg, &addr_string, &ops);
   create_ada_exception_breakpoint (sal, addr_string, NULL, NULL, NULL, ops,
                                    tempflag, from_tty);
 }
 
-static void
-catch_command_1 (char *arg, int tempflag, int from_tty)
-{
-
-  /* The first argument may be an event name, such as "start" or "load".
-     If so, then handle it as such.  If it doesn't match an event name,
-     then attempt to interpret it as an exception name.  (This latter is
-     the v4.16-and-earlier GDB meaning of the "catch" command.)
-
-     First, try to find the bounds of what might be an event name. */
-  char *arg1_start = arg;
-  char *arg1_end;
-  int arg1_length;
-
-  if (arg1_start == NULL)
-    {
-      /* Old behaviour was to use pre-v-4.16 syntax */
-      /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
-      /* return; */
-      /* Now, this is not allowed */
-      error (_("Catch requires an event name."));
-
-    }
-  arg1_end = ep_find_event_name_end (arg1_start);
-  if (arg1_end == NULL)
-    error (_("catch requires an event"));
-  arg1_length = arg1_end + 1 - arg1_start;
-
-  /* Try to match what we found against known event names. */
-  if (strncmp (arg1_start, "signal", arg1_length) == 0)
-    {
-      error (_("Catch of signal not yet implemented"));
-    }
-  else if (strncmp (arg1_start, "catch", arg1_length) == 0)
-    {
-      catch_exception_command_1 (EX_EVENT_CATCH, arg1_end + 1, 
-                                tempflag, from_tty);
-    }
-  else if (strncmp (arg1_start, "throw", arg1_length) == 0)
-    {
-      catch_exception_command_1 (EX_EVENT_THROW, arg1_end + 1, 
-                                tempflag, from_tty);
-    }
-  else if (strncmp (arg1_start, "thread_start", arg1_length) == 0)
-    {
-      error (_("Catch of thread_start not yet implemented"));
-    }
-  else if (strncmp (arg1_start, "thread_exit", arg1_length) == 0)
-    {
-      error (_("Catch of thread_exit not yet implemented"));
-    }
-  else if (strncmp (arg1_start, "thread_join", arg1_length) == 0)
-    {
-      error (_("Catch of thread_join not yet implemented"));
-    }
-  else if (strncmp (arg1_start, "start", arg1_length) == 0)
-    {
-      error (_("Catch of start not yet implemented"));
-    }
-  else if (strncmp (arg1_start, "exit", arg1_length) == 0)
-    {
-      error (_("Catch of exit not yet implemented"));
-    }
-  else if (strncmp (arg1_start, "fork", arg1_length) == 0)
-    {
-      catch_fork_command_1 (catch_fork, arg1_end + 1, tempflag, from_tty);
-    }
-  else if (strncmp (arg1_start, "vfork", arg1_length) == 0)
-    {
-      catch_fork_command_1 (catch_vfork, arg1_end + 1, tempflag, from_tty);
-    }
-  else if (strncmp (arg1_start, "exec", arg1_length) == 0)
-    {
-      catch_exec_command_1 (arg1_end + 1, tempflag, from_tty);
-    }
-  else if (strncmp (arg1_start, "load", arg1_length) == 0)
-    {
-      catch_load_command_1 (arg1_end + 1, tempflag, from_tty);
-    }
-  else if (strncmp (arg1_start, "unload", arg1_length) == 0)
-    {
-      catch_unload_command_1 (arg1_end + 1, tempflag, from_tty);
-    }
-  else if (strncmp (arg1_start, "stop", arg1_length) == 0)
-    {
-      error (_("Catch of stop not yet implemented"));
-    }
-  else if (strncmp (arg1_start, "exception", arg1_length) == 0)
-    {
-      catch_ada_exception_command (arg1_end + 1, tempflag, from_tty);
-    }
-
-  else if (strncmp (arg1_start, "assert", arg1_length) == 0)
-    {
-      catch_assert_command (arg1_end + 1, tempflag, from_tty);
-    }
-
-  /* This doesn't appear to be an event name */
-
-  else
-    {
-      /* Pre-v.4.16 behaviour was to treat the argument
-         as the name of an exception */
-      /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
-      /* Now this is not allowed */
-      error (_("Unknown event kind specified for catch"));
-
-    }
-}
-
 static void
 catch_command (char *arg, int from_tty)
 {
-  catch_command_1 (arg, 0, from_tty);
+  error (_("Catch requires an event name."));
 }
 \f
 
 static void
 tcatch_command (char *arg, int from_tty)
 {
-  catch_command_1 (arg, 1, from_tty);
+  error (_("Catch requires an event name."));
 }
 
 /* Delete breakpoints by address or line.  */
@@ -6960,7 +6798,9 @@ breakpoint_auto_delete (bpstat bs)
   struct breakpoint *b, *temp;
 
   for (; bs; bs = bs->next)
-    if (bs->breakpoint_at && bs->breakpoint_at->owner->disposition == disp_del
+    if (bs->breakpoint_at 
+       && bs->breakpoint_at->owner
+       && bs->breakpoint_at->owner->disposition == disp_del
        && bs->stop)
       delete_breakpoint (bs->breakpoint_at->owner);
 
@@ -6971,8 +6811,23 @@ breakpoint_auto_delete (bpstat bs)
   }
 }
 
+/* If SHOULD_INSERT is true, do not insert any breakpoint locations
+   into the inferior, only remove already-inserted locations that no
+   longer should be inserted.  Functions that delete a breakpoint or
+   breakpoints should pass false, so that deleting a breakpoint
+   doesn't have the side effect of inserting the locations of other
+   breakpoints that are marked not-inserted, but should_be_inserted
+   returns true on them.
+
+   This behaviour is useful is situations close to tear-down -- e.g.,
+   after an exec, while the target still has execution, but breakpoint
+   shadows of the previous executable image should *NOT* be restored
+   to the new image; or before detaching, where the target still has
+   execution and wants to delete breakpoints from GDB's lists, and all
+   breakpoints had already been removed from the inferior.  */
+
 static void
-update_global_location_list (void)
+update_global_location_list (int should_insert)
 {
   struct breakpoint *b;
   struct bp_location **next = &bp_location_chain;
@@ -7008,6 +6863,9 @@ update_global_location_list (void)
       /* Tells if 'loc' is found amoung the new locations.  If not, we
         have to free it.  */
       int found_object = 0;
+      /* Tells if the location should remain inserted in the target.  */
+      int keep_in_target = 0;
+      int removed = 0;
       for (loc2 = bp_location_chain; loc2; loc2 = loc2->global_next)
        if (loc2 == loc)
          {
@@ -7024,13 +6882,12 @@ update_global_location_list (void)
       if (loc->inserted)
        {
          /* If the location is inserted now, we might have to remove it.  */
-         int keep = 0;
 
          if (found_object && should_be_inserted (loc))
            {
              /* The location is still present in the location list, and still
                 should be inserted.  Don't do anything.  */
-             keep = 1;
+             keep_in_target = 1;
            }
          else
            {
@@ -7048,47 +6905,113 @@ update_global_location_list (void)
                      {           
                        loc2->inserted = 1;
                        loc2->target_info = loc->target_info;
-                       keep = 1;
+                       keep_in_target = 1;
                        break;
                      }
                  }
            }
 
-         if (!keep)
-           if (remove_breakpoint (loc, mark_uninserted))
-             {
-               /* This is just about all we can do.  We could keep this
-                  location on the global list, and try to remove it next
-                  time, but there's no particular reason why we will
-                  succeed next time.  
-
-                  Note that at this point, loc->owner is still valid,
-                  as delete_breakpoint frees the breakpoint only
-                  after calling us.  */
-               printf_filtered (_("warning: Error removing breakpoint %d\n"), 
-                                loc->owner->number);
-             }
+         if (!keep_in_target)
+           {
+             if (remove_breakpoint (loc, mark_uninserted))
+               {
+                 /* This is just about all we can do.  We could keep this
+                    location on the global list, and try to remove it next
+                    time, but there's no particular reason why we will
+                    succeed next time.  
+                    
+                    Note that at this point, loc->owner is still valid,
+                    as delete_breakpoint frees the breakpoint only
+                    after calling us.  */
+                 printf_filtered (_("warning: Error removing breakpoint %d\n"), 
+                                  loc->owner->number);
+               }
+             removed = 1;
+           }
        }
 
       if (!found_object)
-       free_bp_location (loc);
+       {
+         if (removed && non_stop)
+           {
+             /* This location was removed from the targets.  In non-stop mode,
+                a race condition is possible where we've removed a breakpoint,
+                but stop events for that breakpoint are already queued and will
+                arrive later.  To suppress spurious SIGTRAPs reported to user,
+                we keep this breakpoint location for a bit, and will retire it
+                after we see 3 * thread_count events.
+                The theory here is that reporting of events should,
+                "on the average", be fair, so after that many event we'll see
+                events from all threads that have anything of interest, and no
+                longer need to keep this breakpoint.  This is just a
+                heuristic, but if it's wrong, we'll report unexpected SIGTRAP,
+                which is usability issue, but not a correctness problem.  */
+             loc->events_till_retirement = 3 * (thread_count () + 1);
+             loc->owner = NULL;
+
+             VEC_safe_push (bp_location_p, moribund_locations, loc);
+           }
+         else
+           free_bp_location (loc);
+       }
     }
-    
+
   ALL_BREAKPOINTS (b)
     {
       check_duplicates (b);
     }
 
-  if (always_inserted_mode && target_has_execution)
+  if (breakpoints_always_inserted_mode () && should_insert
+      && (target_has_execution
+         || (gdbarch_has_global_solist (target_gdbarch)
+             && target_supports_multi_process ())))
     insert_breakpoint_locations ();
 }
 
+void
+breakpoint_retire_moribund (void)
+{
+  struct bp_location *loc;
+  int ix;
+
+  for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
+    if (--(loc->events_till_retirement) == 0)
+      {
+       free_bp_location (loc);
+       VEC_unordered_remove (bp_location_p, moribund_locations, ix);
+       --ix;
+      }
+}
+
 static void
-update_global_location_list_nothrow (void)
+update_global_location_list_nothrow (int inserting)
 {
   struct gdb_exception e;
   TRY_CATCH (e, RETURN_MASK_ERROR)
-    update_global_location_list ();
+    update_global_location_list (inserting);
+}
+
+/* Clear BPT from a BPS.  */
+static void
+bpstat_remove_breakpoint (bpstat bps, struct breakpoint *bpt)
+{
+  bpstat bs;
+  for (bs = bps; bs; bs = bs->next)
+    if (bs->breakpoint_at && bs->breakpoint_at->owner == bpt)
+      {
+       bs->breakpoint_at = NULL;
+       bs->old_val = NULL;
+       /* bs->commands will be freed later.  */
+      }
+}
+
+/* Callback for iterate_over_threads.  */
+static int
+bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
+{
+  struct breakpoint *bpt = data;
+  bpstat_remove_breakpoint (th->stop_bpstat, bpt);
+  return 0;
 }
 
 /* Delete a breakpoint and clean up all traces of it in the data
@@ -7098,7 +7021,6 @@ void
 delete_breakpoint (struct breakpoint *bpt)
 {
   struct breakpoint *b;
-  bpstat bs;
   struct bp_location *loc, *next;
 
   gdb_assert (bpt != NULL);
@@ -7119,9 +7041,7 @@ delete_breakpoint (struct breakpoint *bpt)
   if (bpt->type == bp_none)
     return;
 
-  if (deprecated_delete_breakpoint_hook)
-    deprecated_delete_breakpoint_hook (bpt);
-  breakpoint_delete_event (bpt->number);
+  observer_notify_breakpoint_deleted (bpt->number);
 
   if (breakpoint_chain == bpt)
     breakpoint_chain = bpt->next;
@@ -7146,10 +7066,6 @@ delete_breakpoint (struct breakpoint *bpt)
     value_free (bpt->val);
   if (bpt->source_file != NULL)
     xfree (bpt->source_file);
-  if (bpt->dll_pathname != NULL)
-    xfree (bpt->dll_pathname);
-  if (bpt->triggered_dll_pathname != NULL)
-    xfree (bpt->triggered_dll_pathname);
   if (bpt->exec_pathname != NULL)
     xfree (bpt->exec_pathname);
 
@@ -7162,13 +7078,8 @@ delete_breakpoint (struct breakpoint *bpt)
          bpstat_do_actions (&stop_bpstat);
      in event-top.c won't do anything, and temporary breakpoints
      with commands won't work.  */
-  for (bs = stop_bpstat; bs; bs = bs->next)
-    if (bs->breakpoint_at && bs->breakpoint_at->owner == bpt)
-      {
-       bs->breakpoint_at = NULL;
-       bs->old_val = NULL;
-       /* bs->commands will be freed later.  */
-      }
+
+  iterate_over_threads (bpstat_remove_breakpoint_callback, bpt);
 
   /* Now that breakpoint is removed from breakpoint
      list, update the global location list.  This
@@ -7178,7 +7089,7 @@ delete_breakpoint (struct breakpoint *bpt)
      looks at location's owner.  It might be better
      design to have location completely self-contained,
      but it's not the case now.  */
-  update_global_location_list ();
+  update_global_location_list (0);
 
 
   /* On the chance that someone will soon try again to delete this same
@@ -7350,6 +7261,10 @@ update_breakpoint_locations (struct breakpoint *b,
        b->line_number = sals.sals[i].line;
     }
 
+  /* Update locations of permanent breakpoints.  */
+  if (b->enable_state == bp_permanent)
+    make_breakpoint_permanent (b);
+
   /* If possible, carry over 'disable' status from existing breakpoints.  */
   {
     struct bp_location *e = existing_locations;
@@ -7388,7 +7303,7 @@ update_breakpoint_locations (struct breakpoint *b,
       }
   }
 
-  update_global_location_list ();
+  update_global_location_list (1);
 }
 
 
@@ -7420,8 +7335,6 @@ breakpoint_re_set_one (void *bint)
       return 0;
     case bp_breakpoint:
     case bp_hardware_breakpoint:
-    case bp_catch_load:
-    case bp_catch_unload:
       if (b->addr_string == NULL)
        {
          /* Anything without a string can't be re-set. */
@@ -7521,18 +7434,14 @@ breakpoint_re_set_one (void *bint)
       /* We needn't really do anything to reset these, since the mask
          that requests them is unaffected by e.g., new libraries being
          loaded. */
-    case bp_catch_fork:
-    case bp_catch_vfork:
-    case bp_catch_exec:
+    case bp_catchpoint:
       break;
 
     default:
       printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type);
       /* fall through */
-      /* Delete longjmp and overlay event breakpoints; they will be
-         reset later by breakpoint_re_set.  */
-    case bp_longjmp:
-    case bp_longjmp_resume:
+      /* Delete overlay event breakpoints; they will be reset later by
+         breakpoint_re_set.  */
     case bp_overlay_event:
       delete_breakpoint (b);
       break;
@@ -7554,6 +7463,8 @@ breakpoint_re_set_one (void *bint)
     case bp_watchpoint_scope:
     case bp_call_dummy:
     case bp_step_resume:
+    case bp_longjmp:
+    case bp_longjmp_resume:
       break;
     }
 
@@ -7581,15 +7492,6 @@ breakpoint_re_set (void)
   }
   set_language (save_language);
   input_radix = save_input_radix;
-
-  if (gdbarch_get_longjmp_target_p (current_gdbarch))
-    {
-      create_longjmp_breakpoint ("longjmp");
-      create_longjmp_breakpoint ("_longjmp");
-      create_longjmp_breakpoint ("siglongjmp");
-      create_longjmp_breakpoint ("_siglongjmp");
-      create_longjmp_breakpoint (NULL);
-    }
   
   create_overlay_event_breakpoint ("_ovly_debug_event");
 }
@@ -7637,21 +7539,18 @@ set_ignore_count (int bptnum, int count, int from_tty)
                             count, bptnum);
        }
       breakpoints_changed ();
-      breakpoint_modify_event (b->number);
+      observer_notify_breakpoint_modified (b->number);
       return;
     }
 
   error (_("No breakpoint number %d."), bptnum);
 }
 
-/* Clear the ignore counts of all breakpoints.  */
 void
-breakpoint_clear_ignore_counts (void)
+make_breakpoint_silent (struct breakpoint *b)
 {
-  struct breakpoint *b;
-
-  ALL_BREAKPOINTS (b)
-    b->ignore_count = 0;
+  /* Silence the breakpoint.  */
+  b->silent = 1;
 }
 
 /* Command to set ignore-count of breakpoint N to COUNT.  */
@@ -7783,11 +7682,9 @@ disable_breakpoint (struct breakpoint *bpt)
 
   bpt->enable_state = bp_disabled;
 
-  update_global_location_list ();
+  update_global_location_list (0);
 
-  if (deprecated_modify_breakpoint_hook)
-    deprecated_modify_breakpoint_hook (bpt);
-  breakpoint_modify_event (bpt->number);
+  observer_notify_breakpoint_modified (bpt->number);
 }
 
 static void
@@ -7803,11 +7700,7 @@ disable_command (char *args, int from_tty)
                 bpt->number);
        continue;
       case bp_breakpoint:
-      case bp_catch_load:
-      case bp_catch_unload:
-      case bp_catch_fork:
-      case bp_catch_vfork:
-      case bp_catch_exec:
+      case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
       case bp_hardware_watchpoint:
@@ -7822,7 +7715,7 @@ disable_command (char *args, int from_tty)
       struct bp_location *loc = find_location_by_number (args);
       if (loc)
        loc->enabled = 0;
-      update_global_location_list ();
+      update_global_location_list (0);
     }
   else
     map_breakpoint_numbers (args, disable_breakpoint);
@@ -7907,12 +7800,10 @@ have been allocated for other watchpoints.\n"), bpt->number);
   if (bpt->enable_state != bp_permanent)
     bpt->enable_state = bp_enabled;
   bpt->disposition = disposition;
-  update_global_location_list ();
+  update_global_location_list (1);
   breakpoints_changed ();
   
-  if (deprecated_modify_breakpoint_hook)
-    deprecated_modify_breakpoint_hook (bpt);
-  breakpoint_modify_event (bpt->number);
+  observer_notify_breakpoint_modified (bpt->number);
 }
 
 
@@ -7939,11 +7830,7 @@ enable_command (char *args, int from_tty)
                 bpt->number);
        continue;
       case bp_breakpoint:
-      case bp_catch_load:
-      case bp_catch_unload:
-      case bp_catch_fork:
-      case bp_catch_vfork:
-      case bp_catch_exec:
+      case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
       case bp_hardware_watchpoint:
@@ -7958,7 +7845,7 @@ enable_command (char *args, int from_tty)
       struct bp_location *loc = find_location_by_number (args);
       if (loc)
        loc->enabled = 1;
-      update_global_location_list ();
+      update_global_location_list (1);
     }
   else
     map_breakpoint_numbers (args, enable_breakpoint);
@@ -8126,11 +8013,6 @@ single_step_breakpoint_inserted_here_p (CORE_ADDR pc)
   return 0;
 }
 
-int breakpoints_always_inserted_mode (void)
-{
-  return always_inserted_mode;
-}
-
 \f
 /* This help string is used for the break, hbreak, tbreak and thbreak commands.
    It is defined as a macro to prevent duplication.
@@ -8151,6 +8033,34 @@ Multiple breakpoints at one place are permitted, and useful if conditional.\n\
 \n\
 Do \"help breakpoints\" for info on other commands dealing with breakpoints."
 
+/* List of subcommands for "catch".  */
+static struct cmd_list_element *catch_cmdlist;
+
+/* List of subcommands for "tcatch".  */
+static struct cmd_list_element *tcatch_cmdlist;
+
+/* Like add_cmd, but add the command to both the "catch" and "tcatch"
+   lists, and pass some additional user data to the command function.  */
+static void
+add_catch_command (char *name, char *docstring,
+                  void (*sfunc) (char *args, int from_tty,
+                                 struct cmd_list_element *command),
+                  void *user_data_catch,
+                  void *user_data_tcatch)
+{
+  struct cmd_list_element *command;
+
+  command = add_cmd (name, class_breakpoint, NULL, docstring,
+                    &catch_cmdlist);
+  set_cmd_sfunc (command, sfunc);
+  set_cmd_context (command, user_data_catch);
+
+  command = add_cmd (name, class_breakpoint, NULL, docstring,
+                    &tcatch_cmdlist);
+  set_cmd_sfunc (command, sfunc);
+  set_cmd_context (command, user_data_tcatch);
+}
+
 void
 _initialize_breakpoint (void)
 {
@@ -8408,70 +8318,71 @@ Convenience variable \"$bpnum\" contains the number of the last\n\
 breakpoint set."),
           &maintenanceinfolist);
 
-  add_com ("catch", class_breakpoint, catch_command, _("\
-Set catchpoints to catch events.\n\
-Raised signals may be caught:\n\
-\tcatch signal              - all signals\n\
-\tcatch signal <signame>    - a particular signal\n\
-Raised exceptions may be caught:\n\
-\tcatch throw               - all exceptions, when thrown\n\
-\tcatch throw <exceptname>  - a particular exception, when thrown\n\
-\tcatch catch               - all exceptions, when caught\n\
-\tcatch catch <exceptname>  - a particular exception, when caught\n\
-Thread or process events may be caught:\n\
-\tcatch thread_start        - any threads, just after creation\n\
-\tcatch thread_exit         - any threads, just before expiration\n\
-\tcatch thread_join         - any threads, just after joins\n\
-Process events may be caught:\n\
-\tcatch start               - any processes, just after creation\n\
-\tcatch exit                - any processes, just before expiration\n\
-\tcatch fork                - calls to fork()\n\
-\tcatch vfork               - calls to vfork()\n\
-\tcatch exec                - calls to exec()\n\
-Dynamically-linked library events may be caught:\n\
-\tcatch load                - loads of any library\n\
-\tcatch load <libname>      - loads of a particular library\n\
-\tcatch unload              - unloads of any library\n\
-\tcatch unload <libname>    - unloads of a particular library\n\
-The act of your program's execution stopping may also be caught:\n\
-\tcatch stop\n\n\
-C++ exceptions may be caught:\n\
-\tcatch throw               - all exceptions, when thrown\n\
-\tcatch catch               - all exceptions, when caught\n\
-Ada exceptions may be caught:\n\
-\tcatch exception           - all exceptions, when raised\n\
-\tcatch exception <name>    - a particular exception, when raised\n\
-\tcatch exception unhandled - all unhandled exceptions, when raised\n\
-\tcatch assert              - all failed assertions, when raised\n\
-\n\
-Do \"help set follow-fork-mode\" for info on debugging your program\n\
-after a fork or vfork is caught.\n\n\
-Do \"help breakpoints\" for info on other commands dealing with breakpoints."));
-
-  add_com ("tcatch", class_breakpoint, tcatch_command, _("\
-Set temporary catchpoints to catch events.\n\
-Args like \"catch\" command.\n\
-Like \"catch\" except the catchpoint is only temporary,\n\
-so it will be deleted when hit.  Equivalent to \"catch\" followed\n\
-by using \"enable delete\" on the catchpoint number."));
+  add_prefix_cmd ("catch", class_breakpoint, catch_command, _("\
+Set catchpoints to catch events."),
+                 &catch_cmdlist, "catch ",
+                 0/*allow-unknown*/, &cmdlist);
+
+  add_prefix_cmd ("tcatch", class_breakpoint, tcatch_command, _("\
+Set temporary catchpoints to catch events."),
+                 &tcatch_cmdlist, "tcatch ",
+                 0/*allow-unknown*/, &cmdlist);
+
+  /* Add catch and tcatch sub-commands.  */
+  add_catch_command ("catch", _("\
+Catch an exception, when caught.\n\
+With an argument, catch only exceptions with the given name."),
+                    catch_catch_command,
+                    CATCH_PERMANENT,
+                    CATCH_TEMPORARY);
+  add_catch_command ("throw", _("\
+Catch an exception, when thrown.\n\
+With an argument, catch only exceptions with the given name."),
+                    catch_throw_command,
+                    CATCH_PERMANENT,
+                    CATCH_TEMPORARY);
+  add_catch_command ("fork", _("Catch calls to fork."),
+                    catch_fork_command_1,
+                    (void *) (uintptr_t) catch_fork_permanent,
+                    (void *) (uintptr_t) catch_fork_temporary);
+  add_catch_command ("vfork", _("Catch calls to vfork."),
+                    catch_fork_command_1,
+                    (void *) (uintptr_t) catch_vfork_permanent,
+                    (void *) (uintptr_t) catch_vfork_temporary);
+  add_catch_command ("exec", _("Catch calls to exec."),
+                    catch_exec_command_1,
+                    CATCH_PERMANENT,
+                    CATCH_TEMPORARY);
+  add_catch_command ("exception", _("\
+Catch Ada exceptions, when raised.\n\
+With an argument, catch only exceptions with the given name."),
+                    catch_ada_exception_command,
+                    CATCH_PERMANENT,
+                    CATCH_TEMPORARY);
+  add_catch_command ("assert", _("\
+Catch failed Ada assertions, when raised.\n\
+With an argument, catch only exceptions with the given name."),
+                    catch_assert_command,
+                    CATCH_PERMANENT,
+                    CATCH_TEMPORARY);
 
   c = add_com ("watch", class_breakpoint, watch_command, _("\
 Set a watchpoint for an expression.\n\
 A watchpoint stops execution of your program whenever the value of\n\
 an expression changes."));
-  set_cmd_completer (c, location_completer);
+  set_cmd_completer (c, expression_completer);
 
   c = add_com ("rwatch", class_breakpoint, rwatch_command, _("\
 Set a read watchpoint for an expression.\n\
 A watchpoint stops execution of your program whenever the value of\n\
 an expression is read."));
-  set_cmd_completer (c, location_completer);
+  set_cmd_completer (c, expression_completer);
 
   c = add_com ("awatch", class_breakpoint, awatch_command, _("\
 Set a watchpoint for an expression.\n\
 A watchpoint stops execution of your program whenever the value of\n\
 an expression is either read or written."));
-  set_cmd_completer (c, location_completer);
+  set_cmd_completer (c, expression_completer);
 
   add_info ("watchpoints", breakpoints_info,
            _("Synonym for ``info breakpoints''."));
@@ -8533,14 +8444,18 @@ a warning will be emitted for such breakpoints."),
                           &breakpoint_set_cmdlist,
                           &breakpoint_show_cmdlist);
 
-  add_setshow_boolean_cmd ("always-inserted", class_support,
-                          &always_inserted_mode, _("\
+  add_setshow_enum_cmd ("always-inserted", class_support,
+                       always_inserted_enums, &always_inserted_mode, _("\
 Set mode for inserting breakpoints."), _("\
 Show mode for inserting breakpoints."), _("\
-When this mode is off (which is the default), breakpoints are inserted in\n\
-inferior when it is resumed, and removed when execution stops.  When this\n\
-mode is on, breakpoints are inserted immediately and removed only when\n\
-the user deletes the breakpoint."),
+When this mode is off, breakpoints are inserted in inferior when it is\n\
+resumed, and removed when execution stops.  When this mode is on,\n\
+breakpoints are inserted immediately and removed only when the user\n\
+deletes the breakpoint.  When this mode is auto (which is the default),\n\
+the behaviour depends on the non-stop setting (see help set non-stop).\n\
+In this case, if gdb is controlling the inferior in non-stop mode, gdb\n\
+behaves as if always-inserted mode is on; if gdb is controlling the\n\
+inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
                           NULL,
                           &show_always_inserted_mode,
                           &breakpoint_set_cmdlist,
This page took 0.062152 seconds and 4 git commands to generate.