gdb
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index 893e1c294ed99a3cde1a33d3a5f14343d8f55a04..1235946999bf0f7c5377995b46e2e2791d2ada76 100644 (file)
@@ -25,6 +25,7 @@
 #include "symtab.h"
 #include "frame.h"
 #include "breakpoint.h"
+#include "tracepoint.h"
 #include "gdbtypes.h"
 #include "expression.h"
 #include "gdbcore.h"
 #include "wrapper.h"
 #include "valprint.h"
 
+/* readline include files */
+#include "readline/readline.h"
+#include "readline/history.h"
+
+/* readline defines this.  */
+#undef savestring
+
 #include "mi/mi-common.h"
 
 /* Arguments to pass as context to some catch command handlers.  */
@@ -142,8 +150,6 @@ static int watchpoint_check (void *);
 
 static void maintenance_info_breakpoints (char *, int);
 
-static void create_overlay_event_breakpoint (char *);
-
 static int hw_breakpoint_used_count (void);
 
 static int hw_watchpoint_used_count (enum bptype, int *);
@@ -191,6 +197,21 @@ static int is_hardware_watchpoint (struct breakpoint *bpt);
 
 static void insert_breakpoint_locations (void);
 
+static void tracepoints_info (char *, int);
+
+static void delete_trace_command (char *, int);
+
+static void enable_trace_command (char *, int);
+
+static void disable_trace_command (char *, int);
+
+static void trace_pass_command (char *, int);
+
+/* Flag indicating that a command has proceeded the inferior past the
+   current breakpoint.  */
+
+static int breakpoint_proceeded;
+
 static const char *
 bpdisp_text (enum bpdisp disp)
 {
@@ -309,6 +330,12 @@ static int overlay_events_enabled;
             B ? (TMP=B->global_next, 1): 0;    \
             B = TMP)
 
+/* Iterator for tracepoints only.  */
+
+#define ALL_TRACEPOINTS(B)  \
+  for (B = breakpoint_chain; B; B = B->next)  \
+    if ((B)->type == bp_tracepoint)
+
 /* Chains of all breakpoints defined.  */
 
 struct breakpoint *breakpoint_chain;
@@ -324,6 +351,10 @@ VEC(bp_location_p) *moribund_locations = NULL;
 
 int breakpoint_count;
 
+/* Number of last tracepoint made.  */
+
+int tracepoint_count;
+
 /* Return whether a breakpoint is an active enabled breakpoint.  */
 static int
 breakpoint_enabled (struct breakpoint *b)
@@ -566,7 +597,7 @@ condition_command (char *arg, int from_tty)
            arg = p;
            /* I don't know if it matters whether this is the string the user
               typed in or the decompiled expression.  */
-           b->cond_string = savestring (arg, strlen (arg));
+           b->cond_string = xstrdup (arg);
            b->condition_not_parsed = 0;
            for (loc = b->loc; loc; loc = loc->next)
              {
@@ -928,7 +959,7 @@ update_watchpoint (struct breakpoint *b, int reparse)
              b->type = bp_watchpoint;
            else
              {
-               int target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT
+               int target_resources_ok = target_can_use_hardware_watchpoint
                  (bp_hardware_watchpoint, i + mem_cnt, other_type_used);
                if (target_resources_ok <= 0)
                  b->type = bp_watchpoint;
@@ -1024,6 +1055,11 @@ should_be_inserted (struct bp_location *bpt)
   if (!bpt->enabled || bpt->shlib_disabled || bpt->duplicate)
     return 0;
 
+  /* Tracepoints are inserted by the target at a time of its choosing,
+     not by us.  */
+  if (bpt->owner->type == bp_tracepoint)
+    return 0;
+
   return 1;
 }
 
@@ -1254,8 +1290,7 @@ insert_breakpoints (void)
 
   if (!breakpoints_always_inserted_mode ()
       && (target_has_execution
-         || (gdbarch_has_global_solist (target_gdbarch)
-             && target_supports_multi_process ())))
+         || gdbarch_has_global_breakpoints (target_gdbarch)))
     /* update_global_location_list does not insert breakpoints
        when always_inserted_mode is not enabled.  Explicitly
        insert them now.  */
@@ -1421,12 +1456,59 @@ reattach_breakpoints (int pid)
   return 0;
 }
 
+static int internal_breakpoint_number = -1;
+
+static struct breakpoint *
+create_internal_breakpoint (CORE_ADDR address, enum bptype type)
+{
+  struct symtab_and_line sal;
+  struct breakpoint *b;
+
+  init_sal (&sal);             /* initialize to zeroes */
+
+  sal.pc = address;
+  sal.section = find_pc_overlay (sal.pc);
+
+  b = set_raw_breakpoint (sal, type);
+  b->number = internal_breakpoint_number--;
+  b->disposition = disp_donttouch;
+
+  return b;
+}
+
+static void
+create_overlay_event_breakpoint (char *func_name, struct objfile *objfile)
+{
+  struct breakpoint *b;
+  struct minimal_symbol *m;
+
+  if ((m = lookup_minimal_symbol_text (func_name, objfile)) == NULL)
+    return;
+
+  b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m),
+                                 bp_overlay_event);
+  b->addr_string = xstrdup (func_name);
+
+  if (overlay_debugging == ovly_auto)
+    {
+      b->enable_state = bp_enabled;
+      overlay_events_enabled = 1;
+    }
+  else
+    {
+      b->enable_state = bp_disabled;
+      overlay_events_enabled = 0;
+    }
+  update_global_location_list (1);
+}
+
 void
 update_breakpoints_after_exec (void)
 {
   struct breakpoint *b;
   struct breakpoint *temp;
   struct bp_location *bploc;
+  struct objfile *objfile;
 
   /* We're about to delete breakpoints from GDB's lists.  If the
      INSERTED flag is true, GDB will try to lift the breakpoints by
@@ -1521,7 +1603,8 @@ update_breakpoints_after_exec (void)
       }
   }
   /* FIXME what about longjmp breakpoints?  Re-create them here?  */
-  create_overlay_event_breakpoint ("_ovly_debug_event");
+  ALL_OBJFILES (objfile)
+    create_overlay_event_breakpoint ("_ovly_debug_event", objfile);
 }
 
 int
@@ -1697,7 +1780,7 @@ breakpoint_init_inferior (enum inf_context context)
 
   /* If breakpoint locations are shared across processes, then there's
      nothing to do.  */
-  if (gdbarch_has_global_solist (target_gdbarch))
+  if (gdbarch_has_global_breakpoints (target_gdbarch))
     return;
 
   ALL_BP_LOCATIONS (bpt)
@@ -1888,28 +1971,51 @@ int
 breakpoint_thread_match (CORE_ADDR pc, ptid_t ptid)
 {
   const struct bp_location *bpt;
-  int thread;
-
-  thread = pid_to_thread_id (ptid);
-
+  /* The thread and task IDs associated to PTID, computed lazily.  */
+  int thread = -1;
+  int task = 0;
+  
   ALL_BP_LOCATIONS (bpt)
     {
       if (bpt->loc_type != bp_loc_software_breakpoint
          && bpt->loc_type != bp_loc_hardware_breakpoint)
        continue;
 
-      if ((breakpoint_enabled (bpt->owner)
-          || bpt->owner->enable_state == bp_permanent)
-         && bpt->address == pc
-         && (bpt->owner->thread == -1 || bpt->owner->thread == thread))
+      if (!breakpoint_enabled (bpt->owner)
+         && bpt->owner->enable_state != bp_permanent)
+       continue;
+
+      if (bpt->address != pc)
+       continue;
+
+      if (bpt->owner->thread != -1)
        {
-         if (overlay_debugging 
-             && section_is_overlay (bpt->section) 
-             && !section_is_mapped (bpt->section))
-           continue;           /* unmapped overlay -- can't be a match */
-         else
-           return 1;
+         /* This is a thread-specific breakpoint.  Check that ptid
+            matches that thread.  If thread hasn't been computed yet,
+            it is now time to do so.  */
+         if (thread == -1)
+           thread = pid_to_thread_id (ptid);
+         if (bpt->owner->thread != thread)
+           continue;
        }
+
+      if (bpt->owner->task != 0)
+        {
+         /* This is a task-specific breakpoint.  Check that ptid
+            matches that task.  If task hasn't been computed yet,
+            it is now time to do so.  */
+         if (task == 0)
+           task = ada_get_task_number (ptid);
+         if (bpt->owner->task != task)
+           continue;
+        }
+
+      if (overlay_debugging 
+         && section_is_overlay (bpt->section) 
+         && !section_is_mapped (bpt->section))
+       continue;           /* unmapped overlay -- can't be a match */
+
+      return 1;
     }
 
   return 0;
@@ -2083,6 +2189,26 @@ bpstat_clear_actions (bpstat bs)
     }
 }
 
+/* Called when a command is about to proceed the inferior.  */
+
+static void
+breakpoint_about_to_proceed (void)
+{
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    {
+      struct thread_info *tp = inferior_thread ();
+
+      /* Allow inferior function calls in breakpoint commands to not
+        interrupt the command list.  When the call finishes
+        successfully, the inferior will be standing at the same
+        breakpoint as if nothing happened.  */
+      if (tp->in_infcall)
+       return;
+    }
+
+  breakpoint_proceeded = 1;
+}
+
 /* Stub for cleaning up our state if we error-out of a breakpoint command */
 static void
 cleanup_executing_breakpoints (void *ignore)
@@ -2387,6 +2513,7 @@ print_it_typical (bpstat bs)
     case bp_step_resume:
     case bp_watchpoint_scope:
     case bp_call_dummy:
+    case bp_tracepoint:
     default:
       result = PRINT_UNKNOWN;
       break;
@@ -2520,7 +2647,7 @@ bpstat_alloc (const struct bp_location *bl, bpstat cbs /* Current "bs" value */
 int
 watchpoints_triggered (struct target_waitstatus *ws)
 {
-  int stopped_by_watchpoint = STOPPED_BY_WATCHPOINT (*ws);
+  int stopped_by_watchpoint = target_stopped_by_watchpoint ();
   CORE_ADDR addr;
   struct breakpoint *b;
 
@@ -2630,9 +2757,15 @@ watchpoint_check (void *p)
         that the watchpoint frame couldn't be found by frame_find_by_id()
         because the current PC is currently in an epilogue.  Calling
         gdbarch_in_function_epilogue_p() also when fr == NULL fixes that. */
-      if ((!within_current_scope || fr == get_current_frame ())
-          && gdbarch_in_function_epilogue_p (current_gdbarch, read_pc ()))
-       return WP_VALUE_NOT_CHANGED;
+      if (!within_current_scope || fr == get_current_frame ())
+       {
+         struct frame_info *frame = get_current_frame ();
+         struct gdbarch *frame_arch = get_frame_arch (frame);
+         CORE_ADDR frame_pc = get_frame_pc (frame);
+
+         if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc))
+           return WP_VALUE_NOT_CHANGED;
+       }
       if (fr && within_current_scope)
        /* If we end up stopping, the current frame will get selected
           in normal_stop.  So this call to select_frame won't affect
@@ -2882,6 +3015,13 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
       
       if (bl->cond && bl->owner->disposition != disp_del_at_next_stop)
        {
+         /* We use value_mark and value_free_to_mark because it could
+            be a long time before we return to the command level and
+            call free_all_values.  We can't call free_all_values
+            because we might be in the middle of evaluating a
+            function call.  */
+         struct value *mark = value_mark ();
+
          /* Need to select the frame, with all that implies
             so that the conditions will have the right context.  */
          select_frame (get_current_frame ());
@@ -2890,7 +3030,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
                            "Error in testing breakpoint condition:\n",
                            RETURN_MASK_ALL);
          /* FIXME-someday, should give breakpoint # */
-         free_all_values ();
+         value_free_to_mark (mark);
        }
       if (bl->cond && value_is_zero)
        {
@@ -3281,6 +3421,13 @@ bpstat_what (bpstat bs)
          bs_class = bp_silent;
          retval.call_dummy = 1;
          break;
+       case bp_tracepoint:
+         /* Tracepoint hits should not be reported back to GDB, and
+            if one got through somehow, it should have been filtered
+            out already.  */
+         internal_error (__FILE__, __LINE__,
+                         _("bpstat_what: bp_tracepoint encountered"));
+         break;
        }
       current_action = table[(int) bs_class][(int) current_action];
     }
@@ -3297,7 +3444,7 @@ bpstat_should_step (void)
 {
   struct breakpoint *b;
   ALL_BREAKPOINTS (b)
-    if (breakpoint_enabled (b) && b->type == bp_watchpoint)
+    if (breakpoint_enabled (b) && b->type == bp_watchpoint && b->loc != NULL)
       return 1;
   return 0;
 }
@@ -3380,6 +3527,7 @@ print_one_breakpoint_location (struct breakpoint *b,
     {bp_thread_event, "thread events"},
     {bp_overlay_event, "overlay events"},
     {bp_catchpoint, "catchpoint"},
+    {bp_tracepoint, "tracepoint"},
   };
   
   static char bpenables[] = "nynny";
@@ -3506,6 +3654,7 @@ print_one_breakpoint_location (struct breakpoint *b,
       case bp_shlib_event:
       case bp_thread_event:
       case bp_overlay_event:
+      case bp_tracepoint:
        if (opts.addressprint)
          {
            annotate_field (4);
@@ -3524,12 +3673,20 @@ print_one_breakpoint_location (struct breakpoint *b,
        break;
       }
 
-  if (!part_of_multiple && b->thread != -1)
+  if (!part_of_multiple)
     {
-      /* FIXME: This seems to be redundant and lost here; see the
-        "stop only in" line a little further down. */
-      ui_out_text (uiout, " thread ");
-      ui_out_field_int (uiout, "thread", b->thread);
+      if (b->thread != -1)
+       {
+         /* FIXME: This seems to be redundant and lost here; see the
+            "stop only in" line a little further down. */
+         ui_out_text (uiout, " thread ");
+         ui_out_field_int (uiout, "thread", b->thread);
+       }
+      else if (b->task != 0)
+       {
+         ui_out_text (uiout, " task ");
+         ui_out_field_int (uiout, "task", b->task);
+       }
     }
   
   ui_out_text (uiout, "\n");
@@ -3550,7 +3707,10 @@ print_one_breakpoint_location (struct breakpoint *b,
          because the condition is an internal implementation detail
          that we do not want to expose to the user.  */
       annotate_field (7);
-      ui_out_text (uiout, "\tstop only if ");
+      if (b->type == bp_tracepoint)
+       ui_out_text (uiout, "\ttrace only if ");
+      else
+       ui_out_text (uiout, "\tstop only if ");
       ui_out_field_string (uiout, "cond", b->cond_string);
       ui_out_text (uiout, "\n");
     }
@@ -3602,6 +3762,34 @@ print_one_breakpoint_location (struct breakpoint *b,
       do_cleanups (script_chain);
     }
 
+  if (!part_of_multiple && b->pass_count)
+    {
+      annotate_field (10);
+      ui_out_text (uiout, "\tpass count ");
+      ui_out_field_int (uiout, "pass", b->pass_count);
+      ui_out_text (uiout, " \n");
+    }
+
+  if (!part_of_multiple && b->step_count)
+    {
+      annotate_field (11);
+      ui_out_text (uiout, "\tstep count ");
+      ui_out_field_int (uiout, "step", b->step_count);
+      ui_out_text (uiout, " \n");
+    }
+
+  if (!part_of_multiple && b->actions)
+    {
+      struct action_line *action;
+      annotate_field (12);
+      for (action = b->actions; action; action = action->next)
+       {
+         ui_out_text (uiout, "      A\t");
+         ui_out_text (uiout, action->action);
+         ui_out_text (uiout, "\n");
+       }
+    }
+
   if (ui_out_is_mi_like_p (uiout) && !part_of_multiple)
     {
       if (b->addr_string)
@@ -3692,6 +3880,7 @@ user_settable_breakpoint (const struct breakpoint *b)
   return (b->type == bp_breakpoint
          || b->type == bp_catchpoint
          || b->type == bp_hardware_breakpoint
+         || b->type == bp_tracepoint
          || b->type == bp_watchpoint
          || b->type == bp_read_watchpoint
          || b->type == bp_access_watchpoint
@@ -4070,6 +4259,7 @@ allocate_bp_location (struct breakpoint *bpt)
   switch (bpt->type)
     {
     case bp_breakpoint:
+    case bp_tracepoint:
     case bp_until:
     case bp_finish:
     case bp_longjmp:
@@ -4159,7 +4349,8 @@ static void
 set_breakpoint_location_function (struct bp_location *loc)
 {
   if (loc->owner->type == bp_breakpoint
-      || loc->owner->type == bp_hardware_breakpoint)
+      || loc->owner->type == bp_hardware_breakpoint
+      || loc->owner->type == bp_tracepoint)
     {
       find_pc_partial_function (loc->address, &(loc->function_name), 
                                NULL, NULL);
@@ -4204,8 +4395,7 @@ set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
   if (sal.symtab == NULL)
     b->source_file = NULL;
   else
-    b->source_file = savestring (sal.symtab->filename,
-                                strlen (sal.symtab->filename));
+    b->source_file = xstrdup (sal.symtab->filename);
   b->loc->section = sal.section;
   b->line_number = sal.line;
 
@@ -4234,26 +4424,6 @@ make_breakpoint_permanent (struct breakpoint *b)
     bl->inserted = 1;
 }
 
-static struct breakpoint *
-create_internal_breakpoint (CORE_ADDR address, enum bptype type)
-{
-  static int internal_breakpoint_number = -1;
-  struct symtab_and_line sal;
-  struct breakpoint *b;
-
-  init_sal (&sal);             /* initialize to zeroes */
-
-  sal.pc = address;
-  sal.section = find_pc_overlay (sal.pc);
-
-  b = set_raw_breakpoint (sal, type);
-  b->number = internal_breakpoint_number--;
-  b->disposition = disp_donttouch;
-
-  return b;
-}
-
-
 static void
 create_longjmp_breakpoint (char *func_name)
 {
@@ -4295,40 +4465,6 @@ delete_longjmp_breakpoint (int thread)
       }
 }
 
-static void
-create_overlay_event_breakpoint_1 (char *func_name, struct objfile *objfile)
-{
-  struct breakpoint *b;
-  struct minimal_symbol *m;
-
-  if ((m = lookup_minimal_symbol_text (func_name, objfile)) == NULL)
-    return;
-  b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m), 
-                                 bp_overlay_event);
-  b->addr_string = xstrdup (func_name);
-
-  if (overlay_debugging == ovly_auto)
-    {
-      b->enable_state = bp_enabled;
-      overlay_events_enabled = 1;
-    }
-  else 
-    {
-      b->enable_state = bp_disabled;
-      overlay_events_enabled = 0;
-    }
-  update_global_location_list (1);
-}
-
-static void
-create_overlay_event_breakpoint (char *func_name)
-{
-  struct objfile *objfile;
-  ALL_OBJFILES (objfile)
-    create_overlay_event_breakpoint_1 (func_name, objfile);
-}
-
 void
 enable_overlay_breakpoints (void)
 {
@@ -4434,7 +4570,9 @@ disable_breakpoints_in_shlibs (void)
        becomes enabled, or the duplicate is removed, gdb will try to insert
        all breakpoints.  If we don't set shlib_disabled here, we'll try
        to insert those breakpoints and fail.  */
-    if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint))
+    if (((b->type == bp_breakpoint)
+        || (b->type == bp_hardware_breakpoint)
+        || (b->type == bp_tracepoint))
        && !loc->shlib_disabled
 #ifdef PC_SOLIB
        && PC_SOLIB (loc->address)
@@ -4470,28 +4608,22 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
     struct breakpoint *b = loc->owner;
     if ((loc->loc_type == bp_loc_hardware_breakpoint
         || loc->loc_type == bp_loc_software_breakpoint)
-       && !loc->shlib_disabled)
+       && !loc->shlib_disabled
+       && (b->type == bp_breakpoint || b->type == bp_hardware_breakpoint)
+       && solib_contains_address_p (solib, loc->address))
       {
-#ifdef PC_SOLIB
-       char *so_name = PC_SOLIB (loc->address);
-#else
-       char *so_name = solib_name_from_address (loc->address);
-#endif
-       if (so_name && !strcmp (so_name, solib->so_name))
-          {
-           loc->shlib_disabled = 1;
-           /* At this point, we cannot rely on remove_breakpoint
-              succeeding so we must mark the breakpoint as not inserted
-              to prevent future errors occurring in remove_breakpoints.  */
-           loc->inserted = 0;
-           if (!disabled_shlib_breaks)
-             {
-               target_terminal_ours_for_output ();
-               warning (_("Temporarily disabling breakpoints for unloaded shared library \"%s\""),
-                         so_name);
-             }
-           disabled_shlib_breaks = 1;
+       loc->shlib_disabled = 1;
+       /* At this point, we cannot rely on remove_breakpoint
+          succeeding so we must mark the breakpoint as not inserted
+          to prevent future errors occurring in remove_breakpoints.  */
+       loc->inserted = 0;
+       if (!disabled_shlib_breaks)
+         {
+           target_terminal_ours_for_output ();
+           warning (_("Temporarily disabling breakpoints for unloaded shared library \"%s\""),
+                    solib->so_name);
          }
+       disabled_shlib_breaks = 1;
       }
   }
 }
@@ -4684,8 +4816,7 @@ create_catchpoint (int tempflag, char *cond_string,
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
 
-  b->cond_string = (cond_string == NULL) ? 
-    NULL : savestring (cond_string, strlen (cond_string));
+  b->cond_string = (cond_string == NULL) ? NULL : xstrdup (cond_string);
   b->thread = -1;
   b->addr_string = NULL;
   b->enable_state = bp_enabled;
@@ -4877,6 +5008,43 @@ set_momentary_breakpoint (struct symtab_and_line sal, struct frame_id frame_id,
   return b;
 }
 
+/* Make a deep copy of momentary breakpoint ORIG.  Returns NULL if
+   ORIG is NULL.  */
+
+struct breakpoint *
+clone_momentary_breakpoint (struct breakpoint *orig)
+{
+  struct breakpoint *copy;
+
+  /* If there's nothing to clone, then return nothing.  */
+  if (orig == NULL)
+    return NULL;
+
+  copy = set_raw_breakpoint_without_location (orig->type);
+  copy->loc = allocate_bp_location (copy);
+  set_breakpoint_location_function (copy->loc);
+
+  copy->loc->requested_address = orig->loc->requested_address;
+  copy->loc->address = orig->loc->address;
+  copy->loc->section = orig->loc->section;
+
+  if (orig->source_file == NULL)
+    copy->source_file = NULL;
+  else
+    copy->source_file = xstrdup (orig->source_file);
+
+  copy->line_number = orig->line_number;
+  copy->frame_id = orig->frame_id;
+  copy->thread = orig->thread;
+
+  copy->enable_state = bp_enabled;
+  copy->disposition = disp_donttouch;
+  copy->number = internal_breakpoint_number--;
+
+  update_global_location_list_nothrow (0);
+  return copy;
+}
+
 struct breakpoint *
 set_momentary_breakpoint_at_pc (CORE_ADDR pc, enum bptype type)
 {
@@ -4970,6 +5138,16 @@ mention (struct breakpoint *b)
        printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
        say_where = 1;
        break;
+      case bp_tracepoint:
+       if (ui_out_is_mi_like_p (uiout))
+         {
+           say_where = 0;
+           break;
+         }
+       printf_filtered (_("Tracepoint"));
+       printf_filtered (_(" %d"), b->number);
+       say_where = 1;
+       break;
 
       case bp_until:
       case bp_finish:
@@ -5087,7 +5265,7 @@ static void
 create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
                   char *cond_string,
                   enum bptype type, enum bpdisp disposition,
-                  int thread, int ignore_count, 
+                  int thread, int task, int ignore_count, 
                   struct breakpoint_ops *ops, int from_tty, int enabled)
 {
   struct breakpoint *b = NULL;
@@ -5097,7 +5275,7 @@ create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
     {
       int i = hw_breakpoint_used_count ();
       int target_resources_ok = 
-       TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, 
+       target_can_use_hardware_watchpoint (bp_hardware_breakpoint, 
                                            i + 1, 0);
       if (target_resources_ok == 0)
        error (_("No hardware breakpoint support in the target."));
@@ -5119,6 +5297,7 @@ create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
          set_breakpoint_count (breakpoint_count + 1);
          b->number = breakpoint_count;
          b->thread = thread;
+         b->task = task;
   
          b->cond_string = cond_string;
          b->ignore_count = ignore_count;
@@ -5297,7 +5476,7 @@ static void
 create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
                    char *cond_string,
                    enum bptype type, enum bpdisp disposition,
-                   int thread, int ignore_count, 
+                   int thread, int task, int ignore_count, 
                    struct breakpoint_ops *ops, int from_tty,
                    int enabled)
 {
@@ -5309,10 +5488,8 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
 
       create_breakpoint (expanded, addr_string[i],
                         cond_string, type, disposition,
-                        thread, ignore_count, ops, from_tty, enabled);
+                        thread, task, ignore_count, ops, from_tty, enabled);
     }
-
-  update_global_location_list (1);
 }
 
 /* Parse ARG which is assumed to be a SAL specification possibly
@@ -5343,6 +5520,14 @@ parse_breakpoint_sals (char **address,
          sal.line = default_breakpoint_line;
          sal.symtab = default_breakpoint_symtab;
          sal.section = find_pc_overlay (sal.pc);
+
+         /* "break" without arguments is equivalent to "break *PC" where PC is
+            the default_breakpoint_address.  So make sure to set
+            sal.explicit_pc to prevent GDB from trying to expand the list of
+            sals to include all other instances with the same symtab and line.
+          */
+         sal.explicit_pc = 1;
+
          sals->sals[0] = sal;
          sals->nelts = 1;
        }
@@ -5416,7 +5601,7 @@ do_captured_parse_breakpoint (struct ui_out *ui, void *data)
    If no thread is found, *THREAD is set to -1.  */
 static void 
 find_condition_and_thread (char *tok, CORE_ADDR pc, 
-                          char **cond_string, int *thread)
+                          char **cond_string, int *thread, int *task)
 {
   *cond_string = NULL;
   *thread = -1;
@@ -5459,6 +5644,18 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
          if (!valid_thread_id (*thread))
            error (_("Unknown thread %d."), *thread);
        }
+      else if (toklen >= 1 && strncmp (tok, "task", toklen) == 0)
+       {
+         char *tmptok;
+
+         tok = end_tok + 1;
+         tmptok = tok;
+         *task = strtol (tok, &tok, 0);
+         if (tok == tmptok)
+           error (_("Junk after task keyword."));
+         if (!valid_task_id (*task))
+           error (_("Unknown task %d\n"), *task);
+       }
       else
        error (_("Junk at end of arguments."));
     }
@@ -5477,7 +5674,7 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
 static void
 break_command_really (char *arg, char *cond_string, int thread,
                      int parse_condition_and_thread,
-                     int tempflag, int hardwareflag, 
+                     int tempflag, int hardwareflag, int traceflag,
                      int ignore_count,
                      enum auto_boolean pending_break_support,
                      struct breakpoint_ops *ops,
@@ -5497,6 +5694,8 @@ break_command_really (char *arg, char *cond_string, int thread,
   int i;
   int pending = 0;
   int not_found = 0;
+  enum bptype type_wanted;
+  int task = 0;
 
   sals.sals = NULL;
   sals.nelts = 0;
@@ -5585,6 +5784,10 @@ break_command_really (char *arg, char *cond_string, int thread,
   if (!pending)
     breakpoint_sals_to_pc (&sals, addr_start);
 
+  type_wanted = (traceflag
+                ? bp_tracepoint
+                : (hardwareflag ? bp_hardware_breakpoint : bp_breakpoint));
+
   /* Verify that condition can be parsed, before setting any
      breakpoints.  Allocate a separate condition expression for each
      breakpoint. */
@@ -5598,7 +5801,8 @@ break_command_really (char *arg, char *cond_string, int thread,
                re-parse it in context of each sal.  */
             cond_string = NULL;
             thread = -1;
-            find_condition_and_thread (arg, sals.sals[0].pc, &cond_string, &thread);
+            find_condition_and_thread (arg, sals.sals[0].pc, &cond_string,
+                                       &thread, &task);
             if (cond_string)
                 make_cleanup (xfree, cond_string);
         }
@@ -5611,11 +5815,9 @@ break_command_really (char *arg, char *cond_string, int thread,
                 make_cleanup (xfree, cond_string);
             }
         }
-      create_breakpoints (sals, addr_string, cond_string,
-                         hardwareflag ? bp_hardware_breakpoint 
-                         : bp_breakpoint,
+      create_breakpoints (sals, addr_string, cond_string, type_wanted,
                          tempflag ? disp_del : disp_donttouch,
-                         thread, ignore_count, ops, from_tty, enabled);
+                         thread, task, ignore_count, ops, from_tty, enabled);
     }
   else
     {
@@ -5624,9 +5826,7 @@ break_command_really (char *arg, char *cond_string, int thread,
 
       make_cleanup (xfree, copy_arg);
 
-      b = set_raw_breakpoint_without_location (hardwareflag 
-                                              ? bp_hardware_breakpoint 
-                                              : bp_breakpoint);
+      b = set_raw_breakpoint_without_location (type_wanted);
       set_breakpoint_count (breakpoint_count + 1);
       b->number = breakpoint_count;
       b->thread = -1;
@@ -5638,7 +5838,6 @@ break_command_really (char *arg, char *cond_string, int thread,
       b->ops = ops;
       b->enable_state = enabled ? bp_enabled : bp_disabled;
 
-      update_global_location_list (1);
       mention (b);
     }
   
@@ -5650,6 +5849,9 @@ break_command_really (char *arg, char *cond_string, int thread,
   discard_cleanups (breakpoint_chain);
   /* But cleanup everything else. */
   do_cleanups (old_chain);
+
+  /* error call may happen here - have BREAKPOINT_CHAIN already discarded.  */
+  update_global_location_list (1);
 }
 
 /* Set a breakpoint. 
@@ -5667,7 +5869,7 @@ break_command_1 (char *arg, int flag, int from_tty)
 
   break_command_really (arg, 
                        NULL, 0, 1 /* parse arg */,
-                       tempflag, hardwareflag,
+                       tempflag, hardwareflag, 0 /* traceflag */,
                        0 /* Ignore count */,
                        pending_break_support, 
                        NULL /* breakpoint_ops */,
@@ -5684,7 +5886,7 @@ set_breakpoint (char *address, char *condition,
 {
   break_command_really (address, condition, thread,
                        0 /* condition and thread are valid.  */,
-                       tempflag, hardwareflag,
+                       tempflag, hardwareflag, 0 /* traceflag */,
                        ignore_count,
                        pending 
                        ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
@@ -5728,7 +5930,12 @@ resolve_sal_pc (struct symtab_and_line *sal)
       /* If this SAL corresponds to a breakpoint inserted using
          a line number, then skip the function prologue if necessary.  */
       if (sal->explicit_line)
-        skip_prologue_sal (sal);
+       {
+         /* Preserve the original line number.  */
+         int saved_line = sal->line;
+         skip_prologue_sal (sal);
+         sal->line = saved_line;
+       }
     }
 
   if (sal->section == 0 && sal->symtab != NULL)
@@ -5997,7 +6204,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
     {
       i = hw_watchpoint_used_count (bp_type, &other_type_used);
       target_resources_ok = 
-       TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_type, i + mem_cnt, 
+       target_can_use_hardware_watchpoint (bp_type, i + mem_cnt, 
                                            other_type_used);
       if (target_resources_ok == 0 && bp_type != bp_hardware_watchpoint)
        error (_("Target does not support this type of hardware watchpoint."));
@@ -6135,7 +6342,7 @@ can_use_hardware_watchpoint (struct value *v)
                  CORE_ADDR vaddr = VALUE_ADDRESS (v) + value_offset (v);
                  int       len   = TYPE_LENGTH (value_type (v));
 
-                 if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (vaddr, len))
+                 if (!target_region_ok_for_hw_watchpoint (vaddr, len))
                    return 0;
                  else
                    found_memory_cnt++;
@@ -6464,7 +6671,7 @@ print_exception_catchpoint (struct breakpoint *b)
     breakpoint_adjustment_warning (b->loc->requested_address,
                                   b->loc->address,
                                   b->number, 1);
-  bp_temp = b->loc->owner->disposition == disp_del;
+  bp_temp = b->disposition == disp_del;
   ui_out_text (uiout, 
               bp_temp ? "Temporary catchpoint "
                       : "Catchpoint ");
@@ -6511,7 +6718,7 @@ print_mention_exception_catchpoint (struct breakpoint *b)
   int bp_temp;
   int bp_throw;
 
-  bp_temp = b->loc->owner->disposition == disp_del;
+  bp_temp = b->disposition == disp_del;
   bp_throw = strstr (b->addr_string, "throw") != NULL;
   ui_out_text (uiout, bp_temp ? _("Temporary catchpoint ")
                              : _("Catchpoint "));
@@ -6542,7 +6749,7 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
 
   break_command_really (trigger_func_name, cond_string, -1,
                        0 /* condition and thread are valid.  */,
-                       tempflag, 0,
+                       tempflag, 0, 0,
                        0,
                        AUTO_BOOLEAN_TRUE /* pending */,
                        &gnu_v3_exception_catchpoint_ops, from_tty,
@@ -7028,8 +7235,7 @@ update_global_location_list (int should_insert)
 
   if (breakpoints_always_inserted_mode () && should_insert
       && (target_has_execution
-         || (gdbarch_has_global_solist (target_gdbarch)
-             && target_supports_multi_process ())))
+         || (gdbarch_has_global_breakpoints (target_gdbarch))))
     insert_breakpoint_locations ();
 
   do_cleanups (cleanups);
@@ -7320,9 +7526,7 @@ update_breakpoint_locations (struct breakpoint *b,
       if (sals.sals[i].symtab == NULL)
        b->source_file = NULL;
       else
-       b->source_file =
-         savestring (sals.sals[i].symtab->filename,
-                     strlen (sals.sals[i].symtab->filename));
+       b->source_file = xstrdup (sals.sals[i].symtab->filename);
 
       if (b->line_number == 0)
        b->line_number = sals.sals[i].line;
@@ -7402,6 +7606,7 @@ breakpoint_re_set_one (void *bint)
       return 0;
     case bp_breakpoint:
     case bp_hardware_breakpoint:
+    case bp_tracepoint:
       if (b->addr_string == NULL)
        {
          /* Anything without a string can't be re-set. */
@@ -7454,11 +7659,14 @@ breakpoint_re_set_one (void *bint)
        {
          char *cond_string = 0;
          int thread = -1;
+         int task = 0;
+
          find_condition_and_thread (s, sals.sals[0].pc, 
-                                    &cond_string, &thread);
+                                    &cond_string, &thread, &task);
          if (cond_string)
            b->cond_string = cond_string;
          b->thread = thread;
+         b->task = task;
          b->condition_not_parsed = 0;
        }
       expanded = expand_line_sal_maybe (sals.sals[0]);
@@ -7538,9 +7746,13 @@ breakpoint_re_set_one (void *bint)
   return 0;
 }
 
-/* Re-set all breakpoints after symbols have been re-loaded.  */
+/* Re-set all breakpoints after symbols have been re-loaded.
+
+   If OBJFILE is non-null, create overlay break point only in OBJFILE
+   (speed optimization).  Otherwise rescan all loaded objfiles.  */
+
 void
-breakpoint_re_set (void)
+breakpoint_re_set_objfile (struct objfile *objfile)
 {
   struct breakpoint *b, *temp;
   enum language save_language;
@@ -7559,8 +7771,20 @@ breakpoint_re_set (void)
   }
   set_language (save_language);
   input_radix = save_input_radix;
-  
-  create_overlay_event_breakpoint ("_ovly_debug_event");
+
+  if (objfile == NULL)
+    ALL_OBJFILES (objfile)
+      create_overlay_event_breakpoint ("_ovly_debug_event", objfile);
+  else
+    create_overlay_event_breakpoint ("_ovly_debug_event", objfile);
+}
+
+/* Re-set all breakpoints after symbols have been re-loaded.  */
+
+void
+breakpoint_re_set (void)
+{
+  breakpoint_re_set_objfile (NULL);
 }
 \f
 /* Reset the thread number of this breakpoint:
@@ -7767,6 +7991,7 @@ disable_command (char *args, int from_tty)
                 bpt->number);
        continue;
       case bp_breakpoint:
+      case bp_tracepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -7799,7 +8024,7 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
       int i;
       i = hw_breakpoint_used_count ();
       target_resources_ok = 
-       TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, 
+       target_can_use_hardware_watchpoint (bp_hardware_breakpoint, 
                                            i + 1, 0);
       if (target_resources_ok == 0)
        error (_("No hardware breakpoint support in the target."));
@@ -7859,6 +8084,7 @@ enable_command (char *args, int from_tty)
                 bpt->number);
        continue;
       case bp_breakpoint:
+      case bp_tracepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -8042,6 +8268,324 @@ single_step_breakpoint_inserted_here_p (CORE_ADDR pc)
   return 0;
 }
 
+/* Tracepoint-specific operations.  */
+
+/* Set tracepoint count to NUM.  */
+static void
+set_tracepoint_count (int num)
+{
+  tracepoint_count = num;
+  set_internalvar (lookup_internalvar ("tpnum"),
+                  value_from_longest (builtin_type_int32, (LONGEST) num));
+}
+
+void
+trace_command (char *arg, int from_tty)
+{
+  break_command_really (arg, 
+                       NULL, 0, 1 /* parse arg */,
+                       0 /* tempflag */, 0 /* hardwareflag */,
+                       1 /* traceflag */,
+                       0 /* Ignore count */,
+                       pending_break_support, 
+                       NULL,
+                       from_tty,
+                       1 /* enabled */);
+  set_tracepoint_count (breakpoint_count);
+}
+
+/* Print information on tracepoint number TPNUM_EXP, or all if
+   omitted.  */
+
+static void
+tracepoints_info (char *tpnum_exp, int from_tty)
+{
+  struct breakpoint *b;
+  int tps_to_list = 0;
+
+  /* In the no-arguments case, say "No tracepoints" if none found.  */
+  if (tpnum_exp == 0)
+    {
+      ALL_TRACEPOINTS (b)
+      {
+       if (b->number >= 0)
+         {
+           tps_to_list = 1;
+           break;
+         }
+      }
+      if (!tps_to_list)
+       {
+         ui_out_message (uiout, 0, "No tracepoints.\n");
+         return;
+       }
+    }
+
+  /* Otherwise be the same as "info break".  */
+  breakpoints_info (tpnum_exp, from_tty);
+}
+
+/* The 'enable trace' command enables tracepoints.  
+   Not supported by all targets.  */
+static void
+enable_trace_command (char *args, int from_tty)
+{
+  enable_command (args, from_tty);
+}
+
+/* The 'disable trace' command disables tracepoints.  
+   Not supported by all targets.  */
+static void
+disable_trace_command (char *args, int from_tty)
+{
+  disable_command (args, from_tty);
+}
+
+/* Remove a tracepoint (or all if no argument) */
+static void
+delete_trace_command (char *arg, int from_tty)
+{
+  struct breakpoint *b, *temp;
+
+  dont_repeat ();
+
+  if (arg == 0)
+    {
+      int breaks_to_delete = 0;
+
+      /* Delete all breakpoints if no argument.
+         Do not delete internal or call-dummy breakpoints, these
+         have to be deleted with an explicit breakpoint number argument.  */
+      ALL_TRACEPOINTS (b)
+      {
+       if (b->number >= 0)
+         {
+           breaks_to_delete = 1;
+           break;
+         }
+      }
+
+      /* Ask user only if there are some breakpoints to delete.  */
+      if (!from_tty
+         || (breaks_to_delete && query (_("Delete all tracepoints? "))))
+       {
+         ALL_BREAKPOINTS_SAFE (b, temp)
+         {
+           if (b->type == bp_tracepoint &&
+               b->number >= 0)
+             delete_breakpoint (b);
+         }
+       }
+    }
+  else
+    map_breakpoint_numbers (arg, delete_breakpoint);
+}
+
+/* Set passcount for tracepoint.
+
+   First command argument is passcount, second is tracepoint number.
+   If tracepoint number omitted, apply to most recently defined.
+   Also accepts special argument "all".  */
+
+static void
+trace_pass_command (char *args, int from_tty)
+{
+  struct breakpoint *t1 = (struct breakpoint *) -1, *t2;
+  unsigned int count;
+  int all = 0;
+
+  if (args == 0 || *args == 0)
+    error (_("passcount command requires an argument (count + optional TP num)"));
+
+  count = strtoul (args, &args, 10);   /* Count comes first, then TP num. */
+
+  while (*args && isspace ((int) *args))
+    args++;
+
+  if (*args && strncasecmp (args, "all", 3) == 0)
+    {
+      args += 3;                       /* Skip special argument "all".  */
+      all = 1;
+      if (*args)
+       error (_("Junk at end of arguments."));
+    }
+  else
+    t1 = get_tracepoint_by_number (&args, 1, 1);
+
+  do
+    {
+      if (t1)
+       {
+         ALL_TRACEPOINTS (t2)
+           if (t1 == (struct breakpoint *) -1 || t1 == t2)
+             {
+               t2->pass_count = count;
+               observer_notify_tracepoint_modified (t2->number);
+               if (from_tty)
+                 printf_filtered (_("Setting tracepoint %d's passcount to %d\n"),
+                                  t2->number, count);
+             }
+         if (! all && *args)
+           t1 = get_tracepoint_by_number (&args, 1, 0);
+       }
+    }
+  while (*args);
+}
+
+struct breakpoint *
+get_tracepoint (int num)
+{
+  struct breakpoint *t;
+
+  ALL_TRACEPOINTS (t)
+    if (t->number == num)
+      return t;
+
+  return NULL;
+}
+
+/* Utility: parse a tracepoint number and look it up in the list.
+   If MULTI_P is true, there might be a range of tracepoints in ARG.
+   if OPTIONAL_P is true, then if the argument is missing, the most
+   recent tracepoint (tracepoint_count) is returned.  */
+struct breakpoint *
+get_tracepoint_by_number (char **arg, int multi_p, int optional_p)
+{
+  extern int tracepoint_count;
+  struct breakpoint *t;
+  int tpnum;
+  char *instring = arg == NULL ? NULL : *arg;
+
+  if (arg == NULL || *arg == NULL || ! **arg)
+    {
+      if (optional_p)
+       tpnum = tracepoint_count;
+      else
+       error_no_arg (_("tracepoint number"));
+    }
+  else
+    tpnum = multi_p ? get_number_or_range (arg) : get_number (arg);
+
+  if (tpnum <= 0)
+    {
+      if (instring && *instring)
+       printf_filtered (_("bad tracepoint number at or near '%s'\n"), 
+                        instring);
+      else
+       printf_filtered (_("Tracepoint argument missing and no previous tracepoint\n"));
+      return NULL;
+    }
+
+  ALL_TRACEPOINTS (t)
+    if (t->number == tpnum)
+    {
+      return t;
+    }
+
+  /* FIXME: if we are in the middle of a range we don't want to give
+     a message.  The current interface to get_number_or_range doesn't
+     allow us to discover this.  */
+  printf_unfiltered ("No tracepoint number %d.\n", tpnum);
+  return NULL;
+}
+
+/* save-tracepoints command */
+static void
+tracepoint_save_command (char *args, int from_tty)
+{
+  struct breakpoint *tp;
+  int any_tp = 0;
+  struct action_line *line;
+  FILE *fp;
+  char *i1 = "    ", *i2 = "      ";
+  char *indent, *actionline, *pathname;
+  char tmp[40];
+  struct cleanup *cleanup;
+
+  if (args == 0 || *args == 0)
+    error (_("Argument required (file name in which to save tracepoints)"));
+
+  /* See if we have anything to save.  */
+  ALL_TRACEPOINTS (tp)
+  {
+    any_tp = 1;
+    break;
+  }
+  if (!any_tp)
+    {
+      warning (_("save-tracepoints: no tracepoints to save."));
+      return;
+    }
+
+  pathname = tilde_expand (args);
+  cleanup = make_cleanup (xfree, pathname);
+  if (!(fp = fopen (pathname, "w")))
+    error (_("Unable to open file '%s' for saving tracepoints (%s)"),
+          args, safe_strerror (errno));
+  make_cleanup_fclose (fp);
+  
+  ALL_TRACEPOINTS (tp)
+  {
+    if (tp->addr_string)
+      fprintf (fp, "trace %s\n", tp->addr_string);
+    else
+      {
+       sprintf_vma (tmp, tp->loc->address);
+       fprintf (fp, "trace *0x%s\n", tmp);
+      }
+
+    if (tp->pass_count)
+      fprintf (fp, "  passcount %d\n", tp->pass_count);
+
+    if (tp->actions)
+      {
+       fprintf (fp, "  actions\n");
+       indent = i1;
+       for (line = tp->actions; line; line = line->next)
+         {
+           struct cmd_list_element *cmd;
+
+           QUIT;               /* allow user to bail out with ^C */
+           actionline = line->action;
+           while (isspace ((int) *actionline))
+             actionline++;
+
+           fprintf (fp, "%s%s\n", indent, actionline);
+           if (*actionline != '#')     /* skip for comment lines */
+             {
+               cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
+               if (cmd == 0)
+                 error (_("Bad action list item: %s"), actionline);
+               if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
+                 indent = i2;
+               else if (cmd_cfunc_eq (cmd, end_actions_pseudocommand))
+                 indent = i1;
+             }
+         }
+      }
+  }
+  do_cleanups (cleanup);
+  if (from_tty)
+    printf_filtered (_("Tracepoints saved to file '%s'.\n"), args);
+  return;
+}
+
+/* Create a vector of all tracepoints.  */
+
+VEC(breakpoint_p) *
+all_tracepoints ()
+{
+  VEC(breakpoint_p) *tp_vec = 0;
+  struct breakpoint *tp;
+
+  ALL_TRACEPOINTS (tp)
+  {
+    VEC_safe_push (breakpoint_p, tp_vec, tp);
+  }
+
+  return tp_vec;
+}
+
 \f
 /* This help string is used for the break, hbreak, tbreak and thbreak commands.
    It is defined as a macro to prevent duplication.
@@ -8104,6 +8648,8 @@ _initialize_breakpoint (void)
      before a breakpoint is set.  */
   breakpoint_count = 0;
 
+  tracepoint_count = 0;
+
   add_com ("ignore", class_breakpoint, ignore_command, _("\
 Set ignore-count of breakpoint number N to COUNT.\n\
 Usage is `ignore N COUNT'."));
@@ -8433,6 +8979,58 @@ hardware.)"),
 
   can_use_hw_watchpoints = 1;
 
+  /* Tracepoint manipulation commands.  */
+
+  c = add_com ("trace", class_breakpoint, trace_command, _("\
+Set a tracepoint at specified line or function.\n\
+\n"
+BREAK_ARGS_HELP ("trace") "\n\
+Do \"help tracepoints\" for info on other tracepoint commands."));
+  set_cmd_completer (c, location_completer);
+
+  add_com_alias ("tp", "trace", class_alias, 0);
+  add_com_alias ("tr", "trace", class_alias, 1);
+  add_com_alias ("tra", "trace", class_alias, 1);
+  add_com_alias ("trac", "trace", class_alias, 1);
+
+  add_info ("tracepoints", tracepoints_info, _("\
+Status of tracepoints, or tracepoint number NUMBER.\n\
+Convenience variable \"$tpnum\" contains the number of the\n\
+last tracepoint set."));
+
+  add_info_alias ("tp", "tracepoints", 1);
+
+  add_cmd ("tracepoints", class_trace, delete_trace_command, _("\
+Delete specified tracepoints.\n\
+Arguments are tracepoint numbers, separated by spaces.\n\
+No argument means delete all tracepoints."),
+          &deletelist);
+
+  c = add_cmd ("tracepoints", class_trace, disable_trace_command, _("\
+Disable specified tracepoints.\n\
+Arguments are tracepoint numbers, separated by spaces.\n\
+No argument means disable all tracepoints."),
+          &disablelist);
+  deprecate_cmd (c, "disable");
+
+  c = add_cmd ("tracepoints", class_trace, enable_trace_command, _("\
+Enable specified tracepoints.\n\
+Arguments are tracepoint numbers, separated by spaces.\n\
+No argument means enable all tracepoints."),
+          &enablelist);
+  deprecate_cmd (c, "enable");
+
+  add_com ("passcount", class_trace, trace_pass_command, _("\
+Set the passcount for a tracepoint.\n\
+The trace will end when the tracepoint has been passed 'count' times.\n\
+Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
+if TPNUM is omitted, passcount refers to the last tracepoint defined."));
+
+  c = add_com ("save-tracepoints", class_trace, tracepoint_save_command, _("\
+Save current tracepoint definitions as a script.\n\
+Use the 'source' command in another debug session to restore them."));
+  set_cmd_completer (c, filename_completer);
+
   add_prefix_cmd ("breakpoint", class_maintenance, set_breakpoint_cmd, _("\
 Breakpoint specific settings\n\
 Configure various breakpoint-specific variables such as\n\
@@ -8491,4 +9089,6 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
                           &breakpoint_show_cmdlist);
   
   automatic_hardware_breakpoints = 1;
+
+  observer_attach_about_to_proceed (breakpoint_about_to_proceed);
 }
This page took 0.047151 seconds and 4 git commands to generate.