* config/i386/nm-nbsd.h (FLOAT_INFO): Comment out.
[deliverable/binutils-gdb.git] / gdb / target.c
index 83fe7082a53b24d3a2f3ce8acce352bcb62aa0d0..9ae8941482a56297270da18af8981df5cb7d0df0 100644 (file)
@@ -1,5 +1,5 @@
 /* Select target systems and architectures at runtime for GDB.
-   Copyright 1990, 1992 Free Software Foundation, Inc.
+   Copyright 1990, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
    Contributed by Cygnus Support.
 
 This file is part of GDB.
@@ -21,12 +21,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "defs.h"
 #include <errno.h>
 #include <ctype.h>
+#include "gdb_string.h"
 #include "target.h"
 #include "gdbcmd.h"
 #include "symtab.h"
 #include "inferior.h"
 #include "bfd.h"
 #include "symfile.h"
+#include "objfiles.h"
+#include "wait.h"
+#include <signal.h>
 
 extern int errno;
 
@@ -55,13 +59,20 @@ static void
 tcomplain PARAMS ((void));
 
 static int
-nomemory PARAMS ((CORE_ADDR, char *, int, int));
+nomemory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static int
+return_zero PARAMS ((void));
 
 static void
 ignore PARAMS ((void));
+
 static void
 target_command PARAMS ((char *, int));
 
+static struct target_ops *
+find_default_run_target PARAMS ((char *));
+
 /* Pointer to array of target architecture structures; the size of the
    array; the current index into the array; the allocated size of the 
    array.  */
@@ -74,35 +85,76 @@ unsigned target_struct_allocsize;
 /* The initial current target, so that there is always a semi-valid
    current target.  */
 
-struct target_ops dummy_target = {"None", "None", "",
-    0, 0, 0, 0,                /* open, close, attach, detach */
-    0, 0,              /* resume, wait */
-    0, 0, 0, 0, 0,     /* registers */
-    0, 0,              /* memory */
-    0, 0,              /* bkpts */
-    0, 0, 0, 0, 0,     /* terminal */
-    0, 0,              /* kill, load */
-    0,                         /* lookup_symbol */
-    0, 0,              /* create_inferior, mourn_inferior */
-    dummy_stratum, 0,  /* stratum, next */
-    0, 0, 0, 0, 0,     /* all mem, mem, stack, regs, exec */
-    0, 0,              /* section pointers */
-    OPS_MAGIC,
+struct target_ops dummy_target = {
+  "None",                      /* to_shortname */
+  "None",                      /* to_longname */
+  "",                          /* to_doc */
+  0,                           /* to_open */
+  0,                           /* to_close */
+  find_default_attach,         /* to_attach */
+  0,                           /* to_detach */
+  0,                           /* to_resume */
+  0,                           /* to_wait */
+  0,                           /* to_fetch_registers */
+  0,                           /* to_store_registers */
+  0,                           /* to_prepare_to_store */
+  0,                           /* to_xfer_memory */
+  0,                           /* to_files_info */
+  0,                           /* to_insert_breakpoint */
+  0,                           /* to_remove_breakpoint */
+  0,                           /* to_terminal_init */
+  0,                           /* to_terminal_inferior */
+  0,                           /* to_terminal_ours_for_output */
+  0,                           /* to_terminal_ours */
+  0,                           /* to_terminal_info */
+  0,                           /* to_kill */
+  0,                           /* to_load */
+  0,                           /* to_lookup_symbol */
+  find_default_create_inferior,        /* to_create_inferior */
+  0,                           /* to_mourn_inferior */
+  0,                           /* to_can_run */
+  0,                           /* to_notice_signals */
+  0,                           /* to_thread_alive */
+  0,                           /* to_stop */
+  dummy_stratum,               /* to_stratum */
+  0,                           /* to_next */
+  0,                           /* to_next */
+  0,                           /* to_has_all_memory */
+  0,                           /* to_has_memory */
+  0,                           /* to_has_registers */
+  0,                           /* to_has_execution */
+  0,                           /* to_sections */
+  0,                           /* to_sections_end */
+  OPS_MAGIC,                   /* to_magic */
 };
 
-/* The target structure we are currently using to talk to a process
-   or file or whatever "inferior" we have.  */
+/* Top of target stack.  */
 
-struct target_ops *current_target;
+struct target_stack_item *target_stack;
 
-/* The stack of target structures that have been pushed.  */
+/* The target structure we are currently using to talk to a process
+   or file or whatever "inferior" we have.  */
 
-struct target_ops **current_target_stack;
+struct target_ops current_target;
 
 /* Command list for target.  */
 
 static struct cmd_list_element *targetlist = NULL;
 
+/* Nonzero if we are debugging an attached outside process
+   rather than an inferior.  */
+
+int attach_flag;
+
+#ifdef MAINTENANCE_CMDS
+/* Non-zero if we want to see trace of target level stuff.  */
+
+static int targetdebug = 0;
+
+static void setup_target_debug PARAMS ((void));
+
+#endif
+
 /* The user just typed 'target' without the name of a target.  */
 
 /* ARGSUSED */
@@ -111,7 +163,8 @@ target_command (arg, from_tty)
      char *arg;
      int from_tty;
 {
-  fputs_filtered ("Argument required (target name).\n", stdout);
+  fputs_filtered ("Argument required (target name).  Try `help target'\n",
+                 gdb_stdout);
 }
 
 /* Add a possible target architecture to the list.  */
@@ -120,13 +173,6 @@ void
 add_target (t)
      struct target_ops *t;
 {
-  if (t->to_magic != OPS_MAGIC)
-    {
-      fprintf(stderr, "Magic number of %s target struct wrong\n", 
-       t->to_shortname);
-      abort();
-    }
-
   if (!target_structs)
     {
       target_struct_allocsize = DEFAULT_ALLOCSIZE;
@@ -141,7 +187,7 @@ add_target (t)
                    target_struct_allocsize * sizeof (*target_structs));
     }
   target_structs[target_struct_size++] = t;
-  cleanup_target (t);
+/*  cleanup_target (t);*/
 
   if (targetlist == NULL)
     add_prefix_cmd ("target", class_run, target_command,
@@ -163,12 +209,14 @@ ignore ()
 
 /* ARGSUSED */
 static int
-nomemory (memaddr, myaddr, len, write)
+nomemory (memaddr, myaddr, len, write, t)
      CORE_ADDR memaddr;
      char *myaddr;
      int len;
      int write;
+     struct target_ops *t;
 {
+  errno = EIO;         /* Can't read/write this location */
   return 0;            /* No bytes handled */
 }
 
@@ -176,7 +224,7 @@ static void
 tcomplain ()
 {
   error ("You can't do that when your target is `%s'",
-        current_target->to_shortname);
+        current_target.to_shortname);
 }
 
 void
@@ -200,37 +248,8 @@ default_terminal_info (args, from_tty)
      char *args;
      int from_tty;
 {
-  printf("No saved terminal information.\n");
-}
-
-#if 0
-/* With strata, this function is no longer needed.  FIXME.  */
-/* This is the default target_create_inferior function.  It looks up
-   the stack for some target that cares to create inferiors, then
-   calls it -- or complains if not found.  */
-
-static void
-upstack_create_inferior (exec, args, env)
-     char *exec;
-     char *args;
-     char **env;
-{
-  struct target_ops *t;
-
-  for (t = current_target;
-       t;
-       t = t->to_next)
-    {
-      if (t->to_create_inferior != upstack_create_inferior)
-       {
-          t->to_create_inferior (exec, args, env);
-         return;
-       }
-
-    }
-  tcomplain();
+  printf_unfiltered("No saved terminal information.\n");
 }
-#endif
 
 /* This is the default target_create_inferior and target_attach function.
    If the current target is executing, it asks whether to kill it off.
@@ -243,7 +262,7 @@ kill_or_be_killed (from_tty)
 {
   if (target_has_execution)
     {
-      printf ("You are already running a program:\n");
+      printf_unfiltered ("You are already running a program:\n");
       target_files_info ();
       if (query ("Kill it? ")) {
        target_kill ();
@@ -284,15 +303,6 @@ cleanup_target (t)
      struct target_ops *t;
 {
 
-  /* 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(stderr, "Magic number of %s target struct wrong\n", 
-       t->to_shortname);
-      abort();
-    }
-
 #define de_fault(field, value) \
   if (!t->field)       t->field = value
 
@@ -307,8 +317,6 @@ cleanup_target (t)
   de_fault (to_fetch_registers,        (void (*)())ignore);
   de_fault (to_store_registers,                (void (*)())noprocess);
   de_fault (to_prepare_to_store,       (void (*)())noprocess);
-  de_fault (to_convert_to_virtual,     host_convert_to_virtual);
-  de_fault (to_convert_from_virtual,   host_convert_from_virtual);
   de_fault (to_xfer_memory,            (int (*)())nomemory);
   de_fault (to_files_info,             (void (*)())ignore);
   de_fault (to_insert_breakpoint,      memory_insert_breakpoint);
@@ -323,16 +331,80 @@ cleanup_target (t)
   de_fault (to_lookup_symbol,          nosymbol);
   de_fault (to_create_inferior,                maybe_kill_then_create_inferior);
   de_fault (to_mourn_inferior,         (void (*)())noprocess);
-  de_fault (to_next,                   0);
-  de_fault (to_has_all_memory,         0);
-  de_fault (to_has_memory,             0);
-  de_fault (to_has_stack,              0);
-  de_fault (to_has_registers,          0);
-  de_fault (to_has_execution,          0);
+  de_fault (to_can_run,                        return_zero);
+  de_fault (to_notice_signals,         (void (*)())ignore);
+  de_fault (to_thread_alive,           (int (*)())ignore);
+  de_fault (to_stop,                   (void (*)())ignore);
 
 #undef de_fault
 }
 
+/* Go through the target stack from top to bottom, copying over zero entries in
+   current_target.  In effect, we are doing class inheritance through the
+   pushed target vectors.  */
+
+static void
+update_current_target ()
+{
+  struct target_stack_item *item;
+  struct target_ops *t;
+
+  /* First, reset current_target */
+  memset (&current_target, 0, sizeof current_target);
+
+  for (item = target_stack; item; item = item->next)
+    {
+      t = item->target_ops;
+
+#define INHERIT(FIELD, TARGET) \
+      if (!current_target.FIELD) \
+       current_target.FIELD = TARGET->FIELD
+
+      INHERIT (to_shortname, t);
+      INHERIT (to_longname, t);
+      INHERIT (to_doc, t);
+      INHERIT (to_open, t);
+      INHERIT (to_close, t);
+      INHERIT (to_attach, t);
+      INHERIT (to_detach, t);
+      INHERIT (to_resume, t);
+      INHERIT (to_wait, t);
+      INHERIT (to_fetch_registers, t);
+      INHERIT (to_store_registers, t);
+      INHERIT (to_prepare_to_store, t);
+      INHERIT (to_xfer_memory, t);
+      INHERIT (to_files_info, t);
+      INHERIT (to_insert_breakpoint, t);
+      INHERIT (to_remove_breakpoint, t);
+      INHERIT (to_terminal_init, t);
+      INHERIT (to_terminal_inferior, t);
+      INHERIT (to_terminal_ours_for_output, t);
+      INHERIT (to_terminal_ours, t);
+      INHERIT (to_terminal_info, t);
+      INHERIT (to_kill, t);
+      INHERIT (to_load, t);
+      INHERIT (to_lookup_symbol, t);
+      INHERIT (to_create_inferior, t);
+      INHERIT (to_mourn_inferior, t);
+      INHERIT (to_can_run, t);
+      INHERIT (to_notice_signals, t);
+      INHERIT (to_thread_alive, t);
+      INHERIT (to_stop, t);
+      INHERIT (to_stratum, t);
+      INHERIT (DONT_USE, 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);
+      INHERIT (to_sections, t);
+      INHERIT (to_sections_end, t);
+      INHERIT (to_magic, t);
+
+#undef INHERIT
+    }
+}
+
 /* Push a new target type into the stack of the existing target accessors,
    possibly superseding some of the existing accessors.
 
@@ -347,89 +419,144 @@ int
 push_target (t)
      struct target_ops *t;
 {
-  struct target_ops *st, *prev;
+  struct target_stack_item *cur, *prev, *tmp;
+
+  /* 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);
+      abort();
+    }
+
+  /* Find the proper stratum to install this target in. */
+
+  for (prev = NULL, cur = target_stack; cur; prev = cur, cur = cur->next)
+    {
+      if ((int)(t->to_stratum) >= (int)(cur->target_ops->to_stratum))
+       break;
+    }
+
+  /* If there's already targets at this stratum, remove them. */
+
+  if (cur)
+    while (t->to_stratum == cur->target_ops->to_stratum)
+      {
+       /* There's already something on this stratum.  Close it off.  */
+       (cur->target_ops->to_close) (0);
+       if (prev)
+         prev->next = cur->next; /* Unchain old target_ops */
+       else
+         target_stack = cur->next; /* Unchain first on list */
+       tmp = cur->next;
+       free (cur);
+       cur = tmp;
+      }
+
+  /* We have removed all targets in our stratum, now add the new one.  */
+
+  tmp = (struct target_stack_item *)
+    xmalloc (sizeof (struct target_stack_item));
+  tmp->next = cur;
+  tmp->target_ops = t;
 
-  for (prev = 0, st = current_target;
-       st;
-       prev = st, st = st->to_next) {
-    if ((int)(t->to_stratum) >= (int)(st->to_stratum))
-      break;
-  }
-
-  while (t->to_stratum == st->to_stratum) {
-    /* There's already something on this stratum.  Close it off.  */
-    (st->to_close) (0);
-    if (prev)
-      prev->to_next = st->to_next;     /* Unchain old target_ops */
-    else
-      current_target = st->to_next;    /* Unchain first on list */
-    st = st->to_next;
-  }
-
-  /* We have removed all targets in our stratum, now add ourself.  */
-  t->to_next = st;
   if (prev)
-    prev->to_next = t;
+    prev->next = tmp;
   else
-    current_target = t;
+    target_stack = tmp;
+
+  update_current_target ();
+
+  cleanup_target (&current_target); /* Fill in the gaps */
+
+#ifdef MAINTENANCE_CMDS
+  if (targetdebug)
+    setup_target_debug ();
+#endif
 
-  cleanup_target (current_target);
   return prev != 0;
 }
 
 /* Remove a target_ops vector from the stack, wherever it may be. 
-   Return how many times it was removed (0 or 1 unless bug).  */
+   Return how many times it was removed (0 or 1).  */
 
 int
 unpush_target (t)
      struct target_ops *t;
 {
-  struct target_ops *u, *v;
-  int result = 0;
+  struct target_stack_item *cur, *prev;
 
-  for (u = current_target, v = 0;
-       u;
-       v = u, u = u->to_next)
-    if (u == t)
-      {
-       if (v == 0)
-         pop_target();                 /* unchain top copy */
-       else {
-         (t->to_close)(0);             /* Let it clean up */
-         v->to_next = t->to_next;      /* unchain middle copy */
-       }
-       result++;
-      }
-  return result;
+  if (t->to_close)
+    t->to_close (0);           /* Let it clean up */
+
+  /* Look for the specified target.  Note that we assume that a target
+     can only occur once in the target stack. */
+
+  for (cur = target_stack, prev = NULL; cur; prev = cur, cur = cur->next)
+    if (cur->target_ops == t)
+      break;
+
+  if (!cur)
+    return 0;                  /* Didn't find target_ops, quit now */
+
+  /* Unchain the target */
+
+  if (!prev)
+    target_stack = cur->next;
+  else
+    prev->next = cur->next;
+
+  free (cur);                  /* Release the target_stack_item */
+
+  update_current_target ();
+  cleanup_target (&current_target);
+
+  return 1;
 }
 
 void
 pop_target ()
 {
-  (current_target->to_close)(0);       /* Let it clean up */
-  current_target = current_target->to_next;
-  if (!current_target)         /* At bottom, push dummy.  */
-    push_target (&dummy_target);
+  (current_target.to_close)(0);        /* Let it clean up */
+  if (unpush_target (target_stack->target_ops) == 1)
+    return;
+
+  fprintf_unfiltered(gdb_stderr,
+                    "pop_target couldn't find target %s\n", 
+                    current_target.to_shortname);
+  abort();
 }
 
+#undef MIN
 #define MIN(A, B) (((A) <= (B)) ? (A) : (B))
 
-/* target_read_string -- read a null terminated string from MEMADDR in target.
-   The read may also be terminated early by getting an error from target_xfer_
-   memory.
-   LEN is the size of the buffer pointed to by MYADDR.  Note that a terminating
-   null will only be written if there is sufficient room.  The return value is
-   is the number of bytes (including the null) actually transferred.
-*/
+/* target_read_string -- read a null terminated string, up to LEN bytes,
+   from MEMADDR in target.  Set *ERRNOP to the errno code, or 0 if successful.
+   Set *STRING to a pointer to malloc'd memory containing the data; the caller
+   is responsible for freeing it.  Return the number of bytes successfully
+   read.  */
 
 int
-target_read_string (memaddr, myaddr, len)
+target_read_string (memaddr, string, len, errnop)
      CORE_ADDR memaddr;
-     char *myaddr;
+     char **string;
      int len;
+     int *errnop;
 {
   int tlen, origlen, offset, i;
   char buf[4];
+  int errcode = 0;
+  char *buffer;
+  int buffer_allocated;
+  char *bufptr;
+  unsigned int nbytes_read = 0;
+
+  /* Small for testing.  */
+  buffer_allocated = 4;
+  buffer = xmalloc (buffer_allocated);
+  bufptr = buffer;
 
   origlen = len;
 
@@ -438,31 +565,50 @@ target_read_string (memaddr, myaddr, len)
       tlen = MIN (len, 4 - (memaddr & 3));
       offset = memaddr & 3;
 
-      if (target_xfer_memory (memaddr & ~3, buf, 4, 0))
-       return origlen - len;
+      errcode = target_xfer_memory (memaddr & ~3, buf, 4, 0);
+      if (errcode != 0)
+       goto done;
+
+      if (bufptr - buffer + tlen > buffer_allocated)
+       {
+         unsigned int bytes;
+         bytes = bufptr - buffer;
+         buffer_allocated *= 2;
+         buffer = xrealloc (buffer, buffer_allocated);
+         bufptr = buffer + bytes;
+       }
 
       for (i = 0; i < tlen; i++)
        {
-         *myaddr++ = buf[i + offset];
+         *bufptr++ = buf[i + offset];
          if (buf[i + offset] == '\000')
-           return (origlen - len) + i + 1;
+           {
+             nbytes_read += i + 1;
+             goto done;
+           }
        }
 
       memaddr += tlen;
       len -= tlen;
+      nbytes_read += tlen;
     }
-  return origlen;
+ done:
+  if (errnop != NULL)
+    *errnop = errcode;
+  if (string != NULL)
+    *string = buffer;
+  return nbytes_read;
 }
 
-/* Move memory to or from the targets.  Iterate until all of it has
-   been moved, if necessary.  The top target gets priority; anything
-   it doesn't want, is offered to the next one down, etc.  Note the
-   business with curlen:  if an early target says "no, but I have a
-   boundary overlapping this xfer" then we shorten what we offer to
-   the subsequent targets so the early guy will get a chance at the
-   tail before the subsequent ones do. 
+/* Read LEN bytes of target memory at address MEMADDR, placing the results in
+   GDB's memory at MYADDR.  Returns either 0 for success or an errno value
+   if any error occurs.
 
-   Result is 0 or errno value.  */
+   If an error occurs, no guarantee is made about the contents of the data at
+   MYADDR.  In particular, the caller should not depend upon partial reads
+   filling the buffer with good data.  There is no way for the caller to know
+   how much good data might have been transfered anyway.  Callers that can
+   deal with partial reads should call target_read_memory_partial. */
 
 int
 target_read_memory (memaddr, myaddr, len)
@@ -473,6 +619,48 @@ target_read_memory (memaddr, myaddr, len)
   return target_xfer_memory (memaddr, myaddr, len, 0);
 }
 
+/* Read LEN bytes of target memory at address MEMADDR, placing the results
+   in GDB's memory at MYADDR.  Returns a count of the bytes actually read,
+   and optionally an errno value in the location pointed to by ERRNOPTR
+   if ERRNOPTR is non-null. */
+
+int
+target_read_memory_partial (memaddr, myaddr, len, errnoptr)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int *errnoptr;
+{
+  int nread;   /* Number of bytes actually read. */
+  int errcode; /* Error from last read. */
+
+  /* First try a complete read. */
+  errcode = target_xfer_memory (memaddr, myaddr, len, 0);
+  if (errcode == 0)
+    {
+      /* Got it all. */
+      nread = len;
+    }
+  else
+    {
+      /* Loop, reading one byte at a time until we get as much as we can. */
+      for (errcode = 0, nread = 0; len > 0 && errcode == 0; nread++, len--)
+       {
+         errcode = target_xfer_memory (memaddr++, myaddr++, 1, 0);
+       }
+      /* If an error, the last read was unsuccessful, so adjust count. */
+      if (errcode != 0)
+       {
+         nread--;
+       }
+    }
+  if (errnoptr != NULL)
+    {
+      *errnoptr = errcode;
+    }
+  return (nread);
+}
+
 int
 target_write_memory (memaddr, myaddr, len)
      CORE_ADDR memaddr;
@@ -482,6 +670,16 @@ target_write_memory (memaddr, myaddr, len)
   return target_xfer_memory (memaddr, myaddr, len, 1);
 }
  
+/* Move memory to or from the targets.  Iterate until all of it has
+   been moved, if necessary.  The top target gets priority; anything
+   it doesn't want, is offered to the next one down, etc.  Note the
+   business with curlen:  if an early target says "no, but I have a
+   boundary overlapping this xfer" then we shorten what we offer to
+   the subsequent targets so the early guy will get a chance at the
+   tail before the subsequent ones do. 
+
+   Result is 0 or errno value.  */
+
 int
 target_xfer_memory (memaddr, myaddr, len, write)
      CORE_ADDR memaddr;
@@ -492,10 +690,15 @@ target_xfer_memory (memaddr, myaddr, len, write)
   int curlen;
   int res;
   struct target_ops *t;
-  
+  struct target_stack_item *item;
+
+  /* to_xfer_memory is not guaranteed to set errno, even when it returns
+     0.  */
+  errno = 0;
+
   /* The quick case is that the top target does it all.  */
-  res = current_target->to_xfer_memory
-                       (memaddr, myaddr, len, write, current_target);
+  res = current_target.to_xfer_memory
+                       (memaddr, myaddr, len, write, &current_target);
   if (res == len)
     return 0;
 
@@ -506,21 +709,25 @@ target_xfer_memory (memaddr, myaddr, len, write)
   for (; len > 0;)
     {
       curlen = len;            /* Want to do it all */
-      for (t = current_target;
-          t;
-          t = t->to_has_all_memory? 0: t->to_next)
+      for (item = target_stack; item; item = item->next)
        {
-         res = t->to_xfer_memory(memaddr, myaddr, curlen, write, t);
-         if (res > 0) break;   /* Handled all or part of xfer */
-         if (res == 0) continue;       /* Handled none */
-         curlen = -res;        /* Could handle once we get past res bytes */
+         t = item->target_ops;
+         if (!t->to_has_memory)
+           continue;
+
+         res = t->to_xfer_memory (memaddr, myaddr, curlen, write, t);
+         if (res > 0)
+           break;              /* Handled all or part of xfer */
+         if (t->to_has_all_memory)
+           break;
        }
+
       if (res <= 0)
        {
          /* If this address is for nonexistent memory,
             read zeros if reading, or do nothing if writing.  Return error. */
          if (!write)
-           bzero (myaddr, len);
+           memset (myaddr, 0, len);
          if (errno == 0)
            return EIO;
          else
@@ -542,25 +749,29 @@ target_info (args, from_tty)
      int from_tty;
 {
   struct target_ops *t;
+  struct target_stack_item *item;
   int has_all_mem = 0;
   
   if (symfile_objfile != NULL)
-    printf ("Symbols from \"%s\".\n", symfile_objfile->name);
+    printf_unfiltered ("Symbols from \"%s\".\n", symfile_objfile->name);
 
 #ifdef FILES_INFO_HOOK
   if (FILES_INFO_HOOK ())
     return;
 #endif
 
-  for (t = current_target;
-       t;
-       t = t->to_next)
+  for (item = target_stack; item; item = item->next)
     {
+      t = item->target_ops;
+
+      if (!t->to_has_memory)
+       continue;
+
       if ((int)(t->to_stratum) <= (int)dummy_stratum)
        continue;
       if (has_all_mem)
-       printf("\tWhile running this, gdb does not access memory from...\n");
-      printf("%s:\n", t->to_longname);
+       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;
     }
@@ -582,19 +793,1066 @@ target_preopen (from_tty)
       else
         error ("Program not killed.");
     }
+
+  /* Calling target_kill may remove the target from the stack.  But if
+     it doesn't (which seems like a win for UDI), remove it now.  */
+
+  if (target_has_execution)
+    pop_target ();
 }
 
-static char targ_desc[] = 
-    "Names of targets and files being debugged.\n\
-Shows the entire stack of targets currently in use (including the exec-file,\n\
-core-file, and process, if any), as well as the symbol file name.";
+/* Detach a target after doing deferred register stores.  */
 
 void
-_initialize_targets ()
+target_detach (args, from_tty)
+     char *args;
+     int from_tty;
 {
-  current_target = &dummy_target;
-  cleanup_target (current_target);
+  /* Handle any optimized stores to the inferior.  */
+#ifdef DO_DEFERRED_STORES
+  DO_DEFERRED_STORES;
+#endif
+  (current_target.to_detach) (args, from_tty);
+}
 
-  add_info ("target", target_info, targ_desc);
-  add_info ("files", target_info, targ_desc);
+void
+target_link (modname, t_reloc)
+     char *modname;
+     CORE_ADDR *t_reloc;
+{
+  if (STREQ(current_target.to_shortname, "rombug"))
+    {
+      (current_target.to_lookup_symbol) (modname, t_reloc);
+      if (*t_reloc == 0)
+      error("Unable to link to %s and get relocation in rombug", modname);
+    }
+  else
+    *t_reloc = (CORE_ADDR)-1;
+}
+
+/* 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).  */
+
+static struct target_ops *
+find_default_run_target (do_mesg)
+     char *do_mesg;
+{
+  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_can_run && target_can_run(*t))
+       {
+         runable = *t;
+         ++count;
+       }
+    }
+
+  if (count != 1)
+    error ("Don't know how to %s.  Try \"help target\".", do_mesg);
+
+  return runable;
+}
+
+void
+find_default_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  struct target_ops *t;
+
+  t = find_default_run_target("attach");
+  (t->to_attach) (args, from_tty);
+  return;
+}
+
+void
+find_default_create_inferior (exec_file, allargs, env)
+     char *exec_file;
+     char *allargs;
+     char **env;
+{
+  struct target_ops *t;
+
+  t = find_default_run_target("run");
+  (t->to_create_inferior) (exec_file, allargs, env);
+  return;
+}
+
+static int
+return_zero ()
+{
+  return 0;
+}
+
+struct target_ops *
+find_core_target ()
+{
+  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);
+}
+\f
+/* The inferior process has died.  Long live the inferior!  */
+
+void
+generic_mourn_inferior ()
+{
+  extern int show_breakpoint_hit_counts;
+
+  inferior_pid = 0;
+  attach_flag = 0;
+  breakpoint_init_inferior ();
+  registers_changed ();
+
+#ifdef CLEAR_DEFERRED_STORES
+  /* Delete any pending stores to the inferior... */
+  CLEAR_DEFERRED_STORES;
+#endif
+
+  reopen_exec_file ();
+  reinit_frame_cache ();
+
+  /* It is confusing to the user for ignore counts to stick around
+     from previous runs of the inferior.  So clear them.  */
+  /* However, it is more confusing for the ignore counts to disappear when
+     using hit counts.  So don't clear them if we're counting hits.  */
+  if (!show_breakpoint_hit_counts)
+    breakpoint_clear_ignore_counts ();
+}
+\f
+/* This table must match in order and size the signals in enum target_signal
+   in target.h.  */
+static struct {
+  char *name;
+  char *string;
+  } signals [] =
+{
+  {"0", "Signal 0"},
+  {"SIGHUP", "Hangup"},
+  {"SIGINT", "Interrupt"},
+  {"SIGQUIT", "Quit"},
+  {"SIGILL", "Illegal instruction"},
+  {"SIGTRAP", "Trace/breakpoint trap"},
+  {"SIGABRT", "Aborted"},
+  {"SIGEMT", "Emulation trap"},
+  {"SIGFPE", "Arithmetic exception"},
+  {"SIGKILL", "Killed"},
+  {"SIGBUS", "Bus error"},
+  {"SIGSEGV", "Segmentation fault"},
+  {"SIGSYS", "Bad system call"},
+  {"SIGPIPE", "Broken pipe"},
+  {"SIGALRM", "Alarm clock"},
+  {"SIGTERM", "Terminated"},
+  {"SIGURG", "Urgent I/O condition"},
+  {"SIGSTOP", "Stopped (signal)"},
+  {"SIGTSTP", "Stopped (user)"},
+  {"SIGCONT", "Continued"},
+  {"SIGCHLD", "Child status changed"},
+  {"SIGTTIN", "Stopped (tty input)"},
+  {"SIGTTOU", "Stopped (tty output)"},
+  {"SIGIO", "I/O possible"},
+  {"SIGXCPU", "CPU time limit exceeded"},
+  {"SIGXFSZ", "File size limit exceeded"},
+  {"SIGVTALRM", "Virtual timer expired"},
+  {"SIGPROF", "Profiling timer expired"},
+  {"SIGWINCH", "Window size changed"},
+  {"SIGLOST", "Resource lost"},
+  {"SIGUSR1", "User defined signal 1"},
+  {"SIGUSR2", "User defined signal 2"},
+  {"SIGPWR", "Power fail/restart"},
+  {"SIGPOLL", "Pollable event occurred"},
+  {"SIGWIND", "SIGWIND"},
+  {"SIGPHONE", "SIGPHONE"},
+  {"SIGWAITING", "Process's LWPs are blocked"},
+  {"SIGLWP", "Signal LWP"},
+  {"SIGDANGER", "Swap space dangerously low"},
+  {"SIGGRANT", "Monitor mode granted"},
+  {"SIGRETRACT", "Need to relinguish monitor mode"},
+  {"SIGMSG", "Monitor mode data available"},
+  {"SIGSOUND", "Sound completed"},
+  {"SIGSAK", "Secure attention"},
+  {"SIGPRIO", "SIGPRIO"},
+  {"SIG33", "Real-time event 33"},
+  {"SIG34", "Real-time event 34"},
+  {"SIG35", "Real-time event 35"},
+  {"SIG36", "Real-time event 36"},
+  {"SIG37", "Real-time event 37"},
+  {"SIG38", "Real-time event 38"},
+  {"SIG39", "Real-time event 39"},
+  {"SIG40", "Real-time event 40"},
+  {"SIG41", "Real-time event 41"},
+  {"SIG42", "Real-time event 42"},
+  {"SIG43", "Real-time event 43"},
+  {"SIG44", "Real-time event 44"},
+  {"SIG45", "Real-time event 45"},
+  {"SIG46", "Real-time event 46"},
+  {"SIG47", "Real-time event 47"},
+  {"SIG48", "Real-time event 48"},
+  {"SIG49", "Real-time event 49"},
+  {"SIG50", "Real-time event 50"},
+  {"SIG51", "Real-time event 51"},
+  {"SIG52", "Real-time event 52"},
+  {"SIG53", "Real-time event 53"},
+  {"SIG54", "Real-time event 54"},
+  {"SIG55", "Real-time event 55"},
+  {"SIG56", "Real-time event 56"},
+  {"SIG57", "Real-time event 57"},
+  {"SIG58", "Real-time event 58"},
+  {"SIG59", "Real-time event 59"},
+  {"SIG60", "Real-time event 60"},
+  {"SIG61", "Real-time event 61"},
+  {"SIG62", "Real-time event 62"},
+  {"SIG63", "Real-time event 63"},
+
+  {NULL, "Unknown signal"},
+  {NULL, "Internal error: printing TARGET_SIGNAL_DEFAULT"},
+
+  /* Last entry, used to check whether the table is the right size.  */
+  {NULL, "TARGET_SIGNAL_MAGIC"}
+};
+
+/* Return the string for a signal.  */
+char *
+target_signal_to_string (sig)
+     enum target_signal sig;
+{
+  return signals[sig].string;
+}
+
+/* Return the name for a signal.  */
+char *
+target_signal_to_name (sig)
+     enum target_signal sig;
+{
+  if (sig == TARGET_SIGNAL_UNKNOWN)
+    /* I think the code which prints this will always print it along with
+       the string, so no need to be verbose.  */
+    return "?";
+  return signals[sig].name;
+}
+
+/* Given a name, return its signal.  */
+enum target_signal
+target_signal_from_name (name)
+     char *name;
+{
+  enum target_signal sig;
+
+  /* It's possible we also should allow "SIGCLD" as well as "SIGCHLD"
+     for TARGET_SIGNAL_SIGCHLD.  SIGIOT, on the other hand, is more
+     questionable; seems like by now people should call it SIGABRT
+     instead.  */
+
+  /* This ugly cast brought to you by the native VAX compiler.  */
+  for (sig = TARGET_SIGNAL_HUP;
+       signals[sig].name != NULL;
+       sig = (enum target_signal)((int)sig + 1))
+    if (STREQ (name, signals[sig].name))
+      return sig;
+  return TARGET_SIGNAL_UNKNOWN;
+}
+\f
+/* The following functions are to help certain targets deal
+   with the signal/waitstatus stuff.  They could just as well be in
+   a file called native-utils.c or unixwaitstatus-utils.c or whatever.  */
+
+/* Convert host signal to our signals.  */
+enum target_signal
+target_signal_from_host (hostsig)
+     int hostsig;
+{
+  /* A switch statement would make sense but would require special kludges
+     to deal with the cases where more than one signal has the same number.  */
+
+  if (hostsig == 0) return TARGET_SIGNAL_0;
+
+#if defined (SIGHUP)
+  if (hostsig == SIGHUP) return TARGET_SIGNAL_HUP;
+#endif
+#if defined (SIGINT)
+  if (hostsig == SIGINT) return TARGET_SIGNAL_INT;
+#endif
+#if defined (SIGQUIT)
+  if (hostsig == SIGQUIT) return TARGET_SIGNAL_QUIT;
+#endif
+#if defined (SIGILL)
+  if (hostsig == SIGILL) return TARGET_SIGNAL_ILL;
+#endif
+#if defined (SIGTRAP)
+  if (hostsig == SIGTRAP) return TARGET_SIGNAL_TRAP;
+#endif
+#if defined (SIGABRT)
+  if (hostsig == SIGABRT) return TARGET_SIGNAL_ABRT;
+#endif
+#if defined (SIGEMT)
+  if (hostsig == SIGEMT) return TARGET_SIGNAL_EMT;
+#endif
+#if defined (SIGFPE)
+  if (hostsig == SIGFPE) return TARGET_SIGNAL_FPE;
+#endif
+#if defined (SIGKILL)
+  if (hostsig == SIGKILL) return TARGET_SIGNAL_KILL;
+#endif
+#if defined (SIGBUS)
+  if (hostsig == SIGBUS) return TARGET_SIGNAL_BUS;
+#endif
+#if defined (SIGSEGV)
+  if (hostsig == SIGSEGV) return TARGET_SIGNAL_SEGV;
+#endif
+#if defined (SIGSYS)
+  if (hostsig == SIGSYS) return TARGET_SIGNAL_SYS;
+#endif
+#if defined (SIGPIPE)
+  if (hostsig == SIGPIPE) return TARGET_SIGNAL_PIPE;
+#endif
+#if defined (SIGALRM)
+  if (hostsig == SIGALRM) return TARGET_SIGNAL_ALRM;
+#endif
+#if defined (SIGTERM)
+  if (hostsig == SIGTERM) return TARGET_SIGNAL_TERM;
+#endif
+#if defined (SIGUSR1)
+  if (hostsig == SIGUSR1) return TARGET_SIGNAL_USR1;
+#endif
+#if defined (SIGUSR2)
+  if (hostsig == SIGUSR2) return TARGET_SIGNAL_USR2;
+#endif
+#if defined (SIGCLD)
+  if (hostsig == SIGCLD) return TARGET_SIGNAL_CHLD;
+#endif
+#if defined (SIGCHLD)
+  if (hostsig == SIGCHLD) return TARGET_SIGNAL_CHLD;
+#endif
+#if defined (SIGPWR)
+  if (hostsig == SIGPWR) return TARGET_SIGNAL_PWR;
+#endif
+#if defined (SIGWINCH)
+  if (hostsig == SIGWINCH) return TARGET_SIGNAL_WINCH;
+#endif
+#if defined (SIGURG)
+  if (hostsig == SIGURG) return TARGET_SIGNAL_URG;
+#endif
+#if defined (SIGIO)
+  if (hostsig == SIGIO) return TARGET_SIGNAL_IO;
+#endif
+#if defined (SIGPOLL)
+  if (hostsig == SIGPOLL) return TARGET_SIGNAL_POLL;
+#endif
+#if defined (SIGSTOP)
+  if (hostsig == SIGSTOP) return TARGET_SIGNAL_STOP;
+#endif
+#if defined (SIGTSTP)
+  if (hostsig == SIGTSTP) return TARGET_SIGNAL_TSTP;
+#endif
+#if defined (SIGCONT)
+  if (hostsig == SIGCONT) return TARGET_SIGNAL_CONT;
+#endif
+#if defined (SIGTTIN)
+  if (hostsig == SIGTTIN) return TARGET_SIGNAL_TTIN;
+#endif
+#if defined (SIGTTOU)
+  if (hostsig == SIGTTOU) return TARGET_SIGNAL_TTOU;
+#endif
+#if defined (SIGVTALRM)
+  if (hostsig == SIGVTALRM) return TARGET_SIGNAL_VTALRM;
+#endif
+#if defined (SIGPROF)
+  if (hostsig == SIGPROF) return TARGET_SIGNAL_PROF;
+#endif
+#if defined (SIGXCPU)
+  if (hostsig == SIGXCPU) return TARGET_SIGNAL_XCPU;
+#endif
+#if defined (SIGXFSZ)
+  if (hostsig == SIGXFSZ) return TARGET_SIGNAL_XFSZ;
+#endif
+#if defined (SIGWIND)
+  if (hostsig == SIGWIND) return TARGET_SIGNAL_WIND;
+#endif
+#if defined (SIGPHONE)
+  if (hostsig == SIGPHONE) return TARGET_SIGNAL_PHONE;
+#endif
+#if defined (SIGLOST)
+  if (hostsig == SIGLOST) return TARGET_SIGNAL_LOST;
+#endif
+#if defined (SIGWAITING)
+  if (hostsig == SIGWAITING) return TARGET_SIGNAL_WAITING;
+#endif
+#if defined (SIGLWP)
+  if (hostsig == SIGLWP) return TARGET_SIGNAL_LWP;
+#endif
+#if defined (SIGDANGER)
+  if (hostsig == SIGDANGER) return TARGET_SIGNAL_DANGER;
+#endif
+#if defined (SIGGRANT)
+  if (hostsig == SIGGRANT) return TARGET_SIGNAL_GRANT;
+#endif
+#if defined (SIGRETRACT)
+  if (hostsig == SIGRETRACT) return TARGET_SIGNAL_RETRACT;
+#endif
+#if defined (SIGMSG)
+  if (hostsig == SIGMSG) return TARGET_SIGNAL_MSG;
+#endif
+#if defined (SIGSOUND)
+  if (hostsig == SIGSOUND) return TARGET_SIGNAL_SOUND;
+#endif
+#if defined (SIGSAK)
+  if (hostsig == SIGSAK) return TARGET_SIGNAL_SAK;
+#endif
+#if defined (SIGPRIO)
+  if (hostsig == SIGPRIO) return TARGET_SIGNAL_PRIO;
+#endif
+#if defined (REALTIME_LO)
+  if (hostsig >= REALTIME_LO && hostsig < REALTIME_HI)
+    return (enum target_signal)
+      (hostsig - 33 + (int) TARGET_SIGNAL_REALTIME_33);
+#endif
+  return TARGET_SIGNAL_UNKNOWN;
+}
+
+int
+target_signal_to_host (oursig)
+     enum target_signal oursig;
+{
+  switch (oursig)
+    {
+    case TARGET_SIGNAL_0: return 0;
+
+#if defined (SIGHUP)
+    case TARGET_SIGNAL_HUP: return SIGHUP;
+#endif
+#if defined (SIGINT)
+    case TARGET_SIGNAL_INT: return SIGINT;
+#endif
+#if defined (SIGQUIT)
+    case TARGET_SIGNAL_QUIT: return SIGQUIT;
+#endif
+#if defined (SIGILL)
+    case TARGET_SIGNAL_ILL: return SIGILL;
+#endif
+#if defined (SIGTRAP)
+    case TARGET_SIGNAL_TRAP: return SIGTRAP;
+#endif
+#if defined (SIGABRT)
+    case TARGET_SIGNAL_ABRT: return SIGABRT;
+#endif
+#if defined (SIGEMT)
+    case TARGET_SIGNAL_EMT: return SIGEMT;
+#endif
+#if defined (SIGFPE)
+    case TARGET_SIGNAL_FPE: return SIGFPE;
+#endif
+#if defined (SIGKILL)
+    case TARGET_SIGNAL_KILL: return SIGKILL;
+#endif
+#if defined (SIGBUS)
+    case TARGET_SIGNAL_BUS: return SIGBUS;
+#endif
+#if defined (SIGSEGV)
+    case TARGET_SIGNAL_SEGV: return SIGSEGV;
+#endif
+#if defined (SIGSYS)
+    case TARGET_SIGNAL_SYS: return SIGSYS;
+#endif
+#if defined (SIGPIPE)
+    case TARGET_SIGNAL_PIPE: return SIGPIPE;
+#endif
+#if defined (SIGALRM)
+    case TARGET_SIGNAL_ALRM: return SIGALRM;
+#endif
+#if defined (SIGTERM)
+    case TARGET_SIGNAL_TERM: return SIGTERM;
+#endif
+#if defined (SIGUSR1)
+    case TARGET_SIGNAL_USR1: return SIGUSR1;
+#endif
+#if defined (SIGUSR2)
+    case TARGET_SIGNAL_USR2: return SIGUSR2;
+#endif
+#if defined (SIGCHLD) || defined (SIGCLD)
+    case TARGET_SIGNAL_CHLD: 
+#if defined (SIGCHLD)
+      return SIGCHLD;
+#else
+      return SIGCLD;
+#endif
+#endif /* SIGCLD or SIGCHLD */
+#if defined (SIGPWR)
+    case TARGET_SIGNAL_PWR: return SIGPWR;
+#endif
+#if defined (SIGWINCH)
+    case TARGET_SIGNAL_WINCH: return SIGWINCH;
+#endif
+#if defined (SIGURG)
+    case TARGET_SIGNAL_URG: return SIGURG;
+#endif
+#if defined (SIGIO)
+    case TARGET_SIGNAL_IO: return SIGIO;
+#endif
+#if defined (SIGPOLL)
+    case TARGET_SIGNAL_POLL: return SIGPOLL;
+#endif
+#if defined (SIGSTOP)
+    case TARGET_SIGNAL_STOP: return SIGSTOP;
+#endif
+#if defined (SIGTSTP)
+    case TARGET_SIGNAL_TSTP: return SIGTSTP;
+#endif
+#if defined (SIGCONT)
+    case TARGET_SIGNAL_CONT: return SIGCONT;
+#endif
+#if defined (SIGTTIN)
+    case TARGET_SIGNAL_TTIN: return SIGTTIN;
+#endif
+#if defined (SIGTTOU)
+    case TARGET_SIGNAL_TTOU: return SIGTTOU;
+#endif
+#if defined (SIGVTALRM)
+    case TARGET_SIGNAL_VTALRM: return SIGVTALRM;
+#endif
+#if defined (SIGPROF)
+    case TARGET_SIGNAL_PROF: return SIGPROF;
+#endif
+#if defined (SIGXCPU)
+    case TARGET_SIGNAL_XCPU: return SIGXCPU;
+#endif
+#if defined (SIGXFSZ)
+    case TARGET_SIGNAL_XFSZ: return SIGXFSZ;
+#endif
+#if defined (SIGWIND)
+    case TARGET_SIGNAL_WIND: return SIGWIND;
+#endif
+#if defined (SIGPHONE)
+    case TARGET_SIGNAL_PHONE: return SIGPHONE;
+#endif
+#if defined (SIGLOST)
+    case TARGET_SIGNAL_LOST: return SIGLOST;
+#endif
+#if defined (SIGWAITING)
+    case TARGET_SIGNAL_WAITING: return SIGWAITING;
+#endif
+#if defined (SIGLWP)
+    case TARGET_SIGNAL_LWP: return SIGLWP;
+#endif
+#if defined (SIGDANGER)
+    case TARGET_SIGNAL_DANGER: return SIGDANGER;
+#endif
+#if defined (SIGGRANT)
+    case TARGET_SIGNAL_GRANT: return SIGGRANT;
+#endif
+#if defined (SIGRETRACT)
+    case TARGET_SIGNAL_RETRACT: return SIGRETRACT;
+#endif
+#if defined (SIGMSG)
+    case TARGET_SIGNAL_MSG: return SIGMSG;
+#endif
+#if defined (SIGSOUND)
+    case TARGET_SIGNAL_SOUND: return SIGSOUND;
+#endif
+#if defined (SIGSAK)
+    case TARGET_SIGNAL_SAK: return SIGSAK;
+#endif
+#if defined (SIGPRIO)
+    case TARGET_SIGNAL_PRIO: return SIGPRIO;
+#endif
+    default:
+#if defined (REALTIME_LO)
+      if (oursig >= TARGET_SIGNAL_REALTIME_33
+         && oursig <= TARGET_SIGNAL_REALTIME_63)
+       {
+         int retsig =
+           (int)oursig - (int)TARGET_SIGNAL_REALTIME_33 + REALTIME_LO;
+         if (retsig < REALTIME_HI)
+           return retsig;
+       }
+#endif
+      /* The user might be trying to do "signal SIGSAK" where this system
+        doesn't have SIGSAK.  */
+      warning ("Signal %s does not exist on this system.\n",
+              target_signal_to_name (oursig));
+      return 0;
+    }
+}
+
+/* Helper function for child_wait and the Lynx derivatives of child_wait.
+   HOSTSTATUS is the waitstatus from wait() or the equivalent; store our
+   translation of that in OURSTATUS.  */
+void
+store_waitstatus (ourstatus, hoststatus)
+     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;
+      ourstatus->value.integer = WEXITSTATUS (hoststatus);
+    }
+  else if (!WIFSTOPPED (hoststatus))
+    {
+      ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+      ourstatus->value.sig = target_signal_from_host (WTERMSIG (hoststatus));
+    }
+  else
+    {
+      ourstatus->kind = TARGET_WAITKIND_STOPPED;
+      ourstatus->value.sig = target_signal_from_host (WSTOPSIG (hoststatus));
+    }
+}
+\f
+/* In some circumstances we allow a command to specify a numeric
+   signal.  The idea is to keep these circumstances limited so that
+   users (and scripts) develop portable habits.  For comparison,
+   POSIX.2 `kill' requires that 1,2,3,6,9,14, and 15 work (and using a
+   numeric signal at all is obscelescent.  We are slightly more
+   lenient and allow 1-15 which should match host signal numbers on
+   most systems.  Use of symbolic signal names is strongly encouraged.  */
+
+enum target_signal
+target_signal_from_command (num)
+     int num;
+{
+  if (num >= 1 && num <= 15)
+    return (enum target_signal)num;
+  error ("Only signals 1-15 are valid as numeric signals.\n\
+Use \"info signals\" for a list of symbolic signals.");
+}
+\f
+/* Returns zero to leave the inferior alone, one to interrupt it.  */
+int (*target_activity_function) PARAMS ((void));
+int target_activity_fd;
+\f
+/* Convert a normal process ID to a string.  Returns the string in a static
+   buffer.  */
+
+char *
+normal_pid_to_str (pid)
+     int pid;
+{
+  static char buf[30];
+
+  if (STREQ (current_target.to_shortname, "remote"))
+    sprintf (buf, "thread %d", pid);
+  else
+    sprintf (buf, "process %d", pid);
+
+  return buf;
+}
+\f
+#ifdef MAINTENANCE_CMDS
+static struct target_ops debug_target;
+
+static void
+debug_to_open (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  debug_target.to_open (args, from_tty);
+
+  fprintf_unfiltered (stderr, "target_open (%s, %d)\n", args, from_tty);
+}
+
+static void
+debug_to_close (quitting)
+     int quitting;
+{
+  debug_target.to_close (quitting);
+
+  fprintf_unfiltered (stderr, "target_close (%d)\n", quitting);
+}
+
+static void
+debug_to_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  debug_target.to_attach (args, from_tty);
+
+  fprintf_unfiltered (stderr, "target_attach (%s, %d)\n", args, from_tty);
+}
+
+static void
+debug_to_detach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  debug_target.to_detach (args, from_tty);
+
+  fprintf_unfiltered (stderr, "target_detach (%s, %d)\n", args, from_tty);
+}
+
+static void
+debug_to_resume (pid, step, siggnal)
+     int pid;
+     int step;
+     enum target_signal siggnal;
+{
+  debug_target.to_resume (pid, step, siggnal);
+
+  fprintf_unfiltered (stderr, "target_resume (%d, %s, %s)\n", pid,
+                     step ? "step" : "continue",
+                     target_signal_to_name (siggnal));
+}
+
+static int
+debug_to_wait (pid, status)
+     int pid;
+     struct target_waitstatus *status;
+{
+  int retval;
+
+  retval = debug_target.to_wait (pid, status);
+
+  fprintf_unfiltered (stderr, "target_wait (%d, status) = %d,   ", pid, retval);
+  fprintf_unfiltered (stderr, "status->kind = ");
+  switch (status->kind)
+    {
+    case TARGET_WAITKIND_EXITED:
+      fprintf_unfiltered (stderr, "exited, status = %d\n", status->value.integer);
+      break;
+    case TARGET_WAITKIND_STOPPED:
+      fprintf_unfiltered (stderr, "stopped, signal = %s\n",
+                         target_signal_to_name (status->value.sig));
+      break;
+    case TARGET_WAITKIND_SIGNALLED:
+      fprintf_unfiltered (stderr, "signalled, signal = %s\n",
+                         target_signal_to_name (status->value.sig));
+      break;
+    case TARGET_WAITKIND_LOADED:
+      fprintf_unfiltered (stderr, "loaded\n");
+      break;
+    case TARGET_WAITKIND_SPURIOUS:
+      fprintf_unfiltered (stderr, "spurious\n");
+      break;
+    default:
+      fprintf_unfiltered (stderr, "unknown???\n");
+      break;
+    }
+
+  return retval;
+}
+
+static void
+debug_to_fetch_registers (regno)
+     int regno;
+{
+  debug_target.to_fetch_registers (regno);
+
+  fprintf_unfiltered (stderr, "target_fetch_registers (%s)",
+                     regno != -1 ? reg_names[regno] : "-1");
+  if (regno != -1)
+    fprintf_unfiltered (stderr, " = 0x%x %d", read_register (regno),
+                       read_register (regno));
+  fprintf_unfiltered (stderr, "\n");
+}
+
+static void
+debug_to_store_registers (regno)
+     int regno;
+{
+  debug_target.to_store_registers (regno);
+
+  if (regno >= 0 && regno < NUM_REGS)
+    fprintf_unfiltered (stderr, "target_store_registers (%s) = 0x%x %d\n",
+                       reg_names[regno], read_register (regno),
+                       read_register (regno));
+  else
+    fprintf_unfiltered (stderr, "target_store_registers (%d)\n", regno);
+}
+
+static void
+debug_to_prepare_to_store ()
+{
+  debug_target.to_prepare_to_store ();
+
+  fprintf_unfiltered (stderr, "target_prepare_to_store ()\n");
+}
+
+static int
+debug_to_xfer_memory (memaddr, myaddr, len, write, target)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+     struct target_ops *target;
+{
+  int retval;
+
+  retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write, target);
+
+  fprintf_unfiltered (stderr, "target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d",
+                     memaddr, len, write ? "write" : "read", retval);
+
+  if (retval > 0)
+    {
+      int i;
+
+      fputs_unfiltered (", bytes =", gdb_stderr);
+      for (i = 0; i < retval; i++)
+       fprintf_unfiltered (stderr, " %02x", myaddr[i] & 0xff);
+    }
+
+  fputc_unfiltered ('\n', gdb_stderr);
+
+  return retval;
+}
+
+static void
+debug_to_files_info (target)
+     struct target_ops *target;
+{
+  debug_target.to_files_info (target);
+
+  fprintf_unfiltered (stderr, "target_files_info (xxx)\n");
+}
+
+static int
+debug_to_insert_breakpoint (addr, save)
+     CORE_ADDR addr;
+     char *save;
+{
+  int retval;
+
+  retval = debug_target.to_insert_breakpoint (addr, save);
+
+  fprintf_unfiltered (stderr, "target_insert_breakpoint (0x%x, xxx) = %d\n",
+                     addr, retval);
+  return retval;
+}
+
+static int
+debug_to_remove_breakpoint (addr, save)
+     CORE_ADDR addr;
+     char *save;
+{
+  int retval;
+
+  retval = debug_target.to_remove_breakpoint (addr, save);
+
+  fprintf_unfiltered (stderr, "target_remove_breakpoint (0x%x, xxx) = %d\n",
+                     addr, retval);
+  return retval;
+}
+
+static void
+debug_to_terminal_init ()
+{
+  debug_target.to_terminal_init ();
+
+  fprintf_unfiltered (stderr, "target_terminal_init ()\n");
+}
+
+static void
+debug_to_terminal_inferior ()
+{
+  debug_target.to_terminal_inferior ();
+
+  fprintf_unfiltered (stderr, "target_terminal_inferior ()\n");
+}
+
+static void
+debug_to_terminal_ours_for_output ()
+{
+  debug_target.to_terminal_ours_for_output ();
+
+  fprintf_unfiltered (stderr, "target_terminal_ours_for_output ()\n");
+}
+
+static void
+debug_to_terminal_ours ()
+{
+  debug_target.to_terminal_ours ();
+
+  fprintf_unfiltered (stderr, "target_terminal_ours ()\n");
+}
+
+static void
+debug_to_terminal_info (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  debug_target.to_terminal_info (arg, from_tty);
+
+  fprintf_unfiltered (stderr, "target_terminal_info (%s, %d)\n", arg,
+                     from_tty);
+}
+
+static void
+debug_to_kill ()
+{
+  debug_target.to_kill ();
+
+  fprintf_unfiltered (stderr, "target_kill ()\n");
+}
+
+static void
+debug_to_load (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  debug_target.to_load (args, from_tty);
+
+  fprintf_unfiltered (stderr, "target_load (%s, %d)\n", args, from_tty);
+}
+
+static int
+debug_to_lookup_symbol (name, addrp)
+     char *name;
+     CORE_ADDR *addrp;
+{
+  int retval;
+
+  retval = debug_target.to_lookup_symbol (name, addrp);
+
+  fprintf_unfiltered (stderr, "target_lookup_symbol (%s, xxx)\n", name);
+
+  return retval;
+}
+
+static void
+debug_to_create_inferior (exec_file, args, env)
+     char *exec_file;
+     char *args;
+     char **env;
+{
+  debug_target.to_create_inferior (exec_file, args, env);
+
+  fprintf_unfiltered (stderr, "target_create_inferior (%s, %s, xxx)\n",
+                     exec_file, args);
+}
+
+static void
+debug_to_mourn_inferior ()
+{
+  debug_target.to_mourn_inferior ();
+
+  fprintf_unfiltered (stderr, "target_mourn_inferior ()\n");
+}
+
+static int
+debug_to_can_run ()
+{
+  int retval;
+
+  retval = debug_target.to_can_run ();
+
+  fprintf_unfiltered (stderr, "target_can_run () = %d\n", retval);
+
+  return retval;
+}
+
+static void
+debug_to_notice_signals (pid)
+     int pid;
+{
+  debug_target.to_notice_signals (pid);
+
+  fprintf_unfiltered (stderr, "target_notice_signals (%d)\n", pid);
+}
+
+static int
+debug_to_thread_alive (pid)
+     int pid;
+{
+  debug_target.to_thread_alive (pid);
+
+  fprintf_unfiltered (stderr, "target_thread_alive (%d)\n", pid);
+  return (0);
+}
+
+static void
+debug_to_stop ()
+{
+  debug_target.to_stop ();
+
+  fprintf_unfiltered (stderr, "target_stop ()\n");
+}
+
+static void
+setup_target_debug ()
+{
+  memcpy (&debug_target, &current_target, sizeof debug_target);
+
+  current_target.to_open = debug_to_open;
+  current_target.to_close = debug_to_close;
+  current_target.to_attach = debug_to_attach;
+  current_target.to_detach = debug_to_detach;
+  current_target.to_resume = debug_to_resume;
+  current_target.to_wait = debug_to_wait;
+  current_target.to_fetch_registers = debug_to_fetch_registers;
+  current_target.to_store_registers = debug_to_store_registers;
+  current_target.to_prepare_to_store = debug_to_prepare_to_store;
+  current_target.to_xfer_memory = debug_to_xfer_memory;
+  current_target.to_files_info = debug_to_files_info;
+  current_target.to_insert_breakpoint = debug_to_insert_breakpoint;
+  current_target.to_remove_breakpoint = debug_to_remove_breakpoint;
+  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;
+  current_target.to_terminal_ours = debug_to_terminal_ours;
+  current_target.to_terminal_info = debug_to_terminal_info;
+  current_target.to_kill = debug_to_kill;
+  current_target.to_load = debug_to_load;
+  current_target.to_lookup_symbol = debug_to_lookup_symbol;
+  current_target.to_create_inferior = debug_to_create_inferior;
+  current_target.to_mourn_inferior = debug_to_mourn_inferior;
+  current_target.to_can_run = debug_to_can_run;
+  current_target.to_notice_signals = debug_to_notice_signals;
+  current_target.to_thread_alive = debug_to_thread_alive;
+  current_target.to_stop = debug_to_stop;
+}
+#endif /* MAINTENANCE_CMDS */
+\f
+static char targ_desc[] = 
+    "Names of targets and files being debugged.\n\
+Shows the entire stack of targets currently in use (including the exec-file,\n\
+core-file, and process, if any), as well as the symbol file name.";
+
+void
+initialize_targets ()
+{
+  push_target (&dummy_target);
+
+  add_info ("target", target_info, targ_desc);
+  add_info ("files", target_info, targ_desc);
+
+#ifdef MAINTENANCE_CMDS
+  add_show_from_set (
+     add_set_cmd ("targetdebug", class_maintenance, var_zinteger,
+                 (char *)&targetdebug,
+                "Set target debugging.\n\
+When non-zero, target debugging is enabled.", &setlist),
+                    &showlist);
+#endif
+
+  if (!STREQ (signals[TARGET_SIGNAL_LAST].string, "TARGET_SIGNAL_MAGIC"))
+    abort ();
 }
This page took 0.042957 seconds and 4 git commands to generate.