X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ftarget.c;h=cc3b747d4b8cc930fcfcbf2820a4640115fa80bb;hb=464e0365d26d6de5eaa70d14c69a3028ed222deb;hp=c763af375aecc9961b9e68ee6f39da74caffe7b5;hpb=8db32d44ca88f0560e8a81aec6889fd1f8c7d348;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/target.c b/gdb/target.c index c763af375a..cc3b747d4b 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -36,8 +36,8 @@ #include "dcache.h" #include #include "regcache.h" - -extern int errno; +#include "gdb_assert.h" +#include "gdbcore.h" static void target_info (char *, int); @@ -73,6 +73,12 @@ static void nosupport_runtime (void); static void normal_target_post_startup_inferior (ptid_t ptid); +static LONGEST default_xfer_partial (struct target_ops *ops, + enum target_object object, + const char *annex, void *readbuf, + const void *writebuf, + 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 @@ -213,6 +219,10 @@ target_command (char *arg, int from_tty) void add_target (struct target_ops *t) { + /* Provide default values for all "must have" methods. */ + if (t->to_xfer_partial == NULL) + t->to_xfer_partial = default_xfer_partial; + if (!target_structs) { target_struct_allocsize = DEFAULT_ALLOCSIZE; @@ -420,8 +430,7 @@ update_current_target (void) INHERIT (to_pid_to_str, t); INHERIT (to_extra_thread_info, t); INHERIT (to_stop, t); - /* Do not inherit to_read_partial. */ - /* Do not inherit to_write_partial. */ + /* Do not inherit to_xfer_partial. */ INHERIT (to_rcmd, t); INHERIT (to_enable_exception_callback, t); INHERIT (to_get_current_exception_event, t); @@ -447,8 +456,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) \ @@ -603,6 +612,7 @@ update_current_target (void) de_fault (to_stop, (void (*) (void)) target_ignore); + current_target.to_xfer_partial = default_xfer_partial; de_fault (to_rcmd, (void (*) (char *, struct ui_file *)) tcomplain); @@ -674,8 +684,7 @@ push_target (struct target_ops *t) struct target_ops *tmp = (*cur); (*cur) = (*cur)->beneath; tmp->beneath = NULL; - if (tmp->to_close) - (tmp->to_close) (0); + target_close (tmp, 0); } /* We have removed all targets in our stratum, now add the new one. */ @@ -700,9 +709,6 @@ unpush_target (struct target_ops *t) struct target_ops **cur; struct target_ops *tmp; - if (t->to_close) - t->to_close (0); /* Let it clean up */ - /* Look for the specified target. Note that we assume that a target can only occur once in the target stack. */ @@ -715,6 +721,14 @@ unpush_target (struct target_ops *t) if ((*cur) == NULL) return 0; /* Didn't find target_ops, quit now */ + /* NOTE: cagney/2003-12-06: In '94 the close call was made + unconditional by moving it to before the above check that the + target was in the target stack (something about "Change the way + pushing and popping of targets work to support target overlays + and inheritance"). This doesn't make much sense - only open + targets should be closed. */ + target_close (t, 0); + /* Unchain the target */ tmp = (*cur); (*cur) = (*cur)->beneath; @@ -728,7 +742,7 @@ unpush_target (struct target_ops *t) void pop_target (void) { - (current_target.to_close) (0); /* Let it clean up */ + target_close (¤t_target, 0); /* Let it clean up */ if (unpush_target (target_stack) == 1) return; @@ -1065,24 +1079,60 @@ target_write_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err) /* More generic transfers. */ +static LONGEST +default_xfer_partial (struct target_ops *ops, enum target_object object, + const char *annex, void *readbuf, + const void *writebuf, 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 = -1; + errno = 0; + if (writebuf != NULL) + { + void *buffer = xmalloc (len); + struct cleanup *cleanup = make_cleanup (xfree, buffer); + memcpy (buffer, writebuf, len); + xfered = ops->to_xfer_memory (offset, buffer, len, 1/*write*/, NULL, + ops); + do_cleanups (cleanup); + } + if (readbuf != NULL) + xfered = ops->to_xfer_memory (offset, readbuf, 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 ops->beneath->to_xfer_partial (ops->beneath, object, annex, + readbuf, writebuf, 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_xfer_partial != NULL); + return ops->to_xfer_partial (ops, object, annex, buf, NULL, offset, len); } LONGEST @@ -1091,17 +1141,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_xfer_partial != NULL); + return ops->to_xfer_partial (ops, object, annex, NULL, buf, offset, len); } /* Wrappers to perform the full transfer. */ @@ -1114,12 +1155,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; } @@ -1139,14 +1181,37 @@ 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; } return len; } +/* Memory transfer methods. */ + +void +get_target_memory (struct target_ops *ops, CORE_ADDR addr, void *buf, + LONGEST len) +{ + if (target_read (ops, TARGET_OBJECT_MEMORY, NULL, buf, addr, len) + != len) + memory_error (EIO, addr); +} + +ULONGEST +get_target_memory_unsigned (struct target_ops *ops, + CORE_ADDR addr, int len) +{ + char buf[sizeof (ULONGEST)]; + + gdb_assert (len <= sizeof (buf)); + get_target_memory (ops, addr, buf, len); + return extract_unsigned_integer (buf, len); +} + static void target_info (char *args, int from_tty) { @@ -1225,7 +1290,7 @@ target_disconnect (char *args, int from_tty) void target_link (char *modname, CORE_ADDR *t_reloc) { - if (STREQ (current_target.to_shortname, "rombug")) + if (DEPRECATED_STREQ (current_target.to_shortname, "rombug")) { (current_target.to_lookup_symbol) (modname, t_reloc); if (*t_reloc == 0) @@ -1585,6 +1650,7 @@ init_dummy_target (void) dummy_target.to_stratum = dummy_stratum; dummy_target.to_find_memory_regions = dummy_find_memory_regions; dummy_target.to_make_corefile_notes = dummy_make_corefile_notes; + dummy_target.to_xfer_partial = default_xfer_partial; dummy_target.to_magic = OPS_MAGIC; } @@ -1602,11 +1668,19 @@ debug_to_open (char *args, int from_tty) static void debug_to_close (int quitting) { - debug_target.to_close (quitting); - + target_close (&debug_target, quitting); fprintf_unfiltered (gdb_stdlog, "target_close (%d)\n", quitting); } +void +target_close (struct target_ops *targ, int quitting) +{ + if (targ->to_xclose != NULL) + targ->to_xclose (targ, quitting); + else if (targ->to_close != NULL) + targ->to_close (quitting); +} + static void debug_to_attach (char *args, int from_tty) { @@ -2220,40 +2294,19 @@ debug_to_stop (void) } static LONGEST -debug_to_read_partial (struct target_ops *ops, - enum target_object object, - const char *annex, void *buf, +debug_to_xfer_partial (struct target_ops *ops, enum target_object object, + const char *annex, void *readbuf, const void *writebuf, ULONGEST offset, LONGEST len) { LONGEST retval; - retval = target_read_partial (&debug_target, object, annex, buf, offset, - len); - - fprintf_unfiltered (gdb_stdlog, - "target_read_partial (%d, %s, 0x%lx, 0x%s, %s) = %s\n", - (int) object, (annex ? annex : "(null)"), - (long) buf, paddr_nz (offset), - paddr_d (len), paddr_d (retval)); - - return retval; -} - -static LONGEST -debug_to_write_partial (struct target_ops *ops, - enum target_object object, - const char *annex, const void *buf, - ULONGEST offset, LONGEST len) -{ - LONGEST retval; - - retval = target_write_partial (&debug_target, object, annex, buf, offset, - len); + retval = debug_target.to_xfer_partial (&debug_target, object, annex, + readbuf, writebuf, offset, len); fprintf_unfiltered (gdb_stdlog, - "target_write_partial (%d, %s, 0x%lx, 0x%s, %s) = %s\n", + "target_xfer_partial (%d, %s, 0x%lx, 0x%lx, 0x%s, %s) = %s\n", (int) object, (annex ? annex : "(null)"), - (long) buf, paddr_nz (offset), + (long) readbuf, (long) writebuf, paddr_nz (offset), paddr_d (len), paddr_d (retval)); return retval; @@ -2356,8 +2409,7 @@ setup_target_debug (void) current_target.to_thread_alive = debug_to_thread_alive; current_target.to_find_new_threads = debug_to_find_new_threads; current_target.to_stop = debug_to_stop; - current_target.to_read_partial = debug_to_read_partial; - current_target.to_write_partial = debug_to_write_partial; + current_target.to_xfer_partial = debug_to_xfer_partial; current_target.to_rcmd = debug_to_rcmd; current_target.to_enable_exception_callback = debug_to_enable_exception_callback; current_target.to_get_current_exception_event = debug_to_get_current_exception_event;