2002-05-15 Nick Clifton <nickc@cambridge.redhat.com>
[deliverable/binutils-gdb.git] / gdb / remote.c
index bd8e68e7c6efc72d154baad8b45443362f21c9f5..a1b90b7a5a4f928cb98810c972cd68aaea0b1576 100644 (file)
@@ -1,6 +1,7 @@
 /* Remote target communications for serial-line targets in custom GDB protocol
-   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+   1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -85,7 +86,7 @@ static void remote_resume (ptid_t ptid, int step,
                            enum target_signal siggnal);
 static void remote_async_resume (ptid_t ptid, int step,
                                 enum target_signal siggnal);
-static int remote_start_remote (PTR);
+static int remote_start_remote (struct ui_out *uiout, void *dummy);
 
 static void remote_open (char *name, int from_tty);
 static void remote_async_open (char *name, int from_tty);
@@ -210,7 +211,7 @@ void open_remote_target (char *, int, struct target_ops *, int);
 
 void _initialize_remote (void);
 
-/* Description of the remote protocol.  Strictly speeking, when the
+/* Description of the remote protocol.  Strictly speaking, when the
    target is open()ed, remote.c should create a per-target description
    of the remote protocol using that target's architecture.
    Unfortunatly, the target stack doesn't include local state.  For
@@ -222,6 +223,7 @@ struct packet_reg
   long offset; /* Offset into G packet.  */
   long regnum; /* GDB's internal register number.  */
   LONGEST pnum; /* Remote protocol register number.  */
+  int in_g_packet; /* Always part of G packet.  */
   /* long size in bytes;  == REGISTER_RAW_SIZE (regnum); at present.  */
   /* char *name; == REGISTER_NAME (regnum); at present.  */
 };
@@ -230,7 +232,10 @@ struct remote_state
 {
   /* Description of the remote protocol registers.  */
   long sizeof_g_packet;
-  struct packet_reg *g_packet; /* NULL terminated.  */
+
+  /* Description of the remote protocol registers indexed by REGNUM
+     (making an array of NUM_REGS + NUM_PSEUDO_REGS in size).  */
+  struct packet_reg *regs;
 
   /* This is the size (in chars) of the first response to the ``g''
      packet.  It is used as a heuristic when determining the maximum
@@ -251,7 +256,7 @@ static struct gdbarch_data *remote_gdbarch_data_handle;
 static struct remote_state *
 get_remote_state ()
 {
-  return gdbarch_data (remote_gdbarch_data_handle);
+  return gdbarch_data (current_gdbarch, remote_gdbarch_data_handle);
 }
 
 static void *
@@ -264,16 +269,15 @@ init_remote_state (struct gdbarch *gdbarch)
      behavour - just copy in the description of the register cache.  */
   rs->sizeof_g_packet = REGISTER_BYTES; /* OK use.   */
 
-  /* Since, for the moment, the regcache is still being direct mapped,
-     there are exactly NUM_REGS.  Zero allocate a buffer adding space
-     for a sentinal.  */
-  rs->g_packet = xcalloc (NUM_REGS + 1, sizeof (struct packet_reg));
-  rs->g_packet[NUM_REGS].offset = -1;
-  for (regnum = 0; regnum < NUM_REGS; regnum++)
+  /* Assume a 1:1 regnum<->pnum table.  */
+  rs->regs = xcalloc (NUM_REGS + NUM_PSEUDO_REGS, sizeof (struct packet_reg));
+  for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
     {
-      rs->g_packet[regnum].pnum = regnum;
-      rs->g_packet[regnum].regnum = regnum;
-      rs->g_packet[regnum].offset = REGISTER_BYTE (regnum);
+      struct packet_reg *r = &rs->regs[regnum];
+      r->pnum = regnum;
+      r->regnum = regnum;
+      r->offset = REGISTER_BYTE (regnum);
+      r->in_g_packet = (regnum < NUM_REGS);
       /* ...size = REGISTER_RAW_SIZE (regnum); */
       /* ...name = REGISTER_NAME (regnum); */
     }
@@ -306,30 +310,32 @@ static void
 free_remote_state (struct gdbarch *gdbarch, void *pointer)
 {
   struct remote_state *data = pointer;
-  xfree (data->g_packet);
+  xfree (data->regs);
   xfree (data);
 }
 
 static struct packet_reg *
 packet_reg_from_regnum (struct remote_state *rs, long regnum)
 {
-  struct packet_reg *reg;
-  for (reg = rs->g_packet; reg->offset >= 0; reg++)
+  if (regnum < 0 && regnum >= NUM_REGS + NUM_PSEUDO_REGS)
+    return NULL;
+  else
     {
-      if (reg->regnum == regnum)
-       return reg;
+      struct packet_reg *r = &rs->regs[regnum];
+      gdb_assert (r->regnum == regnum);
+      return r;
     }
-  return NULL;
 }
 
 static struct packet_reg *
 packet_reg_from_pnum (struct remote_state *rs, LONGEST pnum)
 {
-  struct packet_reg *reg;
-  for (reg = rs->g_packet; reg->offset >= 0; reg++)
+  int i;
+  for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
     {
-      if (reg->pnum == pnum)
-       return reg;
+      struct packet_reg *r = &rs->regs[i];
+      if (r->pnum == pnum)
+       return r;
     }
   return NULL;
 }
@@ -669,7 +675,7 @@ add_packet_config_cmd (struct packet_config *config,
   set_cmd = add_set_auto_boolean_cmd (cmd_name, class_obscure,
                                &config->detect, set_doc,
                                set_remote_list);
-  set_cmd->function.sfunc = set_func;
+  set_cmd_sfunc (set_cmd, set_func);
   show_cmd = add_cmd (cmd_name, class_obscure, show_func, show_doc,
                      show_remote_list);
   /* set/show remote NAME-packet {auto,on,off} -- legacy */
@@ -964,8 +970,8 @@ show_remote_protocol_binary_download_cmd (char *args,
 
 
 /* Tokens for use by the asynchronous signal handlers for SIGINT */
-PTR sigint_remote_twice_token;
-PTR sigint_remote_token;
+static void *sigint_remote_twice_token;
+static void *sigint_remote_token;
 
 /* These are pointers to hook functions that may be set in order to
    modify resume/wait behavior for a particular architecture.  */
@@ -996,14 +1002,9 @@ record_currthread (int currthread)
   if (!in_thread_list (pid_to_ptid (currthread)))
     {
       add_thread (pid_to_ptid (currthread));
-#ifdef UI_OUT
       ui_out_text (uiout, "[New ");
       ui_out_text (uiout, target_pid_to_str (pid_to_ptid (currthread)));
       ui_out_text (uiout, "]\n");
-#else
-      printf_filtered ("[New %s]\n",
-                       target_pid_to_str (pid_to_ptid (currthread)));
-#endif
     }
 }
 
@@ -2106,14 +2107,16 @@ remote_cisco_objfile_relocate (bfd_signed_vma text_off, bfd_signed_vma data_off,
 /* Stub for catch_errors.  */
 
 static int
-remote_start_remote_dummy (void *dummy)
+remote_start_remote_dummy (struct ui_out *uiout, void *dummy)
 {
   start_remote ();             /* Initialize gdb process mechanisms */
+  /* NOTE: Return something >=0.  A -ve value is reserved for
+     catch_exceptions.  */
   return 1;
 }
 
 static int
-remote_start_remote (PTR dummy)
+remote_start_remote (struct ui_out *uiout, void *dummy)
 {
   immediate_quit++;            /* Allow user to interrupt it */
 
@@ -2130,7 +2133,9 @@ remote_start_remote (PTR dummy)
   putpkt ("?");                        /* initiate a query from remote machine */
   immediate_quit--;
 
-  return remote_start_remote_dummy (dummy);
+  /* NOTE: See comment above in remote_start_remote_dummy().  This
+     function returns something >=0.  */
+  return remote_start_remote_dummy (uiout, dummy);
 }
 
 /* Open a connection to a remote debugger.
@@ -2221,10 +2226,31 @@ remote_check_symbols (struct objfile *objfile)
     }
 }
 
+static struct serial *
+remote_serial_open (char *name)
+{
+  static int udp_warning = 0;
+
+  /* FIXME: Parsing NAME here is a hack.  But we want to warn here instead
+     of in ser-tcp.c, because it is the remote protocol assuming that the
+     serial connection is reliable and not the serial connection promising
+     to be.  */
+  if (!udp_warning && strncmp (name, "udp:", 4) == 0)
+    {
+      warning ("The remote protocol may be unreliable over UDP.");
+      warning ("Some events may be lost, rendering further debugging "
+              "impossible.");
+      udp_warning = 1;
+    }
+
+  return serial_open (name);
+}
+
 static void
 remote_open_1 (char *name, int from_tty, struct target_ops *target,
               int extended_p)
 {
+  int ex;
   struct remote_state *rs = get_remote_state ();
   if (name == 0)
     error ("To open a remote debug connection, you need to specify what\n"
@@ -2238,7 +2264,7 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target,
 
   unpush_target (target);
 
-  remote_desc = serial_open (name);
+  remote_desc = remote_serial_open (name);
   if (!remote_desc)
     perror_with_name (name);
 
@@ -2287,15 +2313,30 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target,
   no_shared_libraries (NULL, 0);
 #endif
 
-  /* Start the remote connection; if error (0), discard this target.
-     In particular, if the user quits, be sure to discard it
-     (we'd be in an inconsistent state otherwise).  */
-  if (!catch_errors (remote_start_remote, NULL,
-                    "Couldn't establish connection to remote target\n",
-                    RETURN_MASK_ALL))
+  /* Start the remote connection.  If error() or QUIT, discard this
+     target (we'd otherwise be in an inconsistent state) and then
+     propogate the error on up the exception chain.  This ensures that
+     the caller doesn't stumble along blindly assuming that the
+     function succeeded.  The CLI doesn't have this problem but other
+     UI's, such as MI do.
+
+     FIXME: cagney/2002-05-19: Instead of re-throwing the exception,
+     this function should return an error indication letting the
+     caller restore the previous state.  Unfortunatly the command
+     ``target remote'' is directly wired to this function making that
+     impossible.  On a positive note, the CLI side of this problem has
+     been fixed - the function set_cmd_context() makes it possible for
+     all the ``target ....'' commands to share a common callback
+     function.  See cli-dump.c.  */
+  ex = catch_exceptions (uiout,
+                        remote_start_remote, NULL,
+                        "Couldn't establish connection to remote"
+                        " target\n",
+                        RETURN_MASK_ALL);
+  if (ex < 0)
     {
       pop_target ();
-      return;
+      throw_exception (ex);
     }
 
   if (extended_p)
@@ -2326,6 +2367,7 @@ static void
 remote_async_open_1 (char *name, int from_tty, struct target_ops *target,
                     int extended_p)
 {
+  int ex;
   struct remote_state *rs = get_remote_state ();
   if (name == 0)
     error ("To open a remote debug connection, you need to specify what\n"
@@ -2336,7 +2378,7 @@ remote_async_open_1 (char *name, int from_tty, struct target_ops *target,
 
   unpush_target (target);
 
-  remote_desc = serial_open (name);
+  remote_desc = remote_serial_open (name);
   if (!remote_desc)
     perror_with_name (name);
 
@@ -2398,16 +2440,19 @@ remote_async_open_1 (char *name, int from_tty, struct target_ops *target,
   no_shared_libraries (NULL, 0);
 #endif
 
-  /* Start the remote connection; if error (0), discard this target.
-     In particular, if the user quits, be sure to discard it
-     (we'd be in an inconsistent state otherwise).  */
-  if (!catch_errors (remote_start_remote, NULL,
-                    "Couldn't establish connection to remote target\n",
-                    RETURN_MASK_ALL))
+  /* Start the remote connection; if error, discard this target.  See
+     the comments in remote_open_1() for further details such as the
+     need to re-throw the exception.  */
+  ex = catch_exceptions (uiout,
+                        remote_start_remote, NULL,
+                        "Couldn't establish connection to remote"
+                        " target\n",
+                        RETURN_MASK_ALL);
+  if (ex < 0)
     {
       pop_target ();
       wait_forever_enabled_p = 1;
-      return;
+      throw_exception (ex);
     }
 
   wait_forever_enabled_p = 1;
@@ -2876,7 +2921,7 @@ interrupt_query (void)
 Give up (and stop debugging it)? "))
     {
       target_mourn_inferior ();
-      return_to_top_level (RETURN_QUIT);
+      throw_exception (RETURN_QUIT);
     }
 
   target_terminal_inferior ();
@@ -3406,6 +3451,16 @@ remote_fetch_registers (int regnum)
 
   set_thread (PIDGET (inferior_ptid), 1);
 
+  if (regnum >= 0)
+    {
+      struct packet_reg *reg = packet_reg_from_regnum (rs, regnum);
+      gdb_assert (reg != NULL);
+      if (!reg->in_g_packet)
+       internal_error (__FILE__, __LINE__,
+                       "Attempt to fetch a non G-packet register when this "
+                       "remote.c does not support the p-packet.");
+    }
+
   sprintf (buf, "g");
   remote_send (buf, (rs->remote_packet_size));
 
@@ -3462,14 +3517,18 @@ remote_fetch_registers (int regnum)
        warning ("Remote reply is too short: %s", buf);
     }
 
-supply_them:
+ supply_them:
   {
-    struct packet_reg *g;
-    for (g = rs->g_packet; g->offset >= 0; g++)
+    int i;
+    for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
       {
-       supply_register (g->regnum, regs + g->offset);
-       if (buf[g->offset * 2] == 'x')
-         set_register_cached (i, -1);
+       struct packet_reg *r = &rs->regs[i];
+       if (r->in_g_packet)
+         {
+           supply_register (r->regnum, regs + r->offset);
+           if (buf[r->offset * 2] == 'x')
+             set_register_cached (i, -1);
+         }
       }
   }
 }
@@ -3566,12 +3625,14 @@ remote_store_registers (int regnum)
   /* Extract all the registers in the regcache copying them into a
      local buffer.  */
   {
-    struct packet_reg *g;
+    int i;
     regs = alloca (rs->sizeof_g_packet);
     memset (regs, rs->sizeof_g_packet, 0);
-    for (g = rs->g_packet; g->offset >= 0; g++)
+    for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
       {
-       regcache_collect (g->regnum, regs + g->offset);
+       struct packet_reg *r = &rs->regs[i];
+       if (r->in_g_packet)
+         regcache_collect (r->regnum, regs + r->offset);
       }
   }
 
@@ -3922,8 +3983,7 @@ remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
 /* ARGSUSED */
 static int
 remote_xfer_memory (CORE_ADDR mem_addr, char *buffer, int mem_len,
-                   int should_write,
-                   struct mem_attrib *attrib ATTRIBUTE_UNUSED,
+                   int should_write, struct mem_attrib *attrib,
                    struct target_ops *target)
 {
   CORE_ADDR targ_addr;
@@ -4660,7 +4720,7 @@ remote_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
 
   if (val == 0)
     {
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
        val = target_write_memory (addr, (char *) big_break_insn,
                                   sizeof big_break_insn);
       else
@@ -4997,8 +5057,8 @@ compare_sections_command (char *args, int from_tty)
 
       getpkt (buf, (rs->remote_packet_size), 0);
       if (buf[0] == 'E')
-       error ("target memory fault, section %s, range 0x%08x -- 0x%08x",
-              sectname, lma, lma + size);
+       error ("target memory fault, section %s, range 0x%s -- 0x%s",
+              sectname, paddr (lma), paddr (lma + size));
       if (buf[0] != 'C')
        error ("remote target does not support this operation");
 
@@ -5436,6 +5496,7 @@ remote_info_process (char *args, int from_tty)
 static void
 remote_cisco_open (char *name, int from_tty)
 {
+  int ex;
   if (name == 0)
     error ("To open a remote debug connection, you need to specify what \n"
           "device is attached to the remote system (e.g. host:port).");
@@ -5447,7 +5508,7 @@ remote_cisco_open (char *name, int from_tty)
 
   unpush_target (&remote_cisco_ops);
 
-  remote_desc = serial_open (name);
+  remote_desc = remote_serial_open (name);
   if (!remote_desc)
     perror_with_name (name);
 
@@ -5498,14 +5559,18 @@ remote_cisco_open (char *name, int from_tty)
      someday have a notion of debugging several processes.  */
   inferior_ptid = pid_to_ptid (MAGIC_NULL_PID);
 
-  /* Start the remote connection; if error (0), discard this target. */
-
-  if (!catch_errors (remote_start_remote_dummy, (char *) 0,
-                    "Couldn't establish connection to remote target\n",
-                    RETURN_MASK_ALL))
+  /* Start the remote connection; if error, discard this target.  See
+     the comments in remote_open_1() for further details such as the
+     need to re-throw the exception.  */
+  ex = catch_exceptions (uiout,
+                        remote_start_remote_dummy, NULL,
+                        "Couldn't establish connection to remote"
+                        " target\n",
+                        RETURN_MASK_ALL);
+  if (ex < 0)
     {
       pop_target ();
-      return;
+      throw_exception (ex);
     }
 }
 
@@ -5701,7 +5766,7 @@ minitelnet (void)
              if (query ("Interrupt GDB? "))
                {
                  printf_filtered ("Interrupted by user.\n");
-                 return_to_top_level (RETURN_QUIT);
+                 throw_exception (RETURN_QUIT);
                }
              quit_count = 0;
            }
@@ -6083,6 +6148,10 @@ in a memory packet.\n",
                         show_remote_protocol_e_packet_cmd,
                         &remote_set_cmdlist, &remote_show_cmdlist,
                         0);
+  /* Disable by default.  The ``e'' packet has nasty interactions with
+     the threading code - it relies on global state.  */
+  remote_protocol_e.detect = CMD_AUTO_BOOLEAN_FALSE;
+  update_packet_config (&remote_protocol_e);
 
   add_packet_config_cmd (&remote_protocol_E,
                         "E", "step-over-range-w-signal",
@@ -6090,6 +6159,10 @@ in a memory packet.\n",
                         show_remote_protocol_E_packet_cmd,
                         &remote_set_cmdlist, &remote_show_cmdlist,
                         0);
+  /* Disable by default.  The ``e'' packet has nasty interactions with
+     the threading code - it relies on global state.  */
+  remote_protocol_E.detect = CMD_AUTO_BOOLEAN_FALSE;
+  update_packet_config (&remote_protocol_E);
 
   add_packet_config_cmd (&remote_protocol_P,
                         "P", "set-register",
@@ -6138,7 +6211,7 @@ in a memory packet.\n",
                                     &remote_Z_packet_detect,
                                     "\
 Set use of remote protocol `Z' packets", &remote_set_cmdlist);
-  tmpcmd->function.sfunc = set_remote_protocol_Z_packet_cmd;
+  set_cmd_sfunc (tmpcmd, set_remote_protocol_Z_packet_cmd);
   add_cmd ("Z-packet", class_obscure, show_remote_protocol_Z_packet_cmd,
           "Show use of remote protocol `Z' packets ",
           &remote_show_cmdlist);
This page took 0.030388 seconds and 4 git commands to generate.