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/rfc] Add backward compat to target read/write partial


Hello,

The attached patch adds backward compatibility to the recently added read/write partial target vector methods. If a given target vector has to_xfer_memory but not to_read/write_partial, the to_xfer_memory method is used.

It was implemented by adding default read/write partial methods to each target vector.

For testing, I tweaked the existing read/write memory thus:
+#if 0
return target_xfer_memory (memaddr, myaddr, len, 0);
+#else
+ return (target_read (&current_target, TARGET_OBJECT_MEMORY,
+ NULL, myaddr, memaddr, len)
+ <= 0);
+#endif
(included in the patch for reference, must remember to delete it ...). It turned up one bug.


Comments?

Having taken the change to this point, I'm now wondering if the read/write partial methods should be merged into:
to_xfer_partial (targ, object, annex,
offset, len,
readbuf, writebuf)
as that would make migrating existing targets easier.


Thoughts?

Andrew
2003-10-21  Andrew Cagney  <cagney@redhat.com>

	* target.c: Include "gdb_assert.h" (target_read): Call
	"target_read_partial", not "target_write_partial".
	(default_read_partial, default_write_partial): New function.
	(target_read_partial, target_write_partial): Simplify, assume that
	there is always a read/write method.
	(update_current_target, add_target): Always set "to_read_partial"
	and "to_write_partial".
	* Makefile.in (target.o): Update dependencies.
	* target.h: Update copyright date.
	(target_object): Fix typo.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.458
diff -u -r1.458 Makefile.in
--- Makefile.in	18 Oct 2003 18:41:22 -0000	1.458
+++ Makefile.in	21 Oct 2003 17:33:55 -0000
@@ -2365,7 +2365,7 @@
 	$(block_h) $(dictionary_h) $(gdb_string_h) $(gdb_stat_h) $(cp_abi_h)
 target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
 	$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
-	$(gdb_wait_h) $(dcache_h) $(regcache_h)
+	$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h)
 thread.o: thread.c $(defs_h) $(symtab_h) $(frame_h) $(inferior_h) \
 	$(environ_h) $(value_h) $(target_h) $(gdbthread_h) $(command_h) \
 	$(gdbcmd_h) $(regcache_h) $(gdb_h) $(gdb_string_h) $(ui_out_h)
Index: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.59
diff -u -r1.59 target.c
--- target.c	17 Oct 2003 20:17:51 -0000	1.59
+++ target.c	21 Oct 2003 17:33:56 -0000
@@ -36,6 +36,7 @@
 #include "dcache.h"
 #include <signal.h>
 #include "regcache.h"
+#include "gdb_assert.h"
 
 extern int errno;
 
@@ -73,6 +74,15 @@
 
 static void normal_target_post_startup_inferior (ptid_t ptid);
 
+static LONGEST default_read_partial (struct target_ops *ops,
+				     enum target_object object,
+				     const char *annex, void *buf,
+				     ULONGEST offset, LONGEST len);
+static LONGEST default_write_partial (struct target_ops *ops,
+				      enum target_object object,
+				      const char *annex, const void *buf,
+				      ULONGEST offset, LONGEST len);
+
 /* Transfer LEN bytes between target address MEMADDR and GDB address
    MYADDR.  Returns 0 for success, errno code for failure (which
    includes partial transfers -- if you want a more useful response to
@@ -213,6 +223,10 @@
 void
 add_target (struct target_ops *t)
 {
+  /* Provide default values for all "must have" methods.  */
+  t->to_read_partial = default_read_partial;
+  t->to_write_partial = default_write_partial;
+
   if (!target_structs)
     {
       target_struct_allocsize = DEFAULT_ALLOCSIZE;
@@ -447,8 +461,8 @@
 #undef INHERIT
 
   /* Clean up a target struct so it no longer has any zero pointers in
-     it.  We default entries, at least to stubs that print error
-     messages.  */
+     it.  Some entries are defaulted to a method that print an error,
+     others are hard-wired to a standard recursive default.  */
 
 #define de_fault(field, value) \
   if (!current_target.field)               \
@@ -603,6 +617,8 @@
   de_fault (to_stop, 
 	    (void (*) (void)) 
 	    target_ignore);
+  current_target.to_read_partial = default_read_partial;
+  current_target.to_write_partial = default_write_partial;
   de_fault (to_rcmd, 
 	    (void (*) (char *, struct ui_file *)) 
 	    tcomplain);
@@ -842,13 +858,25 @@
 int
 target_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
 {
+#if 0
   return target_xfer_memory (memaddr, myaddr, len, 0);
+#else
+  return (target_read (&current_target, TARGET_OBJECT_MEMORY,
+		       NULL, myaddr, memaddr, len)
+	  <= 0);
+#endif
 }
 
 int
 target_write_memory (CORE_ADDR memaddr, char *myaddr, int len)
 {
+#if 0
   return target_xfer_memory (memaddr, myaddr, len, 1);
+#else
+  return (target_write (&current_target, TARGET_OBJECT_MEMORY,
+			NULL, myaddr, memaddr, len)
+	  <= 0);
+#endif
 }
 
 static int trust_readonly = 0;
@@ -1065,24 +1093,86 @@
 
 /* More generic transfers.  */
 
+static LONGEST
+default_read_partial (struct target_ops *ops,
+		      enum target_object object,
+		      const char *annex, void *buf,
+		      ULONGEST offset, LONGEST len)
+{
+  if (object == TARGET_OBJECT_MEMORY
+      && ops->to_xfer_memory != NULL)
+    /* If available, fall back to the target's "to_xfer_memory"
+       method.  */
+    {
+      int xfered;
+      errno = 0;
+      xfered = ops->to_xfer_memory (offset, buf, len, 0/*read*/, NULL, ops);
+      if (xfered > 0)
+	return xfered;
+      else if (xfered == 0 && errno == 0)
+	/* "to_xfer_memory" uses 0, cross checked against ERRNO as one
+           indication of an error.  */
+	return 0;
+      else
+	return -1;
+    }
+  else if (ops->beneath != NULL)
+    return target_read_partial (ops->beneath, object, annex, buf, offset, len);
+  else
+    return -1;
+}
+
+static LONGEST
+default_write_partial (struct target_ops *ops,
+		       enum target_object object,
+		       const char *annex, const void *buf,
+		       ULONGEST offset, LONGEST len)
+{
+  if (object == TARGET_OBJECT_MEMORY
+      && ops->to_xfer_memory != NULL)
+    /* If available, fall back to the target's "to_xfer_memory"
+       method.  */
+    {
+      int xfered;
+      errno = 0;
+      {
+	void *buffer = xmalloc (len);
+	struct cleanup *cleanup = make_cleanup (xfree, buffer);
+	memcpy (buffer, buf, len);
+	xfered = ops->to_xfer_memory (offset, buffer, len, 1/*write*/, NULL,
+				      ops);
+	do_cleanups (cleanup);
+      }
+      if (xfered > 0)
+	return xfered;
+      else if (xfered == 0 && errno == 0)
+	/* "to_xfer_memory" uses 0, cross checked against ERRNO as one
+           indication of an error.  */
+	return 0;
+      else
+	return -1;
+    }
+  else if (ops->beneath != NULL)
+    return target_write_partial (ops->beneath, object, annex, buf, offset,
+				 len);
+  else
+    return -1;
+}
+
+/* Target vector read/write partial wrapper functions.
+
+   NOTE: cagney/2003-10-21: I wonder if having "to_xfer_partial
+   (inbuf, outbuf)", instead of separate read/write methods, make life
+   easier.  */
+
 LONGEST
 target_read_partial (struct target_ops *ops,
 		     enum target_object object,
 		     const char *annex, void *buf,
 		     ULONGEST offset, LONGEST len)
 {
-  struct target_ops *op;
-
-  /* Find the first target stratum that can handle the request.  */
-  for (op = ops;
-       op != NULL && op->to_read_partial == NULL;
-       op = op->beneath)
-    ;
-  if (op == NULL)
-    return -1;
-  
-  /* Now apply the operation at that level.  */
-  return op->to_read_partial (op, object, annex, buf, offset, len);
+  gdb_assert (ops->to_read_partial != NULL);
+  return ops->to_read_partial (ops, object, annex, buf, offset, len);
 }
 
 LONGEST
@@ -1091,17 +1181,8 @@
 		      const char *annex, const void *buf,
 		      ULONGEST offset, LONGEST len)
 {
-  struct target_ops *op;
-
-  /* Find the first target stratum that can handle the request.  */
-  for (op = ops;
-       op != NULL && op->to_write_partial == NULL;
-       op = op->beneath)
-    ;
-  if (op == NULL)
-    return -1;
-  
-  return op->to_write_partial (op, object, annex, buf, offset, len);
+  gdb_assert (ops->to_write_partial != NULL);
+  return ops->to_write_partial (ops, object, annex, buf, offset, len);
 }
 
 /* Wrappers to perform the full transfer.  */
@@ -1114,9 +1195,9 @@
   LONGEST xfered = 0;
   while (xfered < len)
     {
-      LONGEST xfer = target_write_partial (ops, object, annex,
-					   (bfd_byte *) buf + xfered,
-					   offset + xfered, len - xfered);
+      LONGEST xfer = target_read_partial (ops, object, annex,
+					  (bfd_byte *) buf + xfered,
+					  offset + xfered, len - xfered);
       /* Call an observer, notifying them of the xfer progress?  */
       if (xfer < 0)
 	return xfer;
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.45
diff -u -r1.45 target.h
--- target.h	17 Oct 2003 20:17:51 -0000	1.45
+++ target.h	21 Oct 2003 17:33:56 -0000
@@ -1,6 +1,8 @@
 /* Interface between GDB and target environments, including files and processes
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002 Free Software Foundation, Inc.
+
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
    Contributed by Cygnus Support.  Written by John Gilmore.
 
    This file is part of GDB.
@@ -221,7 +223,7 @@
   /* AVR target specific transfer.  See "avr-tdep.c" and "remote.c".  */
   TARGET_OBJECT_AVR,
   /* Transfer up-to LEN bytes of memory starting at OFFSET.  */
-  TARGET_OBJECT_MEORY
+  TARGET_OBJECT_MEMORY
   /* Possible future ojbects: TARGET_OJBECT_FILE, TARGET_OBJECT_PROC,
      TARGET_OBJECT_AUXV, ...  */
 };

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