summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog14
-rw-r--r--gdb/Makefile.in2
-rw-r--r--gdb/target.c135
-rw-r--r--gdb/target.h8
4 files changed, 123 insertions, 36 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6f40b2bfb7b..c490be327f2 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,19 @@
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
multi-arch method, add "targ" parameter.
(struct target_ops): Declare.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 247d8d16642..4628a7ffd83 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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)
diff --git a/gdb/target.c b/gdb/target.c
index 2677fb3f92c..6a520b10ffc 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -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;
}
diff --git a/gdb/target.h b/gdb/target.h
index b11647a00a6..b4557ff429c 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -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, ... */
};