This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

more OO, use breakpoints_ops for all kinds of breakpoints (Re: [patch] [python] Expose some breakpoint operations to Python)


On Thursday 23 June 2011 18:04:26, Pedro Alves wrote:

> I'd like to finish that conversion soon.

I did a bit more work on this.  Watchpoints were already using
breakpoint_ops.  I added a bkpt_breakpoint_ops for all software/hardware
breakpoints, and a tracepoint_ops for all kinds of tracepoints,
and moved the default actions to the appropriate places.  There
were places where I could cleanup a bit further, but I figured
I'd better do those as follow ups.  I think these 4 major
kinds of "breakpoints" is already a good start.  Further
refinement could split internal / momentary breakpoints
into its own ops, for example.

I left behind the print_one method, as that seems will
require something else, or some disentanglement.

The current insert/remove abstration is at raw location level.
We can't use it as is to split insert_bp_location.  We may need
to rename the current methods to e.g., insert_raw_location (or
move them to the bp_location vtable), and add new breakpoint_ops
methods that call the raw methods, and, handle the different
warnings and insert-failed->revert paths as appropriate per
breakpoint type.

This has no regressions for me.  It misses some comments and
cosmetics here and there, and a ChangeLog entry.  I'll try to
get back to this soon, but I've got other fish to fry at
the moment.

-- 
Pedro Alves

---
 gdb/ada-lang.c             |   56 -
 gdb/breakpoint.c           | 2076 ++++++++++++++++++++++++---------------------
 gdb/breakpoint.h           |   48 -
 gdb/mi/mi-cmd-break.c      |    2 
 gdb/python/py-breakpoint.c |    3 
 5 files changed, 1203 insertions(+), 982 deletions(-)

Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c	2011-06-23 01:25:32.000000000 +0100
+++ src/gdb/breakpoint.c	2011-06-24 17:29:05.868082452 +0100
@@ -94,6 +94,8 @@ static void ignore_command (char *, int)
 
 static int breakpoint_re_set_one (void *);
 
+static void breakpoint_re_set_default (struct breakpoint *);
+
 static void clear_command (char *, int);
 
 static void catch_command (char *, int);
@@ -104,11 +106,14 @@ static void break_command_1 (char *, int
 
 static void mention (struct breakpoint *);
 
+static struct breakpoint *set_raw_breakpoint_without_location (struct gdbarch *,
+							       enum bptype,
+							       struct breakpoint_ops *);
 /* This function is used in gdbtk sources and thus can not be made
    static.  */
 struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch,
-					      struct symtab_and_line,
-					      enum bptype);
+				       struct symtab_and_line,
+				       enum bptype, struct breakpoint_ops *);
 
 static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int);
 
@@ -157,8 +162,6 @@ insertion_state_t;
 static int remove_breakpoint (struct bp_location *, insertion_state_t);
 static int remove_breakpoint_1 (struct bp_location *, insertion_state_t);
 
-static enum print_stop_action print_it_typical (bpstat);
-
 static enum print_stop_action print_bp_stop_message (bpstat bs);
 
 static int watchpoint_check (void *);
@@ -1436,10 +1439,7 @@ update_watchpoint (struct breakpoint *b,
 		    (b->type, i, other_type_used);
 	      if (target_resources_ok <= 0)
 		{
-		  /* If there's no works_in_software_mode method, we
-		     assume that the watchpoint works in software mode.  */
-		  int sw_mode = (!b->ops || !b->ops->works_in_software_mode
-				 || b->ops->works_in_software_mode (b));
+		  int sw_mode = b->ops->works_in_software_mode (b);
 
 		  if (target_resources_ok == 0 && !sw_mode)
 		    error (_("Target does not support this type of "
@@ -1451,8 +1451,7 @@ update_watchpoint (struct breakpoint *b,
 		    b->type = bp_watchpoint;
 		}
 	    }
-	  else if (b->ops && b->ops->works_in_software_mode
-		   && !b->ops->works_in_software_mode (b))
+	  else if (!b->ops->works_in_software_mode (b))
 	    error (_("Expression cannot be implemented with "
 		     "read/access watchpoint."));
 	  else
@@ -1622,12 +1621,7 @@ insert_bp_location (struct bp_location *
 	{
 	  /* No overlay handling: just set the breakpoint.  */
 
-	  if (bl->loc_type == bp_loc_hardware_breakpoint)
-	    val = target_insert_hw_breakpoint (bl->gdbarch,
-					       &bl->target_info);
-	  else
-	    val = target_insert_breakpoint (bl->gdbarch,
-					    &bl->target_info);
+	  val = bl->owner->ops->insert_location (bl);
 	}
       else
 	{
@@ -1661,12 +1655,7 @@ insert_bp_location (struct bp_location *
 	  if (section_is_mapped (bl->section))
 	    {
 	      /* Yes.  This overlay section is mapped into memory.  */
-	      if (bl->loc_type == bp_loc_hardware_breakpoint)
-		val = target_insert_hw_breakpoint (bl->gdbarch,
-						   &bl->target_info);
-	      else
-		val = target_insert_breakpoint (bl->gdbarch,
-						&bl->target_info);
+	      val = bl->owner->ops->insert_location (bl);
 	    }
 	  else
 	    {
@@ -2088,7 +2077,7 @@ create_internal_breakpoint (struct gdbar
   sal.section = find_pc_overlay (sal.pc);
   sal.pspace = current_program_space;
 
-  b = set_raw_breakpoint (gdbarch, sal, type);
+  b = set_raw_breakpoint (gdbarch, sal, type, &bkpt_breakpoint_ops);
   b->number = internal_breakpoint_number--;
   b->disposition = disp_donttouch;
 
@@ -2547,11 +2536,7 @@ remove_breakpoint_1 (struct bp_location
 	  || !(section_is_overlay (bl->section)))
 	{
 	  /* No overlay handling: just remove the breakpoint.  */
-
-	  if (bl->loc_type == bp_loc_hardware_breakpoint)
-	    val = target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info);
-	  else
-	    val = target_remove_breakpoint (bl->gdbarch, &bl->target_info);
+	  val = bl->owner->ops->remove_location (bl);
 	}
       else
 	{
@@ -2579,16 +2564,13 @@ remove_breakpoint_1 (struct bp_location
 		 remove the breakpoint if the section had been
 		 unmapped, but let's not rely on that being safe.  We
 		 don't know what the overlay manager might do.  */
-	      if (bl->loc_type == bp_loc_hardware_breakpoint)
-		val = target_remove_hw_breakpoint (bl->gdbarch,
-						   &bl->target_info);
 
 	      /* However, we should remove *software* breakpoints only
 		 if the section is still mapped, or else we overwrite
 		 wrong code with the saved shadow contents.  */
-	      else if (section_is_mapped (bl->section))
-		val = target_remove_breakpoint (bl->gdbarch,
-						&bl->target_info);
+	      if (bl->loc_type == bp_loc_hardware_breakpoint
+		  || section_is_mapped (bl->section))
+		val = bl->owner->ops->remove_location (bl);
 	      else
 		val = 0;
 	    }
@@ -3305,219 +3287,6 @@ watchpoint_value_print (struct value *va
     }
 }
 
-/* This is the normal print function for a bpstat.  In the future,
-   much of this logic could (should?) be moved to bpstat_stop_status,
-   by having it set different print_it values.
-
-   Current scheme: When we stop, bpstat_print() is called.  It loops
-   through the bpstat list of things causing this stop, calling the
-   print_bp_stop_message function on each one.  The behavior of the
-   print_bp_stop_message function depends on the print_it field of
-   bpstat.  If such field so indicates, call this function here.
-
-   Return values from this routine (ultimately used by bpstat_print()
-   and normal_stop() to decide what to do): 
-   PRINT_NOTHING: Means we already printed all we needed to print,
-   don't print anything else.
-   PRINT_SRC_ONLY: Means we printed something, and we do *not* desire
-   that something to be followed by a location.
-   PRINT_SCR_AND_LOC: Means we printed something, and we *do* desire
-   that something to be followed by a location.
-   PRINT_UNKNOWN: Means we printed nothing or we need to do some more
-   analysis.  */
-
-static enum print_stop_action
-print_it_typical (bpstat bs)
-{
-  struct cleanup *old_chain;
-  struct breakpoint *b;
-  const struct bp_location *bl;
-  struct ui_stream *stb;
-  int bp_temp = 0;
-  enum print_stop_action result;
-
-  gdb_assert (bs->bp_location_at != NULL);
-
-  bl = bs->bp_location_at;
-  b = bs->breakpoint_at;
-
-  stb = ui_out_stream_new (uiout);
-  old_chain = make_cleanup_ui_out_stream_delete (stb);
-
-  switch (b->type)
-    {
-    case bp_breakpoint:
-    case bp_hardware_breakpoint:
-      bp_temp = b->disposition == disp_del;
-      if (bl->address != bl->requested_address)
-	breakpoint_adjustment_warning (bl->requested_address,
-	                               bl->address,
-				       b->number, 1);
-      annotate_breakpoint (b->number);
-      if (bp_temp) 
-	ui_out_text (uiout, "\nTemporary breakpoint ");
-      else
-	ui_out_text (uiout, "\nBreakpoint ");
-      if (ui_out_is_mi_like_p (uiout))
-	{
-	  ui_out_field_string (uiout, "reason", 
-			  async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
-	  ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
-	}
-      ui_out_field_int (uiout, "bkptno", b->number);
-      ui_out_text (uiout, ", ");
-      result = PRINT_SRC_AND_LOC;
-      break;
-
-    case bp_shlib_event:
-      /* Did we stop because the user set the stop_on_solib_events
-	 variable?  (If so, we report this as a generic, "Stopped due
-	 to shlib event" message.) */
-      printf_filtered (_("Stopped due to shared library event\n"));
-      result = PRINT_NOTHING;
-      break;
-
-    case bp_thread_event:
-      /* Not sure how we will get here.
-	 GDB should not stop for these breakpoints.  */
-      printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n"));
-      result = PRINT_NOTHING;
-      break;
-
-    case bp_overlay_event:
-      /* By analogy with the thread event, GDB should not stop for these.  */
-      printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n"));
-      result = PRINT_NOTHING;
-      break;
-
-    case bp_longjmp_master:
-      /* These should never be enabled.  */
-      printf_filtered (_("Longjmp Master Breakpoint: gdb should not stop!\n"));
-      result = PRINT_NOTHING;
-      break;
-
-    case bp_std_terminate_master:
-      /* These should never be enabled.  */
-      printf_filtered (_("std::terminate Master Breakpoint: "
-			 "gdb should not stop!\n"));
-      result = PRINT_NOTHING;
-      break;
-
-    case bp_exception_master:
-      /* These should never be enabled.  */
-      printf_filtered (_("Exception Master Breakpoint: "
-			 "gdb should not stop!\n"));
-      result = PRINT_NOTHING;
-      break;
-
-    case bp_watchpoint:
-    case bp_hardware_watchpoint:
-      annotate_watchpoint (b->number);
-      if (ui_out_is_mi_like_p (uiout))
-	ui_out_field_string
-	  (uiout, "reason",
-	   async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
-      mention (b);
-      make_cleanup_ui_out_tuple_begin_end (uiout, "value");
-      ui_out_text (uiout, "\nOld value = ");
-      watchpoint_value_print (bs->old_val, stb->stream);
-      ui_out_field_stream (uiout, "old", stb);
-      ui_out_text (uiout, "\nNew value = ");
-      watchpoint_value_print (b->val, stb->stream);
-      ui_out_field_stream (uiout, "new", stb);
-      ui_out_text (uiout, "\n");
-      /* More than one watchpoint may have been triggered.  */
-      result = PRINT_UNKNOWN;
-      break;
-
-    case bp_read_watchpoint:
-      if (ui_out_is_mi_like_p (uiout))
-	ui_out_field_string
-	  (uiout, "reason",
-	   async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
-      mention (b);
-      make_cleanup_ui_out_tuple_begin_end (uiout, "value");
-      ui_out_text (uiout, "\nValue = ");
-      watchpoint_value_print (b->val, stb->stream);
-      ui_out_field_stream (uiout, "value", stb);
-      ui_out_text (uiout, "\n");
-      result = PRINT_UNKNOWN;
-      break;
-
-    case bp_access_watchpoint:
-      if (bs->old_val != NULL)
-	{
-	  annotate_watchpoint (b->number);
-	  if (ui_out_is_mi_like_p (uiout))
-	    ui_out_field_string
-	      (uiout, "reason",
-	       async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
-	  mention (b);
-	  make_cleanup_ui_out_tuple_begin_end (uiout, "value");
-	  ui_out_text (uiout, "\nOld value = ");
-	  watchpoint_value_print (bs->old_val, stb->stream);
-	  ui_out_field_stream (uiout, "old", stb);
-	  ui_out_text (uiout, "\nNew value = ");
-	}
-      else 
-	{
-	  mention (b);
-	  if (ui_out_is_mi_like_p (uiout))
-	    ui_out_field_string
-	      (uiout, "reason",
-	       async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
-	  make_cleanup_ui_out_tuple_begin_end (uiout, "value");
-	  ui_out_text (uiout, "\nValue = ");
-	}
-      watchpoint_value_print (b->val, stb->stream);
-      ui_out_field_stream (uiout, "new", stb);
-      ui_out_text (uiout, "\n");
-      result = PRINT_UNKNOWN;
-      break;
-
-    /* Fall through, we don't deal with these types of breakpoints
-       here.  */
-
-    case bp_finish:
-      if (ui_out_is_mi_like_p (uiout))
-	ui_out_field_string
-	  (uiout, "reason",
-	   async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED));
-      result = PRINT_UNKNOWN;
-      break;
-
-    case bp_until:
-      if (ui_out_is_mi_like_p (uiout))
-	ui_out_field_string
-	  (uiout, "reason",
-	   async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED));
-      result = PRINT_UNKNOWN;
-      break;
-
-    case bp_none:
-    case bp_longjmp:
-    case bp_longjmp_resume:
-    case bp_exception:
-    case bp_exception_resume:
-    case bp_step_resume:
-    case bp_hp_step_resume:
-    case bp_watchpoint_scope:
-    case bp_call_dummy:
-    case bp_std_terminate:
-    case bp_tracepoint:
-    case bp_fast_tracepoint:
-    case bp_jit_event:
-    case bp_gnu_ifunc_resolver:
-    case bp_gnu_ifunc_resolver_return:
-    default:
-      result = PRINT_UNKNOWN;
-      break;
-    }
-
-  do_cleanups (old_chain);
-  return result;
-}
-
 /* Generic routine for printing messages indicating why we
    stopped.  The behavior of this function depends on the value
    'print_it' in the bpstat structure.  Under some circumstances we
@@ -3549,14 +3318,10 @@ print_bp_stop_message (bpstat bs)
 	if (b == NULL)
 	  return PRINT_UNKNOWN;
 
-	/* Normal case.  Call the breakpoint's print_it method, or
-	   print_it_typical.  */
-	if (b->ops != NULL && b->ops->print_it != NULL)
-	  return b->ops->print_it (b);
-	else
-	  return print_it_typical (bs);
+	/* Normal case.  Call the breakpoint's print_it method.  */
+	return b->ops->print_it (bs);
       }
-	break;
+      break;
 
     default:
       internal_error (__FILE__, __LINE__,
@@ -3851,10 +3616,11 @@ watchpoint_check (void *p)
          So we can't even detect the first assignment to it and
          watch after that (since the garbage may or may not equal
          the first value assigned).  */
-      /* We print all the stop information in print_it_typical(), but
-	 in this case, by the time we call print_it_typical() this bp
-	 will be deleted already.  So we have no choice but print the
-	 information here.  */
+      /* We print all the stop information in
+	 breakpoint_ops->print_it, but in this case, by the time we
+	 call breakpoint_ops->print_it this bp will be deleted
+	 already.  So we have no choice but print the information
+	 here.  */
       if (ui_out_is_mi_like_p (uiout))
 	ui_out_field_string
 	  (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
@@ -3873,60 +3639,19 @@ which its expression is valid.\n");
 }
 
 /* Return true if it looks like target has stopped due to hitting
-   breakpoint location BL.  This function does not check if we
-   should stop, only if BL explains the stop.   */
+   breakpoint location BL.  This function does not check if we should
+   stop, only if BL explains the stop.  */
+
 static int
 bpstat_check_location (const struct bp_location *bl,
 		       struct address_space *aspace, CORE_ADDR bp_addr)
 {
   struct breakpoint *b = bl->owner;
 
-  /* BL is from existing struct breakpoint.  */
+  /* BL is from an existing breakpoint.  */
   gdb_assert (b != NULL);
 
-  if (b->ops && b->ops->breakpoint_hit)
-    return b->ops->breakpoint_hit (bl, aspace, bp_addr);
-
-  /* By definition, the inferior does not report stops at
-     tracepoints.  */
-  if (is_tracepoint (b))
-    return 0;
-
-  if (!is_watchpoint (b)
-      && b->type != bp_hardware_breakpoint
-      && b->type != bp_catchpoint)	/* a non-watchpoint bp */
-    {
-      if (!breakpoint_address_match (bl->pspace->aspace, bl->address,
-				     aspace, bp_addr))
-	return 0;
-      if (overlay_debugging		/* unmapped overlay section */
-	  && section_is_overlay (bl->section)
-	  && !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 (is_hardware_watchpoint (b)
-      && b->watchpoint_triggered == watch_triggered_no)
-    return 0;
-
-  if (b->type == bp_hardware_breakpoint)
-    {
-      if (bl->address != bp_addr)
-	return 0;
-      if (overlay_debugging		/* unmapped overlay section */
-	  && section_is_overlay (bl->section)
-	  && !section_is_mapped (bl->section))
-	return 0;
-    }
-
-  return 1;
+  return b->ops->breakpoint_hit (bl, aspace, bp_addr);
 }
 
 /* If BS refers to a watchpoint, determine if the watched values
@@ -4307,27 +4032,11 @@ bpstat_stop_status (struct address_space
       if (!bs->stop)
 	continue;
 
-      bpstat_check_watchpoint (bs);
-      if (!bs->stop)
-	continue;
-
       b = bs->breakpoint_at;
-
-      if (b->ops != NULL && b->ops->check_status != NULL)
+      b->ops->check_status (bs);
+      if (bs->stop)
 	{
-	  b->ops->check_status (bs);
-	  if (!bs->stop)
-	    continue;
-	}
-
-	  if (b->type == bp_thread_event || b->type == bp_overlay_event
-	      || b->type == bp_longjmp_master
-	      || b->type == bp_std_terminate_master
-	      || b->type == bp_exception_master)
-	    /* We do not stop for these.  */
-	    bs->stop = 0;
-	  else
-	    bpstat_check_breakpoint_conditions (bs, ptid);
+	  bpstat_check_breakpoint_conditions (bs, ptid);
 
 	  if (bs->stop)
 	    {
@@ -4360,6 +4069,7 @@ bpstat_stop_status (struct address_space
 	  /* Print nothing for this entry if we dont stop or dont print.  */
 	  if (bs->stop == 0 || bs->print == 0)
 	    bs->print_it = print_it_noop;
+	}
     }
 
   /* If we aren't stopping, the value of some hardware watchpoint may
@@ -4992,19 +4702,9 @@ print_one_breakpoint_location (struct br
 
   ui_out_text (uiout, "\n");
 
-  if (!part_of_multiple && b->ops && b->ops->print_one_detail)
+  if (!part_of_multiple)
     b->ops->print_one_detail (b, uiout);
 
-  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);
@@ -5695,6 +5395,8 @@ init_bp_location (struct bp_location *lo
 {
   memset (loc, 0, sizeof (*loc));
 
+  gdb_assert (ops != NULL);
+
   loc->ops = ops;
   loc->owner = owner;
   loc->cond = NULL;
@@ -5753,28 +5455,13 @@ init_bp_location (struct bp_location *lo
 static struct bp_location *
 allocate_bp_location (struct breakpoint *bpt)
 {
-  struct bp_location *loc;
-
-  if (bpt->ops && bpt->ops->allocate_location)
-    return bpt->ops->allocate_location (bpt);
-
-  loc = xmalloc (sizeof (struct bp_location));
-  init_bp_location (loc, NULL, bpt);
-  return loc;
+  return bpt->ops->allocate_location (bpt);
 }
 
 static void
 free_bp_location (struct bp_location *loc)
 {
-  if (loc->ops && loc->ops->dtor)
-    loc->ops->dtor (loc);
-
-  if (loc->cond)
-    xfree (loc->cond);
-
-  if (loc->function_name)
-    xfree (loc->function_name);
-
+  loc->ops->dtor (loc);
   xfree (loc);
 }
 
@@ -5830,6 +5517,8 @@ init_raw_breakpoint_without_location (st
 {
   memset (b, 0, sizeof (*b));
 
+  gdb_assert (ops != NULL);
+
   b->ops = ops;
   b->type = bptype;
   b->gdbarch = gdbarch;
@@ -5849,16 +5538,15 @@ init_raw_breakpoint_without_location (st
 
 /* Helper to set_raw_breakpoint below.  Creates a breakpoint
    that has type BPTYPE and has no locations as yet.  */
-/* This function is used in gdbtk sources and thus can not be made
-   static.  */
 
 static struct breakpoint *
 set_raw_breakpoint_without_location (struct gdbarch *gdbarch,
-				     enum bptype bptype)
+				     enum bptype bptype,
+				     struct breakpoint_ops *ops)
 {
   struct breakpoint *b = XNEW (struct breakpoint);
 
-  init_raw_breakpoint_without_location (b, gdbarch, bptype, NULL);
+  init_raw_breakpoint_without_location (b, gdbarch, bptype, ops);
   add_to_breakpoint_chain (b);
   return b;
 }
@@ -5994,11 +5682,12 @@ init_raw_breakpoint (struct breakpoint *
 
 struct breakpoint *
 set_raw_breakpoint (struct gdbarch *gdbarch,
-		    struct symtab_and_line sal, enum bptype bptype)
+		    struct symtab_and_line sal, enum bptype bptype,
+		    struct breakpoint_ops *ops)
 {
   struct breakpoint *b = XNEW (struct breakpoint);
 
-  init_raw_breakpoint (b, gdbarch, sal, bptype, NULL);
+  init_raw_breakpoint (b, gdbarch, sal, bptype, ops);
   add_to_breakpoint_chain (b);
   return b;
 }
@@ -6341,9 +6030,10 @@ breakpoint_hit_catch_fork (const struct
    catchpoints.  */
 
 static enum print_stop_action
-print_it_catch_fork (struct breakpoint *b)
+print_it_catch_fork (bpstat bs)
 {
-  struct fork_catchpoint *c = (struct fork_catchpoint *) b;
+  struct breakpoint *b = bs->breakpoint_at;
+  struct fork_catchpoint *c = (struct fork_catchpoint *) bs->breakpoint_at;
 
   annotate_catchpoint (b->number);
   printf_filtered (_("\nCatchpoint %d (forked process %d), "),
@@ -6400,18 +6090,18 @@ print_recreate_catch_fork (struct breakp
 
 static struct breakpoint_ops catch_fork_breakpoint_ops =
 {
-  NULL, /* dtor */
-  NULL, /* allocate_location */
-  NULL, /* re_set */
+  bkpt_dtor,
+  bkpt_allocate_location,
+  null_re_set,
   insert_catch_fork,
   remove_catch_fork,
   breakpoint_hit_catch_fork,
-  NULL, /* check_status */
-  NULL, /* resources_needed */
-  NULL, /* works_in_software_mode */
+  null_check_status,
+  null_resources_needed,
+  null_works_in_software_mode,
   print_it_catch_fork,
   print_one_catch_fork,
-  NULL, /* print_one_detail */
+  null_print_one_detail,
   print_mention_catch_fork,
   print_recreate_catch_fork
 };
@@ -6450,8 +6140,9 @@ breakpoint_hit_catch_vfork (const struct
    catchpoints.  */
 
 static enum print_stop_action
-print_it_catch_vfork (struct breakpoint *b)
+print_it_catch_vfork (bpstat bs)
 {
+  struct breakpoint *b = bs->breakpoint_at;
   struct fork_catchpoint *c = (struct fork_catchpoint *) b;
 
   annotate_catchpoint (b->number);
@@ -6508,18 +6199,18 @@ print_recreate_catch_vfork (struct break
 
 static struct breakpoint_ops catch_vfork_breakpoint_ops =
 {
-  NULL, /* dtor */
-  NULL, /* allocate_location */
-  NULL, /* re_set */
+  bkpt_dtor,
+  bkpt_allocate_location,
+  null_re_set,
   insert_catch_vfork,
   remove_catch_vfork,
   breakpoint_hit_catch_vfork,
-  NULL, /* check_status */
-  NULL, /* resources_needed */
-  NULL, /* works_in_software_mode */
+  null_check_status,
+  null_resources_needed,
+  null_works_in_software_mode,
   print_it_catch_vfork,
   print_one_catch_vfork,
-  NULL, /* print_one_detail */
+  null_print_one_detail,
   print_mention_catch_vfork,
   print_recreate_catch_vfork
 };
@@ -6675,8 +6366,9 @@ breakpoint_hit_catch_syscall (const stru
    catchpoints.  */
 
 static enum print_stop_action
-print_it_catch_syscall (struct breakpoint *b)
+print_it_catch_syscall (bpstat bs)
 {
+  struct breakpoint *b = bs->breakpoint_at;
   /* These are needed because we want to know in which state a
      syscall is.  It can be in the TARGET_WAITKIND_SYSCALL_ENTRY
      or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we
@@ -6838,17 +6530,17 @@ print_recreate_catch_syscall (struct bre
 static struct breakpoint_ops catch_syscall_breakpoint_ops =
 {
   dtor_catch_syscall,
-  NULL, /* allocate_location */
-  NULL, /* re_set */
+  bkpt_allocate_location,
+  null_re_set,
   insert_catch_syscall,
   remove_catch_syscall,
   breakpoint_hit_catch_syscall,
-  NULL, /* check_status */
-  NULL, /* resources_needed */
-  NULL, /* works_in_software_mode */
+  null_check_status,
+  null_resources_needed,
+  null_works_in_software_mode,
   print_it_catch_syscall,
   print_one_catch_syscall,
-  NULL, /* print_one_detail */
+  null_print_one_detail,
   print_mention_catch_syscall,
   print_recreate_catch_syscall
 };
@@ -6960,8 +6652,9 @@ breakpoint_hit_catch_exec (const struct
 }
 
 static enum print_stop_action
-print_it_catch_exec (struct breakpoint *b)
+print_it_catch_exec (bpstat bs)
 {
+  struct breakpoint *b = bs->breakpoint_at;
   struct exec_catchpoint *c = (struct exec_catchpoint *) b;
 
   annotate_catchpoint (b->number);
@@ -7011,17 +6704,17 @@ print_recreate_catch_exec (struct breakp
 static struct breakpoint_ops catch_exec_breakpoint_ops =
 {
   dtor_catch_exec,
-  NULL, /* allocate_location */
-  NULL, /* re_set */
+  bkpt_allocate_location,
+  null_re_set,
   insert_catch_exec,
   remove_catch_exec,
   breakpoint_hit_catch_exec,
-  NULL, /* check_status */
-  NULL, /* resources_needed */
-  NULL, /* works_in_software_mode */
+  null_check_status,
+  null_resources_needed,
+  null_works_in_software_mode,
   print_it_catch_exec,
   print_one_catch_exec,
-  NULL, /* print_one_detail */
+  null_print_one_detail,
   print_mention_catch_exec,
   print_recreate_catch_exec
 };
@@ -7054,10 +6747,7 @@ hw_breakpoint_used_count (void)
 	{
 	  /* Special types of hardware breakpoints may use more than
 	     one register.  */
-	  if (b->ops && b->ops->resources_needed)
-	    i += b->ops->resources_needed (bl);
-	  else
-	    i++;
+	  i += b->ops->resources_needed (bl);
 	}
   }
 
@@ -7082,10 +6772,7 @@ hw_watchpoint_used_count (enum bptype ty
 	    {
 	      /* Special types of hardware watchpoints may use more than
 		 one register.  */
-	      if (b->ops && b->ops->resources_needed)
-		i += b->ops->resources_needed (bl);
-	      else
-		i++;
+	      i += b->ops->resources_needed (bl);
 	    }
 	else if (is_hardware_watchpoint (b))
 	  *other_type_used = 1;
@@ -7191,7 +6878,7 @@ set_momentary_breakpoint (struct gdbarch
      one.  */
   gdb_assert (!frame_id_inlined_p (frame_id));
 
-  b = set_raw_breakpoint (gdbarch, sal, type);
+  b = set_raw_breakpoint (gdbarch, sal, type, &bkpt_breakpoint_ops);
   b->enable_state = bp_enabled;
   b->disposition = disp_donttouch;
   b->frame_id = frame_id;
@@ -7219,7 +6906,8 @@ clone_momentary_breakpoint (struct break
   if (orig == NULL)
     return NULL;
 
-  copy = set_raw_breakpoint_without_location (orig->gdbarch, orig->type);
+  copy = set_raw_breakpoint_without_location (orig->gdbarch,
+					      orig->type, orig->ops);
   copy->loc = allocate_bp_location (copy);
   set_breakpoint_location_function (copy->loc, 1);
 
@@ -7267,162 +6955,7 @@ set_momentary_breakpoint_at_pc (struct g
 static void
 mention (struct breakpoint *b)
 {
-  int say_where = 0;
-  struct cleanup *ui_out_chain;
-  struct value_print_options opts;
-
-  get_user_print_options (&opts);
-
-  if (b->ops != NULL && b->ops->print_mention != NULL)
-    b->ops->print_mention (b);
-  else
-    switch (b->type)
-      {
-      case bp_none:
-	printf_filtered (_("(apparently deleted?) Eventpoint %d: "),
-			 b->number);
-	break;
-      case bp_watchpoint:
-	ui_out_text (uiout, "Watchpoint ");
-	ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
-	ui_out_field_int (uiout, "number", b->number);
-	ui_out_text (uiout, ": ");
-	ui_out_field_string (uiout, "exp", b->exp_string);
-	do_cleanups (ui_out_chain);
-	break;
-      case bp_hardware_watchpoint:
-	ui_out_text (uiout, "Hardware watchpoint ");
-	ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
-	ui_out_field_int (uiout, "number", b->number);
-	ui_out_text (uiout, ": ");
-	ui_out_field_string (uiout, "exp", b->exp_string);
-	do_cleanups (ui_out_chain);
-	break;
-      case bp_read_watchpoint:
-	ui_out_text (uiout, "Hardware read watchpoint ");
-	ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt");
-	ui_out_field_int (uiout, "number", b->number);
-	ui_out_text (uiout, ": ");
-	ui_out_field_string (uiout, "exp", b->exp_string);
-	do_cleanups (ui_out_chain);
-	break;
-      case bp_access_watchpoint:
-	ui_out_text (uiout, "Hardware access (read/write) watchpoint ");
-	ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt");
-	ui_out_field_int (uiout, "number", b->number);
-	ui_out_text (uiout, ": ");
-	ui_out_field_string (uiout, "exp", b->exp_string);
-	do_cleanups (ui_out_chain);
-	break;
-      case bp_breakpoint:
-      case bp_gnu_ifunc_resolver:
-	if (ui_out_is_mi_like_p (uiout))
-	  {
-	    say_where = 0;
-	    break;
-	  }
-	if (b->disposition == disp_del)
-	  printf_filtered (_("Temporary breakpoint"));
-	else
-	  printf_filtered (_("Breakpoint"));
-	printf_filtered (_(" %d"), b->number);
-	if (b->type == bp_gnu_ifunc_resolver)
-	  printf_filtered (_(" at gnu-indirect-function resolver"));
-	say_where = 1;
-	break;
-      case bp_hardware_breakpoint:
-	if (ui_out_is_mi_like_p (uiout))
-	  {
-	    say_where = 0;
-	    break;
-	  }
-	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_fast_tracepoint:
-	if (ui_out_is_mi_like_p (uiout))
-	  {
-	    say_where = 0;
-	    break;
-	  }
-	printf_filtered (_("Fast tracepoint"));
-	printf_filtered (_(" %d"), b->number);
-	say_where = 1;
-	break;
-      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_exception:
-      case bp_exception_resume:
-      case bp_step_resume:
-      case bp_hp_step_resume:
-      case bp_call_dummy:
-      case bp_std_terminate:
-      case bp_watchpoint_scope:
-      case bp_shlib_event:
-      case bp_thread_event:
-      case bp_overlay_event:
-      case bp_jit_event:
-      case bp_longjmp_master:
-      case bp_std_terminate_master:
-      case bp_exception_master:
-      case bp_gnu_ifunc_resolver_return:
-	break;
-      }
-
-  if (say_where)
-    {
-      /* i18n: cagney/2005-02-11: Below needs to be merged into a
-	 single string.  */
-      if (b->loc == NULL)
-	{
-	  printf_filtered (_(" (%s) pending."), b->addr_string);
-	}
-      else
-	{
-	  if (opts.addressprint || b->source_file == NULL)
-	    {
-	      printf_filtered (" at ");
-	      fputs_filtered (paddress (b->loc->gdbarch, b->loc->address),
-			      gdb_stdout);
-	    }
-	  if (b->source_file)
-	    printf_filtered (": file %s, line %d.",
-			     b->source_file, b->line_number);
-	  
-	  if (b->loc->next)
-	    {
-	      struct bp_location *loc = b->loc;
-	      int n = 0;
-	      for (; loc; loc = loc->next)
-		++n;
-	      printf_filtered (" (%d locations)", n);		
-	    }
-
-	}
-    }
+  b->ops->print_mention (b);
   if (ui_out_is_mi_like_p (uiout))
     return;
   printf_filtered ("\n");
@@ -7545,7 +7078,7 @@ create_breakpoint_sal (struct gdbarch *g
 
       if (i == 0)
 	{
-	  b = set_raw_breakpoint (gdbarch, sal, type);
+	  b = set_raw_breakpoint (gdbarch, sal, type, ops);
 	  set_breakpoint_number (internal, b);
 	  b->thread = thread;
 	  b->task = task;
@@ -7627,7 +7160,6 @@ create_breakpoint_sal (struct gdbarch *g
     b->addr_string
       = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
 
-  b->ops = ops;
   /* Do not mention breakpoints with a negative number, but do
      notify observers.  */
   if (!internal)
@@ -8085,6 +7617,8 @@ create_breakpoint (struct gdbarch *gdbar
   int task = 0;
   int prev_bkpt_count = breakpoint_count;
 
+  gdb_assert (ops != NULL);
+
   sals.sals = NULL;
   sals.nelts = 0;
   init_linespec_result (&canonical);
@@ -8277,7 +7811,7 @@ create_breakpoint (struct gdbarch *gdbar
 
       make_cleanup (xfree, copy_arg);
 
-      b = set_raw_breakpoint_without_location (gdbarch, type_wanted);
+      b = set_raw_breakpoint_without_location (gdbarch, type_wanted, ops);
       set_breakpoint_number (internal, b);
       b->thread = -1;
       b->addr_string = canonical.canonical[0];
@@ -8285,7 +7819,6 @@ create_breakpoint (struct gdbarch *gdbar
       b->ignore_count = ignore_count;
       b->disposition = tempflag ? disp_del : disp_donttouch;
       b->condition_not_parsed = 1;
-      b->ops = ops;
       b->enable_state = enabled ? bp_enabled : bp_disabled;
       b->pspace = current_program_space;
       b->py_bp_object = NULL;
@@ -8321,13 +7854,13 @@ create_breakpoint (struct gdbarch *gdbar
   return 1;
 }
 
-/* Set a breakpoint. 
+/* Set a breakpoint.
    ARG is a string describing breakpoint address,
    condition, and thread.
    FLAG specifies if a breakpoint is hardware on,
    and if breakpoint is temporary, using BP_HARDWARE_FLAG
    and BP_TEMPFLAG.  */
-   
+
 static void
 break_command_1 (char *arg, int flag, int from_tty)
 {
@@ -8342,13 +7875,12 @@ break_command_1 (char *arg, int flag, in
 		     tempflag, type_wanted,
 		     0 /* Ignore count */,
 		     pending_break_support,
-		     NULL /* breakpoint_ops */,
+		     &bkpt_breakpoint_ops,
 		     from_tty,
 		     1 /* enabled */,
 		     0 /* internal */);
 }
 
-
 /* Helper function for break_command_1 and disassemble_command.  */
 
 void
@@ -8528,8 +8060,9 @@ resources_needed_ranged_breakpoint (cons
    ranged breakpoints.  */
 
 static enum print_stop_action
-print_it_ranged_breakpoint (struct breakpoint *b)
+print_it_ranged_breakpoint (bpstat bs)
 {
+  struct breakpoint *b = bs->breakpoint_at;
   struct bp_location *bl = b->loc;
 
   gdb_assert (b->type == bp_hardware_breakpoint);
@@ -8638,15 +8171,15 @@ print_recreate_ranged_breakpoint (struct
 
 static struct breakpoint_ops ranged_breakpoint_ops =
 {
-  NULL, /* dtor */
-  NULL, /* allocate_location */
-  NULL, /* re_set */
-  NULL, /* insert */
-  NULL, /* remove */
+  bkpt_dtor,
+  bkpt_allocate_location,
+  bkpt_re_set,
+  bkpt_insert_location,
+  bkpt_remove_location,
   breakpoint_hit_ranged_breakpoint,
-  NULL, /* check_status */
+  null_check_status,
   resources_needed_ranged_breakpoint,
-  NULL, /* works_in_software_mode */
+  null_works_in_software_mode,
   print_it_ranged_breakpoint,
   print_one_ranged_breakpoint,
   print_one_detail_ranged_breakpoint,
@@ -8796,13 +8329,12 @@ break_range_command (char *arg, int from
 
   /* Now set up the breakpoint.  */
   b = set_raw_breakpoint (get_current_arch (), sal_start,
-			  bp_hardware_breakpoint);
+			  bp_hardware_breakpoint, &ranged_breakpoint_ops);
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
   b->disposition = disp_donttouch;
   b->addr_string = addr_string_start;
   b->addr_string_range_end = addr_string_end;
-  b->ops = &ranged_breakpoint_ops;
   b->loc->length = length;
 
   discard_cleanups (cleanup_bkpt);
@@ -8921,6 +8453,39 @@ watchpoint_exp_is_const (const struct ex
   return 1;
 }
 
+/* Implement the "re_set" breakpoint_ops method for watchpoints.  */
+
+static void
+re_set_watchpoint (struct breakpoint *b)
+{
+  /* Watchpoint can be either on expression using entirely global
+     variables, or it can be on local variables.
+
+     Watchpoints of the first kind are never auto-deleted, and even
+     persist across program restarts.  Since they can use variables
+     from shared libraries, we need to reparse expression as libraries
+     are loaded and unloaded.
+
+     Watchpoints on local variables can also change meaning as result
+     of solib event.  For example, if a watchpoint uses both a local
+     and a global variables in expression, it's a local watchpoint,
+     but unloading of a shared library will make the expression
+     invalid.  This is not a very common use case, but we still
+     re-evaluate expression, to avoid surprises to the user.
+
+     Note that for local watchpoints, we re-evaluate it only if
+     watchpoints frame id is still valid.  If it's not, it means the
+     watchpoint is out of scope and will be deleted soon.  In fact,
+     I'm not sure we'll ever be called in this case.
+
+     If a local watchpoint's frame id is still valid, then
+     b->exp_valid_block is likewise valid, and we can safely use it.
+
+     Don't do anything about disabled watchpoints, since they will
+     be reevaluated again when enabled.  */
+  update_watchpoint (b, 1 /* reparse */);
+}
+
 /* Implement the "insert" breakpoint_ops method for hardware watchpoints.  */
 
 static int
@@ -8943,102 +8508,90 @@ remove_watchpoint (struct bp_location *b
 				   bl->owner->cond_exp);
 }
 
-/* Implement the "resources_needed" breakpoint_ops method for
-   hardware watchpoints.  */
-
 static int
-resources_needed_watchpoint (const struct bp_location *bl)
+breakpoint_hit_watchpoint (const struct bp_location *bl,
+			   struct address_space *aspace, CORE_ADDR bp_addr)
 {
-  int length = bl->owner->exact? 1 : bl->length;
-
-  return target_region_ok_for_hw_watchpoint (bl->address, length);
-}
+  struct breakpoint *b = bl->owner;
 
-/* Implement the "works_in_software_mode" breakpoint_ops method for
-   hardware watchpoints.  */
+  /* 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 (is_hardware_watchpoint (b)
+      && b->watchpoint_triggered == watch_triggered_no)
+    return 0;
 
-int
-works_in_software_mode_watchpoint (const struct breakpoint *b)
-{
-  return b->type == bp_hardware_watchpoint;
+  return 1;
 }
 
-/* The breakpoint_ops structure to be used in hardware watchpoints.  */
-
-static struct breakpoint_ops watchpoint_breakpoint_ops =
-{
-  NULL, /* dtor */
-  NULL, /* allocate_location */
-  NULL, /* re_set */
-  insert_watchpoint,
-  remove_watchpoint,
-  NULL, /* breakpoint_hit */
-  NULL, /* check_status */
-  resources_needed_watchpoint,
-  works_in_software_mode_watchpoint,
-  NULL, /* print_it */
-  NULL, /* print_one */
-  NULL, /* print_one_detail */
-  NULL, /* print_mention */
-  NULL  /* print_recreate */
-};
-
-/* Implement the "insert" breakpoint_ops method for
-   masked hardware watchpoints.  */
-
-static int
-insert_masked_watchpoint (struct bp_location *bl)
+static void
+check_status_watchpoint (bpstat bs)
 {
-  return target_insert_mask_watchpoint (bl->address, bl->owner->hw_wp_mask,
-					bl->watchpoint_type);
-}
-
-/* Implement the "remove" breakpoint_ops method for
-   masked hardware watchpoints.  */
+  gdb_assert (is_watchpoint (bs->breakpoint_at));
 
-static int
-remove_masked_watchpoint (struct bp_location *bl)
-{
-  return target_remove_mask_watchpoint (bl->address, bl->owner->hw_wp_mask,
-				        bl->watchpoint_type);
+  bpstat_check_watchpoint (bs);
 }
 
 /* Implement the "resources_needed" breakpoint_ops method for
-   masked hardware watchpoints.  */
+   hardware watchpoints.  */
 
 static int
-resources_needed_masked_watchpoint (const struct bp_location *bl)
+resources_needed_watchpoint (const struct bp_location *bl)
 {
-  return target_masked_watch_num_registers (bl->address,
-					    bl->owner->hw_wp_mask);
+  int length = bl->owner->exact? 1 : bl->length;
+
+  return target_region_ok_for_hw_watchpoint (bl->address, length);
 }
 
 /* Implement the "works_in_software_mode" breakpoint_ops method for
-   masked hardware watchpoints.  */
+   hardware watchpoints.  */
 
 static int
-works_in_software_mode_masked_watchpoint (const struct breakpoint *b)
+works_in_software_mode_watchpoint (const struct breakpoint *b)
 {
-  return 0;
+  return b->type == bp_hardware_watchpoint;
 }
 
-/* Implement the "print_it" breakpoint_ops method for
-   masked hardware watchpoints.  */
-
 static enum print_stop_action
-print_it_masked_watchpoint (struct breakpoint *b)
+print_it_watchpoint (bpstat bs)
 {
-  /* Masked watchpoints have only one location.  */
-  gdb_assert (b->loc && b->loc->next == NULL);
+  struct cleanup *old_chain;
+  struct breakpoint *b;
+  const struct bp_location *bl;
+  struct ui_stream *stb;
+  enum print_stop_action result;
+
+  gdb_assert (bs->bp_location_at != NULL);
+
+  bl = bs->bp_location_at;
+  b = bs->breakpoint_at;
+
+  stb = ui_out_stream_new (uiout);
+  old_chain = make_cleanup_ui_out_stream_delete (stb);
 
   switch (b->type)
     {
+    case bp_watchpoint:
     case bp_hardware_watchpoint:
       annotate_watchpoint (b->number);
       if (ui_out_is_mi_like_p (uiout))
 	ui_out_field_string
 	  (uiout, "reason",
 	   async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
+      mention (b);
+      make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+      ui_out_text (uiout, "\nOld value = ");
+      watchpoint_value_print (bs->old_val, stb->stream);
+      ui_out_field_stream (uiout, "old", stb);
+      ui_out_text (uiout, "\nNew value = ");
+      watchpoint_value_print (b->val, stb->stream);
+      ui_out_field_stream (uiout, "new", stb);
+      ui_out_text (uiout, "\n");
+      /* More than one watchpoint may have been triggered.  */
+      result = PRINT_UNKNOWN;
       break;
 
     case bp_read_watchpoint:
@@ -9046,26 +8599,223 @@ print_it_masked_watchpoint (struct break
 	ui_out_field_string
 	  (uiout, "reason",
 	   async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
+      mention (b);
+      make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+      ui_out_text (uiout, "\nValue = ");
+      watchpoint_value_print (b->val, stb->stream);
+      ui_out_field_stream (uiout, "value", stb);
+      ui_out_text (uiout, "\n");
+      result = PRINT_UNKNOWN;
       break;
 
     case bp_access_watchpoint:
-      if (ui_out_is_mi_like_p (uiout))
-	ui_out_field_string
-	  (uiout, "reason",
-	   async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
+      if (bs->old_val != NULL)
+	{
+	  annotate_watchpoint (b->number);
+	  if (ui_out_is_mi_like_p (uiout))
+	    ui_out_field_string
+	      (uiout, "reason",
+	       async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
+	  mention (b);
+	  make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+	  ui_out_text (uiout, "\nOld value = ");
+	  watchpoint_value_print (bs->old_val, stb->stream);
+	  ui_out_field_stream (uiout, "old", stb);
+	  ui_out_text (uiout, "\nNew value = ");
+	}
+      else
+	{
+	  mention (b);
+	  if (ui_out_is_mi_like_p (uiout))
+	    ui_out_field_string
+	      (uiout, "reason",
+	       async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
+	  make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+	  ui_out_text (uiout, "\nValue = ");
+	}
+      watchpoint_value_print (b->val, stb->stream);
+      ui_out_field_stream (uiout, "new", stb);
+      ui_out_text (uiout, "\n");
+      result = PRINT_UNKNOWN;
       break;
     default:
-      internal_error (__FILE__, __LINE__,
-		      _("Invalid hardware watchpoint type."));
+      result = PRINT_UNKNOWN;
     }
 
-  mention (b);
-  ui_out_text (uiout, _("\n\
-Check the underlying instruction at PC for the memory\n\
-address and value which triggered this watchpoint.\n"));
-  ui_out_text (uiout, "\n");
-
-  /* More than one watchpoint may have been triggered.  */
+  do_cleanups (old_chain);
+  return result;
+}
+
+/* Implement the "print_mention" breakpoint_ops method for hardware
+   watchpoints.  */
+
+static void
+print_mention_watchpoint (struct breakpoint *b)
+{
+  struct cleanup *ui_out_chain;
+
+  switch (b->type)
+    {
+    case bp_watchpoint:
+      ui_out_text (uiout, "Watchpoint ");
+      ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
+      break;
+    case bp_hardware_watchpoint:
+      ui_out_text (uiout, "Hardware watchpoint ");
+      ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
+      break;
+    case bp_read_watchpoint:
+      ui_out_text (uiout, "Hardware read watchpoint ");
+      ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt");
+      break;
+    case bp_access_watchpoint:
+      ui_out_text (uiout, "Hardware access (read/write) watchpoint ");
+      ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt");
+      break;
+    default:
+      internal_error (__FILE__, __LINE__,
+		      _("Invalid hardware watchpoint type."));
+    }
+
+  ui_out_field_int (uiout, "number", b->number);
+  ui_out_text (uiout, ": ");
+  ui_out_field_string (uiout, "exp", b->exp_string);
+  do_cleanups (ui_out_chain);
+}
+
+/* Implement the "print_recreate" breakpoint_ops method for
+   watchpoints.  */
+
+static void
+print_recreate_watchpoint (struct breakpoint *b, struct ui_file *fp)
+{
+  char tmp[40];
+
+  switch (b->type)
+    {
+    case bp_watchpoint:
+    case bp_hardware_watchpoint:
+      fprintf_unfiltered (fp, "watch");
+      break;
+    case bp_read_watchpoint:
+      fprintf_unfiltered (fp, "rwatch");
+      break;
+    case bp_access_watchpoint:
+      fprintf_unfiltered (fp, "awatch");
+      break;
+    default:
+      internal_error (__FILE__, __LINE__,
+		      _("Invalid watchpoint type."));
+    }
+
+  fprintf_unfiltered (fp, " %s", b->exp_string);
+}
+
+/* The breakpoint_ops structure to be used in hardware watchpoints.  */
+
+static struct breakpoint_ops watchpoint_breakpoint_ops =
+{
+  bkpt_dtor,
+  bkpt_allocate_location,
+  re_set_watchpoint,
+  insert_watchpoint,
+  remove_watchpoint,
+  breakpoint_hit_watchpoint,
+  check_status_watchpoint,
+  resources_needed_watchpoint,
+  works_in_software_mode_watchpoint,
+  print_it_watchpoint,
+  NULL, /* print_one */
+  null_print_one_detail,
+  print_mention_watchpoint,
+  print_recreate_watchpoint
+};
+
+/* Implement the "insert" breakpoint_ops method for
+   masked hardware watchpoints.  */
+
+static int
+insert_masked_watchpoint (struct bp_location *bl)
+{
+  return target_insert_mask_watchpoint (bl->address, bl->owner->hw_wp_mask,
+					bl->watchpoint_type);
+}
+
+/* Implement the "remove" breakpoint_ops method for
+   masked hardware watchpoints.  */
+
+static int
+remove_masked_watchpoint (struct bp_location *bl)
+{
+  return target_remove_mask_watchpoint (bl->address, bl->owner->hw_wp_mask,
+				        bl->watchpoint_type);
+}
+
+/* Implement the "resources_needed" breakpoint_ops method for
+   masked hardware watchpoints.  */
+
+static int
+resources_needed_masked_watchpoint (const struct bp_location *bl)
+{
+  return target_masked_watch_num_registers (bl->address,
+					    bl->owner->hw_wp_mask);
+}
+
+/* Implement the "works_in_software_mode" breakpoint_ops method for
+   masked hardware watchpoints.  */
+
+static int
+works_in_software_mode_masked_watchpoint (const struct breakpoint *b)
+{
+  return 0;
+}
+
+/* Implement the "print_it" breakpoint_ops method for
+   masked hardware watchpoints.  */
+
+static enum print_stop_action
+print_it_masked_watchpoint (bpstat bs)
+{
+  struct breakpoint *b = bs->breakpoint_at;
+
+  /* Masked watchpoints have only one location.  */
+  gdb_assert (b->loc && b->loc->next == NULL);
+
+  switch (b->type)
+    {
+    case bp_hardware_watchpoint:
+      annotate_watchpoint (b->number);
+      if (ui_out_is_mi_like_p (uiout))
+	ui_out_field_string
+	  (uiout, "reason",
+	   async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
+      break;
+
+    case bp_read_watchpoint:
+      if (ui_out_is_mi_like_p (uiout))
+	ui_out_field_string
+	  (uiout, "reason",
+	   async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
+      break;
+
+    case bp_access_watchpoint:
+      if (ui_out_is_mi_like_p (uiout))
+	ui_out_field_string
+	  (uiout, "reason",
+	   async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
+      break;
+    default:
+      internal_error (__FILE__, __LINE__,
+		      _("Invalid hardware watchpoint type."));
+    }
+
+  mention (b);
+  ui_out_text (uiout, _("\n\
+Check the underlying instruction at PC for the memory\n\
+address and value which triggered this watchpoint.\n"));
+  ui_out_text (uiout, "\n");
+
+  /* More than one watchpoint may have been triggered.  */
   return PRINT_UNKNOWN;
 }
 
@@ -9149,13 +8899,13 @@ print_recreate_masked_watchpoint (struct
 
 static struct breakpoint_ops masked_watchpoint_breakpoint_ops =
 {
-  NULL, /* dtor */
-  NULL, /* allocate_location */
-  NULL, /* re_set */
+  bkpt_dtor,
+  bkpt_allocate_location,
+  re_set_watchpoint,
   insert_masked_watchpoint,
   remove_masked_watchpoint,
-  NULL, /* breakpoint_hit */
-  NULL, /* check_status */
+  breakpoint_hit_watchpoint,
+  check_status_watchpoint,
   resources_needed_masked_watchpoint,
   works_in_software_mode_masked_watchpoint,
   print_it_masked_watchpoint,
@@ -9394,12 +9144,18 @@ watch_command_1 (char *arg, int accessfl
     }
 
   /* Now set up the breakpoint.  */
-  b = set_raw_breakpoint_without_location (NULL, bp_type);
+  if (use_mask)
+    b = set_raw_breakpoint_without_location (NULL, bp_type,
+					     &masked_watchpoint_breakpoint_ops);
+  else
+    b = set_raw_breakpoint_without_location (NULL, bp_type,
+					     &watchpoint_breakpoint_ops);
   b->thread = thread;
   b->disposition = disp_donttouch;
   b->exp = exp;
   b->exp_valid_block = exp_valid_block;
   b->cond_exp_valid_block = cond_exp_valid_block;
+  b->pspace = current_program_space;
   if (just_location)
     {
       struct type *t = value_type (val);
@@ -9425,13 +9181,11 @@ watch_command_1 (char *arg, int accessfl
   if (use_mask)
     {
       b->hw_wp_mask = mask;
-      b->ops = &masked_watchpoint_breakpoint_ops;
     }
   else
     {
       b->val = val;
       b->val_valid = 1;
-      b->ops = &watchpoint_breakpoint_ops;
     }
 
   if (cond_start)
@@ -9881,8 +9635,9 @@ catch_exec_command_1 (char *arg, int fro
 }
 
 static enum print_stop_action
-print_it_exception_catchpoint (struct breakpoint *b)
+print_it_exception_catchpoint (bpstat bs)
 {
+  struct breakpoint *b = bs->breakpoint_at;
   int bp_temp, bp_throw;
 
   annotate_catchpoint (b->number);
@@ -9968,18 +9723,18 @@ print_recreate_exception_catchpoint (str
 }
 
 static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = {
-  NULL, /* dtor */
-  NULL, /* allocate_location */
-  NULL, /* re_set */
-  NULL, /* insert */
-  NULL, /* remove */
-  NULL, /* breakpoint_hit */
-  NULL, /* check_status */
-  NULL, /* resources_needed */
-  NULL, /* works_in_software_mode */
+  bkpt_dtor,
+  bkpt_allocate_location,
+  bkpt_re_set,
+  bkpt_insert_location,
+  bkpt_remove_location,
+  bkpt_breakpoint_hit,
+  bkpt_check_status,
+  bkpt_resources_needed,
+  null_works_in_software_mode,
   print_it_exception_catchpoint,
   print_one_exception_catchpoint,
-  NULL, /* print_one_detail */
+  null_print_one_detail,
   print_mention_exception_catchpoint,
   print_recreate_exception_catchpoint
 };
@@ -10678,127 +10433,730 @@ update_global_location_list (int should_
 	}
     }
 
-  /* Rescan breakpoints at the same address and section, marking the
-     first one as "first" and any others as "duplicates".  This is so
-     that the bpt instruction is only inserted once.  If we have a
-     permanent breakpoint at the same place as BPT, make that one the
-     official one, and the rest as duplicates.  Permanent breakpoints
-     are sorted first for the same address.
-
-     Do the same for hardware watchpoints, but also considering the
-     watchpoint's type (regular/access/read) and length.  */
+  /* Rescan breakpoints at the same address and section, marking the
+     first one as "first" and any others as "duplicates".  This is so
+     that the bpt instruction is only inserted once.  If we have a
+     permanent breakpoint at the same place as BPT, make that one the
+     official one, and the rest as duplicates.  Permanent breakpoints
+     are sorted first for the same address.
+
+     Do the same for hardware watchpoints, but also considering the
+     watchpoint's type (regular/access/read) and length.  */
+
+  bp_loc_first = NULL;
+  wp_loc_first = NULL;
+  awp_loc_first = NULL;
+  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;
+
+      if (b->enable_state == bp_disabled
+	  || b->enable_state == bp_call_disabled
+	  || b->enable_state == bp_startup_disabled
+	  || !loc->enabled
+	  || loc->shlib_disabled
+	  || !breakpoint_address_is_meaningful (b)
+	  || is_tracepoint (b))
+	continue;
+
+      /* Permanent breakpoint should always be inserted.  */
+      if (b->enable_state == bp_permanent && ! loc->inserted)
+	internal_error (__FILE__, __LINE__,
+			_("allegedly permanent breakpoint is not "
+			"actually inserted"));
+
+      if (b->type == bp_hardware_watchpoint)
+	loc_first_p = &wp_loc_first;
+      else if (b->type == bp_read_watchpoint)
+	loc_first_p = &rwp_loc_first;
+      else if (b->type == bp_access_watchpoint)
+	loc_first_p = &awp_loc_first;
+      else
+	loc_first_p = &bp_loc_first;
+
+      if (*loc_first_p == NULL
+	  || (overlay_debugging && loc->section != (*loc_first_p)->section)
+	  || !breakpoint_locations_match (loc, *loc_first_p))
+	{
+	  *loc_first_p = loc;
+	  loc->duplicate = 0;
+	  continue;
+	}
+
+      loc->duplicate = 1;
+
+      if ((*loc_first_p)->owner->enable_state == bp_permanent && loc->inserted
+	  && b->enable_state != bp_permanent)
+	internal_error (__FILE__, __LINE__,
+			_("another breakpoint was inserted on top of "
+			"a permanent breakpoint"));
+    }
+
+  if (breakpoints_always_inserted_mode () && should_insert
+      && (have_live_inferiors ()
+	  || (gdbarch_has_global_breakpoints (target_gdbarch))))
+    insert_breakpoint_locations ();
+
+  do_cleanups (cleanups);
+}
+
+void
+breakpoint_retire_moribund (void)
+{
+  struct bp_location *loc;
+  int ix;
+
+  for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
+    if (--(loc->events_till_retirement) == 0)
+      {
+	decref_bp_location (&loc);
+	VEC_unordered_remove (bp_location_p, moribund_locations, ix);
+	--ix;
+      }
+}
+
+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 BKP from a BPS.  */
+
+static void
+bpstat_remove_bp_location (bpstat bps, struct breakpoint *bpt)
+{
+  bpstat bs;
+
+  for (bs = bps; bs; bs = bs->next)
+    if (bs->breakpoint_at == bpt)
+      {
+	bs->breakpoint_at = NULL;
+	bs->old_val = NULL;
+	/* bs->commands will be freed later.  */
+      }
+}
+
+/* Callback for iterate_over_threads.  */
+static int
+bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
+{
+  struct breakpoint *bpt = data;
+
+  bpstat_remove_bp_location (th->control.stop_bpstat, bpt);
+  return 0;
+}
+
+/* Helper for breakpoint and tracepoint breakpoint_ops->mention
+   callbacks.  */
+
+static void
+say_where (struct breakpoint *b)
+{
+  struct value_print_options opts;
+
+  get_user_print_options (&opts);
+
+  /* i18n: cagney/2005-02-11: Below needs to be merged into a
+     single string.  */
+  if (b->loc == NULL)
+    {
+      printf_filtered (_(" (%s) pending."), b->addr_string);
+    }
+  else
+    {
+      if (opts.addressprint || b->source_file == NULL)
+	{
+	  printf_filtered (" at ");
+	  fputs_filtered (paddress (b->loc->gdbarch, b->loc->address),
+			  gdb_stdout);
+	}
+      if (b->source_file)
+	printf_filtered (": file %s, line %d.",
+			 b->source_file, b->line_number);
+
+      if (b->loc->next)
+	{
+	  struct bp_location *loc = b->loc;
+	  int n = 0;
+	  for (; loc; loc = loc->next)
+	    ++n;
+	  printf_filtered (" (%d locations)", n);
+	}
+    }
+}
+
+/* Default breakpoint_ops methods that do nothing.  */
+
+void
+null_re_set (struct breakpoint *b)
+{
+  /* Nothing to re-set. */
+}
+
+void
+null_check_status (bpstat bs)
+{
+  /* nothing */
+}
+
+/* A "works_in_software_mode" breakpoint_ops method that just internal
+   errors.  */
+
+int
+null_works_in_software_mode (const struct breakpoint *b)
+{
+  gdb_assert_not_reached ("");
+}
+
+/* A "resources_needed" breakpoint_ops method that just internal
+   errors.  */
+
+int
+null_resources_needed (const struct bp_location *bl)
+{
+  gdb_assert_not_reached ("");
+}
+
+void
+null_print_one_detail (const struct breakpoint *self,
+		       struct ui_out *uiout)
+{
+  /* nothing */
+}
+
+/* Default bp_location_ops methods.  */
+
+static void
+bp_location_dtor (struct bp_location *self)
+{
+  xfree (self->cond);
+  xfree (self->function_name);
+}
+
+static const struct bp_location_ops bp_location_ops =
+{
+  bp_location_dtor
+};
+
+/* Default breakpoint_ops methods.  */
+
+void
+bkpt_dtor (struct breakpoint *self)
+{
+  decref_counted_command_line (&self->commands);
+  xfree (self->cond_string);
+  xfree (self->cond_exp);
+  xfree (self->addr_string);
+  xfree (self->addr_string_range_end);
+  xfree (self->exp);
+  xfree (self->exp_string);
+  xfree (self->exp_string_reparse);
+  value_free (self->val);
+  xfree (self->source_file);
+}
+
+struct bp_location *
+bkpt_allocate_location (struct breakpoint *self)
+{
+  struct bp_location *loc;
+
+  loc = XNEW (struct bp_location);
+  init_bp_location (loc, &bp_location_ops, self);
+  return loc;
+}
+
+void
+bkpt_re_set (struct breakpoint *b)
+{
+  switch (b->type)
+    {
+    case bp_breakpoint:
+    case bp_hardware_breakpoint:
+    case bp_gnu_ifunc_resolver:
+      /* Do not attempt to re-set breakpoints disabled during
+	 startup.  */
+      if (b->enable_state == bp_startup_disabled)
+	return;
+
+      if (b->addr_string == NULL)
+	{
+	  /* Anything without a string can't be re-set.  */
+	  delete_breakpoint (b);
+	  return;
+	}
+
+      breakpoint_re_set_default (b);
+      break;
+
+    default:
+      printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type);
+      /* fall through */
+      /* Delete overlay event and longjmp master breakpoints; they
+	 will be reset later by breakpoint_re_set.  */
+    case bp_overlay_event:
+    case bp_longjmp_master:
+    case bp_std_terminate_master:
+    case bp_exception_master:
+      delete_breakpoint (b);
+      break;
+
+      /* This breakpoint is special, it's set up when the inferior
+         starts and we really don't want to touch it.  */
+    case bp_shlib_event:
+
+      /* Like bp_shlib_event, this breakpoint type is special.  Once
+	 it is set up, we do not want to touch it.  */
+    case bp_thread_event:
+
+      /* Keep temporary breakpoints, which can be encountered when we
+         step over a dlopen call and SOLIB_ADD is resetting the
+         breakpoints.  Otherwise these should have been blown away via
+         the cleanup chain or by breakpoint_init_inferior when we
+         rerun the executable.  */
+    case bp_until:
+    case bp_finish:
+    case bp_watchpoint_scope:
+    case bp_call_dummy:
+    case bp_std_terminate:
+    case bp_step_resume:
+    case bp_hp_step_resume:
+    case bp_longjmp:
+    case bp_longjmp_resume:
+    case bp_exception:
+    case bp_exception_resume:
+    case bp_jit_event:
+    case bp_gnu_ifunc_resolver_return:
+      break;
+    }
+}
+
+int
+bkpt_insert_location (struct bp_location *bl)
+{
+  if (bl->loc_type == bp_loc_hardware_breakpoint)
+    return target_insert_hw_breakpoint (bl->gdbarch,
+					&bl->target_info);
+  else
+    return target_insert_breakpoint (bl->gdbarch,
+				     &bl->target_info);
+}
+
+int
+bkpt_remove_location (struct bp_location *bl)
+{
+  if (bl->loc_type == bp_loc_hardware_breakpoint)
+    return target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info);
+  else
+    return target_remove_breakpoint (bl->gdbarch, &bl->target_info);
+}
+
+int
+bkpt_breakpoint_hit (const struct bp_location *bl,
+		     struct address_space *aspace, CORE_ADDR bp_addr)
+{
+  struct breakpoint *b = bl->owner;
+
+  if (!breakpoint_address_match (bl->pspace->aspace, bl->address,
+				 aspace, bp_addr))
+    return 0;
+
+  if (overlay_debugging		/* unmapped overlay section */
+      && section_is_overlay (bl->section)
+      && !section_is_mapped (bl->section))
+    return 0;
+
+  return 1;
+}
+
+void
+bkpt_check_status (bpstat bs)
+{
+  struct breakpoint *b = bs->breakpoint_at;
+
+  if (b->type == bp_thread_event
+      || b->type == bp_overlay_event
+      || b->type == bp_longjmp_master
+      || b->type == bp_std_terminate_master
+      || b->type == bp_exception_master)
+    /* We do not stop for these.  */
+    bs->stop = 0;
+}
+
+int
+bkpt_resources_needed (const struct bp_location *bl)
+{
+  gdb_assert (bl->owner->type == bp_hardware_breakpoint);
+
+  return 1;
+}
+
+int
+bkpt_works_in_software_mode (const struct breakpoint *b)
+{
+  gdb_assert_not_reached ("");
+}
+
+enum print_stop_action
+bkpt_print_it (bpstat bs)
+{
+  struct cleanup *old_chain;
+  struct breakpoint *b;
+  const struct bp_location *bl;
+  struct ui_stream *stb;
+  int bp_temp = 0;
+  enum print_stop_action result;
+
+  gdb_assert (bs->bp_location_at != NULL);
+
+  bl = bs->bp_location_at;
+  b = bs->breakpoint_at;
+
+  stb = ui_out_stream_new (uiout);
+  old_chain = make_cleanup_ui_out_stream_delete (stb);
+
+  switch (b->type)
+    {
+    case bp_breakpoint:
+    case bp_hardware_breakpoint:
+      bp_temp = b->disposition == disp_del;
+      if (bl->address != bl->requested_address)
+	breakpoint_adjustment_warning (bl->requested_address,
+	                               bl->address,
+				       b->number, 1);
+      annotate_breakpoint (b->number);
+      if (bp_temp)
+	ui_out_text (uiout, "\nTemporary breakpoint ");
+      else
+	ui_out_text (uiout, "\nBreakpoint ");
+      if (ui_out_is_mi_like_p (uiout))
+	{
+	  ui_out_field_string (uiout, "reason",
+			  async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
+	  ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+	}
+      ui_out_field_int (uiout, "bkptno", b->number);
+      ui_out_text (uiout, ", ");
+      result = PRINT_SRC_AND_LOC;
+      break;
+
+    case bp_shlib_event:
+      /* Did we stop because the user set the stop_on_solib_events
+	 variable?  (If so, we report this as a generic, "Stopped due
+	 to shlib event" message.) */
+      printf_filtered (_("Stopped due to shared library event\n"));
+      result = PRINT_NOTHING;
+      break;
+
+    case bp_thread_event:
+      /* Not sure how we will get here.
+	 GDB should not stop for these breakpoints.  */
+      printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n"));
+      result = PRINT_NOTHING;
+      break;
+
+    case bp_overlay_event:
+      /* By analogy with the thread event, GDB should not stop for these.  */
+      printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n"));
+      result = PRINT_NOTHING;
+      break;
+
+    case bp_longjmp_master:
+      /* These should never be enabled.  */
+      printf_filtered (_("Longjmp Master Breakpoint: gdb should not stop!\n"));
+      result = PRINT_NOTHING;
+      break;
+
+    case bp_std_terminate_master:
+      /* These should never be enabled.  */
+      printf_filtered (_("std::terminate Master Breakpoint: "
+			 "gdb should not stop!\n"));
+      result = PRINT_NOTHING;
+      break;
+
+    case bp_exception_master:
+      /* These should never be enabled.  */
+      printf_filtered (_("Exception Master Breakpoint: "
+			 "gdb should not stop!\n"));
+      result = PRINT_NOTHING;
+      break;
+
+    /* Fall through, we don't deal with these types of breakpoints
+       here.  */
+
+    case bp_finish:
+      if (ui_out_is_mi_like_p (uiout))
+	ui_out_field_string
+	  (uiout, "reason",
+	   async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED));
+      result = PRINT_UNKNOWN;
+      break;
+
+    case bp_until:
+      if (ui_out_is_mi_like_p (uiout))
+	ui_out_field_string
+	  (uiout, "reason",
+	   async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED));
+      result = PRINT_UNKNOWN;
+      break;
+
+    case bp_none:
+    case bp_longjmp:
+    case bp_longjmp_resume:
+    case bp_exception:
+    case bp_exception_resume:
+    case bp_step_resume:
+    case bp_hp_step_resume:
+    case bp_watchpoint_scope:
+    case bp_call_dummy:
+    case bp_std_terminate:
+    case bp_tracepoint:
+    case bp_fast_tracepoint:
+    case bp_jit_event:
+    case bp_gnu_ifunc_resolver:
+    case bp_gnu_ifunc_resolver_return:
+    default:
+      result = PRINT_UNKNOWN;
+      break;
+    }
+
+  do_cleanups (old_chain);
+  return result;
+}
+
+void
+bkpt_print_mention (struct breakpoint *b)
+{
+  if (ui_out_is_mi_like_p (uiout))
+    return;
+
+  switch (b->type)
+    {
+    case bp_breakpoint:
+    case bp_gnu_ifunc_resolver:
+      if (b->disposition == disp_del)
+	printf_filtered (_("Temporary breakpoint"));
+      else
+	printf_filtered (_("Breakpoint"));
+      printf_filtered (_(" %d"), b->number);
+      if (b->type == bp_gnu_ifunc_resolver)
+	printf_filtered (_(" at gnu-indirect-function resolver"));
+      say_where (b);
+      break;
+    case bp_hardware_breakpoint:
+      printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
+      say_where (b);
+      break;
+    case bp_until:
+    case bp_finish:
+    case bp_longjmp:
+    case bp_longjmp_resume:
+    case bp_exception:
+    case bp_exception_resume:
+    case bp_step_resume:
+    case bp_hp_step_resume:
+    case bp_call_dummy:
+    case bp_std_terminate:
+    case bp_watchpoint_scope:
+    case bp_shlib_event:
+    case bp_thread_event:
+    case bp_overlay_event:
+    case bp_jit_event:
+    case bp_longjmp_master:
+    case bp_std_terminate_master:
+    case bp_exception_master:
+    case bp_gnu_ifunc_resolver_return:
+      break;
+    }
+}
+
+void
+bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp)
+{
+  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
+    internal_error (__FILE__, __LINE__,
+		    _("unhandled breakpoint type %d"), (int) tp->type);
 
-  bp_loc_first = NULL;
-  wp_loc_first = NULL;
-  awp_loc_first = NULL;
-  rwp_loc_first = NULL;
-  ALL_BP_LOCATIONS (loc, locp)
+  if (tp->exp_string)
+    fprintf_unfiltered (fp, " %s", tp->exp_string);
+  else if (tp->addr_string)
+    fprintf_unfiltered (fp, " %s", tp->addr_string);
+  else
     {
-      /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always
-	 non-NULL.  */
-      struct breakpoint *b = loc->owner;
-      struct bp_location **loc_first_p;
+      char tmp[40];
 
-      if (b->enable_state == bp_disabled
-	  || b->enable_state == bp_call_disabled
-	  || b->enable_state == bp_startup_disabled
-	  || !loc->enabled
-	  || loc->shlib_disabled
-	  || !breakpoint_address_is_meaningful (b)
-	  || is_tracepoint (b))
-	continue;
+      sprintf_vma (tmp, tp->loc->address);
+      fprintf_unfiltered (fp, " *0x%s", tmp);
+    }
+}
 
-      /* Permanent breakpoint should always be inserted.  */
-      if (b->enable_state == bp_permanent && ! loc->inserted)
-	internal_error (__FILE__, __LINE__,
-			_("allegedly permanent breakpoint is not "
-			"actually inserted"));
+/* The breakpoint_ops structure to be used in regular breakpoints.  */
 
-      if (b->type == bp_hardware_watchpoint)
-	loc_first_p = &wp_loc_first;
-      else if (b->type == bp_read_watchpoint)
-	loc_first_p = &rwp_loc_first;
-      else if (b->type == bp_access_watchpoint)
-	loc_first_p = &awp_loc_first;
-      else
-	loc_first_p = &bp_loc_first;
+struct breakpoint_ops bkpt_breakpoint_ops =
+{
+  bkpt_dtor,
+  bkpt_allocate_location,
+  bkpt_re_set,
+  bkpt_insert_location,
+  bkpt_remove_location,
+  bkpt_breakpoint_hit,
+  bkpt_check_status,
+  bkpt_resources_needed,
+  null_works_in_software_mode,
+  bkpt_print_it,
+  NULL, /* print_one */
+  null_print_one_detail,
+  bkpt_print_mention,
+  bkpt_print_recreate
+};
 
-      if (*loc_first_p == NULL
-	  || (overlay_debugging && loc->section != (*loc_first_p)->section)
-	  || !breakpoint_locations_match (loc, *loc_first_p))
-	{
-	  *loc_first_p = loc;
-	  loc->duplicate = 0;
-	  continue;
-	}
+/* The breakpoint_ops structure to be used in tracepoints.  */
 
-      loc->duplicate = 1;
+void
+tracepoint_re_set (struct breakpoint *b)
+{
+  breakpoint_re_set_default (b);
+}
 
-      if ((*loc_first_p)->owner->enable_state == bp_permanent && loc->inserted
-	  && b->enable_state != bp_permanent)
-	internal_error (__FILE__, __LINE__,
-			_("another breakpoint was inserted on top of "
-			"a permanent breakpoint"));
-    }
+static int
+tracepoint_insert_location (struct bp_location *bl)
+{
+  gdb_assert_not_reached ("");
+}
 
-  if (breakpoints_always_inserted_mode () && should_insert
-      && (have_live_inferiors ()
-	  || (gdbarch_has_global_breakpoints (target_gdbarch))))
-    insert_breakpoint_locations ();
+static int
+tracepoint_remove_location (struct bp_location *bl)
+{
+  gdb_assert_not_reached ("");
+}
 
-  do_cleanups (cleanups);
+static int
+tracepoint_breakpoint_hit (const struct bp_location *bl,
+			   struct address_space *aspace, CORE_ADDR bp_addr)
+{
+  /* By definition, the inferior does not report stops at
+     tracepoints.  */
+  return 0;
 }
 
-void
-breakpoint_retire_moribund (void)
+static void
+tracepoint_check_status (bpstat bs)
 {
-  struct bp_location *loc;
-  int ix;
+  gdb_assert_not_reached ("");
+}
 
-  for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
-    if (--(loc->events_till_retirement) == 0)
-      {
-	decref_bp_location (&loc);
-	VEC_unordered_remove (bp_location_p, moribund_locations, ix);
-	--ix;
-      }
+static int
+tracepoint_works_in_software_mode (const struct breakpoint *b)
+{
+  gdb_assert_not_reached ("");
+}
+
+static enum print_stop_action
+tracepoint_print_it (bpstat bs)
+{
+  gdb_assert_not_reached ("");
 }
 
 static void
-update_global_location_list_nothrow (int inserting)
+tracepoint_print_one_detail (const struct breakpoint *self,
+			     struct ui_out *uiout)
 {
-  struct gdb_exception e;
+  if (self->static_trace_marker_id)
+    {
+      gdb_assert (self->type == bp_static_tracepoint);
 
-  TRY_CATCH (e, RETURN_MASK_ERROR)
-    update_global_location_list (inserting);
+      ui_out_text (uiout, "\tmarker id is ");
+      ui_out_field_string (uiout, "static-tracepoint-marker-string-id",
+			   self->static_trace_marker_id);
+      ui_out_text (uiout, "\n");
+    }
 }
 
-/* Clear BKP from a BPS.  */
-
 static void
-bpstat_remove_bp_location (bpstat bps, struct breakpoint *bpt)
+tracepoint_print_mention (struct breakpoint *b)
 {
-  bpstat bs;
+  if (ui_out_is_mi_like_p (uiout))
+    return;
 
-  for (bs = bps; bs; bs = bs->next)
-    if (bs->breakpoint_at == bpt)
-      {
-	bs->breakpoint_at = NULL;
-	bs->old_val = NULL;
-	/* bs->commands will be freed later.  */
-      }
+  switch (b->type)
+    {
+    case bp_tracepoint:
+      printf_filtered (_("Tracepoint"));
+      printf_filtered (_(" %d"), b->number);
+      break;
+    case bp_fast_tracepoint:
+      printf_filtered (_("Fast tracepoint"));
+      printf_filtered (_(" %d"), b->number);
+      break;
+    case bp_static_tracepoint:
+      printf_filtered (_("Static tracepoint"));
+      printf_filtered (_(" %d"), b->number);
+      break;
+    }
+
+  say_where (b);
 }
 
-/* Callback for iterate_over_threads.  */
-static int
-bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
+static void
+tracepoint_print_recreate (struct breakpoint *tp, struct ui_file *fp)
 {
-  struct breakpoint *bpt = data;
+  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
+    internal_error (__FILE__, __LINE__,
+		    _("unhandled tracepoint type %d"), (int) tp->type);
 
-  bpstat_remove_bp_location (th->control.stop_bpstat, bpt);
-  return 0;
+  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);
+    }
 }
 
+struct breakpoint_ops tracepoint_breakpoint_ops =
+{
+  bkpt_dtor,
+  bkpt_allocate_location,
+  tracepoint_re_set,
+  tracepoint_insert_location,
+  tracepoint_remove_location,
+  tracepoint_breakpoint_hit,
+  tracepoint_check_status,
+  null_resources_needed,
+  tracepoint_works_in_software_mode,
+  tracepoint_print_it,
+  NULL, /* print_one */
+  tracepoint_print_one_detail,
+  tracepoint_print_mention,
+  tracepoint_print_recreate
+};
+
 /* Delete a breakpoint and clean up all traces of it in the data
    structures.  */
 
@@ -10863,21 +11221,6 @@ delete_breakpoint (struct breakpoint *bp
       break;
     }
 
-  if (bpt->ops != NULL && bpt->ops->dtor != NULL)
-    bpt->ops->dtor (bpt);
-
-  decref_counted_command_line (&bpt->commands);
-  xfree (bpt->cond_string);
-  xfree (bpt->cond_exp);
-  xfree (bpt->addr_string);
-  xfree (bpt->addr_string_range_end);
-  xfree (bpt->exp);
-  xfree (bpt->exp_string);
-  xfree (bpt->exp_string_reparse);
-  value_free (bpt->val);
-  xfree (bpt->source_file);
-
-
   /* Be sure no bpstat's are pointing at the breakpoint after it's
      been freed.  */
   /* FIXME, how can we find all bpstat's?  We just check stop_bpstat
@@ -10898,11 +11241,10 @@ delete_breakpoint (struct breakpoint *bp
      self-contained, but it's not the case now.  */
   update_global_location_list (0);
 
-
+  bpt->ops->dtor (bpt);
   /* On the chance that someone will soon try again to delete this
      same bp, we mark it as deleted before freeing its storage.  */
   bpt->type = bp_none;
-
   xfree (bpt);
 }
 
@@ -11421,7 +11763,11 @@ addr_string_to_sals (struct breakpoint *
   return sals;
 }
 
-void
+/* The default re_set method, for typical hardware or software
+   breakpoints.  Reevaluate the breakpoint and recreate its
+   locations.  */
+
+static void
 breakpoint_re_set_default (struct breakpoint *b)
 {
   int found;
@@ -11473,129 +11819,11 @@ breakpoint_re_set_one (void *bint)
 {
   /* Get past catch_errs.  */
   struct breakpoint *b = (struct breakpoint *) bint;
+  struct cleanup *cleanups;
 
-  if (b->ops != NULL && b->ops->re_set != NULL)
-    {
-      struct cleanup *cleanups;
-
-      cleanups = prepare_re_set_context (b);
-      b->ops->re_set (b);
-      do_cleanups (cleanups);
-
-      return 0;
-    }
-
-  switch (b->type)
-    {
-    case bp_none:
-      warning (_("attempted to reset apparently deleted breakpoint #%d?"),
-	       b->number);
-      return 0;
-    case bp_breakpoint:
-    case bp_hardware_breakpoint:
-    case bp_tracepoint:
-    case bp_fast_tracepoint:
-    case bp_static_tracepoint:
-    case bp_gnu_ifunc_resolver:
-      /* Do not attempt to re-set breakpoints disabled during startup.  */
-      if (b->enable_state == bp_startup_disabled)
-	return 0;
-
-      if (b->addr_string == NULL)
-	{
-	  /* Anything without a string can't be re-set.  */
-	  delete_breakpoint (b);
-	  return 0;
-	}
-
-      {
-	struct cleanup *cleanups;
-
-	cleanups = prepare_re_set_context (b);
-	breakpoint_re_set_default (b);
-	do_cleanups (cleanups);
-      }
-      break;
-
-    case bp_watchpoint:
-    case bp_hardware_watchpoint:
-    case bp_read_watchpoint:
-    case bp_access_watchpoint:
-      /* Watchpoint can be either on expression using entirely global
-	 variables, or it can be on local variables.
-
-	 Watchpoints of the first kind are never auto-deleted, and
-	 even persist across program restarts. Since they can use
-	 variables from shared libraries, we need to reparse
-	 expression as libraries are loaded and unloaded.
-
-	 Watchpoints on local variables can also change meaning as
-	 result of solib event.  For example, if a watchpoint uses
-	 both a local and a global variables in expression, it's a
-	 local watchpoint, but unloading of a shared library will make
-	 the expression invalid.  This is not a very common use case,
-	 but we still re-evaluate expression, to avoid surprises to
-	 the user.
-
-	 Note that for local watchpoints, we re-evaluate it only if
-	 watchpoints frame id is still valid.  If it's not, it means
-	 the watchpoint is out of scope and will be deleted soon.  In
-	 fact, I'm not sure we'll ever be called in this case.
-
-	 If a local watchpoint's frame id is still valid, then
-	 b->exp_valid_block is likewise valid, and we can safely use it.
-	 
-	 Don't do anything about disabled watchpoints, since they will
-	 be reevaluated again when enabled.  */
-      update_watchpoint (b, 1 /* reparse */);
-      break;
-      /* We needn't really do anything to reset these, since the mask
-         that requests them is unaffected by e.g., new libraries being
-         loaded.  */
-    case bp_catchpoint:
-      break;
-
-    default:
-      printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type);
-      /* fall through */
-      /* Delete overlay event and longjmp master breakpoints; they will be
-	 reset later by breakpoint_re_set.  */
-    case bp_overlay_event:
-    case bp_longjmp_master:
-    case bp_std_terminate_master:
-    case bp_exception_master:
-      delete_breakpoint (b);
-      break;
-
-      /* This breakpoint is special, it's set up when the inferior
-         starts and we really don't want to touch it.  */
-    case bp_shlib_event:
-
-      /* Like bp_shlib_event, this breakpoint type is special.
-	 Once it is set up, we do not want to touch it.  */
-    case bp_thread_event:
-
-      /* Keep temporary breakpoints, which can be encountered when we
-         step over a dlopen call and SOLIB_ADD is resetting the
-         breakpoints.  Otherwise these should have been blown away via
-         the cleanup chain or by breakpoint_init_inferior when we
-         rerun the executable.  */
-    case bp_until:
-    case bp_finish:
-    case bp_watchpoint_scope:
-    case bp_call_dummy:
-    case bp_std_terminate:
-    case bp_step_resume:
-    case bp_hp_step_resume:
-    case bp_longjmp:
-    case bp_longjmp_resume:
-    case bp_exception:
-    case bp_exception_resume:
-    case bp_jit_event:
-    case bp_gnu_ifunc_resolver_return:
-      break;
-    }
-
+  cleanups = prepare_re_set_context (b);
+  b->ops->re_set (b);
+  do_cleanups (cleanups);
   return 0;
 }
 
@@ -12347,7 +12575,7 @@ trace_command (char *arg, int from_tty)
 			 bp_tracepoint /* type_wanted */,
 			 0 /* Ignore count */,
 			 pending_break_support,
-			 NULL,
+			 &tracepoint_breakpoint_ops,
 			 from_tty,
 			 1 /* enabled */,
 			 0 /* internal */))
@@ -12364,7 +12592,7 @@ ftrace_command (char *arg, int from_tty)
 			 bp_fast_tracepoint /* type_wanted */,
 			 0 /* Ignore count */,
 			 pending_break_support,
-			 NULL,
+			 &tracepoint_breakpoint_ops,
 			 from_tty,
 			 1 /* enabled */,
 			 0 /* internal */))
@@ -12383,7 +12611,7 @@ strace_command (char *arg, int from_tty)
 			 bp_static_tracepoint /* type_wanted */,
 			 0 /* Ignore count */,
 			 pending_break_support,
-			 NULL,
+			 &tracepoint_breakpoint_ops,
 			 from_tty,
 			 1 /* enabled */,
 			 0 /* internal */))
@@ -12448,7 +12676,7 @@ create_tracepoint_from_upload (struct up
 			  utp->type /* type_wanted */,
 			  0 /* Ignore count */,
 			  pending_break_support,
-			  NULL,
+			  &tracepoint_breakpoint_ops,
 			  0 /* from_tty */,
 			  utp->enabled /* enabled */,
 			  0 /* internal */))
@@ -12774,49 +13002,7 @@ save_breakpoints (char *filename, int fr
     if (filter && !filter (tp))
       continue;
 
-    if (tp->ops != NULL && tp->ops->print_recreate != NULL)
-      (tp->ops->print_recreate) (tp, fp);
-    else
-      {
-	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);
-	  }
-      }
+    tp->ops->print_recreate (tp, fp);
 
     if (tp->thread != -1)
       fprintf_unfiltered (fp, " thread %d", tp->thread);
Index: src/gdb/ada-lang.c
===================================================================
--- src.orig/gdb/ada-lang.c	2011-06-22 18:52:55.000000000 +0100
+++ src/gdb/ada-lang.c	2011-06-24 17:04:42.348082956 +0100
@@ -10860,6 +10860,8 @@ dtor_exception (enum exception_catchpoin
   struct ada_catchpoint *c = (struct ada_catchpoint *) b;
 
   xfree (c->excep_string);
+
+  bkpt_dtor (b);
 }
 
 /* Implement the ALLOCATE_LOCATION method in the breakpoint_ops
@@ -10887,7 +10889,7 @@ re_set_exception (enum exception_catchpo
 
   /* Call the base class's method.  This updates the catchpoint's
      locations.  */
-  breakpoint_re_set_default (b);
+  bkpt_re_set (b);
 
   /* Reparse the exception conditional expressions.  One for each
      location.  */
@@ -10946,8 +10948,10 @@ check_status_exception (enum exception_c
    for all exception catchpoint kinds.  */
 
 static enum print_stop_action
-print_it_exception (enum exception_catchpoint_kind ex, struct breakpoint *b)
+print_it_exception (enum exception_catchpoint_kind ex, bpstat bs)
 {
+  struct breakpoint *b = bs->breakpoint_at;
+
   annotate_catchpoint (b->number);
 
   if (ui_out_is_mi_like_p (uiout))
@@ -11149,9 +11153,9 @@ check_status_catch_exception (bpstat bs)
 }
 
 static enum print_stop_action
-print_it_catch_exception (struct breakpoint *b)
+print_it_catch_exception (bpstat bs)
 {
-  return print_it_exception (ex_catch_exception, b);
+  return print_it_exception (ex_catch_exception, bs);
 }
 
 static void
@@ -11177,15 +11181,15 @@ static struct breakpoint_ops catch_excep
   dtor_catch_exception,
   allocate_location_catch_exception,
   re_set_catch_exception,
-  NULL, /* insert */
-  NULL, /* remove */
-  NULL, /* breakpoint_hit */
+  bkpt_insert_location,
+  bkpt_remove_location,
+  bkpt_breakpoint_hit,
   check_status_catch_exception,
-  NULL, /* resources_needed */
-  NULL, /* works_in_software_mode */
+  bkpt_resources_needed,
+  null_works_in_software_mode,
   print_it_catch_exception,
   print_one_catch_exception,
-  NULL, /* print_one_detail */
+  null_print_one_detail,
   print_mention_catch_exception,
   print_recreate_catch_exception
 };
@@ -11217,9 +11221,9 @@ check_status_catch_exception_unhandled (
 }
 
 static enum print_stop_action
-print_it_catch_exception_unhandled (struct breakpoint *b)
+print_it_catch_exception_unhandled (bpstat bs)
 {
-  return print_it_exception (ex_catch_exception_unhandled, b);
+  return print_it_exception (ex_catch_exception_unhandled, bs);
 }
 
 static void
@@ -11246,15 +11250,15 @@ static struct breakpoint_ops catch_excep
   dtor_catch_exception_unhandled,
   allocate_location_catch_exception_unhandled,
   re_set_catch_exception_unhandled,
-  NULL, /* insert */
-  NULL, /* remove */
-  NULL, /* breakpoint_hit */
+  bkpt_insert_location,
+  bkpt_remove_location,
+  bkpt_breakpoint_hit,
   check_status_catch_exception_unhandled,
-  NULL, /* resources_needed */
-  NULL, /* works_in_software_mode */
+  bkpt_resources_needed,
+  null_works_in_software_mode,
   print_it_catch_exception_unhandled,
   print_one_catch_exception_unhandled,
-  NULL, /* print_one_detail */
+  null_print_one_detail,
   print_mention_catch_exception_unhandled,
   print_recreate_catch_exception_unhandled
 };
@@ -11286,9 +11290,9 @@ check_status_catch_assert (bpstat bs)
 }
 
 static enum print_stop_action
-print_it_catch_assert (struct breakpoint *b)
+print_it_catch_assert (bpstat bs)
 {
-  return print_it_exception (ex_catch_assert, b);
+  return print_it_exception (ex_catch_assert, bs);
 }
 
 static void
@@ -11313,15 +11317,15 @@ static struct breakpoint_ops catch_asser
   dtor_catch_assert,
   allocate_location_catch_assert,
   re_set_catch_assert,
-  NULL, /* insert */
-  NULL, /* remove */
-  NULL, /* breakpoint_hit */
+  bkpt_insert_location,
+  bkpt_remove_location,
+  bkpt_breakpoint_hit,
   check_status_catch_assert,
-  NULL, /* resources_needed */
-  NULL, /* works_in_software_mode */
+  bkpt_resources_needed,
+  null_works_in_software_mode,
   print_it_catch_assert,
   print_one_catch_assert,
-  NULL, /* print_one_detail */
+  null_print_one_detail,
   print_mention_catch_assert,
   print_recreate_catch_assert
 };
Index: src/gdb/breakpoint.h
===================================================================
--- src.orig/gdb/breakpoint.h	2011-06-22 18:52:55.000000000 +0100
+++ src/gdb/breakpoint.h	2011-06-24 17:27:56.988082476 +0100
@@ -422,8 +422,8 @@ struct breakpoint_ops
   void (*re_set) (struct breakpoint *self);
 
   /* Insert the breakpoint or watchpoint or activate the catchpoint.
-     Return 0 for success, 1 if the breakpoint, watchpoint or catchpoint
-     type is not supported, -1 for failure.  */
+     Return 0 for success, 1 if the breakpoint, watchpoint or
+     catchpoint type is not supported, -1 for failure.  */
   int (*insert_location) (struct bp_location *);
 
   /* Remove the breakpoint/catchpoint that was previously inserted
@@ -454,7 +454,7 @@ struct breakpoint_ops
 
   /* The normal print routine for this breakpoint, called when we
      hit it.  */
-  enum print_stop_action (*print_it) (struct breakpoint *);
+  enum print_stop_action (*print_it) (struct bpstats *bs);
 
   /* Display information about this breakpoint, for "info
      breakpoints".  */
@@ -801,9 +801,19 @@ struct bpstat_what
    print_it_done, print_it_noop.  */
 enum print_stop_action
   {
+    /* We printed nothing or we need to do some more analysis.  */
     PRINT_UNKNOWN = -1,
+
+    /* We printed something, and we *do* desire that something to be
+       followed by a location.  */
     PRINT_SRC_AND_LOC,
+
+    /* We printed something, and we do *not* desire that something to
+       be followed by a location.  */
     PRINT_SRC_ONLY,
+
+    /* We already printed all we needed to print, don't print anything
+       else.  */
     PRINT_NOTHING
   };
 
@@ -980,12 +990,6 @@ extern void breakpoint_re_set (void);
 
 extern void breakpoint_re_set_thread (struct breakpoint *);
 
-/* The default re_set method, for typical hardware or software
-   breakpoints.  Reevaluate the breakpoint and recreate its
-   locations.  */
-
-extern void breakpoint_re_set_default (struct breakpoint *);
-
 extern struct breakpoint *set_momentary_breakpoint
   (struct gdbarch *, struct symtab_and_line, struct frame_id, enum bptype);
 
@@ -1025,6 +1029,32 @@ extern void awatch_command_wrapper (char
 extern void rwatch_command_wrapper (char *, int, int);
 extern void tbreak_command (char *, int);
 
+extern void null_re_set (struct breakpoint *b);
+extern int null_works_in_software_mode (const struct breakpoint *b);
+extern int null_resources_needed (const struct bp_location *bl);
+extern void null_check_status (bpstat bs);
+extern void null_print_one_detail (const struct breakpoint *self,
+				   struct ui_out *uiout);
+
+extern struct breakpoint_ops bkpt_breakpoint_ops;
+
+extern void bkpt_dtor (struct breakpoint *self);
+extern struct bp_location *bkpt_allocate_location (struct breakpoint *self);
+extern void bkpt_re_set (struct breakpoint *b);
+extern int bkpt_insert_location (struct bp_location *bl);
+extern int bkpt_remove_location (struct bp_location *bl);
+extern int bkpt_breakpoint_hit (const struct bp_location *bl,
+				struct address_space *aspace,
+				CORE_ADDR bp_addr);
+extern void bkpt_check_status (bpstat bs);
+extern int bkpt_resources_needed (const struct bp_location *bl);
+extern int bkpt_works_in_software_mode (const struct breakpoint *b);
+extern enum print_stop_action bkpt_print_it (bpstat bs);
+extern void null_print_one_detail (const struct breakpoint *self,
+				   struct ui_out *uiout);
+extern void bkpt_print_mention (struct breakpoint *b);
+extern void bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp);
+
 /* Arguments to pass as context to some catch command handlers.  */
 #define CATCH_PERMANENT ((void *) (uintptr_t) 0)
 #define CATCH_TEMPORARY ((void *) (uintptr_t) 1)
Index: src/gdb/mi/mi-cmd-break.c
===================================================================
--- src.orig/gdb/mi/mi-cmd-break.c	2011-04-27 12:26:59.000000000 +0100
+++ src/gdb/mi/mi-cmd-break.c	2011-06-24 15:54:42.148084408 +0100
@@ -169,7 +169,7 @@ mi_cmd_break_insert (char *command, char
 		     temp_p, type_wanted,
 		     ignore_count,
 		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
-		     NULL, 0, enabled, 0);
+		     &bkpt_breakpoint_ops, 0, enabled, 0);
   do_cleanups (back_to);
 
 }
Index: src/gdb/python/py-breakpoint.c
===================================================================
--- src.orig/gdb/python/py-breakpoint.c	2011-04-27 13:08:51.000000000 +0100
+++ src/gdb/python/py-breakpoint.c	2011-06-24 15:55:01.898084401 +0100
@@ -633,7 +633,8 @@ bppy_init (PyObject *self, PyObject *arg
 			       0, bp_breakpoint,
 			       0,
 			       AUTO_BOOLEAN_TRUE,
-			       NULL, 0, 1, internal_bp);
+			       &bkpt_breakpoint_ops,
+			       0, 1, internal_bp);
 	    break;
 	  }
         case bp_watchpoint:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]