/* 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 int return_minus_one (void);
+static void *return_null (void);
+
void target_ignore (void);
static void target_command (char *, int);
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 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 default_xfer_partial;
-static LONGEST target_xfer_partial (struct target_ops *ops,
- enum target_object object,
- const char *annex,
- void *readbuf, const void *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
return_zero);
de_fault (to_extra_thread_info,
(char *(*) (struct thread_info *))
- return_zero);
+ return_null);
de_fault (to_thread_name,
(char *(*) (struct thread_info *))
- return_zero);
+ return_null);
de_fault (to_stop,
(void (*) (ptid_t))
target_ignore);
tcomplain);
de_fault (to_pid_to_exec_file,
(char *(*) (int))
- return_zero);
+ return_null);
de_fault (to_async,
(void (*) (void (*) (enum inferior_event_type, void*), void*))
tcomplain);
tcomplain);
de_fault (to_traceframe_info,
(struct traceframe_info * (*) (void))
- return_zero);
+ return_null);
de_fault (to_supports_evaluation_of_breakpoint_conditions,
(int (*) (void))
return_zero);
return 1;
}
-void
-pop_target (void)
-{
- target_close (target_stack); /* Let it clean up. */
- if (unpush_target (target_stack) == 1)
- return;
-
- fprintf_unfiltered (gdb_stderr,
- "pop_target couldn't find target %s\n",
- current_target.to_shortname);
- internal_error (__FILE__, __LINE__,
- _("failed internal consistency check"));
-}
-
void
pop_all_targets_above (enum strata above_stratum)
{
while ((int) (current_target.to_stratum) > (int) above_stratum)
{
- target_close (target_stack);
if (!unpush_target (target_stack))
{
fprintf_unfiltered (gdb_stderr,
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 addr;
}
+const char *
+target_xfer_error_to_string (enum target_xfer_error err)
+{
+#define CASE(X) case X: return #X
+ switch (err)
+ {
+ CASE(TARGET_XFER_E_IO);
+ CASE(TARGET_XFER_E_UNAVAILABLE);
+ default:
+ return "<unknown>";
+ }
+#undef CASE
+};
+
+
#undef MIN
#define MIN(A, B) (((A) <= (B)) ? (A) : (B))
static LONGEST
target_read_live_memory (enum target_object object,
- ULONGEST memaddr, gdb_byte *myaddr, LONGEST len)
+ ULONGEST memaddr, gdb_byte *myaddr, ULONGEST len)
{
- int ret;
+ LONGEST ret;
struct cleanup *cleanup;
/* Switch momentarily out of tfind mode so to access live memory.
memory_xfer_live_readonly_partial (struct target_ops *ops,
enum target_object object,
gdb_byte *readbuf, ULONGEST memaddr,
- LONGEST len)
+ ULONGEST len)
{
struct target_section *secp;
struct target_section_table *table;
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. */
static LONGEST
memory_xfer_partial_1 (struct target_ops *ops, enum target_object object,
void *readbuf, const void *writebuf, ULONGEST memaddr,
- LONGEST len)
+ ULONGEST len)
{
LONGEST res;
int reg_len;
/* No use trying further, we know some memory starting
at MEMADDR isn't available. */
- return -1;
+ return TARGET_XFER_E_UNAVAILABLE;
}
/* Don't try to read more than how much is available, in
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
static LONGEST
memory_xfer_partial (struct target_ops *ops, enum target_object object,
void *readbuf, const void *writebuf, ULONGEST memaddr,
- LONGEST len)
+ ULONGEST len)
{
int res;
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);
/* For docs see target.h, to_xfer_partial. */
-static LONGEST
+LONGEST
target_xfer_partial (struct target_ops *ops,
enum target_object object, const char *annex,
- void *readbuf, const void *writebuf,
- ULONGEST offset, LONGEST len)
+ gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST 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)
{
host_address_to_string (readbuf),
host_address_to_string (writebuf),
core_addr_to_string_nz (offset),
- plongest (len), plongest (retval));
+ pulongest (len), plongest (retval));
if (readbuf)
myaddr = readbuf;
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. */
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)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
{
if (object == TARGET_OBJECT_MEMORY
&& ops->deprecated_xfer_memory != NULL)
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)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
{
if (ops->beneath != NULL)
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
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;
}
}
return -1;
}
+static void *
+return_null (void)
+{
+ return 0;
+}
+
/*
* Find the next target down the stack from the specified target.
*/
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;
void
target_close (struct target_ops *targ)
{
+ gdb_assert (!target_is_pushed (targ));
+
if (targ->to_xclose != NULL)
targ->to_xclose (targ);
else if (targ->to_close != NULL)
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
int target_async_permitted = 0;
/* The set command writes to this variable. If the inferior is
- executing, linux_nat_async_permitted is *not* updated. */
+ executing, target_async_permitted is *not* updated. */
static int target_async_permitted_1 = 0;
static void
&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 ();
}