Insert breakpoint even when the raw breakpoint is found
authorYao Qi <yao.qi@linaro.org>
Mon, 25 Apr 2016 08:43:36 +0000 (09:43 +0100)
committerYao Qi <yao.qi@linaro.org>
Mon, 25 Apr 2016 08:43:36 +0000 (09:43 +0100)
When GDBserver inserts a breakpoint, it looks for raw breakpoint, if
the raw breakpoint is found, increase its refcount, and return.  This
doesn't work when it steps over a breakpoint using software single
step and the underneath instruction of breakpoint is branch to self.

When stepping over a breakpoint on ADDR using software single step,
GDBserver uninsert the breakpoint, so the corresponding raw breakpoint
RAW's 'inserted' flag is zero.  Then, GDBserver insert single step
breakpoint at the same address ADDR because the instruction is branch
to self, the same raw brekapoint RAW is found, and increase the
refcount.  However, the raw breakpoint is not inserted, and the
program won't stop.

gdb/gdbserver:

2016-04-25  Pedro Alves  <palves@redhat.com>
    Yao Qi  <yao.qi@linaro.org>

* mem-break.c (set_raw_breakpoint_at): Create a raw breakpoint
object.  Insert it if it is not inserted yet.  Increase the
refcount and link it into the proc's raw breakpoint list.

gdb/ChangeLog
gdb/gdbserver/mem-break.c

index 0b08605449823dd01ceca4c29e881f17ec1c0843..5c94832b10e84f0dcad7dc979af3b4809b119b80 100644 (file)
@@ -1,3 +1,10 @@
+2016-04-25  Pedro Alves  <palves@redhat.com>
+           Yao Qi  <yao.qi@linaro.org>
+
+       * mem-break.c (set_raw_breakpoint_at): Create a raw breakpoint
+       object.  Insert it if it is not inserted yet.  Increase the
+       refcount and link it into the proc's raw breakpoint list.
+
 2016-04-25  Yao Qi  <yao.qi@linaro.org>
 
        * breakpoint.c (should_be_inserted): Return 0 if the location's
index b06f8e96ecc02efb120afdded79d45f6726ea4f6..419db9eb6316806c7a4bfb3d1ee71cacc1f91007 100644 (file)
@@ -390,6 +390,7 @@ set_raw_breakpoint_at (enum raw_bkpt_type type, CORE_ADDR where, int kind,
 {
   struct process_info *proc = current_process ();
   struct raw_breakpoint *bp;
+  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
 
   if (type == raw_bkpt_type_sw || type == raw_bkpt_type_hw)
     {
@@ -408,32 +409,39 @@ set_raw_breakpoint_at (enum raw_bkpt_type type, CORE_ADDR where, int kind,
   else
     bp = find_raw_breakpoint_at (where, type, kind);
 
-  if (bp != NULL)
+  if (bp == NULL)
     {
-      bp->refcount++;
-      return bp;
+      bp = XCNEW (struct raw_breakpoint);
+      bp->pc = where;
+      bp->kind = kind;
+      bp->raw_type = type;
+      make_cleanup (xfree, bp);
     }
 
-  bp = XCNEW (struct raw_breakpoint);
-  bp->pc = where;
-  bp->kind = kind;
-  bp->refcount = 1;
-  bp->raw_type = type;
-
-  *err = the_target->insert_point (bp->raw_type, bp->pc, bp->kind, bp);
-  if (*err != 0)
+  if (!bp->inserted)
     {
-      if (debug_threads)
-       debug_printf ("Failed to insert breakpoint at 0x%s (%d).\n",
-                     paddress (where), *err);
-      free (bp);
-      return NULL;
+      *err = the_target->insert_point (bp->raw_type, bp->pc, bp->kind, bp);
+      if (*err != 0)
+       {
+         if (debug_threads)
+           debug_printf ("Failed to insert breakpoint at 0x%s (%d).\n",
+                         paddress (where), *err);
+
+         do_cleanups (old_chain);
+         return NULL;
+       }
+
+      bp->inserted = 1;
     }
 
-  bp->inserted = 1;
-  /* Link the breakpoint in.  */
-  bp->next = proc->raw_breakpoints;
-  proc->raw_breakpoints = bp;
+  discard_cleanups (old_chain);
+
+  /* Link the breakpoint in, if this is the first reference.  */
+  if (++bp->refcount == 1)
+    {
+      bp->next = proc->raw_breakpoints;
+      proc->raw_breakpoints = bp;
+    }
   return bp;
 }