2007-04-16 Denis Pilat <denis.pilat@st.com>
[deliverable/binutils-gdb.git] / gdb / remote.c
index e758412fe2ae955490f4b2793ed058dfb079b68e..866c477b748f48b3fac2f53a09f785857e2ac101 100644 (file)
@@ -1,7 +1,7 @@
 /* Remote target communications for serial-line targets in custom GDB protocol
 
-   Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
-   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -334,12 +334,19 @@ init_remote_state (struct gdbarch *gdbarch)
 
   rsa = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct remote_arch_state);
 
-  /* Assume a 1:1 regnum<->pnum table.  */
+  /* Use the architecture to build a regnum<->pnum table, which will be
+     1:1 unless a feature set specifies otherwise.  */
   rsa->regs = GDBARCH_OBSTACK_CALLOC (gdbarch, NUM_REGS, struct packet_reg);
   for (regnum = 0; regnum < NUM_REGS; regnum++)
     {
       struct packet_reg *r = &rsa->regs[regnum];
-      r->pnum = regnum;
+
+      if (register_size (current_gdbarch, regnum) == 0)
+       /* Do not try to fetch zero-sized (placeholder) registers.  */
+       r->pnum = -1;
+      else
+       r->pnum = gdbarch_remote_register_number (gdbarch, regnum);
+
       r->regnum = regnum;
     }
 
@@ -893,6 +900,7 @@ enum {
   PACKET_Z3,
   PACKET_Z4,
   PACKET_qXfer_auxv,
+  PACKET_qXfer_features,
   PACKET_qXfer_memory_map,
   PACKET_qGetTLSAddr,
   PACKET_qSupported,
@@ -996,8 +1004,8 @@ static int use_threadinfo_query;
 static int use_threadextra_query;
 
 /* Tokens for use by the asynchronous signal handlers for SIGINT.  */
-static void *sigint_remote_twice_token;
-static void *sigint_remote_token;
+static struct async_signal_handler *sigint_remote_twice_token;
+static struct async_signal_handler *sigint_remote_token;
 
 /* These are pointers to hook functions that may be set in order to
    modify resume/wait behavior for a particular architecture.  */
@@ -2294,6 +2302,8 @@ static struct protocol_feature remote_protocol_features[] = {
   { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
   { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_auxv },
+  { "qXfer:features:read", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_features },
   { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_memory_map },
   { "QPassSignals", PACKET_DISABLE, remote_supported_packet,
@@ -2945,11 +2955,9 @@ cleanup_sigint_signal_handler (void *dummy)
 {
   signal (SIGINT, handle_sigint);
   if (sigint_remote_twice_token)
-    delete_async_signal_handler ((struct async_signal_handler **)
-                                &sigint_remote_twice_token);
+    delete_async_signal_handler (&sigint_remote_twice_token);
   if (sigint_remote_token)
-    delete_async_signal_handler ((struct async_signal_handler **)
-                                &sigint_remote_token);
+    delete_async_signal_handler (&sigint_remote_token);
 }
 
 /* Send ^C to target to halt it.  Target will respond, and send us a
@@ -3535,11 +3543,10 @@ fetch_register_using_p (struct packet_reg *reg)
 
 /* Fetch the registers included in the target's 'g' packet.  */
 
-static void
-fetch_registers_using_g (void)
+static int
+send_g_packet (void)
 {
   struct remote_state *rs = get_remote_state ();
-  struct remote_arch_state *rsa = get_remote_arch_state ();
   int i, buf_len;
   char *p;
   char *regs;
@@ -3547,11 +3554,41 @@ fetch_registers_using_g (void)
   sprintf (rs->buf, "g");
   remote_send (&rs->buf, &rs->buf_size);
 
+  /* We can get out of synch in various cases.  If the first character
+     in the buffer is not a hex character, assume that has happened
+     and try to fetch another packet to read.  */
+  while ((rs->buf[0] < '0' || rs->buf[0] > '9')
+        && (rs->buf[0] < 'A' || rs->buf[0] > 'F')
+        && (rs->buf[0] < 'a' || rs->buf[0] > 'f')
+        && rs->buf[0] != 'x')  /* New: unavailable register value.  */
+    {
+      if (remote_debug)
+       fprintf_unfiltered (gdb_stdlog,
+                           "Bad register packet; fetching a new packet\n");
+      getpkt (&rs->buf, &rs->buf_size, 0);
+    }
+
   buf_len = strlen (rs->buf);
 
   /* Sanity check the received packet.  */
   if (buf_len % 2 != 0)
     error (_("Remote 'g' packet reply is of odd length: %s"), rs->buf);
+
+  return buf_len / 2;
+}
+
+static void
+process_g_packet (void)
+{
+  struct remote_state *rs = get_remote_state ();
+  struct remote_arch_state *rsa = get_remote_arch_state ();
+  int i, buf_len;
+  char *p;
+  char *regs;
+
+  buf_len = strlen (rs->buf);
+
+  /* Further sanity checks, with knowledge of the architecture.  */
   if (REGISTER_BYTES_OK_P () && !REGISTER_BYTES_OK (buf_len / 2))
     error (_("Remote 'g' packet reply is wrong length: %s"), rs->buf);
   if (buf_len > 2 * rsa->sizeof_g_packet)
@@ -3588,20 +3625,6 @@ fetch_registers_using_g (void)
   /* Unimplemented registers read as all bits zero.  */
   memset (regs, 0, rsa->sizeof_g_packet);
 
-  /* We can get out of synch in various cases.  If the first character
-     in the buffer is not a hex character, assume that has happened
-     and try to fetch another packet to read.  */
-  while ((rs->buf[0] < '0' || rs->buf[0] > '9')
-        && (rs->buf[0] < 'A' || rs->buf[0] > 'F')
-        && (rs->buf[0] < 'a' || rs->buf[0] > 'f')
-        && rs->buf[0] != 'x')  /* New: unavailable register value.  */
-    {
-      if (remote_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "Bad register packet; fetching a new packet\n");
-      getpkt (&rs->buf, &rs->buf_size, 0);
-    }
-
   /* Reply describes registers byte by byte, each byte encoded as two
      hex characters.  Suck them all up, then supply them to the
      register cacheing/storage mechanism.  */
@@ -3648,6 +3671,13 @@ fetch_registers_using_g (void)
   }
 }
 
+static void
+fetch_registers_using_g (void)
+{
+  send_g_packet ();
+  process_g_packet ();
+}
+
 static void
 remote_fetch_registers (int regnum)
 {
@@ -5078,35 +5108,6 @@ extended_remote_async_create_inferior (char *exec_file, char *args,
 }
 \f
 
-/* On some machines, e.g. 68k, we may use a different breakpoint
-   instruction than other targets; in those use
-   DEPRECATED_REMOTE_BREAKPOINT instead of just BREAKPOINT_FROM_PC.
-   Also, bi-endian targets may define
-   DEPRECATED_LITTLE_REMOTE_BREAKPOINT and
-   DEPRECATED_BIG_REMOTE_BREAKPOINT.  If none of these are defined, we
-   just call the standard routines that are in mem-break.c.  */
-
-/* NOTE: cagney/2003-06-08: This is silly.  A remote and simulator
-   target should use an identical BREAKPOINT_FROM_PC.  As for native,
-   the ARCH-OS-tdep.c code can override the default.  */
-
-#if defined (DEPRECATED_LITTLE_REMOTE_BREAKPOINT) && defined (DEPRECATED_BIG_REMOTE_BREAKPOINT) && !defined(DEPRECATED_REMOTE_BREAKPOINT)
-#define DEPRECATED_REMOTE_BREAKPOINT
-#endif
-
-#ifdef DEPRECATED_REMOTE_BREAKPOINT
-
-/* If the target isn't bi-endian, just pretend it is.  */
-#if !defined (DEPRECATED_LITTLE_REMOTE_BREAKPOINT) && !defined (DEPRECATED_BIG_REMOTE_BREAKPOINT)
-#define DEPRECATED_LITTLE_REMOTE_BREAKPOINT DEPRECATED_REMOTE_BREAKPOINT
-#define DEPRECATED_BIG_REMOTE_BREAKPOINT DEPRECATED_REMOTE_BREAKPOINT
-#endif
-
-static unsigned char big_break_insn[] = DEPRECATED_BIG_REMOTE_BREAKPOINT;
-static unsigned char little_break_insn[] = DEPRECATED_LITTLE_REMOTE_BREAKPOINT;
-
-#endif /* DEPRECATED_REMOTE_BREAKPOINT */
-
 /* Insert a breakpoint.  On targets that have software breakpoint
    support, we ask the remote target to do the work; on targets
    which don't, we insert a traditional memory breakpoint.  */
@@ -5116,9 +5117,6 @@ remote_insert_breakpoint (struct bp_target_info *bp_tgt)
 {
   CORE_ADDR addr = bp_tgt->placed_address;
   struct remote_state *rs = get_remote_state ();
-#ifdef DEPRECATED_REMOTE_BREAKPOINT
-  int val;
-#endif
 
   /* Try the "Z" s/w breakpoint packet if it is not already disabled.
      If it succeeds, then set the support to PACKET_ENABLE.  If it
@@ -5151,24 +5149,7 @@ remote_insert_breakpoint (struct bp_target_info *bp_tgt)
        }
     }
 
-#ifdef DEPRECATED_REMOTE_BREAKPOINT
-  bp_tgt->placed_size = bp_tgt->shadow_len = sizeof big_break_insn;
-  val = target_read_memory (addr, bp_tgt->shadow_contents, bp_tgt->shadow_len);
-
-  if (val == 0)
-    {
-      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-       val = target_write_memory (addr, (char *) big_break_insn,
-                                  sizeof big_break_insn);
-      else
-       val = target_write_memory (addr, (char *) little_break_insn,
-                                  sizeof little_break_insn);
-    }
-
-  return val;
-#else
   return memory_insert_breakpoint (bp_tgt);
-#endif /* DEPRECATED_REMOTE_BREAKPOINT */
 }
 
 static int
@@ -5196,12 +5177,7 @@ remote_remove_breakpoint (struct bp_target_info *bp_tgt)
       return (rs->buf[0] == 'E');
     }
 
-#ifdef DEPRECATED_REMOTE_BREAKPOINT
-  return target_write_memory (bp_tgt->placed_address, bp_tgt->shadow_contents,
-                             bp_tgt->shadow_len);
-#else
   return memory_remove_breakpoint (bp_tgt);
-#endif /* DEPRECATED_REMOTE_BREAKPOINT */
 }
 
 static int
@@ -5696,6 +5672,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
       return remote_read_qxfer (ops, "auxv", annex, readbuf, offset, len,
                                &remote_protocol_packets[PACKET_qXfer_auxv]);
 
+    case TARGET_OBJECT_AVAILABLE_FEATURES:
+      return remote_read_qxfer
+       (ops, "features", annex, readbuf, offset, len,
+        &remote_protocol_packets[PACKET_qXfer_features]);
+
     case TARGET_OBJECT_MEMORY_MAP:
       gdb_assert (annex == NULL);
       return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
@@ -6052,6 +6033,83 @@ remote_get_thread_local_address (ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset)
   return 0;
 }
 
+/* Support for inferring a target description based on the current
+   architecture and the size of a 'g' packet.  While the 'g' packet
+   can have any size (since optional registers can be left off the
+   end), some sizes are easily recognizable given knowledge of the
+   approximate architecture.  */
+
+struct remote_g_packet_guess
+{
+  int bytes;
+  const struct target_desc *tdesc;
+};
+typedef struct remote_g_packet_guess remote_g_packet_guess_s;
+DEF_VEC_O(remote_g_packet_guess_s);
+
+struct remote_g_packet_data
+{
+  VEC(remote_g_packet_guess_s) *guesses;
+};
+
+static struct gdbarch_data *remote_g_packet_data_handle;
+
+static void *
+remote_g_packet_data_init (struct obstack *obstack)
+{
+  return OBSTACK_ZALLOC (obstack, struct remote_g_packet_data);
+}
+
+void
+register_remote_g_packet_guess (struct gdbarch *gdbarch, int bytes,
+                               const struct target_desc *tdesc)
+{
+  struct remote_g_packet_data *data
+    = gdbarch_data (gdbarch, remote_g_packet_data_handle);
+  struct remote_g_packet_guess new_guess, *guess;
+  int ix;
+
+  gdb_assert (tdesc != NULL);
+
+  for (ix = 0;
+       VEC_iterate (remote_g_packet_guess_s, data->guesses, ix, guess);
+       ix++)
+    if (guess->bytes == bytes)
+      internal_error (__FILE__, __LINE__,
+                     "Duplicate g packet description added for size %d",
+                     bytes);
+
+  new_guess.bytes = bytes;
+  new_guess.tdesc = tdesc;
+  VEC_safe_push (remote_g_packet_guess_s, data->guesses, &new_guess);
+}
+
+static const struct target_desc *
+remote_read_description (struct target_ops *target)
+{
+  struct remote_g_packet_data *data
+    = gdbarch_data (current_gdbarch, remote_g_packet_data_handle);
+
+  if (!VEC_empty (remote_g_packet_guess_s, data->guesses))
+    {
+      struct remote_g_packet_guess *guess;
+      int ix;
+      int bytes = send_g_packet ();
+
+      for (ix = 0;
+          VEC_iterate (remote_g_packet_guess_s, data->guesses, ix, guess);
+          ix++)
+       if (guess->bytes == bytes)
+         return guess->tdesc;
+
+      /* We discard the g packet.  A minor optimization would be to
+        hold on to it, and fill the register cache once we have selected
+        an architecture, but it's too tricky to do safely.  */
+    }
+
+  return NULL;
+}
+
 static void
 init_remote_ops (void)
 {
@@ -6103,6 +6161,7 @@ Specify the serial device it is connected to\n\
   remote_ops.to_memory_map = remote_memory_map;
   remote_ops.to_flash_erase = remote_flash_erase;
   remote_ops.to_flash_done = remote_flash_done;
+  remote_ops.to_read_description = remote_read_description;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
@@ -6235,6 +6294,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
   remote_async_ops.to_memory_map = remote_memory_map;
   remote_async_ops.to_flash_erase = remote_flash_erase;
   remote_async_ops.to_flash_done = remote_flash_done;
+  remote_ops.to_read_description = remote_read_description;
 }
 
 /* Set up the async extended remote vector by making a copy of the standard
@@ -6326,6 +6386,8 @@ _initialize_remote (void)
   /* architecture specific data */
   remote_gdbarch_data_handle =
     gdbarch_data_register_post_init (init_remote_state);
+  remote_g_packet_data_handle =
+    gdbarch_data_register_pre_init (remote_g_packet_data_init);
 
   /* Old tacky stuff.  NOTE: This comes after the remote protocol so
      that the remote protocol has been initialized.  */
@@ -6488,6 +6550,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_auxv],
                         "qXfer:auxv:read", "read-aux-vector", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_features],
+                        "qXfer:features:read", "target-features", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map],
                         "qXfer:memory-map:read", "memory-map", 0);
 
This page took 0.037525 seconds and 4 git commands to generate.