daily update
[deliverable/binutils-gdb.git] / gdb / target.c
index 7861372fc78aec29df371f54c26f4d199d532904..944d601659f9860dece77ea34a104d5e900613d8 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
+   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    Contributed by Cygnus Support.
@@ -10,7 +10,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -19,9 +19,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include <errno.h>
@@ -39,6 +37,9 @@
 #include "regcache.h"
 #include "gdb_assert.h"
 #include "gdbcore.h"
+#include "exceptions.h"
+#include "target-descriptions.h"
+#include "gdb_stdint.h"
 
 static void target_info (char *, int);
 
@@ -104,11 +105,11 @@ static void debug_to_resume (ptid_t, int, enum target_signal);
 
 static ptid_t debug_to_wait (ptid_t, struct target_waitstatus *);
 
-static void debug_to_fetch_registers (int);
+static void debug_to_fetch_registers (struct regcache *, int);
 
-static void debug_to_store_registers (int);
+static void debug_to_store_registers (struct regcache *, int);
 
-static void debug_to_prepare_to_store (void);
+static void debug_to_prepare_to_store (struct regcache *);
 
 static void debug_to_files_info (struct target_ops *);
 
@@ -167,7 +168,7 @@ static void debug_to_stop (void);
 struct target_ops deprecated_child_ops;
 
 /* Pointer to array of target architecture structures; the size of the
-   array; the current index into the array; the allocated size of the 
+   array; the current index into the array; the allocated size of the
    array.  */
 struct target_ops **target_structs;
 unsigned target_struct_size;
@@ -203,6 +204,11 @@ int attach_flag;
 
 static int trust_readonly = 0;
 
+/* Nonzero if we should show true memory content including
+   memory breakpoint inserted by gdb.  */
+
+static int show_memory_breakpoints = 0;
+
 /* Non-zero if we want to see trace of target level stuff.  */
 
 static int targetdebug = 0;
@@ -377,7 +383,7 @@ update_current_target (void)
 {
   struct target_ops *t;
 
-  /* First, reset curren'ts contents.  */
+  /* First, reset current's contents.  */
   memset (&current_target, 0, sizeof (current_target));
 
 #define INHERIT(FIELD, TARGET) \
@@ -411,6 +417,7 @@ update_current_target (void)
       INHERIT (to_remove_watchpoint, t);
       INHERIT (to_stopped_data_address, t);
       INHERIT (to_stopped_by_watchpoint, t);
+      INHERIT (to_have_steppable_watchpoint, t);
       INHERIT (to_have_continuable_watchpoint, t);
       INHERIT (to_region_ok_for_hw_watchpoint, t);
       INHERIT (to_terminal_init, t);
@@ -432,7 +439,6 @@ update_current_target (void)
       /* Do not inherit to_follow_fork.  */
       INHERIT (to_insert_exec_catchpoint, t);
       INHERIT (to_remove_exec_catchpoint, t);
-      INHERIT (to_reported_exec_events_per_exec_call, t);
       INHERIT (to_has_exited, t);
       INHERIT (to_mourn_inferior, t);
       INHERIT (to_can_run, t);
@@ -444,9 +450,8 @@ update_current_target (void)
       INHERIT (to_stop, t);
       /* Do not inherit to_xfer_partial.  */
       INHERIT (to_rcmd, t);
-      INHERIT (to_enable_exception_callback, t);
-      INHERIT (to_get_current_exception_event, t);
       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);
@@ -459,11 +464,15 @@ update_current_target (void)
       INHERIT (to_can_async_p, t);
       INHERIT (to_is_async_p, t);
       INHERIT (to_async, t);
-      INHERIT (to_async_mask_value, t);
+      INHERIT (to_async_mask, t);
       INHERIT (to_find_memory_regions, t);
       INHERIT (to_make_corefile_notes, t);
       INHERIT (to_get_thread_local_address, t);
+      /* Do not inherit to_read_description.  */
       INHERIT (to_magic, t);
+      /* Do not inherit to_memory_map.  */
+      /* Do not inherit to_flash_erase.  */
+      /* Do not inherit to_flash_done.  */
     }
 #undef INHERIT
 
@@ -475,44 +484,44 @@ update_current_target (void)
   if (!current_target.field)               \
     current_target.field = value
 
-  de_fault (to_open, 
-           (void (*) (char *, int)) 
+  de_fault (to_open,
+           (void (*) (char *, int))
            tcomplain);
-  de_fault (to_close, 
-           (void (*) (int)) 
+  de_fault (to_close,
+           (void (*) (int))
            target_ignore);
-  de_fault (to_attach, 
+  de_fault (to_attach,
            maybe_kill_then_attach);
-  de_fault (to_post_attach, 
-           (void (*) (int)) 
+  de_fault (to_post_attach,
+           (void (*) (int))
            target_ignore);
-  de_fault (to_detach, 
-           (void (*) (char *, int)) 
+  de_fault (to_detach,
+           (void (*) (char *, int))
            target_ignore);
-  de_fault (to_resume, 
-           (void (*) (ptid_t, int, enum target_signal)) 
+  de_fault (to_resume,
+           (void (*) (ptid_t, int, enum target_signal))
            noprocess);
-  de_fault (to_wait, 
-           (ptid_t (*) (ptid_t, struct target_waitstatus *)) 
+  de_fault (to_wait,
+           (ptid_t (*) (ptid_t, struct target_waitstatus *))
            noprocess);
-  de_fault (to_fetch_registers, 
-           (void (*) (int)) 
+  de_fault (to_fetch_registers,
+           (void (*) (struct regcache *, int))
            target_ignore);
-  de_fault (to_store_registers, 
-           (void (*) (int)) 
+  de_fault (to_store_registers,
+           (void (*) (struct regcache *, int))
            noprocess);
-  de_fault (to_prepare_to_store, 
-           (void (*) (void)) 
+  de_fault (to_prepare_to_store,
+           (void (*) (struct regcache *))
            noprocess);
-  de_fault (deprecated_xfer_memory, 
-           (int (*) (CORE_ADDR, gdb_byte *, int, int, struct mem_attrib *, struct target_ops *)) 
+  de_fault (deprecated_xfer_memory,
+           (int (*) (CORE_ADDR, gdb_byte *, int, int, struct mem_attrib *, struct target_ops *))
            nomemory);
-  de_fault (to_files_info, 
-           (void (*) (struct target_ops *)) 
+  de_fault (to_files_info,
+           (void (*) (struct target_ops *))
            target_ignore);
-  de_fault (to_insert_breakpoint, 
+  de_fault (to_insert_breakpoint,
            memory_insert_breakpoint);
-  de_fault (to_remove_breakpoint, 
+  de_fault (to_remove_breakpoint,
            memory_remove_breakpoint);
   de_fault (to_can_use_hw_breakpoint,
            (int (*) (int, int, int))
@@ -537,112 +546,160 @@ update_current_target (void)
            return_zero);
   de_fault (to_region_ok_for_hw_watchpoint,
            default_region_ok_for_hw_watchpoint);
-  de_fault (to_terminal_init, 
-           (void (*) (void)) 
+  de_fault (to_terminal_init,
+           (void (*) (void))
            target_ignore);
-  de_fault (to_terminal_inferior, 
-           (void (*) (void)) 
+  de_fault (to_terminal_inferior,
+           (void (*) (void))
            target_ignore);
-  de_fault (to_terminal_ours_for_output, 
-           (void (*) (void)) 
+  de_fault (to_terminal_ours_for_output,
+           (void (*) (void))
            target_ignore);
-  de_fault (to_terminal_ours, 
-           (void (*) (void)) 
+  de_fault (to_terminal_ours,
+           (void (*) (void))
            target_ignore);
-  de_fault (to_terminal_save_ours, 
-           (void (*) (void)) 
+  de_fault (to_terminal_save_ours,
+           (void (*) (void))
            target_ignore);
-  de_fault (to_terminal_info, 
+  de_fault (to_terminal_info,
            default_terminal_info);
-  de_fault (to_kill, 
-           (void (*) (void)) 
+  de_fault (to_kill,
+           (void (*) (void))
            noprocess);
-  de_fault (to_load, 
-           (void (*) (char *, int)) 
+  de_fault (to_load,
+           (void (*) (char *, int))
            tcomplain);
-  de_fault (to_lookup_symbol, 
-           (int (*) (char *, CORE_ADDR *)) 
+  de_fault (to_lookup_symbol,
+           (int (*) (char *, CORE_ADDR *))
            nosymbol);
-  de_fault (to_create_inferior, 
+  de_fault (to_create_inferior,
            maybe_kill_then_create_inferior);
-  de_fault (to_post_startup_inferior, 
-           (void (*) (ptid_t)) 
+  de_fault (to_post_startup_inferior,
+           (void (*) (ptid_t))
            target_ignore);
-  de_fault (to_acknowledge_created_inferior, 
-           (void (*) (int)) 
+  de_fault (to_acknowledge_created_inferior,
+           (void (*) (int))
            target_ignore);
-  de_fault (to_insert_fork_catchpoint, 
-           (void (*) (int)) 
+  de_fault (to_insert_fork_catchpoint,
+           (void (*) (int))
            tcomplain);
-  de_fault (to_remove_fork_catchpoint, 
-           (int (*) (int)) 
+  de_fault (to_remove_fork_catchpoint,
+           (int (*) (int))
            tcomplain);
-  de_fault (to_insert_vfork_catchpoint, 
-           (void (*) (int)) 
+  de_fault (to_insert_vfork_catchpoint,
+           (void (*) (int))
            tcomplain);
-  de_fault (to_remove_vfork_catchpoint, 
-           (int (*) (int)) 
+  de_fault (to_remove_vfork_catchpoint,
+           (int (*) (int))
            tcomplain);
-  de_fault (to_insert_exec_catchpoint, 
-           (void (*) (int)) 
+  de_fault (to_insert_exec_catchpoint,
+           (void (*) (int))
            tcomplain);
-  de_fault (to_remove_exec_catchpoint, 
-           (int (*) (int)) 
+  de_fault (to_remove_exec_catchpoint,
+           (int (*) (int))
            tcomplain);
-  de_fault (to_reported_exec_events_per_exec_call, 
-           (int (*) (void)) 
-           return_one);
-  de_fault (to_has_exited, 
-           (int (*) (int, int, int *)) 
+  de_fault (to_has_exited,
+           (int (*) (int, int, int *))
            return_zero);
-  de_fault (to_mourn_inferior, 
-           (void (*) (void)) 
+  de_fault (to_mourn_inferior,
+           (void (*) (void))
            noprocess);
-  de_fault (to_can_run, 
+  de_fault (to_can_run,
            return_zero);
-  de_fault (to_notice_signals, 
-           (void (*) (ptid_t)) 
+  de_fault (to_notice_signals,
+           (void (*) (ptid_t))
            target_ignore);
-  de_fault (to_thread_alive, 
-           (int (*) (ptid_t)) 
+  de_fault (to_thread_alive,
+           (int (*) (ptid_t))
            return_zero);
-  de_fault (to_find_new_threads, 
-           (void (*) (void)) 
+  de_fault (to_find_new_threads,
+           (void (*) (void))
            target_ignore);
-  de_fault (to_extra_thread_info, 
-           (char *(*) (struct thread_info *)) 
+  de_fault (to_extra_thread_info,
+           (char *(*) (struct thread_info *))
            return_zero);
-  de_fault (to_stop, 
-           (void (*) (void)) 
+  de_fault (to_stop,
+           (void (*) (void))
            target_ignore);
   current_target.to_xfer_partial = current_xfer_partial;
-  de_fault (to_rcmd, 
-           (void (*) (char *, struct ui_file *)) 
+  de_fault (to_rcmd,
+           (void (*) (char *, struct ui_file *))
            tcomplain);
-  de_fault (to_enable_exception_callback, 
-           (struct symtab_and_line * (*) (enum exception_event_kind, int)) 
-           nosupport_runtime);
-  de_fault (to_get_current_exception_event, 
-           (struct exception_event_record * (*) (void)) 
-           nosupport_runtime);
-  de_fault (to_pid_to_exec_file, 
-           (char *(*) (int)) 
+  de_fault (to_pid_to_exec_file,
+           (char *(*) (int))
            return_zero);
-  de_fault (to_can_async_p, 
-           (int (*) (void)) 
+  de_fault (to_can_async_p,
+           (int (*) (void))
            return_zero);
-  de_fault (to_is_async_p, 
-           (int (*) (void)) 
+  de_fault (to_is_async_p,
+           (int (*) (void))
            return_zero);
-  de_fault (to_async, 
-           (void (*) (void (*) (enum inferior_event_type, void*), void*)) 
+  de_fault (to_async,
+           (void (*) (void (*) (enum inferior_event_type, void*), void*))
            tcomplain);
+  de_fault (to_async_mask,
+           (int (*) (int))
+           return_one);
+  current_target.to_read_description = NULL;
 #undef de_fault
 
   /* Finally, position the target-stack beneath the squashed
      "current_target".  That way code looking for a non-inherited
      target method can quickly and simply find it.  */
   current_target.beneath = target_stack;
+
+  if (targetdebug)
+    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,
@@ -696,14 +753,11 @@ push_target (struct target_ops *t)
 
   update_current_target ();
 
-  if (targetdebug)
-    setup_target_debug ();
-
   /* Not on top?  */
   return (t != target_stack);
 }
 
-/* Remove a target_ops vector from the stack, wherever it may be. 
+/* Remove a target_ops vector from the stack, wherever it may be.
    Return how many times it was removed (0 or 1).  */
 
 int
@@ -755,6 +809,92 @@ pop_target (void)
   internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
 }
 
+/* Using the objfile specified in OBJFILE, find the address for the
+   current thread's thread-local storage with offset OFFSET.  */
+CORE_ADDR
+target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset)
+{
+  volatile CORE_ADDR addr = 0;
+
+  if (target_get_thread_local_address_p ()
+      && gdbarch_fetch_tls_load_module_address_p (current_gdbarch))
+    {
+      ptid_t ptid = inferior_ptid;
+      volatile struct gdb_exception ex;
+
+      TRY_CATCH (ex, RETURN_MASK_ALL)
+       {
+         CORE_ADDR lm_addr;
+         
+         /* Fetch the load module address for this objfile.  */
+         lm_addr = gdbarch_fetch_tls_load_module_address (current_gdbarch,
+                                                          objfile);
+         /* If it's 0, throw the appropriate exception.  */
+         if (lm_addr == 0)
+           throw_error (TLS_LOAD_MODULE_NOT_FOUND_ERROR,
+                        _("TLS load module not found"));
+
+         addr = target_get_thread_local_address (ptid, lm_addr, offset);
+       }
+      /* If an error occurred, print TLS related messages here.  Otherwise,
+         throw the error to some higher catcher.  */
+      if (ex.reason < 0)
+       {
+         int objfile_is_library = (objfile->flags & OBJF_SHARED);
+
+         switch (ex.error)
+           {
+           case TLS_NO_LIBRARY_SUPPORT_ERROR:
+             error (_("Cannot find thread-local variables in this thread library."));
+             break;
+           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);
+             else
+               error (_("Cannot find executable file `%s' in dynamic"
+                        " linker's load module list"), objfile->name);
+             break;
+           case TLS_NOT_ALLOCATED_YET_ERROR:
+             if (objfile_is_library)
+               error (_("The inferior has not yet allocated storage for"
+                        " thread-local variables in\n"
+                        "the shared library `%s'\n"
+                        "for %s"),
+                      objfile->name, 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));
+             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);
+             else
+               error (_("Cannot find thread-local storage for %s, "
+                        "executable file %s:\n%s"),
+                      target_pid_to_str (ptid),
+                      objfile->name, ex.message);
+             break;
+           default:
+             throw_exception (ex);
+             break;
+           }
+       }
+    }
+  /* It wouldn't be wrong here to try a gdbarch method, too; finding
+     TLS is an ABI-specific thing.  But we don't do that yet.  */
+  else
+    error (_("Cannot find thread-local variables on this target"));
+
+  return addr;
+}
+
 #undef MIN
 #define MIN(A, B) (((A) <= (B)) ? (A) : (B))
 
@@ -775,6 +915,8 @@ target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
   char *bufptr;
   unsigned int nbytes_read = 0;
 
+  gdb_assert (string);
+
   /* Small for testing.  */
   buffer_allocated = 4;
   buffer = xmalloc (buffer_allocated);
@@ -824,10 +966,9 @@ target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
       nbytes_read += tlen;
     }
 done:
+  *string = buffer;
   if (errnop != NULL)
     *errnop = errcode;
-  if (string != NULL)
-    *string = buffer;
   return nbytes_read;
 }
 
@@ -873,9 +1014,18 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
        return xfer_memory (memaddr, readbuf, len, 0, NULL, ops);
     }
 
+  /* Likewise for accesses to unmapped overlay sections.  */
+  if (readbuf != NULL && overlay_debugging)
+    {
+      asection *section = find_pc_overlay (memaddr);
+      if (pc_in_unmapped_range (memaddr, section))
+       return xfer_memory (memaddr, readbuf, len, 0, NULL, ops);
+    }
+
   /* Try GDB's internal data cache.  */
   region = lookup_mem_region (memaddr);
-  if (memaddr + len < region->hi)
+  /* region->hi == 0 means there's no upper bound.  */
+  if (memaddr + len < region->hi || region->hi == 0)
     reg_len = len;
   else
     reg_len = region->hi - memaddr;
@@ -891,6 +1041,15 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
       if (readbuf != NULL)
        return -1;
       break;
+
+    case MEM_FLASH:
+      /* We only support writing to flash during "load" for now.  */
+      if (writebuf != NULL)
+       error (_("Writing to flash memory forbidden in this context"));
+      break;
+
+    case MEM_NONE:
+      return -1;
     }
 
   if (region->attrib.cache)
@@ -910,7 +1069,11 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
       if (res <= 0)
        return -1;
       else
-       return res;
+       {
+         if (readbuf && !show_memory_breakpoints)
+           breakpoint_restore_shadows (readbuf, memaddr, reg_len);
+         return res;
+       }
     }
 
   /* If none of those methods found the memory we wanted, fall back
@@ -926,19 +1089,43 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
   do
     {
       res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
-                                 readbuf, writebuf, memaddr, len);
+                                 readbuf, writebuf, memaddr, reg_len);
       if (res > 0)
-       return res;
+       break;
+
+      /* We want to continue past core files to executables, but not
+        past a running target's memory.  */
+      if (ops->to_has_all_memory)
+       break;
 
       ops = ops->beneath;
     }
   while (ops != NULL);
 
+  if (readbuf && !show_memory_breakpoints)
+    breakpoint_restore_shadows (readbuf, memaddr, reg_len);
+
   /* If we still haven't got anything, return the last error.  We
      give up.  */
   return res;
 }
 
+static void
+restore_show_memory_breakpoints (void *arg)
+{
+  show_memory_breakpoints = (uintptr_t) arg;
+}
+
+struct cleanup *
+make_show_memory_breakpoints_cleanup (int show)
+{
+  int current = show_memory_breakpoints;
+  show_memory_breakpoints = show;
+
+  return make_cleanup (restore_show_memory_breakpoints,
+                      (void *) (uintptr_t) current);
+}
+
 static LONGEST
 target_xfer_partial (struct target_ops *ops,
                     enum target_object object, const char *annex,
@@ -986,7 +1173,7 @@ target_xfer_partial (struct target_ops *ops,
       if (retval > 0 && myaddr != NULL)
        {
          int i;
-         
+
          fputs_unfiltered (", bytes =", gdb_stdlog);
          for (i = 0; i < retval; i++)
            {
@@ -999,11 +1186,11 @@ target_xfer_partial (struct target_ops *ops,
                    }
                  fprintf_unfiltered (gdb_stdlog, "\n");
                }
-             
+
              fprintf_unfiltered (gdb_stdlog, " %02x", myaddr[i] & 0xff);
            }
        }
-      
+
       fputc_unfiltered ('\n', gdb_stdlog);
     }
   return retval;
@@ -1040,6 +1227,89 @@ target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
     return EIO;
 }
 
+/* Fetch the target's memory map.  */
+
+VEC(mem_region_s) *
+target_memory_map (void)
+{
+  VEC(mem_region_s) *result;
+  struct mem_region *last_one, *this_one;
+  int ix;
+  struct target_ops *t;
+
+  if (targetdebug)
+    fprintf_unfiltered (gdb_stdlog, "target_memory_map ()\n");
+
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    if (t->to_memory_map != NULL)
+      break;
+
+  if (t == NULL)
+    return NULL;
+
+  result = t->to_memory_map (t);
+  if (result == NULL)
+    return NULL;
+
+  qsort (VEC_address (mem_region_s, result),
+        VEC_length (mem_region_s, result),
+        sizeof (struct mem_region), mem_region_cmp);
+
+  /* Check that regions do not overlap.  Simultaneously assign
+     a numbering for the "mem" commands to use to refer to
+     each region.  */
+  last_one = NULL;
+  for (ix = 0; VEC_iterate (mem_region_s, result, ix, this_one); ix++)
+    {
+      this_one->number = ix;
+
+      if (last_one && last_one->hi > this_one->lo)
+       {
+         warning (_("Overlapping regions in memory map: ignoring"));
+         VEC_free (mem_region_s, result);
+         return NULL;
+       }
+      last_one = this_one;
+    }
+
+  return result;
+}
+
+void
+target_flash_erase (ULONGEST address, LONGEST length)
+{
+  struct target_ops *t;
+
+  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;
+       }
+
+  tcomplain ();
+}
+
+void
+target_flash_done (void)
+{
+  struct target_ops *t;
+
+  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;
+       }
+
+  tcomplain ();
+}
+
 #ifndef target_stopped_data_address_p
 int
 target_stopped_data_address_p (struct target_ops *target)
@@ -1068,7 +1338,7 @@ Mode for reading from readonly sections is %s.\n"),
 
 static LONGEST
 default_xfer_partial (struct target_ops *ops, enum target_object object,
-                     const char *annex, gdb_byte *readbuf, 
+                     const char *annex, gdb_byte *readbuf,
                      const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
 {
   if (object == TARGET_OBJECT_MEMORY
@@ -1088,8 +1358,8 @@ default_xfer_partial (struct target_ops *ops, enum target_object object,
          do_cleanups (cleanup);
        }
       if (readbuf != NULL)
-       xfered = ops->deprecated_xfer_memory (offset, readbuf, len, 0/*read*/,
-                                             NULL, ops);
+       xfered = ops->deprecated_xfer_memory (offset, readbuf, len, 
+                                             0/*read*/, NULL, ops);
       if (xfered > 0)
        return xfered;
       else if (xfered == 0 && errno == 0)
@@ -1180,6 +1450,11 @@ target_write_with_progress (struct target_ops *ops,
                            void (*progress) (ULONGEST, void *), void *baton)
 {
   LONGEST xfered = 0;
+
+  /* Give the progress callback a chance to set up.  */
+  if (progress)
+    (*progress) (0, baton);
+
   while (xfered < len)
     {
       LONGEST xfer = target_write_partial (ops, object, annex,
@@ -1356,6 +1631,20 @@ target_info (char *args, int from_tty)
     }
 }
 
+/* This function is called before any new inferior is created, e.g.
+   by running a program, attaching, or connecting to a target.
+   It cleans up any state from previous invocations which might
+   change between runs.  This is a subset of what target_preopen
+   resets (things which might change between targets).  */
+
+void
+target_pre_inferior (int from_tty)
+{
+  invalidate_target_mem_regions ();
+
+  target_clear_description ();
+}
+
 /* This is to be called by the open routine before it does
    anything.  */
 
@@ -1378,6 +1667,8 @@ target_preopen (int from_tty)
 
   if (target_has_execution)
     pop_target ();
+
+  target_pre_inferior (from_tty);
 }
 
 /* Detach a target after doing deferred register stores.  */
@@ -1385,6 +1676,10 @@ target_preopen (int from_tty)
 void
 target_detach (char *args, int from_tty)
 {
+  /* If we're in breakpoints-always-inserted mode, have to
+     remove them before detaching.  */
+  remove_breakpoints ();
+
   (current_target.to_detach) (args, from_tty);
 }
 
@@ -1393,6 +1688,10 @@ target_disconnect (char *args, int from_tty)
 {
   struct target_ops *t;
 
+  /* If we're in breakpoints-always-inserted mode, have to
+     remove them before disconnecting.  */  
+  remove_breakpoints ();
+
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     if (t->to_disconnect != NULL)
        {
@@ -1406,14 +1705,6 @@ target_disconnect (char *args, int from_tty)
   tcomplain ();
 }
 
-int
-target_async_mask (int mask)
-{
-  int saved_async_masked_status = target_async_mask_value;
-  target_async_mask_value = mask;
-  return saved_async_masked_status;
-}
-
 /* Look through the list of possible targets for a target that can
    follow forks.  */
 
@@ -1439,11 +1730,68 @@ target_follow_fork (int follow_child)
                  "could not find a target to follow fork");
 }
 
+/* Look for a target which can describe architectural features, starting
+   from TARGET.  If we find one, return its description.  */
+
+const struct target_desc *
+target_read_description (struct target_ops *target)
+{
+  struct target_ops *t;
+
+  for (t = target; t != NULL; t = t->beneath)
+    if (t->to_read_description != NULL)
+      {
+       const struct target_desc *tdesc;
+
+       tdesc = t->to_read_description (t);
+       if (tdesc)
+         return tdesc;
+      }
+
+  return NULL;
+}
+
+/* Look through the currently pushed targets.  If none of them will
+   be able to restart the currently running process, issue an error
+   message.  */
+
+void
+target_require_runnable (void)
+{
+  struct target_ops *t;
+
+  for (t = target_stack; t != NULL; t = t->beneath)
+    {
+      /* If this target knows how to create a new program, then
+        assume we will still be able to after killing the current
+        one.  Either killing and mourning will not pop T, or else
+        find_default_run_target will find it again.  */
+      if (t->to_create_inferior != NULL)
+       return;
+
+      /* 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)
+       continue;
+
+      error (_("\
+The \"%s\" target does not support \"run\".  Try \"help target\" or \"continue\"."),
+            t->to_shortname);
+    }
+
+  /* This function is only called if the target is running.  In that
+     case there should have been a process_stratum target and it
+     should either know how to create inferiors, or not... */
+  internal_error (__FILE__, __LINE__, "No targets found");
+}
+
 /* Look through the list of possible targets for a target that can
    execute a run or attach command without any other data.  This is
    used to locate the default process stratum.
 
-   Result is always valid (error() is called for errors).  */
+   If DO_MESG is not NULL, the result is always valid (error() is
+   called for errors); else, return NULL on error.  */
 
 static struct target_ops *
 find_default_run_target (char *do_mesg)
@@ -1465,7 +1813,12 @@ find_default_run_target (char *do_mesg)
     }
 
   if (count != 1)
-    error (_("Don't know how to %s.  Try \"help target\"."), do_mesg);
+    {
+      if (do_mesg)
+       error (_("Don't know how to %s.  Try \"help target\"."), do_mesg);
+      else
+       return NULL;
+    }
 
   return runable;
 }
@@ -1491,6 +1844,36 @@ find_default_create_inferior (char *exec_file, char *allargs, char **env,
   return;
 }
 
+int
+find_default_can_async_p (void)
+{
+  struct target_ops *t;
+
+  /* This may be called before the target is pushed on the stack;
+     look for the default process stratum.  If there's none, gdb isn't
+     configured with a native debugger, and target remote isn't
+     connected yet.  */
+  t = find_default_run_target (NULL);
+  if (t && t->to_can_async_p)
+    return (t->to_can_async_p) ();
+  return 0;
+}
+
+int
+find_default_is_async_p (void)
+{
+  struct target_ops *t;
+
+  /* This may be called before the target is pushed on the stack;
+     look for the default process stratum.  If there's none, gdb isn't
+     configured with a native debugger, and target remote isn't
+     connected yet.  */
+  t = find_default_run_target (NULL);
+  if (t && t->to_is_async_p)
+    return (t->to_is_async_p) ();
+  return 0;
+}
+
 static int
 default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
 {
@@ -1547,7 +1930,7 @@ target_resize_to_sections (struct target_ops *target, int num_added)
 
   /* Check to see if anyone else was pointing to this structure.
      If old_value was null, then no one was. */
-     
+
   if (old_value)
     {
       for (t = target_structs; t < target_structs + target_struct_size;
@@ -1567,7 +1950,7 @@ target_resize_to_sections (struct target_ops *target, int num_added)
          current_target.to_sections_end = target->to_sections_end;
        }
     }
-  
+
   return old_count;
 
 }
@@ -1691,19 +2074,12 @@ generic_mourn_inferior (void)
     deprecated_detach_hook ();
 }
 \f
-/* Helper function for child_wait and the Lynx derivatives of child_wait.
+/* Helper function for child_wait and the derivatives of child_wait.
    HOSTSTATUS is the waitstatus from wait() or the equivalent; store our
    translation of that in OURSTATUS.  */
 void
 store_waitstatus (struct target_waitstatus *ourstatus, int hoststatus)
 {
-#ifdef CHILD_SPECIAL_WAITSTATUS
-  /* CHILD_SPECIAL_WAITSTATUS should return nonzero and set *OURSTATUS
-     if it wants to deal with hoststatus.  */
-  if (CHILD_SPECIAL_WAITSTATUS (ourstatus, hoststatus))
-    return;
-#endif
-
   if (WIFEXITED (hoststatus))
     {
       ourstatus->kind = TARGET_WAITKIND_EXITED;
@@ -1762,6 +2138,8 @@ init_dummy_target (void)
   dummy_target.to_doc = "";
   dummy_target.to_attach = find_default_attach;
   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;
   dummy_target.to_pid_to_str = normal_pid_to_str;
   dummy_target.to_stratum = dummy_stratum;
   dummy_target.to_find_memory_regions = dummy_find_memory_regions;
@@ -1878,53 +2256,58 @@ debug_to_wait (ptid_t ptid, struct target_waitstatus *status)
 }
 
 static void
-debug_print_register (const char * func, int regno)
+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 < NUM_REGS + NUM_PSEUDO_REGS
-      && REGISTER_NAME (regno) != NULL && REGISTER_NAME (regno)[0] != '\0')
-    fprintf_unfiltered (gdb_stdlog, "(%s)", REGISTER_NAME (regno));
+  if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)
+                           + gdbarch_num_pseudo_regs (gdbarch)
+      && gdbarch_register_name (gdbarch, regno) != NULL
+      && gdbarch_register_name (gdbarch, regno)[0] != '\0')
+    fprintf_unfiltered (gdb_stdlog, "(%s)",
+                       gdbarch_register_name (gdbarch, regno));
   else
     fprintf_unfiltered (gdb_stdlog, "(%d)", regno);
   if (regno >= 0)
     {
-      int i;
+      int i, size = register_size (gdbarch, regno);
       unsigned char buf[MAX_REGISTER_SIZE];
-      deprecated_read_register_gen (regno, buf);
+      regcache_cooked_read (regcache, regno, buf);
       fprintf_unfiltered (gdb_stdlog, " = ");
-      for (i = 0; i < register_size (current_gdbarch, regno); i++)
+      for (i = 0; i < size; i++)
        {
          fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
        }
-      if (register_size (current_gdbarch, regno) <= sizeof (LONGEST))
+      if (size <= sizeof (LONGEST))
        {
+         ULONGEST val = extract_unsigned_integer (buf, size);
          fprintf_unfiltered (gdb_stdlog, " 0x%s %s",
-                             paddr_nz (read_register (regno)),
-                             paddr_d (read_register (regno)));
+                             paddr_nz (val), paddr_d (val));
        }
     }
   fprintf_unfiltered (gdb_stdlog, "\n");
 }
 
 static void
-debug_to_fetch_registers (int regno)
+debug_to_fetch_registers (struct regcache *regcache, int regno)
 {
-  debug_target.to_fetch_registers (regno);
-  debug_print_register ("target_fetch_registers", regno);
+  debug_target.to_fetch_registers (regcache, regno);
+  debug_print_register ("target_fetch_registers", regcache, regno);
 }
 
 static void
-debug_to_store_registers (int regno)
+debug_to_store_registers (struct regcache *regcache, int regno)
 {
-  debug_target.to_store_registers (regno);
-  debug_print_register ("target_store_registers", regno);
+  debug_target.to_store_registers (regcache, regno);
+  debug_print_register ("target_store_registers", regcache, regno);
   fprintf_unfiltered (gdb_stdlog, "\n");
 }
 
 static void
-debug_to_prepare_to_store (void)
+debug_to_prepare_to_store (struct regcache *regcache)
 {
-  debug_target.to_prepare_to_store ();
+  debug_target.to_prepare_to_store (regcache);
 
   fprintf_unfiltered (gdb_stdlog, "target_prepare_to_store ()\n");
 }
@@ -1960,7 +2343,7 @@ deprecated_debug_xfer_memory (CORE_ADDR memaddr, bfd_byte *myaddr, int len,
                }
              fprintf_unfiltered (gdb_stdlog, "\n");
            }
-         
+
          fprintf_unfiltered (gdb_stdlog, " %02x", myaddr[i] & 0xff);
        }
     }
@@ -2110,10 +2493,10 @@ debug_to_remove_watchpoint (CORE_ADDR addr, int len, int type)
 {
   int retval;
 
-  retval = debug_target.to_insert_watchpoint (addr, len, type);
+  retval = debug_target.to_remove_watchpoint (addr, len, type);
 
   fprintf_unfiltered (gdb_stdlog,
-                     "target_insert_watchpoint (0x%lx, %d, %d) = %ld\n",
+                     "target_remove_watchpoint (0x%lx, %d, %d) = %ld\n",
                      (unsigned long) addr, len, type, (unsigned long) retval);
   return retval;
 }
@@ -2289,20 +2672,6 @@ debug_to_remove_exec_catchpoint (int pid)
   return retval;
 }
 
-static int
-debug_to_reported_exec_events_per_exec_call (void)
-{
-  int reported_exec_events;
-
-  reported_exec_events = debug_target.to_reported_exec_events_per_exec_call ();
-
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_reported_exec_events_per_exec_call () = %d\n",
-                     reported_exec_events);
-
-  return reported_exec_events;
-}
-
 static int
 debug_to_has_exited (int pid, int wait_status, int *exit_status)
 {
@@ -2382,26 +2751,6 @@ debug_to_rcmd (char *command,
   fprintf_unfiltered (gdb_stdlog, "target_rcmd (%s, ...)\n", command);
 }
 
-static struct symtab_and_line *
-debug_to_enable_exception_callback (enum exception_event_kind kind, int enable)
-{
-  struct symtab_and_line *result;
-  result = debug_target.to_enable_exception_callback (kind, enable);
-  fprintf_unfiltered (gdb_stdlog,
-                     "target get_exception_callback_sal (%d, %d)\n",
-                     kind, enable);
-  return result;
-}
-
-static struct exception_event_record *
-debug_to_get_current_exception_event (void)
-{
-  struct exception_event_record *result;
-  result = debug_target.to_get_current_exception_event ();
-  fprintf_unfiltered (gdb_stdlog, "target get_current_exception_event ()\n");
-  return result;
-}
-
 static char *
 debug_to_pid_to_exec_file (int pid)
 {
@@ -2460,7 +2809,6 @@ setup_target_debug (void)
   current_target.to_remove_vfork_catchpoint = debug_to_remove_vfork_catchpoint;
   current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint;
   current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint;
-  current_target.to_reported_exec_events_per_exec_call = debug_to_reported_exec_events_per_exec_call;
   current_target.to_has_exited = debug_to_has_exited;
   current_target.to_mourn_inferior = debug_to_mourn_inferior;
   current_target.to_can_run = debug_to_can_run;
@@ -2469,8 +2817,6 @@ setup_target_debug (void)
   current_target.to_find_new_threads = debug_to_find_new_threads;
   current_target.to_stop = debug_to_stop;
   current_target.to_rcmd = debug_to_rcmd;
-  current_target.to_enable_exception_callback = debug_to_enable_exception_callback;
-  current_target.to_get_current_exception_event = debug_to_get_current_exception_event;
   current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file;
 }
 \f
@@ -2493,6 +2839,21 @@ do_monitor_command (char *cmd,
   target_rcmd (cmd, gdb_stdtarg);
 }
 
+/* Print the name of each layers of our target stack.  */
+
+static void
+maintenance_print_target_stack (char *cmd, int from_tty)
+{
+  struct target_ops *t;
+
+  printf_filtered (_("The current target stack is:\n"));
+
+  for (t = target_stack; t != NULL; t = t->beneath)
+    {
+      printf_filtered ("  - %s (%s)\n", t->to_shortname, t->to_longname);
+    }
+}
+
 void
 initialize_targets (void)
 {
@@ -2512,7 +2873,7 @@ command."),
                            show_targetdebug,
                            &setdebuglist, &showdebuglist);
 
-  add_setshow_boolean_cmd ("trust-readonly-sections", class_support, 
+  add_setshow_boolean_cmd ("trust-readonly-sections", class_support,
                           &trust_readonly, _("\
 Set mode for reading from readonly sections."), _("\
 Show mode for reading from readonly sections."), _("\
@@ -2526,5 +2887,9 @@ result in significant performance improvement for remote targets."),
   add_com ("monitor", class_obscure, do_monitor_command,
           _("Send a command to the remote monitor (remote targets only)."));
 
+  add_cmd ("target-stack", class_maintenance, maintenance_print_target_stack,
+           _("Print the name of each layer of the internal target stack."),
+           &maintenanceprintlist);
+
   target_dcache = dcache_init ();
 }
This page took 0.044908 seconds and 4 git commands to generate.