[rfc] Allow xfer_partial to signal EOF out of band

Daniel Jacobowitz drow@false.org
Thu Jun 22 03:36:00 GMT 2006


This patch adds a mechanism for to_xfer_partial to signal that it's done.
I didn't implement the new mechanism for any other targets besides remote;
it could easily be done for e.g. procfs_read_auxv, but the turnaround time
is such that it's not a big deal either way.  For the remote protocol,
where there's an extra round trip to the remote link, I set *no_more if
the target tells me to.

This is strictly an optional flag.  If you don't set it, returning zero will
signal EOF exactly as before.

Any comments on this?  Otherwise, I'll commit it after qXfer:auxv:read. 
This is the patch which actually saves one packet whenever a remote object
is transferred.

-- 
Daniel Jacobowitz
CodeSourcery

2006-06-21  Daniel Jacobowitz  <dan@codesourcery.com>

	* target.h (target_read_partial): Update prototype.
	(struct target_ops): Add NO_MORE argument to to_xfer_partial.
	* target.c (default_xfer_partial, target_xfer_partial)
	(xfer_using_stratum, target_read_memory_partial)
	(target_write_memory_partial, target_read_partial)
	(target_write_partial): Update for new argument.
	(target_read): Use NO_MORE to stop looping.
	* remote.c (remote_read_qxfer): Add NO_MORE argument.  Set
	it for 'l' responses.
	(remote_xfer_partial): Update.

	* auxv.c, auxv.h, bfd-target.c, bsd-kvm.c, bsd-uthread.c,
	corelow.c, ia64-linux-nat.c, inf-ptrace.c, inf-ttrace.c,
	inftarg.c, kod.c, linux-nat.c, linux-thread-db.c, procfs.c,
	sol-thread.c, sparc-nat.c: Update to_xfer_partial implementations.

Index: src/gdb/auxv.c
===================================================================
--- src.orig/gdb/auxv.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/auxv.c	2006-06-21 18:12:01.000000000 -0400
@@ -48,7 +48,8 @@ procfs_xfer_auxv (struct target_ops *ops
 		  gdb_byte *readbuf,
 		  const gdb_byte *writebuf,
 		  ULONGEST offset,
-		  LONGEST len)
+		  LONGEST len,
+		  int *no_more)
 {
   char *pathname;
   int fd;
Index: src/gdb/auxv.h
===================================================================
--- src.orig/gdb/auxv.h	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/auxv.h	2006-06-21 18:12:27.000000000 -0400
@@ -63,7 +63,8 @@ extern LONGEST procfs_xfer_auxv (struct 
 				 gdb_byte *readbuf,
 				 const gdb_byte *writebuf,
 				 ULONGEST offset,
-				 LONGEST len);
+				 LONGEST len,
+				 int *no_more);
 
 
 #endif
Index: src/gdb/bfd-target.c
===================================================================
--- src.orig/gdb/bfd-target.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/bfd-target.c	2006-06-21 18:12:34.000000000 -0400
@@ -73,7 +73,7 @@ target_bfd_xfer_partial (struct target_o
 			 enum target_object object,
 			 const char *annex, gdb_byte *readbuf,
 			 const gdb_byte *writebuf,
-			 ULONGEST offset, LONGEST len)
+			 ULONGEST offset, LONGEST len, int *no_more)
 {
   switch (object)
     {
Index: src/gdb/bsd-kvm.c
===================================================================
--- src.orig/gdb/bsd-kvm.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/bsd-kvm.c	2006-06-21 18:12:49.000000000 -0400
@@ -125,7 +125,7 @@ static LONGEST
 bsd_kvm_xfer_partial (struct target_ops *ops, enum target_object object,
 		      const char *annex, gdb_byte *readbuf,
 		      const gdb_byte *writebuf,
-		      ULONGEST offset, LONGEST len)
+		      ULONGEST offset, LONGEST len, int *no_more)
 {
   switch (object)
     {
Index: src/gdb/bsd-uthread.c
===================================================================
--- src.orig/gdb/bsd-uthread.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/bsd-uthread.c	2006-06-21 18:13:10.000000000 -0400
@@ -322,11 +322,11 @@ static LONGEST
 bsd_uthread_xfer_partial (struct target_ops *ops, enum target_object object,
 			  const char *annex, gdb_byte *readbuf,
 			  const gdb_byte *writebuf,
-			  ULONGEST offset, LONGEST len)
+			  ULONGEST offset, LONGEST len, int *no_more)
 {
   gdb_assert (ops->beneath->to_xfer_partial);
   return ops->beneath->to_xfer_partial (ops->beneath, object, annex, readbuf,
-					writebuf, offset, len);
+					writebuf, offset, len, no_more);
 }
 
 static ptid_t
Index: src/gdb/corelow.c
===================================================================
--- src.orig/gdb/corelow.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/corelow.c	2006-06-21 18:33:42.000000000 -0400
@@ -511,7 +511,8 @@ core_files_info (struct target_ops *t)
 static LONGEST
 core_xfer_partial (struct target_ops *ops, enum target_object object,
 		   const char *annex, gdb_byte *readbuf,
-		   const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+		   const gdb_byte *writebuf, ULONGEST offset, LONGEST len,
+		   int *no_more)
 {
   switch (object)
     {
@@ -591,7 +592,8 @@ core_xfer_partial (struct target_ops *op
     default:
       if (ops->beneath != NULL)
 	return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
-					      readbuf, writebuf, offset, len);
+					      readbuf, writebuf, offset, len,
+					      no_more);
       return -1;
     }
 }
Index: src/gdb/ia64-linux-nat.c
===================================================================
--- src.orig/gdb/ia64-linux-nat.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/ia64-linux-nat.c	2006-06-21 18:13:43.000000000 -0400
@@ -669,14 +669,14 @@ ia64_linux_stopped_by_watchpoint (void)
 
 static LONGEST (*super_xfer_partial) (struct target_ops *, enum target_object,
 				      const char *, gdb_byte *, const gdb_byte *,
-				      ULONGEST, LONGEST);
+				      ULONGEST, LONGEST, int *);
 
 static LONGEST 
 ia64_linux_xfer_partial (struct target_ops *ops,
 			 enum target_object object,
 			 const char *annex,
 			 gdb_byte *readbuf, const gdb_byte *writebuf,
-			 ULONGEST offset, LONGEST len)
+			 ULONGEST offset, LONGEST len, int *no_more)
 {
   if (object == TARGET_OBJECT_UNWIND_TABLE && writebuf == NULL && offset == 0)
     return syscall (__NR_getunwind, readbuf, len);
Index: src/gdb/inf-ptrace.c
===================================================================
--- src.orig/gdb/inf-ptrace.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/inf-ptrace.c	2006-06-21 18:15:08.000000000 -0400
@@ -436,7 +436,7 @@ static LONGEST
 inf_ptrace_xfer_partial (struct target_ops *ops, enum target_object object,
 			 const char *annex, gdb_byte *readbuf,
 			 const gdb_byte *writebuf,
-			 ULONGEST offset, LONGEST len)
+			 ULONGEST offset, LONGEST len, int *no_more)
 {
   pid_t pid = ptid_get_pid (inferior_ptid);
 
Index: src/gdb/inf-ttrace.c
===================================================================
--- src.orig/gdb/inf-ttrace.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/inf-ttrace.c	2006-06-21 18:15:25.000000000 -0400
@@ -1052,7 +1052,8 @@ inf_ttrace_xfer_memory (CORE_ADDR addr, 
 static LONGEST
 inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
 			 const char *annex, gdb_byte *readbuf,
-			 const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+			 const gdb_byte *writebuf, ULONGEST offset,
+			 LONGEST len, int *no_more)
 {
   switch (object)
     {
Index: src/gdb/inftarg.c
===================================================================
--- src.orig/gdb/inftarg.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/inftarg.c	2006-06-21 18:15:33.000000000 -0400
@@ -521,7 +521,8 @@ child_core_file_to_sym_file (char *core)
 static LONGEST
 child_xfer_partial (struct target_ops *ops, enum target_object object,
 		    const char *annex, gdb_byte *readbuf,
-		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len,
+		    int *no_more)
 {
   switch (object)
     {
Index: src/gdb/kod.c
===================================================================
--- src.orig/gdb/kod.c	2006-06-21 18:29:06.000000000 -0400
+++ src/gdb/kod.c	2006-06-21 18:34:39.000000000 -0400
@@ -88,11 +88,12 @@ static void
 gdb_kod_query (char *arg, char *result, int *maxsiz)
 {
   LONGEST bufsiz = 0;
+  int no_more = 0;
 
   /* Check if current target has remote_query capabilities.  If not,
      it does not have kod either.  */
   bufsiz = target_read_partial (&current_target, TARGET_OBJECT_KOD,
-				NULL, NULL, 0, 0);
+				NULL, NULL, 0, 0, &no_more);
   if (bufsiz < 0)
     {
       strcpy (result,
@@ -121,7 +122,7 @@ gdb_kod_query (char *arg, char *result, 
 
   /* Send actual request.  */
   if (target_read_partial (&current_target, TARGET_OBJECT_KOD,
-			   arg, result, 0, bufsiz) < 0)
+			   arg, result, 0, bufsiz, &no_more) < 0)
     strcpy (result, "ERR: remote query failed");
 }
 
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/linux-nat.c	2006-06-21 18:16:38.000000000 -0400
@@ -97,7 +97,7 @@ static LONGEST (*super_xfer_partial) (st
 				      enum target_object,
 				      const char *, gdb_byte *, 
 				      const gdb_byte *,
-				      ULONGEST, LONGEST);
+				      ULONGEST, LONGEST, int *);
 
 static int debug_linux_nat;
 static void
@@ -2367,7 +2367,7 @@ static LONGEST
 linux_nat_xfer_partial (struct target_ops *ops, enum target_object object,
 			const char *annex, gdb_byte *readbuf,
 			const gdb_byte *writebuf,
-			ULONGEST offset, LONGEST len)
+			ULONGEST offset, LONGEST len, int *no_more)
 {
   struct cleanup *old_chain = save_inferior_ptid ();
   LONGEST xfer;
@@ -2376,7 +2376,7 @@ linux_nat_xfer_partial (struct target_op
     inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid));
 
   xfer = linux_ops->to_xfer_partial (ops, object, annex, readbuf, writebuf,
-				     offset, len);
+				     offset, len, no_more);
 
   do_cleanups (old_chain);
   return xfer;
@@ -2994,7 +2994,7 @@ static LONGEST
 linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
 			 const char *annex, gdb_byte *readbuf,
 			 const gdb_byte *writebuf,
-			 ULONGEST offset, LONGEST len)
+			 ULONGEST offset, LONGEST len, int *no_more)
 {
   LONGEST ret;
   int fd;
@@ -3115,21 +3115,22 @@ linux_proc_pending_signals (int pid, sig
 static LONGEST
 linux_xfer_partial (struct target_ops *ops, enum target_object object,
                     const char *annex, gdb_byte *readbuf,
-		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len,
+		    int *no_more)
 {
   LONGEST xfer;
 
   if (object == TARGET_OBJECT_AUXV)
     return procfs_xfer_auxv (ops, object, annex, readbuf, writebuf,
-			     offset, len);
+			     offset, len, no_more);
 
   xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
-				  offset, len);
+				  offset, len, no_more);
   if (xfer != 0)
     return xfer;
 
   return super_xfer_partial (ops, object, annex, readbuf, writebuf,
-			     offset, len);
+			     offset, len, no_more);
 }
 
 #ifndef FETCH_INFERIOR_REGISTERS
Index: src/gdb/linux-thread-db.c
===================================================================
--- src.orig/gdb/linux-thread-db.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/linux-thread-db.c	2006-06-21 18:17:01.000000000 -0400
@@ -968,7 +968,8 @@ thread_db_wait (ptid_t ptid, struct targ
 static LONGEST
 thread_db_xfer_partial (struct target_ops *ops, enum target_object object,
 			const char *annex, gdb_byte *readbuf,
-			const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+			const gdb_byte *writebuf, ULONGEST offset,
+			LONGEST len, int *no_more)
 {
   struct cleanup *old_chain = save_inferior_ptid ();
   LONGEST xfer;
@@ -984,7 +985,8 @@ thread_db_xfer_partial (struct target_op
     }
 
   xfer = target_beneath->to_xfer_partial (ops, object, annex,
-					  readbuf, writebuf, offset, len);
+					  readbuf, writebuf, offset, len,
+					  no_more);
 
   do_cleanups (old_chain);
   return xfer;
Index: src/gdb/procfs.c
===================================================================
--- src.orig/gdb/procfs.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/procfs.c	2006-06-21 18:17:26.000000000 -0400
@@ -134,7 +134,8 @@ static LONGEST procfs_xfer_partial (stru
 				    enum target_object object,
 				    const char *annex,
 				    void *readbuf, const void *writebuf,
-				    ULONGEST offset, LONGEST len);
+				    ULONGEST offset, LONGEST len,
+				    int *no_more);
 
 static int procfs_thread_alive (ptid_t);
 
@@ -4301,7 +4302,8 @@ wait_again:
 static LONGEST
 procfs_xfer_partial (struct target_ops *ops, enum target_object object,
 		     const char *annex, void *readbuf,
-		     const void *writebuf, ULONGEST offset, LONGEST len)
+		     const void *writebuf, ULONGEST offset, LONGEST len,
+		     int *no_more)
 {
   switch (object)
     {
@@ -4317,13 +4319,14 @@ procfs_xfer_partial (struct target_ops *
 #ifdef NEW_PROC_API
     case TARGET_OBJECT_AUXV:
       return procfs_xfer_auxv (ops, object, annex, readbuf, writebuf,
-			       offset, len);
+			       offset, len, no_more);
 #endif
 
     default:
       if (ops->beneath != NULL)
 	return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
-					      readbuf, writebuf, offset, len);
+					      readbuf, writebuf, offset, len,
+					      no_more);
       return -1;
     }
 }
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/remote.c	2006-06-21 18:18:49.000000000 -0400
@@ -5150,6 +5150,7 @@ static LONGEST
 remote_read_qxfer (struct target_ops *ops, const char *object_name,
 		   const char *annex,
 		   gdb_byte *readbuf, ULONGEST offset, LONGEST len,
+		   int *no_more,
 		   struct packet_config *packet)
 {
   struct remote_state *rs = get_remote_state ();
@@ -5173,10 +5174,10 @@ remote_read_qxfer (struct target_ops *op
   if (packet_len < 0 || packet_ok (rs->buf, packet) != PACKET_OK)
     return -1;
 
-  /* 'l' is an EOF marker, possibly including data.  Right now we don't
-     do anything with this, because the target_xfer_partial interface
-     doesn't have room for it.  */
-  if (rs->buf[0] != 'm' && rs->buf[0] != 'l')
+  /* 'l' is an EOF marker, possibly including a final block of data.  */
+  if (rs->buf[0] == 'l')
+    *no_more = 1;
+  else if (rs->buf[0] != 'm')
     error (_("Unknown remote qXfer reply: %s"), rs->buf);
 
   /* 'm' means there is (or at least might be) more data after this
@@ -5193,7 +5194,8 @@ remote_read_qxfer (struct target_ops *op
 static LONGEST
 remote_xfer_partial (struct target_ops *ops, enum target_object object,
 		     const char *annex, gdb_byte *readbuf,
-		     const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+		     const gdb_byte *writebuf, ULONGEST offset, LONGEST len,
+		     int *no_more)
 {
   struct remote_state *rs = get_remote_state ();
   int i;
@@ -5243,6 +5245,7 @@ remote_xfer_partial (struct target_ops *
     case TARGET_OBJECT_AUXV:
       gdb_assert (annex == NULL);
       return remote_read_qxfer (ops, "auxv", annex, readbuf, offset, len,
+				no_more,
 				&remote_protocol_packets[PACKET_qXfer_auxv]);
 
     default:
Index: src/gdb/sol-thread.c
===================================================================
--- src.orig/gdb/sol-thread.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/sol-thread.c	2006-06-21 18:19:11.000000000 -0400
@@ -698,9 +698,9 @@ sol_thread_xfer_memory (CORE_ADDR memadd
 
 static LONGEST
 sol_thread_xfer_partial (struct target_ops *ops, enum target_object object,
-			  const char *annex, gdb_byte *readbuf,
-			  const gdb_byte *writebuf,
-			 ULONGEST offset, LONGEST len)
+			 const char *annex, gdb_byte *readbuf,
+			 const gdb_byte *writebuf,
+			 ULONGEST offset, LONGEST len, int *no_more)
 {
   int retval;
   struct cleanup *old_chain;
@@ -719,10 +719,12 @@ sol_thread_xfer_partial (struct target_o
 
   if (target_has_execution)
     retval = procfs_ops.to_xfer_partial (ops, object, annex,
-					 readbuf, writebuf, offset, len);
+					 readbuf, writebuf, offset, len,
+					 no_more);
   else
     retval = orig_core_ops.to_xfer_partial (ops, object, annex,
-					    readbuf, writebuf, offset, len);
+					    readbuf, writebuf, offset, len,
+					    no_more);
 
   do_cleanups (old_chain);
 
Index: src/gdb/sparc-nat.c
===================================================================
--- src.orig/gdb/sparc-nat.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/sparc-nat.c	2006-06-21 18:19:34.000000000 -0400
@@ -308,19 +308,20 @@ sparc_xfer_wcookie (struct target_ops *o
 
 LONGEST (*inf_ptrace_xfer_partial) (struct target_ops *, enum target_object,
 				    const char *, gdb_byte *, const gdb_byte *,
-				    ULONGEST, LONGEST);
+				    ULONGEST, LONGEST, int *);
 
 static LONGEST
 sparc_xfer_partial (struct target_ops *ops, enum target_object object,
 		    const char *annex, gdb_byte *readbuf,
-		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len,
+		    int *no_more)
 {
   if (object == TARGET_OBJECT_WCOOKIE)
     return sparc_xfer_wcookie (ops, object, annex, readbuf, writebuf, 
-			       offset, len);
+			       offset, len, no_more);
 
   return inf_ptrace_xfer_partial (ops, object, annex, readbuf, writebuf,
-				  offset, len);
+				  offset, len, no_more);
 }
 
 /* Create a prototype generic SPARC target.  The client can override
Index: src/gdb/target.c
===================================================================
--- src.orig/gdb/target.c	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/target.c	2006-06-21 18:36:23.000000000 -0400
@@ -74,7 +74,8 @@ static LONGEST default_xfer_partial (str
 				     enum target_object object,
 				     const char *annex, gdb_byte *readbuf,
 				     const gdb_byte *writebuf,
-				     ULONGEST offset, LONGEST len);
+				     ULONGEST offset, LONGEST len,
+				     int *no_more);
 
 /* Transfer LEN bytes between target address MEMADDR and GDB address
    MYADDR.  Returns 0 for success, errno code for failure (which
@@ -851,13 +852,13 @@ static LONGEST
 target_xfer_partial (struct target_ops *ops,
 		     enum target_object object, const char *annex,
 		     void *readbuf, const void *writebuf,
-		     ULONGEST offset, LONGEST len)
+		     ULONGEST offset, LONGEST len, int *no_more)
 {
   LONGEST retval;
 
   gdb_assert (ops->to_xfer_partial != NULL);
   retval = ops->to_xfer_partial (ops, object, annex, readbuf, writebuf,
-				 offset, len);
+				 offset, len, no_more);
   if (targetdebug)
     {
       const unsigned char *myaddr = NULL;
@@ -932,6 +933,7 @@ xfer_using_stratum (enum target_object o
 {
   LONGEST xfered;
   struct target_ops *target;
+  int no_more = 0;
 
   /* Always successful.  */
   if (len == 0)
@@ -944,7 +946,8 @@ xfer_using_stratum (enum target_object o
   while (1)
     {
       xfered = target_xfer_partial (target, object, annex,
-				    readbuf, writebuf, offset, len);
+				    readbuf, writebuf, offset, len,
+				    &no_more);
       if (xfered > 0)
 	{
 	  /* The partial xfer succeeded, update the counts, check that
@@ -1241,10 +1244,10 @@ target_read_memory_partial (CORE_ADDR me
 {
   if (target_xfer_partial_p ())
     {
-      int retval;
+      int retval, no_more;
 
       retval = target_xfer_partial (target_stack, TARGET_OBJECT_MEMORY,
-				    NULL, buf, NULL, memaddr, len);
+				    NULL, buf, NULL, memaddr, len, &no_more);
 
       if (retval <= 0)
 	{
@@ -1270,10 +1273,10 @@ target_write_memory_partial (CORE_ADDR m
 {
   if (target_xfer_partial_p ())
     {
-      int retval;
+      int retval, no_more;
 
       retval = target_xfer_partial (target_stack, TARGET_OBJECT_MEMORY,
-				    NULL, NULL, buf, memaddr, len);
+				    NULL, NULL, buf, memaddr, len, &no_more);
 
       if (retval <= 0)
 	{
@@ -1298,7 +1301,8 @@ target_write_memory_partial (CORE_ADDR m
 static LONGEST
 default_xfer_partial (struct target_ops *ops, enum target_object object,
 		      const char *annex, gdb_byte *readbuf, 
-		      const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+		      const gdb_byte *writebuf, ULONGEST offset, LONGEST len,
+		      int *no_more)
 {
   if (object == TARGET_OBJECT_MEMORY
       && ops->deprecated_xfer_memory != NULL)
@@ -1330,7 +1334,7 @@ default_xfer_partial (struct target_ops 
     }
   else if (ops->beneath != NULL)
     return target_xfer_partial (ops->beneath, object, annex,
-				readbuf, writebuf, offset, len);
+				readbuf, writebuf, offset, len, no_more);
   else
     return -1;
 }
@@ -1345,9 +1349,10 @@ LONGEST
 target_read_partial (struct target_ops *ops,
 		     enum target_object object,
 		     const char *annex, gdb_byte *buf,
-		     ULONGEST offset, LONGEST len)
+		     ULONGEST offset, LONGEST len, int *no_more)
 {
-  return target_xfer_partial (ops, object, annex, buf, NULL, offset, len);
+  return target_xfer_partial (ops, object, annex, buf, NULL, offset, len,
+			      no_more);
 }
 
 LONGEST
@@ -1356,7 +1361,12 @@ target_write_partial (struct target_ops 
 		      const char *annex, const gdb_byte *buf,
 		      ULONGEST offset, LONGEST len)
 {
-  return target_xfer_partial (ops, object, annex, NULL, buf, offset, len);
+  /* NO_MORE is only useful for reads, so it does not need to be part of
+     this function's interface.  */
+  int no_more;
+
+  return target_xfer_partial (ops, object, annex, NULL, buf, offset, len,
+			      &no_more);
 }
 
 /* Wrappers to perform the full transfer.  */
@@ -1367,11 +1377,14 @@ target_read (struct target_ops *ops,
 	     ULONGEST offset, LONGEST len)
 {
   LONGEST xfered = 0;
-  while (xfered < len)
+  int no_more = 0;
+
+  while (!no_more && xfered < len)
     {
       LONGEST xfer = target_read_partial (ops, object, annex,
 					  (gdb_byte *) buf + xfered,
-					  offset + xfered, len - xfered);
+					  offset + xfered, len - xfered,
+					  &no_more);
       /* Call an observer, notifying them of the xfer progress?  */
       if (xfer == 0)
 	return xfered;
@@ -1380,7 +1393,7 @@ target_read (struct target_ops *ops,
       xfered += xfer;
       QUIT;
     }
-  return len;
+  return xfered;
 }
 
 LONGEST
Index: src/gdb/target.h
===================================================================
--- src.orig/gdb/target.h	2006-06-21 18:10:59.000000000 -0400
+++ src/gdb/target.h	2006-06-21 18:30:10.000000000 -0400
@@ -187,7 +187,8 @@ enum target_signal target_signal_from_na
 
    Return the number of bytes actually transfered, zero when no
    further transfer is possible, and -1 when the transfer is not
-   supported.
+   supported.  A successful transfer may also set *NO_MORE to 1,
+   if the target knows that no more data is available.
 
    NOTE: cagney/2003-10-17: The current interface does not support a
    "retry" mechanism.  Instead it assumes that at least one byte will
@@ -239,7 +240,8 @@ enum target_object
 extern LONGEST target_read_partial (struct target_ops *ops,
 				    enum target_object object,
 				    const char *annex, gdb_byte *buf,
-				    ULONGEST offset, LONGEST len);
+				    ULONGEST offset, LONGEST len,
+				    int *no_more);
 
 extern LONGEST target_write_partial (struct target_ops *ops,
 				     enum target_object object,
@@ -441,7 +443,7 @@ struct target_ops
     LONGEST (*to_xfer_partial) (struct target_ops *ops,
 				enum target_object object, const char *annex,
 				gdb_byte *readbuf, const gdb_byte *writebuf,
-				ULONGEST offset, LONGEST len);
+				ULONGEST offset, LONGEST len, int *no_more);
 
     int to_magic;
     /* Need sub-structure for target machine related rather than comm related?



More information about the Gdb-patches mailing list