This is the mail archive of the gdb-patches@sources.redhat.com 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]

PATCH: breakpoints for gdbserver


This gives gdbserver a framework for memory-shadowing breakpoints, invisible
to GDB.  They won't behave gracefully if GDB tries to single-step over them
or if the user puts breakpoints at the same places; I intend to control all
the cases where gdbserver might insert them with command line options, so
that if (say) you want to debug LinuxThreads, you can turn off gdbserver
thread support.  That's the only way to get reasonable results, IMHO.

There's a little bit of ugliness here, in that some targets do not support
PTRACE_SINGLESTEP.  If gdbserver does not know how to single-step a target,
the backend for that target should supply a function to find a safe
instruction that we know will be reached, to place a temporary breakpoint
on.  It can be the next instruction, or it can be the function return
address, since the only places these breakpoints will be used (so far, at
least) are on empty marker functions in the dynamic linker or in
LinuxThreads or in some similar event-based debugging technique.  Hurdles
will be dealt with as they arise; I don't want to over-complicate this. 
Both single-step and resume breakpoint methods have been tested.

The only target to actually support breakpoints right now is i386-*-linux-gnu. 
I'll go through and add breakpoints for all the other gdbserver targets at a
not-too-future date.

I'll commit this in a day or so unless someone sees a problem with it.  Next
on my list is a per-inferior register cache, and then I'll knuckle down to
the core of an actual threads package.  No documentation is needed with this
patch, although when I have a little time I may write a small gdbserver
internals document... on the off chance someone actually wants to resurrect
this on a target I don't have, and all...

-- 
Daniel Jacobowitz                           Carnegie Mellon University
MontaVista Software                         Debian GNU/Linux Developer

2002-04-16  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.

Index: mem-break.c
===================================================================
RCS file: N/A
diff -u /dev/null mem-break.c
--- /dev/null	Wed Dec 31 19:00:00 1969
+++ mem-break.c	Tue Apr 16 00:43:43 2002
@@ -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);
+    }
+}
+
+
Index: mem-break.h
===================================================================
RCS file: N/A
diff -u /dev/null mem-break.h
--- /dev/null	Wed Dec 31 19:00:00 1969
+++ mem-break.h	Tue Apr 16 00:44:57 2002
@@ -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: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/Makefile.in,v
retrieving revision 1.16
diff -u -p -r1.16 Makefile.in
--- Makefile.in	9 Apr 2002 21:25:29 -0000	1.16
+++ Makefile.in	16 Apr 2002 05:23:15 -0000
@@ -124,6 +124,7 @@ TAGFILES = $(SOURCES) ${HFILES} ${ALLPAR
 
 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_
 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: inferiors.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/inferiors.c,v
retrieving revision 1.1
diff -u -p -r1.1 inferiors.c
--- inferiors.c	9 Apr 2002 21:17:45 -0000	1.1
+++ inferiors.c	16 Apr 2002 05:23:15 -0000
@@ -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: linux-i386-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-i386-low.c,v
retrieving revision 1.3
diff -u -p -r1.3 linux-i386-low.c
--- linux-i386-low.c	9 Apr 2002 22:44:43 -0000	1.3
+++ linux-i386-low.c	16 Apr 2002 05:23:15 -0000
@@ -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: linux-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.14
diff -u -p -r1.14 linux-low.c
--- linux-low.c	11 Apr 2002 20:30:06 -0000	1.14
+++ linux-low.c	16 Apr 2002 05:23:15 -0000
@@ -35,6 +35,10 @@
 #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, ch
     }
 
   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, ch
 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, ch
    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: linux-low.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.h,v
retrieving revision 1.4
diff -u -p -r1.4 linux-low.h
--- linux-low.h	11 Apr 2002 20:30:06 -0000	1.4
+++ linux-low.h	16 Apr 2002 05:23:15 -0000
@@ -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;
Index: server.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.10
diff -u -p -r1.10 server.c
--- server.c	9 Apr 2002 23:52:06 -0000	1.10
+++ server.c	16 Apr 2002 05:23:15 -0000
@@ -48,8 +48,6 @@ attach_inferior (int pid, char *statuspt
   if (myattach (pid) != 0)
     return -1;
 
-  add_inferior (pid);
-
   *sigptr = mywait (statusptr);
 
   return 0;
Index: server.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.h,v
retrieving revision 1.9
diff -u -p -r1.9 server.h
--- server.h	9 Apr 2002 23:52:06 -0000	1.9
+++ server.h	16 Apr 2002 05:23:15 -0000
@@ -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_inf
 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: target.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/target.c,v
retrieving revision 1.1
diff -u -p -r1.1 target.c
--- target.c	9 Apr 2002 21:17:45 -0000	1.1
+++ target.c	16 Apr 2002 05:23:15 -0000
@@ -26,6 +26,20 @@
 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: target.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/target.h,v
retrieving revision 1.2
diff -u -p -r1.2 target.h
--- target.h	9 Apr 2002 23:52:06 -0000	1.2
+++ target.h	16 Apr 2002 05:23:15 -0000
@@ -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 */


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