This is the mail archive of the
gdb-patches@sourceware.cygnus.com
mailing list for the GDB project.
target_{read,write}_memory_partial
- To: gdb-patches at sourceware dot cygnus dot com
- Subject: target_{read,write}_memory_partial
- From: Andrew Cagney <ac131313 at cygnus dot com>
- Date: Sun, 17 Oct 1999 15:57:51 +1000
- DJ-Gateway: from newsgroup cygnus.patches.gdb
- Newsgroups: cygnus.patches.gdb
- Organization: Cygnus Solutions
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, ¤t_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