/* Select target systems and architectures at runtime for GDB.
- Copyright (C) 1990-2013 Free Software Foundation, Inc.
+ Copyright (C) 1990-2014 Free Software Foundation, Inc.
Contributed by Cygnus Support.
#include "defs.h"
#include <errno.h>
-#include "gdb_string.h"
+#include <string.h>
#include "target.h"
+#include "target-dcache.h"
#include "gdbcmd.h"
#include "symtab.h"
#include "inferior.h"
static struct target_ops *find_default_run_target (char *);
-static LONGEST default_xfer_partial (struct target_ops *ops,
- enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len);
+static target_xfer_partial_ftype default_xfer_partial;
-static LONGEST current_xfer_partial (struct target_ops *ops,
- enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len);
+static target_xfer_partial_ftype current_xfer_partial;
static struct gdbarch *default_thread_architecture (struct target_ops *ops,
ptid_t ptid);
static void setup_target_debug (void);
-/* The option sets this. */
-static int stack_cache_enabled_p_1 = 1;
-/* And set_stack_cache_enabled_p updates this.
- The reason for the separation is so that we don't flush the cache for
- on->on transitions. */
-static int stack_cache_enabled_p = 1;
-
-/* This is called *after* the stack-cache has been set.
- Flush the cache for off->on and on->off transitions.
- There's no real need to flush the cache for on->off transitions,
- except cleanliness. */
-
-static void
-set_stack_cache_enabled_p (char *args, int from_tty,
- struct cmd_list_element *c)
-{
- if (stack_cache_enabled_p != stack_cache_enabled_p_1)
- target_dcache_invalidate ();
-
- stack_cache_enabled_p = stack_cache_enabled_p_1;
-}
-
-static void
-show_stack_cache_enabled_p (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
-{
- fprintf_filtered (file, _("Cache use for stack accesses is %s.\n"), value);
-}
-
-/* Cache of memory operations, to speed up remote access. */
-static DCACHE *target_dcache;
-
-/* Invalidate the target dcache. */
-
-void
-target_dcache_invalidate (void)
-{
- dcache_invalidate (target_dcache);
-}
-
/* The user just typed 'target' without the name of a target. */
static void
case TLS_LOAD_MODULE_NOT_FOUND_ERROR:
if (objfile_is_library)
error (_("Cannot find shared library `%s' in dynamic"
- " linker's load module list"), objfile->name);
+ " linker's load module list"), objfile_name (objfile));
else
error (_("Cannot find executable file `%s' in dynamic"
- " linker's load module list"), objfile->name);
+ " linker's load module list"), objfile_name (objfile));
break;
case TLS_NOT_ALLOCATED_YET_ERROR:
if (objfile_is_library)
" thread-local variables in\n"
"the shared library `%s'\n"
"for %s"),
- objfile->name, target_pid_to_str (ptid));
+ objfile_name (objfile), target_pid_to_str (ptid));
else
error (_("The inferior has not yet allocated storage for"
" thread-local variables in\n"
"the executable `%s'\n"
"for %s"),
- objfile->name, target_pid_to_str (ptid));
+ objfile_name (objfile), target_pid_to_str (ptid));
break;
case TLS_GENERIC_ERROR:
if (objfile_is_library)
error (_("Cannot find thread-local storage for %s, "
"shared library %s:\n%s"),
target_pid_to_str (ptid),
- objfile->name, ex.message);
+ objfile_name (objfile), ex.message);
else
error (_("Cannot find thread-local storage for %s, "
"executable file %s:\n%s"),
target_pid_to_str (ptid),
- objfile->name, ex.message);
+ objfile_name (objfile), ex.message);
break;
default:
throw_exception (ex);
return 0;
}
+/* Read memory from more than one valid target. A core file, for
+ instance, could have some of memory but delegate other bits to
+ the target below it. So, we must manually try all targets. */
+
+static LONGEST
+raw_memory_xfer_partial (struct target_ops *ops, void *readbuf,
+ const void *writebuf, ULONGEST memaddr, LONGEST len)
+{
+ LONGEST res;
+
+ do
+ {
+ res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
+ readbuf, writebuf, memaddr, len);
+ if (res > 0)
+ break;
+
+ /* We want to continue past core files to executables, but not
+ past a running target's memory. */
+ if (ops->to_has_all_memory (ops))
+ break;
+
+ ops = ops->beneath;
+ }
+ while (ops != NULL);
+
+ return res;
+}
+
/* Perform a partial memory transfer.
For docs see target.h, to_xfer_partial. */
the collected memory range fails. */
&& get_traceframe_number () == -1
&& (region->attrib.cache
- || (stack_cache_enabled_p && object == TARGET_OBJECT_STACK_MEMORY)))
+ || (stack_cache_enabled_p () && object == TARGET_OBJECT_STACK_MEMORY)
+ || (code_cache_enabled_p () && object == TARGET_OBJECT_CODE_MEMORY)))
{
+ DCACHE *dcache = target_dcache_get_or_init ();
+
if (readbuf != NULL)
- res = dcache_xfer_memory (ops, target_dcache, memaddr, readbuf,
- reg_len, 0);
+ res = 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. */
- res = dcache_xfer_memory (ops, target_dcache, memaddr,
- (void *) writebuf,
+ res = dcache_xfer_memory (ops, dcache, memaddr, (void *) writebuf,
reg_len, 1);
if (res <= 0)
return -1;
to_xfer_partial is enough; if it doesn't recognize an object
it will call the to_xfer_partial of the next target down.
But for memory this won't do. Memory is the only target
- object which can be read from more than one valid target.
- A core file, for instance, could have some of memory but
- delegate other bits to the target below it. So, we must
- manually try all targets. */
-
- do
- {
- res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
- readbuf, writebuf, memaddr, reg_len);
- if (res > 0)
- break;
-
- /* We want to continue past core files to executables, but not
- past a running target's memory. */
- if (ops->to_has_all_memory (ops))
- break;
-
- ops = ops->beneath;
- }
- while (ops != NULL);
+ object which can be read from more than one valid target. */
+ res = raw_memory_xfer_partial (ops, readbuf, writebuf, memaddr, reg_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
if (res > 0
&& inf != NULL
&& writebuf != NULL
+ && target_dcache_init_p ()
&& !region->attrib.cache
- && stack_cache_enabled_p
- && object != TARGET_OBJECT_STACK_MEMORY)
+ && ((stack_cache_enabled_p () && object != TARGET_OBJECT_STACK_MEMORY)
+ || (code_cache_enabled_p () && object != TARGET_OBJECT_CODE_MEMORY)))
{
- dcache_update (target_dcache, memaddr, (void *) writebuf, res);
+ DCACHE *dcache = target_dcache_get ();
+
+ dcache_update (dcache, memaddr, (void *) writebuf, res);
}
/* If we still haven't got anything, return the last error. We
void *buf;
struct cleanup *old_chain;
+ /* A large write request is likely to be partially satisfied
+ by memory_xfer_partial_1. We will continually malloc
+ and free a copy of the entire write request for breakpoint
+ shadow handling even though we only end up writing a small
+ subset of it. Cap writes to 4KB to mitigate this. */
+ len = min (4096, len);
+
buf = xmalloc (len);
old_chain = make_cleanup (xfree, buf);
memcpy (buf, writebuf, len);
LONGEST
target_xfer_partial (struct target_ops *ops,
enum target_object object, const char *annex,
- void *readbuf, const void *writebuf,
+ gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len)
{
LONGEST retval;
/* If this is a memory transfer, let the memory-specific code
have a look at it instead. Memory transfers are more
complicated. */
- if (object == TARGET_OBJECT_MEMORY || object == TARGET_OBJECT_STACK_MEMORY)
+ if (object == TARGET_OBJECT_MEMORY || object == TARGET_OBJECT_STACK_MEMORY
+ || object == TARGET_OBJECT_CODE_MEMORY)
retval = memory_xfer_partial (ops, object, readbuf,
writebuf, offset, len);
- else
+ else if (object == TARGET_OBJECT_RAW_MEMORY)
{
- enum target_object raw_object = object;
-
- /* If this is a raw memory transfer, request the normal
- memory object from other layers. */
- if (raw_object == TARGET_OBJECT_RAW_MEMORY)
- raw_object = TARGET_OBJECT_MEMORY;
-
- retval = ops->to_xfer_partial (ops, raw_object, annex, readbuf,
- writebuf, offset, len);
+ /* Request the normal memory object from other layers. */
+ retval = raw_memory_xfer_partial (ops, readbuf, writebuf, offset, len);
}
+ else
+ retval = ops->to_xfer_partial (ops, object, annex, readbuf,
+ writebuf, offset, len);
if (targetdebug)
{
return retval;
}
-/* Read LEN bytes of target memory at address MEMADDR, placing the results in
- GDB's memory at MYADDR. Returns either 0 for success or an errno value
- if any error occurs.
+/* Read LEN bytes of target memory at address MEMADDR, placing the
+ results in GDB's memory at MYADDR. Returns either 0 for success or
+ a target_xfer_error value if any error occurs.
If an error occurs, no guarantee is made about the contents of the data at
MYADDR. In particular, the caller should not depend upon partial reads
myaddr, memaddr, len) == len)
return 0;
else
- return EIO;
+ return TARGET_XFER_E_IO;
+}
+
+/* Like target_read_memory, but specify explicitly that this is a read
+ from the target's raw memory. That is, this read bypasses the
+ dcache, breakpoint shadowing, etc. */
+
+int
+target_read_raw_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
+{
+ /* See comment in target_read_memory about why the request starts at
+ current_target.beneath. */
+ if (target_read (current_target.beneath, TARGET_OBJECT_RAW_MEMORY, NULL,
+ myaddr, memaddr, len) == len)
+ return 0;
+ else
+ return TARGET_XFER_E_IO;
}
/* Like target_read_memory, but specify explicitly that this is a read from
int
target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
{
- /* Dispatch to the topmost target, not the flattened current_target.
- Memory accesses check target->to_has_(all_)memory, and the
- flattened target doesn't inherit those. */
-
+ /* See comment in target_read_memory about why the request starts at
+ current_target.beneath. */
if (target_read (current_target.beneath, TARGET_OBJECT_STACK_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
- return EIO;
+ return TARGET_XFER_E_IO;
+}
+
+/* Like target_read_memory, but specify explicitly that this is a read from
+ the target's code. This may trigger different cache behavior. */
+
+int
+target_read_code (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
+{
+ /* See comment in target_read_memory about why the request starts at
+ current_target.beneath. */
+ if (target_read (current_target.beneath, TARGET_OBJECT_CODE_MEMORY, NULL,
+ myaddr, memaddr, len) == len)
+ return 0;
+ else
+ return TARGET_XFER_E_IO;
}
/* Write LEN bytes from MYADDR to target memory at address MEMADDR.
- Returns either 0 for success or an errno value if any error occurs.
- If an error occurs, no guarantee is made about how much data got written.
- Callers that can deal with partial writes should call target_write. */
+ Returns either 0 for success or a target_xfer_error value if any
+ error occurs. If an error occurs, no guarantee is made about how
+ much data got written. Callers that can deal with partial writes
+ should call target_write. */
int
target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
{
- /* Dispatch to the topmost target, not the flattened current_target.
- Memory accesses check target->to_has_(all_)memory, and the
- flattened target doesn't inherit those. */
+ /* See comment in target_read_memory about why the request starts at
+ current_target.beneath. */
if (target_write (current_target.beneath, TARGET_OBJECT_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
- return EIO;
+ return TARGET_XFER_E_IO;
}
/* Write LEN bytes from MYADDR to target raw memory at address
- MEMADDR. Returns either 0 for success or an errno value if any
- error occurs. If an error occurs, no guarantee is made about how
- much data got written. Callers that can deal with partial writes
- should call target_write. */
+ MEMADDR. Returns either 0 for success or a target_xfer_error value
+ if any error occurs. If an error occurs, no guarantee is made
+ about how much data got written. Callers that can deal with
+ partial writes should call target_write. */
int
target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
{
- /* Dispatch to the topmost target, not the flattened current_target.
- Memory accesses check target->to_has_(all_)memory, and the
- flattened target doesn't inherit those. */
+ /* See comment in target_read_memory about why the request starts at
+ current_target.beneath. */
if (target_write (current_target.beneath, TARGET_OBJECT_RAW_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
- return EIO;
+ return TARGET_XFER_E_IO;
}
/* Fetch the target's memory map. */
for this target). */
if (target_read (ops, TARGET_OBJECT_RAW_MEMORY, NULL, buf, addr, len)
!= len)
- memory_error (EIO, addr);
+ memory_error (TARGET_XFER_E_IO, addr);
}
ULONGEST
int has_all_mem = 0;
if (symfile_objfile != NULL)
- printf_unfiltered (_("Symbols from \"%s\".\n"), symfile_objfile->name);
+ printf_unfiltered (_("Symbols from \"%s\".\n"),
+ objfile_name (symfile_objfile));
for (t = target_stack; t != NULL; t = t->beneath)
{
/* Detach a target after doing deferred register stores. */
void
-target_detach (char *args, int from_tty)
+target_detach (const char *args, int from_tty)
{
struct target_ops* t;
else
/* If we're in breakpoints-always-inserted mode, have to remove
them before detaching. */
- remove_breakpoints_pid (PIDGET (inferior_ptid));
+ remove_breakpoints_pid (ptid_get_pid (inferior_ptid));
prepare_for_detach ();
fprintf_unfiltered (gdb_stdlog,
"target_wait (%d, status, options={%s})"
" = %d, %s\n",
- PIDGET (ptid), options_string,
- PIDGET (retval), status_string);
+ ptid_get_pid (ptid), options_string,
+ ptid_get_pid (retval), status_string);
xfree (status_string);
xfree (options_string);
}
t->to_resume (t, ptid, step, signal);
if (targetdebug)
fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n",
- PIDGET (ptid),
+ ptid_get_pid (ptid),
step ? "step" : "continue",
gdb_signal_to_name (signal));
follow forks. */
int
-target_follow_fork (int follow_child)
+target_follow_fork (int follow_child, int detach_fork)
{
struct target_ops *t;
{
if (t->to_follow_fork != NULL)
{
- int retval = t->to_follow_fork (t, follow_child);
+ int retval = t->to_follow_fork (t, follow_child, detach_fork);
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog, "target_follow_fork (%d) = %d\n",
- follow_child, retval);
+ fprintf_unfiltered (gdb_stdlog,
+ "target_follow_fork (%d, %d) = %d\n",
+ follow_child, detach_fork, retval);
return retval;
}
}
dummy_target.to_doc = "";
dummy_target.to_attach = find_default_attach;
dummy_target.to_detach =
- (void (*)(struct target_ops *, char *, int))target_ignore;
+ (void (*)(struct target_ops *, const char *, int))target_ignore;
dummy_target.to_create_inferior = find_default_create_inferior;
dummy_target.to_can_async_p = find_default_can_async_p;
dummy_target.to_is_async_p = find_default_is_async_p;
retval = t->to_thread_alive (t, ptid);
if (targetdebug)
fprintf_unfiltered (gdb_stdlog, "target_thread_alive (%d) = %d\n",
- PIDGET (ptid), retval);
+ ptid_get_pid (ptid), retval);
return retval;
}
if (targetdebug)
fprintf_unfiltered (gdb_stdlog,
"target_core_of_thread (%d) = %d\n",
- PIDGET (ptid), retval);
+ ptid_get_pid (ptid), retval);
return retval;
}
}
for (t = current_target.beneath; t != NULL; t = t->beneath)
if (t->to_disable_btrace != NULL)
- return t->to_disable_btrace (btinfo);
+ {
+ t->to_disable_btrace (btinfo);
+ return;
+ }
tcomplain ();
}
for (t = current_target.beneath; t != NULL; t = t->beneath)
if (t->to_teardown_btrace != NULL)
- return t->to_teardown_btrace (btinfo);
+ {
+ t->to_teardown_btrace (btinfo);
+ return;
+ }
tcomplain ();
}
debug_target.to_post_startup_inferior (ptid);
fprintf_unfiltered (gdb_stdlog, "target_post_startup_inferior (%d)\n",
- PIDGET (ptid));
+ ptid_get_pid (ptid));
}
static int
&setlist,
&showlist);
- add_setshow_boolean_cmd ("stack-cache", class_support,
- &stack_cache_enabled_p_1, _("\
-Set cache use for stack access."), _("\
-Show cache use for stack access."), _("\
-When on, use the data cache for all stack access, regardless of any\n\
-configured memory regions. This improves remote performance significantly.\n\
-By default, caching for stack access is on."),
- set_stack_cache_enabled_p,
- show_stack_cache_enabled_p,
- &setlist, &showlist);
-
add_setshow_boolean_cmd ("may-write-registers", class_support,
&may_write_registers_1, _("\
Set permission to write into registers."), _("\
Otherwise, any attempt to interrupt or stop will be ignored."),
set_target_permissions, NULL,
&setlist, &showlist);
-
-
- target_dcache = dcache_init ();
}