* Makefile.in (mips-tdep.o, target-descriptions.o): Update.
authorDaniel Jacobowitz <drow@false.org>
Tue, 28 Nov 2006 22:14:31 +0000 (22:14 +0000)
committerDaniel Jacobowitz <drow@false.org>
Tue, 28 Nov 2006 22:14:31 +0000 (22:14 +0000)
* target-descriptions.c (struct property): New.
(struct target_desc): Add properties member.
(tdesc_property, set_tdesc_property): New.
* target-descriptions.h (tdesc_property, set_tdesc_property):
Declare.
* mips-tdep.c (PROPERTY_GP32, PROPERTY_GP64): New constants.
(struct gdbarch_tdep): Add register_size_valid_p and register_size.
(mips_isa_regsize): Use them.
(mips_register_g_packet_guesses): New.
(mips_gdbarch_init): Call it.  If a target description is supplied,
check for internal properties.  Check for register size mismatches.
* remote.c (send_g_packet, process_g_packet): New functions, split
out from fetch_registers_using_g.
(fetch_registers_using_g): Use them.
(struct remote_g_packet_guess, remote_g_packet_guess_s)
(struct remote_g_packet_data, remote_g_packet_data_handle)
(remote_g_packet_data_init, register_remote_g_packet_guess)
(remote_read_description): New.
(init_remote_ops, init_remote_async_ops): Set to_read_description.
(_initialize_remote): Register remote_g_packet_data_handle.
* remote.h (register_remote_g_packet_guess): Declare.

gdb/ChangeLog
gdb/Makefile.in
gdb/mips-tdep.c
gdb/remote.c
gdb/remote.h
gdb/target-descriptions.c
gdb/target-descriptions.h

index ab8040e89cdfc8a004607d3f2077e91a163d5d93..96f8c93891666a7c8ca5f350fd55dc421ba692a4 100644 (file)
@@ -1,3 +1,28 @@
+2006-11-28  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * Makefile.in (mips-tdep.o, target-descriptions.o): Update.
+       * target-descriptions.c (struct property): New.
+       (struct target_desc): Add properties member.
+       (tdesc_property, set_tdesc_property): New.
+       * target-descriptions.h (tdesc_property, set_tdesc_property):
+       Declare.
+       * mips-tdep.c (PROPERTY_GP32, PROPERTY_GP64): New constants.
+       (struct gdbarch_tdep): Add register_size_valid_p and register_size.
+       (mips_isa_regsize): Use them.
+       (mips_register_g_packet_guesses): New.
+       (mips_gdbarch_init): Call it.  If a target description is supplied,
+       check for internal properties.  Check for register size mismatches.
+       * remote.c (send_g_packet, process_g_packet): New functions, split
+       out from fetch_registers_using_g.
+       (fetch_registers_using_g): Use them.
+       (struct remote_g_packet_guess, remote_g_packet_guess_s)
+       (struct remote_g_packet_data, remote_g_packet_data_handle)
+       (remote_g_packet_data_init, register_remote_g_packet_guess)
+       (remote_read_description): New.
+       (init_remote_ops, init_remote_async_ops): Set to_read_description.
+       (_initialize_remote): Register remote_g_packet_data_handle.
+       * remote.h (register_remote_g_packet_guess): Declare.
+
 2006-11-28  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * Makefile.in (SFILES): Add new and missed files.
index c98e5b94c4b9b322626fc90e6565b9a2866364e5..695a3a77a5dbe395e229dad6f02b8c8b50fcf8e0 100644 (file)
@@ -2382,7 +2382,7 @@ mips-tdep.o: mips-tdep.c $(defs_h) $(gdb_string_h) $(gdb_assert_h) \
        $(block_h) $(reggroups_h) $(opcode_mips_h) $(elf_mips_h) \
        $(elf_bfd_h) $(symcat_h) $(sim_regno_h) $(dis_asm_h) \
        $(frame_unwind_h) $(frame_base_h) $(trad_frame_h) $(infcall_h) \
-       $(floatformat_h)
+       $(floatformat_h) $(remote_h) $(target_descriptions_h)
 mipsv4-nat.o: mipsv4-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(target_h) \
        $(regcache_h) $(gregset_h)
 memory-map.o: memory-map.c $(defs_h) $(memory_map_h) $(xml_support_h) \
@@ -2780,7 +2780,7 @@ target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
        $(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \
        $(exceptions_h) $(target_descriptions_h)
 target-descriptions.o: target-descriptions.c $(defs_h) $(arch_utils_h) \
-       $(target_h) $(target_descriptions_h) $(gdb_assert_h)
+       $(target_h) $(target_descriptions_h) $(vec_h) $(gdb_assert_h)
 target-memory.o: target-memory.c $(defs_h) $(vec_h) $(target_h) \
        $(memory_map_h) $(gdb_assert_h)
 thread.o: thread.c $(defs_h) $(symtab_h) $(frame_h) $(inferior_h) \
index 19f0e0dfa8244c45d628ff41576463ba29ac8b9c..8b3ddb8870a4e012d5fb850789b308d1dceb25a7 100644 (file)
@@ -55,6 +55,8 @@
 #include "trad-frame.h"
 #include "infcall.h"
 #include "floatformat.h"
+#include "remote.h"
+#include "target-descriptions.h"
 
 static const struct objfile_data *mips_pdr_data;
 
@@ -119,6 +121,11 @@ static enum mips_fpu_type mips_fpu_type = MIPS_DEFAULT_FPU_TYPE;
 
 static int mips_debug = 0;
 
+/* Properties (for struct target_desc) describing the g/G packet
+   layout.  */
+#define PROPERTY_GP32 "internal: transfers-32bit-registers"
+#define PROPERTY_GP64 "internal: transfers-64bit-registers"
+
 /* MIPS specific per-architecture information */
 struct gdbarch_tdep
 {
@@ -141,6 +148,13 @@ struct gdbarch_tdep
   const struct mips_regnum *regnum;
   /* Register names table for the current register set.  */
   const char **mips_processor_reg_names;
+
+  /* The size of register data available from the target, if known.
+     This doesn't quite obsolete the manual
+     mips64_transfers_32bit_regs_p, since that is documented to force
+     left alignment even for big endian (very strange).  */
+  int register_size_valid_p;
+  int register_size;
 };
 
 static int
@@ -245,6 +259,13 @@ mips_abi (struct gdbarch *gdbarch)
 int
 mips_isa_regsize (struct gdbarch *gdbarch)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* If we know how big the registers are, use that size.  */
+  if (tdep->register_size_valid_p)
+    return tdep->register_size;
+
+  /* Fall back to the previous behavior.  */
   return (gdbarch_bfd_arch_info (gdbarch)->bits_per_word
          / gdbarch_bfd_arch_info (gdbarch)->bits_per_byte);
 }
@@ -4711,6 +4732,37 @@ global_mips_abi (void)
   internal_error (__FILE__, __LINE__, _("unknown ABI string"));
 }
 
+static void
+mips_register_g_packet_guesses (struct gdbarch *gdbarch)
+{
+  static struct target_desc *tdesc_gp32, *tdesc_gp64;
+
+  if (tdesc_gp32 == NULL)
+    {
+      /* Create feature sets with the appropriate properties.  The values
+        are not important.  */
+
+      tdesc_gp32 = allocate_target_description ();
+      set_tdesc_property (tdesc_gp32, PROPERTY_GP32, "");
+
+      tdesc_gp64 = allocate_target_description ();
+      set_tdesc_property (tdesc_gp64, PROPERTY_GP64, "");
+    }
+
+  /* If the size matches the set of 32-bit or 64-bit integer registers,
+     assume that's what we've got.  */
+  register_remote_g_packet_guess (gdbarch, 38 * 4, tdesc_gp32);
+  register_remote_g_packet_guess (gdbarch, 38 * 8, tdesc_gp64);
+
+  /* If the size matches the full set of registers GDB traditionally
+     knows about, including floating point, for either 32-bit or
+     64-bit, assume that's what we've got.  */
+  register_remote_g_packet_guess (gdbarch, 90 * 4, tdesc_gp32);
+  register_remote_g_packet_guess (gdbarch, 90 * 8, tdesc_gp64);
+
+  /* Otherwise we don't have a useful guess.  */
+}
+
 static struct gdbarch *
 mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
@@ -4855,6 +4907,16 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     fprintf_unfiltered (gdb_stdlog,
                        "mips_gdbarch_init: fpu_type = %d\n", fpu_type);
 
+  /* Check for blatant incompatibilities.  */
+
+  /* If we have only 32-bit registers, then we can't debug a 64-bit
+     ABI.  */
+  if (info.target_desc
+      && tdesc_property (info.target_desc, PROPERTY_GP32) != NULL
+      && mips_abi != MIPS_ABI_EABI32
+      && mips_abi != MIPS_ABI_O32)
+    return NULL;
+
   /* try to find a pre-existing architecture */
   for (arches = gdbarch_list_lookup_by_info (arches, &info);
        arches != NULL;
@@ -4885,6 +4947,23 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->found_abi = found_abi;
   tdep->mips_abi = mips_abi;
   tdep->mips_fpu_type = fpu_type;
+  tdep->register_size_valid_p = 0;
+  tdep->register_size = 0;
+
+  if (info.target_desc)
+    {
+      /* Some useful properties can be inferred from the target.  */
+      if (tdesc_property (info.target_desc, PROPERTY_GP32) != NULL)
+       {
+         tdep->register_size_valid_p = 1;
+         tdep->register_size = 4;
+       }
+      else if (tdesc_property (info.target_desc, PROPERTY_GP64) != NULL)
+       {
+         tdep->register_size_valid_p = 1;
+         tdep->register_size = 8;
+       }
+    }
 
   /* Initially set everything according to the default ABI/ISA.  */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -5152,6 +5231,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_single_step_through_delay (gdbarch, mips_single_step_through_delay);
 
+  mips_register_g_packet_guesses (gdbarch);
+
   /* Hook in OS ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
index e758412fe2ae955490f4b2793ed058dfb079b68e..69bc65bd16e5ab4844696293e2eede7cd331eb93 100644 (file)
@@ -3535,11 +3535,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 +3546,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 +3617,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 +3663,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)
 {
@@ -6052,6 +6074,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 +6202,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 +6335,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 +6427,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.  */
index fd84a91bdbed7b098f5bdab868c5e3c2ec0dcae5..50f1a8614763a365bec69ce829e8772052c1dcfe 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef REMOTE_H
 #define REMOTE_H
 
+struct target_desc;
+
 /* FIXME?: move this interface down to tgt vector) */
 
 /* Read a packet from the remote machine, with error checking, and
@@ -63,4 +65,7 @@ extern int remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len);
 extern void (*deprecated_target_resume_hook) (void);
 extern void (*deprecated_target_wait_loop_hook) (void);
 
+void register_remote_g_packet_guess (struct gdbarch *gdbarch, int bytes,
+                                    const struct target_desc *tdesc);
+
 #endif
index 041d72be15cb92ad8558200d1cbbcfac9811a73f..ffee104b9763adf64ed78c378e3a1b429a321cf6 100644 (file)
 #include "arch-utils.h"
 #include "target.h"
 #include "target-descriptions.h"
+#include "vec.h"
 
 #include "gdb_assert.h"
 
 /* Types.  */
 
+typedef struct property
+{
+  const char *key;
+  const char *value;
+} property_s;
+DEF_VEC_O(property_s);
+
 struct target_desc
 {
+  /* Any architecture-specific properties specified by the target.  */
+  VEC(property_s) *properties;
 };
 
 /* Global state.  These variables are associated with the current
@@ -122,6 +132,23 @@ target_current_description (void)
   return NULL;
 }
 
+/* Return the string value of a property named KEY, or NULL if the
+   property was not specified.  */
+
+const char *
+tdesc_property (const struct target_desc *target_desc, const char *key)
+{
+  struct property *prop;
+  int ix;
+
+  for (ix = 0; VEC_iterate (property_s, target_desc->properties, ix, prop);
+       ix++)
+    if (strcmp (prop->key, key) == 0)
+      return prop->value;
+
+  return NULL;
+}
+
 /* Methods for constructing a target description.  */
 
 struct target_desc *
@@ -129,3 +156,23 @@ allocate_target_description (void)
 {
   return XZALLOC (struct target_desc);
 }
+
+void
+set_tdesc_property (struct target_desc *target_desc,
+                   const char *key, const char *value)
+{
+  struct property *prop, new_prop;
+  int ix;
+
+  gdb_assert (key != NULL && value != NULL);
+
+  for (ix = 0; VEC_iterate (property_s, target_desc->properties, ix, prop);
+       ix++)
+    if (strcmp (prop->key, key) == 0)
+      internal_error (__FILE__, __LINE__,
+                     _("Attempted to add duplicate property \"%s\""), key);
+
+  new_prop.key = key;
+  new_prop.value = value;
+  VEC_safe_push (property_s, target_desc->properties, &new_prop);
+}
index bbcf879a866269c682aefedf160658a085f232dc..74f59833d95c10cb5b0ee7067e1e5cfc333a7a00 100644 (file)
@@ -45,8 +45,17 @@ const struct target_desc *target_current_description (void);
 
 /* Accessors for target descriptions.  */
 
+/* Return the string value of a property named KEY, or NULL if the
+   property was not specified.  */
+
+const char *tdesc_property (const struct target_desc *,
+                           const char *key);
+
 /* Methods for constructing a target description.  */
 
 struct target_desc *allocate_target_description (void);
 
+void set_tdesc_property (struct target_desc *,
+                        const char *key, const char *value);
+
 #endif /* TARGET_DESCRIPTIONS_H */