This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [rfc] Let the remote protocol report the target's arch


On Fri, Jan 05, 2007 at 02:56:42PM +0200, Eli Zaretskii wrote:
> > +Access the target's @dfn{target description}.  @xref{Target Descriptions}.  The
> 
> ``target's target description''?  Wouldn't this be better:
> 
>   Access the @dfn{target description}.

You think that's bad, you should have heard the three or four things I
called this before "target descriptions" :-) Yes, it sounds better your
way.

> > +annex specifies which XML document to access.  The main description is
> > +always loaded from @samp{target.xml}.
> 
> Is `target.xml' a literal file name, or is the `target' part something
> that will be replaced with a specific target name?  If the former,
> please use @file{target.xml}, if the latter, @file{@var{target}.xml}.
> If it's not a file at all, I think this text needs to explain what it
> is.
> 
> Similar problems with the markup of target.xml are elsewhere in the
> patch.

We're in a @table @samp, and the paragraph says:

@item qXfer:features:read:@var{annex}:@var{offset},@var{length}
Access the @dfn{target description}.  @xref{Target Descriptions}.  The
annex specifies which XML document to access.  The main description is
always loaded from @samp{target.xml}.

target.xml is a literal string which will be used as an annex, so I've
rewritten it as "from the @samp{target.xml} annex".  I think @samp
is right, since it's part of the remote packet - do you agree?

> 
> > +@node Target Descriptions
> > +@appendix Target Descriptions
> 
> Please add a suitable @cindex entry here, for those who will look for
> this stuff because they remember it's described somewhere in the
> manual.

I added:
@cindex target descriptions, XML

> I suggest a sentence before @table to explain what is described in
> this table.

Thanks, done.

> >                                           If @var{path} is empty,
> > +use the target-supplied description.
> 
> This sentence is unclear, at least to me: what is this target-supplied
> description, and where does one find it?  If it's target.xml, then how
> about mentioning it here explicitly?

Is this better?

Read the target description from @var{path}.  If @var{path} is empty,
use the description supplied by the current target; for instance,
via the @samp{qXfer:features:read} packet (@pxref{qXfer target
description read}).

Do you think that "set tdesc filename" without a path, or "unset tdesc
filename", is clearer?  We don't make much use of "unset" today, but we
could if it's more apparent what's going on that way.  I noticed that
you can't set some other filename variables to empty even though they
default to empty.

> > +@node Target Description Format
> > +@section Target Description Format
> 
> Suggest an @cindex entry here as well: someone could be looking for
> this format description.

Ok.

> > +@noindent
> > +This description only says that the target uses the x86-64 architecture.
> > +describes a simple target feature set which only contains two
> > +registers, named @code{s0} (a 32-bit integer register) and @code{s1}
> > +(a 32-bit floating point register).
> 
> Something's missing here, before the "describes a simple target" part.

Actually something's extra - meant to delete the last three lines,
since they are from another patch.  This one doesn't support describing
registers.

> > +The content of the @samp{<architecture>} element is an architecture
> > +name, from the same selection accepted by @code{set architecture}
> 
> There's no `<architecture>' element in the example that precedes this
> text, which is confusing.  You should probably rewrite the example.

Yeah, that form worked better in the description of register sets,
which will be in a later patch.  I'll avoid it for now.

> > +set tdesc filename
> > +show tdesc filename
> > +  Read an XML target description from the specified local file instead
> > +  of querying the target for its description.
> 
> Actually, "set tdesc filename" command doesn't read anything, it just
> sets the name of the file from which to read the description.

Well, it will cause GDB to read the file immediately (and update the
current gdbarch).  Is this better?

  Use the specified local file as an XML target description, and do
  not query the target for its built-in description.

> Anyway, I think NEWS should say explicitly that GDB can now read a
> description of remote target's features from an XML file.  Then these
> two new commands will make sense to the reader.

Good idea.  Thanks for all the comments!  Is this better?

-- 
Daniel Jacobowitz
CodeSourcery

2006-12-07  Daniel Jacobowitz  <dan@codesourcery.com>

	* NEWS: Mention target descriptions, "set tdesc filename",
	"show tdesc filename", and qXfer:features:read.
	* arch-utils.c (choose_architecture_for_target): New function.
	(gdbarch_info_fill): Call it.
	* target-descriptions.c (struct property): Make members non-const.
	(struct target_desc): Add arch member.
	(target_description_filename): New variable.
	(target_find_description): Try via XML first.
	(tdesc_architecture): New.
	(free_target_description, make_cleanup_free_target_description): New.
	(set_tdesc_property): Call xstrdup.
	(set_tdesc_architecture, tdesc_set_cmdlist, tdesc_show_cmdlist)
	(set_tdesc_cmd, show_tdesc_cmd, set_tdesc_filename_cmd)
	(show_tdesc_filename_cmd, _initialize_target_descriptions): New.
	* target-descriptions.h (tdesc_architecture)
	(make_cleanup_free_target_description, set_tdesc_architecture): New
	prototypes.
	* Makefile.in (SFILES): Add xml-tdesc.c.
	(COMMON_OBS): Add xml-tdesc.o.
	(target-descriptions.o): Update.
	(xml-tdesc.o): New rule.
	* xml-tdesc.c, xml-tdesc.h: New files.
	* remote.c (PACKET_qXfer_features): New enum.
	(remote_protocol_features): Add qXfer:features:read.
	(remote_xfer_partial): Handle TARGET_OBJECT_AVAILABLE_FEATURES.
	(_initialize_remote): Register qXfer:features:read.
	* target.h (enum target_object): Add TARGET_OBJECT_AVAILABLE_FEATURES.
	* features/gdb-target.dtd: New file.

2006-12-07  Daniel Jacobowitz  <dan@codesourcery.com>

	* linux-i386-low.c (the_low_target): Set arch_string.
	* linux-x86-64-low.c (the_low_target): Likewise.
	* linux-low.c (linux_arch_string): New.
	(linux_target_ops): Add it.
	* linux-low.h (struct linux_target_ops): Add arch_string.
	* server.c (write_qxfer_response): Use const void * for DATA.
	(get_features_xml): New.
	(handle_query): Handle qXfer:features:read.  Report it for qSupported.
	* target.h (struct target_ops): Add arch_string method.

2006-12-07  Daniel Jacobowitz  <dan@codesourcery.com>

	* gdb.texinfo (Target Descriptions): New section.
	(General Query Packets): Add QPassSignals anchor.  Mention
	qXfer:features:read under qSupported.  Expand mentions of
	qXfer:memory-map:read and QPassSignals.  Document
	qXfer:features:read.

---
 gdb/Makefile.in                  |    9 +
 gdb/NEWS                         |   12 ++
 gdb/arch-utils.c                 |   73 ++++++++++++
 gdb/doc/gdb.texinfo              |  153 +++++++++++++++++++++++++
 gdb/features/gdb-target.dtd      |    9 +
 gdb/gdbserver/linux-i386-low.c   |    6 +
 gdb/gdbserver/linux-low.c        |    7 +
 gdb/gdbserver/linux-low.h        |    4 
 gdb/gdbserver/linux-x86-64-low.c |    6 +
 gdb/gdbserver/server.c           |   69 +++++++++++
 gdb/gdbserver/target.h           |    4 
 gdb/remote.c                     |   11 +
 gdb/target-descriptions.c        |  140 ++++++++++++++++++++++-
 gdb/target-descriptions.h        |    9 +
 gdb/target.h                     |    6 -
 gdb/xml-tdesc.c                  |  233 +++++++++++++++++++++++++++++++++++++++
 gdb/xml-tdesc.h                  |   36 ++++++
 17 files changed, 774 insertions(+), 13 deletions(-)

Index: src/gdb/arch-utils.c
===================================================================
--- src.orig/gdb/arch-utils.c	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/arch-utils.c	2006-12-07 14:50:17.000000000 -0500
@@ -409,6 +409,75 @@ set_endian (char *ignore_args, int from_
   show_endian (gdb_stdout, from_tty, NULL, NULL);
 }
 
+/* Given SELECTED, a currently selected BFD architecture, and
+   FROM_TARGET, a BFD architecture reported by the target description,
+   return what architecture to use.  Either may be NULL; if both are
+   specified, we use the more specific.  If the two are obviously
+   incompatible, warn the user.  */
+
+static const struct bfd_arch_info *
+choose_architecture_for_target (const struct bfd_arch_info *selected,
+				const struct bfd_arch_info *from_target)
+{
+  const struct bfd_arch_info *compat1, *compat2;
+
+  if (selected == NULL)
+    return from_target;
+
+  if (from_target == NULL)
+    return selected;
+
+  /* struct bfd_arch_info objects are singletons: that is, there's
+     supposed to be exactly one instance for a given machine.  So you
+     can tell whether two are equivalent by comparing pointers.  */
+  if (from_target == selected)
+    return selected;
+
+  /* BFD's 'A->compatible (A, B)' functions return zero if A and B are
+     incompatible.  But if they are compatible, it returns the 'more
+     featureful' of the two arches.  That is, if A can run code
+     written for B, but B can't run code written for A, then it'll
+     return A.
+
+     Some targets (e.g. MIPS as of 2006-12-04) don't fully
+     implement this, instead always returning NULL or the first
+     argument.  We detect that case by checking both directions.  */
+
+  compat1 = selected->compatible (selected, from_target);
+  compat2 = from_target->compatible (from_target, selected);
+
+  if (compat1 == NULL && compat2 == NULL)
+    {
+      warning (_("Selected architecture %s is not compatible "
+		 "with reported target architecture %s"),
+	       selected->printable_name, from_target->printable_name);
+      return selected;
+    }
+
+  if (compat1 == NULL)
+    return compat2;
+  if (compat2 == NULL)
+    return compat1;
+  if (compat1 == compat2)
+    return compat1;
+
+  /* If the two didn't match, but one of them was a default architecture,
+     assume the more specific one is correct.  This handles the case
+     where an executable or target description just says "mips", but
+     the other knows which MIPS variant.  */
+  if (compat1->the_default)
+    return compat2;
+  if (compat2->the_default)
+    return compat1;
+
+  /* We have no idea which one is better.  This is a bug, but not
+     a critical problem; warn the user.  */
+  warning (_("Selected architecture %s is ambiguous with "
+	     "reported target architecture %s"),
+	   selected->printable_name, from_target->printable_name);
+  return selected;
+}
+
 /* Functions to manipulate the architecture of the target */
 
 enum set_arch { set_arch_auto, set_arch_manual };
@@ -703,6 +772,10 @@ gdbarch_info_fill (struct gdbarch_info *
       && bfd_get_arch (info->abfd) != bfd_arch_unknown
       && bfd_get_arch (info->abfd) != bfd_arch_obscure)
     info->bfd_arch_info = bfd_get_arch_info (info->abfd);
+  /* From the target.  */
+  if (info->target_desc != NULL)
+    info->bfd_arch_info = choose_architecture_for_target
+      (info->bfd_arch_info, tdesc_architecture (info->target_desc));
   /* From the default.  */
   if (info->bfd_arch_info == NULL)
     info->bfd_arch_info = default_bfd_arch;
Index: src/gdb/target-descriptions.c
===================================================================
--- src.orig/gdb/target-descriptions.c	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/target-descriptions.c	2006-12-07 14:50:17.000000000 -0500
@@ -24,9 +24,11 @@
 
 #include "defs.h"
 #include "arch-utils.h"
+#include "gdbcmd.h"
 #include "target.h"
 #include "target-descriptions.h"
 #include "vec.h"
+#include "xml-tdesc.h"
 
 #include "gdb_assert.h"
 
@@ -34,13 +36,16 @@
 
 typedef struct property
 {
-  const char *key;
-  const char *value;
+  char *key;
+  char *value;
 } property_s;
 DEF_VEC_O(property_s);
 
 struct target_desc
 {
+  /* The architecture reported by the target, if any.  */
+  const struct bfd_arch_info *arch;
+
   /* Any architecture-specific properties specified by the target.  */
   VEC(property_s) *properties;
 };
@@ -62,6 +67,12 @@ static int target_desc_fetched;
 
 static const struct target_desc *current_target_desc;
 
+/* Other global variables.  */
+
+/* The filename to read a target description from.  */
+
+static char *target_description_filename;
+
 /* Fetch the current target's description, and switch the current
    architecture to one which incorporates that description.  */
 
@@ -80,7 +91,22 @@ target_find_description (void)
      disconnected from the previous target.  */
   gdb_assert (gdbarch_target_desc (current_gdbarch) == NULL);
 
-  current_target_desc = target_read_description (&current_target);
+  /* First try to fetch an XML description from the user-specified
+     file.  */
+  current_target_desc = NULL;
+  if (target_description_filename != NULL
+      && *target_description_filename != '\0')
+    current_target_desc
+      = file_read_description_xml (target_description_filename);
+
+  /* Next try to read the description from the current target using
+     target objects.  */
+  if (current_target_desc == NULL)
+    current_target_desc = target_read_description_xml (&current_target);
+
+  /* If that failed try a target-specific hook.  */
+  if (current_target_desc == NULL)
+    current_target_desc = target_read_description (&current_target);
 
   /* If a non-NULL description was returned, then update the current
      architecture.  */
@@ -131,6 +157,9 @@ target_current_description (void)
 
   return NULL;
 }
+
+
+/* Direct accessors for feature sets.  */
 
 /* Return the string value of a property named KEY, or NULL if the
    property was not specified.  */
@@ -149,6 +178,16 @@ tdesc_property (const struct target_desc
   return NULL;
 }
 
+/* Return the BFD architecture associated with this target
+   description, or NULL if no architecture was specified.  */
+
+const struct bfd_arch_info *
+tdesc_architecture (const struct target_desc *target_desc)
+{
+  return target_desc->arch;
+}
+
+
 /* Methods for constructing a target description.  */
 
 struct target_desc *
@@ -157,6 +196,31 @@ allocate_target_description (void)
   return XZALLOC (struct target_desc);
 }
 
+static void
+free_target_description (void *arg)
+{
+  struct target_desc *target_desc = arg;
+  struct property *prop;
+  int ix;
+
+  for (ix = 0;
+       VEC_iterate (property_s, target_desc->properties, ix, prop);
+       ix++)
+    {
+      xfree (prop->key);
+      xfree (prop->value);
+    }
+  VEC_free (property_s, target_desc->properties);
+
+  xfree (target_desc);
+}
+
+struct cleanup *
+make_cleanup_free_target_description (struct target_desc *target_desc)
+{
+  return make_cleanup (free_target_description, target_desc);
+}
+
 void
 set_tdesc_property (struct target_desc *target_desc,
 		    const char *key, const char *value)
@@ -172,7 +236,73 @@ set_tdesc_property (struct target_desc *
       internal_error (__FILE__, __LINE__,
 		      _("Attempted to add duplicate property \"%s\""), key);
 
-  new_prop.key = key;
-  new_prop.value = value;
+  new_prop.key = xstrdup (key);
+  new_prop.value = xstrdup (value);
   VEC_safe_push (property_s, target_desc->properties, &new_prop);
 }
+
+void
+set_tdesc_architecture (struct target_desc *target_desc,
+			const struct bfd_arch_info *arch)
+{
+  target_desc->arch = arch;
+}
+
+static struct cmd_list_element *tdesc_set_cmdlist, *tdesc_show_cmdlist;
+
+static void
+set_tdesc_cmd (char *args, int from_tty)
+{
+  help_list (tdesc_set_cmdlist, "set tdesc ", -1, gdb_stdout);
+}
+
+static void
+show_tdesc_cmd (char *args, int from_tty)
+{
+  cmd_show_list (tdesc_show_cmdlist, from_tty, "");
+}
+
+static void
+set_tdesc_filename_cmd (char *args, int from_tty,
+			struct cmd_list_element *c)
+{
+  target_clear_description ();
+  target_find_description ();
+}
+
+static void
+show_tdesc_filename_cmd (struct ui_file *file, int from_tty,
+			 struct cmd_list_element *c,
+			 const char *value)
+{
+  if (value != NULL && *value != '\0')
+    printf_filtered (_("The target description will be read from \"%s\"."),
+		     value);
+  else
+    printf_filtered (_("\
+The target description will be read from the target."));
+}
+
+void
+_initialize_target_descriptions (void)
+{
+  add_prefix_cmd ("tdesc", class_maintenance, set_tdesc_cmd, _("\
+Set target description specific variables."),
+		  &tdesc_set_cmdlist, "set tdesc ",
+		  0 /* allow-unknown */, &setlist);
+  add_prefix_cmd ("tdesc", class_maintenance, show_tdesc_cmd, _("\
+Show target description specific variables."),
+		  &tdesc_set_cmdlist, "show tdesc ",
+		  0 /* allow-unknown */, &showlist);
+
+  add_setshow_optional_filename_cmd ("filename", class_obscure,
+				     &target_description_filename,
+				     _("\
+Set the file to read an XML target description from"), _("\
+Show the file to read an XML target description from"), _("\
+When set, GDB will read the target description from a local\n\
+file instead of querying the remote target."),
+				     set_tdesc_filename_cmd,
+				     show_tdesc_filename_cmd,
+				     &tdesc_set_cmdlist, &tdesc_show_cmdlist);
+}
Index: src/gdb/target-descriptions.h
===================================================================
--- src.orig/gdb/target-descriptions.h	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/target-descriptions.h	2006-12-07 14:50:17.000000000 -0500
@@ -45,6 +45,12 @@ const struct target_desc *target_current
 
 /* Accessors for target descriptions.  */
 
+/* Return the BFD architecture associated with this target
+   description, or NULL if no architecture was specified.  */
+
+const struct bfd_arch_info *tdesc_architecture
+  (const struct target_desc *);
+
 /* Return the string value of a property named KEY, or NULL if the
    property was not specified.  */
 
@@ -54,6 +60,9 @@ const char *tdesc_property (const struct
 /* Methods for constructing a target description.  */
 
 struct target_desc *allocate_target_description (void);
+struct cleanup *make_cleanup_free_target_description (struct target_desc *);
+void set_tdesc_architecture (struct target_desc *,
+			     const struct bfd_arch_info *);
 
 void set_tdesc_property (struct target_desc *,
 			 const char *key, const char *value);
Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in	2006-12-07 14:50:13.000000000 -0500
+++ src/gdb/Makefile.in	2006-12-07 14:50:17.000000000 -0500
@@ -563,7 +563,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
 	user-regs.c \
 	valarith.c valops.c valprint.c value.c varobj.c vec.c \
 	wrapper.c \
-	xml-support.c
+	xml-tdesc.c xml-support.c
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 
@@ -970,7 +970,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
 	tramp-frame.o \
 	solib.o solib-null.o \
 	prologue-value.o memory-map.o xml-support.o \
-	target-descriptions.o target-memory.o
+	target-descriptions.o target-memory.o xml-tdesc.o
 
 TSOBS = inflow.o
 
@@ -2780,7 +2780,8 @@ target.o: target.c $(defs_h) $(gdb_strin
 	$(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) $(vec_h) $(gdb_assert_h)
+	$(target_h) $(target_descriptions_h) $(vec_h) $(xml_tdesc_h) \
+	$(gdbcmd_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) \
@@ -2878,6 +2879,8 @@ xcoffread.o: xcoffread.c $(defs_h) $(bfd
 	$(complaints_h) $(gdb_stabs_h) $(aout_stab_gnu_h)
 xcoffsolib.o: xcoffsolib.c $(defs_h) $(bfd_h) $(xcoffsolib_h) $(inferior_h) \
 	$(gdbcmd_h) $(symfile_h) $(frame_h) $(gdb_regex_h)
+xml-tdesc.o: xml-tdesc.c $(defs_h) $(target_h) $(target_descriptions_h) \
+	$(xml_tdesc_h) $(xml_support_h) $(gdb_assert_h)
 xml-support.o: xml-support.c $(defs_h) $(xml_support_h) $(exceptions_h) \
 	$(gdbcmd_h) $(gdb_string_h) $(gdb_expat_h) $(safe_ctype_h)
 xstormy16-tdep.o: xstormy16-tdep.c $(defs_h) $(frame_h) $(frame_base_h) \
Index: src/gdb/xml-tdesc.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/xml-tdesc.c	2006-12-07 14:50:17.000000000 -0500
@@ -0,0 +1,233 @@
+/* XML target description support for GDB.
+
+   Copyright (C) 2006
+   Free Software Foundation, Inc.
+
+   Contributed by CodeSourcery.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "defs.h"
+#include "target.h"
+#include "target-descriptions.h"
+#include "xml-support.h"
+#include "xml-tdesc.h"
+
+#include "gdb_assert.h"
+
+#if !defined(HAVE_LIBEXPAT)
+
+/* Parse DOCUMENT into a target description.  Or don't, since we don't have
+   an XML parser.  */
+
+static struct target_desc *
+tdesc_parse_xml (const char *document)
+{
+  static int have_warned;
+
+  if (!have_warned)
+    {
+      have_warned = 1;
+      warning (_("Can not parse XML target description; XML support was "
+		 "disabled at compile time"));
+    }
+
+  return NULL;
+}
+
+#else /* HAVE_LIBEXPAT */
+
+/* Callback data for target description parsing.  */
+
+struct tdesc_parsing_data
+{
+  /* The target description we are building.  */
+  struct target_desc *tdesc;
+};
+
+/* Handle the end of an <architecture> element and its value.  */
+
+static void
+tdesc_end_arch (struct gdb_xml_parser *parser,
+		const struct gdb_xml_element *element,
+		void *user_data, const char *body_text)
+{
+  struct tdesc_parsing_data *data = user_data;
+  const struct bfd_arch_info *arch;
+
+  arch = bfd_scan_arch (body_text);
+  if (arch == NULL)
+    gdb_xml_error (parser, _("Target description specified unknown "
+			     "architecture \"%s\""), body_text);
+  set_tdesc_architecture (data->tdesc, arch);
+}
+
+/* The elements and attributes of an XML target description.  */
+
+const struct gdb_xml_element target_children[] = {
+  { "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
+    NULL, tdesc_end_arch },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element tdesc_elements[] = {
+  { "target", NULL, target_children, GDB_XML_EF_NONE,
+    NULL, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+/* Parse DOCUMENT into a target description and return it.  */
+
+static struct target_desc *
+tdesc_parse_xml (const char *document)
+{
+  struct cleanup *back_to, *result_cleanup;
+  struct gdb_xml_parser *parser;
+  struct tdesc_parsing_data data;
+
+  memset (&data, 0, sizeof (struct tdesc_parsing_data));
+
+  back_to = make_cleanup (null_cleanup, NULL);
+  parser = gdb_xml_create_parser_and_cleanup (_("target description"),
+					      tdesc_elements, &data);
+
+  data.tdesc = allocate_target_description ();
+  result_cleanup = make_cleanup_free_target_description (data.tdesc);
+
+  if (gdb_xml_parse (parser, document) == 0)
+    {
+      /* Parsed successfully.  */
+      discard_cleanups (result_cleanup);
+      do_cleanups (back_to);
+      return data.tdesc;
+    }
+  else
+    {
+      warning (_("Could not load XML target description; ignoring"));
+      do_cleanups (back_to);
+      return NULL;
+    }
+}
+
+#endif /* HAVE_LIBEXPAT */
+
+
+/* Close FILE.  */
+
+static void
+do_cleanup_fclose (void *file)
+{
+  fclose (file);
+}
+
+/* Open FILENAME, read all its text into memory, close it, and return
+   the text.  If something goes wrong, return NULL and warn.  */
+
+static char *
+fetch_xml_from_file (const char *filename)
+{
+  FILE *file;
+  struct cleanup *back_to;
+  char *text;
+  size_t len, offset;
+
+  file = fopen (filename, FOPEN_RT);
+  if (file == NULL)
+    {
+      warning (_("Could not open \"%s\""), filename);
+      return NULL;
+    }
+  back_to = make_cleanup (do_cleanup_fclose, file);
+
+  /* Read in the whole file, one chunk at a time.  */
+  len = 4096;
+  offset = 0;
+  text = xmalloc (len);
+  make_cleanup (free_current_contents, &text);
+  while (1)
+    {
+      size_t bytes_read;
+
+      /* Continue reading where the last read left off.  Leave at least
+	 one byte so that we can NUL-terminate the result.  */
+      bytes_read = fread (text + offset, 1, len - offset - 1, file);
+      if (ferror (file))
+	{
+	  warning (_("Read error from \"%s\""), filename);
+	  do_cleanups (back_to);
+	  return NULL;
+	}
+
+      offset += bytes_read;
+
+      if (feof (file))
+	break;
+
+      len = len * 2;
+      text = xrealloc (text, len);
+    }
+
+  fclose (file);
+  discard_cleanups (back_to);
+
+  text[offset] = '\0';
+  return text;
+}
+
+/* Read an XML target description from FILENAME.  Parse it, and return
+   the parsed description.  */
+
+const struct target_desc *
+file_read_description_xml (const char *filename)
+{
+  struct target_desc *tdesc;
+  char *tdesc_str;
+  struct cleanup *back_to;
+
+  tdesc_str = fetch_xml_from_file (filename);
+  if (tdesc_str == NULL)
+    return NULL;
+
+  back_to = make_cleanup (xfree, tdesc_str);
+  tdesc = tdesc_parse_xml (tdesc_str);
+  do_cleanups (back_to);
+
+  return tdesc;
+}
+
+/* Read an XML target description using OPS.  Parse it, and return the
+   parsed description.  */
+
+const struct target_desc *
+target_read_description_xml (struct target_ops *ops)
+{
+  struct target_desc *tdesc;
+  char *tdesc_str;
+  struct cleanup *back_to;
+
+  tdesc_str = target_read_stralloc (ops, TARGET_OBJECT_AVAILABLE_FEATURES,
+				    "target.xml");
+  if (tdesc_str == NULL)
+    return NULL;
+
+  back_to = make_cleanup (xfree, tdesc_str);
+  tdesc = tdesc_parse_xml (tdesc_str);
+  do_cleanups (back_to);
+
+  return tdesc;
+}
Index: src/gdb/xml-tdesc.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/xml-tdesc.h	2006-12-07 14:50:17.000000000 -0500
@@ -0,0 +1,36 @@
+/* XML target description support for GDB.
+
+   Copyright (C) 2006
+   Free Software Foundation, Inc.
+
+   Contributed by CodeSourcery.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+struct target_ops;
+struct target_desc;
+
+/* Read an XML target description from FILENAME.  Parse it, and return
+   the parsed description.  */
+
+const struct target_desc *file_read_description_xml (const char *filename);
+
+/* Read an XML target description using OPS.  Parse it, and return the
+   parsed description.  */
+
+const struct target_desc *target_read_description_xml (struct target_ops *);
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/remote.c	2006-12-07 14:50:17.000000000 -0500
@@ -893,6 +893,7 @@ enum {
   PACKET_Z3,
   PACKET_Z4,
   PACKET_qXfer_auxv,
+  PACKET_qXfer_features,
   PACKET_qXfer_memory_map,
   PACKET_qGetTLSAddr,
   PACKET_qSupported,
@@ -2294,6 +2295,8 @@ static struct protocol_feature remote_pr
   { "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,
@@ -5718,6 +5721,11 @@ remote_xfer_partial (struct target_ops *
       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,
@@ -6591,6 +6599,9 @@ Show the maximum size of the address (in
   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);
 
Index: src/gdb/target.h
===================================================================
--- src.orig/gdb/target.h	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/target.h	2006-12-07 14:50:17.000000000 -0500
@@ -206,8 +206,10 @@ enum target_object
      a previously erased flash memory.  Using it without erasing
      flash can have unexpected results.  Addresses are physical
      address on target, and not relative to flash start.  */
-  TARGET_OBJECT_FLASH
-
+  TARGET_OBJECT_FLASH,
+  /* Available target-specific features, e.g. registers and coprocessors.
+     See "target-descriptions.c".  ANNEX should never be empty.  */
+  TARGET_OBJECT_AVAILABLE_FEATURES
   /* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC, ... */
 };
 
Index: src/gdb/gdbserver/linux-i386-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-i386-low.c	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/gdbserver/linux-i386-low.c	2006-12-07 14:50:17.000000000 -0500
@@ -198,4 +198,10 @@ struct linux_target_ops the_low_target =
   NULL,
   1,
   i386_breakpoint_at,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  0,
+  "i386"
 };
Index: src/gdb/gdbserver/linux-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-low.c	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/gdbserver/linux-low.c	2006-12-07 14:50:17.000000000 -0500
@@ -1638,6 +1638,12 @@ linux_read_offsets (CORE_ADDR *text_p, C
 }
 #endif
 
+static const char *
+linux_arch_string (void)
+{
+  return the_low_target.arch_string;
+}
+
 static struct target_ops linux_target_ops = {
   linux_create_inferior,
   linux_attach,
@@ -1667,6 +1673,7 @@ static struct target_ops linux_target_op
 #else
   NULL,
 #endif
+  linux_arch_string,
 };
 
 static void
Index: src/gdb/gdbserver/linux-low.h
===================================================================
--- src.orig/gdb/gdbserver/linux-low.h	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/gdbserver/linux-low.h	2006-12-07 14:50:17.000000000 -0500
@@ -71,6 +71,10 @@ struct linux_target_ops
   /* Whether to left-pad registers for PEEKUSR/POKEUSR if they are smaller
      than an xfer unit.  */
   int left_pad_xfer;
+
+  /* What string to report to GDB when it asks for the architecture,
+     or NULL not to answer.  */
+  const char *arch_string;
 };
 
 extern struct linux_target_ops the_low_target;
Index: src/gdb/gdbserver/linux-x86-64-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-x86-64-low.c	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/gdbserver/linux-x86-64-low.c	2006-12-07 14:50:17.000000000 -0500
@@ -173,4 +173,10 @@ struct linux_target_ops the_low_target =
   NULL,                                 
   1,
   x86_64_breakpoint_at,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  0,
+  "i386:x86-64",
 };
Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/gdbserver/server.c	2006-12-07 14:50:17.000000000 -0500
@@ -146,7 +146,7 @@ decode_xfer_read (char *buf, char **anne
    to as much of DATA/LEN as we could fit.  IS_MORE controls
    the first character of the response.  */
 static int
-write_qxfer_response (char *buf, unsigned char *data, int len, int is_more)
+write_qxfer_response (char *buf, const void *data, int len, int is_more)
 {
   int out_len;
 
@@ -193,6 +193,31 @@ handle_general_set (char *own_buf)
   own_buf[0] = 0;
 }
 
+static const char *
+get_features_xml (void)
+{
+  static int features_supported = -1;
+  static char *document;
+
+  if (features_supported == -1)
+    {
+      const char *arch = (*the_target->arch_string) ();
+
+      if (arch == NULL)
+	features_supported = 0;
+      else
+	{
+	  features_supported = 1;
+	  document = malloc (64 + strlen (arch));
+	  snprintf (document, 64 + strlen (arch),
+		    "<target><architecture>%s</architecture></target>",
+		    arch);
+	}
+    }
+
+  return document;
+}
+
 /* Handle all of the extended 'q' packets.  */
 void
 handle_query (char *own_buf, int *new_packet_len_p)
@@ -280,6 +305,45 @@ handle_query (char *own_buf, int *new_pa
       return;
     }
 
+  if (strncmp ("qXfer:features:read:", own_buf, 20) == 0)
+    {
+      CORE_ADDR ofs;
+      unsigned int len, total_len;
+      const char *document;
+      char *annex;
+
+      document = get_features_xml ();
+      if (document == NULL)
+	{
+	  own_buf[0] = '\0';
+	  return;
+	}
+
+      /* Reject any annex other than target.xml; grab the offset and
+	 length.  */
+      if (decode_xfer_read (own_buf + 20, &annex, &ofs, &len) < 0
+	  || strcmp (annex, "target.xml") != 0)
+	{
+	  strcpy (own_buf, "E00");
+	  return;
+	}
+
+      total_len = strlen (document);
+      if (len > PBUFSIZ - 2)
+	len = PBUFSIZ - 2;
+
+      if (ofs > total_len)
+	write_enn (own_buf);
+      else if (len < total_len - ofs)
+	*new_packet_len_p = write_qxfer_response (own_buf, document + ofs,
+						  len, 1);
+      else
+	*new_packet_len_p = write_qxfer_response (own_buf, document + ofs,
+						  total_len - ofs, 0);
+
+      return;
+    }
+
   /* Protocol features query.  */
   if (strncmp ("qSupported", own_buf, 10) == 0
       && (own_buf[10] == ':' || own_buf[10] == '\0'))
@@ -289,6 +353,9 @@ handle_query (char *own_buf, int *new_pa
       if (the_target->read_auxv != NULL)
 	strcat (own_buf, ";qXfer:auxv:read+");
 
+      if (get_features_xml () != NULL)
+	strcat (own_buf, ";qXfer:features:read+");
+
       return;
     }
 
Index: src/gdb/gdbserver/target.h
===================================================================
--- src.orig/gdb/gdbserver/target.h	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/gdbserver/target.h	2006-12-07 14:50:17.000000000 -0500
@@ -172,6 +172,10 @@ struct target_ops
 
   int (*get_tls_address) (struct thread_info *thread, CORE_ADDR offset,
 			  CORE_ADDR load_module, CORE_ADDR *address);
+
+  /* Return a string identifying the current architecture, or NULL if
+     this operation is not supported.  */
+  const char *(*arch_string) (void);
 };
 
 extern struct target_ops *the_target;
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2006-12-07 14:49:55.000000000 -0500
+++ src/gdb/doc/gdb.texinfo	2007-01-05 14:04:36.000000000 -0500
@@ -159,6 +159,8 @@ Copyright (C) 1988-2006 Free Software Fo
 * Maintenance Commands::        Maintenance Commands
 * Remote Protocol::             GDB Remote Serial Protocol
 * Agent Expressions::           The GDB Agent Expression Mechanism
+* Target Descriptions::         How targets can describe themselves to
+                                @value{GDBN}
 * Copying::			GNU General Public License says
                                 how you can copy and share GDB
 * GNU Free Documentation License::  The license for this documentation
@@ -23664,6 +23666,7 @@ Reply: see @code{remote.c:remote_unpack_
 @item QPassSignals: @var{signal} @r{[};@var{signal}@r{]}@dots{}
 @cindex pass signals to inferior, remote request
 @cindex @samp{QPassSignals} packet
+@anchor{QPassSignals}
 Each listed @var{signal} should be passed directly to the inferior process. 
 Signals are numbered identically to continue packets and stop replies
 (@pxref{Stop Reply Packets}).  Each @var{signal} list item should be
@@ -23830,6 +23833,11 @@ These are the currently defined stub fea
 @tab @samp{-}
 @tab Yes
 
+@item @samp{qXfer:features:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
 @item @samp{qXfer:memory-map:read}
 @tab No
 @tab @samp{-}
@@ -23860,6 +23868,18 @@ byte in its buffer for the NUL.  If this
 The remote stub understands the @samp{qXfer:auxv:read} packet
 (@pxref{qXfer auxiliary vector read}).
 
+@item qXfer:features:read
+The remote stub understands the @samp{qXfer:features:read} packet
+(@pxref{qXfer target description read}).
+
+@item qXfer:memory-map:read
+The remote stub understands the @samp{qXfer:memory-map:read} packet
+(@pxref{qXfer memory map read}).
+
+@item QPassSignals
+The remote stub understands the @samp{QPassSignals} packet
+(@pxref{QPassSignals}).
+
 @end table
 
 @item qSymbol::
@@ -23956,9 +23976,16 @@ auxiliary vector}.  Note @var{annex} mus
 
 This packet is not probed by default; the remote stub must request it,
 by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
-@end table
 
-@table @samp
+@item qXfer:features:read:@var{annex}:@var{offset},@var{length}
+@anchor{qXfer target description read}
+Access the @dfn{target description}.  @xref{Target Descriptions}.  The
+annex specifies which XML document to access.  The main description is
+always loaded from the @samp{target.xml} annex.
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+
 @item qXfer:memory-map:read::@var{offset},@var{length}
 @anchor{qXfer memory map read}
 Access the target's @dfn{memory-map}.  @xref{Memory map format}.  The
@@ -25533,6 +25560,128 @@ The formal DTD for memory map format is 
 
 @include agentexpr.texi
 
+@node Target Descriptions
+@appendix Target Descriptions
+@cindex target descriptions
+
+@strong{Warning:} target descriptions are still under active development,
+and the contents and format may change between @value{GDBN} releases.
+The format is expected to stabilize in the future.
+
+One of the challenges of using @value{GDBN} to debug embedded systems
+is that there are so many minor variants of each processor
+architecture in use.  It is common practice for vendors to start with
+a standard processor core --- ARM, PowerPC, or MIPS, for example ---
+and then make changes to adapt it to a particular market niche.  Some
+architectures have hundreds of variants, available from dozens of
+vendors.  This leads to a number of problems:
+
+@itemize @bullet
+@item
+With so many different customized processors, it is difficult for
+the @value{GDBN} maintainers to keep up with the changes.
+@item
+Since individual variants may have short lifetimes or limited
+audiences, it may not be worthwhile to carry information about every
+variant in the @value{GDBN} source tree.
+@item
+When @value{GDBN} does support the architecture of the embedded system
+at hand, the task of finding the correct architecture name to give the
+@command{set architecture} command can be error-prone.
+@end itemize
+
+To address these problems, the @value{GDBN} remote protocol allows a
+target system to not only identify itself to @value{GDBN}, but to
+actually describe its own features.  This lets @value{GDBN} support
+processor variants it has never seen before --- to the extent that the
+descriptions are accurate, and that @value{GDBN} understands them.
+
+@menu
+* Retrieving Descriptions::         How descriptions are fetched from a target.
+* Target Description Format::       The contents of a target description.
+@end menu
+
+@node Retrieving Descriptions
+@section Retrieving Descriptions
+
+Target descriptions can be read from the target automatically, or
+specified by the user manually.  The default behavior is to read the
+description from the target.  @value{GDBN} retrieves it via the remote
+protocol using @samp{qXfer} requests (@pxref{General Query Packets,
+qXfer}).  The @var{annex} in the @samp{qXfer} packet will be
+@samp{target.xml}.  The contents of the @samp{target.xml} annex are an
+XML document, of the form described in @ref{Target Description
+Format}.
+
+Alternatively, you can specify a file to read for the target description.
+If a file is set, the target will not be queried.  The commands to
+specify a file are:
+
+@table @code
+@cindex set tdesc filename
+@item set tdesc filename @var{path}
+Read the target description from @var{path}.  If @var{path} is empty,
+use the description supplied by the current target; for instance,
+via the @samp{qXfer:features:read} packet (@pxref{qXfer target description
+read}).
+
+@cindex show tdesc filename
+@item show tdesc filename
+Show the filename to read for a target description, if set.
+@end table
+
+
+@node Target Description Format
+@section Target Description Format
+@cindex target descriptions, XML format
+
+A target description annex is an @uref{http://www.w3.org/XML/, XML}
+document which complies with the Document Type Definition provided in
+the @value{GDBN} sources in @file{gdb/features/gdb-target.dtd}.  This
+means you can use generally available tools like @command{xmllint} to
+check that your feature descriptions are well-formed and valid.
+However, to help people unfamiliar with XML write descriptions for
+their targets, we also describe the grammar here.
+
+At the moment, target descriptions can only provide minimal information
+about the architecture of the remote target.  @value{GDBN} can use this
+information to autoconfigure, or to warn you if you connect to an
+unsupported target.
+
+Here is a simple target description:
+
+@example
+<target>
+  <architecture>i386:x86-64</architecture>
+</target>
+@end example
+
+@noindent
+This minimal description only says that the target uses
+the x86-64 architecture.
+
+A target description has the overall form:
+
+@example
+<?xml version="1.0"?>
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>@var{arch name}</architecture>
+</target>
+@end example
+
+@noindent
+The description is generally insensitive to whitespace and line
+breaks, under the usual common-sense rules.  The XML version
+declaration and document type declaration can generally be omitted
+(@value{GDBN} does not require them), but specifying them may be
+useful for XML validation tools.
+
+The content of the @samp{<architecture>} element is an architecture
+name, from the same selection accepted by @code{set architecture}
+(@pxref{Targets, ,Specifying a Debugging Target}).
+
+
 @include gpl.texi
 
 @raisesections
Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS	2006-12-07 14:49:50.000000000 -0500
+++ src/gdb/NEWS	2007-01-05 14:11:30.000000000 -0500
@@ -9,6 +9,10 @@ frequency signals (e.g. SIGALRM) via the
 * GDB for MIPS targets now autodetects whether a remote target provides
 32-bit or 64-bit register values.
 
+* GDB now understands XML target descriptions, which specify the
+target's overall architecture.  GDB can read a description from
+a local file or over the remote serial protocol.
+
 * New commands
 
 set mem inaccessible-by-default
@@ -28,6 +32,11 @@ show breakpoint auto-hw
   "break" command and internal breakpoints used for other commands
   including "next" and "finish".
 
+set tdesc filename
+show tdesc filename
+  Use the specified local file as an XML target description, and do
+  not query the target for its built-in description.
+
 * New targets
 
 MIPS64 GNU/Linux (gdbserver)	mips64-linux-gnu
@@ -38,6 +47,9 @@ QPassSignals:
   Ignore the specified signals; pass them directly to the debugged program
   without stopping other threads or reporting them to GDB.
 
+qXfer:features:read:
+  Read an XML target description from the target, which describes its
+  features.
 
 *** Changes in GDB 6.6
 
Index: src/gdb/features/gdb-target.dtd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/features/gdb-target.dtd	2006-12-07 14:50:17.000000000 -0500
@@ -0,0 +1,9 @@
+<!-- The root element of a GDB target description is <target>.  -->
+
+<!ELEMENT target	(architecture?)>
+<!ATTLIST target
+	xmlns:xi	CDATA	#FIXED "http://www.w3.org/2001/XInclude";>
+
+<!ELEMENT architecture	(#PCDATA)>
+
+


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]