2003-10-22 Andrew Cagney <cagney@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Thu, 23 Oct 2003 00:13:53 +0000 (00:13 +0000)
committerAndrew Cagney <cagney@redhat.com>
Thu, 23 Oct 2003 00:13:53 +0000 (00:13 +0000)
* 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".
(target_write, target_read): Fail on a zero byte transfer.
* Makefile.in (target.o): Update dependencies.
* target.h: Update copyright date.
(target_object): Fix typo.

gdb/ChangeLog
gdb/Makefile.in
gdb/target.c
gdb/target.h

index 6f40b2bfb7b6b04e51bb44b1c4827bd9fb012a8b..c490be327f2f05cbf7f5d678f3b10918eb85b426 100644 (file)
@@ -1,3 +1,17 @@
+2003-10-22  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".
+       (target_write, target_read): Fail on a zero byte transfer.
+       * Makefile.in (target.o): Update dependencies.
+       * target.h: Update copyright date.
+       (target_object): Fix typo.
+
 2003-10-22  Andrew Cagney  <cagney@redhat.com>
 
        * gdbarch.sh (convert_from_func_ptr_addr): Convert to a pure
index 247d8d1664237540bd54c3e61817263acd245ca7..4628a7ffd836ac6cd23079e8c3aed1a7940c1dd1 100644 (file)
@@ -2365,7 +2365,7 @@ symtab.o: symtab.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \
        $(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 2677fb3f92c956df433838156113f3dc7664a10e..6a520b10ffc77f376e7bf6f3a3f603a42896c79e 100644 (file)
@@ -36,6 +36,7 @@
 #include "dcache.h"
 #include <signal.h>
 #include "regcache.h"
+#include "gdb_assert.h"
 
 static void target_info (char *, int);
 
@@ -71,6 +72,15 @@ static void nosupport_runtime (void);
 
 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
@@ -211,6 +221,10 @@ target_command (char *arg, int from_tty)
 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;
@@ -445,8 +459,8 @@ update_current_target (void)
 #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)               \
@@ -601,6 +615,8 @@ update_current_target (void)
   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);
@@ -1061,24 +1077,86 @@ target_write_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err)
 
 /* 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
@@ -1087,17 +1165,8 @@ target_write_partial (struct target_ops *ops,
                      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.  */
@@ -1110,12 +1179,13 @@ target_read (struct target_ops *ops,
   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;
+      if (xfer <= 0)
+       /* Call memory_error?  */
+       return -1;
       xfered += xfer;
       QUIT;
     }
@@ -1135,8 +1205,9 @@ target_write (struct target_ops *ops,
                                           (bfd_byte *) buf + xfered,
                                           offset + xfered, len - xfered);
       /* Call an observer, notifying them of the xfer progress?  */
-      if (xfer < 0)
-       return xfer;
+      if (xfer <= 0)
+       /* Call memory_error?  */
+       return -1;
       xfered += xfer;
       QUIT;
     }
index b11647a00a6faa4221158f7891abcad258fbfa27..b4557ff429c646d6754c019af9a51c7a49a0d967 100644 (file)
@@ -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 @@ enum target_object
   /* 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, ...  */
 };