This is the mail archive of the gdb-patches@sourceware.cygnus.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]

target_{read,write}_memory_partial


FYI,

The attatched patch re-does the target_{read,write}_memory_partial
functions so that they (IMO) do something useful.

The old target_read_memory_partial gives the impression that it was a
clever customization for valprint.c:val_print_string.  The replacement
doesn't try to be clever.  It lets the caller know exactly what
happened.

	enjoy,
		Andrew
Sun Oct 17 15:12:33 1999  Andrew Cagney  <cagney@b1.cygnus.com>

	* target.c (target_xfer_memory_partial): New function. Simple
 	implementation of partial memory reads.
	(target_read_memory_partial): New function.  Replaces old
 	target_read_memory_partial.
	(target_write_memory_partial): New function.
	* target.h: Update.

	* valprint.c (partial_memory_read): New function, based on old
 	memory_read_partial.  Implement partial memory reads the way that
 	val_print_string likes.
	(val_print_string): Use partial_memory_read.

Index: target.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/target.c,v
retrieving revision 1.110
diff -p -r1.110 target.c
*** target.c	1999/10/01 22:56:40	1.110
--- target.c	1999/10/17 05:48:36
*************** static void nosupport_runtime PARAMS ((v
*** 87,96 ****
  
  static void normal_target_post_startup_inferior PARAMS ((int pid));
  
! /* 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 partial transfers, try
!    target_read_memory_partial).  */
  
  static int
  target_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
--- 87,97 ----
  
  static void normal_target_post_startup_inferior PARAMS ((int pid));
  
! /* 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
!    partial transfers, try either target_read_memory_partial or
!    target_write_memory_partial).  */
  
  static int
  target_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
*************** target_read_memory_section (memaddr, mya
*** 787,834 ****
    return target_xfer_memory (memaddr, myaddr, len, 0, bfd_section);
  }
  
- /* Read LEN bytes of target memory at address MEMADDR, placing the results
-    in GDB's memory at MYADDR.  Returns a count of the bytes actually read,
-    and optionally an errno value in the location pointed to by ERRNOPTR
-    if ERRNOPTR is non-null. */
- 
- int
- target_read_memory_partial (memaddr, myaddr, len, errnoptr)
-      CORE_ADDR memaddr;
-      char *myaddr;
-      int len;
-      int *errnoptr;
- {
-   int nread;			/* Number of bytes actually read. */
-   int errcode;			/* Error from last read. */
- 
-   /* First try a complete read. */
-   errcode = target_xfer_memory (memaddr, myaddr, len, 0, NULL);
-   if (errcode == 0)
-     {
-       /* Got it all. */
-       nread = len;
-     }
-   else
-     {
-       /* Loop, reading one byte at a time until we get as much as we can. */
-       for (errcode = 0, nread = 0; len > 0 && errcode == 0; nread++, len--)
- 	{
- 	  errcode = target_xfer_memory (memaddr++, myaddr++, 1, 0, NULL);
- 	}
-       /* If an error, the last read was unsuccessful, so adjust count. */
-       if (errcode != 0)
- 	{
- 	  nread--;
- 	}
-     }
-   if (errnoptr != NULL)
-     {
-       *errnoptr = errcode;
-     }
-   return (nread);
- }
- 
  int
  target_write_memory (memaddr, myaddr, len)
       CORE_ADDR memaddr;
--- 788,793 ----
*************** target_xfer_memory (memaddr, myaddr, len
*** 922,927 ****
--- 881,955 ----
    return 0;			/* We managed to cover it all somehow. */
  }
  
+ 
+ /* Perform a partial memory transfer.  */
+ 
+ static int
+ target_xfer_memory_partial (CORE_ADDR memaddr, char *buf, int len,
+ 			    int write_p, int *err)
+ {
+   int res;
+   int err_res;
+   int len_res;
+   struct target_ops *t;
+   struct target_stack_item *item;
+ 
+   /* Zero length requests are ok and require no work.  */
+   if (len == 0)
+     {
+       *err = 0;
+       return 0;
+     }
+ 
+   /* The quick case is that the top target does it all.  */
+   res = current_target.to_xfer_memory (memaddr, buf, len, write_p, &current_target);
+   if (res > 0)
+     {
+       *err = 0;
+       return res;
+     }
+ 
+   /* xfer memory doesn't always reliably set errno. */
+   errno = 0;
+ 
+   /* Try all levels of the target stack to see one can handle it. */
+   for (item = target_stack; item; item = item->next)
+     {
+       t = item->target_ops;
+       if (!t->to_has_memory)
+ 	continue;
+       res = t->to_xfer_memory (memaddr, buf, len, write_p, t);
+       if (res > 0)
+ 	{
+ 	  /* Handled all or part of xfer */
+ 	  *err = 0;
+ 	  return res;
+ 	}
+       if (t->to_has_all_memory)
+ 	break;
+     }
+ 
+   /* Total failure.  Return error. */
+   if (errno != 0)
+     {
+       *err = errno;
+       return -1;
+     }
+   *err = EIO;
+   return -1;
+ }
+ 
+ int
+ target_read_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err)
+ {
+   return target_xfer_memory_partial (memaddr, buf, len, 0, err);
+ }
+ 
+ int
+ target_write_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err)
+ {
+   return target_xfer_memory_partial (memaddr, buf, len, 1, err);
+ }
  
  /* ARGSUSED */
  static void
Index: target.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/target.h,v
retrieving revision 1.87
diff -p -r1.87 target.h
*** target.h	1999/10/14 01:17:49	1.87
--- target.h	1999/10/17 05:48:38
*************** target_read_memory_section PARAMS ((CORE
*** 591,599 ****
  				    asection * bfd_section));
  
  extern int
- target_read_memory_partial PARAMS ((CORE_ADDR, char *, int, int *));
- 
- extern int
  target_write_memory PARAMS ((CORE_ADDR, char *, int));
  
  extern int
--- 591,596 ----
*************** xfer_memory PARAMS ((CORE_ADDR, char *, 
*** 601,606 ****
--- 598,613 ----
  
  extern int
  child_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+ 
+ /* Make a single attempt at transfering LEN bytes.  On a successful
+    transfer, the number of bytes actually transfered is returned and
+    ERR is set to 0.  When a transfer fails, -1 is returned (the number
+    of bytes actually transfered is not defined) and ERR is set to a
+    non-zero error indication. */
+ 
+ extern int target_read_memory_partial (CORE_ADDR addr, char *buf, int len, int *err);
+ 
+ extern int target_write_memory_partial (CORE_ADDR addr, char *buf, int len, int *err);
  
  extern char *
    child_pid_to_exec_file PARAMS ((int));
Index: valprint.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/valprint.c,v
retrieving revision 1.119
diff -p -r1.119 valprint.c
*** valprint.c	1999/09/03 08:15:41	1.119
--- valprint.c	1999/10/17 05:48:43
***************
*** 37,42 ****
--- 37,45 ----
  
  /* Prototypes for local functions */
  
+ static int partial_memory_read (CORE_ADDR memaddr, char *myaddr,
+ 				int len, int *errnoptr);
+ 
  static void print_hex_chars PARAMS ((GDB_FILE *, unsigned char *,
  				     unsigned int));
  
*************** val_print_array_elements (type, valaddr,
*** 1149,1154 ****
--- 1152,1198 ----
      }
  }
  
+ /* Read LEN bytes of target memory at address MEMADDR, placing the
+    results in GDB's memory at MYADDR.  Returns a count of the bytes
+    actually read, and optionally an errno value in the location
+    pointed to by ERRNOPTR if ERRNOPTR is non-null. */
+ 
+ /* FIXME: cagney/1999-10-14: Only used by val_print_string.  Can this
+    function be eliminated.  */
+ 
+ static int
+ partial_memory_read (CORE_ADDR memaddr, char *myaddr, int len, int *errnoptr)
+ {
+   int nread;			/* Number of bytes actually read. */
+   int errcode;			/* Error from last read. */
+ 
+   /* First try a complete read. */
+   errcode = target_read_memory (memaddr, myaddr, len);
+   if (errcode == 0)
+     {
+       /* Got it all. */
+       nread = len;
+     }
+   else
+     {
+       /* Loop, reading one byte at a time until we get as much as we can. */
+       for (errcode = 0, nread = 0; len > 0 && errcode == 0; nread++, len--)
+ 	{
+ 	  errcode = target_read_memory (memaddr++, myaddr++, 1);
+ 	}
+       /* If an error, the last read was unsuccessful, so adjust count. */
+       if (errcode != 0)
+ 	{
+ 	  nread--;
+ 	}
+     }
+   if (errnoptr != NULL)
+     {
+       *errnoptr = errcode;
+     }
+   return (nread);
+ }
+ 
  /*  Print a string from the inferior, starting at ADDR and printing up to LEN
     characters, of WIDTH bytes a piece, to STREAM.  If LEN is -1, printing
     stops at the first null byte, otherwise printing proceeds (including null
*************** val_print_string (addr, len, width, stre
*** 1208,1214 ****
        bufptr = buffer;
        old_chain = make_cleanup (free, buffer);
  
!       nfetch = target_read_memory_partial (addr, bufptr, len * width, &errcode)
  	/ width;
        addr += nfetch * width;
        bufptr += nfetch * width;
--- 1252,1258 ----
        bufptr = buffer;
        old_chain = make_cleanup (free, buffer);
  
!       nfetch = partial_memory_read (addr, bufptr, len * width, &errcode)
  	/ width;
        addr += nfetch * width;
        bufptr += nfetch * width;
*************** val_print_string (addr, len, width, stre
*** 1234,1240 ****
  	  bufsize += nfetch;
  
  	  /* Read as much as we can. */
! 	  nfetch = target_read_memory_partial (addr, bufptr, nfetch * width, &errcode)
  	    / width;
  
  	  /* Scan this chunk for the null byte that terminates the string
--- 1278,1284 ----
  	  bufsize += nfetch;
  
  	  /* Read as much as we can. */
! 	  nfetch = partial_memory_read (addr, bufptr, nfetch * width, &errcode)
  	    / width;
  
  	  /* Scan this chunk for the null byte that terminates the string


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