xref: /dragonfly/contrib/gdb-7/gdb/xml-tdesc.c (revision ef5ccd6c)
15796c8dcSSimon Schubert /* XML target description support for GDB.
25796c8dcSSimon Schubert 
3*ef5ccd6cSJohn Marino    Copyright (C) 2006-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert    Contributed by CodeSourcery.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This file is part of GDB.
85796c8dcSSimon Schubert 
95796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
105796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
115796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
125796c8dcSSimon Schubert    (at your option) any later version.
135796c8dcSSimon Schubert 
145796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
155796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
165796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
175796c8dcSSimon Schubert    GNU General Public License for more details.
185796c8dcSSimon Schubert 
195796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
205796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
215796c8dcSSimon Schubert 
225796c8dcSSimon Schubert #include "defs.h"
235796c8dcSSimon Schubert #include "target.h"
245796c8dcSSimon Schubert #include "target-descriptions.h"
255796c8dcSSimon Schubert #include "xml-support.h"
265796c8dcSSimon Schubert #include "xml-tdesc.h"
275796c8dcSSimon Schubert #include "osabi.h"
285796c8dcSSimon Schubert 
295796c8dcSSimon Schubert #include "filenames.h"
305796c8dcSSimon Schubert 
315796c8dcSSimon Schubert #include "gdb_assert.h"
325796c8dcSSimon Schubert 
335796c8dcSSimon Schubert #if !defined(HAVE_LIBEXPAT)
345796c8dcSSimon Schubert 
355796c8dcSSimon Schubert /* Parse DOCUMENT into a target description.  Or don't, since we don't have
365796c8dcSSimon Schubert    an XML parser.  */
375796c8dcSSimon Schubert 
385796c8dcSSimon Schubert static struct target_desc *
tdesc_parse_xml(const char * document,xml_fetch_another fetcher,void * fetcher_baton)395796c8dcSSimon Schubert tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
405796c8dcSSimon Schubert 		 void *fetcher_baton)
415796c8dcSSimon Schubert {
425796c8dcSSimon Schubert   static int have_warned;
435796c8dcSSimon Schubert 
445796c8dcSSimon Schubert   if (!have_warned)
455796c8dcSSimon Schubert     {
465796c8dcSSimon Schubert       have_warned = 1;
475796c8dcSSimon Schubert       warning (_("Can not parse XML target description; XML support was "
485796c8dcSSimon Schubert 		 "disabled at compile time"));
495796c8dcSSimon Schubert     }
505796c8dcSSimon Schubert 
515796c8dcSSimon Schubert   return NULL;
525796c8dcSSimon Schubert }
535796c8dcSSimon Schubert 
545796c8dcSSimon Schubert #else /* HAVE_LIBEXPAT */
555796c8dcSSimon Schubert 
565796c8dcSSimon Schubert /* A record of every XML description we have parsed.  We never discard
575796c8dcSSimon Schubert    old descriptions, because we never discard gdbarches.  As long as we
585796c8dcSSimon Schubert    have a gdbarch referencing this description, we want to have a copy
595796c8dcSSimon Schubert    of it here, so that if we parse the same XML document again we can
605796c8dcSSimon Schubert    return the same "struct target_desc *"; if they are not singletons,
615796c8dcSSimon Schubert    then we will create unnecessary duplicate gdbarches.  See
625796c8dcSSimon Schubert    gdbarch_list_lookup_by_info.  */
635796c8dcSSimon Schubert 
645796c8dcSSimon Schubert struct tdesc_xml_cache
655796c8dcSSimon Schubert {
665796c8dcSSimon Schubert   const char *xml_document;
675796c8dcSSimon Schubert   struct target_desc *tdesc;
685796c8dcSSimon Schubert };
695796c8dcSSimon Schubert typedef struct tdesc_xml_cache tdesc_xml_cache_s;
705796c8dcSSimon Schubert DEF_VEC_O(tdesc_xml_cache_s);
715796c8dcSSimon Schubert 
VEC(tdesc_xml_cache_s)725796c8dcSSimon Schubert static VEC(tdesc_xml_cache_s) *xml_cache;
735796c8dcSSimon Schubert 
745796c8dcSSimon Schubert /* Callback data for target description parsing.  */
755796c8dcSSimon Schubert 
765796c8dcSSimon Schubert struct tdesc_parsing_data
775796c8dcSSimon Schubert {
785796c8dcSSimon Schubert   /* The target description we are building.  */
795796c8dcSSimon Schubert   struct target_desc *tdesc;
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert   /* The target feature we are currently parsing, or last parsed.  */
825796c8dcSSimon Schubert   struct tdesc_feature *current_feature;
835796c8dcSSimon Schubert 
845796c8dcSSimon Schubert   /* The register number to use for the next register we see, if
855796c8dcSSimon Schubert      it does not have its own.  This starts at zero.  */
865796c8dcSSimon Schubert   int next_regnum;
875796c8dcSSimon Schubert 
88cf7f2e2dSJohn Marino   /* The struct or union we are currently parsing, or last parsed.  */
89cf7f2e2dSJohn Marino   struct tdesc_type *current_type;
90cf7f2e2dSJohn Marino 
91cf7f2e2dSJohn Marino   /* The byte size of the current struct type, if specified.  Zero
92cf7f2e2dSJohn Marino      if not specified.  */
93cf7f2e2dSJohn Marino   int current_type_size;
94cf7f2e2dSJohn Marino 
95cf7f2e2dSJohn Marino   /* Whether the current type is a flags type.  */
96cf7f2e2dSJohn Marino   int current_type_is_flags;
975796c8dcSSimon Schubert };
985796c8dcSSimon Schubert 
995796c8dcSSimon Schubert /* Handle the end of an <architecture> element and its value.  */
1005796c8dcSSimon Schubert 
1015796c8dcSSimon Schubert static void
tdesc_end_arch(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,const char * body_text)1025796c8dcSSimon Schubert tdesc_end_arch (struct gdb_xml_parser *parser,
1035796c8dcSSimon Schubert 		const struct gdb_xml_element *element,
1045796c8dcSSimon Schubert 		void *user_data, const char *body_text)
1055796c8dcSSimon Schubert {
1065796c8dcSSimon Schubert   struct tdesc_parsing_data *data = user_data;
1075796c8dcSSimon Schubert   const struct bfd_arch_info *arch;
1085796c8dcSSimon Schubert 
1095796c8dcSSimon Schubert   arch = bfd_scan_arch (body_text);
1105796c8dcSSimon Schubert   if (arch == NULL)
1115796c8dcSSimon Schubert     gdb_xml_error (parser, _("Target description specified unknown "
1125796c8dcSSimon Schubert 			     "architecture \"%s\""), body_text);
1135796c8dcSSimon Schubert   set_tdesc_architecture (data->tdesc, arch);
1145796c8dcSSimon Schubert }
1155796c8dcSSimon Schubert 
1165796c8dcSSimon Schubert /* Handle the end of an <osabi> element and its value.  */
1175796c8dcSSimon Schubert 
1185796c8dcSSimon Schubert static void
tdesc_end_osabi(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,const char * body_text)1195796c8dcSSimon Schubert tdesc_end_osabi (struct gdb_xml_parser *parser,
1205796c8dcSSimon Schubert 		 const struct gdb_xml_element *element,
1215796c8dcSSimon Schubert 		 void *user_data, const char *body_text)
1225796c8dcSSimon Schubert {
1235796c8dcSSimon Schubert   struct tdesc_parsing_data *data = user_data;
1245796c8dcSSimon Schubert   enum gdb_osabi osabi;
1255796c8dcSSimon Schubert 
1265796c8dcSSimon Schubert   osabi = osabi_from_tdesc_string (body_text);
1275796c8dcSSimon Schubert   if (osabi == GDB_OSABI_UNKNOWN)
1285796c8dcSSimon Schubert     warning (_("Target description specified unknown osabi \"%s\""),
1295796c8dcSSimon Schubert 	     body_text);
1305796c8dcSSimon Schubert   else
1315796c8dcSSimon Schubert     set_tdesc_osabi (data->tdesc, osabi);
1325796c8dcSSimon Schubert }
1335796c8dcSSimon Schubert 
1345796c8dcSSimon Schubert /* Handle the end of a <compatible> element and its value.  */
1355796c8dcSSimon Schubert 
1365796c8dcSSimon Schubert static void
tdesc_end_compatible(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,const char * body_text)1375796c8dcSSimon Schubert tdesc_end_compatible (struct gdb_xml_parser *parser,
1385796c8dcSSimon Schubert 		      const struct gdb_xml_element *element,
1395796c8dcSSimon Schubert 		      void *user_data, const char *body_text)
1405796c8dcSSimon Schubert {
1415796c8dcSSimon Schubert   struct tdesc_parsing_data *data = user_data;
1425796c8dcSSimon Schubert   const struct bfd_arch_info *arch;
1435796c8dcSSimon Schubert 
1445796c8dcSSimon Schubert   arch = bfd_scan_arch (body_text);
1455796c8dcSSimon Schubert   tdesc_add_compatible (data->tdesc, arch);
1465796c8dcSSimon Schubert }
1475796c8dcSSimon Schubert 
1485796c8dcSSimon Schubert /* Handle the start of a <target> element.  */
1495796c8dcSSimon Schubert 
1505796c8dcSSimon Schubert static void
tdesc_start_target(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)1515796c8dcSSimon Schubert tdesc_start_target (struct gdb_xml_parser *parser,
1525796c8dcSSimon Schubert 		    const struct gdb_xml_element *element,
1535796c8dcSSimon Schubert 		    void *user_data, VEC(gdb_xml_value_s) *attributes)
1545796c8dcSSimon Schubert {
155c50c785cSJohn Marino   char *version = xml_find_attribute (attributes, "version")->value;
1565796c8dcSSimon Schubert 
1575796c8dcSSimon Schubert   if (strcmp (version, "1.0") != 0)
1585796c8dcSSimon Schubert     gdb_xml_error (parser,
1595796c8dcSSimon Schubert 		   _("Target description has unsupported version \"%s\""),
1605796c8dcSSimon Schubert 		   version);
1615796c8dcSSimon Schubert }
1625796c8dcSSimon Schubert 
1635796c8dcSSimon Schubert /* Handle the start of a <feature> element.  */
1645796c8dcSSimon Schubert 
1655796c8dcSSimon Schubert static void
tdesc_start_feature(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)1665796c8dcSSimon Schubert tdesc_start_feature (struct gdb_xml_parser *parser,
1675796c8dcSSimon Schubert 		     const struct gdb_xml_element *element,
1685796c8dcSSimon Schubert 		     void *user_data, VEC(gdb_xml_value_s) *attributes)
1695796c8dcSSimon Schubert {
1705796c8dcSSimon Schubert   struct tdesc_parsing_data *data = user_data;
171c50c785cSJohn Marino   char *name = xml_find_attribute (attributes, "name")->value;
1725796c8dcSSimon Schubert 
1735796c8dcSSimon Schubert   data->current_feature = tdesc_create_feature (data->tdesc, name);
1745796c8dcSSimon Schubert }
1755796c8dcSSimon Schubert 
1765796c8dcSSimon Schubert /* Handle the start of a <reg> element.  Fill in the optional
1775796c8dcSSimon Schubert    attributes and attach it to the containing feature.  */
1785796c8dcSSimon Schubert 
1795796c8dcSSimon Schubert static void
tdesc_start_reg(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)1805796c8dcSSimon Schubert tdesc_start_reg (struct gdb_xml_parser *parser,
1815796c8dcSSimon Schubert 		 const struct gdb_xml_element *element,
1825796c8dcSSimon Schubert 		 void *user_data, VEC(gdb_xml_value_s) *attributes)
1835796c8dcSSimon Schubert {
1845796c8dcSSimon Schubert   struct tdesc_parsing_data *data = user_data;
1855796c8dcSSimon Schubert   struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
1865796c8dcSSimon Schubert   int ix = 0, length;
1875796c8dcSSimon Schubert   char *name, *group, *type;
1885796c8dcSSimon Schubert   int bitsize, regnum, save_restore;
1895796c8dcSSimon Schubert 
1905796c8dcSSimon Schubert   length = VEC_length (gdb_xml_value_s, attributes);
1915796c8dcSSimon Schubert 
1925796c8dcSSimon Schubert   name = attrs[ix++].value;
1935796c8dcSSimon Schubert   bitsize = * (ULONGEST *) attrs[ix++].value;
1945796c8dcSSimon Schubert 
1955796c8dcSSimon Schubert   if (ix < length && strcmp (attrs[ix].name, "regnum") == 0)
1965796c8dcSSimon Schubert     regnum = * (ULONGEST *) attrs[ix++].value;
1975796c8dcSSimon Schubert   else
1985796c8dcSSimon Schubert     regnum = data->next_regnum;
1995796c8dcSSimon Schubert 
2005796c8dcSSimon Schubert   if (ix < length && strcmp (attrs[ix].name, "type") == 0)
2015796c8dcSSimon Schubert     type = attrs[ix++].value;
2025796c8dcSSimon Schubert   else
2035796c8dcSSimon Schubert     type = "int";
2045796c8dcSSimon Schubert 
2055796c8dcSSimon Schubert   if (ix < length && strcmp (attrs[ix].name, "group") == 0)
2065796c8dcSSimon Schubert     group = attrs[ix++].value;
2075796c8dcSSimon Schubert   else
2085796c8dcSSimon Schubert     group = NULL;
2095796c8dcSSimon Schubert 
2105796c8dcSSimon Schubert   if (ix < length && strcmp (attrs[ix].name, "save-restore") == 0)
2115796c8dcSSimon Schubert     save_restore = * (ULONGEST *) attrs[ix++].value;
2125796c8dcSSimon Schubert   else
2135796c8dcSSimon Schubert     save_restore = 1;
2145796c8dcSSimon Schubert 
2155796c8dcSSimon Schubert   if (strcmp (type, "int") != 0
2165796c8dcSSimon Schubert       && strcmp (type, "float") != 0
2175796c8dcSSimon Schubert       && tdesc_named_type (data->current_feature, type) == NULL)
2185796c8dcSSimon Schubert     gdb_xml_error (parser, _("Register \"%s\" has unknown type \"%s\""),
2195796c8dcSSimon Schubert 		   name, type);
2205796c8dcSSimon Schubert 
2215796c8dcSSimon Schubert   tdesc_create_reg (data->current_feature, name, regnum, save_restore, group,
2225796c8dcSSimon Schubert 		    bitsize, type);
2235796c8dcSSimon Schubert 
2245796c8dcSSimon Schubert   data->next_regnum = regnum + 1;
2255796c8dcSSimon Schubert }
2265796c8dcSSimon Schubert 
2275796c8dcSSimon Schubert /* Handle the start of a <union> element.  Initialize the type and
2285796c8dcSSimon Schubert    record it with the current feature.  */
2295796c8dcSSimon Schubert 
2305796c8dcSSimon Schubert static void
tdesc_start_union(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)2315796c8dcSSimon Schubert tdesc_start_union (struct gdb_xml_parser *parser,
2325796c8dcSSimon Schubert 		   const struct gdb_xml_element *element,
2335796c8dcSSimon Schubert 		   void *user_data, VEC(gdb_xml_value_s) *attributes)
2345796c8dcSSimon Schubert {
2355796c8dcSSimon Schubert   struct tdesc_parsing_data *data = user_data;
236c50c785cSJohn Marino   char *id = xml_find_attribute (attributes, "id")->value;
2375796c8dcSSimon Schubert 
238cf7f2e2dSJohn Marino   data->current_type = tdesc_create_union (data->current_feature, id);
239cf7f2e2dSJohn Marino   data->current_type_size = 0;
240cf7f2e2dSJohn Marino   data->current_type_is_flags = 0;
241cf7f2e2dSJohn Marino }
242cf7f2e2dSJohn Marino 
243cf7f2e2dSJohn Marino /* Handle the start of a <struct> element.  Initialize the type and
244cf7f2e2dSJohn Marino    record it with the current feature.  */
245cf7f2e2dSJohn Marino 
246cf7f2e2dSJohn Marino static void
tdesc_start_struct(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)247cf7f2e2dSJohn Marino tdesc_start_struct (struct gdb_xml_parser *parser,
248cf7f2e2dSJohn Marino 		   const struct gdb_xml_element *element,
249cf7f2e2dSJohn Marino 		   void *user_data, VEC(gdb_xml_value_s) *attributes)
250cf7f2e2dSJohn Marino {
251cf7f2e2dSJohn Marino   struct tdesc_parsing_data *data = user_data;
252c50c785cSJohn Marino   char *id = xml_find_attribute (attributes, "id")->value;
253cf7f2e2dSJohn Marino   struct tdesc_type *type;
254c50c785cSJohn Marino   struct gdb_xml_value *attr;
255cf7f2e2dSJohn Marino 
256cf7f2e2dSJohn Marino   type = tdesc_create_struct (data->current_feature, id);
257cf7f2e2dSJohn Marino   data->current_type = type;
258cf7f2e2dSJohn Marino   data->current_type_size = 0;
259cf7f2e2dSJohn Marino   data->current_type_is_flags = 0;
260cf7f2e2dSJohn Marino 
261c50c785cSJohn Marino   attr = xml_find_attribute (attributes, "size");
262c50c785cSJohn Marino   if (attr != NULL)
263cf7f2e2dSJohn Marino     {
264c50c785cSJohn Marino       int size = (int) * (ULONGEST *) attr->value;
265cf7f2e2dSJohn Marino 
266cf7f2e2dSJohn Marino       tdesc_set_struct_size (type, size);
267cf7f2e2dSJohn Marino       data->current_type_size = size;
268cf7f2e2dSJohn Marino     }
269cf7f2e2dSJohn Marino }
270cf7f2e2dSJohn Marino 
271cf7f2e2dSJohn Marino static void
tdesc_start_flags(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)272cf7f2e2dSJohn Marino tdesc_start_flags (struct gdb_xml_parser *parser,
273cf7f2e2dSJohn Marino 		   const struct gdb_xml_element *element,
274cf7f2e2dSJohn Marino 		   void *user_data, VEC(gdb_xml_value_s) *attributes)
275cf7f2e2dSJohn Marino {
276cf7f2e2dSJohn Marino   struct tdesc_parsing_data *data = user_data;
277c50c785cSJohn Marino   char *id = xml_find_attribute (attributes, "id")->value;
278cf7f2e2dSJohn Marino   int length = (int) * (ULONGEST *)
279c50c785cSJohn Marino     xml_find_attribute (attributes, "size")->value;
280cf7f2e2dSJohn Marino   struct tdesc_type *type;
281cf7f2e2dSJohn Marino 
282cf7f2e2dSJohn Marino   type = tdesc_create_flags (data->current_feature, id, length);
283cf7f2e2dSJohn Marino 
284cf7f2e2dSJohn Marino   data->current_type = type;
285cf7f2e2dSJohn Marino   data->current_type_size = 0;
286cf7f2e2dSJohn Marino   data->current_type_is_flags = 1;
2875796c8dcSSimon Schubert }
2885796c8dcSSimon Schubert 
2895796c8dcSSimon Schubert /* Handle the start of a <field> element.  Attach the field to the
290cf7f2e2dSJohn Marino    current struct or union.  */
2915796c8dcSSimon Schubert 
2925796c8dcSSimon Schubert static void
tdesc_start_field(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)2935796c8dcSSimon Schubert tdesc_start_field (struct gdb_xml_parser *parser,
2945796c8dcSSimon Schubert 		   const struct gdb_xml_element *element,
2955796c8dcSSimon Schubert 		   void *user_data, VEC(gdb_xml_value_s) *attributes)
2965796c8dcSSimon Schubert {
2975796c8dcSSimon Schubert   struct tdesc_parsing_data *data = user_data;
298c50c785cSJohn Marino   struct gdb_xml_value *attr;
2995796c8dcSSimon Schubert   struct tdesc_type *field_type;
3005796c8dcSSimon Schubert   char *field_name, *field_type_id;
301cf7f2e2dSJohn Marino   int start, end;
3025796c8dcSSimon Schubert 
303c50c785cSJohn Marino   field_name = xml_find_attribute (attributes, "name")->value;
304cf7f2e2dSJohn Marino 
305c50c785cSJohn Marino   attr = xml_find_attribute (attributes, "type");
306c50c785cSJohn Marino   if (attr != NULL)
307c50c785cSJohn Marino     field_type_id = attr->value;
308cf7f2e2dSJohn Marino   else
309cf7f2e2dSJohn Marino     field_type_id = NULL;
310cf7f2e2dSJohn Marino 
311c50c785cSJohn Marino   attr = xml_find_attribute (attributes, "start");
312c50c785cSJohn Marino   if (attr != NULL)
313c50c785cSJohn Marino     start = * (ULONGEST *) attr->value;
314cf7f2e2dSJohn Marino   else
315cf7f2e2dSJohn Marino     start = -1;
316cf7f2e2dSJohn Marino 
317c50c785cSJohn Marino   attr = xml_find_attribute (attributes, "end");
318c50c785cSJohn Marino   if (attr != NULL)
319c50c785cSJohn Marino     end = * (ULONGEST *) attr->value;
320cf7f2e2dSJohn Marino   else
321cf7f2e2dSJohn Marino     end = -1;
322cf7f2e2dSJohn Marino 
323cf7f2e2dSJohn Marino   if (field_type_id != NULL)
324cf7f2e2dSJohn Marino     {
325cf7f2e2dSJohn Marino       if (data->current_type_is_flags)
326cf7f2e2dSJohn Marino 	gdb_xml_error (parser, _("Cannot add typed field \"%s\" to flags"),
327cf7f2e2dSJohn Marino 		       field_name);
328cf7f2e2dSJohn Marino       if (data->current_type_size != 0)
329cf7f2e2dSJohn Marino 	gdb_xml_error (parser,
330c50c785cSJohn Marino 		       _("Explicitly sized type can not "
331c50c785cSJohn Marino 			 "contain non-bitfield \"%s\""),
332cf7f2e2dSJohn Marino 		       field_name);
3335796c8dcSSimon Schubert 
3345796c8dcSSimon Schubert       field_type = tdesc_named_type (data->current_feature, field_type_id);
3355796c8dcSSimon Schubert       if (field_type == NULL)
336cf7f2e2dSJohn Marino 	gdb_xml_error (parser, _("Field \"%s\" references undefined "
3375796c8dcSSimon Schubert 				 "type \"%s\""),
3385796c8dcSSimon Schubert 		       field_name, field_type_id);
3395796c8dcSSimon Schubert 
340cf7f2e2dSJohn Marino       tdesc_add_field (data->current_type, field_name, field_type);
341cf7f2e2dSJohn Marino     }
342cf7f2e2dSJohn Marino   else if (start != -1 && end != -1)
343cf7f2e2dSJohn Marino     {
344cf7f2e2dSJohn Marino       struct tdesc_type *t = data->current_type;
345cf7f2e2dSJohn Marino 
346cf7f2e2dSJohn Marino       if (data->current_type_is_flags)
347cf7f2e2dSJohn Marino 	tdesc_add_flag (t, start, field_name);
348cf7f2e2dSJohn Marino       else
349cf7f2e2dSJohn Marino 	{
350cf7f2e2dSJohn Marino 	  if (data->current_type_size == 0)
351cf7f2e2dSJohn Marino 	    gdb_xml_error (parser,
352c50c785cSJohn Marino 			   _("Implicitly sized type can "
353c50c785cSJohn Marino 			     "not contain bitfield \"%s\""),
354cf7f2e2dSJohn Marino 			   field_name);
355cf7f2e2dSJohn Marino 
356cf7f2e2dSJohn Marino 	  if (end >= 64)
357cf7f2e2dSJohn Marino 	    gdb_xml_error (parser,
358c50c785cSJohn Marino 			   _("Bitfield \"%s\" goes past "
359c50c785cSJohn Marino 			     "64 bits (unsupported)"),
360cf7f2e2dSJohn Marino 			   field_name);
361cf7f2e2dSJohn Marino 
362cf7f2e2dSJohn Marino 	  /* Assume that the bit numbering in XML is "lsb-zero".  Most
363cf7f2e2dSJohn Marino 	     architectures other than PowerPC use this ordering.  In
364cf7f2e2dSJohn Marino 	     the future, we can add an XML tag to indicate "msb-zero"
365cf7f2e2dSJohn Marino 	     numbering.  */
366cf7f2e2dSJohn Marino 	  if (start > end)
367cf7f2e2dSJohn Marino 	    gdb_xml_error (parser, _("Bitfield \"%s\" has start after end"),
368cf7f2e2dSJohn Marino 			   field_name);
369cf7f2e2dSJohn Marino 
370cf7f2e2dSJohn Marino 	  if (end >= data->current_type_size * TARGET_CHAR_BIT)
371c50c785cSJohn Marino 	    gdb_xml_error (parser,
372c50c785cSJohn Marino 			   _("Bitfield \"%s\" does not fit in struct"));
373cf7f2e2dSJohn Marino 
374cf7f2e2dSJohn Marino 	  tdesc_add_bitfield (t, field_name, start, end);
375cf7f2e2dSJohn Marino 	}
376cf7f2e2dSJohn Marino     }
377cf7f2e2dSJohn Marino   else
378cf7f2e2dSJohn Marino     gdb_xml_error (parser, _("Field \"%s\" has neither type nor bit position"),
379cf7f2e2dSJohn Marino 		   field_name);
3805796c8dcSSimon Schubert }
3815796c8dcSSimon Schubert 
3825796c8dcSSimon Schubert /* Handle the start of a <vector> element.  Initialize the type and
3835796c8dcSSimon Schubert    record it with the current feature.  */
3845796c8dcSSimon Schubert 
3855796c8dcSSimon Schubert static void
tdesc_start_vector(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)3865796c8dcSSimon Schubert tdesc_start_vector (struct gdb_xml_parser *parser,
3875796c8dcSSimon Schubert 		    const struct gdb_xml_element *element,
3885796c8dcSSimon Schubert 		    void *user_data, VEC(gdb_xml_value_s) *attributes)
3895796c8dcSSimon Schubert {
3905796c8dcSSimon Schubert   struct tdesc_parsing_data *data = user_data;
3915796c8dcSSimon Schubert   struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
3925796c8dcSSimon Schubert   struct tdesc_type *field_type;
3935796c8dcSSimon Schubert   char *id, *field_type_id;
3945796c8dcSSimon Schubert   int count;
3955796c8dcSSimon Schubert 
3965796c8dcSSimon Schubert   id = attrs[0].value;
3975796c8dcSSimon Schubert   field_type_id = attrs[1].value;
3985796c8dcSSimon Schubert   count = * (ULONGEST *) attrs[2].value;
3995796c8dcSSimon Schubert 
4005796c8dcSSimon Schubert   field_type = tdesc_named_type (data->current_feature, field_type_id);
4015796c8dcSSimon Schubert   if (field_type == NULL)
4025796c8dcSSimon Schubert     gdb_xml_error (parser, _("Vector \"%s\" references undefined type \"%s\""),
4035796c8dcSSimon Schubert 		   id, field_type_id);
4045796c8dcSSimon Schubert 
4055796c8dcSSimon Schubert   tdesc_create_vector (data->current_feature, id, field_type, count);
4065796c8dcSSimon Schubert }
4075796c8dcSSimon Schubert 
4085796c8dcSSimon Schubert /* The elements and attributes of an XML target description.  */
4095796c8dcSSimon Schubert 
4105796c8dcSSimon Schubert static const struct gdb_xml_attribute field_attributes[] = {
4115796c8dcSSimon Schubert   { "name", GDB_XML_AF_NONE, NULL, NULL },
412cf7f2e2dSJohn Marino   { "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
413cf7f2e2dSJohn Marino   { "start", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
414cf7f2e2dSJohn Marino   { "end", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
4155796c8dcSSimon Schubert   { NULL, GDB_XML_AF_NONE, NULL, NULL }
4165796c8dcSSimon Schubert };
4175796c8dcSSimon Schubert 
418cf7f2e2dSJohn Marino static const struct gdb_xml_element struct_union_children[] = {
4195796c8dcSSimon Schubert   { "field", field_attributes, NULL, GDB_XML_EF_REPEATABLE,
4205796c8dcSSimon Schubert     tdesc_start_field, NULL },
4215796c8dcSSimon Schubert   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
4225796c8dcSSimon Schubert };
4235796c8dcSSimon Schubert 
4245796c8dcSSimon Schubert static const struct gdb_xml_attribute reg_attributes[] = {
4255796c8dcSSimon Schubert   { "name", GDB_XML_AF_NONE, NULL, NULL },
4265796c8dcSSimon Schubert   { "bitsize", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
4275796c8dcSSimon Schubert   { "regnum", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
4285796c8dcSSimon Schubert   { "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
4295796c8dcSSimon Schubert   { "group", GDB_XML_AF_OPTIONAL, NULL, NULL },
4305796c8dcSSimon Schubert   { "save-restore", GDB_XML_AF_OPTIONAL,
4315796c8dcSSimon Schubert     gdb_xml_parse_attr_enum, gdb_xml_enums_boolean },
4325796c8dcSSimon Schubert   { NULL, GDB_XML_AF_NONE, NULL, NULL }
4335796c8dcSSimon Schubert };
4345796c8dcSSimon Schubert 
435cf7f2e2dSJohn Marino static const struct gdb_xml_attribute struct_union_attributes[] = {
4365796c8dcSSimon Schubert   { "id", GDB_XML_AF_NONE, NULL, NULL },
437cf7f2e2dSJohn Marino   { "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL},
438cf7f2e2dSJohn Marino   { NULL, GDB_XML_AF_NONE, NULL, NULL }
439cf7f2e2dSJohn Marino };
440cf7f2e2dSJohn Marino 
441cf7f2e2dSJohn Marino static const struct gdb_xml_attribute flags_attributes[] = {
442cf7f2e2dSJohn Marino   { "id", GDB_XML_AF_NONE, NULL, NULL },
443cf7f2e2dSJohn Marino   { "size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL},
4445796c8dcSSimon Schubert   { NULL, GDB_XML_AF_NONE, NULL, NULL }
4455796c8dcSSimon Schubert };
4465796c8dcSSimon Schubert 
4475796c8dcSSimon Schubert static const struct gdb_xml_attribute vector_attributes[] = {
4485796c8dcSSimon Schubert   { "id", GDB_XML_AF_NONE, NULL, NULL },
4495796c8dcSSimon Schubert   { "type", GDB_XML_AF_NONE, NULL, NULL },
4505796c8dcSSimon Schubert   { "count", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
4515796c8dcSSimon Schubert   { NULL, GDB_XML_AF_NONE, NULL, NULL }
4525796c8dcSSimon Schubert };
4535796c8dcSSimon Schubert 
4545796c8dcSSimon Schubert static const struct gdb_xml_attribute feature_attributes[] = {
4555796c8dcSSimon Schubert   { "name", GDB_XML_AF_NONE, NULL, NULL },
4565796c8dcSSimon Schubert   { NULL, GDB_XML_AF_NONE, NULL, NULL }
4575796c8dcSSimon Schubert };
4585796c8dcSSimon Schubert 
4595796c8dcSSimon Schubert static const struct gdb_xml_element feature_children[] = {
4605796c8dcSSimon Schubert   { "reg", reg_attributes, NULL,
4615796c8dcSSimon Schubert     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
4625796c8dcSSimon Schubert     tdesc_start_reg, NULL },
463cf7f2e2dSJohn Marino   { "struct", struct_union_attributes, struct_union_children,
464cf7f2e2dSJohn Marino     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
465cf7f2e2dSJohn Marino     tdesc_start_struct, NULL },
466cf7f2e2dSJohn Marino   { "union", struct_union_attributes, struct_union_children,
4675796c8dcSSimon Schubert     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
4685796c8dcSSimon Schubert     tdesc_start_union, NULL },
469cf7f2e2dSJohn Marino   { "flags", flags_attributes, struct_union_children,
470cf7f2e2dSJohn Marino     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
471cf7f2e2dSJohn Marino     tdesc_start_flags, NULL },
4725796c8dcSSimon Schubert   { "vector", vector_attributes, NULL,
4735796c8dcSSimon Schubert     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
4745796c8dcSSimon Schubert     tdesc_start_vector, NULL },
4755796c8dcSSimon Schubert   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
4765796c8dcSSimon Schubert };
4775796c8dcSSimon Schubert 
4785796c8dcSSimon Schubert static const struct gdb_xml_attribute target_attributes[] = {
4795796c8dcSSimon Schubert   { "version", GDB_XML_AF_NONE, NULL, NULL },
4805796c8dcSSimon Schubert   { NULL, GDB_XML_AF_NONE, NULL, NULL }
4815796c8dcSSimon Schubert };
4825796c8dcSSimon Schubert 
4835796c8dcSSimon Schubert static const struct gdb_xml_element target_children[] = {
4845796c8dcSSimon Schubert   { "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
4855796c8dcSSimon Schubert     NULL, tdesc_end_arch },
4865796c8dcSSimon Schubert   { "osabi", NULL, NULL, GDB_XML_EF_OPTIONAL,
4875796c8dcSSimon Schubert     NULL, tdesc_end_osabi },
4885796c8dcSSimon Schubert   { "compatible", NULL, NULL, GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
4895796c8dcSSimon Schubert     NULL, tdesc_end_compatible },
4905796c8dcSSimon Schubert   { "feature", feature_attributes, feature_children,
4915796c8dcSSimon Schubert     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
4925796c8dcSSimon Schubert     tdesc_start_feature, NULL },
4935796c8dcSSimon Schubert   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
4945796c8dcSSimon Schubert };
4955796c8dcSSimon Schubert 
4965796c8dcSSimon Schubert static const struct gdb_xml_element tdesc_elements[] = {
4975796c8dcSSimon Schubert   { "target", target_attributes, target_children, GDB_XML_EF_NONE,
4985796c8dcSSimon Schubert     tdesc_start_target, NULL },
4995796c8dcSSimon Schubert   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
5005796c8dcSSimon Schubert };
5015796c8dcSSimon Schubert 
5025796c8dcSSimon Schubert /* Parse DOCUMENT into a target description and return it.  */
5035796c8dcSSimon Schubert 
5045796c8dcSSimon Schubert static struct target_desc *
tdesc_parse_xml(const char * document,xml_fetch_another fetcher,void * fetcher_baton)5055796c8dcSSimon Schubert tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
5065796c8dcSSimon Schubert 		 void *fetcher_baton)
5075796c8dcSSimon Schubert {
5085796c8dcSSimon Schubert   struct cleanup *back_to, *result_cleanup;
5095796c8dcSSimon Schubert   struct tdesc_parsing_data data;
5105796c8dcSSimon Schubert   struct tdesc_xml_cache *cache;
5115796c8dcSSimon Schubert   char *expanded_text;
5125796c8dcSSimon Schubert   int ix;
5135796c8dcSSimon Schubert 
5145796c8dcSSimon Schubert   /* Expand all XInclude directives.  */
5155796c8dcSSimon Schubert   expanded_text = xml_process_xincludes (_("target description"),
5165796c8dcSSimon Schubert 					 document, fetcher, fetcher_baton, 0);
5175796c8dcSSimon Schubert   if (expanded_text == NULL)
5185796c8dcSSimon Schubert     {
5195796c8dcSSimon Schubert       warning (_("Could not load XML target description; ignoring"));
5205796c8dcSSimon Schubert       return NULL;
5215796c8dcSSimon Schubert     }
5225796c8dcSSimon Schubert 
5235796c8dcSSimon Schubert   /* Check for an exact match in the list of descriptions we have
5245796c8dcSSimon Schubert      previously parsed.  strcmp is a slightly inefficient way to
5255796c8dcSSimon Schubert      do this; an SHA-1 checksum would work as well.  */
5265796c8dcSSimon Schubert   for (ix = 0; VEC_iterate (tdesc_xml_cache_s, xml_cache, ix, cache); ix++)
5275796c8dcSSimon Schubert     if (strcmp (cache->xml_document, expanded_text) == 0)
5285796c8dcSSimon Schubert       {
5295796c8dcSSimon Schubert        xfree (expanded_text);
5305796c8dcSSimon Schubert        return cache->tdesc;
5315796c8dcSSimon Schubert       }
5325796c8dcSSimon Schubert 
5335796c8dcSSimon Schubert   back_to = make_cleanup (null_cleanup, NULL);
5345796c8dcSSimon Schubert 
5355796c8dcSSimon Schubert   memset (&data, 0, sizeof (struct tdesc_parsing_data));
5365796c8dcSSimon Schubert   data.tdesc = allocate_target_description ();
5375796c8dcSSimon Schubert   result_cleanup = make_cleanup_free_target_description (data.tdesc);
5385796c8dcSSimon Schubert   make_cleanup (xfree, expanded_text);
5395796c8dcSSimon Schubert 
540c50c785cSJohn Marino   if (gdb_xml_parse_quick (_("target description"), "gdb-target.dtd",
541c50c785cSJohn Marino 			   tdesc_elements, expanded_text, &data) == 0)
5425796c8dcSSimon Schubert     {
5435796c8dcSSimon Schubert       /* Parsed successfully.  */
5445796c8dcSSimon Schubert       struct tdesc_xml_cache new_cache;
5455796c8dcSSimon Schubert 
5465796c8dcSSimon Schubert       new_cache.xml_document = expanded_text;
5475796c8dcSSimon Schubert       new_cache.tdesc = data.tdesc;
5485796c8dcSSimon Schubert       VEC_safe_push (tdesc_xml_cache_s, xml_cache, &new_cache);
5495796c8dcSSimon Schubert       discard_cleanups (result_cleanup);
5505796c8dcSSimon Schubert       do_cleanups (back_to);
5515796c8dcSSimon Schubert       return data.tdesc;
5525796c8dcSSimon Schubert     }
5535796c8dcSSimon Schubert   else
5545796c8dcSSimon Schubert     {
5555796c8dcSSimon Schubert       warning (_("Could not load XML target description; ignoring"));
5565796c8dcSSimon Schubert       do_cleanups (back_to);
5575796c8dcSSimon Schubert       return NULL;
5585796c8dcSSimon Schubert     }
5595796c8dcSSimon Schubert }
5605796c8dcSSimon Schubert #endif /* HAVE_LIBEXPAT */
5615796c8dcSSimon Schubert 
5625796c8dcSSimon Schubert 
5635796c8dcSSimon Schubert /* Read an XML target description from FILENAME.  Parse it, and return
5645796c8dcSSimon Schubert    the parsed description.  */
5655796c8dcSSimon Schubert 
5665796c8dcSSimon Schubert const struct target_desc *
file_read_description_xml(const char * filename)5675796c8dcSSimon Schubert file_read_description_xml (const char *filename)
5685796c8dcSSimon Schubert {
5695796c8dcSSimon Schubert   struct target_desc *tdesc;
5705796c8dcSSimon Schubert   char *tdesc_str;
5715796c8dcSSimon Schubert   struct cleanup *back_to;
5725796c8dcSSimon Schubert   char *dirname;
5735796c8dcSSimon Schubert 
5745796c8dcSSimon Schubert   tdesc_str = xml_fetch_content_from_file (filename, NULL);
5755796c8dcSSimon Schubert   if (tdesc_str == NULL)
5765796c8dcSSimon Schubert     {
5775796c8dcSSimon Schubert       warning (_("Could not open \"%s\""), filename);
5785796c8dcSSimon Schubert       return NULL;
5795796c8dcSSimon Schubert     }
5805796c8dcSSimon Schubert 
5815796c8dcSSimon Schubert   back_to = make_cleanup (xfree, tdesc_str);
5825796c8dcSSimon Schubert 
5835796c8dcSSimon Schubert   dirname = ldirname (filename);
5845796c8dcSSimon Schubert   if (dirname != NULL)
5855796c8dcSSimon Schubert     make_cleanup (xfree, dirname);
5865796c8dcSSimon Schubert 
5875796c8dcSSimon Schubert   tdesc = tdesc_parse_xml (tdesc_str, xml_fetch_content_from_file, dirname);
5885796c8dcSSimon Schubert   do_cleanups (back_to);
5895796c8dcSSimon Schubert 
5905796c8dcSSimon Schubert   return tdesc;
5915796c8dcSSimon Schubert }
5925796c8dcSSimon Schubert 
5935796c8dcSSimon Schubert /* Read a string representation of available features from the target,
5945796c8dcSSimon Schubert    using TARGET_OBJECT_AVAILABLE_FEATURES.  The returned string is
5955796c8dcSSimon Schubert    malloc allocated and NUL-terminated.  NAME should be a non-NULL
5965796c8dcSSimon Schubert    string identifying the XML document we want; the top level document
5975796c8dcSSimon Schubert    is "target.xml".  Other calls may be performed for the DTD or
5985796c8dcSSimon Schubert    for <xi:include>.  */
5995796c8dcSSimon Schubert 
6005796c8dcSSimon Schubert static char *
fetch_available_features_from_target(const char * name,void * baton_)6015796c8dcSSimon Schubert fetch_available_features_from_target (const char *name, void *baton_)
6025796c8dcSSimon Schubert {
6035796c8dcSSimon Schubert   struct target_ops *ops = baton_;
6045796c8dcSSimon Schubert 
6055796c8dcSSimon Schubert   /* Read this object as a string.  This ensures that a NUL
6065796c8dcSSimon Schubert      terminator is added.  */
6075796c8dcSSimon Schubert   return target_read_stralloc (ops,
6085796c8dcSSimon Schubert 			       TARGET_OBJECT_AVAILABLE_FEATURES,
6095796c8dcSSimon Schubert 			       name);
6105796c8dcSSimon Schubert }
6115796c8dcSSimon Schubert 
6125796c8dcSSimon Schubert 
6135796c8dcSSimon Schubert /* Read an XML target description using OPS.  Parse it, and return the
6145796c8dcSSimon Schubert    parsed description.  */
6155796c8dcSSimon Schubert 
6165796c8dcSSimon Schubert const struct target_desc *
target_read_description_xml(struct target_ops * ops)6175796c8dcSSimon Schubert target_read_description_xml (struct target_ops *ops)
6185796c8dcSSimon Schubert {
6195796c8dcSSimon Schubert   struct target_desc *tdesc;
6205796c8dcSSimon Schubert   char *tdesc_str;
6215796c8dcSSimon Schubert   struct cleanup *back_to;
6225796c8dcSSimon Schubert 
6235796c8dcSSimon Schubert   tdesc_str = fetch_available_features_from_target ("target.xml", ops);
6245796c8dcSSimon Schubert   if (tdesc_str == NULL)
6255796c8dcSSimon Schubert     return NULL;
6265796c8dcSSimon Schubert 
6275796c8dcSSimon Schubert   back_to = make_cleanup (xfree, tdesc_str);
6285796c8dcSSimon Schubert   tdesc = tdesc_parse_xml (tdesc_str,
6295796c8dcSSimon Schubert 			   fetch_available_features_from_target,
6305796c8dcSSimon Schubert 			   ops);
6315796c8dcSSimon Schubert   do_cleanups (back_to);
6325796c8dcSSimon Schubert 
6335796c8dcSSimon Schubert   return tdesc;
6345796c8dcSSimon Schubert }
635