* breakpoint.c (update_watchpoint, _initialize_breakpoint): Remove
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index 2efb76683afbd25e3a2cfdee4811950fe4aa7ebb..ea8f8abd2bcaf10589c8eef3e4db26290eb26020 100644 (file)
@@ -61,6 +61,7 @@
 #include "valprint.h"
 #include "jit.h"
 #include "xml-syscall.h"
+#include "parser-defs.h"
 
 /* readline include files */
 #include "readline/readline.h"
@@ -195,6 +196,8 @@ static void tcatch_command (char *arg, int from_tty);
 
 static void ep_skip_leading_whitespace (char **s);
 
+static void detach_single_step_breakpoints (void);
+
 static int single_step_breakpoint_inserted_here_p (struct address_space *,
                                                   CORE_ADDR pc);
 
@@ -206,6 +209,9 @@ static void update_global_location_list (int);
 
 static void update_global_location_list_nothrow (int);
 
+static int bpstat_remove_bp_location_callback (struct thread_info *th,
+                                              void *data);
+
 static int is_hardware_watchpoint (const struct breakpoint *bpt);
 
 static int is_watchpoint (const struct breakpoint *bpt);
@@ -224,6 +230,11 @@ static void disable_trace_command (char *, int);
 
 static void trace_pass_command (char *, int);
 
+/* Assuming we're creating a static tracepoint, does S look like a
+   static tracepoint marker spec ("-m MARKER_ID")?  */
+#define is_marker_spec(s)                                              \
+  (strncmp (s, "-m", 2) == 0 && ((s)[2] == ' ' || (s)[2] == '\t'))
+
 /* A reference-counted struct command_line.  This lets multiple
    breakpoints share a single command list.  */
 struct counted_command_line
@@ -252,6 +263,7 @@ bpdisp_text (enum bpdisp disp)
   /* NOTE: the following values are a part of MI protocol and represent
      values of 'disp' field returned when inferior stops at a breakpoint.  */
   static char *bpdisps[] = {"del", "dstp", "dis", "keep"};
+
   return bpdisps[(int) disp];
 }
 
@@ -416,6 +428,10 @@ static int prev_breakpoint_count;
 
 static int tracepoint_count;
 
+static struct cmd_list_element *breakpoint_set_cmdlist;
+static struct cmd_list_element *breakpoint_show_cmdlist;
+static struct cmd_list_element *save_cmdlist;
+
 /* Return whether a breakpoint is an active enabled breakpoint.  */
 static int
 breakpoint_enabled (struct breakpoint *b)
@@ -474,6 +490,7 @@ alloc_counted_command_line (struct command_line *commands)
 {
   struct counted_command_line *result
     = xmalloc (sizeof (struct counted_command_line));
+
   result->refc = 1;
   result->commands = commands;
   return result;
@@ -709,6 +726,62 @@ get_breakpoint (int num)
 }
 
 \f
+
+void
+set_breakpoint_condition (struct breakpoint *b, char *exp,
+                         int from_tty)
+{
+  struct bp_location *loc = b->loc;
+
+  for (; loc; loc = loc->next)
+    {
+      xfree (loc->cond);
+      loc->cond = NULL;
+    }
+  xfree (b->cond_string);
+  b->cond_string = NULL;
+  xfree (b->cond_exp);
+  b->cond_exp = NULL;
+
+  if (*exp == 0)
+    {
+      if (from_tty)
+       printf_filtered (_("Breakpoint %d now unconditional.\n"), b->number);
+    }
+  else
+    {
+      char *arg = exp;
+
+      /* I don't know if it matters whether this is the string the user
+        typed in or the decompiled expression.  */
+      b->cond_string = xstrdup (arg);
+      b->condition_not_parsed = 0;
+
+      if (is_watchpoint (b))
+       {
+         innermost_block = NULL;
+         arg = exp;
+         b->cond_exp = parse_exp_1 (&arg, 0, 0);
+         if (*arg)
+           error (_("Junk at end of expression"));
+         b->cond_exp_valid_block = innermost_block;
+       }
+      else
+       {
+         for (loc = b->loc; loc; loc = loc->next)
+           {
+             arg = exp;
+             loc->cond =
+               parse_exp_1 (&arg, block_for_pc (loc->address), 0);
+             if (*arg)
+               error (_("Junk at end of expression"));
+           }
+       }
+    }
+  breakpoints_changed ();
+  observer_notify_breakpoint_modified (b->number);
+}
+
 /* condition N EXP -- set break condition of breakpoint N to EXP.  */
 
 static void
@@ -729,53 +802,7 @@ condition_command (char *arg, int from_tty)
   ALL_BREAKPOINTS (b)
     if (b->number == bnum)
       {
-       struct bp_location *loc = b->loc;
-       for (; loc; loc = loc->next)
-         {
-           xfree (loc->cond);
-           loc->cond = NULL;
-         }
-       xfree (b->cond_string);
-       b->cond_string = NULL;
-       xfree (b->cond_exp);
-       b->cond_exp = NULL;
-
-       if (*p == 0)
-         {
-           if (from_tty)
-             printf_filtered (_("Breakpoint %d now unconditional.\n"), bnum);
-         }
-       else
-         {
-           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 = xstrdup (arg);
-           b->condition_not_parsed = 0;
-
-           if (is_watchpoint (b))
-             {
-               innermost_block = NULL;
-               arg = p;
-               b->cond_exp = parse_exp_1 (&arg, 0, 0);
-               if (*arg)
-                 error (_("Junk at end of expression"));
-               b->cond_exp_valid_block = innermost_block;
-             }
-           else
-             {
-               for (loc = b->loc; loc; loc = loc->next)
-                 {
-                   arg = p;
-                   loc->cond =
-                     parse_exp_1 (&arg, block_for_pc (loc->address), 0);
-                   if (*arg)
-                     error (_("Junk at end of expression"));
-                 }
-             }
-         }
-       breakpoints_changed ();
-       observer_notify_breakpoint_modified (b->number);
+       set_breakpoint_condition (b, p, from_tty);
        return;
       }
 
@@ -790,6 +817,7 @@ static void
 check_no_tracepoint_commands (struct command_line *commands)
 {
   struct command_line *c;
+
   for (c = commands; c; c = c->next)
     {
       int i;
@@ -816,7 +844,9 @@ check_no_tracepoint_commands (struct command_line *commands)
 int
 is_tracepoint (const struct breakpoint *b)
 {
-  return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint);
+  return (b->type == bp_tracepoint
+         || b->type == bp_fast_tracepoint
+         || b->type == bp_static_tracepoint);
 }
   
 /* A helper function that validsates that COMMANDS are valid for a
@@ -837,11 +867,14 @@ validate_commands_for_breakpoint (struct breakpoint *b,
       struct command_line *while_stepping = 0;
       for (c = commands; c; c = c->next)
        {
-         char *l = c->line;
          if (c->control_type == while_stepping_control)
            {
              if (b->type == bp_fast_tracepoint)
-               error (_("The 'while-stepping' command cannot be used for fast tracepoint"));
+               error (_("\
+The 'while-stepping' command cannot be used for fast tracepoint"));
+             else if (b->type == bp_static_tracepoint)
+               error (_("\
+The 'while-stepping' command cannot be used for static tracepoint"));
 
              if (while_stepping)
                error (_("The 'while-stepping' command can be used only once"));
@@ -857,7 +890,6 @@ validate_commands_for_breakpoint (struct breakpoint *b,
          c2 = while_stepping->body_list[0];
          for (; c2; c2 = c2->next)
            {
-             char *l = c2->line;
              if (c2->control_type == while_stepping_control)
                error (_("The 'while-stepping' command cannot be nested"));
            }
@@ -869,6 +901,27 @@ validate_commands_for_breakpoint (struct breakpoint *b,
     }
 }
 
+/* Return a vector of all the static tracepoints set at ADDR.  The
+   caller is responsible for releasing the vector.  */
+
+VEC(breakpoint_p) *
+static_tracepoints_here (CORE_ADDR addr)
+{
+  struct breakpoint *b;
+  VEC(breakpoint_p) *found = 0;
+  struct bp_location *loc;
+
+  ALL_BREAKPOINTS (b)
+    if (b->type == bp_static_tracepoint)
+      {
+       for (loc = b->loc; loc; loc = loc->next)
+         if (loc->address == addr)
+           VEC_safe_push(breakpoint_p, found, b);
+      }
+
+  return found;
+}
+
 /* Set the command list of B to COMMANDS.  If breakpoint is tracepoint,
    validate that only allowed commands are included.
 */
@@ -888,6 +941,7 @@ void
 check_tracepoint_command (char *line, void *closure)
 {
   struct breakpoint *b = closure;
+
   validate_actionline (&line, b);
 }
 
@@ -1093,6 +1147,7 @@ breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr, LONGEST len)
     int bp_size = 0;
     int bptoffset = 0;
 
+    /* bp_location array has B->OWNER always non-NULL.  */
     if (b->owner->type == bp_none)
       warning (_("reading through apparently deleted breakpoint #%d?"),
               b->owner->number);
@@ -1152,7 +1207,6 @@ static void
 insert_catchpoint (struct ui_out *uo, void *args)
 {
   struct breakpoint *b = (struct breakpoint *) args;
-  int val = -1;
 
   gdb_assert (b->type == bp_catchpoint);
   gdb_assert (b->ops != NULL && b->ops->insert != NULL);
@@ -1329,9 +1383,7 @@ update_watchpoint (struct breakpoint *b, int reparse)
 {
   int within_current_scope;
   struct frame_id saved_frame_id;
-  struct bp_location *loc;
   int frame_saved;
-  bpstat bs;
 
   /* If this is a local watchpoint, we only want to check if the
      watchpoint frame is in scope if the current thread is the thread
@@ -1532,7 +1584,7 @@ update_watchpoint (struct breakpoint *b, int reparse)
   else if (!within_current_scope)
     {
       printf_filtered (_("\
-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)
@@ -1555,7 +1607,7 @@ in which its expression is valid.\n"),
 static int
 should_be_inserted (struct bp_location *bpt)
 {
-  if (!breakpoint_enabled (bpt->owner))
+  if (bpt->owner == NULL || !breakpoint_enabled (bpt->owner))
     return 0;
 
   if (bpt->owner->disposition == disp_del_at_next_stop)
@@ -1632,7 +1684,6 @@ insert_bp_location (struct bp_location *bpt,
            {
              if (automatic_hardware_breakpoints)
                {
-                 int changed = 0;
                  enum bp_loc_type new_type;
                  
                  if (mr->attrib.mode != MEM_RW)
@@ -1643,6 +1694,7 @@ insert_bp_location (struct bp_location *bpt,
                  if (new_type != bpt->loc_type)
                    {
                      static int said = 0;
+
                      bpt->loc_type = new_type;
                      if (!said)
                        {
@@ -1858,6 +1910,7 @@ breakpoint_program_space_exit (struct program_space *pspace)
 
       if (loc->pspace == pspace)
        {
+         /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL.  */
          if (loc->owner->loc == loc)
            loc->owner->loc = loc->next;
          else
@@ -1923,14 +1976,12 @@ insert_breakpoint_locations (void)
 
   ALL_BP_LOCATIONS (b, bp_tmp)
     {
-      struct thread_info *tp;
-      CORE_ADDR last_addr;
-
       if (!should_be_inserted (b) || b->inserted)
        continue;
 
       /* There is no point inserting thread-specific breakpoints if the
-        thread no longer exists.  */
+        thread no longer exists.  ALL_BP_LOCATIONS bp_location has B->OWNER
+        always non-NULL.  */
       if (b->owner->thread != -1
          && !valid_thread_id (b->owner->thread))
        continue;
@@ -2366,6 +2417,10 @@ detach_breakpoints (int pid)
     if (b->inserted)
       val |= remove_breakpoint_1 (b, mark_inserted);
   }
+
+  /* Detach single-step breakpoints as well.  */
+  detach_single_step_breakpoints ();
+
   do_cleanups (old_chain);
   return val;
 }
@@ -2380,7 +2435,9 @@ static int
 remove_breakpoint_1 (struct bp_location *b, insertion_state_t is)
 {
   int val;
-  struct cleanup *old_chain;
+
+  /* B is never in moribund_locations by our callers.  */
+  gdb_assert (b->owner != NULL);
 
   if (b->owner->enable_state == bp_permanent)
     /* Permanent breakpoints cannot be inserted or removed.  */
@@ -2467,9 +2524,6 @@ remove_breakpoint_1 (struct bp_location *b, insertion_state_t is)
     }
   else if (b->loc_type == bp_loc_hardware_watchpoint)
     {
-      struct value *v;
-      struct value *n;
-
       b->inserted = (is == mark_inserted);
       val = target_remove_watchpoint (b->address, b->length, 
                                      b->watchpoint_type);
@@ -2500,6 +2554,9 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is)
   int ret;
   struct cleanup *old_chain;
 
+  /* B is never in moribund_locations by our callers.  */
+  gdb_assert (b->owner != NULL);
+
   if (b->owner->enable_state == bp_permanent)
     /* Permanent breakpoints cannot be inserted or removed.  */
     return 0;
@@ -2557,6 +2614,7 @@ breakpoint_init_inferior (enum inf_context context)
 
   ALL_BP_LOCATIONS (bpt, bptp_tmp)
   {
+    /* ALL_BP_LOCATIONS bp_location has BPT->OWNER always non-NULL.  */
     if (bpt->pspace == pspace
        && bpt->owner->enable_state != bp_permanent)
       bpt->inserted = 0;
@@ -2654,6 +2712,7 @@ breakpoint_here_p (struct address_space *aspace, CORE_ADDR pc)
          && bpt->loc_type != bp_loc_hardware_breakpoint)
        continue;
 
+      /* ALL_BP_LOCATIONS bp_location has BPT->OWNER always non-NULL.  */
       if ((breakpoint_enabled (bpt->owner)
           || bpt->owner->enable_state == bp_permanent)
          && breakpoint_address_match (bpt->pspace->aspace, bpt->address,
@@ -2742,7 +2801,6 @@ int
 software_breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc)
 {
   struct bp_location *bpt, **bptp_tmp;
-  int any_breakpoint_here = 0;
 
   ALL_BP_LOCATIONS (bpt, bptp_tmp)
     {
@@ -2819,6 +2877,7 @@ breakpoint_thread_match (struct address_space *aspace, CORE_ADDR pc,
          && bpt->loc_type != bp_loc_hardware_breakpoint)
        continue;
 
+      /* ALL_BP_LOCATIONS bp_location has BPT->OWNER always non-NULL.  */
       if (!breakpoint_enabled (bpt->owner)
          && bpt->owner->enable_state != bp_permanent)
        continue;
@@ -3185,6 +3244,11 @@ print_it_typical (bpstat bs)
   if (bs->breakpoint_at == NULL)
     return PRINT_UNKNOWN;
   bl = bs->breakpoint_at;
+
+  /* bl->owner can be NULL if it was a momentary breakpoint
+     which has since been placed into moribund_locations.  */
+  if (bl->owner == NULL)
+    return PRINT_UNKNOWN;
   b = bl->owner;
 
   stb = ui_out_stream_new (uiout);
@@ -3448,6 +3512,7 @@ breakpoint_cond_eval (void *exp)
 {
   struct value *mark = value_mark ();
   int i = !value_true (evaluate_expression ((struct expression *) exp));
+
   value_free_to_mark (mark);
   return i;
 }
@@ -3485,9 +3550,7 @@ watchpoints_triggered (struct target_waitstatus *ws)
       /* We were not stopped by a watchpoint.  Mark all watchpoints
         as not triggered.  */
       ALL_BREAKPOINTS (b)
-       if (b->type == bp_hardware_watchpoint
-           || b->type == bp_read_watchpoint
-           || b->type == bp_access_watchpoint)
+       if (is_hardware_watchpoint (b))
          b->watchpoint_triggered = watch_triggered_no;
 
       return 0;
@@ -3498,9 +3561,7 @@ watchpoints_triggered (struct target_waitstatus *ws)
       /* We were stopped by a watchpoint, but we don't know where.
         Mark all watchpoints as unknown.  */
       ALL_BREAKPOINTS (b)
-       if (b->type == bp_hardware_watchpoint
-           || b->type == bp_read_watchpoint
-           || b->type == bp_access_watchpoint)
+       if (is_hardware_watchpoint (b))
          b->watchpoint_triggered = watch_triggered_unknown;
 
       return stopped_by_watchpoint;
@@ -3511,12 +3572,9 @@ watchpoints_triggered (struct target_waitstatus *ws)
      triggered.  */
 
   ALL_BREAKPOINTS (b)
-    if (b->type == bp_hardware_watchpoint
-       || b->type == bp_read_watchpoint
-       || b->type == bp_access_watchpoint)
+    if (is_hardware_watchpoint (b))
       {
        struct bp_location *loc;
-       struct value *v;
 
        b->watchpoint_triggered = watch_triggered_no;
        for (loc = b->loc; loc; loc = loc->next)
@@ -3561,6 +3619,9 @@ watchpoint_check (void *p)
   struct frame_info *fr;
   int within_current_scope;
 
+  /* BS is built for existing struct breakpoint.  */
+  gdb_assert (bs->breakpoint_at != NULL);
+  gdb_assert (bs->breakpoint_at->owner != NULL);
   b = bs->breakpoint_at->owner;
 
   /* If this is a local watchpoint, we only want to check if the
@@ -3689,15 +3750,15 @@ bpstat_check_location (const struct bp_location *bl,
 {
   struct breakpoint *b = bl->owner;
 
+  /* BL is from existing struct breakpoint.  */
+  gdb_assert (b != NULL);
+
   /* By definition, the inferior does not report stops at
      tracepoints.  */
   if (is_tracepoint (b))
     return 0;
 
-  if (b->type != bp_watchpoint
-      && b->type != bp_hardware_watchpoint
-      && b->type != bp_read_watchpoint
-      && b->type != bp_access_watchpoint
+  if (!is_watchpoint (b)
       && b->type != bp_hardware_breakpoint
       && b->type != bp_catchpoint)     /* a non-watchpoint bp */
     {
@@ -3709,17 +3770,15 @@ bpstat_check_location (const struct bp_location *bl,
          && !section_is_mapped (bl->section))
        return 0;
     }
-  
+
   /* Continuable hardware watchpoints are treated as non-existent if the
      reason we stopped wasn't a hardware watchpoint (we didn't stop on
      some data address).  Otherwise gdb won't stop on a break instruction
      in the code (not from a breakpoint) when a hardware watchpoint has
      been defined.  Also skip watchpoints which we know did not trigger
      (did not match the data address).  */
-  
-  if ((b->type == bp_hardware_watchpoint
-       || b->type == bp_read_watchpoint
-       || b->type == bp_access_watchpoint)
+
+  if (is_hardware_watchpoint (b)
       && b->watchpoint_triggered == watch_triggered_no)
     return 0;
   
@@ -3749,16 +3808,17 @@ bpstat_check_location (const struct bp_location *bl,
 static void
 bpstat_check_watchpoint (bpstat bs)
 {
-  const struct bp_location *bl = bs->breakpoint_at;
-  struct breakpoint *b = bl->owner;
+  const struct bp_location *bl;
+  struct breakpoint *b;
 
-  if (b->type == bp_watchpoint
-      || b->type == bp_read_watchpoint
-      || b->type == bp_access_watchpoint
-      || b->type == bp_hardware_watchpoint)
+  /* BS is built for existing struct breakpoint.  */
+  bl = bs->breakpoint_at;
+  gdb_assert (bl != NULL);
+  b = bl->owner;
+  gdb_assert (b != NULL);
+
+  if (is_watchpoint (b))
     {
-      CORE_ADDR addr;
-      struct value *v;
       int must_check_value = 0;
       
       if (b->type == bp_watchpoint)
@@ -3907,8 +3967,14 @@ static void
 bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
 {
   int thread_id = pid_to_thread_id (ptid);
-  const struct bp_location *bl = bs->breakpoint_at;
-  struct breakpoint *b = bl->owner;
+  const struct bp_location *bl;
+  struct breakpoint *b;
+
+  /* BS is built for existing struct breakpoint.  */
+  bl = bs->breakpoint_at;
+  gdb_assert (bl != NULL);
+  b = bl->owner;
+  gdb_assert (b != NULL);
 
   if (frame_id_p (b->frame_id)
       && !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ())))
@@ -4033,7 +4099,7 @@ bpstat_stop_status (struct address_space *aspace,
                    CORE_ADDR bp_addr, ptid_t ptid)
 {
   struct breakpoint *b = NULL;
-  struct bp_location *bl, **blp_tmp;
+  struct bp_location *bl;
   struct bp_location *loc;
   /* Root of the chain of bpstat's */
   struct bpstats root_bs[1];
@@ -4054,9 +4120,9 @@ bpstat_stop_status (struct address_space *aspace,
       for (bl = b->loc; bl != NULL; bl = bl->next)
        {
          /* For hardware watchpoints, we look only at the first location.
-            The watchpoint_check function will work on entire expression,
-            not the individual locations.  For read watchopints, the
-            watchpoints_triggered function have checked all locations
+            The watchpoint_check function will work on the entire expression,
+            not the individual locations.  For read watchpoints, the
+            watchpoints_triggered function has checked all locations
             already.  */
          if (b->type == bp_hardware_watchpoint && bl != b->loc)
            break;
@@ -4141,12 +4207,8 @@ bpstat_stop_status (struct address_space *aspace,
      not have changed, but the intermediate memory locations we are
      watching may have.  Don't bother if we're stopping; this will get
      done later.  */
-  for (bs = root_bs->next; bs != NULL; bs = bs->next)
-    if (bs->stop)
-      break;
-
   need_remove_insert = 0;
-  if (bs == NULL)
+  if (! bpstat_causes_stop (root_bs->next))
     for (bs = root_bs->next; bs != NULL; bs = bs->next)
       if (!bs->stop
          && bs->breakpoint_at->owner
@@ -4164,151 +4226,64 @@ bpstat_stop_status (struct address_space *aspace,
 
   return root_bs->next;
 }
-\f
-/* Tell what to do about this bpstat.  */
-struct bpstat_what
-bpstat_what (bpstat bs)
-{
-  /* Classify each bpstat as one of the following.  */
-  enum class
-    {
-      /* This bpstat element has no effect on the main_action.  */
-      no_effect = 0,
-
-      /* There was a watchpoint, stop but don't print.  */
-      wp_silent,
-
-      /* There was a watchpoint, stop and print.  */
-      wp_noisy,
-
-      /* There was a breakpoint but we're not stopping.  */
-      bp_nostop,
-
-      /* There was a breakpoint, stop but don't print.  */
-      bp_silent,
 
-      /* There was a breakpoint, stop and print.  */
-      bp_noisy,
-
-      /* We hit the longjmp breakpoint.  */
-      long_jump,
+static void
+handle_jit_event (void)
+{
+  struct frame_info *frame;
+  struct gdbarch *gdbarch;
 
-      /* We hit the longjmp_resume breakpoint.  */
-      long_resume,
+  /* Switch terminal for any messages produced by
+     breakpoint_re_set.  */
+  target_terminal_ours_for_output ();
 
-      /* We hit the step_resume breakpoint.  */
-      step_resume,
+  frame = get_current_frame ();
+  gdbarch = get_frame_arch (frame);
 
-      /* We hit the shared library event breakpoint.  */
-      shlib_event,
+  jit_event_handler (gdbarch);
 
-      /* We hit the jit event breakpoint.  */
-      jit_event,
+  target_terminal_inferior ();
+}
 
-      /* This is just used to count how many enums there are.  */
-      class_last
-    };
+/* Prepare WHAT final decision for infrun.  */
 
-  /* Here is the table which drives this routine.  So that we can
-     format it pretty, we define some abbreviations for the
-     enum bpstat_what codes.  */
-#define kc BPSTAT_WHAT_KEEP_CHECKING
-#define ss BPSTAT_WHAT_STOP_SILENT
-#define sn BPSTAT_WHAT_STOP_NOISY
-#define sgl BPSTAT_WHAT_SINGLE
-#define slr BPSTAT_WHAT_SET_LONGJMP_RESUME
-#define clr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
-#define sr BPSTAT_WHAT_STEP_RESUME
-#define shl BPSTAT_WHAT_CHECK_SHLIBS
-#define jit BPSTAT_WHAT_CHECK_JIT
-
-/* "Can't happen."  Might want to print an error message.
-   abort() is not out of the question, but chances are GDB is just
-   a bit confused, not unusable.  */
-#define err BPSTAT_WHAT_STOP_NOISY
-
-  /* Given an old action and a class, come up with a new action.  */
-  /* One interesting property of this table is that wp_silent is the same
-     as bp_silent and wp_noisy is the same as bp_noisy.  That is because
-     after stopping, the check for whether to step over a breakpoint
-     (BPSTAT_WHAT_SINGLE type stuff) is handled in proceed() without
-     reference to how we stopped.  We retain separate wp_silent and
-     bp_silent codes in case we want to change that someday. 
-
-     Another possibly interesting property of this table is that
-     there's a partial ordering, priority-like, of the actions.  Once
-     you've decided that some action is appropriate, you'll never go
-     back and decide something of a lower priority is better.  The
-     ordering is:
-
-     kc   < jit clr sgl shl slr sn sr ss
-     sgl  < jit shl slr sn sr ss
-     slr  < jit err shl sn sr ss
-     clr  < jit err shl sn sr ss
-     ss   < jit shl sn sr
-     sn   < jit shl sr
-     jit  < shl sr
-     shl  < sr
-     sr   <
-
-     What I think this means is that we don't need a damned table
-     here.  If you just put the rows and columns in the right order,
-     it'd look awfully regular.  We could simply walk the bpstat list
-     and choose the highest priority action we find, with a little
-     logic to handle the 'err' cases.  */
-
-  /* step_resume entries: a step resume breakpoint overrides another
-     breakpoint of signal handling (see comment in wait_for_inferior
-     at where we set the step_resume breakpoint).  */
-
-  static const enum bpstat_what_main_action
-    table[(int) class_last][(int) BPSTAT_WHAT_LAST] =
-  {
-  /*                              old action */
-  /*               kc   ss   sn   sgl  slr  clr  sr  shl  jit */
-/* no_effect */   {kc,  ss,  sn,  sgl, slr, clr, sr, shl, jit},
-/* wp_silent */   {ss,  ss,  sn,  ss,  ss,  ss,  sr, shl, jit},
-/* wp_noisy */    {sn,  sn,  sn,  sn,  sn,  sn,  sr, shl, jit},
-/* bp_nostop */   {sgl, ss,  sn,  sgl, slr, slr, sr, shl, jit},
-/* bp_silent */   {ss,  ss,  sn,  ss,  ss,  ss,  sr, shl, jit},
-/* bp_noisy */    {sn,  sn,  sn,  sn,  sn,  sn,  sr, shl, jit},
-/* long_jump */   {slr, ss,  sn,  slr, slr, err, sr, shl, jit},
-/* long_resume */ {clr, ss,  sn,  err, err, err, sr, shl, jit},
-/* step_resume */ {sr,  sr,  sr,  sr,  sr,  sr,  sr, sr,  sr },
-/* shlib */       {shl, shl, shl, shl, shl, shl, sr, shl, shl},
-/* jit_event */   {jit, jit, jit, jit, jit, jit, sr, jit, jit}
-  };
+/* Decide what infrun needs to do with this bpstat.  */
 
-#undef kc
-#undef ss
-#undef sn
-#undef sgl
-#undef slr
-#undef clr
-#undef err
-#undef sr
-#undef ts
-#undef shl
-#undef jit
-  enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
+struct bpstat_what
+bpstat_what (bpstat bs)
+{
   struct bpstat_what retval;
+  /* We need to defer calling `solib_add', as adding new symbols
+     resets breakpoints, which in turn deletes breakpoint locations,
+     and hence may clear unprocessed entries in the BS chain.  */
+  int shlib_event = 0;
+  int jit_event = 0;
 
+  retval.main_action = BPSTAT_WHAT_KEEP_CHECKING;
   retval.call_dummy = STOP_NONE;
+
   for (; bs != NULL; bs = bs->next)
     {
-      enum class bs_class = no_effect;
+      /* Extract this BS's action.  After processing each BS, we check
+        if its action overrides all we've seem so far.  */
+      enum bpstat_what_main_action this_action = BPSTAT_WHAT_KEEP_CHECKING;
+      enum bptype bptype;
+
       if (bs->breakpoint_at == NULL)
-       /* I suspect this can happen if it was a momentary breakpoint
-          which has since been deleted.  */
-       continue;
-      if (bs->breakpoint_at->owner == NULL)
-       bs_class = bp_nostop;
+       {
+         /* I suspect this can happen if it was a momentary
+            breakpoint which has since been deleted.  */
+         bptype = bp_none;
+       }
+      else if (bs->breakpoint_at->owner == NULL)
+       bptype = bp_none;
       else
-      switch (bs->breakpoint_at->owner->type)
+       bptype = bs->breakpoint_at->owner->type;
+
+      switch (bptype)
        {
        case bp_none:
-         continue;
-
+         break;
        case bp_breakpoint:
        case bp_hardware_breakpoint:
        case bp_until:
@@ -4316,12 +4291,12 @@ bpstat_what (bpstat bs)
          if (bs->stop)
            {
              if (bs->print)
-               bs_class = bp_noisy;
+               this_action = BPSTAT_WHAT_STOP_NOISY;
              else
-               bs_class = bp_silent;
+               this_action = BPSTAT_WHAT_STOP_SILENT;
            }
          else
-           bs_class = bp_nostop;
+           this_action = BPSTAT_WHAT_SINGLE;
          break;
        case bp_watchpoint:
        case bp_hardware_watchpoint:
@@ -4330,82 +4305,125 @@ bpstat_what (bpstat bs)
          if (bs->stop)
            {
              if (bs->print)
-               bs_class = wp_noisy;
+               this_action = BPSTAT_WHAT_STOP_NOISY;
              else
-               bs_class = wp_silent;
+               this_action = BPSTAT_WHAT_STOP_SILENT;
            }
          else
-           /* There was a watchpoint, but we're not stopping. 
-              This requires no further action.  */
-           bs_class = no_effect;
+           {
+             /* There was a watchpoint, but we're not stopping.
+                This requires no further action.  */
+           }
          break;
        case bp_longjmp:
-         bs_class = long_jump;
+         this_action = BPSTAT_WHAT_SET_LONGJMP_RESUME;
          break;
        case bp_longjmp_resume:
-         bs_class = long_resume;
+         this_action = BPSTAT_WHAT_CLEAR_LONGJMP_RESUME;
          break;
        case bp_step_resume:
          if (bs->stop)
+           this_action = BPSTAT_WHAT_STEP_RESUME;
+         else
            {
-             bs_class = step_resume;
+             /* It is for the wrong frame.  */
+             this_action = BPSTAT_WHAT_SINGLE;
            }
-         else
-           /* It is for the wrong frame.  */
-           bs_class = bp_nostop;
          break;
        case bp_watchpoint_scope:
-         bs_class = bp_nostop;
-         break;
-       case bp_shlib_event:
-         bs_class = shlib_event;
-         break;
-       case bp_jit_event:
-         bs_class = jit_event;
-         break;
        case bp_thread_event:
        case bp_overlay_event:
        case bp_longjmp_master:
        case bp_std_terminate_master:
-         bs_class = bp_nostop;
+         this_action = BPSTAT_WHAT_SINGLE;
          break;
        case bp_catchpoint:
          if (bs->stop)
            {
              if (bs->print)
-               bs_class = bp_noisy;
+               this_action = BPSTAT_WHAT_STOP_NOISY;
              else
-               bs_class = bp_silent;
+               this_action = BPSTAT_WHAT_STOP_SILENT;
+           }
+         else
+           {
+             /* There was a catchpoint, but we're not stopping.
+                This requires no further action.  */
            }
+         break;
+       case bp_shlib_event:
+         shlib_event = 1;
+
+         /* If requested, stop when the dynamic linker notifies GDB
+            of events.  This allows the user to get control and place
+            breakpoints in initializer routines for dynamically
+            loaded objects (among other things).  */
+         if (stop_on_solib_events)
+           this_action = BPSTAT_WHAT_STOP_NOISY;
          else
-           /* There was a catchpoint, but we're not stopping.  
-              This requires no further action.  */
-           bs_class = no_effect;
+           this_action = BPSTAT_WHAT_SINGLE;
+         break;
+       case bp_jit_event:
+         jit_event = 1;
+         this_action = BPSTAT_WHAT_SINGLE;
          break;
        case bp_call_dummy:
          /* Make sure the action is stop (silent or noisy),
             so infrun.c pops the dummy frame.  */
-         bs_class = bp_silent;
          retval.call_dummy = STOP_STACK_DUMMY;
+         this_action = BPSTAT_WHAT_STOP_SILENT;
          break;
        case bp_std_terminate:
          /* Make sure the action is stop (silent or noisy),
             so infrun.c pops the dummy frame.  */
-         bs_class = bp_silent;
          retval.call_dummy = STOP_STD_TERMINATE;
+         this_action = BPSTAT_WHAT_STOP_SILENT;
          break;
        case bp_tracepoint:
        case bp_fast_tracepoint:
+       case bp_static_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: tracepoint encountered"));
-         break;
+       default:
+         internal_error (__FILE__, __LINE__,
+                         _("bpstat_what: unhandled bptype %d"), (int) bptype);
        }
-      current_action = table[(int) bs_class][(int) current_action];
+
+      retval.main_action = max (retval.main_action, this_action);
+    }
+
+  if (shlib_event)
+    {
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog, "bpstat_what: bp_shlib_event\n");
+
+      /* Check for any newly added shared libraries if we're supposed
+        to be adding them automatically.  */
+
+      /* Switch terminal for any messages produced by
+        breakpoint_re_set.  */
+      target_terminal_ours_for_output ();
+
+#ifdef SOLIB_ADD
+      SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
+#else
+      solib_add (NULL, 0, &current_target, auto_solib_add);
+#endif
+
+      target_terminal_inferior ();
+    }
+
+  if (jit_event)
+    {
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog, "bpstat_what: bp_jit_event\n");
+
+      handle_jit_event ();
     }
-  retval.main_action = current_action;
+
   return retval;
 }
 
@@ -4417,6 +4435,7 @@ int
 bpstat_should_step (void)
 {
   struct breakpoint *b;
+
   ALL_BREAKPOINTS (b)
     if (breakpoint_enabled (b) && b->type == bp_watchpoint && b->loc != NULL)
       return 1;
@@ -4498,7 +4517,6 @@ print_one_breakpoint_location (struct breakpoint *b,
                               int allflag)
 {
   struct command_line *l;
-  struct symbol *sym;
   struct ep_type_description
     {
       enum bptype type;
@@ -4529,6 +4547,7 @@ print_one_breakpoint_location (struct breakpoint *b,
     {bp_catchpoint, "catchpoint"},
     {bp_tracepoint, "tracepoint"},
     {bp_fast_tracepoint, "fast tracepoint"},
+    {bp_static_tracepoint, "static tracepoint"},
     {bp_jit_event, "jit events"},
   };
   
@@ -4661,6 +4680,7 @@ print_one_breakpoint_location (struct breakpoint *b,
       case bp_std_terminate_master:
       case bp_tracepoint:
       case bp_fast_tracepoint:
+      case bp_static_tracepoint:
       case bp_jit_event:
        if (opts.addressprint)
          {
@@ -4690,6 +4710,8 @@ print_one_breakpoint_location (struct breakpoint *b,
          || (!gdbarch_has_global_breakpoints (target_gdbarch)
              && (number_of_program_spaces () > 1
                  || number_of_inferiors () > 1)
+             /* LOC is for existing B, it cannot be in moribund_locations and
+                thus having NULL OWNER.  */
              && loc->owner->type != bp_catchpoint)))
     {
       struct inferior *inf;
@@ -4729,6 +4751,16 @@ print_one_breakpoint_location (struct breakpoint *b,
   
   ui_out_text (uiout, "\n");
   
+  if (!part_of_multiple && b->static_trace_marker_id)
+    {
+      gdb_assert (b->type == bp_static_tracepoint);
+
+      ui_out_text (uiout, "\tmarker id is ");
+      ui_out_field_string (uiout, "static-tracepoint-marker-string-id",
+                          b->static_trace_marker_id);
+      ui_out_text (uiout, "\n");
+    }
+
   if (part_of_multiple && frame_id_p (b->frame_id))
     {
       annotate_field (6);
@@ -4891,11 +4923,13 @@ do_captured_breakpoint_query (struct ui_out *uiout, void *data)
   struct captured_breakpoint_query_args *args = data;
   struct breakpoint *b;
   struct bp_location *dummy_loc = NULL;
+
   ALL_BREAKPOINTS (b)
     {
       if (args->bnum == b->number)
        {
          int print_address_bits = breakpoint_address_bits (b);
+
          print_one_breakpoint (b, &dummy_loc, print_address_bits, 0);
          return GDB_RC_OK;
        }
@@ -4907,6 +4941,7 @@ enum gdb_rc
 gdb_breakpoint_query (struct ui_out *uiout, int bnum, char **error_message)
 {
   struct captured_breakpoint_query_args args;
+
   args.bnum = bnum;
   /* For the moment we don't trust print_one_breakpoint() to not throw
      an error. */
@@ -4927,10 +4962,7 @@ user_settable_breakpoint (const struct breakpoint *b)
          || b->type == bp_catchpoint
          || b->type == bp_hardware_breakpoint
          || is_tracepoint (b)
-         || b->type == bp_watchpoint
-         || b->type == bp_read_watchpoint
-         || b->type == bp_access_watchpoint
-         || b->type == bp_hardware_watchpoint);
+         || is_watchpoint (b));
 }
        
 /* Print information on user settable breakpoint (watchpoint, etc)
@@ -5056,6 +5088,25 @@ breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *))
   return nr_printable_breakpoints;
 }
 
+/* Display the value of default-collect in a way that is generally
+   compatible with the breakpoint list.  */
+
+static void
+default_collect_info (void)
+{
+  /* If it has no value (which is frequently the case), say nothing; a
+     message like "No default-collect." gets in user's face when it's
+     not wanted.  */
+  if (!*default_collect)
+    return;
+
+  /* The following phrase lines up nicely with per-tracepoint collect
+     actions.  */
+  ui_out_text (uiout, "default collect ");
+  ui_out_field_string (uiout, "default-collect", default_collect);
+  ui_out_text (uiout, " \n");
+}
+  
 static void
 breakpoints_info (char *bnum_exp, int from_tty)
 {
@@ -5065,6 +5116,8 @@ breakpoints_info (char *bnum_exp, int from_tty)
     bnum = parse_and_eval_long (bnum_exp);
 
   breakpoint_1 (bnum, 0, NULL);
+
+  default_collect_info ();
 }
 
 static void
@@ -5095,6 +5148,8 @@ maintenance_info_breakpoints (char *bnum_exp, int from_tty)
     bnum = parse_and_eval_long (bnum_exp);
 
   breakpoint_1 (bnum, 1, NULL);
+
+  default_collect_info ();
 }
 
 static int
@@ -5103,6 +5158,7 @@ breakpoint_has_pc (struct breakpoint *b,
                   CORE_ADDR pc, struct obj_section *section)
 {
   struct bp_location *bl = b->loc;
+
   for (; bl; bl = bl->next)
     {
       if (bl->pspace == pspace
@@ -5202,6 +5258,10 @@ breakpoint_address_is_meaningful (struct breakpoint *bpt)
 static int
 watchpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2)
 {
+  /* Both of them must not be in moribund_locations.  */
+  gdb_assert (loc1->owner != NULL);
+  gdb_assert (loc2->owner != NULL);
+
   /* Note that this checks the owner's type, not the location's.  In
      case the target does not support read watchpoints, but does
      support access watchpoints, we'll have bp_read_watchpoint
@@ -5235,8 +5295,14 @@ breakpoint_address_match (struct address_space *aspace1, CORE_ADDR addr1,
 static int
 breakpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2)
 {
-  int hw_point1 = is_hardware_watchpoint (loc1->owner);
-  int hw_point2 = is_hardware_watchpoint (loc2->owner);
+  int hw_point1, hw_point2;
+
+  /* Both of them must not be in moribund_locations.  */
+  gdb_assert (loc1->owner != NULL);
+  gdb_assert (loc2->owner != NULL);
+
+  hw_point1 = is_hardware_watchpoint (loc1->owner);
+  hw_point2 = is_hardware_watchpoint (loc2->owner);
 
   if (hw_point1 != hw_point2)
     return 0;
@@ -5310,7 +5376,7 @@ adjust_breakpoint_address (struct gdbarch *gdbarch,
 static struct bp_location *
 allocate_bp_location (struct breakpoint *bpt)
 {
-  struct bp_location *loc, *loc_p;
+  struct bp_location *loc;
 
   loc = xmalloc (sizeof (struct bp_location));
   memset (loc, 0, sizeof (*loc));
@@ -5351,6 +5417,7 @@ allocate_bp_location (struct breakpoint *bpt)
     case bp_catchpoint:
     case bp_tracepoint:
     case bp_fast_tracepoint:
+    case bp_static_tracepoint:
       loc->loc_type = bp_loc_other;
       break;
     default:
@@ -5362,6 +5429,18 @@ allocate_bp_location (struct breakpoint *bpt)
 
 static void free_bp_location (struct bp_location *loc)
 {
+  /* Be sure no bpstat's are pointing at it after it's been freed.  */
+  /* FIXME, how can we find all bpstat's?
+     We just check stop_bpstat for now.  Note that we cannot just
+     remove bpstats pointing at bpt from the stop_bpstat list
+     entirely, as breakpoint commands are associated with the bpstat;
+     if we remove it here, then the later call to
+         bpstat_do_actions (&stop_bpstat);
+     in event-top.c won't do anything, and temporary breakpoints
+     with commands won't work.  */
+
+  iterate_over_threads (bpstat_remove_bp_location_callback, loc);
+
   if (loc->cond)
     xfree (loc->cond);
 
@@ -5421,6 +5500,8 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch,
 static void
 set_breakpoint_location_function (struct bp_location *loc)
 {
+  gdb_assert (loc->owner != NULL);
+
   if (loc->owner->type == bp_breakpoint
       || loc->owner->type == bp_hardware_breakpoint
       || is_tracepoint (loc->owner))
@@ -5513,6 +5594,7 @@ void
 make_breakpoint_permanent (struct breakpoint *b)
 {
   struct bp_location *bl;
+
   b->enable_state = bp_permanent;
 
   /* By definition, permanent breakpoints are already present in the code. 
@@ -5542,6 +5624,7 @@ set_longjmp_breakpoint (int thread)
        && b->type == bp_longjmp_master)
       {
        struct breakpoint *clone = clone_momentary_breakpoint (b);
+
        clone->type = bp_longjmp;
        clone->thread = thread;
       }
@@ -5701,7 +5784,9 @@ disable_breakpoints_in_shlibs (void)
 
   ALL_BP_LOCATIONS (loc, locp_tmp)
   {
+    /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL.  */
     struct breakpoint *b = loc->owner;
+
     /* We apply the check to all breakpoints, including disabled
        for those with loc->duplicate set.  This is so that when breakpoint
        becomes enabled, or the duplicate is removed, gdb will try to insert
@@ -5744,7 +5829,9 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
 
   ALL_BP_LOCATIONS (loc, locp_tmp)
   {
+    /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL.  */
     struct breakpoint *b = loc->owner;
+
     if ((loc->loc_type == bp_loc_hardware_breakpoint
         || loc->loc_type == bp_loc_software_breakpoint)
        && solib->pspace == loc->pspace
@@ -5842,6 +5929,15 @@ print_mention_catch_fork (struct breakpoint *b)
   printf_filtered (_("Catchpoint %d (fork)"), b->number);
 }
 
+/* Implement the "print_recreate" breakpoint_ops method for fork
+   catchpoints.  */
+
+static void
+print_recreate_catch_fork (struct breakpoint *b, struct ui_file *fp)
+{
+  fprintf_unfiltered (fp, "catch fork");
+}
+
 /* The breakpoint_ops structure to be used in fork catchpoints.  */
 
 static struct breakpoint_ops catch_fork_breakpoint_ops =
@@ -5851,7 +5947,8 @@ static struct breakpoint_ops catch_fork_breakpoint_ops =
   breakpoint_hit_catch_fork,
   print_it_catch_fork,
   print_one_catch_fork,
-  print_mention_catch_fork
+  print_mention_catch_fork,
+  print_recreate_catch_fork
 };
 
 /* Implement the "insert" breakpoint_ops method for vfork catchpoints.  */
@@ -5923,6 +6020,15 @@ print_mention_catch_vfork (struct breakpoint *b)
   printf_filtered (_("Catchpoint %d (vfork)"), b->number);
 }
 
+/* Implement the "print_recreate" breakpoint_ops method for vfork
+   catchpoints.  */
+
+static void
+print_recreate_catch_vfork (struct breakpoint *b, struct ui_file *fp)
+{
+  fprintf_unfiltered (fp, "catch vfork");
+}
+
 /* The breakpoint_ops structure to be used in vfork catchpoints.  */
 
 static struct breakpoint_ops catch_vfork_breakpoint_ops =
@@ -5932,7 +6038,8 @@ static struct breakpoint_ops catch_vfork_breakpoint_ops =
   breakpoint_hit_catch_vfork,
   print_it_catch_vfork,
   print_one_catch_vfork,
-  print_mention_catch_vfork
+  print_mention_catch_vfork,
+  print_recreate_catch_vfork
 };
 
 /* Implement the "insert" breakpoint_ops method for syscall
@@ -5949,11 +6056,13 @@ insert_catch_syscall (struct breakpoint *b)
   else
     {
       int i, iter;
+
       for (i = 0;
            VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
            i++)
        {
           int elem;
+
          if (iter >= VEC_length (int, inf->syscalls_counts))
            {
               int old_size = VEC_length (int, inf->syscalls_counts);
@@ -5991,6 +6100,7 @@ remove_catch_syscall (struct breakpoint *b)
   else
     {
       int i, iter;
+
       for (i = 0;
            VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
            i++)
@@ -6029,6 +6139,7 @@ breakpoint_hit_catch_syscall (struct breakpoint *b)
   if (b->syscalls_to_be_caught)
     {
       int i, iter;
+
       for (i = 0;
            VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
            i++)
@@ -6110,6 +6221,7 @@ print_one_catch_syscall (struct breakpoint *b,
     {
       int i, iter;
       char *text = xstrprintf ("%s", "");
+
       for (i = 0;
            VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
            i++)
@@ -6171,6 +6283,33 @@ print_mention_catch_syscall (struct breakpoint *b)
                      b->number);
 }
 
+/* Implement the "print_recreate" breakpoint_ops method for syscall
+   catchpoints.  */
+
+static void
+print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp)
+{
+  fprintf_unfiltered (fp, "catch syscall");
+
+  if (b->syscalls_to_be_caught)
+    {
+      int i, iter;
+
+      for (i = 0;
+           VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
+           i++)
+        {
+          struct syscall s;
+
+          get_syscall_by_number (iter, &s);
+          if (s.name)
+            fprintf_unfiltered (fp, " %s", s.name);
+          else
+            fprintf_unfiltered (fp, " %d", s.number);
+        }
+    }
+}
+
 /* The breakpoint_ops structure to be used in syscall catchpoints.  */
 
 static struct breakpoint_ops catch_syscall_breakpoint_ops =
@@ -6180,7 +6319,8 @@ static struct breakpoint_ops catch_syscall_breakpoint_ops =
   breakpoint_hit_catch_syscall,
   print_it_catch_syscall,
   print_one_catch_syscall,
-  print_mention_catch_syscall
+  print_mention_catch_syscall,
+  print_recreate_catch_syscall
 };
 
 /* Returns non-zero if 'b' is a syscall catchpoint.  */
@@ -6316,6 +6456,15 @@ print_mention_catch_exec (struct breakpoint *b)
   printf_filtered (_("Catchpoint %d (exec)"), b->number);
 }
 
+/* Implement the "print_recreate" breakpoint_ops method for exec
+   catchpoints.  */
+
+static void
+print_recreate_catch_exec (struct breakpoint *b, struct ui_file *fp)
+{
+  fprintf_unfiltered (fp, "catch exec");
+}
+
 static struct breakpoint_ops catch_exec_breakpoint_ops =
 {
   insert_catch_exec,
@@ -6323,7 +6472,8 @@ static struct breakpoint_ops catch_exec_breakpoint_ops =
   breakpoint_hit_catch_exec,
   print_it_catch_exec,
   print_one_catch_exec,
-  print_mention_catch_exec
+  print_mention_catch_exec,
+  print_recreate_catch_exec
 };
 
 static void
@@ -6370,9 +6520,7 @@ hw_watchpoint_used_count (enum bptype type, int *other_type_used)
       {
        if (b->type == type)
          i++;
-       else if ((b->type == bp_hardware_watchpoint
-                 || b->type == bp_read_watchpoint
-                 || b->type == bp_access_watchpoint))
+       else if (is_hardware_watchpoint (b))
          *other_type_used = 1;
       }
   }
@@ -6386,11 +6534,7 @@ disable_watchpoints_before_interactive_call_start (void)
 
   ALL_BREAKPOINTS (b)
   {
-    if (((b->type == bp_watchpoint)
-        || (b->type == bp_hardware_watchpoint)
-        || (b->type == bp_read_watchpoint)
-        || (b->type == bp_access_watchpoint))
-       && breakpoint_enabled (b))
+    if (is_watchpoint (b) && breakpoint_enabled (b))
       {
        b->enable_state = bp_call_disabled;
        update_global_location_list (0);
@@ -6405,11 +6549,7 @@ enable_watchpoints_after_interactive_call_stop (void)
 
   ALL_BREAKPOINTS (b)
   {
-    if (((b->type == bp_watchpoint)
-        || (b->type == bp_hardware_watchpoint)
-        || (b->type == bp_read_watchpoint)
-        || (b->type == bp_access_watchpoint))
-       && (b->enable_state == bp_call_disabled))
+    if (is_watchpoint (b) && b->enable_state == bp_call_disabled)
       {
        b->enable_state = bp_enabled;
        update_global_location_list (1);
@@ -6654,10 +6794,20 @@ mention (struct breakpoint *b)
        printf_filtered (_(" %d"), b->number);
        say_where = 1;
        break;
-
-      case bp_until:
-      case bp_finish:
-      case bp_longjmp:
+      case bp_static_tracepoint:
+       if (ui_out_is_mi_like_p (uiout))
+         {
+           say_where = 0;
+           break;
+         }
+       printf_filtered (_("Static tracepoint"));
+       printf_filtered (_(" %d"), b->number);
+       say_where = 1;
+       break;
+
+      case bp_until:
+      case bp_finish:
+      case bp_longjmp:
       case bp_longjmp_resume:
       case bp_step_resume:
       case bp_call_dummy:
@@ -6833,9 +6983,47 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
          b->ignore_count = ignore_count;
          b->enable_state = enabled ? bp_enabled : bp_disabled;
          b->disposition = disposition;
-
          b->pspace = sals.sals[0].pspace;
 
+         if (type == bp_static_tracepoint)
+           {
+             struct static_tracepoint_marker marker;
+
+             if (is_marker_spec (addr_string))
+               {
+                 /* We already know the marker exists, otherwise, we
+                    wouldn't see a sal for it.  */
+                 char *p = &addr_string[3];
+                 char *endp;
+                 char *marker_str;
+                 int i;
+
+                 while (*p == ' ' || *p == '\t')
+                   p++;
+
+                 endp = p;
+                 while (*endp != ' ' && *endp != '\t' && *endp != '\0')
+                   endp++;
+
+                 marker_str = savestring (p, endp - p);
+                 b->static_trace_marker_id = marker_str;
+
+                 printf_filtered (_("Probed static tracepoint marker \"%s\"\n"),
+                                  b->static_trace_marker_id);
+               }
+             else if (target_static_tracepoint_marker_at (sal.pc, &marker))
+               {
+                 b->static_trace_marker_id = xstrdup (marker.str_id);
+                 release_static_tracepoint_marker (&marker);
+
+                 printf_filtered (_("Probed static tracepoint marker \"%s\"\n"),
+                                  b->static_trace_marker_id);
+               }
+             else
+               warning (_("\
+Couldn't determine the static tracepoint marker to probe"));
+           }
+
          if (enabled && b->pspace->executing_startup
              && (b->type == bp_breakpoint
                  || b->type == bp_hardware_breakpoint))
@@ -7028,6 +7216,7 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
                        int enabled)
 {
   int i;
+
   for (i = 0; i < sals.nelts; ++i)
     {
       struct symtabs_and_lines expanded = 
@@ -7051,6 +7240,7 @@ parse_breakpoint_sals (char **address,
                       int *not_found_ptr)
 {
   char *addr_start = *address;
+
   *addr_string = NULL;
   /* If no arg given, or if first arg is 'if ', use the default
      breakpoint. */
@@ -7060,6 +7250,7 @@ parse_breakpoint_sals (char **address,
       if (default_breakpoint_valid)
        {
          struct symtab_and_line sal;
+
          init_sal (&sal);              /* initialize to zeroes */
          sals->sals = (struct symtab_and_line *)
            xmalloc (sizeof (struct symtab_and_line));
@@ -7110,11 +7301,13 @@ parse_breakpoint_sals (char **address,
   if (addr_start != (*address))
     {
       int i;
+
       for (i = 0; i < sals->nelts; i++)
        {
          /* Add the string if not present. */
          if ((*addr_string)[i] == NULL)
-           (*addr_string)[i] = savestring (addr_start, (*address) - addr_start);
+           (*addr_string)[i] = savestring (addr_start, 
+                                           (*address) - addr_start);
        }
     }
 }
@@ -7124,10 +7317,10 @@ parse_breakpoint_sals (char **address,
    inserted as a breakpoint.  If it can't throw an error. */
 
 static void
-breakpoint_sals_to_pc (struct symtabs_and_lines *sals,
-                      char *address)
+breakpoint_sals_to_pc (struct symtabs_and_lines *sals)
 {    
   int i;
+
   for (i = 0; i < sals->nelts; i++)
     resolve_sal_pc (&sals->sals[i]);
 }
@@ -7191,6 +7384,7 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
       int toklen;
       char *cond_start = NULL;
       char *cond_end = NULL;
+
       while (*tok == ' ' || *tok == '\t')
        tok++;
       
@@ -7241,6 +7435,58 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
     }
 }
 
+/* Decode a static tracepoint marker spec.  */
+
+static struct symtabs_and_lines
+decode_static_tracepoint_spec (char **arg_p)
+{
+  VEC(static_tracepoint_marker_p) *markers = NULL;
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+  struct symbol *sym;
+  struct cleanup *old_chain;
+  char *p = &(*arg_p)[3];
+  char *endp;
+  char *marker_str;
+  int i;
+
+  while (*p == ' ' || *p == '\t')
+    p++;
+
+  endp = p;
+  while (*endp != ' ' && *endp != '\t' && *endp != '\0')
+    endp++;
+
+  marker_str = savestring (p, endp - p);
+  old_chain = make_cleanup (xfree, marker_str);
+
+  markers = target_static_tracepoint_markers_by_strid (marker_str);
+  if (VEC_empty(static_tracepoint_marker_p, markers))
+    error (_("No known static tracepoint marker named %s"), marker_str);
+
+  sals.nelts = VEC_length(static_tracepoint_marker_p, markers);
+  sals.sals = xmalloc (sizeof *sals.sals * sals.nelts);
+
+  for (i = 0; i < sals.nelts; i++)
+    {
+      struct static_tracepoint_marker *marker;
+
+      marker = VEC_index (static_tracepoint_marker_p, markers, i);
+
+      init_sal (&sals.sals[i]);
+
+      sals.sals[i] = find_pc_line (marker->address, 0);
+      sals.sals[i].pc = marker->address;
+
+      release_static_tracepoint_marker (marker);
+    }
+
+  do_cleanups (old_chain);
+
+  *arg_p = endp;
+  return sals;
+}
+
 /* Set a breakpoint.  This function is shared between CLI and MI
    functions for setting a breakpoint.  This function has two major
    modes of operations, selected by the PARSE_CONDITION_AND_THREAD
@@ -7254,7 +7500,7 @@ int
 create_breakpoint (struct gdbarch *gdbarch,
                   char *arg, char *cond_string, int thread,
                   int parse_condition_and_thread,
-                  int tempflag, int hardwareflag, int traceflag,
+                  int tempflag, enum bptype type_wanted,
                   int ignore_count,
                   enum auto_boolean pending_break_support,
                   struct breakpoint_ops *ops,
@@ -7265,7 +7511,6 @@ create_breakpoint (struct gdbarch *gdbarch,
   struct symtabs_and_lines sals;
   struct symtab_and_line pending_sal;
   char *copy_arg;
-  char *err_msg;
   char *addr_start = arg;
   char **addr_string;
   struct cleanup *old_chain;
@@ -7274,7 +7519,6 @@ create_breakpoint (struct gdbarch *gdbarch,
   int i;
   int pending = 0;
   int not_found = 0;
-  enum bptype type_wanted;
   int task = 0;
   int prev_bkpt_count = breakpoint_count;
 
@@ -7287,6 +7531,19 @@ create_breakpoint (struct gdbarch *gdbarch,
   parse_args.addr_string_p = &addr_string;
   parse_args.not_found_ptr = &not_found;
 
+  if (type_wanted == bp_static_tracepoint && is_marker_spec (arg))
+    {
+      int i;
+
+      sals = decode_static_tracepoint_spec (&arg);
+
+      copy_arg = savestring (addr_start, arg - addr_start);
+      addr_string = xcalloc (sals.nelts, sizeof (char **));
+      for (i = 0; i < sals.nelts; i++)
+       addr_string[i] = xstrdup (copy_arg);
+      goto done;
+    }
+
   e = catch_exception (uiout, do_captured_parse_breakpoint, 
                       &parse_args, RETURN_MASK_ALL);
 
@@ -7333,6 +7590,8 @@ create_breakpoint (struct gdbarch *gdbarch,
        return 0;
     }
 
+  done:
+
   /* Create a chain of things that always need to be cleaned up. */
   old_chain = make_cleanup (null_cleanup, 0);
 
@@ -7362,11 +7621,7 @@ create_breakpoint (struct gdbarch *gdbarch,
   /* Resolve all line numbers to PC's and verify that the addresses
      are ok for the target.  */
   if (!pending)
-    breakpoint_sals_to_pc (&sals, addr_start);
-
-  type_wanted = (traceflag
-                ? (hardwareflag ? bp_fast_tracepoint : bp_tracepoint)
-                : (hardwareflag ? bp_hardware_breakpoint : bp_breakpoint));
+    breakpoint_sals_to_pc (&sals);
 
   /* Fast tracepoints may have additional restrictions on location.  */
   if (type_wanted == bp_fast_tracepoint)
@@ -7399,14 +7654,58 @@ create_breakpoint (struct gdbarch *gdbarch,
                 make_cleanup (xfree, cond_string);
             }
         }
-      create_breakpoints_sal (gdbarch, sals, addr_string, cond_string,
-                             type_wanted, tempflag ? disp_del : disp_donttouch,
-                             thread, task, ignore_count, ops, from_tty,
-                             enabled);
+
+      /* If the user is creating a static tracepoint by marker id
+        (strace -m MARKER_ID), then store the sals index, so that
+        breakpoint_re_set can try to match up which of the newly
+        found markers corresponds to this one, and, don't try to
+        expand multiple locations for each sal, given than SALS
+        already should contain all sals for MARKER_ID.  */
+      if (type_wanted == bp_static_tracepoint
+         && is_marker_spec (addr_string[0]))
+       {
+         int i;
+
+         for (i = 0; i < sals.nelts; ++i)
+           {
+             struct symtabs_and_lines expanded;
+             struct breakpoint *tp;
+             struct cleanup *old_chain;
+
+             expanded.nelts = 1;
+             expanded.sals = xmalloc (sizeof (struct symtab_and_line));
+             expanded.sals[0] = sals.sals[i];
+             old_chain = make_cleanup (xfree, expanded.sals);
+
+             create_breakpoint_sal (gdbarch, expanded, addr_string[i],
+                                    cond_string, type_wanted,
+                                    tempflag ? disp_del : disp_donttouch,
+                                    thread, task, ignore_count, ops,
+                                    from_tty, enabled);
+
+             do_cleanups (old_chain);
+
+             /* Get the tracepoint we just created.  */
+             tp = get_breakpoint (breakpoint_count);
+             gdb_assert (tp != NULL);
+
+             /* Given that its possible to have multiple markers with
+                the same string id, if the user is creating a static
+                tracepoint by marker id ("strace -m MARKER_ID"), then
+                store the sals index, so that breakpoint_re_set can
+                try to match up which of the newly found markers
+                corresponds to this one  */
+             tp->static_trace_marker_id_idx = i;
+           }
+       }
+      else
+       create_breakpoints_sal (gdbarch, sals, addr_string, cond_string,
+                               type_wanted, tempflag ? disp_del : disp_donttouch,
+                               thread, task, ignore_count, ops, from_tty,
+                               enabled);
     }
   else
     {
-      struct symtab_and_line sal = {0};
       struct breakpoint *b;
 
       make_cleanup (xfree, copy_arg);
@@ -7461,13 +7760,15 @@ create_breakpoint (struct gdbarch *gdbarch,
 static void
 break_command_1 (char *arg, int flag, int from_tty)
 {
-  int hardwareflag = flag & BP_HARDWAREFLAG;
   int tempflag = flag & BP_TEMPFLAG;
+  enum bptype type_wanted = (flag & BP_HARDWAREFLAG
+                            ? bp_hardware_breakpoint
+                            : bp_breakpoint);
 
   create_breakpoint (get_current_arch (),
                     arg,
                     NULL, 0, 1 /* parse arg */,
-                    tempflag, hardwareflag, 0 /* traceflag */,
+                    tempflag, type_wanted,
                     0 /* Ignore count */,
                     pending_break_support,
                     NULL /* breakpoint_ops */,
@@ -7476,7 +7777,6 @@ break_command_1 (char *arg, int flag, int from_tty)
 }
 
 
-
 /* Helper function for break_command_1 and disassemble_command.  */
 
 void
@@ -7631,13 +7931,117 @@ stopat_command (char *arg, int from_tty)
     break_command_1 (arg, 0, from_tty);
 }
 
+/*  Return non-zero if EXP is verified as constant.  Returned zero means EXP is
+    variable.  Also the constant detection may fail for some constant
+    expressions and in such case still falsely return zero.  */
+static int
+watchpoint_exp_is_const (const struct expression *exp)
+{
+  int i = exp->nelts;
+
+  while (i > 0)
+    {
+      int oplenp, argsp;
+
+      /* We are only interested in the descriptor of each element.  */
+      operator_length (exp, i, &oplenp, &argsp);
+      i -= oplenp;
+
+      switch (exp->elts[i].opcode)
+       {
+       case BINOP_ADD:
+       case BINOP_SUB:
+       case BINOP_MUL:
+       case BINOP_DIV:
+       case BINOP_REM:
+       case BINOP_MOD:
+       case BINOP_LSH:
+       case BINOP_RSH:
+       case BINOP_LOGICAL_AND:
+       case BINOP_LOGICAL_OR:
+       case BINOP_BITWISE_AND:
+       case BINOP_BITWISE_IOR:
+       case BINOP_BITWISE_XOR:
+       case BINOP_EQUAL:
+       case BINOP_NOTEQUAL:
+       case BINOP_LESS:
+       case BINOP_GTR:
+       case BINOP_LEQ:
+       case BINOP_GEQ:
+       case BINOP_REPEAT:
+       case BINOP_COMMA:
+       case BINOP_EXP:
+       case BINOP_MIN:
+       case BINOP_MAX:
+       case BINOP_INTDIV:
+       case BINOP_CONCAT:
+       case BINOP_IN:
+       case BINOP_RANGE:
+       case TERNOP_COND:
+       case TERNOP_SLICE:
+       case TERNOP_SLICE_COUNT:
+
+       case OP_LONG:
+       case OP_DOUBLE:
+       case OP_DECFLOAT:
+       case OP_LAST:
+       case OP_COMPLEX:
+       case OP_STRING:
+       case OP_BITSTRING:
+       case OP_ARRAY:
+       case OP_TYPE:
+       case OP_NAME:
+       case OP_OBJC_NSSTRING:
+
+       case UNOP_NEG:
+       case UNOP_LOGICAL_NOT:
+       case UNOP_COMPLEMENT:
+       case UNOP_ADDR:
+       case UNOP_HIGH:
+         /* Unary, binary and ternary operators: We have to check their
+            operands.  If they are constant, then so is the result of
+            that operation.  For instance, if A and B are determined to be
+            constants, then so is "A + B".
+
+            UNOP_IND is one exception to the rule above, because the value
+            of *ADDR is not necessarily a constant, even when ADDR is.  */
+         break;
+
+       case OP_VAR_VALUE:
+         /* Check whether the associated symbol is a constant.
+            We use SYMBOL_CLASS rather than TYPE_CONST because it's
+            possible that a buggy compiler could mark a variable as constant
+            even when it is not, and TYPE_CONST would return true in this
+            case, while SYMBOL_CLASS wouldn't.
+            We also have to check for function symbols because they are
+            always constant.  */
+         {
+           struct symbol *s = exp->elts[i + 2].symbol;
+
+           if (SYMBOL_CLASS (s) != LOC_BLOCK
+               && SYMBOL_CLASS (s) != LOC_CONST
+               && SYMBOL_CLASS (s) != LOC_CONST_BYTES)
+             return 0;
+           break;
+         }
+
+       /* The default action is to return 0 because we are using
+          the optimistic approach here: If we don't know something,
+          then it is not a constant.  */
+       default:
+         return 0;
+       }
+    }
+
+  return 1;
+}
+
 /* accessflag:  hw_write:  watch write, 
                 hw_read:   watch read, 
                hw_access: watch access (read or write) */
 static void
 watch_command_1 (char *arg, int accessflag, int from_tty)
 {
-  struct gdbarch *gdbarch = get_current_arch ();
   struct breakpoint *b, *scope_breakpoint = NULL;
   struct expression *exp;
   struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
@@ -7726,6 +8130,17 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
   while (exp_end > exp_start && (exp_end[-1] == ' ' || exp_end[-1] == '\t'))
     --exp_end;
 
+  /* Checking if the expression is not constant.  */
+  if (watchpoint_exp_is_const (exp))
+    {
+      int len;
+
+      len = exp_end - exp_start;
+      while (len > 0 && isspace (exp_start[len - 1]))
+       len--;
+      error (_("Cannot watch constant value `%.*s'."), len, exp_start);
+    }
+
   exp_valid_block = innermost_block;
   mark = value_mark ();
   fetch_watchpoint_value (exp, &val, NULL, NULL);
@@ -8140,7 +8555,8 @@ typedef enum
 catch_fork_kind;
 
 static void
-catch_fork_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
+catch_fork_command_1 (char *arg, int from_tty, 
+                     struct cmd_list_element *command)
 {
   struct gdbarch *gdbarch = get_current_arch ();
   char *cond_string = NULL;
@@ -8186,7 +8602,8 @@ catch_fork_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
 }
 
 static void
-catch_exec_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)
 {
   struct gdbarch *gdbarch = get_current_arch ();
   int tempflag;
@@ -8246,9 +8663,11 @@ print_exception_catchpoint (struct breakpoint *b)
 }
 
 static void
-print_one_exception_catchpoint (struct breakpoint *b, struct bp_location **last_loc)
+print_one_exception_catchpoint (struct breakpoint *b, 
+                               struct bp_location **last_loc)
 {
   struct value_print_options opts;
+
   get_user_print_options (&opts);
   if (opts.addressprint)
     {
@@ -8283,13 +8702,29 @@ print_mention_exception_catchpoint (struct breakpoint *b)
                               : _(" (catch)"));
 }
 
+/* Implement the "print_recreate" breakpoint_ops method for throw and
+   catch catchpoints.  */
+
+static void
+print_recreate_exception_catchpoint (struct breakpoint *b, struct ui_file *fp)
+{
+  int bp_temp;
+  int bp_throw;
+
+  bp_temp = b->disposition == disp_del;
+  bp_throw = strstr (b->addr_string, "throw") != NULL;
+  fprintf_unfiltered (fp, bp_temp ? "tcatch " : "catch ");
+  fprintf_unfiltered (fp, bp_throw ? "throw" : "catch");
+}
+
 static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = {
   NULL, /* insert */
   NULL, /* remove */
   NULL, /* breakpoint_hit */
   print_exception_catchpoint,
   print_one_exception_catchpoint,
-  print_mention_exception_catchpoint
+  print_mention_exception_catchpoint,
+  print_recreate_exception_catchpoint
 };
 
 static int
@@ -8306,7 +8741,7 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
   create_breakpoint (get_current_arch (),
                     trigger_func_name, cond_string, -1,
                     0 /* condition and thread are valid.  */,
-                    tempflag, 0, 0,
+                    tempflag, bp_breakpoint,
                     0,
                     AUTO_BOOLEAN_TRUE /* pending */,
                     &gnu_v3_exception_catchpoint_ops, from_tty,
@@ -8322,7 +8757,6 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
                           int tempflag, int from_tty)
 {
   char *cond_string = NULL;
-  struct symtab_and_line *sal = NULL;
 
   if (!arg)
     arg = "";
@@ -8349,6 +8783,7 @@ static void
 catch_catch_command (char *arg, int from_tty, struct cmd_list_element *command)
 {
   int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
   catch_exception_command_1 (EX_EVENT_CATCH, arg, tempflag, from_tty);
 }
 
@@ -8358,6 +8793,7 @@ static void
 catch_throw_command (char *arg, int from_tty, struct cmd_list_element *command)
 {
   int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
   catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
 }
 
@@ -8422,7 +8858,6 @@ catch_ada_exception_command (char *arg, int from_tty,
   struct gdbarch *gdbarch = get_current_arch ();
   int tempflag;
   struct symtab_and_line sal;
-  enum bptype type;
   char *addr_string = NULL;
   char *exp_string = NULL;
   char *cond_string = NULL;
@@ -8500,7 +8935,8 @@ catch_syscall_split_args (char *arg)
 /* Implement the "catch syscall" command.  */
 
 static void
-catch_syscall_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
+catch_syscall_command_1 (char *arg, int from_tty, 
+                        struct cmd_list_element *command)
 {
   int tempflag;
   VEC(int) *filter;
@@ -8652,11 +9088,7 @@ clear_command (char *arg, int from_tty)
        {
          int match = 0;
          /* Are we going to delete b? */
-         if (b->type != bp_none
-             && b->type != bp_watchpoint
-             && b->type != bp_hardware_watchpoint
-             && b->type != bp_read_watchpoint
-             && b->type != bp_access_watchpoint)
+         if (b->type != bp_none && !is_watchpoint (b))
            {
              struct bp_location *loc = b->loc;
              for (; loc; loc = loc->next)
@@ -8748,6 +9180,7 @@ bp_location_compare (const void *ap, const void *bp)
 {
   struct bp_location *a = *(void **) ap;
   struct bp_location *b = *(void **) bp;
+  /* A and B come from existing breakpoints having non-NULL OWNER.  */
   int a_perm = a->owner->enable_state == bp_permanent;
   int b_perm = b->owner->enable_state == bp_permanent;
 
@@ -8925,6 +9358,7 @@ update_global_location_list (int should_insert)
                 See if there's another location at the same address, in which 
                 case we don't need to remove this one from the target.  */
 
+             /* OLD_LOC comes from existing struct breakpoint.  */
              if (breakpoint_address_is_meaningful (old_loc->owner))
                {
                  for (loc2p = locp;
@@ -9011,7 +9445,7 @@ update_global_location_list (int should_insert)
                 soon, we'll fail to do the PC adjustment, and report
                 a random SIGTRAP to the user.  When the user resumes
                 the inferior, it will most likely immediately crash
-                with SIGILL/SIGBUS/SEGSEGV, or worse, get silently
+                with SIGILL/SIGBUS/SIGSEGV, or worse, get silently
                 corrupted, because of being resumed e.g., in the
                 middle of a multi-byte instruction, or skipped a
                 one-byte instruction.  This was actually seen happen
@@ -9057,6 +9491,7 @@ update_global_location_list (int should_insert)
   rwp_loc_first = NULL;
   ALL_BP_LOCATIONS (loc, locp)
     {
+      /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL.  */
       struct breakpoint *b = loc->owner;
       struct bp_location **loc_first_p;
 
@@ -9129,17 +9564,19 @@ static void
 update_global_location_list_nothrow (int inserting)
 {
   struct gdb_exception e;
+
   TRY_CATCH (e, RETURN_MASK_ERROR)
     update_global_location_list (inserting);
 }
 
-/* Clear BPT from a BPS.  */
+/* Clear LOC from a BPS.  */
 static void
-bpstat_remove_breakpoint (bpstat bps, struct breakpoint *bpt)
+bpstat_remove_bp_location (bpstat bps, struct bp_location *loc)
 {
   bpstat bs;
+
   for (bs = bps; bs; bs = bs->next)
-    if (bs->breakpoint_at && bs->breakpoint_at->owner == bpt)
+    if (bs->breakpoint_at == loc)
       {
        bs->breakpoint_at = NULL;
        bs->old_val = NULL;
@@ -9149,10 +9586,11 @@ bpstat_remove_breakpoint (bpstat bps, struct breakpoint *bpt)
 
 /* Callback for iterate_over_threads.  */
 static int
-bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
+bpstat_remove_bp_location_callback (struct thread_info *th, void *data)
 {
-  struct breakpoint *bpt = data;
-  bpstat_remove_breakpoint (th->stop_bpstat, bpt);
+  struct bp_location *loc = data;
+
+  bpstat_remove_bp_location (th->stop_bpstat, loc);
   return 0;
 }
 
@@ -9163,7 +9601,6 @@ void
 delete_breakpoint (struct breakpoint *bpt)
 {
   struct breakpoint *b;
-  struct bp_location *loc, *next;
 
   gdb_assert (bpt != NULL);
 
@@ -9216,18 +9653,6 @@ delete_breakpoint (struct breakpoint *bpt)
   xfree (bpt->exec_pathname);
   clean_up_filters (&bpt->syscalls_to_be_caught);
 
-  /* Be sure no bpstat's are pointing at it after it's been freed.  */
-  /* FIXME, how can we find all bpstat's?
-     We just check stop_bpstat for now.  Note that we cannot just
-     remove bpstats pointing at bpt from the stop_bpstat list
-     entirely, as breakpoint commands are associated with the bpstat;
-     if we remove it here, then the later call to
-         bpstat_do_actions (&stop_bpstat);
-     in event-top.c won't do anything, and temporary breakpoints
-     with commands won't work.  */
-
-  iterate_over_threads (bpstat_remove_breakpoint_callback, bpt);
-
   /* Now that breakpoint is removed from breakpoint
      list, update the global location list.  This
      will remove locations that used to belong to
@@ -9339,7 +9764,8 @@ ambiguous_names_p (struct bp_location *loc)
 {
   struct bp_location *l;
   htab_t htab = htab_create_alloc (13, htab_hash_string,
-                                  (int (*) (const void *, const void *)) streq,
+                                  (int (*) (const void *, 
+                                            const void *)) streq,
                                   NULL, xcalloc, xfree);
 
   for (l = loc; l != NULL; l = l->next)
@@ -9367,6 +9793,139 @@ ambiguous_names_p (struct bp_location *loc)
   return 0;
 }
 
+/* When symbols change, it probably means the sources changed as well,
+   and it might mean the static tracepoint markers are no longer at
+   the same address or line numbers they used to be at last we
+   checked.  Losing your static tracepoints whenever you rebuild is
+   undesirable.  This function tries to resync/rematch gdb static
+   tracepoints with the markers on the target, for static tracepoints
+   that have not been set by marker id.  Static tracepoint that have
+   been set by marker id are reset by marker id in breakpoint_re_set.
+   The heuristic is:
+
+   1) For a tracepoint set at a specific address, look for a marker at
+   the old PC.  If one is found there, assume to be the same marker.
+   If the name / string id of the marker found is different from the
+   previous known name, assume that means the user renamed the marker
+   in the sources, and output a warning.
+
+   2) For a tracepoint set at a given line number, look for a marker
+   at the new address of the old line number.  If one is found there,
+   assume to be the same marker.  If the name / string id of the
+   marker found is different from the previous known name, assume that
+   means the user renamed the marker in the sources, and output a
+   warning.
+
+   3) If a marker is no longer found at the same address or line, it
+   may mean the marker no longer exists.  But it may also just mean
+   the code changed a bit.  Maybe the user added a few lines of code
+   that made the marker move up or down (in line number terms).  Ask
+   the target for info about the marker with the string id as we knew
+   it.  If found, update line number and address in the matching
+   static tracepoint.  This will get confused if there's more than one
+   marker with the same ID (possible in UST, although unadvised
+   precisely because it confuses tools).  */
+
+static struct symtab_and_line
+update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
+{
+  struct static_tracepoint_marker marker;
+  CORE_ADDR pc;
+  int i;
+
+  pc = sal.pc;
+  if (sal.line)
+    find_line_pc (sal.symtab, sal.line, &pc);
+
+  if (target_static_tracepoint_marker_at (pc, &marker))
+    {
+      if (strcmp (b->static_trace_marker_id, marker.str_id) != 0)
+       warning (_("static tracepoint %d changed probed marker from %s to %s"),
+                b->number,
+                b->static_trace_marker_id, marker.str_id);
+
+      xfree (b->static_trace_marker_id);
+      b->static_trace_marker_id = xstrdup (marker.str_id);
+      release_static_tracepoint_marker (&marker);
+
+      return sal;
+    }
+
+  /* Old marker wasn't found on target at lineno.  Try looking it up
+     by string ID.  */
+  if (!sal.explicit_pc
+      && sal.line != 0
+      && sal.symtab != NULL
+      && b->static_trace_marker_id != NULL)
+    {
+      VEC(static_tracepoint_marker_p) *markers;
+
+      markers
+       = target_static_tracepoint_markers_by_strid (b->static_trace_marker_id);
+
+      if (!VEC_empty(static_tracepoint_marker_p, markers))
+       {
+         struct symtab_and_line sal;
+         struct symbol *sym;
+         struct static_tracepoint_marker *marker;
+
+         marker = VEC_index (static_tracepoint_marker_p, markers, 0);
+
+         xfree (b->static_trace_marker_id);
+         b->static_trace_marker_id = xstrdup (marker->str_id);
+
+         warning (_("marker for static tracepoint %d (%s) not "
+                    "found at previous line number"),
+                  b->number, b->static_trace_marker_id);
+
+         init_sal (&sal);
+
+         sal.pc = marker->address;
+
+         sal = find_pc_line (marker->address, 0);
+         sym = find_pc_sect_function (marker->address, NULL);
+         ui_out_text (uiout, "Now in ");
+         if (sym)
+           {
+             ui_out_field_string (uiout, "func",
+                                  SYMBOL_PRINT_NAME (sym));
+             ui_out_text (uiout, " at ");
+           }
+         ui_out_field_string (uiout, "file", sal.symtab->filename);
+         ui_out_text (uiout, ":");
+
+         if (ui_out_is_mi_like_p (uiout))
+           {
+             char *fullname = symtab_to_fullname (sal.symtab);
+
+             if (fullname)
+               ui_out_field_string (uiout, "fullname", fullname);
+           }
+
+         ui_out_field_int (uiout, "line", sal.line);
+         ui_out_text (uiout, "\n");
+
+         b->line_number = sal.line;
+
+         xfree (b->source_file);
+         if (sym)
+           b->source_file = xstrdup (sal.symtab->filename);
+         else
+           b->source_file = NULL;
+
+         xfree (b->addr_string);
+         b->addr_string = xstrprintf ("%s:%d",
+                                      sal.symtab->filename, b->line_number);
+
+         /* Might be nice to check if function changed, and warn if
+            so.  */
+
+         release_static_tracepoint_marker (marker);
+       }
+    }
+  return sal;
+}
+
 static void
 update_breakpoint_locations (struct breakpoint *b,
                             struct symtabs_and_lines sals)
@@ -9469,7 +10028,6 @@ update_breakpoint_locations (struct breakpoint *b,
   update_global_location_list (1);
 }
 
-
 /* Reset a breakpoint given it's struct breakpoint * BINT.
    The value we return ends up being the return value from catch_errors.
    Unused in this case.  */
@@ -9479,16 +10037,14 @@ breakpoint_re_set_one (void *bint)
 {
   /* get past catch_errs */
   struct breakpoint *b = (struct breakpoint *) bint;
-  struct value *mark;
-  int i;
   int not_found = 0;
   int *not_found_ptr = &not_found;
   struct symtabs_and_lines sals = {0};
   struct symtabs_and_lines expanded = {0};
   char *s;
-  enum enable_state save_enable;
   struct gdb_exception e;
   struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
+  int marker_spec = 0;
 
   switch (b->type)
     {
@@ -9500,6 +10056,7 @@ breakpoint_re_set_one (void *bint)
     case bp_hardware_breakpoint:
     case bp_tracepoint:
     case bp_fast_tracepoint:
+    case bp_static_tracepoint:
       /* Do not attempt to re-set breakpoints disabled during startup.  */
       if (b->enable_state == bp_startup_disabled)
        return 0;
@@ -9518,10 +10075,24 @@ breakpoint_re_set_one (void *bint)
       save_current_space_and_thread ();
       switch_to_program_space_and_thread (b->pspace);
 
+      marker_spec = b->type == bp_static_tracepoint && is_marker_spec (s);
+
       TRY_CATCH (e, RETURN_MASK_ERROR)
        {
-         sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
-                               not_found_ptr);
+         if (marker_spec)
+           {
+             sals = decode_static_tracepoint_spec (&s);
+             if (sals.nelts > b->static_trace_marker_id_idx)
+               {
+                 sals.sals[0] = sals.sals[b->static_trace_marker_id_idx];
+                 sals.nelts = 1;
+               }
+             else
+               error (_("marker %s not found"), b->static_trace_marker_id);
+           }
+         else
+           sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
+                                 not_found_ptr);
        }
       if (e.reason < 0)
        {
@@ -9571,6 +10142,9 @@ breakpoint_re_set_one (void *bint)
              b->condition_not_parsed = 0;
            }
 
+         if (b->type == bp_static_tracepoint && !marker_spec)
+           sals.sals[0] = update_static_tracepoint (b, sals.sals[0]);
+
          expanded = expand_line_sal_maybe (sals.sals[0]);
        }
 
@@ -9911,6 +10485,7 @@ static void
 disable_command (char *args, int from_tty)
 {
   struct breakpoint *bpt;
+
   if (args == 0)
     ALL_BREAKPOINTS (bpt)
       switch (bpt->type)
@@ -9922,6 +10497,7 @@ disable_command (char *args, int from_tty)
       case bp_breakpoint:
       case bp_tracepoint:
       case bp_fast_tracepoint:
+      case bp_static_tracepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -9946,8 +10522,7 @@ disable_command (char *args, int from_tty)
 static void
 do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
 {
-  int target_resources_ok, other_type_used;
-  struct value *mark;
+  int target_resources_ok;
 
   if (bpt->type == bp_hardware_breakpoint)
     {
@@ -9962,10 +10537,7 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
        error (_("Hardware breakpoints used exceeds limit."));
     }
 
-  if (bpt->type == bp_watchpoint
-      || bpt->type == bp_hardware_watchpoint
-      || bpt->type == bp_read_watchpoint
-      || bpt->type == bp_access_watchpoint)
+  if (is_watchpoint (bpt))
     {
       struct gdb_exception e;
 
@@ -10014,6 +10586,7 @@ static void
 enable_command (char *args, int from_tty)
 {
   struct breakpoint *bpt;
+
   if (args == 0)
     ALL_BREAKPOINTS (bpt)
       switch (bpt->type)
@@ -10025,6 +10598,7 @@ enable_command (char *args, int from_tty)
       case bp_breakpoint:
       case bp_tracepoint:
       case bp_fast_tracepoint:
+      case bp_static_tracepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -10115,6 +10689,7 @@ struct symtabs_and_lines
 decode_line_spec_1 (char *string, int funfirstline)
 {
   struct symtabs_and_lines sals;
+
   if (string == 0)
     error (_("Empty line specification."));
   if (default_breakpoint_valid)
@@ -10232,10 +10807,44 @@ remove_single_step_breakpoints (void)
     }
 }
 
+/* Delete software single step breakpoints without removing them from
+   the inferior.  This is intended to be used if the inferior's address
+   space where they were inserted is already gone, e.g. after exit or
+   exec.  */
+
+void
+cancel_single_step_breakpoints (void)
+{
+  int i;
+
+  for (i = 0; i < 2; i++)
+    if (single_step_breakpoints[i])
+      {
+       xfree (single_step_breakpoints[i]);
+       single_step_breakpoints[i] = NULL;
+       single_step_gdbarch[i] = NULL;
+      }
+}
+
+/* Detach software single-step breakpoints from INFERIOR_PTID without
+   removing them.  */
+
+static void
+detach_single_step_breakpoints (void)
+{
+  int i;
+
+  for (i = 0; i < 2; i++)
+    if (single_step_breakpoints[i])
+      target_remove_breakpoint (single_step_gdbarch[i],
+                               single_step_breakpoints[i]);
+}
+
 /* Check whether a software single-step breakpoint is inserted at PC.  */
 
 static int
-single_step_breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc)
+single_step_breakpoint_inserted_here_p (struct address_space *aspace, 
+                                       CORE_ADDR pc)
 {
   int i;
 
@@ -10303,6 +10912,7 @@ catch_syscall_completer (struct cmd_list_element *cmd,
                          char *text, char *word)
 {
   const char **list = get_syscall_names ();
+
   return (list == NULL) ? NULL : complete_on_enum (list, text, word);
 }
 
@@ -10322,8 +10932,8 @@ trace_command (char *arg, int from_tty)
   if (create_breakpoint (get_current_arch (),
                         arg,
                         NULL, 0, 1 /* parse arg */,
-                        0 /* tempflag */, 0 /* hardwareflag */,
-                        1 /* traceflag */,
+                        0 /* tempflag */,
+                        bp_tracepoint /* type_wanted */,
                         0 /* Ignore count */,
                         pending_break_support,
                         NULL,
@@ -10338,8 +10948,26 @@ ftrace_command (char *arg, int from_tty)
   if (create_breakpoint (get_current_arch (),
                         arg,
                         NULL, 0, 1 /* parse arg */,
-                        0 /* tempflag */, 1 /* hardwareflag */,
-                        1 /* traceflag */,
+                        0 /* tempflag */,
+                        bp_fast_tracepoint /* type_wanted */,
+                        0 /* Ignore count */,
+                        pending_break_support,
+                        NULL,
+                        from_tty,
+                        1 /* enabled */))
+    set_tracepoint_count (breakpoint_count);
+}
+
+/* strace command implementation.  Creates a static tracepoint.  */
+
+void
+strace_command (char *arg, int from_tty)
+{
+  if (create_breakpoint (get_current_arch (),
+                        arg,
+                        NULL, 0, 1 /* parse arg */,
+                        0 /* tempflag */,
+                        bp_static_tracepoint /* type_wanted */,
                         0 /* Ignore count */,
                         pending_break_support,
                         NULL,
@@ -10352,18 +10980,16 @@ ftrace_command (char *arg, int from_tty)
    list that was acquired during tracepoint uploading.  */
 
 static struct uploaded_tp *this_utp;
-static struct uploaded_string *next_cmd;
+static int next_cmd;
 
 static char *
 read_uploaded_action (void)
 {
   char *rslt;
 
-  if (!next_cmd)
-    return NULL;
+  VEC_iterate (char_ptr, this_utp->cmd_strings, next_cmd, rslt);
 
-  rslt = next_cmd->str;
-  next_cmd = next_cmd->next;
+  next_cmd++;
 
   return rslt;
 }
@@ -10403,8 +11029,7 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
                          addr_str,
                          utp->cond_string, -1, 0 /* parse cond/thread */,
                          0 /* tempflag */,
-                         (utp->type == bp_fast_tracepoint) /* hardwareflag */,
-                         1 /* traceflag */,
+                         utp->type /* type_wanted */,
                          0 /* Ignore count */,
                          pending_break_support,
                          NULL,
@@ -10429,18 +11054,19 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
      special-purpose "reader" function and call the usual command line
      reader, then pass the result to the breakpoint command-setting
      function.  */
-  if (utp->cmd_strings)
+  if (!VEC_empty (char_ptr, utp->cmd_strings))
     {
       struct command_line *cmd_list;
 
       this_utp = utp;
-      next_cmd = utp->cmd_strings;
+      next_cmd = 0;
 
       cmd_list = read_command_lines_1 (read_uploaded_action, 1, NULL, NULL);
 
       breakpoint_set_commands (tp, cmd_list);
     }
-  else if (utp->numactions > 0 || utp->num_step_actions > 0)
+  else if (!VEC_empty (char_ptr, utp->actions)
+          || !VEC_empty (char_ptr, utp->step_actions))
     warning (_("Uploaded tracepoint %d actions have no source form, ignoring them"),
             utp->number);
 
@@ -10467,6 +11093,8 @@ tracepoints_info (char *tpnum_exp, int from_tty)
       else
        ui_out_message (uiout, 0, "No tracepoint number %d.\n", tpnum);
     }
+
+  default_collect_info ();
 }
 
 /* The 'enable trace' command enables tracepoints.  
@@ -10649,63 +11277,136 @@ get_tracepoint_by_number (char **arg, int multi_p, int optional_p)
   return NULL;
 }
 
-/* save-tracepoints command */
+/* Save information on user settable breakpoints (watchpoints, etc) to
+   a new script file named FILENAME.  If FILTER is non-NULL, call it
+   on each breakpoint and only include the ones for which it returns
+   non-zero.  */
+
 static void
-tracepoint_save_command (char *args, int from_tty)
+save_breakpoints (char *filename, int from_tty,
+                 int (*filter) (const struct breakpoint *))
 {
   struct breakpoint *tp;
-  int any_tp = 0;
-  struct command_line *line;
+  int any = 0;
   char *pathname;
-  char tmp[40];
   struct cleanup *cleanup;
   struct ui_file *fp;
+  int extra_trace_bits = 0;
 
-  if (args == 0 || *args == 0)
-    error (_("Argument required (file name in which to save tracepoints)"));
+  if (filename == 0 || *filename == 0)
+    error (_("Argument required (file name in which to save)"));
 
   /* See if we have anything to save.  */
-  ALL_TRACEPOINTS (tp)
+  ALL_BREAKPOINTS (tp)
   {
-    any_tp = 1;
-    break;
+    /* Skip internal and momentary breakpoints.  */
+    if (!user_settable_breakpoint (tp))
+      continue;
+
+    /* If we have a filter, only save the breakpoints it accepts.  */
+    if (filter && !filter (tp))
+      continue;
+
+    any = 1;
+
+    if (is_tracepoint (tp))
+      {
+       extra_trace_bits = 1;
+
+       /* We can stop searching.  */
+       break;
+      }
   }
-  if (!any_tp)
+
+  if (!any)
     {
-      warning (_("save-tracepoints: no tracepoints to save."));
+      warning (_("Nothing to save."));
       return;
     }
 
-  pathname = tilde_expand (args);
+  pathname = tilde_expand (filename);
   cleanup = make_cleanup (xfree, pathname);
   fp = gdb_fopen (pathname, "w");
   if (!fp)
-    error (_("Unable to open file '%s' for saving tracepoints (%s)"),
-          args, safe_strerror (errno));
+    error (_("Unable to open file '%s' for saving (%s)"),
+          filename, safe_strerror (errno));
   make_cleanup_ui_file_delete (fp);
 
-  save_trace_state_variables (fp);
+  if (extra_trace_bits)
+    save_trace_state_variables (fp);
 
-  ALL_TRACEPOINTS (tp)
+  ALL_BREAKPOINTS (tp)
   {
-    if (tp->type == bp_fast_tracepoint)
-      fprintf_unfiltered (fp, "ftrace");
-    else
-      fprintf_unfiltered (fp, "trace");
+    /* Skip internal and momentary breakpoints.  */
+    if (!user_settable_breakpoint (tp))
+      continue;
 
-    if (tp->addr_string)
-      fprintf_unfiltered (fp, " %s", tp->addr_string);
+    /* If we have a filter, only save the breakpoints it accepts.  */
+    if (filter && !filter (tp))
+      continue;
+
+    if (tp->ops != NULL)
+      (tp->ops->print_recreate) (tp, fp);
     else
       {
-       sprintf_vma (tmp, tp->loc->address);
-       fprintf_unfiltered (fp, " *0x%s", tmp);
+       if (tp->type == bp_fast_tracepoint)
+         fprintf_unfiltered (fp, "ftrace");
+       if (tp->type == bp_static_tracepoint)
+         fprintf_unfiltered (fp, "strace");
+       else if (tp->type == bp_tracepoint)
+         fprintf_unfiltered (fp, "trace");
+       else if (tp->type == bp_breakpoint && tp->disposition == disp_del)
+         fprintf_unfiltered (fp, "tbreak");
+       else if (tp->type == bp_breakpoint)
+         fprintf_unfiltered (fp, "break");
+       else if (tp->type == bp_hardware_breakpoint
+                && tp->disposition == disp_del)
+         fprintf_unfiltered (fp, "thbreak");
+       else if (tp->type == bp_hardware_breakpoint)
+         fprintf_unfiltered (fp, "hbreak");
+       else if (tp->type == bp_watchpoint)
+         fprintf_unfiltered (fp, "watch");
+       else if (tp->type == bp_hardware_watchpoint)
+         fprintf_unfiltered (fp, "watch");
+       else if (tp->type == bp_read_watchpoint)
+         fprintf_unfiltered (fp, "rwatch");
+       else if (tp->type == bp_access_watchpoint)
+         fprintf_unfiltered (fp, "awatch");
+       else
+         internal_error (__FILE__, __LINE__,
+                         _("unhandled breakpoint type %d"), (int) tp->type);
+
+       if (tp->exp_string)
+         fprintf_unfiltered (fp, " %s", tp->exp_string);
+       else if (tp->addr_string)
+         fprintf_unfiltered (fp, " %s", tp->addr_string);
+       else
+         {
+           char tmp[40];
+
+           sprintf_vma (tmp, tp->loc->address);
+           fprintf_unfiltered (fp, " *0x%s", tmp);
+         }
       }
 
-    if (tp->cond_string)
-      fprintf_unfiltered (fp, " if %s", tp->cond_string);
+    if (tp->thread != -1)
+      fprintf_unfiltered (fp, " thread %d", tp->thread);
+
+    if (tp->task != 0)
+      fprintf_unfiltered (fp, " task %d", tp->task);
 
     fprintf_unfiltered (fp, "\n");
 
+    /* Note, we can't rely on tp->number for anything, as we can't
+       assume the recreated breakpoint numbers will match.  Use $bpnum
+       instead.  */
+
+    if (tp->cond_string)
+      fprintf_unfiltered (fp, "  condition $bpnum %s\n", tp->cond_string);
+
+    if (tp->ignore_count)
+      fprintf_unfiltered (fp, "  ignore $bpnum %d\n", tp->ignore_count);
+
     if (tp->pass_count)
       fprintf_unfiltered (fp, "  passcount %d\n", tp->pass_count);
 
@@ -10713,7 +11414,7 @@ tracepoint_save_command (char *args, int from_tty)
       {
        volatile struct gdb_exception ex;       
 
-       fprintf_unfiltered (fp, "  actions\n");
+       fprintf_unfiltered (fp, "  commands\n");
        
        ui_out_redirect (uiout, fp);
        TRY_CATCH (ex, RETURN_MASK_ERROR)
@@ -10727,15 +11428,46 @@ tracepoint_save_command (char *args, int from_tty)
 
        fprintf_unfiltered (fp, "  end\n");
       }
+
+    if (tp->enable_state == bp_disabled)
+      fprintf_unfiltered (fp, "disable\n");
+
+    /* If this is a multi-location breakpoint, check if the locations
+       should be individually disabled.  Watchpoint locations are
+       special, and not user visible.  */
+    if (!is_watchpoint (tp) && tp->loc && tp->loc->next)
+      {
+       struct bp_location *loc;
+       int n = 1;
+
+       for (loc = tp->loc; loc != NULL; loc = loc->next, n++)
+         if (!loc->enabled)
+           fprintf_unfiltered (fp, "disable $bpnum.%d\n", n);
+      }
   }
 
-  if (*default_collect)
+  if (extra_trace_bits && *default_collect)
     fprintf_unfiltered (fp, "set default-collect %s\n", default_collect);
 
   do_cleanups (cleanup);
   if (from_tty)
-    printf_filtered (_("Tracepoints saved to file '%s'.\n"), args);
-  return;
+    printf_filtered (_("Saved to file '%s'.\n"), filename);
+}
+
+/* The `save breakpoints' command.  */
+
+static void
+save_breakpoints_command (char *args, int from_tty)
+{
+  save_breakpoints (args, from_tty, NULL);
+}
+
+/* The `save tracepoints' command.  */
+
+static void
+save_tracepoints_command (char *args, int from_tty)
+{
+  save_breakpoints (args, from_tty, is_tracepoint);
 }
 
 /* Create a vector of all tracepoints.  */
@@ -10814,11 +11546,17 @@ clear_syscall_counts (struct inferior *inf)
   VEC_free (int, inf->syscalls_counts);
 }
 
+static void
+save_command (char *arg, int from_tty)
+{
+  printf_unfiltered (_("\
+\"save\" must be followed by the name of a save subcommand.\n"));
+  help_list (save_cmdlist, "save ", -1, gdb_stdout);
+}
+
 void
 _initialize_breakpoint (void)
 {
-  static struct cmd_list_element *breakpoint_set_cmdlist;
-  static struct cmd_list_element *breakpoint_show_cmdlist;
   struct cmd_list_element *c;
 
   observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
@@ -10894,7 +11632,7 @@ With a subcommand you can enable temporarily."));
 
   add_com_alias ("en", "enable", class_breakpoint, 1);
 
-  add_abbrev_prefix_cmd ("breakpoints", class_breakpoint, enable_command, _("\
+  add_prefix_cmd ("breakpoints", class_breakpoint, enable_command, _("\
 Enable some breakpoints.\n\
 Give breakpoint numbers (separated by spaces) as arguments.\n\
 This is used to cancel the effect of the \"disable\" command.\n\
@@ -11199,6 +11937,31 @@ BREAK_ARGS_HELP ("ftrace") "\n\
 Do \"help tracepoints\" for info on other tracepoint commands."));
   set_cmd_completer (c, location_completer);
 
+  c = add_com ("strace", class_breakpoint, strace_command, _("\
+Set a static tracepoint at specified line, function or marker.\n\
+\n\
+strace [LOCATION] [if CONDITION]\n\
+LOCATION may be a line number, function name, \"*\" and an address,\n\
+or -m MARKER_ID.\n\
+If a line number is specified, probe the marker at start of code\n\
+for that line.  If a function is specified, probe the marker at start\n\
+of code for that function.  If an address is specified, probe the marker\n\
+at that exact address.  If a marker id is specified, probe the marker\n\
+with that name.  With no LOCATION, uses current execution address of\n\
+the selected stack frame.\n\
+Static tracepoints accept an extra collect action -- ``collect $_sdata''.\n\
+This collects arbitrary user data passed in the probe point call to the\n\
+tracing library.  You can inspect it when analyzing the trace buffer,\n\
+by printing the $_sdata variable like any other convenience variable.\n\
+\n\
+CONDITION is a boolean expression.\n\
+\n\
+Multiple tracepoints at one place are permitted, and useful if conditional.\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.\n\
+Do \"help tracepoints\" for info on other tracepoint commands."));
+  set_cmd_completer (c, location_completer);
+
   add_info ("tracepoints", tracepoints_info, _("\
 Status of tracepoints, or tracepoint number NUMBER.\n\
 Convenience variable \"$tpnum\" contains the number of the\n\
@@ -11232,11 +11995,28 @@ 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, _("\
+  add_prefix_cmd ("save", class_breakpoint, save_command,
+                 _("Save breakpoint definitions as a script."),
+                 &save_cmdlist, "save ",
+                 0/*allow-unknown*/, &cmdlist);
+
+  c = add_cmd ("breakpoints", class_breakpoint, save_breakpoints_command, _("\
+Save current breakpoint definitions as a script.\n\
+This includes all types of breakpoints (breakpoints, watchpoints,\n\
+catchpoints, tracepoints).  Use the 'source' command in another debug\n\
+session to restore them."),
+              &save_cmdlist);
+  set_cmd_completer (c, filename_completer);
+
+  c = add_cmd ("tracepoints", class_trace, save_tracepoints_command, _("\
 Save current tracepoint definitions as a script.\n\
-Use the 'source' command in another debug session to restore them."));
+Use the 'source' command in another debug session to restore them."),
+              &save_cmdlist);
   set_cmd_completer (c, filename_completer);
 
+  c = add_com_alias ("save-tracepoints", "save tracepoints", class_trace, 0);
+  deprecate_cmd (c, "save tracepoints");
+
   add_prefix_cmd ("breakpoint", class_maintenance, set_breakpoint_cmd, _("\
 Breakpoint specific settings\n\
 Configure various breakpoint-specific variables such as\n\
This page took 0.056418 seconds and 4 git commands to generate.