Demote to sw watchpoint only in update_watchpoint.
authorThiago Jung Bauermann <bauerman@br.ibm.com>
Thu, 5 May 2011 22:52:10 +0000 (22:52 +0000)
committerThiago Jung Bauermann <bauerman@br.ibm.com>
Thu, 5 May 2011 22:52:10 +0000 (22:52 +0000)
* breakpoint.c (update_watchpoint): Change between software and
hardware watchpoint for all kinds of watchpoints, not just
read/write ones.  Determine b->exact value here instead of
in watch_command_1.  Error out if there are not enough resources
for a read or access hardware watchpoint.
(watch_command_1): Remove logic of checking whether there are
enough resources available, since update_watchpoint will do that
work now.  Don't set b->exact here.  Catch exceptions thrown by
update_watchpoint and delete the watchpoint.
(can_use_hardware_watchpoint): Remove exact_watchpoints argument.
Use target_exact_watchpoints instead.
(delete_breakpoint): Notify observers only if deleted watchpoint
has a breakpoint number assigned to it.

gdb/ChangeLog
gdb/breakpoint.c

index df26b1f198e9ac95a20c7165f4358b99bebc0c22..98b5fb828b50b560d7c146f48c5e9e140826058a 100644 (file)
@@ -1,3 +1,20 @@
+2011-05-05  Thiago Jung Bauermann  <bauerman@br.ibm.com>
+
+       Demote to sw watchpoint only in update_watchpoint.
+       * breakpoint.c (update_watchpoint): Change between software and
+       hardware watchpoint for all kinds of watchpoints, not just
+       read/write ones.  Determine b->exact value here instead of
+       in watch_command_1.  Error out if there are not enough resources
+       for a read or access hardware watchpoint.
+       (watch_command_1): Remove logic of checking whether there are
+       enough resources available, since update_watchpoint will do that
+       work now.  Don't set b->exact here.  Catch exceptions thrown by
+       update_watchpoint and delete the watchpoint.
+       (can_use_hardware_watchpoint): Remove exact_watchpoints argument.
+       Use target_exact_watchpoints instead.
+       (delete_breakpoint): Notify observers only if deleted watchpoint
+       has a breakpoint number assigned to it.
+
 2011-05-05  Janis Johnson  <janisjo@codesourcery.com>
 
        * MAINTAINERS: Add myself as a write-after-approval maintainer.
index d8eb891abc7d4d14f1ee5a6770c76ee1e6d9514b..b5fc44865a4193651bf3f11222bb24a970bf6df0 100644 (file)
@@ -101,7 +101,7 @@ static void clear_command (char *, int);
 
 static void catch_command (char *, int);
 
-static int can_use_hardware_watchpoint (struct value *, int);
+static int can_use_hardware_watchpoint (struct value *);
 
 static void break_command_1 (char *, int, int);
 
@@ -1404,19 +1404,22 @@ update_watchpoint (struct breakpoint *b, int reparse)
         an ordinary watchpoint depending on the hardware support
         and free hardware slots.  REPARSE is set when the inferior
         is started.  */
-      if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint)
-         && reparse)
+      if (reparse)
        {
          int reg_cnt;
          enum bp_loc_type loc_type;
          struct bp_location *bl;
 
-         reg_cnt = can_use_hardware_watchpoint (val_chain, b->exact);
+         reg_cnt = can_use_hardware_watchpoint (val_chain);
 
          if (reg_cnt)
            {
              int i, target_resources_ok, other_type_used;
 
+             /* Use an exact watchpoint when there's only one memory region to be
+                watched, and only one debug register is needed to watch it.  */
+             b->exact = target_exact_watchpoints && reg_cnt == 1;
+
              /* We need to determine how many resources are already
                 used for all other hardware watchpoints plus this one
                 to see if we still have enough resources to also fit
@@ -1424,16 +1427,29 @@ update_watchpoint (struct breakpoint *b, int reparse)
                 hw_watchpoint_used_count call below counts this
                 watchpoint, make sure that it is marked as a hardware
                 watchpoint.  */
-             b->type = bp_hardware_watchpoint;
-
-             i = hw_watchpoint_used_count (bp_hardware_watchpoint,
-                                           &other_type_used);
+             if (b->type == bp_watchpoint)
+               b->type = bp_hardware_watchpoint;
 
+             i = hw_watchpoint_used_count (b->type, &other_type_used);
              target_resources_ok = target_can_use_hardware_watchpoint
-                   (bp_hardware_watchpoint, i, other_type_used);
+                   (b->type, i, other_type_used);
              if (target_resources_ok <= 0)
-               b->type = bp_watchpoint;
+               {
+                 if (target_resources_ok == 0
+                     && b->type != bp_hardware_watchpoint)
+                   error (_("Target does not support this type of "
+                            "hardware watchpoint."));
+                 else if (target_resources_ok < 0
+                     && b->type != bp_hardware_watchpoint)
+                   error (_("Target can only support one kind "
+                            "of HW watchpoint at a time."));
+                 else
+                   b->type = bp_watchpoint;
+               }
            }
+         else if (b->type != bp_hardware_watchpoint)
+           error (_("Expression cannot be implemented with "
+                    "read/access watchpoint."));
          else
            b->type = bp_watchpoint;
 
@@ -8783,6 +8799,7 @@ static void
 watch_command_1 (char *arg, int accessflag, int from_tty,
                 int just_location, int internal)
 {
+  volatile struct gdb_exception e;
   struct breakpoint *b, *scope_breakpoint = NULL;
   struct expression *exp;
   struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
@@ -8794,9 +8811,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
   int toklen;
   char *cond_start = NULL;
   char *cond_end = NULL;
-  int i, other_type_used, target_resources_ok = 0;
   enum bptype bp_type;
-  int reg_cnt = 0;
   int thread = -1;
   int pc = 0;
 
@@ -8926,28 +8941,6 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
   else
     bp_type = bp_hardware_watchpoint;
 
-  reg_cnt = can_use_hardware_watchpoint (val, target_exact_watchpoints);
-  if (reg_cnt == 0 && bp_type != bp_hardware_watchpoint)
-    error (_("Expression cannot be implemented with read/access watchpoint."));
-  if (reg_cnt != 0)
-    {
-      i = hw_watchpoint_used_count (bp_type, &other_type_used);
-      target_resources_ok = 
-       target_can_use_hardware_watchpoint (bp_type, i + reg_cnt,
-                                           other_type_used);
-      if (target_resources_ok == 0 && bp_type != bp_hardware_watchpoint)
-       error (_("Target does not support this type of hardware watchpoint."));
-
-      if (target_resources_ok < 0 && bp_type != bp_hardware_watchpoint)
-       error (_("Target can only support one kind "
-                "of HW watchpoint at a time."));
-    }
-
-  /* Change the type of breakpoint to an ordinary watchpoint if a
-     hardware watchpoint could not be set.  */
-  if (!reg_cnt || target_resources_ok <= 0)
-    bp_type = bp_watchpoint;
-
   frame = block_innermost_frame (exp_valid_block);
 
   /* If the expression is "local", then set up a "watchpoint scope"
@@ -8985,7 +8978,6 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
 
   /* Now set up the breakpoint.  */
   b = set_raw_breakpoint_without_location (NULL, bp_type);
-  set_breakpoint_number (internal, b);
   b->thread = thread;
   b->disposition = disp_donttouch;
   b->exp = exp;
@@ -9016,10 +9008,6 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
   b->val_valid = 1;
   b->ops = &watchpoint_breakpoint_ops;
 
-  /* Use an exact watchpoint when there's only one memory region to be
-     watched, and only one debug register is needed to watch it.  */
-  b->exact = target_exact_watchpoints && reg_cnt == 1;
-
   if (cond_start)
     b->cond_string = savestring (cond_start, cond_end - cond_start);
   else
@@ -9047,12 +9035,22 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
   if (!just_location)
     value_free_to_mark (mark);
 
-  /* Finally update the new watchpoint.  This creates the locations
-     that should be inserted.  */
-  update_watchpoint (b, 1);
+  TRY_CATCH (e, RETURN_MASK_ALL)
+    {
+      /* Finally update the new watchpoint.  This creates the locations
+        that should be inserted.  */
+      update_watchpoint (b, 1);
+    }
+  if (e.reason < 0)
+    {
+      delete_breakpoint (b);
+      throw_exception (e);
+    }
+
+  set_breakpoint_number (internal, b);
 
   /* Do not mention breakpoints with a negative number, but do
-       notify observers.  */
+     notify observers.  */
   if (!internal)
     mention (b);
   observer_notify_breakpoint_created (b);
@@ -9061,14 +9059,10 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
 }
 
 /* Return count of debug registers needed to watch the given expression.
-   If EXACT_WATCHPOINTS is 1, then consider that only the address of
-   the start of the watched region will be monitored (i.e., all accesses
-   will be aligned).  This uses less debug registers on some targets.
-
    If the watchpoint cannot be handled in hardware return zero.  */
 
 static int
-can_use_hardware_watchpoint (struct value *v, int exact_watchpoints)
+can_use_hardware_watchpoint (struct value *v)
 {
   int found_memory_cnt = 0;
   struct value *head = v;
@@ -9124,7 +9118,7 @@ can_use_hardware_watchpoint (struct value *v, int exact_watchpoints)
                  int len;
                  int num_regs;
 
-                 len = (exact_watchpoints
+                 len = (target_exact_watchpoints
                         && is_scalar_type_recursive (vtype))?
                    1 : TYPE_LENGTH (value_type (v));
 
@@ -10483,7 +10477,12 @@ delete_breakpoint (struct breakpoint *bpt)
       bpt->related_breakpoint = bpt;
     }
 
-  observer_notify_breakpoint_deleted (bpt);
+  /* watch_command_1 creates a watchpoint but only sets its number if
+     update_watchpoint succeeds in creating its bp_locations.  If there's
+     a problem in that process, we'll be asked to delete the half-created
+     watchpoint.  In that case, don't announce the deletion.  */
+  if (bpt->number)
+    observer_notify_breakpoint_deleted (bpt);
 
   if (breakpoint_chain == bpt)
     breakpoint_chain = bpt->next;