gdb
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index 9454428522324f83dfa355d92d28f291226e4a32..1235946999bf0f7c5377995b46e2e2791d2ada76 100644 (file)
@@ -2,7 +2,7 @@
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
    1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008 Free Software Foundation, Inc.
+   2008, 2009 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -25,6 +25,7 @@
 #include "symtab.h"
 #include "frame.h"
 #include "breakpoint.h"
+#include "tracepoint.h"
 #include "gdbtypes.h"
 #include "expression.h"
 #include "gdbcore.h"
 #include "ada-lang.h"
 #include "top.h"
 #include "wrapper.h"
+#include "valprint.h"
+
+/* readline include files */
+#include "readline/readline.h"
+#include "readline/history.h"
+
+/* readline defines this.  */
+#undef savestring
 
 #include "mi/mi-common.h"
 
@@ -141,8 +150,6 @@ static int watchpoint_check (void *);
 
 static void maintenance_info_breakpoints (char *, int);
 
-static void create_overlay_event_breakpoint (char *);
-
 static int hw_breakpoint_used_count (void);
 
 static int hw_watchpoint_used_count (enum bptype, int *);
@@ -159,10 +166,6 @@ 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);
@@ -184,8 +187,7 @@ static int single_step_breakpoint_inserted_here_p (CORE_ADDR pc);
 
 static void free_bp_location (struct bp_location *loc);
 
-static struct bp_location *
-allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type);
+static struct bp_location *allocate_bp_location (struct breakpoint *bpt);
 
 static void update_global_location_list (int);
 
@@ -195,6 +197,21 @@ static int is_hardware_watchpoint (struct breakpoint *bpt);
 
 static void insert_breakpoint_locations (void);
 
+static void tracepoints_info (char *, int);
+
+static void delete_trace_command (char *, int);
+
+static void enable_trace_command (char *, int);
+
+static void disable_trace_command (char *, int);
+
+static void trace_pass_command (char *, int);
+
+/* Flag indicating that a command has proceeded the inferior past the
+   current breakpoint.  */
+
+static int breakpoint_proceeded;
+
 static const char *
 bpdisp_text (enum bpdisp disp)
 {
@@ -287,8 +304,6 @@ breakpoints_always_inserted_mode (void)
 
 void _initialize_breakpoint (void);
 
-extern int addressprint;       /* Print machine addresses? */
-
 /* Are we executing breakpoint commands?  */
 static int executing_breakpoint_commands;
 
@@ -315,9 +330,11 @@ 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.  */
+/* Iterator for tracepoints only.  */
 
-int show_breakpoint_hit_counts = 1;
+#define ALL_TRACEPOINTS(B)  \
+  for (B = breakpoint_chain; B; B = B->next)  \
+    if ((B)->type == bp_tracepoint)
 
 /* Chains of all breakpoints defined.  */
 
@@ -334,58 +351,9 @@ VEC(bp_location_p) *moribund_locations = NULL;
 
 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.  */
+/* Number of last tracepoint made.  */
 
-#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
+int tracepoint_count;
 
 /* Return whether a breakpoint is an active enabled breakpoint.  */
 static int
@@ -629,7 +597,7 @@ condition_command (char *arg, int from_tty)
            arg = p;
            /* I don't know if it matters whether this is the string the user
               typed in or the decompiled expression.  */
-           b->cond_string = savestring (arg, strlen (arg));
+           b->cond_string = xstrdup (arg);
            b->condition_not_parsed = 0;
            for (loc = b->loc; loc; loc = loc->next)
              {
@@ -799,21 +767,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
@@ -829,7 +786,7 @@ is_hardware_watchpoint (struct breakpoint *bpt)
    in *VAL_CHAIN.  RESULTP and VAL_CHAIN may be NULL if the caller does
    not need them.
 
-   If an error occurs while evaluating the expression, *RESULTP will
+   If a memory error occurs while evaluating the expression, *RESULTP will
    be set to NULL.  *RESULTP may be a lazy value, if the result could
    not be read from memory.  It is used to determine whether a value
    is user-specified (we should watch the whole value) or intermediate
@@ -850,6 +807,7 @@ fetch_watchpoint_value (struct expression *exp, struct value **valp,
                        struct value **resultp, struct value **val_chain)
 {
   struct value *mark, *new_mark, *result;
+  volatile struct gdb_exception ex;
 
   *valp = NULL;
   if (resultp)
@@ -860,7 +818,26 @@ fetch_watchpoint_value (struct expression *exp, struct value **valp,
   /* Evaluate the expression.  */
   mark = value_mark ();
   result = NULL;
-  gdb_evaluate_expression (exp, &result);
+
+  TRY_CATCH (ex, RETURN_MASK_ALL)
+    {
+      result = evaluate_expression (exp);
+    }
+  if (ex.reason < 0)
+    {
+      /* Ignore memory errors, we want watchpoints pointing at
+        inaccessible memory to still be created; otherwise, throw the
+        error to some higher catcher.  */
+      switch (ex.error)
+       {
+       case MEMORY_ERROR:
+         break;
+       default:
+         throw_exception (ex);
+         break;
+       }
+    }
+
   new_mark = value_mark ();
   if (mark == new_mark)
     return;
@@ -882,13 +859,15 @@ fetch_watchpoint_value (struct expression *exp, struct value **valp,
     }
 }
 
-/* Assuming that B is a hardware watchpoint:
-   - Reparse watchpoint expression, is REPARSE is non-zero
+/* Assuming that B is a watchpoint:
+   - Reparse watchpoint expression, if REPARSE is non-zero
    - Evaluate expression and store the result in B->val
+   - Evaluate the condition if there is one, and store the result
+     in b->loc->cond.
    - Update the list of values that must be watched in B->loc.
 
-   If the watchpoint is disabled, do nothing.  If this is
-   local watchpoint that is out of scope, delete it.  */
+   If the watchpoint disposition is disp_del_at_next_stop, then do nothing.
+   If this is local watchpoint that is out of scope, delete it.  */
 static void
 update_watchpoint (struct breakpoint *b, int reparse)
 {
@@ -897,10 +876,9 @@ update_watchpoint (struct breakpoint *b, int reparse)
   struct bp_location *loc;
   bpstat bs;
 
-  /* We don't free locations.  They are stored in
-     bp_location_chain and update_global_locations will
-     eventually delete them and remove breakpoints if
-     needed.  */
+  /* We don't free locations.  They are stored in bp_location_chain and
+     update_global_locations will eventually delete them and remove
+     breakpoints if needed.  */
   b->loc = NULL;
 
   if (b->disposition == disp_del_at_next_stop)
@@ -965,6 +943,31 @@ update_watchpoint (struct breakpoint *b, int reparse)
          b->val_valid = 1;
        }
 
+       /* Change the type of breakpoint between hardware assisted or an
+          ordinary watchpoint depending on the hardware support and free
+          hardware slots.  REPARSE is set when the inferior is started.  */
+       if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint)
+           && reparse)
+         {
+           int i, mem_cnt, other_type_used;
+
+           i = hw_watchpoint_used_count (bp_hardware_watchpoint,
+                                         &other_type_used);
+           mem_cnt = can_use_hardware_watchpoint (val_chain);
+
+           if (!mem_cnt)
+             b->type = bp_watchpoint;
+           else
+             {
+               int target_resources_ok = target_can_use_hardware_watchpoint
+                 (bp_hardware_watchpoint, i + mem_cnt, other_type_used);
+               if (target_resources_ok <= 0)
+                 b->type = bp_watchpoint;
+               else
+                 b->type = bp_hardware_watchpoint;
+             }
+         }
+
       /* Look at each value on the value chain.  */
       for (v = val_chain; v; v = next)
        {
@@ -997,7 +1000,7 @@ update_watchpoint (struct breakpoint *b, int reparse)
                  else if (b->type == bp_access_watchpoint)
                    type = hw_access;
                  
-                 loc = allocate_bp_location (b, bp_hardware_watchpoint);
+                 loc = allocate_bp_location (b);
                  for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
                    ;
                  *tmp = loc;
@@ -1025,7 +1028,7 @@ update_watchpoint (struct breakpoint *b, int reparse)
   else if (!within_current_scope)
     {
       printf_filtered (_("\
-Hardware watchpoint %d deleted because the program has left the block \n\
+Watchpoint %d deleted because the program has left the block \n\
 in which its expression is valid.\n"),
                       b->number);
       if (b->related_breakpoint)
@@ -1052,19 +1055,24 @@ should_be_inserted (struct bp_location *bpt)
   if (!bpt->enabled || bpt->shlib_disabled || bpt->duplicate)
     return 0;
 
+  /* Tracepoints are inserted by the target at a time of its choosing,
+     not by us.  */
+  if (bpt->owner->type == bp_tracepoint)
+    return 0;
+
   return 1;
 }
 
 /* Insert a low-level "breakpoint" of some type.  BPT is the breakpoint.
    Any error messages are printed to TMP_ERROR_STREAM; and DISABLED_BREAKS,
-   PROCESS_WARNING, and HW_BREAKPOINT_ERROR are used to report problems.
+   and HW_BREAKPOINT_ERROR are used to report problems.
 
    NOTE drow/2003-09-09: This routine could be broken down to an object-style
    method for each breakpoint or catchpoint type.  */
 static int
 insert_bp_location (struct bp_location *bpt,
                    struct ui_file *tmp_error_stream,
-                   int *disabled_breaks, int *process_warning,
+                   int *disabled_breaks,
                    int *hw_breakpoint_error)
 {
   int val = 0;
@@ -1163,8 +1171,8 @@ Note: automatically using hardware breakpoints for read-only addresses.\n"));
                  bpt->overlay_target_info.placed_address = addr;
                  val = target_insert_breakpoint (&bpt->overlay_target_info);
                  if (val != 0)
-                   fprintf_unfiltered (tmp_error_stream, 
-                                       "Overlay breakpoint %d failed: in ROM?", 
+                   fprintf_unfiltered (tmp_error_stream,
+                                       "Overlay breakpoint %d failed: in ROM?\n",
                                        bpt->owner->number);
                }
            }
@@ -1188,7 +1196,7 @@ Note: automatically using hardware breakpoints for read-only addresses.\n"));
       if (val)
        {
          /* Can't set the breakpoint.  */
-         if (solib_address (bpt->address))
+         if (solib_name_from_address (bpt->address))
            {
              /* See also: disable_breakpoints_in_shlibs. */
              val = 0;
@@ -1207,9 +1215,6 @@ Note: automatically using hardware breakpoints for read-only addresses.\n"));
            }
          else
            {
-#ifdef ONE_PROCESS_WRITETEXT
-             *process_warning = 1;
-#endif
              if (bpt->loc_type == bp_loc_hardware_breakpoint)
                {
                  *hw_breakpoint_error = 1;
@@ -1248,9 +1253,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);
@@ -1285,7 +1288,9 @@ insert_breakpoints (void)
 
   update_global_location_list (1);
 
-  if (!breakpoints_always_inserted_mode () && target_has_execution)
+  if (!breakpoints_always_inserted_mode ()
+      && (target_has_execution
+         || gdbarch_has_global_breakpoints (target_gdbarch)))
     /* update_global_location_list does not insert breakpoints
        when always_inserted_mode is not enabled.  Explicitly
        insert them now.  */
@@ -1306,10 +1311,9 @@ insert_breakpoint_locations (void)
   int val = 0;
   int disabled_breaks = 0;
   int hw_breakpoint_error = 0;
-  int process_warning = 0;
 
   struct ui_file *tmp_error_stream = mem_fileopen ();
-  make_cleanup_ui_file_delete (tmp_error_stream);
+  struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_error_stream);
   
   /* Explicitly mark the warning -- this will only be printed if
      there was an error.  */
@@ -1327,7 +1331,7 @@ insert_breakpoint_locations (void)
        continue;
 
       val = insert_bp_location (b, tmp_error_stream,
-                                   &disabled_breaks, &process_warning,
+                                   &disabled_breaks,
                                    &hw_breakpoint_error);
       if (val)
        error = val;
@@ -1379,14 +1383,11 @@ insert_breakpoint_locations (void)
                              "Could not insert hardware breakpoints:\n\
 You may have requested too many hardware breakpoints/watchpoints.\n");
        }
-#ifdef ONE_PROCESS_WRITETEXT
-      if (process_warning)
-       fprintf_unfiltered (tmp_error_stream,
-                           "The same program may be running in another process.");
-#endif
       target_terminal_ours_for_output ();
       error_stream (tmp_error_stream);
     }
+
+  do_cleanups (cleanups);
 }
 
 int
@@ -1432,7 +1433,7 @@ reattach_breakpoints (int pid)
   int val;
   struct cleanup *old_chain = save_inferior_ptid ();
   struct ui_file *tmp_error_stream = mem_fileopen ();
-  int dummy1 = 0, dummy2 = 0, dummy3 = 0;
+  int dummy1 = 0, dummy2 = 0;
 
   make_cleanup_ui_file_delete (tmp_error_stream);
 
@@ -1443,7 +1444,7 @@ reattach_breakpoints (int pid)
       {
        b->inserted = 0;
        val = insert_bp_location (b, tmp_error_stream,
-                                 &dummy1, &dummy2, &dummy3);
+                                 &dummy1, &dummy2);
        if (val != 0)
          {
            do_cleanups (old_chain);
@@ -1455,12 +1456,59 @@ reattach_breakpoints (int pid)
   return 0;
 }
 
+static int internal_breakpoint_number = -1;
+
+static struct breakpoint *
+create_internal_breakpoint (CORE_ADDR address, enum bptype type)
+{
+  struct symtab_and_line sal;
+  struct breakpoint *b;
+
+  init_sal (&sal);             /* initialize to zeroes */
+
+  sal.pc = address;
+  sal.section = find_pc_overlay (sal.pc);
+
+  b = set_raw_breakpoint (sal, type);
+  b->number = internal_breakpoint_number--;
+  b->disposition = disp_donttouch;
+
+  return b;
+}
+
+static void
+create_overlay_event_breakpoint (char *func_name, struct objfile *objfile)
+{
+  struct breakpoint *b;
+  struct minimal_symbol *m;
+
+  if ((m = lookup_minimal_symbol_text (func_name, objfile)) == NULL)
+    return;
+
+  b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m),
+                                 bp_overlay_event);
+  b->addr_string = xstrdup (func_name);
+
+  if (overlay_debugging == ovly_auto)
+    {
+      b->enable_state = bp_enabled;
+      overlay_events_enabled = 1;
+    }
+  else
+    {
+      b->enable_state = bp_disabled;
+      overlay_events_enabled = 0;
+    }
+  update_global_location_list (1);
+}
+
 void
 update_breakpoints_after_exec (void)
 {
   struct breakpoint *b;
   struct breakpoint *temp;
   struct bp_location *bploc;
+  struct objfile *objfile;
 
   /* We're about to delete breakpoints from GDB's lists.  If the
      INSERTED flag is true, GDB will try to lift the breakpoints by
@@ -1505,19 +1553,13 @@ 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))
+    if (b->type == bp_catchpoint)
       {
-       continue;
+        /* 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
@@ -1561,7 +1603,8 @@ update_breakpoints_after_exec (void)
       }
   }
   /* FIXME what about longjmp breakpoints?  Re-create them here?  */
-  create_overlay_event_breakpoint ("_ovly_debug_event");
+  ALL_OBJFILES (objfile)
+    create_overlay_event_breakpoint ("_ovly_debug_event", objfile);
 }
 
 int
@@ -1669,7 +1712,7 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is)
       /* 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))
+      if (val && solib_name_from_address (b->address))
        val = 0;
 
       if (val)
@@ -1690,28 +1733,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);
@@ -1748,6 +1776,12 @@ 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_breakpoints (target_gdbarch))
+    return;
 
   ALL_BP_LOCATIONS (bpt)
     if (bpt->owner->enable_state != bp_permanent)
@@ -1790,6 +1824,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
@@ -1832,6 +1871,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.
@@ -1918,28 +1971,51 @@ int
 breakpoint_thread_match (CORE_ADDR pc, ptid_t ptid)
 {
   const struct bp_location *bpt;
-  int thread;
-
-  thread = pid_to_thread_id (ptid);
-
+  /* The thread and task IDs associated to PTID, computed lazily.  */
+  int thread = -1;
+  int task = 0;
+  
   ALL_BP_LOCATIONS (bpt)
     {
       if (bpt->loc_type != bp_loc_software_breakpoint
          && bpt->loc_type != bp_loc_hardware_breakpoint)
        continue;
 
-      if ((breakpoint_enabled (bpt->owner)
-          || bpt->owner->enable_state == bp_permanent)
-         && bpt->address == pc
-         && (bpt->owner->thread == -1 || bpt->owner->thread == thread))
+      if (!breakpoint_enabled (bpt->owner)
+         && bpt->owner->enable_state != bp_permanent)
+       continue;
+
+      if (bpt->address != pc)
+       continue;
+
+      if (bpt->owner->thread != -1)
        {
-         if (overlay_debugging 
-             && section_is_overlay (bpt->section) 
-             && !section_is_mapped (bpt->section))
-           continue;           /* unmapped overlay -- can't be a match */
-         else
-           return 1;
+         /* This is a thread-specific breakpoint.  Check that ptid
+            matches that thread.  If thread hasn't been computed yet,
+            it is now time to do so.  */
+         if (thread == -1)
+           thread = pid_to_thread_id (ptid);
+         if (bpt->owner->thread != thread)
+           continue;
        }
+
+      if (bpt->owner->task != 0)
+        {
+         /* This is a task-specific breakpoint.  Check that ptid
+            matches that task.  If task hasn't been computed yet,
+            it is now time to do so.  */
+         if (task == 0)
+           task = ada_get_task_number (ptid);
+         if (bpt->owner->task != task)
+           continue;
+        }
+
+      if (overlay_debugging 
+         && section_is_overlay (bpt->section) 
+         && !section_is_mapped (bpt->section))
+       continue;           /* unmapped overlay -- can't be a match */
+
+      return 1;
     }
 
   return 0;
@@ -1952,22 +2028,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 
@@ -2128,6 +2189,26 @@ bpstat_clear_actions (bpstat bs)
     }
 }
 
+/* Called when a command is about to proceed the inferior.  */
+
+static void
+breakpoint_about_to_proceed (void)
+{
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    {
+      struct thread_info *tp = inferior_thread ();
+
+      /* Allow inferior function calls in breakpoint commands to not
+        interrupt the command list.  When the call finishes
+        successfully, the inferior will be standing at the same
+        breakpoint as if nothing happened.  */
+      if (tp->in_infcall)
+       return;
+    }
+
+  breakpoint_proceeded = 1;
+}
+
 /* Stub for cleaning up our state if we error-out of a breakpoint command */
 static void
 cleanup_executing_breakpoints (void *ignore)
@@ -2248,7 +2329,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,
@@ -2275,13 +2360,13 @@ watchpoint_value_print (struct value *val, struct ui_file *stream)
 static enum print_stop_action
 print_it_typical (bpstat bs)
 {
-  struct cleanup *old_chain, *ui_out_chain;
+  struct cleanup *old_chain;
   struct breakpoint *b;
   const struct bp_location *bl;
   struct ui_stream *stb;
-  int bp_temp = 0;  
-  stb = ui_out_stream_new (uiout);
-  old_chain = make_cleanup_ui_out_stream_delete (stb);
+  int bp_temp = 0;
+  enum print_stop_action result;
+
   /* bs->breakpoint_at can be NULL if it was a momentary breakpoint
      which has since been deleted.  */
   if (bs->breakpoint_at == NULL)
@@ -2289,6 +2374,9 @@ print_it_typical (bpstat bs)
   bl = bs->breakpoint_at;
   b = bl->owner;
 
+  stb = ui_out_stream_new (uiout);
+  old_chain = make_cleanup_ui_out_stream_delete (stb);
+
   switch (b->type)
     {
     case bp_breakpoint:
@@ -2311,7 +2399,7 @@ print_it_typical (bpstat bs)
        }
       ui_out_field_int (uiout, "bkptno", b->number);
       ui_out_text (uiout, ", ");
-      return PRINT_SRC_AND_LOC;
+      result = PRINT_SRC_AND_LOC;
       break;
 
     case bp_shlib_event:
@@ -2319,60 +2407,20 @@ print_it_typical (bpstat bs)
         variable?  (If so, we report this as a generic, "Stopped due
         to shlib event" message.) */
       printf_filtered (_("Stopped due to shared library event\n"));
-      return PRINT_NOTHING;
+      result = PRINT_NOTHING;
       break;
 
     case bp_thread_event:
       /* Not sure how we will get here. 
         GDB should not stop for these breakpoints.  */
       printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n"));
-      return PRINT_NOTHING;
+      result = PRINT_NOTHING;
       break;
 
     case bp_overlay_event:
       /* By analogy with the thread event, GDB should not stop for these. */
       printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n"));
-      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, 
-                      ptid_get_pid (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, 
-                      ptid_get_pid (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;
+      result = PRINT_NOTHING;
       break;
 
     case bp_watchpoint:
@@ -2383,17 +2431,16 @@ print_it_typical (bpstat bs)
          (uiout, "reason",
           async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
       mention (b);
-      ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+      make_cleanup_ui_out_tuple_begin_end (uiout, "value");
       ui_out_text (uiout, "\nOld value = ");
       watchpoint_value_print (bs->old_val, stb->stream);
       ui_out_field_stream (uiout, "old", stb);
       ui_out_text (uiout, "\nNew value = ");
       watchpoint_value_print (b->val, stb->stream);
       ui_out_field_stream (uiout, "new", stb);
-      do_cleanups (ui_out_chain);
       ui_out_text (uiout, "\n");
       /* More than one watchpoint may have been triggered.  */
-      return PRINT_UNKNOWN;
+      result = PRINT_UNKNOWN;
       break;
 
     case bp_read_watchpoint:
@@ -2402,13 +2449,12 @@ print_it_typical (bpstat bs)
          (uiout, "reason",
           async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
       mention (b);
-      ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+      make_cleanup_ui_out_tuple_begin_end (uiout, "value");
       ui_out_text (uiout, "\nValue = ");
       watchpoint_value_print (b->val, stb->stream);
       ui_out_field_stream (uiout, "value", stb);
-      do_cleanups (ui_out_chain);
       ui_out_text (uiout, "\n");
-      return PRINT_UNKNOWN;
+      result = PRINT_UNKNOWN;
       break;
 
     case bp_access_watchpoint:
@@ -2420,7 +2466,7 @@ print_it_typical (bpstat bs)
              (uiout, "reason",
               async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
          mention (b);
-         ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+         make_cleanup_ui_out_tuple_begin_end (uiout, "value");
          ui_out_text (uiout, "\nOld value = ");
          watchpoint_value_print (bs->old_val, stb->stream);
          ui_out_field_stream (uiout, "old", stb);
@@ -2433,14 +2479,13 @@ print_it_typical (bpstat bs)
            ui_out_field_string
              (uiout, "reason",
               async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
-         ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+         make_cleanup_ui_out_tuple_begin_end (uiout, "value");
          ui_out_text (uiout, "\nValue = ");
        }
       watchpoint_value_print (b->val, stb->stream);
       ui_out_field_stream (uiout, "new", stb);
-      do_cleanups (ui_out_chain);
       ui_out_text (uiout, "\n");
-      return PRINT_UNKNOWN;
+      result = PRINT_UNKNOWN;
       break;
 
     /* Fall through, we don't deal with these types of breakpoints
@@ -2451,7 +2496,7 @@ print_it_typical (bpstat bs)
        ui_out_field_string
          (uiout, "reason",
           async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED));
-      return PRINT_UNKNOWN;
+      result = PRINT_UNKNOWN;
       break;
 
     case bp_until:
@@ -2459,7 +2504,7 @@ print_it_typical (bpstat bs)
        ui_out_field_string
          (uiout, "reason",
           async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED));
-      return PRINT_UNKNOWN;
+      result = PRINT_UNKNOWN;
       break;
 
     case bp_none:
@@ -2468,9 +2513,14 @@ print_it_typical (bpstat bs)
     case bp_step_resume:
     case bp_watchpoint_scope:
     case bp_call_dummy:
+    case bp_tracepoint:
     default:
-      return PRINT_UNKNOWN;
+      result = PRINT_UNKNOWN;
+      break;
     }
+
+  do_cleanups (old_chain);
+  return result;
 }
 
 /* Generic routine for printing messages indicating why we
@@ -2597,7 +2647,7 @@ bpstat_alloc (const struct bp_location *bl, bpstat cbs /* Current "bs" value */
 int
 watchpoints_triggered (struct target_waitstatus *ws)
 {
-  int stopped_by_watchpoint = STOPPED_BY_WATCHPOINT (*ws);
+  int stopped_by_watchpoint = target_stopped_by_watchpoint ();
   CORE_ADDR addr;
   struct breakpoint *b;
 
@@ -2707,9 +2757,15 @@ watchpoint_check (void *p)
         that the watchpoint frame couldn't be found by frame_find_by_id()
         because the current PC is currently in an epilogue.  Calling
         gdbarch_in_function_epilogue_p() also when fr == NULL fixes that. */
-      if ((!within_current_scope || fr == get_current_frame ())
-          && gdbarch_in_function_epilogue_p (current_gdbarch, read_pc ()))
-       return WP_VALUE_NOT_CHANGED;
+      if (!within_current_scope || fr == get_current_frame ())
+       {
+         struct frame_info *frame = get_current_frame ();
+         struct gdbarch *frame_arch = get_frame_arch (frame);
+         CORE_ADDR frame_pc = get_frame_pc (frame);
+
+         if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc))
+           return WP_VALUE_NOT_CHANGED;
+       }
       if (fr && within_current_scope)
        /* If we end up stopping, the current frame will get selected
           in normal_stop.  So this call to select_frame won't affect
@@ -2793,9 +2849,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;
@@ -2827,48 +2881,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 (inferior_ptid,
-                              &b->forked_inferior_pid))
-    return 0;
-  
-  if ((b->type == bp_catch_vfork)
-      && !inferior_has_vforked (inferior_ptid,
-                               &b->forked_inferior_pid))
-    return 0;
-  
-  if ((b->type == bp_catch_exec)
-      && !inferior_has_execd (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;
 }
 
@@ -2995,6 +3015,13 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
       
       if (bl->cond && bl->owner->disposition != disp_del_at_next_stop)
        {
+         /* We use value_mark and value_free_to_mark because it could
+            be a long time before we return to the command level and
+            call free_all_values.  We can't call free_all_values
+            because we might be in the middle of evaluating a
+            function call.  */
+         struct value *mark = value_mark ();
+
          /* Need to select the frame, with all that implies
             so that the conditions will have the right context.  */
          select_frame (get_current_frame ());
@@ -3003,7 +3030,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
                            "Error in testing breakpoint condition:\n",
                            RETURN_MASK_ALL);
          /* FIXME-someday, should give breakpoint # */
-         free_all_values ();
+         value_free_to_mark (mark);
        }
       if (bl->cond && value_is_zero)
        {
@@ -3054,6 +3081,7 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
   /* Pointer to the last thing in the chain currently.  */
   bpstat bs = root_bs;
   int ix;
+  int need_remove_insert;
 
   ALL_BP_LOCATIONS (bl)
   {
@@ -3146,6 +3174,7 @@ 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
@@ -3158,11 +3187,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
@@ -3203,9 +3236,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
     };
@@ -3221,7 +3251,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
@@ -3242,14 +3271,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
@@ -3266,30 +3294,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
@@ -3302,7 +3328,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;
 
@@ -3377,19 +3402,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)
@@ -3408,6 +3421,13 @@ bpstat_what (bpstat bs)
          bs_class = bp_silent;
          retval.call_dummy = 1;
          break;
+       case bp_tracepoint:
+         /* Tracepoint hits should not be reported back to GDB, and
+            if one got through somehow, it should have been filtered
+            out already.  */
+         internal_error (__FILE__, __LINE__,
+                         _("bpstat_what: bp_tracepoint encountered"));
+         break;
        }
       current_action = table[(int) bs_class][(int) current_action];
     }
@@ -3424,74 +3444,13 @@ bpstat_should_step (void)
 {
   struct breakpoint *b;
   ALL_BREAKPOINTS (b)
-    if (breakpoint_enabled (b) && b->type == bp_watchpoint)
+    if (breakpoint_enabled (b) && b->type == bp_watchpoint && b->loc != NULL)
       return 1;
   return 0;
 }
 
 \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,
@@ -3567,11 +3526,8 @@ 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"},
+    {bp_tracepoint, "tracepoint"},
   };
   
   static char bpenables[] = "nynny";
@@ -3582,6 +3538,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
@@ -3645,7 +3604,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, "           ");
@@ -3677,64 +3636,10 @@ 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 (!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);
-         }
-       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, "\" ");
-         }
+       ui_out_field_string (uiout, "what", b->exp_string);
        break;
 
       case bp_breakpoint:
@@ -3749,7 +3654,8 @@ print_one_breakpoint_location (struct breakpoint *b,
       case bp_shlib_event:
       case bp_thread_event:
       case bp_overlay_event:
-       if (addressprint)
+      case bp_tracepoint:
+       if (opts.addressprint)
          {
            annotate_field (4);
            if (header_of_multiple)
@@ -3767,12 +3673,20 @@ print_one_breakpoint_location (struct breakpoint *b,
        break;
       }
 
-  if (!part_of_multiple && b->thread != -1)
+  if (!part_of_multiple)
     {
-      /* FIXME: This seems to be redundant and lost here; see the
-        "stop only in" line a little further down. */
-      ui_out_text (uiout, " thread ");
-      ui_out_field_int (uiout, "thread", b->thread);
+      if (b->thread != -1)
+       {
+         /* FIXME: This seems to be redundant and lost here; see the
+            "stop only in" line a little further down. */
+         ui_out_text (uiout, " thread ");
+         ui_out_field_int (uiout, "thread", b->thread);
+       }
+      else if (b->task != 0)
+       {
+         ui_out_text (uiout, " task ");
+         ui_out_field_int (uiout, "task", b->task);
+       }
     }
   
   ui_out_text (uiout, "\n");
@@ -3793,7 +3707,10 @@ print_one_breakpoint_location (struct breakpoint *b,
          because the condition is an internal implementation detail
          that we do not want to expose to the user.  */
       annotate_field (7);
-      ui_out_text (uiout, "\tstop only if ");
+      if (b->type == bp_tracepoint)
+       ui_out_text (uiout, "\ttrace only if ");
+      else
+       ui_out_text (uiout, "\tstop only if ");
       ui_out_field_string (uiout, "cond", b->cond_string);
       ui_out_text (uiout, "\n");
     }
@@ -3806,7 +3723,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))
@@ -3824,7 +3741,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)
@@ -3845,6 +3762,34 @@ print_one_breakpoint_location (struct breakpoint *b,
       do_cleanups (script_chain);
     }
 
+  if (!part_of_multiple && b->pass_count)
+    {
+      annotate_field (10);
+      ui_out_text (uiout, "\tpass count ");
+      ui_out_field_int (uiout, "pass", b->pass_count);
+      ui_out_text (uiout, " \n");
+    }
+
+  if (!part_of_multiple && b->step_count)
+    {
+      annotate_field (11);
+      ui_out_text (uiout, "\tstep count ");
+      ui_out_field_int (uiout, "step", b->step_count);
+      ui_out_text (uiout, " \n");
+    }
+
+  if (!part_of_multiple && b->actions)
+    {
+      struct action_line *action;
+      annotate_field (12);
+      for (action = b->actions; action; action = action->next)
+       {
+         ui_out_text (uiout, "      A\t");
+         ui_out_text (uiout, action->action);
+         ui_out_text (uiout, "\n");
+       }
+    }
+
   if (ui_out_is_mi_like_p (uiout) && !part_of_multiple)
     {
       if (b->addr_string)
@@ -3933,12 +3878,9 @@ 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_tracepoint
          || b->type == bp_watchpoint
          || b->type == bp_read_watchpoint
          || b->type == bp_access_watchpoint
@@ -3956,7 +3898,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)
@@ -3967,7 +3912,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");
@@ -3990,7 +3935,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);
@@ -4144,9 +4089,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_catch_fork
-      bp_catch_vork */
+      bp_catchpoint */
 
 static int
 breakpoint_address_is_meaningful (struct breakpoint *bpt)
@@ -4157,9 +4100,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_catch_fork
-         && type != bp_catch_vfork);
+         && type != bp_catchpoint);
 }
 
 /* Rescan breakpoints at the same address and section as BPT,
@@ -4196,8 +4137,8 @@ check_duplicates_for (CORE_ADDR address, struct obj_section *section)
     }
 
   /* If we found a permanent breakpoint at this address, go over the
-     list again and declare all the other breakpoints there to be the
-     duplicates.  */
+     list again and declare all the other breakpoints there (except
+     other permanent breakpoints) to be the duplicates.  */
   if (perm_bp)
     {
       perm_bp->duplicate = 0;
@@ -4211,7 +4152,8 @@ check_duplicates_for (CORE_ADDR address, struct obj_section *section)
       ALL_BP_LOCATIONS (b)
        if (b != perm_bp)
          {
-           if (b->owner->enable_state != bp_disabled
+           if (b->owner->enable_state != bp_permanent
+               && b->owner->enable_state != bp_disabled
                && b->owner->enable_state != bp_call_disabled
                && b->enabled && !b->shlib_disabled             
                && b->address == address        /* address / overlay match */
@@ -4274,9 +4216,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.  */
@@ -4304,7 +4244,7 @@ adjust_breakpoint_address (CORE_ADDR bpaddr, enum bptype bptype)
 /* Allocate a struct bp_location.  */
 
 static struct bp_location *
-allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type)
+allocate_bp_location (struct breakpoint *bpt)
 {
   struct bp_location *loc, *loc_p;
 
@@ -4316,9 +4256,10 @@ allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type)
   loc->shlib_disabled = 0;
   loc->enabled = 1;
 
-  switch (bp_type)
+  switch (bpt->type)
     {
     case bp_breakpoint:
+    case bp_tracepoint:
     case bp_until:
     case bp_finish:
     case bp_longjmp:
@@ -4329,8 +4270,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:
@@ -4342,9 +4281,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:
@@ -4386,8 +4323,6 @@ 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 = null_ptid;
   b->exec_pathname = NULL;
   b->ops = NULL;
@@ -4414,7 +4349,8 @@ static void
 set_breakpoint_location_function (struct bp_location *loc)
 {
   if (loc->owner->type == bp_breakpoint
-      || loc->owner->type == bp_hardware_breakpoint)
+      || loc->owner->type == bp_hardware_breakpoint
+      || loc->owner->type == bp_tracepoint)
     {
       find_pc_partial_function (loc->address, &(loc->function_name), 
                                NULL, NULL);
@@ -4450,17 +4386,16 @@ set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
      breakpoint may cause target_read_memory() to be called and we do
      not want its scan of the location chain to find a breakpoint and
      location that's only been partially initialized.  */
-  adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
+  adjusted_address = adjust_breakpoint_address (sal.pc, b->type);
 
-  b->loc = allocate_bp_location (b, bptype);
+  b->loc = allocate_bp_location (b);
   b->loc->requested_address = sal.pc;
   b->loc->address = adjusted_address;
 
   if (sal.symtab == NULL)
     b->source_file = NULL;
   else
-    b->source_file = savestring (sal.symtab->filename,
-                                strlen (sal.symtab->filename));
+    b->source_file = xstrdup (sal.symtab->filename);
   b->loc->section = sal.section;
   b->line_number = sal.line;
 
@@ -4489,26 +4424,6 @@ make_breakpoint_permanent (struct breakpoint *b)
     bl->inserted = 1;
 }
 
-static struct breakpoint *
-create_internal_breakpoint (CORE_ADDR address, enum bptype type)
-{
-  static int internal_breakpoint_number = -1;
-  struct symtab_and_line sal;
-  struct breakpoint *b;
-
-  init_sal (&sal);             /* initialize to zeroes */
-
-  sal.pc = address;
-  sal.section = find_pc_overlay (sal.pc);
-
-  b = set_raw_breakpoint (sal, type);
-  b->number = internal_breakpoint_number--;
-  b->disposition = disp_donttouch;
-
-  return b;
-}
-
-
 static void
 create_longjmp_breakpoint (char *func_name)
 {
@@ -4550,40 +4465,6 @@ delete_longjmp_breakpoint (int thread)
       }
 }
 
-static void
-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, objfile)) == NULL)
-    return;
-  b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m), 
-                                 bp_overlay_event);
-  b->addr_string = xstrdup (func_name);
-
-  if (overlay_debugging == ovly_auto)
-    {
-      b->enable_state = bp_enabled;
-      overlay_events_enabled = 1;
-    }
-  else 
-    {
-      b->enable_state = bp_disabled;
-      overlay_events_enabled = 0;
-    }
-  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
 enable_overlay_breakpoints (void)
 {
@@ -4680,7 +4561,6 @@ void
 disable_breakpoints_in_shlibs (void)
 {
   struct bp_location *loc;
-  int disabled_shlib_breaks = 0;
 
   ALL_BP_LOCATIONS (loc)
   {
@@ -4690,12 +4570,14 @@ disable_breakpoints_in_shlibs (void)
        becomes enabled, or the duplicate is removed, gdb will try to insert
        all breakpoints.  If we don't set shlib_disabled here, we'll try
        to insert those breakpoints and fail.  */
-    if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint))
+    if (((b->type == bp_breakpoint)
+        || (b->type == bp_hardware_breakpoint)
+        || (b->type == bp_tracepoint))
        && !loc->shlib_disabled
 #ifdef PC_SOLIB
        && PC_SOLIB (loc->address)
 #else
-       && solib_address (loc->address)
+       && solib_name_from_address (loc->address)
 #endif
        )
       {
@@ -4713,104 +4595,318 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
   struct bp_location *loc;
   int disabled_shlib_breaks = 0;
 
+  /* SunOS a.out shared libraries are always mapped, so do not
+     disable breakpoints; they will only be reported as unloaded
+     through clear_solib when GDB discards its shared library
+     list.  See clear_solib for more information.  */
+  if (exec_bfd != NULL
+      && bfd_get_flavour (exec_bfd) == bfd_target_aout_flavour)
+    return;
+
   ALL_BP_LOCATIONS (loc)
   {
     struct breakpoint *b = loc->owner;
     if ((loc->loc_type == bp_loc_hardware_breakpoint
         || loc->loc_type == bp_loc_software_breakpoint)
-       && !loc->shlib_disabled)
+       && !loc->shlib_disabled
+       && (b->type == bp_breakpoint || b->type == bp_hardware_breakpoint)
+       && solib_contains_address_p (solib, loc->address))
       {
-#ifdef PC_SOLIB
-       char *so_name = PC_SOLIB (loc->address);
-#else
-       char *so_name = solib_address (loc->address);
-#endif
-       if (so_name && !strcmp (so_name, solib->so_name))
-          {
-           loc->shlib_disabled = 1;
-           /* At this point, we cannot rely on remove_breakpoint
-              succeeding so we must mark the breakpoint as not inserted
-              to prevent future errors occurring in remove_breakpoints.  */
-           loc->inserted = 0;
-           if (!disabled_shlib_breaks)
-             {
-               target_terminal_ours_for_output ();
-               warning (_("Temporarily disabling breakpoints for unloaded shared library \"%s\""),
-                         so_name);
-             }
-           disabled_shlib_breaks = 1;
+       loc->shlib_disabled = 1;
+       /* At this point, we cannot rely on remove_breakpoint
+          succeeding so we must mark the breakpoint as not inserted
+          to prevent future errors occurring in remove_breakpoints.  */
+       loc->inserted = 0;
+       if (!disabled_shlib_breaks)
+         {
+           target_terminal_ours_for_output ();
+           warning (_("Temporarily disabling breakpoints for unloaded shared library \"%s\""),
+                    solib->so_name);
          }
+       disabled_shlib_breaks = 1;
       }
   }
 }
 
+/* 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 = null_ptid;
-  update_global_location_list (1);
+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)
+{
+  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
+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)
 {
-  create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_vfork);
+  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
-create_exec_event_catchpoint (int tempflag, char *cond_string)
+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) ?
-    NULL : savestring (cond_string, strlen (cond_string));
-  b->thread = thread;
+
+  b->cond_string = (cond_string == NULL) ? NULL : xstrdup (cond_string);
+  b->thread = -1;
   b->addr_string = NULL;
   b->enable_state = bp_enabled;
   b->disposition = tempflag ? disp_del : disp_donttouch;
-  update_global_location_list (1);
+  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)
 {
@@ -4912,6 +5008,43 @@ set_momentary_breakpoint (struct symtab_and_line sal, struct frame_id frame_id,
   return b;
 }
 
+/* Make a deep copy of momentary breakpoint ORIG.  Returns NULL if
+   ORIG is NULL.  */
+
+struct breakpoint *
+clone_momentary_breakpoint (struct breakpoint *orig)
+{
+  struct breakpoint *copy;
+
+  /* If there's nothing to clone, then return nothing.  */
+  if (orig == NULL)
+    return NULL;
+
+  copy = set_raw_breakpoint_without_location (orig->type);
+  copy->loc = allocate_bp_location (copy);
+  set_breakpoint_location_function (copy->loc);
+
+  copy->loc->requested_address = orig->loc->requested_address;
+  copy->loc->address = orig->loc->address;
+  copy->loc->section = orig->loc->section;
+
+  if (orig->source_file == NULL)
+    copy->source_file = NULL;
+  else
+    copy->source_file = xstrdup (orig->source_file);
+
+  copy->line_number = orig->line_number;
+  copy->frame_id = orig->frame_id;
+  copy->thread = orig->thread;
+
+  copy->enable_state = bp_enabled;
+  copy->disposition = disp_donttouch;
+  copy->number = internal_breakpoint_number--;
+
+  update_global_location_list_nothrow (0);
+  return copy;
+}
+
 struct breakpoint *
 set_momentary_breakpoint_at_pc (CORE_ADDR pc, enum bptype type)
 {
@@ -4932,11 +5065,10 @@ static void
 mention (struct breakpoint *b)
 {
   int say_where = 0;
-  struct cleanup *old_chain, *ui_out_chain;
-  struct ui_stream *stb;
+  struct cleanup *ui_out_chain;
+  struct value_print_options opts;
 
-  stb = ui_out_stream_new (uiout);
-  old_chain = make_cleanup_ui_out_stream_delete (stb);
+  get_user_print_options (&opts);
 
   /* FIXME: This is misplaced; mention() is called by things (like
      hitting a watchpoint) other than breakpoint creation.  It should
@@ -4957,8 +5089,7 @@ mention (struct breakpoint *b)
        ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
        ui_out_field_int (uiout, "number", b->number);
        ui_out_text (uiout, ": ");
-       print_expression (b->exp, stb->stream);
-       ui_out_field_stream (uiout, "exp", stb);
+       ui_out_field_string (uiout, "exp", b->exp_string);
        do_cleanups (ui_out_chain);
        break;
       case bp_hardware_watchpoint:
@@ -4966,8 +5097,7 @@ mention (struct breakpoint *b)
        ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
        ui_out_field_int (uiout, "number", b->number);
        ui_out_text (uiout, ": ");
-       print_expression (b->exp, stb->stream);
-       ui_out_field_stream (uiout, "exp", stb);
+       ui_out_field_string (uiout, "exp", b->exp_string);
        do_cleanups (ui_out_chain);
        break;
       case bp_read_watchpoint:
@@ -4975,8 +5105,7 @@ mention (struct breakpoint *b)
        ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt");
        ui_out_field_int (uiout, "number", b->number);
        ui_out_text (uiout, ": ");
-       print_expression (b->exp, stb->stream);
-       ui_out_field_stream (uiout, "exp", stb);
+       ui_out_field_string (uiout, "exp", b->exp_string);
        do_cleanups (ui_out_chain);
        break;
       case bp_access_watchpoint:
@@ -4984,8 +5113,7 @@ mention (struct breakpoint *b)
        ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt");
        ui_out_field_int (uiout, "number", b->number);
        ui_out_text (uiout, ": ");
-       print_expression (b->exp, stb->stream);
-       ui_out_field_stream (uiout, "exp", stb);
+       ui_out_field_string (uiout, "exp", b->exp_string);
        do_cleanups (ui_out_chain);
        break;
       case bp_breakpoint:
@@ -5010,23 +5138,15 @@ 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);
+      case bp_tracepoint:
+       if (ui_out_is_mi_like_p (uiout))
+         {
+           say_where = 0;
+           break;
+         }
+       printf_filtered (_("Tracepoint"));
+       printf_filtered (_(" %d"), b->number);
+       say_where = 1;
        break;
 
       case bp_until:
@@ -5052,7 +5172,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);
@@ -5072,7 +5192,6 @@ mention (struct breakpoint *b)
 
        }
     }
-  do_cleanups (old_chain);
   if (ui_out_is_mi_like_p (uiout))
     return;
   printf_filtered ("\n");
@@ -5080,18 +5199,17 @@ mention (struct breakpoint *b)
 \f
 
 static struct bp_location *
-add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype,
+add_location_to_breakpoint (struct breakpoint *b,
                            const struct symtab_and_line *sal)
 {
   struct bp_location *loc, **tmp;
 
-  loc = allocate_bp_location (b, bptype);
+  loc = allocate_bp_location (b);
   for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
     ;
   *tmp = loc;
   loc->requested_address = sal->pc;
-  loc->address = adjust_breakpoint_address (loc->requested_address,
-                                           bptype);
+  loc->address = adjust_breakpoint_address (loc->requested_address, b->type);
   loc->section = sal->section;
 
   set_breakpoint_location_function (loc);
@@ -5109,19 +5227,32 @@ bp_loc_is_permanent (struct bp_location *loc)
   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)
-    return 1;
+    retval = 1;
 
-  return 0;
+  do_cleanups (cleanup);
+
+  return retval;
 }
 
 
@@ -5134,8 +5265,8 @@ static void
 create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
                   char *cond_string,
                   enum bptype type, enum bpdisp disposition,
-                  int thread, int ignore_count, 
-                  struct breakpoint_ops *ops, int from_tty)
+                  int thread, int task, int ignore_count, 
+                  struct breakpoint_ops *ops, int from_tty, int enabled)
 {
   struct breakpoint *b = NULL;
   int i;
@@ -5144,7 +5275,7 @@ create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
     {
       int i = hw_breakpoint_used_count ();
       int target_resources_ok = 
-       TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, 
+       target_can_use_hardware_watchpoint (bp_hardware_breakpoint, 
                                            i + 1, 0);
       if (target_resources_ok == 0)
        error (_("No hardware breakpoint support in the target."));
@@ -5166,17 +5297,18 @@ create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
          set_breakpoint_count (breakpoint_count + 1);
          b->number = breakpoint_count;
          b->thread = thread;
+         b->task = task;
   
          b->cond_string = cond_string;
          b->ignore_count = ignore_count;
-         b->enable_state = bp_enabled;
+         b->enable_state = enabled ? bp_enabled : bp_disabled;
          b->disposition = disposition;
 
          loc = b->loc;
        }
       else
        {
-         loc = add_location_to_breakpoint (b, type, &sal);
+         loc = add_location_to_breakpoint (b, &sal);
        }
 
       if (bp_loc_is_permanent (loc))
@@ -5204,7 +5336,8 @@ create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
 
 /* Remove element at INDEX_TO_REMOVE from SAL, shifting other
    elements to fill the void space.  */
-static void remove_sal (struct symtabs_and_lines *sal, int index_to_remove)
+static void
+remove_sal (struct symtabs_and_lines *sal, int index_to_remove)
 {
   int i = index_to_remove+1;
   int last_index = sal->nelts-1;
@@ -5229,7 +5362,7 @@ static void remove_sal (struct symtabs_and_lines *sal, int index_to_remove)
    line in all existing instantiations of 'foo'.
 
 */
-struct symtabs_and_lines
+static struct symtabs_and_lines
 expand_line_sal_maybe (struct symtab_and_line sal)
 {
   struct symtabs_and_lines expanded;
@@ -5343,8 +5476,9 @@ static void
 create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
                    char *cond_string,
                    enum bptype type, enum bpdisp disposition,
-                   int thread, int ignore_count, 
-                   struct breakpoint_ops *ops, int from_tty)
+                   int thread, int task, int ignore_count, 
+                   struct breakpoint_ops *ops, int from_tty,
+                   int enabled)
 {
   int i;
   for (i = 0; i < sals.nelts; ++i)
@@ -5354,10 +5488,8 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
 
       create_breakpoint (expanded, addr_string[i],
                         cond_string, type, disposition,
-                        thread, ignore_count, ops, from_tty);
+                        thread, task, ignore_count, ops, from_tty, enabled);
     }
-
-  update_global_location_list (1);
 }
 
 /* Parse ARG which is assumed to be a SAL specification possibly
@@ -5388,6 +5520,14 @@ parse_breakpoint_sals (char **address,
          sal.line = default_breakpoint_line;
          sal.symtab = default_breakpoint_symtab;
          sal.section = find_pc_overlay (sal.pc);
+
+         /* "break" without arguments is equivalent to "break *PC" where PC is
+            the default_breakpoint_address.  So make sure to set
+            sal.explicit_pc to prevent GDB from trying to expand the list of
+            sals to include all other instances with the same symtab and line.
+          */
+         sal.explicit_pc = 1;
+
          sals->sals[0] = sal;
          sals->nelts = 1;
        }
@@ -5461,7 +5601,7 @@ do_captured_parse_breakpoint (struct ui_out *ui, void *data)
    If no thread is found, *THREAD is set to -1.  */
 static void 
 find_condition_and_thread (char *tok, CORE_ADDR pc, 
-                          char **cond_string, int *thread)
+                          char **cond_string, int *thread, int *task)
 {
   *cond_string = NULL;
   *thread = -1;
@@ -5483,8 +5623,11 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
       
       if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
        {
+         struct expression *expr;
+
          tok = cond_start = end_tok + 1;
-         parse_exp_1 (&tok, block_for_pc (pc), 0);
+         expr = parse_exp_1 (&tok, block_for_pc (pc), 0);
+         xfree (expr);
          cond_end = tok;
          *cond_string = savestring (cond_start, 
                                     cond_end - cond_start);
@@ -5501,6 +5644,18 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
          if (!valid_thread_id (*thread))
            error (_("Unknown thread %d."), *thread);
        }
+      else if (toklen >= 1 && strncmp (tok, "task", toklen) == 0)
+       {
+         char *tmptok;
+
+         tok = end_tok + 1;
+         tmptok = tok;
+         *task = strtol (tok, &tok, 0);
+         if (tok == tmptok)
+           error (_("Junk after task keyword."));
+         if (!valid_task_id (*task))
+           error (_("Unknown task %d\n"), *task);
+       }
       else
        error (_("Junk at end of arguments."));
     }
@@ -5519,11 +5674,12 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
 static void
 break_command_really (char *arg, char *cond_string, int thread,
                      int parse_condition_and_thread,
-                     int tempflag, int hardwareflag, 
+                     int tempflag, int hardwareflag, int traceflag,
                      int ignore_count,
                      enum auto_boolean pending_break_support,
                      struct breakpoint_ops *ops,
-                     int from_tty)
+                     int from_tty,
+                     int enabled)
 {
   struct gdb_exception e;
   struct symtabs_and_lines sals;
@@ -5538,6 +5694,8 @@ break_command_really (char *arg, char *cond_string, int thread,
   int i;
   int pending = 0;
   int not_found = 0;
+  enum bptype type_wanted;
+  int task = 0;
 
   sals.sals = NULL;
   sals.nelts = 0;
@@ -5626,6 +5784,10 @@ break_command_really (char *arg, char *cond_string, int thread,
   if (!pending)
     breakpoint_sals_to_pc (&sals, addr_start);
 
+  type_wanted = (traceflag
+                ? bp_tracepoint
+                : (hardwareflag ? bp_hardware_breakpoint : bp_breakpoint));
+
   /* Verify that condition can be parsed, before setting any
      breakpoints.  Allocate a separate condition expression for each
      breakpoint. */
@@ -5639,7 +5801,8 @@ break_command_really (char *arg, char *cond_string, int thread,
                re-parse it in context of each sal.  */
             cond_string = NULL;
             thread = -1;
-            find_condition_and_thread (arg, sals.sals[0].pc, &cond_string, &thread);
+            find_condition_and_thread (arg, sals.sals[0].pc, &cond_string,
+                                       &thread, &task);
             if (cond_string)
                 make_cleanup (xfree, cond_string);
         }
@@ -5652,11 +5815,9 @@ break_command_really (char *arg, char *cond_string, int thread,
                 make_cleanup (xfree, cond_string);
             }
         }
-      create_breakpoints (sals, addr_string, cond_string,
-                         hardwareflag ? bp_hardware_breakpoint 
-                         : bp_breakpoint,
+      create_breakpoints (sals, addr_string, cond_string, type_wanted,
                          tempflag ? disp_del : disp_donttouch,
-                         thread, ignore_count, ops, from_tty);
+                         thread, task, ignore_count, ops, from_tty, enabled);
     }
   else
     {
@@ -5665,9 +5826,7 @@ break_command_really (char *arg, char *cond_string, int thread,
 
       make_cleanup (xfree, copy_arg);
 
-      b = set_raw_breakpoint_without_location (hardwareflag 
-                                              ? bp_hardware_breakpoint 
-                                              : bp_breakpoint);
+      b = set_raw_breakpoint_without_location (type_wanted);
       set_breakpoint_count (breakpoint_count + 1);
       b->number = breakpoint_count;
       b->thread = -1;
@@ -5677,8 +5836,8 @@ break_command_really (char *arg, char *cond_string, int thread,
       b->disposition = tempflag ? disp_del : disp_donttouch;
       b->condition_not_parsed = 1;
       b->ops = ops;
+      b->enable_state = enabled ? bp_enabled : bp_disabled;
 
-      update_global_location_list (1);
       mention (b);
     }
   
@@ -5690,6 +5849,9 @@ break_command_really (char *arg, char *cond_string, int thread,
   discard_cleanups (breakpoint_chain);
   /* But cleanup everything else. */
   do_cleanups (old_chain);
+
+  /* error call may happen here - have BREAKPOINT_CHAIN already discarded.  */
+  update_global_location_list (1);
 }
 
 /* Set a breakpoint. 
@@ -5707,11 +5869,12 @@ break_command_1 (char *arg, int flag, int from_tty)
 
   break_command_really (arg, 
                        NULL, 0, 1 /* parse arg */,
-                       tempflag, hardwareflag,
+                       tempflag, hardwareflag, 0 /* traceflag */,
                        0 /* Ignore count */,
                        pending_break_support, 
                        NULL /* breakpoint_ops */,
-                       from_tty);
+                       from_tty,
+                       1 /* enabled */);
 }
 
 
@@ -5719,15 +5882,15 @@ void
 set_breakpoint (char *address, char *condition,
                int hardwareflag, int tempflag,
                int thread, int ignore_count,
-               int pending)
+               int pending, int enabled)
 {
   break_command_really (address, condition, thread,
                        0 /* condition and thread are valid.  */,
-                       tempflag, hardwareflag,
+                       tempflag, hardwareflag, 0 /* traceflag */,
                        ignore_count,
                        pending 
                        ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
-                       NULL, 0);
+                       NULL, 0, enabled);
 }
 
 /* Adjust SAL to the first instruction past the function prologue.
@@ -5767,7 +5930,12 @@ resolve_sal_pc (struct symtab_and_line *sal)
       /* If this SAL corresponds to a breakpoint inserted using
          a line number, then skip the function prologue if necessary.  */
       if (sal->explicit_line)
-        skip_prologue_sal (sal);
+       {
+         /* Preserve the original line number.  */
+         int saved_line = sal->line;
+         skip_prologue_sal (sal);
+         sal->line = saved_line;
+       }
     }
 
   if (sal->section == 0 && sal->symtab != NULL)
@@ -5992,6 +6160,12 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
   exp_start = arg;
   exp = parse_exp_1 (&arg, 0, 0);
   exp_end = arg;
+  /* Remove trailing whitespace from the expression before saving it.
+     This makes the eventual display of the expression string a bit
+     prettier.  */
+  while (exp_end > exp_start && (exp_end[-1] == ' ' || exp_end[-1] == '\t'))
+    --exp_end;
+
   exp_valid_block = innermost_block;
   mark = value_mark ();
   fetch_watchpoint_value (exp, &val, NULL, NULL);
@@ -6030,7 +6204,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
     {
       i = hw_watchpoint_used_count (bp_type, &other_type_used);
       target_resources_ok = 
-       TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_type, i + mem_cnt, 
+       target_can_use_hardware_watchpoint (bp_type, i + mem_cnt, 
                                            other_type_used);
       if (target_resources_ok == 0 && bp_type != bp_hardware_watchpoint)
        error (_("Target does not support this type of hardware watchpoint."));
@@ -6168,7 +6342,7 @@ can_use_hardware_watchpoint (struct value *v)
                  CORE_ADDR vaddr = VALUE_ADDRESS (v) + value_offset (v);
                  int       len   = TYPE_LENGTH (value_type (v));
 
-                 if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (vaddr, len))
+                 if (!target_region_ok_for_hw_watchpoint (vaddr, len))
                    return 0;
                  else
                    found_memory_cnt++;
@@ -6421,121 +6595,47 @@ catch_fork_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
   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:
-     catch [v]fork
-     catch [v]fork if <cond>
-
-     First, check if there's an if clause. */
-  cond_string = ep_parse_optional_if_clause (&arg);
-
-  if ((*arg != '\0') && !isspace (*arg))
-    error (_("Junk at end of arguments."));
-
-  /* If this target supports it, create a fork or vfork catchpoint
-     and enable reporting of such events. */
-  switch (fork_kind)
-    {
-    case catch_fork_temporary:
-    case catch_fork_permanent:
-      create_fork_event_catchpoint (tempflag, cond_string);
-      break;
-    case catch_vfork_temporary:
-    case catch_vfork_permanent:
-      create_vfork_event_catchpoint (tempflag, cond_string);
-      break;
-    default:
-      error (_("unsupported or unknown fork kind; cannot catch it"));
-      break;
-    }
-}
-
-static void
-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:
-     catch exec
-     catch exec if <cond>
-
-     First, check if there's an if clause. */
-  cond_string = ep_parse_optional_if_clause (&arg);
-
-  if ((*arg != '\0') && !isspace (*arg))
-    error (_("Junk at end of arguments."));
-
-  /* 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 from_tty, struct cmd_list_element *command)
-{
-  int tempflag;
-  char *dll_pathname = NULL;
-  char *cond_string = NULL;
-
-  tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+  tempflag = (fork_kind == catch_fork_temporary
+             || fork_kind == catch_vfork_temporary);
 
   if (!arg)
     arg = "";
   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".
+     catch [v]fork
+     catch [v]fork if <cond>
 
-     First, check if there's an if clause.  If so, then there
-     cannot be a filename. */
+     First, check if there's an if clause. */
   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);
+  /* If this target supports it, create a fork or vfork catchpoint
+     and enable reporting of such events. */
+  switch (fork_kind)
+    {
+    case catch_fork_temporary:
+    case catch_fork_permanent:
+      create_fork_vfork_event_catchpoint (tempflag, cond_string,
+                                          &catch_fork_breakpoint_ops);
+      break;
+    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"));
+      break;
+    }
 }
 
 static void
-catch_unload_command_1 (char *arg, int from_tty,
-                       struct cmd_list_element *command)
+catch_exec_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
 {
   int tempflag;
-  char *dll_pathname = NULL;
   char *cond_string = NULL;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
@@ -6545,37 +6645,18 @@ catch_unload_command_1 (char *arg, int from_tty,
   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".
+     catch exec
+     catch exec if <cond>
 
-     First, check if there's an if clause.  If so, then there
-     cannot be a filename. */
+     First, check if there's an if clause. */
   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);
+  /* If this target supports it, create an exec catchpoint
+     and enable reporting of such events. */
+  create_catchpoint (tempflag, cond_string, &catch_exec_breakpoint_ops);
 }
 
 static enum print_stop_action
@@ -6590,7 +6671,7 @@ print_exception_catchpoint (struct breakpoint *b)
     breakpoint_adjustment_warning (b->loc->requested_address,
                                   b->loc->address,
                                   b->number, 1);
-  bp_temp = b->loc->owner->disposition == disp_del;
+  bp_temp = b->disposition == disp_del;
   ui_out_text (uiout, 
               bp_temp ? "Temporary catchpoint "
                       : "Catchpoint ");
@@ -6612,7 +6693,9 @@ print_exception_catchpoint (struct breakpoint *b)
 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)
@@ -6635,7 +6718,7 @@ print_mention_exception_catchpoint (struct breakpoint *b)
   int bp_temp;
   int bp_throw;
 
-  bp_temp = b->loc->owner->disposition == disp_del;
+  bp_temp = b->disposition == disp_del;
   bp_throw = strstr (b->addr_string, "throw") != NULL;
   ui_out_text (uiout, bp_temp ? _("Temporary catchpoint ")
                              : _("Catchpoint "));
@@ -6645,6 +6728,9 @@ print_mention_exception_catchpoint (struct breakpoint *b)
 }
 
 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
@@ -6663,10 +6749,11 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
 
   break_command_really (trigger_func_name, cond_string, -1,
                        0 /* condition and thread are valid.  */,
-                       tempflag, 0,
+                       tempflag, 0, 0,
                        0,
                        AUTO_BOOLEAN_TRUE /* pending */,
-                       &gnu_v3_exception_catchpoint_ops, from_tty);
+                       &gnu_v3_exception_catchpoint_ops, from_tty,
+                       1 /* enabled */);
 
   return 1;
 }
@@ -6985,7 +7072,17 @@ breakpoint_auto_delete (bpstat bs)
   }
 }
 
-/* If SHOULD_INSERT is true, do not insert any breakpoint locations
+/* A cleanup function which destroys a vector.  */
+
+static void
+do_vec_free (void *p)
+{
+  VEC(bp_location_p) **vec = p;
+  if (*vec)
+    VEC_free (bp_location_p, *vec);
+}
+
+/* If SHOULD_INSERT is false, 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
@@ -7007,11 +7104,12 @@ update_global_location_list (int should_insert)
   struct bp_location **next = &bp_location_chain;
   struct bp_location *loc;
   struct bp_location *loc2;
-  struct gdb_exception e;
   VEC(bp_location_p) *old_locations = NULL;
   int ret;
   int ix;
-  
+  struct cleanup *cleanups;
+
+  cleanups = make_cleanup (do_vec_free, &old_locations);
   /* Store old locations for future reference.  */
   for (loc = bp_location_chain; loc; loc = loc->global_next)
     VEC_safe_push (bp_location_p, old_locations, loc);
@@ -7105,8 +7203,8 @@ update_global_location_list (int should_insert)
        }
 
       if (!found_object)
-       {             
-         if (removed)
+       {
+         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,
@@ -7114,29 +7212,33 @@ update_global_location_list (int should_insert)
                 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, 
+                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 
+                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.  */     
+                which is usability issue, but not a correctness problem.  */
              loc->events_till_retirement = 3 * (thread_count () + 1);
              loc->owner = NULL;
-           }
 
-         free_bp_location (loc);
+             VEC_safe_push (bp_location_p, moribund_locations, loc);
+           }
+         else
+           free_bp_location (loc);
        }
     }
-    
+
   ALL_BREAKPOINTS (b)
     {
       check_duplicates (b);
     }
 
-  if (breakpoints_always_inserted_mode ()
-      && should_insert
-      && target_has_execution)
+  if (breakpoints_always_inserted_mode () && should_insert
+      && (target_has_execution
+         || (gdbarch_has_global_breakpoints (target_gdbarch))))
     insert_breakpoint_locations ();
+
+  do_cleanups (cleanups);
 }
 
 void
@@ -7237,10 +7339,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);
 
@@ -7401,7 +7499,7 @@ update_breakpoint_locations (struct breakpoint *b,
   for (i = 0; i < sals.nelts; ++i)
     {
       struct bp_location *new_loc = 
-       add_location_to_breakpoint (b, b->type, &(sals.sals[i]));
+       add_location_to_breakpoint (b, &(sals.sals[i]));
 
       /* Reparse conditions, they might contain references to the
         old symtab.  */
@@ -7428,9 +7526,7 @@ update_breakpoint_locations (struct breakpoint *b,
       if (sals.sals[i].symtab == NULL)
        b->source_file = NULL;
       else
-       b->source_file =
-         savestring (sals.sals[i].symtab->filename,
-                     strlen (sals.sals[i].symtab->filename));
+       b->source_file = xstrdup (sals.sals[i].symtab->filename);
 
       if (b->line_number == 0)
        b->line_number = sals.sals[i].line;
@@ -7500,7 +7596,7 @@ breakpoint_re_set_one (void *bint)
   char *s;
   enum enable_state save_enable;
   struct gdb_exception e;
-
+  struct cleanup *cleanups;
 
   switch (b->type)
     {
@@ -7510,8 +7606,7 @@ breakpoint_re_set_one (void *bint)
       return 0;
     case bp_breakpoint:
     case bp_hardware_breakpoint:
-    case bp_catch_load:
-    case bp_catch_unload:
+    case bp_tracepoint:
       if (b->addr_string == NULL)
        {
          /* Anything without a string can't be re-set. */
@@ -7564,17 +7659,20 @@ breakpoint_re_set_one (void *bint)
        {
          char *cond_string = 0;
          int thread = -1;
+         int task = 0;
+
          find_condition_and_thread (s, sals.sals[0].pc, 
-                                    &cond_string, &thread);
+                                    &cond_string, &thread, &task);
          if (cond_string)
            b->cond_string = cond_string;
          b->thread = thread;
+         b->task = task;
          b->condition_not_parsed = 0;
        }
       expanded = expand_line_sal_maybe (sals.sals[0]);
+      cleanups = make_cleanup (xfree, sals.sals);
       update_breakpoint_locations (b, expanded);
-
-      xfree (sals.sals);
+      do_cleanups (cleanups);
       break;
 
     case bp_watchpoint:
@@ -7611,9 +7709,7 @@ 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:
@@ -7650,9 +7746,13 @@ breakpoint_re_set_one (void *bint)
   return 0;
 }
 
-/* Re-set all breakpoints after symbols have been re-loaded.  */
+/* Re-set all breakpoints after symbols have been re-loaded.
+
+   If OBJFILE is non-null, create overlay break point only in OBJFILE
+   (speed optimization).  Otherwise rescan all loaded objfiles.  */
+
 void
-breakpoint_re_set (void)
+breakpoint_re_set_objfile (struct objfile *objfile)
 {
   struct breakpoint *b, *temp;
   enum language save_language;
@@ -7671,8 +7771,20 @@ breakpoint_re_set (void)
   }
   set_language (save_language);
   input_radix = save_input_radix;
-  
-  create_overlay_event_breakpoint ("_ovly_debug_event");
+
+  if (objfile == NULL)
+    ALL_OBJFILES (objfile)
+      create_overlay_event_breakpoint ("_ovly_debug_event", objfile);
+  else
+    create_overlay_event_breakpoint ("_ovly_debug_event", objfile);
+}
+
+/* Re-set all breakpoints after symbols have been re-loaded.  */
+
+void
+breakpoint_re_set (void)
+{
+  breakpoint_re_set_objfile (NULL);
 }
 \f
 /* Reset the thread number of this breakpoint:
@@ -7725,14 +7837,11 @@ set_ignore_count (int bptnum, int count, int from_tty)
   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.  */
@@ -7882,11 +7991,8 @@ 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_tracepoint:
+      case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
       case bp_hardware_watchpoint:
@@ -7918,7 +8024,7 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
       int i;
       i = hw_breakpoint_used_count ();
       target_resources_ok = 
-       TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, 
+       target_can_use_hardware_watchpoint (bp_hardware_breakpoint, 
                                            i + 1, 0);
       if (target_resources_ok == 0)
        error (_("No hardware breakpoint support in the target."));
@@ -7931,56 +8037,18 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
       bpt->type == bp_read_watchpoint || 
       bpt->type == bp_access_watchpoint)
     {
-      struct frame_id saved_frame_id;
-      
-      saved_frame_id = get_frame_id (get_selected_frame (NULL));
-      if (bpt->exp_valid_block != NULL)
+      struct gdb_exception e;
+
+      TRY_CATCH (e, RETURN_MASK_ALL)
        {
-         struct frame_info *fr =
-           fr = frame_find_by_id (bpt->watchpoint_frame);
-         if (fr == NULL)
-           {
-             printf_filtered (_("\
-Cannot enable watchpoint %d because the block in which its expression\n\
-is valid is not currently in scope.\n"), bpt->number);
-             return;
-           }
-         select_frame (fr);
+         update_watchpoint (bpt, 1 /* reparse */);
        }
-      
-      if (bpt->val)
-       value_free (bpt->val);
-      mark = value_mark ();
-      fetch_watchpoint_value (bpt->exp, &bpt->val, NULL, NULL);
-      if (bpt->val)
-       release_value (bpt->val);
-      bpt->val_valid = 1;
-
-      if (bpt->type == bp_hardware_watchpoint ||
-         bpt->type == bp_read_watchpoint ||
-         bpt->type == bp_access_watchpoint)
+      if (e.reason < 0)
        {
-         int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
-         int mem_cnt = can_use_hardware_watchpoint (bpt->val);
-         
-         /* Hack around 'unused var' error for some targets here */
-         (void) mem_cnt, (void) i;
-         target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
-                                                                   bpt->type, i + mem_cnt, other_type_used);
-         /* we can consider of type is bp_hardware_watchpoint, convert to 
-            bp_watchpoint in the following condition */
-         if (target_resources_ok < 0)
-           {
-             printf_filtered (_("\
-Cannot enable watchpoint %d because target watch resources\n\
-have been allocated for other watchpoints.\n"), bpt->number);
-             value_free_to_mark (mark);
-             return;
-           }
+         exception_fprintf (gdb_stderr, e, _("Cannot enable watchpoint %d: "),
+                            bpt->number);
+         return;
        }
-      
-      select_frame (frame_find_by_id (saved_frame_id));
-      value_free_to_mark (mark);
     }
 
   if (bpt->enable_state != bp_permanent)
@@ -8016,11 +8084,8 @@ 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_tracepoint:
+      case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
       case bp_hardware_watchpoint:
@@ -8203,6 +8268,324 @@ single_step_breakpoint_inserted_here_p (CORE_ADDR pc)
   return 0;
 }
 
+/* Tracepoint-specific operations.  */
+
+/* Set tracepoint count to NUM.  */
+static void
+set_tracepoint_count (int num)
+{
+  tracepoint_count = num;
+  set_internalvar (lookup_internalvar ("tpnum"),
+                  value_from_longest (builtin_type_int32, (LONGEST) num));
+}
+
+void
+trace_command (char *arg, int from_tty)
+{
+  break_command_really (arg, 
+                       NULL, 0, 1 /* parse arg */,
+                       0 /* tempflag */, 0 /* hardwareflag */,
+                       1 /* traceflag */,
+                       0 /* Ignore count */,
+                       pending_break_support, 
+                       NULL,
+                       from_tty,
+                       1 /* enabled */);
+  set_tracepoint_count (breakpoint_count);
+}
+
+/* Print information on tracepoint number TPNUM_EXP, or all if
+   omitted.  */
+
+static void
+tracepoints_info (char *tpnum_exp, int from_tty)
+{
+  struct breakpoint *b;
+  int tps_to_list = 0;
+
+  /* In the no-arguments case, say "No tracepoints" if none found.  */
+  if (tpnum_exp == 0)
+    {
+      ALL_TRACEPOINTS (b)
+      {
+       if (b->number >= 0)
+         {
+           tps_to_list = 1;
+           break;
+         }
+      }
+      if (!tps_to_list)
+       {
+         ui_out_message (uiout, 0, "No tracepoints.\n");
+         return;
+       }
+    }
+
+  /* Otherwise be the same as "info break".  */
+  breakpoints_info (tpnum_exp, from_tty);
+}
+
+/* The 'enable trace' command enables tracepoints.  
+   Not supported by all targets.  */
+static void
+enable_trace_command (char *args, int from_tty)
+{
+  enable_command (args, from_tty);
+}
+
+/* The 'disable trace' command disables tracepoints.  
+   Not supported by all targets.  */
+static void
+disable_trace_command (char *args, int from_tty)
+{
+  disable_command (args, from_tty);
+}
+
+/* Remove a tracepoint (or all if no argument) */
+static void
+delete_trace_command (char *arg, int from_tty)
+{
+  struct breakpoint *b, *temp;
+
+  dont_repeat ();
+
+  if (arg == 0)
+    {
+      int breaks_to_delete = 0;
+
+      /* Delete all breakpoints if no argument.
+         Do not delete internal or call-dummy breakpoints, these
+         have to be deleted with an explicit breakpoint number argument.  */
+      ALL_TRACEPOINTS (b)
+      {
+       if (b->number >= 0)
+         {
+           breaks_to_delete = 1;
+           break;
+         }
+      }
+
+      /* Ask user only if there are some breakpoints to delete.  */
+      if (!from_tty
+         || (breaks_to_delete && query (_("Delete all tracepoints? "))))
+       {
+         ALL_BREAKPOINTS_SAFE (b, temp)
+         {
+           if (b->type == bp_tracepoint &&
+               b->number >= 0)
+             delete_breakpoint (b);
+         }
+       }
+    }
+  else
+    map_breakpoint_numbers (arg, delete_breakpoint);
+}
+
+/* Set passcount for tracepoint.
+
+   First command argument is passcount, second is tracepoint number.
+   If tracepoint number omitted, apply to most recently defined.
+   Also accepts special argument "all".  */
+
+static void
+trace_pass_command (char *args, int from_tty)
+{
+  struct breakpoint *t1 = (struct breakpoint *) -1, *t2;
+  unsigned int count;
+  int all = 0;
+
+  if (args == 0 || *args == 0)
+    error (_("passcount command requires an argument (count + optional TP num)"));
+
+  count = strtoul (args, &args, 10);   /* Count comes first, then TP num. */
+
+  while (*args && isspace ((int) *args))
+    args++;
+
+  if (*args && strncasecmp (args, "all", 3) == 0)
+    {
+      args += 3;                       /* Skip special argument "all".  */
+      all = 1;
+      if (*args)
+       error (_("Junk at end of arguments."));
+    }
+  else
+    t1 = get_tracepoint_by_number (&args, 1, 1);
+
+  do
+    {
+      if (t1)
+       {
+         ALL_TRACEPOINTS (t2)
+           if (t1 == (struct breakpoint *) -1 || t1 == t2)
+             {
+               t2->pass_count = count;
+               observer_notify_tracepoint_modified (t2->number);
+               if (from_tty)
+                 printf_filtered (_("Setting tracepoint %d's passcount to %d\n"),
+                                  t2->number, count);
+             }
+         if (! all && *args)
+           t1 = get_tracepoint_by_number (&args, 1, 0);
+       }
+    }
+  while (*args);
+}
+
+struct breakpoint *
+get_tracepoint (int num)
+{
+  struct breakpoint *t;
+
+  ALL_TRACEPOINTS (t)
+    if (t->number == num)
+      return t;
+
+  return NULL;
+}
+
+/* Utility: parse a tracepoint number and look it up in the list.
+   If MULTI_P is true, there might be a range of tracepoints in ARG.
+   if OPTIONAL_P is true, then if the argument is missing, the most
+   recent tracepoint (tracepoint_count) is returned.  */
+struct breakpoint *
+get_tracepoint_by_number (char **arg, int multi_p, int optional_p)
+{
+  extern int tracepoint_count;
+  struct breakpoint *t;
+  int tpnum;
+  char *instring = arg == NULL ? NULL : *arg;
+
+  if (arg == NULL || *arg == NULL || ! **arg)
+    {
+      if (optional_p)
+       tpnum = tracepoint_count;
+      else
+       error_no_arg (_("tracepoint number"));
+    }
+  else
+    tpnum = multi_p ? get_number_or_range (arg) : get_number (arg);
+
+  if (tpnum <= 0)
+    {
+      if (instring && *instring)
+       printf_filtered (_("bad tracepoint number at or near '%s'\n"), 
+                        instring);
+      else
+       printf_filtered (_("Tracepoint argument missing and no previous tracepoint\n"));
+      return NULL;
+    }
+
+  ALL_TRACEPOINTS (t)
+    if (t->number == tpnum)
+    {
+      return t;
+    }
+
+  /* FIXME: if we are in the middle of a range we don't want to give
+     a message.  The current interface to get_number_or_range doesn't
+     allow us to discover this.  */
+  printf_unfiltered ("No tracepoint number %d.\n", tpnum);
+  return NULL;
+}
+
+/* save-tracepoints command */
+static void
+tracepoint_save_command (char *args, int from_tty)
+{
+  struct breakpoint *tp;
+  int any_tp = 0;
+  struct action_line *line;
+  FILE *fp;
+  char *i1 = "    ", *i2 = "      ";
+  char *indent, *actionline, *pathname;
+  char tmp[40];
+  struct cleanup *cleanup;
+
+  if (args == 0 || *args == 0)
+    error (_("Argument required (file name in which to save tracepoints)"));
+
+  /* See if we have anything to save.  */
+  ALL_TRACEPOINTS (tp)
+  {
+    any_tp = 1;
+    break;
+  }
+  if (!any_tp)
+    {
+      warning (_("save-tracepoints: no tracepoints to save."));
+      return;
+    }
+
+  pathname = tilde_expand (args);
+  cleanup = make_cleanup (xfree, pathname);
+  if (!(fp = fopen (pathname, "w")))
+    error (_("Unable to open file '%s' for saving tracepoints (%s)"),
+          args, safe_strerror (errno));
+  make_cleanup_fclose (fp);
+  
+  ALL_TRACEPOINTS (tp)
+  {
+    if (tp->addr_string)
+      fprintf (fp, "trace %s\n", tp->addr_string);
+    else
+      {
+       sprintf_vma (tmp, tp->loc->address);
+       fprintf (fp, "trace *0x%s\n", tmp);
+      }
+
+    if (tp->pass_count)
+      fprintf (fp, "  passcount %d\n", tp->pass_count);
+
+    if (tp->actions)
+      {
+       fprintf (fp, "  actions\n");
+       indent = i1;
+       for (line = tp->actions; line; line = line->next)
+         {
+           struct cmd_list_element *cmd;
+
+           QUIT;               /* allow user to bail out with ^C */
+           actionline = line->action;
+           while (isspace ((int) *actionline))
+             actionline++;
+
+           fprintf (fp, "%s%s\n", indent, actionline);
+           if (*actionline != '#')     /* skip for comment lines */
+             {
+               cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
+               if (cmd == 0)
+                 error (_("Bad action list item: %s"), actionline);
+               if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
+                 indent = i2;
+               else if (cmd_cfunc_eq (cmd, end_actions_pseudocommand))
+                 indent = i1;
+             }
+         }
+      }
+  }
+  do_cleanups (cleanup);
+  if (from_tty)
+    printf_filtered (_("Tracepoints saved to file '%s'.\n"), args);
+  return;
+}
+
+/* Create a vector of all tracepoints.  */
+
+VEC(breakpoint_p) *
+all_tracepoints ()
+{
+  VEC(breakpoint_p) *tp_vec = 0;
+  struct breakpoint *tp;
+
+  ALL_TRACEPOINTS (tp)
+  {
+    VEC_safe_push (breakpoint_p, tp_vec, tp);
+  }
+
+  return tp_vec;
+}
+
 \f
 /* This help string is used for the break, hbreak, tbreak and thbreak commands.
    It is defined as a macro to prevent duplication.
@@ -8265,6 +8648,8 @@ _initialize_breakpoint (void)
      before a breakpoint is set.  */
   breakpoint_count = 0;
 
+  tracepoint_count = 0;
+
   add_com ("ignore", class_breakpoint, ignore_command, _("\
 Set ignore-count of breakpoint number N to COUNT.\n\
 Usage is `ignore N COUNT'."));
@@ -8543,18 +8928,6 @@ With an argument, catch only exceptions with the given name."),
                     catch_exec_command_1,
                     CATCH_PERMANENT,
                     CATCH_TEMPORARY);
-  add_catch_command ("load", _("\
-Catch library loads.\n\
-With an argument, catch only loads of that library."),
-                    catch_load_command_1,
-                    CATCH_PERMANENT,
-                    CATCH_TEMPORARY);
-  add_catch_command ("unload", _("\
-Catch library unloads.\n\
-With an argument, catch only unloads of that library."),
-                    catch_unload_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."),
@@ -8606,6 +8979,58 @@ hardware.)"),
 
   can_use_hw_watchpoints = 1;
 
+  /* Tracepoint manipulation commands.  */
+
+  c = add_com ("trace", class_breakpoint, trace_command, _("\
+Set a tracepoint at specified line or function.\n\
+\n"
+BREAK_ARGS_HELP ("trace") "\n\
+Do \"help tracepoints\" for info on other tracepoint commands."));
+  set_cmd_completer (c, location_completer);
+
+  add_com_alias ("tp", "trace", class_alias, 0);
+  add_com_alias ("tr", "trace", class_alias, 1);
+  add_com_alias ("tra", "trace", class_alias, 1);
+  add_com_alias ("trac", "trace", class_alias, 1);
+
+  add_info ("tracepoints", tracepoints_info, _("\
+Status of tracepoints, or tracepoint number NUMBER.\n\
+Convenience variable \"$tpnum\" contains the number of the\n\
+last tracepoint set."));
+
+  add_info_alias ("tp", "tracepoints", 1);
+
+  add_cmd ("tracepoints", class_trace, delete_trace_command, _("\
+Delete specified tracepoints.\n\
+Arguments are tracepoint numbers, separated by spaces.\n\
+No argument means delete all tracepoints."),
+          &deletelist);
+
+  c = add_cmd ("tracepoints", class_trace, disable_trace_command, _("\
+Disable specified tracepoints.\n\
+Arguments are tracepoint numbers, separated by spaces.\n\
+No argument means disable all tracepoints."),
+          &disablelist);
+  deprecate_cmd (c, "disable");
+
+  c = add_cmd ("tracepoints", class_trace, enable_trace_command, _("\
+Enable specified tracepoints.\n\
+Arguments are tracepoint numbers, separated by spaces.\n\
+No argument means enable all tracepoints."),
+          &enablelist);
+  deprecate_cmd (c, "enable");
+
+  add_com ("passcount", class_trace, trace_pass_command, _("\
+Set the passcount for a tracepoint.\n\
+The trace will end when the tracepoint has been passed 'count' times.\n\
+Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
+if TPNUM is omitted, passcount refers to the last tracepoint defined."));
+
+  c = add_com ("save-tracepoints", class_trace, tracepoint_save_command, _("\
+Save current tracepoint definitions as a script.\n\
+Use the 'source' command in another debug session to restore them."));
+  set_cmd_completer (c, filename_completer);
+
   add_prefix_cmd ("breakpoint", class_maintenance, set_breakpoint_cmd, _("\
 Breakpoint specific settings\n\
 Configure various breakpoint-specific variables such as\n\
@@ -8664,4 +9089,6 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
                           &breakpoint_show_cmdlist);
   
   automatic_hardware_breakpoints = 1;
+
+  observer_attach_about_to_proceed (breakpoint_about_to_proceed);
 }
This page took 0.069356 seconds and 4 git commands to generate.