* linux-low.c (linux_wait_1): Avoid setting need_step_over is
authorPedro Alves <palves@redhat.com>
Thu, 1 Apr 2010 14:25:34 +0000 (14:25 +0000)
committerPedro Alves <palves@redhat.com>
Thu, 1 Apr 2010 14:25:34 +0000 (14:25 +0000)
there's a GDB breakpoint at stop_pc.  Always report a trap to GDB
if we could tell there's a GDB breakpoint at stop_pc.
(need_step_over_p): Don't do a step over if we find a GDB
breakpoint at the resume PC.

* mem-break.c (struct raw_breakpoint): New.
(enum bkpt_type): New type `gdb_breakpoint'.
(struct breakpoint): Delete the `PC', `old_data' and `inserted'
fields.  New field `raw'.
(find_raw_breakpoint_at): New.
(set_raw_breakpoint_at): Handle refcounting.  Create a raw
breakpoint instead.
(set_breakpoint_at): Adjust.
(delete_raw_breakpoint): New.
(release_breakpoint): New.
(delete_breakpoint): Rename to...
(delete_breakpoint_1): ... this.  Add proc parameter.  Use
release_breakpoint.  Return ENOENT.
(delete_breakpoint): Reimplement.
(find_breakpoint_at): Delete.
(find_gdb_breakpoint_at): New.
(delete_breakpoint_at): Delete.
(set_gdb_breakpoint_at): New.
(delete_gdb_breakpoint_at): New.
(gdb_breakpoint_here): New.
(set_reinsert_breakpoint): Use release_breakpoint.
(uninsert_breakpoint): Rename to ...
(uninsert_raw_breakpoint): ... this.
(uninsert_breakpoints_at): Adjust to handle raw breakpoints.
(reinsert_raw_breakpoint): Change parameter type to
raw_breakpoint.
(reinsert_breakpoints_at): Adjust to handle raw breakpoints
instead.
(check_breakpoints): Adjust.  Use release_breakpoint.
(breakpoint_here): Rewrite using find_raw_breakpoint_at.
(breakpoint_inserted_here): Ditto.
(check_mem_read): Adjust to iterate over raw breakpoints instead.
Don't trust the breakpoint's shadow if it is not inserted.
(check_mem_write): Adjust to iterate over raw breakpoints instead.
(delete_all_breakpoints): Adjust.
(free_all_breakpoints): Mark all breakpoints as uninserted, and
use delete_breakpoint_1.

* mem-break.h (breakpoints_supported): Delete declaration.
(set_gdb_breakpoint_at): Declare.
(gdb_breakpoint_here): Declare.
(delete_breakpoint_at): Delete.
(delete_gdb_breakpoint_at): Declare.

* server.h (struct raw_breakpoint): Forward declare.
(struct process_info): New field `raw_breakpoints'.

* linux-x86-low.c (x86_insert_point, x86_remote_point): Handle Z0
breakpoints.

gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-low.c
gdb/gdbserver/linux-x86-low.c
gdb/gdbserver/mem-break.c
gdb/gdbserver/mem-break.h
gdb/gdbserver/server.h

index 9831ef3..eb6c0ba 100644 (file)
@@ -1,3 +1,61 @@
+2010-04-01  Pedro Alves  <pedro@codesourcery.com>
+
+       * linux-low.c (linux_wait_1): Avoid setting need_step_over is
+       there's a GDB breakpoint at stop_pc.  Always report a trap to GDB
+       if we could tell there's a GDB breakpoint at stop_pc.
+       (need_step_over_p): Don't do a step over if we find a GDB
+       breakpoint at the resume PC.
+
+       * mem-break.c (struct raw_breakpoint): New.
+       (enum bkpt_type): New type `gdb_breakpoint'.
+       (struct breakpoint): Delete the `PC', `old_data' and `inserted'
+       fields.  New field `raw'.
+       (find_raw_breakpoint_at): New.
+       (set_raw_breakpoint_at): Handle refcounting.  Create a raw
+       breakpoint instead.
+       (set_breakpoint_at): Adjust.
+       (delete_raw_breakpoint): New.
+       (release_breakpoint): New.
+       (delete_breakpoint): Rename to...
+       (delete_breakpoint_1): ... this.  Add proc parameter.  Use
+       release_breakpoint.  Return ENOENT.
+       (delete_breakpoint): Reimplement.
+       (find_breakpoint_at): Delete.
+       (find_gdb_breakpoint_at): New.
+       (delete_breakpoint_at): Delete.
+       (set_gdb_breakpoint_at): New.
+       (delete_gdb_breakpoint_at): New.
+       (gdb_breakpoint_here): New.
+       (set_reinsert_breakpoint): Use release_breakpoint.
+       (uninsert_breakpoint): Rename to ...
+       (uninsert_raw_breakpoint): ... this.
+       (uninsert_breakpoints_at): Adjust to handle raw breakpoints.
+       (reinsert_raw_breakpoint): Change parameter type to
+       raw_breakpoint.
+       (reinsert_breakpoints_at): Adjust to handle raw breakpoints
+       instead.
+       (check_breakpoints): Adjust.  Use release_breakpoint.
+       (breakpoint_here): Rewrite using find_raw_breakpoint_at.
+       (breakpoint_inserted_here): Ditto.
+       (check_mem_read): Adjust to iterate over raw breakpoints instead.
+       Don't trust the breakpoint's shadow if it is not inserted.
+       (check_mem_write): Adjust to iterate over raw breakpoints instead.
+       (delete_all_breakpoints): Adjust.
+       (free_all_breakpoints): Mark all breakpoints as uninserted, and
+       use delete_breakpoint_1.
+
+       * mem-break.h (breakpoints_supported): Delete declaration.
+       (set_gdb_breakpoint_at): Declare.
+       (gdb_breakpoint_here): Declare.
+       (delete_breakpoint_at): Delete.
+       (delete_gdb_breakpoint_at): Declare.
+
+       * server.h (struct raw_breakpoint): Forward declare.
+       (struct process_info): New field `raw_breakpoints'.
+
+       * linux-x86-low.c (x86_insert_point, x86_remote_point): Handle Z0
+       breakpoints.
+
 2010-03-24  Pedro Alves  <pedro@codesourcery.com>
 
        * linux-low.c (status_pending_p_callback): Fix comment.
index ad68179..84f549c 100644 (file)
@@ -1740,7 +1740,8 @@ retry:
          if (debug_threads)
            fprintf (stderr, "Hit a gdbserver breakpoint.\n");
 
-         event_child->need_step_over = 1;
+         if (breakpoint_here (event_child->stop_pc))
+           event_child->need_step_over = 1;
        }
     }
   else
@@ -1755,11 +1756,18 @@ retry:
 
   /* Check If GDB would be interested in this event.  If GDB wanted
      this thread to single step, we always want to report the SIGTRAP,
-     and let GDB handle it.  */
+     and let GDB handle it.  Watchpoints should always be reported.
+     So should signals we can't explain.  A SIGTRAP we can't explain
+     could be a GDB breakpoint --- we may or not support Z0
+     breakpoints.  If we do, we're be able to handle GDB breakpoints
+     on top of internal breakpoints, by handling the internal
+     breakpoint and still reporting the event to GDB.  If we don't,
+     we're out of luck, GDB won't see the breakpoint hit.  */
   report_to_gdb = (!maybe_internal_trap
                   || event_child->last_resume_kind == resume_step
                   || event_child->stopped_by_watchpoint
-                  || (!step_over_finished && !bp_explains_trap));
+                  || (!step_over_finished && !bp_explains_trap)
+                  || gdb_breakpoint_here (event_child->stop_pc));
 
   /* We found no reason GDB would want us to stop.  We either hit one
      of our own breakpoints, or finished an internal step GDB
@@ -1801,6 +1809,8 @@ retry:
        fprintf (stderr, "GDB wanted to single-step, reporting event.\n");
       if (event_child->stopped_by_watchpoint)
        fprintf (stderr, "Stopped by watchpoint.\n");
+      if (gdb_breakpoint_here (event_child->stop_pc))
+       fprintf (stderr, "Stopped by GDB breakpoint.\n");
       if (debug_threads)
        fprintf (stderr, "Hit a non-gdbserver trap event.\n");
     }
@@ -2401,21 +2411,37 @@ need_step_over_p (struct inferior_list_entry *entry, void *dummy)
   saved_inferior = current_inferior;
   current_inferior = get_lwp_thread (lwp);
 
-  /* We only step over our breakpoints.  */
+  /* We can only step over breakpoints we know about.  */
   if (breakpoint_here (pc))
     {
-      if (debug_threads)
-       fprintf (stderr,
-                "Need step over [LWP %ld]? yes, found breakpoint at 0x%s\n",
-                lwpid_of (lwp), paddress (pc));
+      /* Don't step over a breakpoint that GDB expects to hit
+        though.  */
+      if (gdb_breakpoint_here (pc))
+       {
+         if (debug_threads)
+           fprintf (stderr,
+                    "Need step over [LWP %ld]? yes, but found"
+                    " GDB breakpoint at 0x%s; skipping step over\n",
+                    lwpid_of (lwp), paddress (pc));
 
-      /* We've found an lwp that needs stepping over --- return 1 so
-        that find_inferior stops looking.  */
-      current_inferior = saved_inferior;
+         current_inferior = saved_inferior;
+         return 0;
+       }
+      else
+       {
+         if (debug_threads)
+           fprintf (stderr,
+                    "Need step over [LWP %ld]? yes, found breakpoint at 0x%s\n",
+                    lwpid_of (lwp), paddress (pc));
 
-      /* If the step over is cancelled, this is set again.  */
-      lwp->need_step_over = 0;
-      return 1;
+         /* We've found an lwp that needs stepping over --- return 1 so
+            that find_inferior stops looking.  */
+         current_inferior = saved_inferior;
+
+         /* If the step over is cancelled, this is set again.  */
+         lwp->need_step_over = 0;
+         return 1;
+       }
     }
 
   current_inferior = saved_inferior;
index fe5d46e..1f9e1b1 100644 (file)
@@ -431,6 +431,8 @@ x86_insert_point (char type, CORE_ADDR addr, int len)
   struct process_info *proc = current_process ();
   switch (type)
     {
+    case '0':
+      return set_gdb_breakpoint_at (addr);
     case '2':
     case '3':
     case '4':
@@ -448,6 +450,8 @@ x86_remove_point (char type, CORE_ADDR addr, int len)
   struct process_info *proc = current_process ();
   switch (type)
     {
+    case '0':
+      return delete_gdb_breakpoint_at (addr);
     case '2':
     case '3':
     case '4':
index 33de80c..5256cb7 100644 (file)
@@ -26,9 +26,53 @@ int breakpoint_len;
 
 #define MAX_BREAKPOINT_LEN 8
 
+/* GDB will never try to install multiple breakpoints at the same
+   address.  But, we need to keep track of internal breakpoints too,
+   and so we do need to be able to install multiple breakpoints at the
+   same address transparently.  We keep track of two different, and
+   closely related structures.  A raw breakpoint, which manages the
+   low level, close to the metal aspect of a breakpoint.  It holds the
+   breakpoint address, and a buffer holding a copy of the instructions
+   that would be in memory had not been a breakpoint there (we call
+   that the shadow memory of the breakpoint).  We occasionally need to
+   temporarilly uninsert a breakpoint without the client knowing about
+   it (e.g., to step over an internal breakpoint), so we keep an
+   `inserted' state associated with this low level breakpoint
+   structure.  There can only be one such object for a given address.
+   Then, we have (a bit higher level) breakpoints.  This structure
+   holds a callback to be called whenever a breakpoint is hit, a
+   high-level type, and a link to a low level raw breakpoint.  There
+   can be many high-level breakpoints at the same address, and all of
+   them will point to the same raw breakpoint, which is reference
+   counted.  */
+
+/* The low level, physical, raw breakpoint.  */
+struct raw_breakpoint
+{
+  struct raw_breakpoint *next;
+
+  /* A reference count.  Each high level breakpoint referencing this
+     raw breakpoint accounts for one reference.  */
+  int refcount;
+
+  /* The breakpoint's insertion address.  There can only be one raw
+     breakpoint for a given PC.  */
+  CORE_ADDR pc;
+
+  /* The breakpoint's shadow memory.  */
+  unsigned char old_data[MAX_BREAKPOINT_LEN];
+
+  /* Non-zero if this breakpoint is currently inserted in the
+     inferior.  */
+  int inserted;
+};
+
 /* The type of a breakpoint.  */
 enum bkpt_type
   {
+    /* A GDB breakpoint, requested with a Z0 packet.  */
+    gdb_breakpoint,
+
     /* A basic-software-single-step breakpoint.  */
     reinsert_breakpoint,
 
@@ -37,38 +81,57 @@ enum bkpt_type
     other_breakpoint,
   };
 
+/* A high level (in gdbserver's perspective) breakpoint.  */
 struct breakpoint
 {
   struct breakpoint *next;
-  CORE_ADDR pc;
-  unsigned char old_data[MAX_BREAKPOINT_LEN];
-
-  /* Non-zero if this breakpoint is currently inserted in the
-     inferior.  */
-  int inserted;
 
   /* The breakpoint's type.  */
   enum bkpt_type type;
 
+  /* Link to this breakpoint's raw breakpoint.  This is always
+     non-NULL.  */
+  struct raw_breakpoint *raw;
+
   /* Function to call when we hit this breakpoint.  If it returns 1,
-     the breakpoint shall be deleted; 0, it will be left inserted.  */
+     the breakpoint shall be deleted; 0 or if this callback is NULL,
+     it will be left inserted.  */
   int (*handler) (CORE_ADDR);
 };
 
-static void uninsert_breakpoint (struct breakpoint *bp);
+static struct raw_breakpoint *
+find_raw_breakpoint_at (CORE_ADDR where)
+{
+  struct process_info *proc = current_process ();
+  struct raw_breakpoint *bp;
 
-static struct breakpoint *
+  for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
+    if (bp->pc == where)
+      return bp;
+
+  return NULL;
+}
+
+static struct raw_breakpoint *
 set_raw_breakpoint_at (CORE_ADDR where)
 {
   struct process_info *proc = current_process ();
-  struct breakpoint *bp;
+  struct raw_breakpoint *bp;
   int err;
 
   if (breakpoint_data == NULL)
     error ("Target does not support breakpoints.");
 
+  bp = find_raw_breakpoint_at (where);
+  if (bp != NULL)
+    {
+      bp->refcount++;
+      return bp;
+    }
+
   bp = xcalloc (1, sizeof (*bp));
   bp->pc = where;
+  bp->refcount = 1;
 
   err = (*the_target->read_memory) (where, bp->old_data,
                                    breakpoint_len);
@@ -97,8 +160,8 @@ set_raw_breakpoint_at (CORE_ADDR where)
 
   /* Link the breakpoint in.  */
   bp->inserted = 1;
-  bp->next = proc->breakpoints;
-  proc->breakpoints = bp;
+  bp->next = proc->raw_breakpoints;
+  proc->raw_breakpoints = bp;
   return bp;
 }
 
@@ -107,10 +170,11 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
 {
   struct process_info *proc = current_process ();
   struct breakpoint *bp;
+  struct raw_breakpoint *raw;
 
-  bp = set_raw_breakpoint_at (where);
+  raw = set_raw_breakpoint_at (where);
 
-  if (bp == NULL)
+  if (raw == NULL)
     {
       /* warn? */
       return NULL;
@@ -118,6 +182,8 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
 
   bp = xcalloc (1, sizeof (struct breakpoint));
   bp->type = other_breakpoint;
+
+  bp->raw = raw;
   bp->handler = handler;
 
   bp->next = proc->breakpoints;
@@ -126,11 +192,84 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
   return bp;
 }
 
-static void
-delete_breakpoint (struct breakpoint *todel)
+static int
+delete_raw_breakpoint (struct process_info *proc, struct raw_breakpoint *todel)
+{
+  struct raw_breakpoint *bp, **bp_link;
+  int ret;
+
+  bp = proc->raw_breakpoints;
+  bp_link = &proc->raw_breakpoints;
+
+  while (bp)
+    {
+      if (bp == todel)
+       {
+         if (bp->inserted)
+           {
+             struct raw_breakpoint *prev_bp_link = *bp_link;
+
+             *bp_link = bp->next;
+
+             ret = (*the_target->write_memory) (bp->pc, bp->old_data,
+                                                breakpoint_len);
+             if (ret != 0)
+               {
+                 /* Something went wrong, relink the breakpoint.  */
+                 *bp_link = prev_bp_link;
+
+                 if (debug_threads)
+                   fprintf (stderr,
+                            "Failed to uninsert raw breakpoint "
+                            "at 0x%s (%s) while deleting it.\n",
+                            paddress (bp->pc), strerror (ret));
+                 return ret;
+               }
+
+           }
+         else
+           *bp_link = bp->next;
+
+         free (bp);
+         return 0;
+       }
+      else
+       {
+         bp_link = &bp->next;
+         bp = *bp_link;
+       }
+    }
+
+  warning ("Could not find raw breakpoint in list.");
+  return ENOENT;
+}
+
+static int
+release_breakpoint (struct process_info *proc, struct breakpoint *bp)
+{
+  int newrefcount;
+  int ret;
+
+  newrefcount = bp->raw->refcount - 1;
+  if (newrefcount == 0)
+    {
+      ret = delete_raw_breakpoint (proc, bp->raw);
+      if (ret != 0)
+       return ret;
+    }
+  else
+    bp->raw->refcount = newrefcount;
+
+  free (bp);
+
+  return 0;
+}
+
+static int
+delete_breakpoint_1 (struct process_info *proc, struct breakpoint *todel)
 {
-  struct process_info *proc = current_process ();
   struct breakpoint *bp, **bp_link;
+  int err;
 
   bp = proc->breakpoints;
   bp_link = &proc->breakpoints;
@@ -141,9 +280,12 @@ delete_breakpoint (struct breakpoint *todel)
        {
          *bp_link = bp->next;
 
-         uninsert_breakpoint (bp);
-         free (bp);
-         return;
+         err = release_breakpoint (proc, bp);
+         if (err != 0)
+           return err;
+
+         bp = *bp_link;
+         return 0;
        }
       else
        {
@@ -153,30 +295,71 @@ delete_breakpoint (struct breakpoint *todel)
     }
 
   warning ("Could not find breakpoint in list.");
+  return ENOENT;
+}
+
+static int
+delete_breakpoint (struct breakpoint *todel)
+{
+  struct process_info *proc = current_process ();
+  return delete_breakpoint_1 (proc, todel);
 }
 
 static struct breakpoint *
-find_breakpoint_at (CORE_ADDR where)
+find_gdb_breakpoint_at (CORE_ADDR where)
 {
   struct process_info *proc = current_process ();
-  struct breakpoint *bp = proc->breakpoints;
+  struct breakpoint *bp;
 
-  while (bp != NULL)
-    {
-      if (bp->pc == where)
-       return bp;
-      bp = bp->next;
-    }
+  for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
+    if (bp->type == gdb_breakpoint && bp->raw->pc == where)
+      return bp;
 
   return NULL;
 }
 
-void
-delete_breakpoint_at (CORE_ADDR addr)
+int
+set_gdb_breakpoint_at (CORE_ADDR where)
 {
-  struct breakpoint *bp = find_breakpoint_at (addr);
-  if (bp != NULL)
-    delete_breakpoint (bp);
+  struct breakpoint *bp;
+
+  if (breakpoint_data == NULL)
+    return 1;
+
+  bp = set_breakpoint_at (where, NULL);
+  if (bp == NULL)
+    return -1;
+
+  bp->type = gdb_breakpoint;
+  return 0;
+}
+
+int
+delete_gdb_breakpoint_at (CORE_ADDR addr)
+{
+  struct breakpoint *bp;
+  int err;
+
+  if (breakpoint_data == NULL)
+    return 1;
+
+  bp = find_gdb_breakpoint_at (addr);
+  if (bp == NULL)
+    return -1;
+
+  err = delete_breakpoint (bp);
+  if (err)
+    return -1;
+
+  return 0;
+}
+
+int
+gdb_breakpoint_here (CORE_ADDR where)
+{
+  struct breakpoint *bp = find_gdb_breakpoint_at (where);
+
+  return (bp != NULL);
 }
 
 void
@@ -185,7 +368,6 @@ set_reinsert_breakpoint (CORE_ADDR stop_at)
   struct breakpoint *bp;
 
   bp = set_breakpoint_at (stop_at, NULL);
-
   bp->type = reinsert_breakpoint;
 }
 
@@ -203,13 +385,7 @@ delete_reinsert_breakpoints (void)
       if (bp->type == reinsert_breakpoint)
        {
          *bp_link = bp->next;
-
-         /* If something goes wrong, maybe this is a shared library
-            breakpoint, and the shared library has been unmapped.
-            Assume the breakpoint is gone anyway.  */
-         uninsert_breakpoint (bp);
-         free (bp);
-
+         release_breakpoint (proc, bp);
          bp = *bp_link;
        }
       else
@@ -221,7 +397,7 @@ delete_reinsert_breakpoints (void)
 }
 
 static void
-uninsert_breakpoint (struct breakpoint *bp)
+uninsert_raw_breakpoint (struct raw_breakpoint *bp)
 {
   if (bp->inserted)
     {
@@ -245,9 +421,9 @@ uninsert_breakpoint (struct breakpoint *bp)
 void
 uninsert_breakpoints_at (CORE_ADDR pc)
 {
-  struct breakpoint *bp;
+  struct raw_breakpoint *bp;
 
-  bp = find_breakpoint_at (pc);
+  bp = find_raw_breakpoint_at (pc);
   if (bp == NULL)
     {
       /* This can happen when we remove all breakpoints while handling
@@ -261,11 +437,11 @@ uninsert_breakpoints_at (CORE_ADDR pc)
     }
 
   if (bp->inserted)
-    uninsert_breakpoint (bp);
+    uninsert_raw_breakpoint (bp);
 }
 
 static void
-reinsert_raw_breakpoint (struct breakpoint *bp)
+reinsert_raw_breakpoint (struct raw_breakpoint *bp)
 {
   int err;
 
@@ -285,16 +461,16 @@ reinsert_raw_breakpoint (struct breakpoint *bp)
 void
 reinsert_breakpoints_at (CORE_ADDR pc)
 {
-  struct breakpoint *bp;
+  struct raw_breakpoint *bp;
 
-  bp = find_breakpoint_at (pc);
+  bp = find_raw_breakpoint_at (pc);
   if (bp == NULL)
     {
       /* This can happen when we remove all breakpoints while handling
         a step-over.  */
       if (debug_threads)
        fprintf (stderr,
-                "Could not find breakpoint at 0x%s "
+                "Could not find raw breakpoint at 0x%s "
                 "in list (reinserting).\n",
                 paddress (pc));
       return;
@@ -314,9 +490,9 @@ check_breakpoints (CORE_ADDR stop_pc)
 
   while (bp)
     {
-      if (bp->pc == stop_pc)
+      if (bp->raw->pc == stop_pc)
        {
-         if (!bp->inserted)
+         if (!bp->raw->inserted)
            {
              warning ("Hit a removed breakpoint?");
              return;
@@ -326,7 +502,7 @@ check_breakpoints (CORE_ADDR stop_pc)
            {
              *bp_link = bp->next;
 
-             delete_breakpoint (bp);
+             release_breakpoint (proc, bp);
 
              bp = *bp_link;
              continue;
@@ -348,34 +524,24 @@ set_breakpoint_data (const unsigned char *bp_data, int bp_len)
 int
 breakpoint_here (CORE_ADDR addr)
 {
-  struct process_info *proc = current_process ();
-  struct breakpoint *bp;
-
-  for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
-    if (bp->pc == addr)
-      return 1;
-
-  return 0;
+  return (find_raw_breakpoint_at (addr) != NULL);
 }
 
 int
 breakpoint_inserted_here (CORE_ADDR addr)
 {
-  struct process_info *proc = current_process ();
-  struct breakpoint *bp;
+  struct raw_breakpoint *bp;
 
-  for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
-    if (bp->pc == addr && bp->inserted)
-      return 1;
+  bp = find_raw_breakpoint_at (addr);
 
-  return 0;
+  return (bp != NULL && bp->inserted);
 }
 
 void
 check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
 {
   struct process_info *proc = current_process ();
-  struct breakpoint *bp = proc->breakpoints;
+  struct raw_breakpoint *bp = proc->raw_breakpoints;
   CORE_ADDR mem_end = mem_addr + mem_len;
 
   for (; bp != NULL; bp = bp->next)
@@ -401,7 +567,8 @@ check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
       copy_offset = start - bp->pc;
       buf_offset = start - mem_addr;
 
-      memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
+      if (bp->inserted)
+       memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
     }
 }
 
@@ -409,7 +576,7 @@ void
 check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
 {
   struct process_info *proc = current_process ();
-  struct breakpoint *bp = proc->breakpoints;
+  struct raw_breakpoint *bp = proc->raw_breakpoints;
   CORE_ADDR mem_end = mem_addr + mem_len;
 
   for (; bp != NULL; bp = bp->next)
@@ -449,7 +616,7 @@ delete_all_breakpoints (void)
   struct process_info *proc = current_process ();
 
   while (proc->breakpoints)
-    delete_breakpoint (proc->breakpoints);
+    delete_breakpoint_1 (proc, proc->breakpoints);
 }
 
 /* Release all breakpoints, but do not try to un-insert them from the
@@ -458,12 +625,15 @@ delete_all_breakpoints (void)
 void
 free_all_breakpoints (struct process_info *proc)
 {
-  struct breakpoint *bp;
+  struct raw_breakpoint *raw_bp;
 
+  for (raw_bp = proc->raw_breakpoints; raw_bp != NULL; raw_bp = raw_bp->next)
+    raw_bp->inserted = 0;
+
+  /* Note: use PROC explicitly instead of deferring to
+     delete_all_breakpoints --- CURRENT_INFERIOR may already have been
+     released when we get here.  There should be no call to
+     current_process from here on.  */
   while (proc->breakpoints)
-    {
-      bp = proc->breakpoints;
-      proc->breakpoints = bp->next;
-      free (bp);
-    }
+    delete_breakpoint_1 (proc, proc->breakpoints);
 }
index 2953d03..01087fd 100644 (file)
 /* Breakpoints are opaque.  */
 struct breakpoint;
 
-/* Returns TRUE if breakpoints are supported on this target.  */
+/* Create a new GDB breakpoint at WHERE.  Returns -1 if breakpoints
+   are not supported on this target, 0 otherwise.  */
 
-int breakpoints_supported (void);
+int set_gdb_breakpoint_at (CORE_ADDR where);
 
 /* Returns TRUE if there's any breakpoint at ADDR in our tables,
    inserted, or not.  */
@@ -38,6 +39,10 @@ int breakpoint_here (CORE_ADDR addr);
 
 int breakpoint_inserted_here (CORE_ADDR addr);
 
+/* Returns TRUE if there's a GDB breakpoint set at ADDR.  */
+
+int gdb_breakpoint_here (CORE_ADDR where);
+
 /* Create a new breakpoint at WHERE, and call HANDLER when
    it is hit.  HANDLER should return 1 if the breakpoint
    should be deleted, 0 otherwise.  */
@@ -45,10 +50,10 @@ int breakpoint_inserted_here (CORE_ADDR addr);
 struct breakpoint *set_breakpoint_at (CORE_ADDR where,
                                      int (*handler) (CORE_ADDR));
 
-/* Delete a breakpoint previously inserted at ADDR with
-   set_breakpoint_at.  */
+/* Delete a GDB breakpoint previously inserted at ADDR with
+   set_gdb_breakpoint_at.  */
 
-void delete_breakpoint_at (CORE_ADDR addr);
+int delete_gdb_breakpoint_at (CORE_ADDR addr);
 
 /* Set a reinsert breakpoint at STOP_AT.  */
 
index 54d80ed..88c6c5e 100644 (file)
@@ -191,6 +191,7 @@ struct dll_info
 
 struct sym_cache;
 struct breakpoint;
+struct raw_breakpoint;
 struct process_info_private;
 
 struct process_info
@@ -209,6 +210,9 @@ struct process_info
   /* The list of memory breakpoints.  */
   struct breakpoint *breakpoints;
 
+  /* The list of raw memory breakpoints.  */
+  struct raw_breakpoint *raw_breakpoints;
+
   /* Private target data.  */
   struct process_info_private *private;
 };