2002-04-20 Daniel Jacobowitz <drow@mvista.com>
authorDaniel Jacobowitz <drow@false.org>
Sat, 20 Apr 2002 17:04:09 +0000 (17:04 +0000)
committerDaniel Jacobowitz <drow@false.org>
Sat, 20 Apr 2002 17:04:09 +0000 (17:04 +0000)
        * gdbserver/mem-break.c: New file.
        * gdbserver/mem-break.h: New file.
        * gdbserver/Makefile.in: Add mem-break.o rule; update server.h
        dependencies.
        * gdbserver/inferiors.c (struct inferior_info): Add target_data
        member.
        (clear_inferiors): Free target_data member if set.
        (inferior_target_data, set_inferior_target_data): New functions.
        * gdbserver/linux-i386-low.c (i386_breakpoint, i386_breakpoint_len)
        (i386_stop_pc, i386_set_pc): New.  Add to the_low_target.
        * gdbserver/linux-low.c (linux_bp_reinsert): New variable.
        (struct inferior_linux_data): New.
        (linux_create_inferior): Use set_inferior_target_data.
        (linux_attach): Likewise.  Call add_inferior.
        (linux_wait_for_one_inferior): New function.
        (linux_wait): Call it.
        (linux_write_memory): Add const.
        (initialize_low): Call set_breakpoint_data.
        * gdbserver/linux-low.h (struct linux_target_ops): Add breakpoint
        handling members.
        * gdbserver/server.c (attach_inferior): Remove extra add_inferior
        call.
        * gdbserver/server.h: Include mem-break.h.  Update inferior.c
        prototypes.
        * gdbserver/target.c (read_inferior_memory)
        (write_inferior_memory): New functions.
        * gdbserver/target.h (read_inferior_memory)
        (write_inferior_memory): Change macros to prototypes.
        (struct target_ops): Update comments.  Add const to write_memory
        definition.

12 files changed:
gdb/ChangeLog
gdb/gdbserver/Makefile.in
gdb/gdbserver/inferiors.c
gdb/gdbserver/linux-i386-low.c
gdb/gdbserver/linux-low.c
gdb/gdbserver/linux-low.h
gdb/gdbserver/mem-break.c [new file with mode: 0644]
gdb/gdbserver/mem-break.h [new file with mode: 0644]
gdb/gdbserver/server.c
gdb/gdbserver/server.h
gdb/gdbserver/target.c
gdb/gdbserver/target.h

index 7b92527..32f2a24 100644 (file)
@@ -1,3 +1,36 @@
+2002-04-20  Daniel Jacobowitz  <drow@mvista.com>
+
+       * gdbserver/mem-break.c: New file.
+       * gdbserver/mem-break.h: New file.
+       * gdbserver/Makefile.in: Add mem-break.o rule; update server.h
+       dependencies.
+       * gdbserver/inferiors.c (struct inferior_info): Add target_data
+       member.
+       (clear_inferiors): Free target_data member if set.
+       (inferior_target_data, set_inferior_target_data): New functions.
+       * gdbserver/linux-i386-low.c (i386_breakpoint, i386_breakpoint_len)
+       (i386_stop_pc, i386_set_pc): New.  Add to the_low_target.
+       * gdbserver/linux-low.c (linux_bp_reinsert): New variable.
+       (struct inferior_linux_data): New.
+       (linux_create_inferior): Use set_inferior_target_data.
+       (linux_attach): Likewise.  Call add_inferior.
+       (linux_wait_for_one_inferior): New function.
+       (linux_wait): Call it.
+       (linux_write_memory): Add const.
+       (initialize_low): Call set_breakpoint_data.
+       * gdbserver/linux-low.h (struct linux_target_ops): Add breakpoint
+       handling members.
+       * gdbserver/server.c (attach_inferior): Remove extra add_inferior
+       call.
+       * gdbserver/server.h: Include mem-break.h.  Update inferior.c
+       prototypes.
+       * gdbserver/target.c (read_inferior_memory)
+       (write_inferior_memory): New functions.
+       * gdbserver/target.h (read_inferior_memory)
+       (write_inferior_memory): Change macros to prototypes.
+       (struct target_ops): Update comments.  Add const to write_memory
+       definition.
+
 2002-04-19  Andrew Cagney  <ac131313@redhat.com>
 
        * sparc-tdep.c (sparc_get_saved_register): Use get_prev_frame
index 1e15bc0..a0bad13 100644 (file)
@@ -124,6 +124,7 @@ TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
 
 OBS = inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
        utils.o \
+       mem-break.o \
        $(DEPFILES)
 
 # Prevent Sun make from putting in the machine type.  Setting
@@ -233,9 +234,11 @@ unexport CHILLFLAGS CHILL_LIB CHILL_FOR_TARGET :
 regdat_sh = $(srcdir)/../regformats/regdat.sh
 regdef_h = $(srcdir)/../regformats/regdef.h
 regcache_h = $(srcdir)/regcache.h
-server_h = $(srcdir)/server.h $(regcache_h) config.h $(srcdir)/target.h
+server_h = $(srcdir)/server.h $(regcache_h) config.h $(srcdir)/target.h \
+               $(srcdir)/mem-break.h
 
 inferiors.o: inferiors.c $(server_h)
+mem-break.o: mem-break.c $(server_h)
 regcache.o: regcache.c $(server_h) $(regdef_h)
 remote-utils.o: remote-utils.c terminal.h $(server_h)
 server.o: server.c $(server_h)
index 1daa3c5..f8cbd04 100644 (file)
@@ -28,6 +28,7 @@
 struct inferior_info
 {
   int pid;
+  void *target_data;
   struct inferior_info *next;
 };
 
@@ -63,9 +64,25 @@ clear_inferiors (void)
   while (inf)
     {
       next_inf = inf->next;
+
+      if (inf->target_data)
+       free (inf->target_data);
+
       free (inf);
       inf = next_inf;
     }
 
   inferiors = NULL;
 }
+
+void *
+inferior_target_data (struct inferior_info *inferior)
+{
+  return inferior->target_data;
+}
+
+void
+set_inferior_target_data (struct inferior_info *inferior, void *data)
+{
+  inferior->target_data = data;
+}
index 2a398d7..7126432 100644 (file)
@@ -121,9 +121,37 @@ struct regset_info target_regsets[] = {
 
 #endif /* HAVE_LINUX_REGSETS */
 
+static const char i386_breakpoint[] = { 0xCC };
+#define i386_breakpoint_len 1
+
+static CORE_ADDR
+i386_stop_pc ()
+{
+  unsigned long pc;
+
+  /* Overkill */
+  fetch_inferior_registers (0);
+
+  collect_register_by_name ("eip", &pc);
+  return pc - 1;
+}
+
+static void
+i386_set_pc (CORE_ADDR newpc)
+{
+  supply_register_by_name ("eip", &newpc);
+
+  /* Overkill */
+  store_inferior_registers (0);
+}
+
 struct linux_target_ops the_low_target = {
   i386_num_regs,
   i386_regmap,
   i386_cannot_fetch_register,
   i386_cannot_store_register,
+  i386_stop_pc,
+  i386_set_pc,
+  i386_breakpoint,
+  i386_breakpoint_len,
 };
index bd1a876..10966e0 100644 (file)
 #include <stdlib.h>
 #include <unistd.h>
 
+static CORE_ADDR linux_bp_reinsert;
+
+static void linux_resume (int step, int signal);
+
 #define PTRACE_ARG3_TYPE long
 #define PTRACE_XFER_TYPE long
 
@@ -46,12 +50,18 @@ extern int errno;
 
 static int inferior_pid;
 
+struct inferior_linux_data
+{
+  int pid;
+};
+
 /* Start an inferior process and returns its pid.
    ALLARGS is a vector of program-name and args. */
 
 static int
 linux_create_inferior (char *program, char **allargs)
 {
+  struct inferior_linux_data *tdata;
   int pid;
 
   pid = fork ();
@@ -71,6 +81,10 @@ linux_create_inferior (char *program, char **allargs)
     }
 
   add_inferior (pid);
+  tdata = (struct inferior_linux_data *) malloc (sizeof (*tdata));
+  tdata->pid = pid;
+  set_inferior_target_data (current_inferior, tdata);
+
   /* FIXME remove */
   inferior_pid = pid;
   return 0;
@@ -81,6 +95,8 @@ linux_create_inferior (char *program, char **allargs)
 static int
 linux_attach (int pid)
 {
+  struct inferior_linux_data *tdata;
+
   if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
     {
       fprintf (stderr, "Cannot attach to process %d: %s (%d)\n", pid,
@@ -90,6 +106,10 @@ linux_attach (int pid)
       _exit (0177);
     }
 
+  add_inferior (pid);
+  tdata = (struct inferior_linux_data *) malloc (sizeof (*tdata));
+  tdata->pid = pid;
+  set_inferior_target_data (current_inferior, tdata);
   return 0;
 }
 
@@ -112,19 +132,75 @@ linux_thread_alive (int pid)
   return 1;
 }
 
+static int
+linux_wait_for_one_inferior (struct inferior_info *child)
+{
+  struct inferior_linux_data *child_data = inferior_target_data (child);
+  int pid, wstat;
+
+  while (1)
+    {
+      pid = waitpid (child_data->pid, &wstat, 0);
+
+      if (pid != child_data->pid)
+       perror_with_name ("wait");
+
+      /* If this target supports breakpoints, see if we hit one.  */
+      if (the_low_target.stop_pc != NULL
+         && WIFSTOPPED (wstat)
+         && WSTOPSIG (wstat) == SIGTRAP)
+       {
+         CORE_ADDR stop_pc;
+
+         if (linux_bp_reinsert != 0)
+           {
+             reinsert_breakpoint (linux_bp_reinsert);
+             linux_bp_reinsert = 0;
+             linux_resume (0, 0);
+             continue;
+           }
+
+         fetch_inferior_registers (0);
+         stop_pc = (*the_low_target.stop_pc) ();
+
+         if (check_breakpoints (stop_pc) != 0)
+           {
+             if (the_low_target.set_pc != NULL)
+               (*the_low_target.set_pc) (stop_pc);
+
+             if (the_low_target.breakpoint_reinsert_addr == NULL)
+               {
+                 linux_bp_reinsert = stop_pc;
+                 uninsert_breakpoint (stop_pc);
+                 linux_resume (1, 0);
+               }
+             else
+               {
+                 reinsert_breakpoint_by_bp
+                   (stop_pc, (*the_low_target.breakpoint_reinsert_addr) ());
+                 linux_resume (0, 0);
+               }
+
+             continue;
+           }
+       }
+
+      return wstat;
+    }
+  /* NOTREACHED */
+  return 0;
+}
+
 /* Wait for process, returns status */
 
 static unsigned char
 linux_wait (char *status)
 {
-  int pid;
   int w;
 
   enable_async_io ();
-  pid = waitpid (inferior_pid, &w, 0);
+  w = linux_wait_for_one_inferior (current_inferior);
   disable_async_io ();
-  if (pid != inferior_pid)
-    perror_with_name ("wait");
 
   if (WIFEXITED (w))
     {
@@ -440,7 +516,7 @@ linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
    returns the value of errno.  */
 
 static int
-linux_write_memory (CORE_ADDR memaddr, char *myaddr, int len)
+linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
 {
   register int i;
   /* Round starting address down to longword boundary.  */
@@ -508,5 +584,7 @@ void
 initialize_low (void)
 {
   set_target_ops (&linux_target_ops);
+  set_breakpoint_data (the_low_target.breakpoint,
+                      the_low_target.breakpoint_len);
   init_registers ();
 }
index e485a8e..b484982 100644 (file)
@@ -39,6 +39,11 @@ struct linux_target_ops
      store the register, and 2 if failure to store the register
      is acceptable.  */
   int (*cannot_store_register) (int);
+  CORE_ADDR (*stop_pc) (void);
+  void (*set_pc) (CORE_ADDR newpc);
+  const char *breakpoint;
+  int breakpoint_len;
+  CORE_ADDR (*breakpoint_reinsert_addr) (void);
 };
 
 extern struct linux_target_ops the_low_target;
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
new file mode 100644 (file)
index 0000000..91addf6
--- /dev/null
@@ -0,0 +1,280 @@
+/* Memory breakpoint operations for the remote server for GDB.
+   Copyright 2002
+   Free Software Foundation, Inc.
+
+   Contributed by MontaVista Software.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "server.h"
+
+const char *breakpoint_data;
+int breakpoint_len;
+
+#define MAX_BREAKPOINT_LEN 8
+
+struct breakpoint
+{
+  struct breakpoint *next;
+  CORE_ADDR pc;
+  unsigned char old_data[MAX_BREAKPOINT_LEN];
+
+  /* Non-zero iff we are stepping over this breakpoint.  */
+  int reinserting;
+
+  /* Non-NULL iff this breakpoint was inserted to step over
+     another one.  Points to the other breakpoint (which is also
+     in the *next chain somewhere).  */
+  struct breakpoint *breakpoint_to_reinsert;
+
+  /* Function to call when we hit this breakpoint.  */
+  void (*handler) (CORE_ADDR);
+};
+
+struct breakpoint *breakpoints;
+
+void
+set_breakpoint_at (CORE_ADDR where, void (*handler) (CORE_ADDR))
+{
+  struct breakpoint *bp;
+
+  if (breakpoint_data == NULL)
+    error ("Target does not support breakpoints.");
+
+  bp = malloc (sizeof (struct breakpoint));
+  memset (bp, 0, sizeof (struct breakpoint));
+
+  (*the_target->read_memory) (where, bp->old_data,
+                             breakpoint_len);
+  (*the_target->write_memory) (where, breakpoint_data,
+                              breakpoint_len);
+
+  bp->pc = where;
+  bp->handler = handler;
+
+  bp->next = breakpoints;
+  breakpoints = bp;
+}
+
+static void
+delete_breakpoint (struct breakpoint *bp)
+{
+  struct breakpoint *cur;
+
+  if (breakpoints == bp)
+    {
+      breakpoints = bp->next;
+      (*the_target->write_memory) (bp->pc, bp->old_data,
+                                  breakpoint_len);
+      free (bp);
+      return;
+    }
+  cur = breakpoints;
+  while (cur->next)
+    {
+      if (cur->next == bp)
+       {
+         cur->next = bp->next;
+         (*the_target->write_memory) (bp->pc, bp->old_data,
+                                      breakpoint_len);
+         free (bp);
+         return;
+       }
+    }
+  warning ("Could not find breakpoint in list.");
+}
+
+static struct breakpoint *
+find_breakpoint_at (CORE_ADDR where)
+{
+  struct breakpoint *bp = breakpoints;
+
+  while (bp != NULL)
+    {
+      if (bp->pc == where)
+       return bp;
+      bp = bp->next;
+    }
+
+  return NULL;
+}
+
+static void
+reinsert_breakpoint_handler (CORE_ADDR stop_pc)
+{
+  struct breakpoint *stop_bp, *orig_bp;
+
+  stop_bp = find_breakpoint_at (stop_pc);
+  if (stop_bp == NULL)
+    error ("lost the stopping breakpoint.");
+
+  orig_bp = stop_bp->breakpoint_to_reinsert;
+  if (orig_bp == NULL)
+    error ("no breakpoint to reinsert");
+
+  (*the_target->write_memory) (orig_bp->pc, breakpoint_data,
+                              breakpoint_len);
+  orig_bp->reinserting = 0;
+  delete_breakpoint (stop_bp);
+}
+
+void
+reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at)
+{
+  struct breakpoint *bp, *orig_bp;
+
+  set_breakpoint_at (stop_at, reinsert_breakpoint_handler);
+
+  orig_bp = find_breakpoint_at (stop_at);
+  if (orig_bp == NULL)
+    error ("Could not find original breakpoint in list.");
+
+  bp = find_breakpoint_at (stop_at);
+  if (bp == NULL)
+    error ("Could not find breakpoint in list (reinserting by breakpoint).");
+  bp->breakpoint_to_reinsert = orig_bp;
+
+  (*the_target->write_memory) (orig_bp->pc, orig_bp->old_data,
+                              breakpoint_len);
+  orig_bp->reinserting = 1;
+}
+
+void
+uninsert_breakpoint (CORE_ADDR stopped_at)
+{
+  struct breakpoint *bp;
+
+  bp = find_breakpoint_at (stopped_at);
+  if (bp == NULL)
+    error ("Could not find breakpoint in list (uninserting).");
+
+  (*the_target->write_memory) (bp->pc, bp->old_data,
+                              breakpoint_len);
+  bp->reinserting = 1;
+}
+
+void
+reinsert_breakpoint (CORE_ADDR stopped_at)
+{
+  struct breakpoint *bp;
+
+  bp = find_breakpoint_at (stopped_at);
+  if (bp == NULL)
+    error ("Could not find breakpoint in list (uninserting).");
+  if (! bp->reinserting)
+    error ("Breakpoint already inserted at reinsert time.");
+
+  (*the_target->write_memory) (bp->pc, breakpoint_data,
+                              breakpoint_len);
+  bp->reinserting = 0;
+}
+
+int
+check_breakpoints (CORE_ADDR stop_pc)
+{
+  struct breakpoint *bp;
+
+  bp = find_breakpoint_at (stop_pc);
+  if (bp == NULL)
+    return 0;
+  if (bp->reinserting)
+    {
+      warning ("Hit a removed breakpoint?");
+      return 0;
+    }
+
+  (*bp->handler) (bp->pc);
+  return 1;
+}
+
+void
+set_breakpoint_data (const char *bp_data, int bp_len)
+{
+  breakpoint_data = bp_data;
+  breakpoint_len = bp_len;
+}
+
+void
+check_mem_read (CORE_ADDR mem_addr, char *buf, int mem_len)
+{
+  struct breakpoint *bp = breakpoints;
+  CORE_ADDR mem_end = mem_addr + mem_len;
+
+  for (; bp != NULL; bp = bp->next)
+    {
+      CORE_ADDR bp_end = bp->pc + breakpoint_len;
+      CORE_ADDR start, end;
+      int copy_offset, copy_len, buf_offset;
+
+      if (mem_addr >= bp_end)
+       continue;
+      if (bp->pc >= mem_end)
+       continue;
+
+      start = bp->pc;
+      if (mem_addr > start)
+       start = mem_addr;
+
+      end = bp_end;
+      if (end > mem_end)
+       end = mem_end;
+
+      copy_len = end - start;
+      copy_offset = start - bp->pc;
+      buf_offset = start - mem_addr;
+
+      memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
+    }
+}
+
+void
+check_mem_write (CORE_ADDR mem_addr, char *buf, int mem_len)
+{
+  struct breakpoint *bp = breakpoints;
+  CORE_ADDR mem_end = mem_addr + mem_len;
+
+  for (; bp != NULL; bp = bp->next)
+    {
+      CORE_ADDR bp_end = bp->pc + breakpoint_len;
+      CORE_ADDR start, end;
+      int copy_offset, copy_len, buf_offset;
+
+      if (mem_addr >= bp_end)
+       continue;
+      if (bp->pc >= mem_end)
+       continue;
+
+      start = bp->pc;
+      if (mem_addr > start)
+       start = mem_addr;
+
+      end = bp_end;
+      if (end > mem_end)
+       end = mem_end;
+
+      copy_len = end - start;
+      copy_offset = start - bp->pc;
+      buf_offset = start - mem_addr;
+
+      memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len);
+      if (bp->reinserting == 0)
+       memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len);
+    }
+}
+
+
diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h
new file mode 100644 (file)
index 0000000..356e763
--- /dev/null
@@ -0,0 +1,71 @@
+/* Memory breakpoint interfaces for the remote server for GDB.
+   Copyright 2002
+   Free Software Foundation, Inc.
+
+   Contributed by MontaVista Software.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef MEM_BREAK_H
+#define MEM_BREAK_H
+
+/* Breakpoints are opaque.  */
+
+/* Create a new breakpoint at WHERE, and call HANDLER when
+   it is hit.  */
+
+void set_breakpoint_at (CORE_ADDR where,
+                       void (*handler) (CORE_ADDR));
+
+/* Create a reinsertion breakpoint at STOP_AT for the breakpoint
+   currently at STOP_PC (and temporarily remove the breakpoint at
+   STOP_PC).  */
+
+void reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at);
+
+/* Change the status of the breakpoint at WHERE to inserted.  */
+
+void reinsert_breakpoint (CORE_ADDR where);
+
+/* Change the status of the breakpoint at WHERE to uninserted.  */
+
+void uninsert_breakpoint (CORE_ADDR where);
+
+/* See if any breakpoint claims ownership of STOP_PC.  Call the handler for
+   the breakpoint, if found.  */
+
+int check_breakpoints (CORE_ADDR stop_pc);
+
+/* See if any breakpoints shadow the target memory area from MEM_ADDR
+   to MEM_ADDR + MEM_LEN.  Update the data already read from the target
+   (in BUF) if necessary.  */
+
+void check_mem_read (CORE_ADDR mem_addr, char *buf, int mem_len);
+
+/* See if any breakpoints shadow the target memory area from MEM_ADDR
+   to MEM_ADDR + MEM_LEN.  Update the data to be written to the target
+   (in BUF) if necessary, as well as the original data for any breakpoints.  */
+
+void check_mem_write (CORE_ADDR mem_addr, char *buf, int mem_len);
+
+/* Set the byte pattern to insert for memory breakpoints.  This function
+   must be called before any breakpoints are set.  */
+
+void set_breakpoint_data (const char *bp_data, int bp_len);
+
+#endif /* MEM_BREAK_H */
index 3afab2b..ba85b59 100644 (file)
@@ -48,8 +48,6 @@ attach_inferior (int pid, char *statusptr, unsigned char *sigptr)
   if (myattach (pid) != 0)
     return -1;
 
-  add_inferior (pid);
-
   *sigptr = mywait (statusptr);
 
   return 0;
index 3f0a543..0d08422 100644 (file)
@@ -58,6 +58,7 @@ typedef long long CORE_ADDR;
 #include "gdb/signals.h"
 
 #include "target.h"
+#include "mem-break.h"
 
 /* Target-specific functions */
 
@@ -74,6 +75,9 @@ extern struct inferior_info *current_inferior;
 extern int signal_pid;
 void add_inferior (int pid);
 void clear_inferiors (void);
+void *inferior_target_data (struct inferior_info *);
+void set_inferior_target_data (struct inferior_info *, void *);
+
 
 /* Public variables in server.c */
 
index 3bd87d3..53a4c1e 100644 (file)
 struct target_ops *the_target;
 
 void
+read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
+{
+  (*the_target->read_memory) (memaddr, myaddr, len);
+  check_mem_read (memaddr, myaddr, len);
+}
+
+int
+write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
+{
+  check_mem_write (memaddr, myaddr, len);
+  return (*the_target->write_memory) (memaddr, myaddr, len);
+}
+
+void
 set_target_ops (struct target_ops *target)
 {
   the_target = (struct target_ops *) malloc (sizeof (*the_target));
index 685a801..6d06b9f 100644 (file)
@@ -81,24 +81,27 @@ struct target_ops
 
   void (*store_registers) (int regno);
 
-  /* Read memory from the inferior process.
+  /* Read memory from the inferior process.  This should generally be
+     called through read_inferior_memory, which handles breakpoint shadowing.
 
      Read LEN bytes at MEMADDR into a buffer at MYADDR.  */
 
   void (*read_memory) (CORE_ADDR memaddr, char *myaddr, int len);
 
-  /* Write memory to the inferior process.
+  /* Write memory to the inferior process.  This should generally be
+     called through write_inferior_memory, which handles breakpoint shadowing.
 
      Write LEN bytes from the buffer at MYADDR to MEMADDR.
 
      Returns 0 on success and errno on failure.  */
 
-  int (*write_memory) (CORE_ADDR memaddr, char *myaddr, int len);
+  int (*write_memory) (CORE_ADDR memaddr, const char *myaddr, int len);
 
   /* Query GDB for the values of any symbols we're interested in.
      This function is called whenever we receive a "qSymbols::"
      query, which corresponds to every time more symbols (might)
-     become available.  */
+     become available.  NULL if we aren't interested in any
+     symbols.  */
 
   void (*look_up_symbols) (void);
 };
@@ -131,10 +134,8 @@ void set_target_ops (struct target_ops *);
 #define store_inferior_registers(regno) \
   (*the_target->store_registers) (regno)
 
-#define read_inferior_memory(memaddr,myaddr,len) \
-  (*the_target->read_memory) (memaddr, myaddr, len)
+void read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len);
 
-#define write_inferior_memory(memaddr,myaddr,len) \
-  (*the_target->write_memory) (memaddr, myaddr, len)
+int write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len);
 
 #endif /* TARGET_H */