add autom4te.cache to .cvsignore
[deliverable/binutils-gdb.git] / gdb / target.c
index 65d24a54f637e437cf7ef96943fda4de7727d4b0..f9d6064e0c4eed30a66a9ce7094d88640f6f10e3 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
    Free Software Foundation, Inc.
 
    Contributed by Cygnus Support.
@@ -39,6 +39,8 @@
 #include "regcache.h"
 #include "gdb_assert.h"
 #include "gdbcore.h"
+#include "exceptions.h"
+#include "target-descriptions.h"
 
 static void target_info (char *, int);
 
@@ -377,7 +379,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) \
@@ -463,7 +465,11 @@ update_current_target (void)
       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
 
@@ -637,6 +643,7 @@ update_current_target (void)
   de_fault (to_async,
            (void (*) (void (*) (enum inferior_event_type, void*), void*))
            tcomplain);
+  current_target.to_read_description = NULL;
 #undef de_fault
 
   /* Finally, position the target-stack beneath the squashed
@@ -645,6 +652,56 @@ update_current_target (void)
   current_target.beneath = target_stack;
 }
 
+/* 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.
 
@@ -755,6 +812,92 @@ pop_target (void)
   internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
 }
 
+/* Using the objfile specified in BATON, 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))
 
@@ -875,7 +1018,8 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
 
   /* 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 +1035,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)
@@ -926,7 +1079,7 @@ 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;
 
@@ -1040,6 +1193,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)
@@ -1180,6 +1416,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 +1597,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 +1633,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.  */
@@ -1439,6 +1696,27 @@ 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 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.
@@ -2110,10 +2388,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;
 }
@@ -2493,6 +2771,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)
 {
@@ -2526,5 +2819,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.028096 seconds and 4 git commands to generate.