From 0088c768bba3ae61ff9288b0edce4a5cdd8c2227 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Thu, 23 Oct 2003 00:13:53 +0000 Subject: [PATCH] 2003-10-22 Andrew Cagney * 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 | 14 +++++ gdb/Makefile.in | 2 +- gdb/target.c | 135 ++++++++++++++++++++++++++++++++++++------------ gdb/target.h | 8 +-- 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,3 +1,17 @@ +2003-10-22 Andrew Cagney + + * 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 * gdbarch.sh (convert_from_func_ptr_addr): Convert to a pure 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 #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, ... */ }; -- 2.30.2