[gdbserver] Move malloc.h include to server.h.
[deliverable/binutils-gdb.git] / gdb / target.c
index 8de1be8a812aa97b4e306c08ffc3d05b3580d5f2..59841258554a0a39b800bd2f829de7c777c759c1 100644 (file)
@@ -1,7 +1,7 @@
 /* Select target systems and architectures at runtime for GDB.
 
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
    Contributed by Cygnus Support.
 #include "gdbthread.h"
 #include "solib.h"
 #include "exec.h"
+#include "inline-frame.h"
+#include "tracepoint.h"
 
 static void target_info (char *, int);
 
-static void kill_or_be_killed (int);
-
 static void default_terminal_info (char *, int);
 
 static int default_watchpoint_addr_within_range (struct target_ops *,
@@ -56,7 +56,7 @@ static int default_region_ok_for_hw_watchpoint (CORE_ADDR, int);
 
 static int nosymbol (char *, CORE_ADDR *);
 
-static void tcomplain (void) ATTR_NORETURN;
+static void tcomplain (void) ATTRIBUTE_NORETURN;
 
 static int nomemory (CORE_ADDR, char *, int, int, struct target_ops *);
 
@@ -72,8 +72,6 @@ static void target_command (char *, int);
 
 static struct target_ops *find_default_run_target (char *);
 
-static void nosupport_runtime (void);
-
 static LONGEST default_xfer_partial (struct target_ops *ops,
                                     enum target_object object,
                                     const char *annex, gdb_byte *readbuf,
@@ -92,6 +90,9 @@ static LONGEST target_xfer_partial (struct target_ops *ops,
                                    void *readbuf, const void *writebuf,
                                    ULONGEST offset, LONGEST len);
 
+static struct gdbarch *default_thread_architecture (struct target_ops *ops,
+                                                   ptid_t ptid);
+
 static void init_dummy_target (void);
 
 static struct target_ops debug_target;
@@ -102,19 +103,25 @@ static void debug_to_prepare_to_store (struct regcache *);
 
 static void debug_to_files_info (struct target_ops *);
 
-static int debug_to_insert_breakpoint (struct bp_target_info *);
+static int debug_to_insert_breakpoint (struct gdbarch *,
+                                      struct bp_target_info *);
 
-static int debug_to_remove_breakpoint (struct bp_target_info *);
+static int debug_to_remove_breakpoint (struct gdbarch *,
+                                      struct bp_target_info *);
 
 static int debug_to_can_use_hw_breakpoint (int, int, int);
 
-static int debug_to_insert_hw_breakpoint (struct bp_target_info *);
+static int debug_to_insert_hw_breakpoint (struct gdbarch *,
+                                         struct bp_target_info *);
 
-static int debug_to_remove_hw_breakpoint (struct bp_target_info *);
+static int debug_to_remove_hw_breakpoint (struct gdbarch *,
+                                         struct bp_target_info *);
 
-static int debug_to_insert_watchpoint (CORE_ADDR, int, int);
+static int debug_to_insert_watchpoint (CORE_ADDR, int, int,
+                                      struct expression *);
 
-static int debug_to_remove_watchpoint (CORE_ADDR, int, int);
+static int debug_to_remove_watchpoint (CORE_ADDR, int, int,
+                                      struct expression *);
 
 static int debug_to_stopped_by_watchpoint (void);
 
@@ -125,6 +132,9 @@ static int debug_to_watchpoint_addr_within_range (struct target_ops *,
 
 static int debug_to_region_ok_for_hw_watchpoint (CORE_ADDR, int);
 
+static int debug_to_can_accel_watchpoint_condition (CORE_ADDR, int, int,
+                                                   struct expression *);
+
 static void debug_to_terminal_init (void);
 
 static void debug_to_terminal_inferior (void);
@@ -190,6 +200,22 @@ static int trust_readonly = 0;
 
 static int show_memory_breakpoints = 0;
 
+/* These globals control whether GDB attempts to perform these
+   operations; they are useful for targets that need to prevent
+   inadvertant disruption, such as in non-stop mode.  */
+
+int may_write_registers = 1;
+
+int may_write_memory = 1;
+
+int may_insert_breakpoints = 1;
+
+int may_insert_tracepoints = 1;
+
+int may_insert_fast_tracepoints = 1;
+
+int may_stop = 1;
+
 /* Non-zero if we want to see trace of target level stuff.  */
 
 static int targetdebug = 0;
@@ -202,7 +228,45 @@ show_targetdebug (struct ui_file *file, int from_tty,
 
 static void setup_target_debug (void);
 
-DCACHE *target_dcache;
+/* 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.  */
 
@@ -213,6 +277,120 @@ target_command (char *arg, int from_tty)
                  gdb_stdout);
 }
 
+/* Default target_has_* methods for process_stratum targets.  */
+
+int
+default_child_has_all_memory (struct target_ops *ops)
+{
+  /* If no inferior selected, then we can't read memory here.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return 0;
+
+  return 1;
+}
+
+int
+default_child_has_memory (struct target_ops *ops)
+{
+  /* If no inferior selected, then we can't read memory here.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return 0;
+
+  return 1;
+}
+
+int
+default_child_has_stack (struct target_ops *ops)
+{
+  /* If no inferior selected, there's no stack.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return 0;
+
+  return 1;
+}
+
+int
+default_child_has_registers (struct target_ops *ops)
+{
+  /* Can't read registers from no inferior.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return 0;
+
+  return 1;
+}
+
+int
+default_child_has_execution (struct target_ops *ops)
+{
+  /* If there's no thread selected, then we can't make it run through
+     hoops.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return 0;
+
+  return 1;
+}
+
+
+int
+target_has_all_memory_1 (void)
+{
+  struct target_ops *t;
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    if (t->to_has_all_memory (t))
+      return 1;
+
+  return 0;
+}
+
+int
+target_has_memory_1 (void)
+{
+  struct target_ops *t;
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    if (t->to_has_memory (t))
+      return 1;
+
+  return 0;
+}
+
+int
+target_has_stack_1 (void)
+{
+  struct target_ops *t;
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    if (t->to_has_stack (t))
+      return 1;
+
+  return 0;
+}
+
+int
+target_has_registers_1 (void)
+{
+  struct target_ops *t;
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    if (t->to_has_registers (t))
+      return 1;
+
+  return 0;
+}
+
+int
+target_has_execution_1 (void)
+{
+  struct target_ops *t;
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    if (t->to_has_execution (t))
+      return 1;
+
+  return 0;
+}
+
 /* Add a possible target architecture to the list.  */
 
 void
@@ -222,6 +400,21 @@ add_target (struct target_ops *t)
   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 = (int (*) (struct target_ops *)) return_zero;
+
+  if (t->to_has_memory == NULL)
+    t->to_has_memory = (int (*) (struct target_ops *)) return_zero;
+
+  if (t->to_has_stack == NULL)
+    t->to_has_stack = (int (*) (struct target_ops *)) return_zero;
+
+  if (t->to_has_registers == NULL)
+    t->to_has_registers = (int (*) (struct target_ops *)) return_zero;
+
+  if (t->to_has_execution == NULL)
+    t->to_has_execution = (int (*) (struct target_ops *)) return_zero;
+
   if (!target_structs)
     {
       target_struct_allocsize = DEFAULT_ALLOCSIZE;
@@ -276,7 +469,7 @@ target_kill (void)
 void
 target_load (char *arg, int from_tty)
 {
-  dcache_invalidate (target_dcache);
+  target_dcache_invalidate ();
   (*current_target.to_load) (arg, from_tty);
 }
 
@@ -285,6 +478,7 @@ 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)       
@@ -306,8 +500,10 @@ void
 target_terminal_inferior (void)
 {
   /* A background resume (``run&'') should leave GDB in control of the
-     terminal.  */
-  if (target_is_async_p () && !sync_execution)
+     terminal. Use target_can_async_p, not target_is_async_p, since at
+     this point the target is not async yet.  However, if sync_execution
+     is not set, we know it will become async prior to resume.  */
+  if (target_can_async_p () && !sync_execution)
     return;
 
   /* If GDB is resuming the inferior in the foreground, install
@@ -342,49 +538,12 @@ nosymbol (char *name, CORE_ADDR *addrp)
   return 1;                    /* Symbol does not exist in target env */
 }
 
-static void
-nosupport_runtime (void)
-{
-  if (ptid_equal (inferior_ptid, null_ptid))
-    noprocess ();
-  else
-    error (_("No run-time support for this"));
-}
-
-
 static void
 default_terminal_info (char *args, int from_tty)
 {
   printf_unfiltered (_("No saved terminal information.\n"));
 }
 
-/* This is the default target_create_inferior and target_attach function.
-   If the current target is executing, it asks whether to kill it off.
-   If this function returns without calling error(), it has killed off
-   the target, and the operation should be attempted.  */
-
-static void
-kill_or_be_killed (int from_tty)
-{
-  if (target_has_execution)
-    {
-      printf_unfiltered (_("You are already running a program:\n"));
-      target_files_info ();
-      if (query (_("Kill it? ")))
-       {
-         target_kill ();
-         if (target_has_execution)
-           error (_("Killing the program did not help."));
-         return;
-       }
-      else
-       {
-         error (_("Program not killed."));
-       }
-    }
-  tcomplain ();
-}
-
 /* A default implementation for the to_get_ada_task_ptid target method.
 
    This function builds the PTID by using both LWP and TID as part of
@@ -453,6 +612,7 @@ update_current_target (void)
       INHERIT (to_stopped_by_watchpoint, t);
       INHERIT (to_watchpoint_addr_within_range, t);
       INHERIT (to_region_ok_for_hw_watchpoint, t);
+      INHERIT (to_can_accel_watchpoint_condition, t);
       INHERIT (to_terminal_init, t);
       INHERIT (to_terminal_inferior, t);
       INHERIT (to_terminal_ours_for_output, t);
@@ -472,8 +632,9 @@ update_current_target (void)
       /* Do not inherit to_follow_fork.  */
       INHERIT (to_insert_exec_catchpoint, t);
       INHERIT (to_remove_exec_catchpoint, t);
+      INHERIT (to_set_syscall_catchpoint, t);
       INHERIT (to_has_exited, t);
-      /* Do not inherit to_mourn_inferiour.  */
+      /* Do not inherit to_mourn_inferior.  */
       INHERIT (to_can_run, t);
       INHERIT (to_notice_signals, t);
       /* Do not inherit to_thread_alive.  */
@@ -486,11 +647,11 @@ update_current_target (void)
       INHERIT (to_pid_to_exec_file, t);
       INHERIT (to_log_command, t);
       INHERIT (to_stratum, t);
-      INHERIT (to_has_all_memory, t);
-      INHERIT (to_has_memory, t);
-      INHERIT (to_has_stack, t);
-      INHERIT (to_has_registers, t);
-      INHERIT (to_has_execution, t);
+      /* Do not inherit to_has_all_memory */
+      /* Do not inherit to_has_memory */
+      /* Do not inherit to_has_stack */
+      /* Do not inherit to_has_registers */
+      /* Do not inherit to_has_execution */
       INHERIT (to_has_thread_control, t);
       INHERIT (to_can_async_p, t);
       INHERIT (to_is_async_p, t);
@@ -498,12 +659,34 @@ update_current_target (void)
       INHERIT (to_async_mask, t);
       INHERIT (to_find_memory_regions, t);
       INHERIT (to_make_corefile_notes, t);
+      INHERIT (to_get_bookmark, t);
+      INHERIT (to_goto_bookmark, t);
       /* Do not inherit to_get_thread_local_address.  */
       INHERIT (to_can_execute_reverse, t);
+      INHERIT (to_thread_architecture, t);
       /* Do not inherit to_read_description.  */
       INHERIT (to_get_ada_task_ptid, t);
       /* Do not inherit to_search_memory.  */
       INHERIT (to_supports_multi_process, t);
+      INHERIT (to_trace_init, t);
+      INHERIT (to_download_tracepoint, t);
+      INHERIT (to_download_trace_state_variable, t);
+      INHERIT (to_trace_set_readonly_regions, t);
+      INHERIT (to_trace_start, t);
+      INHERIT (to_get_trace_status, t);
+      INHERIT (to_trace_stop, t);
+      INHERIT (to_trace_find, t);
+      INHERIT (to_get_trace_state_variable_value, t);
+      INHERIT (to_save_trace_data, t);
+      INHERIT (to_upload_tracepoints, t);
+      INHERIT (to_upload_trace_state_variables, t);
+      INHERIT (to_get_raw_trace_data, t);
+      INHERIT (to_set_disconnected_tracing, t);
+      INHERIT (to_set_circular_trace_buffer, t);
+      INHERIT (to_get_tib_address, t);
+      INHERIT (to_set_permissions, t);
+      INHERIT (to_static_tracepoint_marker_at, t);
+      INHERIT (to_static_tracepoint_markers_by_strid, t);
       INHERIT (to_magic, t);
       /* Do not inherit to_memory_map.  */
       /* Do not inherit to_flash_erase.  */
@@ -545,16 +728,16 @@ update_current_target (void)
            (int (*) (int, int, int))
            return_zero);
   de_fault (to_insert_hw_breakpoint,
-           (int (*) (struct bp_target_info *))
+           (int (*) (struct gdbarch *, struct bp_target_info *))
            return_minus_one);
   de_fault (to_remove_hw_breakpoint,
-           (int (*) (struct bp_target_info *))
+           (int (*) (struct gdbarch *, struct bp_target_info *))
            return_minus_one);
   de_fault (to_insert_watchpoint,
-           (int (*) (CORE_ADDR, int, int))
+           (int (*) (CORE_ADDR, int, int, struct expression *))
            return_minus_one);
   de_fault (to_remove_watchpoint,
-           (int (*) (CORE_ADDR, int, int))
+           (int (*) (CORE_ADDR, int, int, struct expression *))
            return_minus_one);
   de_fault (to_stopped_by_watchpoint,
            (int (*) (void))
@@ -566,6 +749,9 @@ update_current_target (void)
            default_watchpoint_addr_within_range);
   de_fault (to_region_ok_for_hw_watchpoint,
            default_region_ok_for_hw_watchpoint);
+  de_fault (to_can_accel_watchpoint_condition,
+            (int (*) (CORE_ADDR, int, int, struct expression *))
+            return_zero);
   de_fault (to_terminal_init,
            (void (*) (void))
            target_ignore);
@@ -613,6 +799,9 @@ update_current_target (void)
   de_fault (to_remove_exec_catchpoint,
            (int (*) (int))
            tcomplain);
+  de_fault (to_set_syscall_catchpoint,
+           (int (*) (int, int, int, int, int *))
+           tcomplain);
   de_fault (to_has_exited,
            (int (*) (int, int, int *))
            return_zero);
@@ -640,6 +829,8 @@ update_current_target (void)
   de_fault (to_async_mask,
            (int (*) (int))
            return_one);
+  de_fault (to_thread_architecture,
+           default_thread_architecture);
   current_target.to_read_description = NULL;
   de_fault (to_get_ada_task_ptid,
             (ptid_t (*) (long, long))
@@ -647,6 +838,63 @@ update_current_target (void)
   de_fault (to_supports_multi_process,
            (int (*) (void))
            return_zero);
+  de_fault (to_trace_init,
+           (void (*) (void))
+           tcomplain);
+  de_fault (to_download_tracepoint,
+           (void (*) (struct breakpoint *))
+           tcomplain);
+  de_fault (to_download_trace_state_variable,
+           (void (*) (struct trace_state_variable *))
+           tcomplain);
+  de_fault (to_trace_set_readonly_regions,
+           (void (*) (void))
+           tcomplain);
+  de_fault (to_trace_start,
+           (void (*) (void))
+           tcomplain);
+  de_fault (to_get_trace_status,
+           (int (*) (struct trace_status *))
+           return_minus_one);
+  de_fault (to_trace_stop,
+           (void (*) (void))
+           tcomplain);
+  de_fault (to_trace_find,
+           (int (*) (enum trace_find_type, int, ULONGEST, ULONGEST, int *))
+           return_minus_one);
+  de_fault (to_get_trace_state_variable_value,
+           (int (*) (int, LONGEST *))
+           return_zero);
+  de_fault (to_save_trace_data,
+           (int (*) (const char *))
+           tcomplain);
+  de_fault (to_upload_tracepoints,
+           (int (*) (struct uploaded_tp **))
+           return_zero);
+  de_fault (to_upload_trace_state_variables,
+           (int (*) (struct uploaded_tsv **))
+           return_zero);
+  de_fault (to_get_raw_trace_data,
+           (LONGEST (*) (gdb_byte *, ULONGEST, LONGEST))
+           tcomplain);
+  de_fault (to_set_disconnected_tracing,
+           (void (*) (int))
+           target_ignore);
+  de_fault (to_set_circular_trace_buffer,
+           (void (*) (int))
+           target_ignore);
+  de_fault (to_get_tib_address,
+           (int (*) (ptid_t, CORE_ADDR *))
+           tcomplain);
+  de_fault (to_set_permissions,
+           (void (*) (void))
+           target_ignore);
+  de_fault (to_static_tracepoint_marker_at,
+           (int (*) (CORE_ADDR, struct static_tracepoint_marker *))
+           return_zero);
+  de_fault (to_static_tracepoint_markers_by_strid,
+           (VEC(static_tracepoint_marker_p) * (*) (const char *))
+           tcomplain);
 #undef de_fault
 
   /* Finally, position the target-stack beneath the squashed
@@ -658,67 +906,14 @@ update_current_target (void)
     setup_target_debug ();
 }
 
-/* Mark OPS as a running target.  This reverses the effect
-   of target_mark_exited.  */
-
-void
-target_mark_running (struct target_ops *ops)
-{
-  struct target_ops *t;
-
-  for (t = target_stack; t != NULL; t = t->beneath)
-    if (t == ops)
-      break;
-  if (t == NULL)
-    internal_error (__FILE__, __LINE__,
-                   "Attempted to mark unpushed target \"%s\" as running",
-                   ops->to_shortname);
-
-  ops->to_has_execution = 1;
-  ops->to_has_all_memory = 1;
-  ops->to_has_memory = 1;
-  ops->to_has_stack = 1;
-  ops->to_has_registers = 1;
-
-  update_current_target ();
-}
-
-/* Mark OPS as a non-running target.  This reverses the effect
-   of target_mark_running.  */
-
-void
-target_mark_exited (struct target_ops *ops)
-{
-  struct target_ops *t;
-
-  for (t = target_stack; t != NULL; t = t->beneath)
-    if (t == ops)
-      break;
-  if (t == NULL)
-    internal_error (__FILE__, __LINE__,
-                   "Attempted to mark unpushed target \"%s\" as running",
-                   ops->to_shortname);
-
-  ops->to_has_execution = 0;
-  ops->to_has_all_memory = 0;
-  ops->to_has_memory = 0;
-  ops->to_has_stack = 0;
-  ops->to_has_registers = 0;
-
-  update_current_target ();
-}
-
 /* Push a new target type into the stack of the existing target accessors,
    possibly superseding some of the existing accessors.
 
-   Result is zero if the pushed target ended up on top of the stack,
-   nonzero if at least one target is on top of it.
-
    Rather than allow an empty stack, we always have the dummy target at
    the bottom stratum, so we can call the function vectors without
    checking them.  */
 
-int
+void
 push_target (struct target_ops *t)
 {
   struct target_ops **cur;
@@ -748,6 +943,7 @@ push_target (struct target_ops *t)
       /* There's already something at this stratum level.  Close it,
          and un-hook it from the stack.  */
       struct target_ops *tmp = (*cur);
+
       (*cur) = (*cur)->beneath;
       tmp->beneath = NULL;
       target_close (tmp, 0);
@@ -758,9 +954,6 @@ push_target (struct target_ops *t)
   (*cur) = t;
 
   update_current_target ();
-
-  /* Not on top?  */
-  return (t != target_stack);
 }
 
 /* Remove a target_ops vector from the stack, wherever it may be.
@@ -816,7 +1009,8 @@ pop_target (void)
   fprintf_unfiltered (gdb_stderr,
                      "pop_target couldn't find target %s\n",
                      current_target.to_shortname);
-  internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+  internal_error (__FILE__, __LINE__,
+                 _("failed internal consistency check"));
 }
 
 void
@@ -843,6 +1037,30 @@ pop_all_targets (int quitting)
   pop_all_targets_above (dummy_stratum, quitting);
 }
 
+/* Return 1 if T is now pushed in the target stack.  Return 0 otherwise.  */
+
+int
+target_is_pushed (struct target_ops *t)
+{
+  struct target_ops **cur;
+
+  /* Check magic number.  If wrong, it probably means someone changed
+     the struct definition, but not all the places that initialize one.  */
+  if (t->to_magic != OPS_MAGIC)
+    {
+      fprintf_unfiltered (gdb_stderr,
+                         "Magic number of %s target struct wrong\n",
+                         t->to_shortname);
+      internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+    }
+
+  for (cur = &target_stack; (*cur) != NULL; cur = &(*cur)->beneath)
+    if (*cur == t)
+      return 1;
+
+  return 0;
+}
+
 /* Using the objfile specified in OBJFILE, find the address for the
    current thread's thread-local storage with offset OFFSET.  */
 CORE_ADDR
@@ -988,6 +1206,7 @@ target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
       if (bufptr - buffer + tlen > buffer_allocated)
        {
          unsigned int bytes;
+
          bytes = bufptr - buffer;
          buffer_allocated *= 2;
          buffer = xrealloc (buffer, buffer_allocated);
@@ -1049,16 +1268,18 @@ target_section_by_addr (struct target_ops *target, CORE_ADDR addr)
   return NULL;
 }
 
-/* Perform a partial memory transfer.  The arguments and return
-   value are just as for target_xfer_partial.  */
+/* Perform a partial memory transfer.
+   For docs see target.h, to_xfer_partial.  */
 
 static LONGEST
-memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf,
-                    ULONGEST memaddr, LONGEST len)
+memory_xfer_partial (struct target_ops *ops, enum target_object object,
+                    void *readbuf, const void *writebuf, ULONGEST memaddr,
+                    LONGEST len)
 {
   LONGEST res;
   int reg_len;
   struct mem_region *region;
+  struct inferior *inf;
 
   /* Zero length requests are ok and require no work.  */
   if (len == 0)
@@ -1069,11 +1290,13 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
   if (readbuf != NULL && overlay_debugging)
     {
       struct obj_section *section = find_pc_overlay (memaddr);
+
       if (pc_in_unmapped_range (memaddr, section))
        {
          struct target_section_table *table
            = target_get_section_table (ops);
          const char *section_name = section->the_bfd_section->name;
+
          memaddr = overlay_mapped_address (memaddr, section);
          return section_table_xfer_memory_partial (readbuf, writebuf,
                                                    memaddr, len,
@@ -1133,18 +1356,27 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
       return -1;
     }
 
-  if (region->attrib.cache)
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    inf = find_inferior_pid (ptid_get_pid (inferior_ptid));
+  else
+    inf = NULL;
+
+  if (inf != 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.  */
+      && get_traceframe_number () == -1
+      && (region->attrib.cache
+         || (stack_cache_enabled_p && object == TARGET_OBJECT_STACK_MEMORY)))
     {
-      /* FIXME drow/2006-08-09: This call discards OPS, so the raw
-        memory request will start back at current_target.  */
       if (readbuf != NULL)
-       res = dcache_xfer_memory (target_dcache, memaddr, readbuf,
+       res = dcache_xfer_memory (ops, target_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 (target_dcache, memaddr,
+       res = dcache_xfer_memory (ops, target_dcache, memaddr,
                                  (void *) writebuf,
                                  reg_len, 1);
       if (res <= 0)
@@ -1176,7 +1408,7 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
 
       /* We want to continue past core files to executables, but not
         past a running target's memory.  */
-      if (ops->to_has_all_memory)
+      if (ops->to_has_all_memory (ops))
        break;
 
       ops = ops->beneath;
@@ -1186,6 +1418,20 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
   if (readbuf && !show_memory_breakpoints)
     breakpoint_restore_shadows (readbuf, 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
+     to update the cache.  */
+
+  if (res > 0
+      && inf != NULL
+      && writebuf != NULL
+      && !region->attrib.cache
+      && stack_cache_enabled_p
+      && object != TARGET_OBJECT_STACK_MEMORY)
+    {
+      dcache_update (target_dcache, memaddr, (void *) writebuf, res);
+    }
+
   /* If we still haven't got anything, return the last error.  We
      give up.  */
   return res;
@@ -1201,12 +1447,14 @@ struct cleanup *
 make_show_memory_breakpoints_cleanup (int show)
 {
   int current = show_memory_breakpoints;
-  show_memory_breakpoints = show;
 
+  show_memory_breakpoints = show;
   return make_cleanup (restore_show_memory_breakpoints,
                       (void *) (uintptr_t) current);
 }
 
+/* For docs see target.h, to_xfer_partial.  */
+
 static LONGEST
 target_xfer_partial (struct target_ops *ops,
                     enum target_object object, const char *annex,
@@ -1217,11 +1465,16 @@ target_xfer_partial (struct target_ops *ops,
 
   gdb_assert (ops->to_xfer_partial != NULL);
 
+  if (writebuf && !may_write_memory)
+    error (_("Writing to memory is not allowed (addr %s, len %s)"),
+          core_addr_to_string_nz (offset), plongest (len));
+
   /* 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)
-    retval = memory_xfer_partial (ops, readbuf, writebuf, offset, len);
+  if (object == TARGET_OBJECT_MEMORY || object == TARGET_OBJECT_STACK_MEMORY)
+    retval = memory_xfer_partial (ops, object, readbuf,
+                                 writebuf, offset, len);
   else
     {
       enum target_object raw_object = object;
@@ -1293,17 +1546,45 @@ target_xfer_partial (struct target_ops *ops,
 int
 target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
 {
-  if (target_read (&current_target, TARGET_OBJECT_MEMORY, NULL,
+  /* 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.  */
+  if (target_read (current_target.beneath, TARGET_OBJECT_MEMORY, NULL,
                   myaddr, memaddr, len) == len)
     return 0;
   else
     return EIO;
 }
 
+/* Like target_read_memory, but specify explicitly that this is a read from
+   the target's stack.  This may trigger different cache behavior.  */
+
+int
+target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int 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.  */
+
+  if (target_read (current_target.beneath, TARGET_OBJECT_STACK_MEMORY, NULL,
+                  myaddr, memaddr, len) == len)
+    return 0;
+  else
+    return EIO;
+}
+
+/* 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.  */
+
 int
 target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
 {
-  if (target_write (&current_target, TARGET_OBJECT_MEMORY, NULL,
+  /* 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.  */
+  if (target_write (current_target.beneath, TARGET_OBJECT_MEMORY, NULL,
                    myaddr, memaddr, len) == len)
     return 0;
   else
@@ -1365,13 +1646,13 @@ target_flash_erase (ULONGEST address, LONGEST length)
 
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     if (t->to_flash_erase != NULL)
-       {
-         if (targetdebug)
-           fprintf_unfiltered (gdb_stdlog, "target_flash_erase (%s, %s)\n",
-                                paddr (address), phex (length, 0));
-         t->to_flash_erase (t, address, length);
-         return;
-       }
+      {
+       if (targetdebug)
+         fprintf_unfiltered (gdb_stdlog, "target_flash_erase (%s, %s)\n",
+                             hex_string (address), phex (length, 0));
+       t->to_flash_erase (t, address, length);
+       return;
+      }
 
   tcomplain ();
 }
@@ -1383,12 +1664,12 @@ target_flash_done (void)
 
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     if (t->to_flash_done != NULL)
-       {
-         if (targetdebug)
-           fprintf_unfiltered (gdb_stdlog, "target_flash_done\n");
-         t->to_flash_done (t);
-         return;
-       }
+      {
+       if (targetdebug)
+         fprintf_unfiltered (gdb_stdlog, "target_flash_done\n");
+       t->to_flash_done (t);
+       return;
+      }
 
   tcomplain ();
 }
@@ -1415,11 +1696,13 @@ default_xfer_partial (struct target_ops *ops, enum target_object object,
        "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);
@@ -1460,11 +1743,7 @@ current_xfer_partial (struct target_ops *ops, enum target_object object,
     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.  */
+/* Target vector read/write partial wrapper functions.  */
 
 static LONGEST
 target_read_partial (struct target_ops *ops,
@@ -1475,102 +1754,239 @@ target_read_partial (struct target_ops *ops,
   return target_xfer_partial (ops, object, annex, buf, NULL, offset, len);
 }
 
-static LONGEST
-target_write_partial (struct target_ops *ops,
-                     enum target_object object,
-                     const char *annex, const gdb_byte *buf,
-                     ULONGEST offset, LONGEST len)
+static LONGEST
+target_write_partial (struct target_ops *ops,
+                     enum target_object object,
+                     const char *annex, const gdb_byte *buf,
+                     ULONGEST offset, LONGEST len)
+{
+  return target_xfer_partial (ops, object, annex, NULL, buf, offset, len);
+}
+
+/* Wrappers to perform the full transfer.  */
+
+/* For docs on target_read see target.h.  */
+
+LONGEST
+target_read (struct target_ops *ops,
+            enum target_object object,
+            const char *annex, gdb_byte *buf,
+            ULONGEST offset, LONGEST len)
+{
+  LONGEST xfered = 0;
+
+  while (xfered < len)
+    {
+      LONGEST xfer = target_read_partial (ops, object, annex,
+                                         (gdb_byte *) buf + xfered,
+                                         offset + xfered, len - xfered);
+
+      /* Call an observer, notifying them of the xfer progress?  */
+      if (xfer == 0)
+       return xfered;
+      if (xfer < 0)
+       return -1;
+      xfered += xfer;
+      QUIT;
+    }
+  return len;
+}
+
+/** Assuming that the entire [begin, end) range of memory cannot be read,
+    try to read whatever subrange is possible to read.
+
+    The function results, in RESULT, either zero or one memory block.
+    If there's a readable subrange at the beginning, it is completely
+    read and returned. Any further readable subrange will not be read.
+    Otherwise, if there's a readable subrange at the end, it will be
+    completely read and returned.  Any readable subranges before it (obviously,
+    not starting at the beginning), will be ignored. In other cases --
+    either no readable subrange, or readable subrange (s) that is neither
+    at the beginning, or end, nothing is returned.
+
+    The purpose of this function is to handle a read across a boundary of
+    accessible memory in a case when memory map is not available. The above
+    restrictions are fine for this case, but will give incorrect results if
+    the memory is 'patchy'. However, supporting 'patchy' memory would require
+    trying to read every single byte, and it seems unacceptable solution.
+    Explicit memory map is recommended for this case -- and
+    target_read_memory_robust will take care of reading multiple ranges then.  */
+
+static void
+read_whatever_is_readable (struct target_ops *ops, ULONGEST begin, ULONGEST end,
+                          VEC(memory_read_result_s) **result)
+{
+  gdb_byte *buf = xmalloc (end-begin);
+  ULONGEST current_begin = begin;
+  ULONGEST current_end = end;
+  int forward;
+  memory_read_result_s r;
+
+  /* If we previously failed to read 1 byte, nothing can be done here.  */
+  if (end - begin <= 1)
+    return;
+
+  /* Check that either first or the last byte is readable, and give up
+     if not. This heuristic is meant to permit reading accessible memory
+     at the boundary of accessible region.  */
+  if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
+                          buf, begin, 1) == 1)
+    {
+      forward = 1;
+      ++current_begin;
+    }
+  else if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
+                               buf + (end-begin) - 1, end - 1, 1) == 1)
+    {
+      forward = 0;
+      --current_end;
+    }
+  else
+    {
+      return;
+    }
+
+  /* Loop invariant is that the [current_begin, current_end) was previously
+     found to be not readable as a whole.
+
+     Note loop condition -- if the range has 1 byte, we can't divide the range
+     so there's no point trying further.  */
+  while (current_end - current_begin > 1)
+    {
+      ULONGEST first_half_begin, first_half_end;
+      ULONGEST second_half_begin, second_half_end;
+      LONGEST xfer;
+
+      ULONGEST middle = current_begin + (current_end - current_begin)/2;
+      if (forward)
+       {
+         first_half_begin = current_begin;
+         first_half_end = middle;
+         second_half_begin = middle;
+         second_half_end = current_end;
+       }
+      else
+       {
+         first_half_begin = middle;
+         first_half_end = current_end;
+         second_half_begin = current_begin;
+         second_half_end = middle;
+       }
+
+      xfer = target_read (ops, TARGET_OBJECT_MEMORY, NULL,
+                         buf + (first_half_begin - begin),
+                         first_half_begin,
+                         first_half_end - first_half_begin);
+
+      if (xfer == first_half_end - first_half_begin)
+       {
+         /* This half reads up fine. So, the error must be in the other half.  */
+         current_begin = second_half_begin;
+         current_end = second_half_end;
+       }
+      else
+       {
+         /* This half is not readable. Because we've tried one byte, we
+            know some part of this half if actually redable. Go to the next
+            iteration to divide again and try to read.
+
+            We don't handle the other half, because this function only tries
+            to read a single readable subrange.  */
+         current_begin = first_half_begin;
+         current_end = first_half_end;
+       }
+    }
+
+  if (forward)
+    {
+      /* The [begin, current_begin) range has been read.  */
+      r.begin = begin;
+      r.end = current_begin;
+      r.data = buf;
+    }
+  else
+    {
+      /* The [current_end, end) range has been read.  */
+      LONGEST rlen = end - current_end;
+      r.data = xmalloc (rlen);
+      memcpy (r.data, buf + current_end - begin, rlen);
+      r.begin = current_end;
+      r.end = end;
+      xfree (buf);
+    }
+  VEC_safe_push(memory_read_result_s, (*result), &r);
+}
+
+void
+free_memory_read_result_vector (void *x)
 {
-  return target_xfer_partial (ops, object, annex, NULL, buf, offset, len);
-}
+  VEC(memory_read_result_s) *v = x;
+  memory_read_result_s *current;
+  int ix;
 
-/* Wrappers to perform the full transfer.  */
-LONGEST
-target_read (struct target_ops *ops,
-            enum target_object object,
-            const char *annex, gdb_byte *buf,
-            ULONGEST offset, LONGEST len)
-{
-  LONGEST xfered = 0;
-  while (xfered < len)
+  for (ix = 0; VEC_iterate (memory_read_result_s, v, ix, current); ++ix)
     {
-      LONGEST xfer = target_read_partial (ops, object, annex,
-                                         (gdb_byte *) buf + xfered,
-                                         offset + xfered, len - xfered);
-      /* Call an observer, notifying them of the xfer progress?  */
-      if (xfer == 0)
-       return xfered;
-      if (xfer < 0)
-       return -1;
-      xfered += xfer;
-      QUIT;
+      xfree (current->data);
     }
-  return len;
+  VEC_free (memory_read_result_s, v);
 }
 
-LONGEST
-target_read_until_error (struct target_ops *ops,
-                        enum target_object object,
-                        const char *annex, gdb_byte *buf,
-                        ULONGEST offset, LONGEST len)
+VEC(memory_read_result_s) *
+read_memory_robust (struct target_ops *ops, ULONGEST offset, LONGEST len)
 {
+  VEC(memory_read_result_s) *result = 0;
+
   LONGEST xfered = 0;
   while (xfered < len)
     {
-      LONGEST xfer = target_read_partial (ops, object, annex,
-                                         (gdb_byte *) buf + xfered,
-                                         offset + xfered, len - xfered);
-      /* Call an observer, notifying them of the xfer progress?  */
-      if (xfer == 0)
-       return xfered;
-      if (xfer < 0)
+      struct mem_region *region = lookup_mem_region (offset + xfered);
+      LONGEST rlen;
+
+      /* If there is no explicit region, a fake one should be created.  */
+      gdb_assert (region);
+
+      if (region->hi == 0)
+       rlen = len - xfered;
+      else
+       rlen = region->hi - offset;
+
+      if (region->attrib.mode == MEM_NONE || region->attrib.mode == MEM_WO)
        {
-         /* We've got an error.  Try to read in smaller blocks.  */
-         ULONGEST start = offset + xfered;
-         ULONGEST remaining = len - xfered;
-         ULONGEST half;
-
-         /* If an attempt was made to read a random memory address,
-            it's likely that the very first byte is not accessible.
-            Try reading the first byte, to avoid doing log N tries
-            below.  */
-         xfer = target_read_partial (ops, object, annex, 
-                                     (gdb_byte *) buf + xfered, start, 1);
+         /* Cannot read this region. Note that we can end up here only
+            if the region is explicitly marked inaccessible, or
+            'inaccessible-by-default' is in effect.  */
+         xfered += rlen;
+       }
+      else
+       {
+         LONGEST to_read = min (len - xfered, rlen);
+         gdb_byte *buffer = (gdb_byte *)xmalloc (to_read);
+
+         LONGEST xfer = target_read (ops, TARGET_OBJECT_MEMORY, NULL,
+                                     (gdb_byte *) buffer,
+                                     offset + xfered, to_read);
+         /* Call an observer, notifying them of the xfer progress?  */
          if (xfer <= 0)
-           return xfered;
-         start += 1;
-         remaining -= 1;
-         half = remaining/2;
-         
-         while (half > 0)
            {
-             xfer = target_read_partial (ops, object, annex,
-                                         (gdb_byte *) buf + xfered,
-                                         start, half);
-             if (xfer == 0)
-               return xfered;
-             if (xfer < 0)
-               {
-                 remaining = half;               
-               }
-             else
-               {
-                 /* We have successfully read the first half.  So, the
-                    error must be in the second half.  Adjust start and
-                    remaining to point at the second half.  */
-                 xfered += xfer;
-                 start += xfer;
-                 remaining -= xfer;
-               }
-             half = remaining/2;
+             /* Got an error reading full chunk. See if maybe we can read
+                some subrange.  */
+             xfree (buffer);
+             read_whatever_is_readable (ops, offset + xfered, offset + xfered + to_read, &result);
+             xfered += to_read;
            }
-
-         return xfered;
+         else
+           {
+             struct memory_read_result r;
+             r.data = buffer;
+             r.begin = offset + xfered;
+             r.end = r.begin + xfer;
+             VEC_safe_push (memory_read_result_s, result, &r);
+             xfered += xfer;
+           }
+         QUIT;
        }
-      xfered += xfer;
-      QUIT;
     }
-  return len;
+  return result;
 }
 
 
@@ -1609,6 +2025,8 @@ target_write_with_progress (struct target_ops *ops,
   return len;
 }
 
+/* For docs on target_write see target.h.  */
+
 LONGEST
 target_write (struct target_ops *ops,
              enum target_object object,
@@ -1735,14 +2153,44 @@ get_target_memory (struct target_ops *ops, CORE_ADDR addr, gdb_byte *buf,
 }
 
 ULONGEST
-get_target_memory_unsigned (struct target_ops *ops,
-                           CORE_ADDR addr, int len)
+get_target_memory_unsigned (struct target_ops *ops, CORE_ADDR addr,
+                           int len, enum bfd_endian byte_order)
 {
   gdb_byte buf[sizeof (ULONGEST)];
 
   gdb_assert (len <= sizeof (buf));
   get_target_memory (ops, addr, buf, len);
-  return extract_unsigned_integer (buf, len);
+  return extract_unsigned_integer (buf, len, byte_order);
+}
+
+int
+target_insert_breakpoint (struct gdbarch *gdbarch,
+                         struct bp_target_info *bp_tgt)
+{
+  if (!may_insert_breakpoints)
+    {
+      warning (_("May not insert breakpoints"));
+      return 1;
+    }
+
+  return (*current_target.to_insert_breakpoint) (gdbarch, bp_tgt);
+}
+
+int
+target_remove_breakpoint (struct gdbarch *gdbarch,
+                         struct bp_target_info *bp_tgt)
+{
+  /* This is kind of a weird case to handle, but the permission might
+     have been changed after breakpoints were inserted - in which case
+     we should just take the user literally and assume that any
+     breakpoints should be left in place.  */
+  if (!may_insert_breakpoints)
+    {
+      warning (_("May not remove breakpoints"));
+      return 1;
+    }
+
+  return (*current_target.to_remove_breakpoint) (gdbarch, bp_tgt);
 }
 
 static void
@@ -1756,7 +2204,7 @@ target_info (char *args, int from_tty)
 
   for (t = target_stack; t != NULL; t = t->beneath)
     {
-      if (!t->to_has_memory)
+      if (!(*t->to_has_memory) (t))
        continue;
 
       if ((int) (t->to_stratum) <= (int) dummy_stratum)
@@ -1765,7 +2213,7 @@ target_info (char *args, int from_tty)
        printf_unfiltered (_("\tWhile running this, GDB does not access memory from...\n"));
       printf_unfiltered ("%s:\n", t->to_longname);
       (t->to_files_info) (t);
-      has_all_mem = t->to_has_all_memory;
+      has_all_mem = (*t->to_has_all_memory) (t);
     }
 }
 
@@ -1808,6 +2256,29 @@ target_pre_inferior (int from_tty)
     }
 }
 
+/* Callback for iterate_over_inferiors.  Gets rid of the given
+   inferior.  */
+
+static int
+dispose_inferior (struct inferior *inf, void *args)
+{
+  struct thread_info *thread;
+
+  thread = any_thread_of_process (inf->pid);
+  if (thread)
+    {
+      switch_to_thread (thread->ptid);
+
+      /* Core inferiors actually should be detached, not killed.  */
+      if (target_has_execution)
+       target_kill ();
+      else
+       target_detach (NULL, 0);
+    }
+
+  return 0;
+}
+
 /* This is to be called by the open routine before it does
    anything.  */
 
@@ -1816,11 +2287,12 @@ target_preopen (int from_tty)
 {
   dont_repeat ();
 
-  if (target_has_execution)
+  if (have_inferiors ())
     {
       if (!from_tty
-          || query (_("A program is being debugged already.  Kill it? ")))
-       target_kill ();
+         || !have_live_inferiors ()
+         || query (_("A program is being debugged already.  Kill it? ")))
+       iterate_over_inferiors (dispose_inferior, NULL);
       else
        error (_("Program not killed."));
     }
@@ -1848,7 +2320,9 @@ target_detach (char *args, int from_tty)
   else
     /* If we're in breakpoints-always-inserted mode, have to remove
        them before detaching.  */
-    remove_breakpoints ();
+    remove_breakpoints_pid (PIDGET (inferior_ptid));
+
+  prepare_for_detach ();
 
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     {
@@ -1937,7 +2411,7 @@ target_resume (ptid_t ptid, int step, enum target_signal signal)
 {
   struct target_ops *t;
 
-  dcache_invalidate (target_dcache);
+  target_dcache_invalidate ();
 
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     {
@@ -1950,8 +2424,10 @@ target_resume (ptid_t ptid, int step, enum target_signal signal)
                                step ? "step" : "continue",
                                target_signal_to_name (signal));
 
+         registers_changed_ptid (ptid);
          set_executing (ptid, 1);
          set_running (ptid, 1);
+         clear_inline_frame_state (ptid);
          return;
        }
     }
@@ -1971,6 +2447,7 @@ target_follow_fork (int follow_child)
       if (t->to_follow_fork != NULL)
        {
          int retval = t->to_follow_fork (t, follow_child);
+
          if (targetdebug)
            fprintf_unfiltered (gdb_stdlog, "target_follow_fork (%d) = %d\n",
                                follow_child, retval);
@@ -1987,6 +2464,7 @@ void
 target_mourn_inferior (void)
 {
   struct target_ops *t;
+
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     {
       if (t->to_mourn_inferior != NULL)        
@@ -2005,7 +2483,7 @@ target_mourn_inferior (void)
     }
 
   internal_error (__FILE__, __LINE__,
-                 "could not find a target to follow mourn inferiour");
+                 "could not find a target to follow mourn inferior");
 }
 
 /* Look for a target which can describe architectural features, starting
@@ -2087,6 +2565,7 @@ simple_search_memory (struct target_ops *ops,
       if (found_ptr != NULL)
        {
          CORE_ADDR found_addr = start_addr + (found_ptr - search_buf);
+
          *found_addrp = found_addr;
          do_cleanups (old_cleanups);
          return 1;
@@ -2103,7 +2582,7 @@ simple_search_memory (struct target_ops *ops,
       if (search_space_len >= pattern_len)
        {
          unsigned keep_len = search_buf_size - chunk_size;
-         CORE_ADDR read_addr = start_addr + keep_len;
+         CORE_ADDR read_addr = start_addr + chunk_size + keep_len;
          int nr_to_read;
 
          /* Copy the trailing part of the previous iteration to the front
@@ -2169,7 +2648,7 @@ target_search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
     {
       /* If a special version of to_search_memory isn't available, use the
         simple version.  */
-      found = simple_search_memory (&current_target,
+      found = simple_search_memory (current_target.beneath,
                                    start_addr, search_space_len,
                                    pattern, pattern_len, found_addrp);
     }
@@ -2201,7 +2680,8 @@ target_require_runnable (void)
       /* Do not worry about thread_stratum targets that can not
         create inferiors.  Assume they will be pushed again if
         necessary, and continue to the process_stratum.  */
-      if (t->to_stratum == thread_stratum)
+      if (t->to_stratum == thread_stratum
+         || t->to_stratum == arch_stratum)
        continue;
 
       error (_("\
@@ -2319,6 +2799,7 @@ int
 target_supports_non_stop (void)
 {
   struct target_ops *t;
+
   for (t = &current_target; t != NULL; t = t->beneath)
     if (t->to_supports_non_stop)
       return t->to_supports_non_stop ();
@@ -2330,7 +2811,6 @@ target_supports_non_stop (void)
 char *
 target_get_osdata (const char *type)
 {
-  char *document;
   struct target_ops *t;
 
   /* If we're already connected to something that can get us OS
@@ -2347,6 +2827,42 @@ target_get_osdata (const char *type)
   return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type);
 }
 
+/* Determine the current address space of thread PTID.  */
+
+struct address_space *
+target_thread_address_space (ptid_t ptid)
+{
+  struct address_space *aspace;
+  struct inferior *inf;
+  struct target_ops *t;
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    {
+      if (t->to_thread_address_space != NULL)
+       {
+         aspace = t->to_thread_address_space (t, ptid);
+         gdb_assert (aspace);
+
+         if (targetdebug)
+           fprintf_unfiltered (gdb_stdlog,
+                               "target_thread_address_space (%s) = %d\n",
+                               target_pid_to_str (ptid),
+                               address_space_num (aspace));
+         return aspace;
+       }
+    }
+
+  /* Fall-back to the "main" address space of the inferior.  */
+  inf = find_inferior_pid (ptid_get_pid (ptid));
+
+  if (inf == NULL || inf->aspace == NULL)
+    internal_error (__FILE__, __LINE__, "\
+Can't determine the current address space of thread %s\n",
+                   target_pid_to_str (ptid));
+
+  return inf->aspace;
+}
+
 static int
 default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
 {
@@ -2361,6 +2877,12 @@ default_watchpoint_addr_within_range (struct target_ops *target,
   return addr >= start && addr < start + length;
 }
 
+static struct gdbarch *
+default_thread_architecture (struct target_ops *ops, ptid_t ptid)
+{
+  return target_gdbarch;
+}
+
 static int
 return_zero (void)
 {
@@ -2403,31 +2925,6 @@ find_run_target (void)
   return (count == 1 ? runable : NULL);
 }
 
-/* Find a single core_stratum target in the list of targets and return it.
-   If for some reason there is more than one, return NULL.  */
-
-struct target_ops *
-find_core_target (void)
-{
-  struct target_ops **t;
-  struct target_ops *runable = NULL;
-  int count;
-
-  count = 0;
-
-  for (t = target_structs; t < target_structs + target_struct_size;
-       ++t)
-    {
-      if ((*t)->to_stratum == core_stratum)
-       {
-         runable = *t;
-         ++count;
-       }
-    }
-
-  return (count == 1 ? runable : NULL);
-}
-
 /*
  * Find the next target down the stack from the specified target.
  */
@@ -2452,7 +2949,7 @@ generic_mourn_inferior (void)
   if (!ptid_equal (ptid, null_ptid))
     {
       int pid = ptid_get_pid (ptid);
-      delete_inferior (pid);
+      exit_inferior (pid);
     }
 
   breakpoint_init_inferior (inf_exited);
@@ -2506,20 +3003,37 @@ dummy_pid_to_str (struct target_ops *ops, ptid_t ptid)
   return normal_pid_to_str (ptid);
 }
 
-/* Error-catcher for target_find_memory_regions */
-static int dummy_find_memory_regions (int (*ignore1) (), void *ignore2)
+/* Error-catcher for target_find_memory_regions.  */
+static int
+dummy_find_memory_regions (find_memory_region_ftype ignore1, void *ignore2)
 {
-  error (_("No target."));
+  error (_("Command not implemented for this target."));
   return 0;
 }
 
-/* Error-catcher for target_make_corefile_notes */
-static char * dummy_make_corefile_notes (bfd *ignore1, int *ignore2)
+/* Error-catcher for target_make_corefile_notes.  */
+static char *
+dummy_make_corefile_notes (bfd *ignore1, int *ignore2)
+{
+  error (_("Command not implemented for this target."));
+  return NULL;
+}
+
+/* Error-catcher for target_get_bookmark.  */
+static gdb_byte *
+dummy_get_bookmark (char *ignore1, int ignore2)
 {
-  error (_("No target."));
+  tcomplain ();
   return NULL;
 }
 
+/* Error-catcher for target_goto_bookmark.  */
+static void
+dummy_goto_bookmark (gdb_byte *ignore, int from_tty)
+{
+  tcomplain ();
+}
+
 /* Set up the handful of non-empty slots needed by the dummy target
    vector.  */
 
@@ -2540,7 +3054,17 @@ 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_get_bookmark = dummy_get_bookmark;
+  dummy_target.to_goto_bookmark = dummy_goto_bookmark;
   dummy_target.to_xfer_partial = default_xfer_partial;
+  dummy_target.to_has_all_memory = (int (*) (struct target_ops *)) return_zero;
+  dummy_target.to_has_memory = (int (*) (struct target_ops *)) return_zero;
+  dummy_target.to_has_stack = (int (*) (struct target_ops *)) return_zero;
+  dummy_target.to_has_registers = (int (*) (struct target_ops *)) return_zero;
+  dummy_target.to_has_execution = (int (*) (struct target_ops *)) return_zero;
+  dummy_target.to_stopped_by_watchpoint = return_zero;
+  dummy_target.to_stopped_data_address =
+    (int (*) (struct target_ops *, CORE_ADDR *)) return_zero;
   dummy_target.to_magic = OPS_MAGIC;
 }
 \f
@@ -2568,6 +3092,7 @@ void
 target_attach (char *args, int from_tty)
 {
   struct target_ops *t;
+
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     {
       if (t->to_attach != NULL)        
@@ -2588,6 +3113,7 @@ int
 target_thread_alive (ptid_t ptid)
 {
   struct target_ops *t;
+
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     {
       if (t->to_thread_alive != NULL)
@@ -2610,6 +3136,7 @@ void
 target_find_new_threads (void)
 {
   struct target_ops *t;
+
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     {
       if (t->to_find_new_threads != NULL)
@@ -2623,6 +3150,18 @@ target_find_new_threads (void)
     }
 }
 
+void
+target_stop (ptid_t ptid)
+{
+  if (!may_stop)
+    {
+      warning (_("May not interrupt or stop the target, ignoring attempt"));
+      return;
+    }
+
+  (*current_target.to_stop) (ptid);
+}
+
 static void
 debug_to_post_attach (int pid)
 {
@@ -2659,9 +3198,9 @@ target_waitstatus_to_string (const struct target_waitstatus *ws)
     case TARGET_WAITKIND_EXECD:
       return xstrprintf ("%sexecd", kind_str);
     case TARGET_WAITKIND_SYSCALL_ENTRY:
-      return xstrprintf ("%ssyscall-entry", kind_str);
+      return xstrprintf ("%sentered syscall", kind_str);
     case TARGET_WAITKIND_SYSCALL_RETURN:
-      return xstrprintf ("%ssyscall-return", kind_str);
+      return xstrprintf ("%sexited syscall", kind_str);
     case TARGET_WAITKIND_SPURIOUS:
       return xstrprintf ("%sspurious", kind_str);
     case TARGET_WAITKIND_IGNORE:
@@ -2678,6 +3217,7 @@ debug_print_register (const char * func,
                      struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
+
   fprintf_unfiltered (gdb_stdlog, "%s ", func);
   if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)
       && gdbarch_register_name (gdbarch, regno) != NULL
@@ -2688,8 +3228,10 @@ debug_print_register (const char * func,
     fprintf_unfiltered (gdb_stdlog, "(%d)", regno);
   if (regno >= 0 && regno < gdbarch_num_regs (gdbarch))
     {
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
       int i, size = register_size (gdbarch, regno);
       unsigned char buf[MAX_REGISTER_SIZE];
+
       regcache_raw_collect (regcache, regno, buf);
       fprintf_unfiltered (gdb_stdlog, " = ");
       for (i = 0; i < size; i++)
@@ -2698,7 +3240,8 @@ debug_print_register (const char * func,
        }
       if (size <= sizeof (LONGEST))
        {
-         ULONGEST val = extract_unsigned_integer (buf, size);
+         ULONGEST val = extract_unsigned_integer (buf, size, byte_order);
+
          fprintf_unfiltered (gdb_stdlog, " %s %s",
                              core_addr_to_string_nz (val), plongest (val));
        }
@@ -2710,6 +3253,7 @@ void
 target_fetch_registers (struct regcache *regcache, int regno)
 {
   struct target_ops *t;
+
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     {
       if (t->to_fetch_registers != NULL)
@@ -2725,8 +3269,11 @@ target_fetch_registers (struct regcache *regcache, int regno)
 void
 target_store_registers (struct regcache *regcache, int regno)
 {
-
   struct target_ops *t;
+
+  if (!may_write_registers)
+    error (_("Writing to registers is not allowed (regno %d)"), regno);
+
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     {
       if (t->to_store_registers != NULL)
@@ -2743,6 +3290,50 @@ target_store_registers (struct regcache *regcache, int regno)
   noprocess ();
 }
 
+int
+target_core_of_thread (ptid_t ptid)
+{
+  struct target_ops *t;
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    {
+      if (t->to_core_of_thread != NULL)
+       {
+         int retval = t->to_core_of_thread (t, ptid);
+
+         if (targetdebug)
+           fprintf_unfiltered (gdb_stdlog, "target_core_of_thread (%d) = %d\n",
+                               PIDGET (ptid), retval);
+         return retval;
+       }
+    }
+
+  return -1;
+}
+
+int
+target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
+{
+  struct target_ops *t;
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    {
+      if (t->to_verify_memory != NULL)
+       {
+         int retval = t->to_verify_memory (t, data, memaddr, size);
+
+         if (targetdebug)
+           fprintf_unfiltered (gdb_stdlog, "target_verify_memory (%s, %s) = %d\n",
+                               paddress (target_gdbarch, memaddr),
+                               pulongest (size),
+                               retval);
+         return retval;
+       }
+    }
+
+  tcomplain ();
+}
+
 static void
 debug_to_prepare_to_store (struct regcache *regcache)
 {
@@ -2763,8 +3354,8 @@ deprecated_debug_xfer_memory (CORE_ADDR memaddr, bfd_byte *myaddr, int len,
 
   fprintf_unfiltered (gdb_stdlog,
                      "target_xfer_memory (%s, xxx, %d, %s, xxx) = %d",
-                     paddress (memaddr), len, write ? "write" : "read",
-                      retval);
+                     paddress (target_gdbarch, memaddr), len,
+                     write ? "write" : "read", retval);
 
   if (retval > 0)
     {
@@ -2801,29 +3392,31 @@ debug_to_files_info (struct target_ops *target)
 }
 
 static int
-debug_to_insert_breakpoint (struct bp_target_info *bp_tgt)
+debug_to_insert_breakpoint (struct gdbarch *gdbarch,
+                           struct bp_target_info *bp_tgt)
 {
   int retval;
 
-  retval = debug_target.to_insert_breakpoint (bp_tgt);
+  retval = debug_target.to_insert_breakpoint (gdbarch, bp_tgt);
 
   fprintf_unfiltered (gdb_stdlog,
-                     "target_insert_breakpoint (0x%lx, xxx) = %ld\n",
-                     (unsigned long) bp_tgt->placed_address,
+                     "target_insert_breakpoint (%s, xxx) = %ld\n",
+                     core_addr_to_string (bp_tgt->placed_address),
                      (unsigned long) retval);
   return retval;
 }
 
 static int
-debug_to_remove_breakpoint (struct bp_target_info *bp_tgt)
+debug_to_remove_breakpoint (struct gdbarch *gdbarch,
+                           struct bp_target_info *bp_tgt)
 {
   int retval;
 
-  retval = debug_target.to_remove_breakpoint (bp_tgt);
+  retval = debug_target.to_remove_breakpoint (gdbarch, bp_tgt);
 
   fprintf_unfiltered (gdb_stdlog,
-                     "target_remove_breakpoint (0x%lx, xxx) = %ld\n",
-                     (unsigned long) bp_tgt->placed_address,
+                     "target_remove_breakpoint (%s, xxx) = %ld\n",
+                     core_addr_to_string (bp_tgt->placed_address),
                      (unsigned long) retval);
   return retval;
 }
@@ -2852,10 +3445,24 @@ debug_to_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
   retval = debug_target.to_region_ok_for_hw_watchpoint (addr, len);
 
   fprintf_unfiltered (gdb_stdlog,
-                     "target_region_ok_for_hw_watchpoint (%ld, %ld) = 0x%lx\n",
-                     (unsigned long) addr,
-                     (unsigned long) len,
-                     (unsigned long) retval);
+                     "target_region_ok_for_hw_watchpoint (%s, %ld) = %s\n",
+                     core_addr_to_string (addr), (unsigned long) len,
+                     core_addr_to_string (retval));
+  return retval;
+}
+
+static int
+debug_to_can_accel_watchpoint_condition (CORE_ADDR addr, int len, int rw,
+                                        struct expression *cond)
+{
+  int retval;
+
+  retval = debug_target.to_can_accel_watchpoint_condition (addr, len, rw, cond);
+
+  fprintf_unfiltered (gdb_stdlog,
+                     "target_can_accel_watchpoint_condition (%s, %d, %d, %s) = %ld\n",
+                     core_addr_to_string (addr), len, rw,
+                     host_address_to_string (cond), (unsigned long) retval);
   return retval;
 }
 
@@ -2880,8 +3487,8 @@ debug_to_stopped_data_address (struct target_ops *target, CORE_ADDR *addr)
   retval = debug_target.to_stopped_data_address (target, addr);
 
   fprintf_unfiltered (gdb_stdlog,
-                     "target_stopped_data_address ([0x%lx]) = %ld\n",
-                     (unsigned long)*addr,
+                     "target_stopped_data_address ([%s]) = %ld\n",
+                     core_addr_to_string (*addr),
                      (unsigned long)retval);
   return retval;
 }
@@ -2897,63 +3504,69 @@ debug_to_watchpoint_addr_within_range (struct target_ops *target,
                                                         start, length);
 
   fprintf_filtered (gdb_stdlog,
-                   "target_watchpoint_addr_within_range (0x%lx, 0x%lx, %d) = %d\n",
-                   (unsigned long) addr, (unsigned long) start, length,
-                   retval);
+                   "target_watchpoint_addr_within_range (%s, %s, %d) = %d\n",
+                   core_addr_to_string (addr), core_addr_to_string (start),
+                   length, retval);
   return retval;
 }
 
 static int
-debug_to_insert_hw_breakpoint (struct bp_target_info *bp_tgt)
+debug_to_insert_hw_breakpoint (struct gdbarch *gdbarch,
+                              struct bp_target_info *bp_tgt)
 {
   int retval;
 
-  retval = debug_target.to_insert_hw_breakpoint (bp_tgt);
+  retval = debug_target.to_insert_hw_breakpoint (gdbarch, bp_tgt);
 
   fprintf_unfiltered (gdb_stdlog,
-                     "target_insert_hw_breakpoint (0x%lx, xxx) = %ld\n",
-                     (unsigned long) bp_tgt->placed_address,
+                     "target_insert_hw_breakpoint (%s, xxx) = %ld\n",
+                     core_addr_to_string (bp_tgt->placed_address),
                      (unsigned long) retval);
   return retval;
 }
 
 static int
-debug_to_remove_hw_breakpoint (struct bp_target_info *bp_tgt)
+debug_to_remove_hw_breakpoint (struct gdbarch *gdbarch,
+                              struct bp_target_info *bp_tgt)
 {
   int retval;
 
-  retval = debug_target.to_remove_hw_breakpoint (bp_tgt);
+  retval = debug_target.to_remove_hw_breakpoint (gdbarch, bp_tgt);
 
   fprintf_unfiltered (gdb_stdlog,
-                     "target_remove_hw_breakpoint (0x%lx, xxx) = %ld\n",
-                     (unsigned long) bp_tgt->placed_address,
+                     "target_remove_hw_breakpoint (%s, xxx) = %ld\n",
+                     core_addr_to_string (bp_tgt->placed_address),
                      (unsigned long) retval);
   return retval;
 }
 
 static int
-debug_to_insert_watchpoint (CORE_ADDR addr, int len, int type)
+debug_to_insert_watchpoint (CORE_ADDR addr, int len, int type,
+                           struct expression *cond)
 {
   int retval;
 
-  retval = debug_target.to_insert_watchpoint (addr, len, type);
+  retval = debug_target.to_insert_watchpoint (addr, len, type, cond);
 
   fprintf_unfiltered (gdb_stdlog,
-                     "target_insert_watchpoint (0x%lx, %d, %d) = %ld\n",
-                     (unsigned long) addr, len, type, (unsigned long) retval);
+                     "target_insert_watchpoint (%s, %d, %d, %s) = %ld\n",
+                     core_addr_to_string (addr), len, type,
+                     host_address_to_string (cond), (unsigned long) retval);
   return retval;
 }
 
 static int
-debug_to_remove_watchpoint (CORE_ADDR addr, int len, int type)
+debug_to_remove_watchpoint (CORE_ADDR addr, int len, int type,
+                           struct expression *cond)
 {
   int retval;
 
-  retval = debug_target.to_remove_watchpoint (addr, len, type);
+  retval = debug_target.to_remove_watchpoint (addr, len, type, cond);
 
   fprintf_unfiltered (gdb_stdlog,
-                     "target_remove_watchpoint (0x%lx, %d, %d) = %ld\n",
-                     (unsigned long) addr, len, type, (unsigned long) retval);
+                     "target_remove_watchpoint (%s, %d, %d, %s) = %ld\n",
+                     core_addr_to_string (addr), len, type,
+                     host_address_to_string (cond), (unsigned long) retval);
   return retval;
 }
 
@@ -3144,6 +3757,19 @@ debug_to_notice_signals (ptid_t ptid)
                       PIDGET (ptid));
 }
 
+static struct gdbarch *
+debug_to_thread_architecture (struct target_ops *ops, ptid_t ptid)
+{
+  struct gdbarch *retval;
+
+  retval = debug_target.to_thread_architecture (ops, ptid);
+
+  fprintf_unfiltered (gdb_stdlog, "target_thread_architecture (%s) = %s [%s]\n",
+                     target_pid_to_str (ptid), host_address_to_string (retval),
+                     gdbarch_bfd_arch_info (retval)->printable_name);
+  return retval;
+}
+
 static void
 debug_to_stop (ptid_t ptid)
 {
@@ -3195,6 +3821,7 @@ setup_target_debug (void)
   current_target.to_stopped_data_address = debug_to_stopped_data_address;
   current_target.to_watchpoint_addr_within_range = debug_to_watchpoint_addr_within_range;
   current_target.to_region_ok_for_hw_watchpoint = debug_to_region_ok_for_hw_watchpoint;
+  current_target.to_can_accel_watchpoint_condition = debug_to_can_accel_watchpoint_condition;
   current_target.to_terminal_init = debug_to_terminal_init;
   current_target.to_terminal_inferior = debug_to_terminal_inferior;
   current_target.to_terminal_ours_for_output = debug_to_terminal_ours_for_output;
@@ -3217,6 +3844,7 @@ setup_target_debug (void)
   current_target.to_stop = debug_to_stop;
   current_target.to_rcmd = debug_to_rcmd;
   current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file;
+  current_target.to_thread_architecture = debug_to_thread_architecture;
 }
 \f
 
@@ -3264,7 +3892,7 @@ static void
 set_maintenance_target_async_permitted (char *args, int from_tty,
                                        struct cmd_list_element *c)
 {
-  if (target_has_execution)
+  if (have_live_inferiors ())
     {
       target_async_permitted_1 = target_async_permitted;
       error (_("Cannot change this setting while the inferior is running."));
@@ -3282,6 +3910,62 @@ show_maintenance_target_async_permitted (struct ui_file *file, int from_tty,
 Controlling the inferior in asynchronous mode is %s.\n"), value);
 }
 
+/* Temporary copies of permission settings.  */
+
+static int may_write_registers_1 = 1;
+static int may_write_memory_1 = 1;
+static int may_insert_breakpoints_1 = 1;
+static int may_insert_tracepoints_1 = 1;
+static int may_insert_fast_tracepoints_1 = 1;
+static int may_stop_1 = 1;
+
+/* Make the user-set values match the real values again.  */
+
+void
+update_target_permissions (void)
+{
+  may_write_registers_1 = may_write_registers;
+  may_write_memory_1 = may_write_memory;
+  may_insert_breakpoints_1 = may_insert_breakpoints;
+  may_insert_tracepoints_1 = may_insert_tracepoints;
+  may_insert_fast_tracepoints_1 = may_insert_fast_tracepoints;
+  may_stop_1 = may_stop;
+}
+
+/* The one function handles (most of) the permission flags in the same
+   way.  */
+
+static void
+set_target_permissions (char *args, int from_tty,
+                       struct cmd_list_element *c)
+{
+  if (target_has_execution)
+    {
+      update_target_permissions ();
+      error (_("Cannot change this setting while the inferior is running."));
+    }
+
+  /* Make the real values match the user-changed values.  */
+  may_write_registers = may_write_registers_1;
+  may_insert_breakpoints = may_insert_breakpoints_1;
+  may_insert_tracepoints = may_insert_tracepoints_1;
+  may_insert_fast_tracepoints = may_insert_fast_tracepoints_1;
+  may_stop = may_stop_1;
+  update_observer_mode ();
+}
+
+/* Set memory write permission independently of observer mode.  */
+
+static void
+set_write_memory_permission (char *args, int from_tty,
+                       struct cmd_list_element *c)
+{
+  /* Make the real values match the user-changed values.  */
+  may_write_memory = may_write_memory_1;
+  update_observer_mode ();
+}
+
+
 void
 initialize_targets (void)
 {
@@ -3329,5 +4013,71 @@ Tells gdb whether to control the inferior in asynchronous mode."),
                           &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."), _("\
+Show permission to write into registers."), _("\
+When this permission is on, GDB may write into the target's registers.\n\
+Otherwise, any sort of write attempt will result in an error."),
+                          set_target_permissions, NULL,
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("may-write-memory", class_support,
+                          &may_write_memory_1, _("\
+Set permission to write into target memory."), _("\
+Show permission to write into target memory."), _("\
+When this permission is on, GDB may write into the target's memory.\n\
+Otherwise, any sort of write attempt will result in an error."),
+                          set_write_memory_permission, NULL,
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("may-insert-breakpoints", class_support,
+                          &may_insert_breakpoints_1, _("\
+Set permission to insert breakpoints in the target."), _("\
+Show permission to insert breakpoints in the target."), _("\
+When this permission is on, GDB may insert breakpoints in the program.\n\
+Otherwise, any sort of insertion attempt will result in an error."),
+                          set_target_permissions, NULL,
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("may-insert-tracepoints", class_support,
+                          &may_insert_tracepoints_1, _("\
+Set permission to insert tracepoints in the target."), _("\
+Show permission to insert tracepoints in the target."), _("\
+When this permission is on, GDB may insert tracepoints in the program.\n\
+Otherwise, any sort of insertion attempt will result in an error."),
+                          set_target_permissions, NULL,
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("may-insert-fast-tracepoints", class_support,
+                          &may_insert_fast_tracepoints_1, _("\
+Set permission to insert fast tracepoints in the target."), _("\
+Show permission to insert fast tracepoints in the target."), _("\
+When this permission is on, GDB may insert fast tracepoints.\n\
+Otherwise, any sort of insertion attempt will result in an error."),
+                          set_target_permissions, NULL,
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("may-interrupt", class_support,
+                          &may_stop_1, _("\
+Set permission to interrupt or signal the target."), _("\
+Show permission to interrupt or signal the target."), _("\
+When this permission is on, GDB may interrupt/stop the target's execution.\n\
+Otherwise, any attempt to interrupt or stop will be ignored."),
+                          set_target_permissions, NULL,
+                          &setlist, &showlist);
+
+
   target_dcache = dcache_init ();
 }
This page took 0.049744 seconds and 4 git commands to generate.