static void tcomplain (void) ATTRIBUTE_NORETURN;
-static int nomemory (CORE_ADDR, char *, int, int, struct target_ops *);
-
static int return_zero (struct target_ops *);
static int return_zero_has_execution (struct target_ops *, ptid_t);
static struct target_ops *find_default_run_target (char *);
-static target_xfer_partial_ftype default_xfer_partial;
-
static struct gdbarch *default_thread_architecture (struct target_ops *ops,
ptid_t ptid);
static char *default_pid_to_str (struct target_ops *ops, ptid_t ptid);
-static int find_default_can_async_p (struct target_ops *ignore);
-
-static int find_default_is_async_p (struct target_ops *ignore);
-
static enum exec_direction_kind default_execution_direction
(struct target_ops *self);
complete_target_initialization (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 (t->to_has_all_memory == NULL)
t->to_has_all_memory = return_zero;
if (t->to_has_execution == NULL)
t->to_has_execution = return_zero_has_execution;
+ /* These methods can be called on an unpushed target and so require
+ a default implementation if the target might plausibly be the
+ default run target. */
+ gdb_assert (t->to_can_run == NULL || (t->to_can_async_p != NULL
+ && t->to_supports_non_stop != NULL));
+
install_delegators (t);
}
(*current_target.to_load) (¤t_target, arg, from_tty);
}
-void
-target_create_inferior (char *exec_file, char *args,
- char **env, int from_tty)
-{
- struct target_ops *t;
-
- for (t = current_target.beneath; t != NULL; t = t->beneath)
- {
- if (t->to_create_inferior != NULL)
- {
- t->to_create_inferior (t, exec_file, args, env, from_tty);
- if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_create_inferior (%s, %s, xxx, %d)\n",
- exec_file, args, from_tty);
- return;
- }
- }
-
- internal_error (__FILE__, __LINE__,
- _("could not find a target to create inferior"));
-}
-
void
target_terminal_inferior (void)
{
(*current_target.to_terminal_inferior) (¤t_target);
}
-static int
-nomemory (CORE_ADDR memaddr, char *myaddr, int len, int write,
- struct target_ops *t)
-{
- errno = EIO; /* Can't read/write this location. */
- return 0; /* No bytes handled. */
-}
-
static void
tcomplain (void)
{
INHERIT (to_shortname, t);
INHERIT (to_longname, t);
INHERIT (to_attach_no_wait, t);
- INHERIT (deprecated_xfer_memory, t);
INHERIT (to_have_steppable_watchpoint, t);
INHERIT (to_have_continuable_watchpoint, t);
INHERIT (to_has_thread_control, t);
}
#undef INHERIT
- /* Clean up a target struct so it no longer has any zero pointers in
- it. Do not add any new de_faults here. Instead, use the
- delegation mechanism provided by make-target-delegates. */
-
-#define de_fault(field, value) \
- if (!current_target.field) \
- current_target.field = value
-
- de_fault (deprecated_xfer_memory,
- (int (*) (CORE_ADDR, gdb_byte *, int, int,
- struct mem_attrib *, struct target_ops *))
- nomemory);
-
-#undef de_fault
-
/* Finally, position the target-stack beneath the squashed
"current_target". That way code looking for a non-inherited
target method can quickly and simply find it. */
}
while (ops != NULL);
+ /* The cache works at the raw memory level. Make sure the cache
+ gets updated with raw contents no matter what kind of memory
+ object was originally being written. Note we do write-through
+ first, so that if it fails, we don't write to the cache contents
+ that never made it to the target. */
+ if (writebuf != NULL
+ && !ptid_equal (inferior_ptid, null_ptid)
+ && target_dcache_init_p ()
+ && (stack_cache_enabled_p () || code_cache_enabled_p ()))
+ {
+ DCACHE *dcache = target_dcache_get ();
+
+ /* Note that writing to an area of memory which wasn't present
+ in the cache doesn't cause it to be loaded in. */
+ dcache_update (dcache, res, memaddr, writebuf, *xfered_len);
+ }
+
return res;
}
inf = NULL;
if (inf != NULL
+ && readbuf != NULL
/* The dcache reads whole cache lines; that doesn't play well
with reading from a trace buffer, because reading outside of
the collected memory range fails. */
|| (code_cache_enabled_p () && object == TARGET_OBJECT_CODE_MEMORY)))
{
DCACHE *dcache = target_dcache_get_or_init ();
- int l;
- if (readbuf != NULL)
- l = dcache_xfer_memory (ops, dcache, memaddr, readbuf, reg_len, 0);
- else
- /* FIXME drow/2006-08-09: If we're going to preserve const
- correctness dcache_xfer_memory should take readbuf and
- writebuf. */
- l = dcache_xfer_memory (ops, dcache, memaddr, (void *) writebuf,
- reg_len, 1);
- if (l <= 0)
- return TARGET_XFER_E_IO;
- else
- {
- *xfered_len = (ULONGEST) l;
- return TARGET_XFER_OK;
- }
+ return dcache_read_memory_partial (ops, dcache, memaddr, readbuf,
+ reg_len, xfered_len);
}
/* If none of those methods found the memory we wanted, fall back
res = raw_memory_xfer_partial (ops, readbuf, writebuf, memaddr, reg_len,
xfered_len);
- /* Make sure the cache gets updated no matter what - if we are writing
- to the stack. Even if this write is not tagged as such, we still need
- to update the cache. */
-
- if (res == TARGET_XFER_OK
- && inf != NULL
- && writebuf != NULL
- && target_dcache_init_p ()
- && !region->attrib.cache
- && ((stack_cache_enabled_p () && object != TARGET_OBJECT_STACK_MEMORY)
- || (code_cache_enabled_p () && object != TARGET_OBJECT_CODE_MEMORY)))
- {
- DCACHE *dcache = target_dcache_get ();
-
- dcache_update (dcache, memaddr, (void *) writebuf, reg_len);
- }
-
/* If we still haven't got anything, return the last error. We
give up. */
return res;
value);
}
-/* More generic transfers. */
-
-static enum target_xfer_status
-default_xfer_partial (struct target_ops *ops, enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
- ULONGEST *xfered_len)
-{
- if (object == TARGET_OBJECT_MEMORY
- && ops->deprecated_xfer_memory != NULL)
- /* If available, fall back to the target's
- "deprecated_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->deprecated_xfer_memory (offset, buffer, len,
- 1/*write*/, NULL, ops);
- do_cleanups (cleanup);
- }
- if (readbuf != NULL)
- xfered = ops->deprecated_xfer_memory (offset, readbuf, len,
- 0/*read*/, NULL, ops);
- if (xfered > 0)
- {
- *xfered_len = (ULONGEST) xfered;
- return TARGET_XFER_E_IO;
- }
- else if (xfered == 0 && errno == 0)
- /* "deprecated_xfer_memory" uses 0, cross checked against
- ERRNO as one indication of an error. */
- return TARGET_XFER_EOF;
- else
- return TARGET_XFER_E_IO;
- }
- else
- {
- gdb_assert (ops->beneath != NULL);
- return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
- readbuf, writebuf, offset, len,
- xfered_len);
- }
-}
-
/* Target vector read/write partial wrapper functions. */
static enum target_xfer_status
return runable;
}
-void
-find_default_attach (struct target_ops *ops, char *args, int from_tty)
-{
- struct target_ops *t;
-
- t = find_default_run_target ("attach");
- (t->to_attach) (t, args, from_tty);
- return;
-}
+/* See target.h. */
-void
-find_default_create_inferior (struct target_ops *ops,
- char *exec_file, char *allargs, char **env,
- int from_tty)
+struct target_ops *
+find_attach_target (void)
{
struct target_ops *t;
- t = find_default_run_target ("run");
- (t->to_create_inferior) (t, exec_file, allargs, env, from_tty);
- return;
-}
+ /* If a target on the current stack can attach, use it. */
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_attach != NULL)
+ break;
+ }
-static int
-find_default_can_async_p (struct target_ops *ignore)
-{
- struct target_ops *t;
+ /* Otherwise, use the default run target for attaching. */
+ if (t == NULL)
+ t = find_default_run_target ("attach");
- /* This may be called before the target is pushed on the stack;
- look for the default process stratum. If there's none, gdb isn't
- configured with a native debugger, and target remote isn't
- connected yet. */
- t = find_default_run_target (NULL);
- if (t && t->to_can_async_p != delegate_can_async_p)
- return (t->to_can_async_p) (t);
- return 0;
+ return t;
}
-static int
-find_default_is_async_p (struct target_ops *ignore)
-{
- struct target_ops *t;
-
- /* This may be called before the target is pushed on the stack;
- look for the default process stratum. If there's none, gdb isn't
- configured with a native debugger, and target remote isn't
- connected yet. */
- t = find_default_run_target (NULL);
- if (t && t->to_is_async_p != delegate_is_async_p)
- return (t->to_is_async_p) (t);
- return 0;
-}
+/* See target.h. */
-static int
-find_default_supports_non_stop (struct target_ops *self)
+struct target_ops *
+find_run_target (void)
{
struct target_ops *t;
- t = find_default_run_target (NULL);
- if (t && t->to_supports_non_stop)
- return (t->to_supports_non_stop) (t);
- return 0;
-}
-
-int
-target_supports_non_stop (void)
-{
- struct target_ops *t;
+ /* If a target on the current stack can attach, use it. */
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_create_inferior != NULL)
+ break;
+ }
- for (t = ¤t_target; t != NULL; t = t->beneath)
- if (t->to_supports_non_stop)
- return t->to_supports_non_stop (t);
+ /* Otherwise, use the default run target. */
+ if (t == NULL)
+ t = find_default_run_target ("run");
- return 0;
+ return t;
}
/* Implement the "info proc" command. */
dummy_target.to_shortname = "None";
dummy_target.to_longname = "None";
dummy_target.to_doc = "";
- dummy_target.to_create_inferior = find_default_create_inferior;
- dummy_target.to_supports_non_stop = find_default_supports_non_stop;
dummy_target.to_supports_disable_randomization
= find_default_supports_disable_randomization;
dummy_target.to_stratum = dummy_stratum;
fprintf_unfiltered (gdb_stdlog, "target_close ()\n");
}
-void
-target_attach (char *args, int from_tty)
-{
- current_target.to_attach (¤t_target, args, from_tty);
- if (targetdebug)
- fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n",
- args, from_tty);
-}
-
int
target_thread_alive (ptid_t ptid)
{
return current_target.to_decr_pc_after_break (¤t_target, gdbarch);
}
-static int
-deprecated_debug_xfer_memory (CORE_ADDR memaddr, bfd_byte *myaddr, int len,
- int write, struct mem_attrib *attrib,
- struct target_ops *target)
-{
- int retval;
-
- retval = debug_target.deprecated_xfer_memory (memaddr, myaddr, len, write,
- attrib, target);
-
- fprintf_unfiltered (gdb_stdlog,
- "target_xfer_memory (%s, xxx, %d, %s, xxx) = %d",
- paddress (target_gdbarch (), memaddr), len,
- write ? "write" : "read", retval);
-
- if (retval > 0)
- {
- int i;
-
- fputs_unfiltered (", bytes =", gdb_stdlog);
- for (i = 0; i < retval; i++)
- {
- if ((((intptr_t) &(myaddr[i])) & 0xf) == 0)
- {
- if (targetdebug < 2 && i > 0)
- {
- fprintf_unfiltered (gdb_stdlog, " ...");
- break;
- }
- fprintf_unfiltered (gdb_stdlog, "\n");
- }
-
- fprintf_unfiltered (gdb_stdlog, " %02x", myaddr[i] & 0xff);
- }
- }
-
- fputc_unfiltered ('\n', gdb_stdlog);
-
- return retval;
-}
-
static void
debug_to_files_info (struct target_ops *target)
{
current_target.to_open = debug_to_open;
current_target.to_post_attach = debug_to_post_attach;
current_target.to_prepare_to_store = debug_to_prepare_to_store;
- current_target.deprecated_xfer_memory = deprecated_debug_xfer_memory;
current_target.to_files_info = debug_to_files_info;
current_target.to_insert_breakpoint = debug_to_insert_breakpoint;
current_target.to_remove_breakpoint = debug_to_remove_breakpoint;