GDB (API)
/home/stan/gdb/src/gdb/xml-tdesc.c
Go to the documentation of this file.
00001 /* XML target description support for GDB.
00002 
00003    Copyright (C) 2006-2013 Free Software Foundation, Inc.
00004 
00005    Contributed by CodeSourcery.
00006 
00007    This file is part of GDB.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 3 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00021 
00022 #include "defs.h"
00023 #include "target.h"
00024 #include "target-descriptions.h"
00025 #include "xml-support.h"
00026 #include "xml-tdesc.h"
00027 #include "osabi.h"
00028 
00029 #include "filenames.h"
00030 
00031 #include "gdb_assert.h"
00032 
00033 #if !defined(HAVE_LIBEXPAT)
00034 
00035 /* Parse DOCUMENT into a target description.  Or don't, since we don't have
00036    an XML parser.  */
00037 
00038 static struct target_desc *
00039 tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
00040                  void *fetcher_baton)
00041 {
00042   static int have_warned;
00043 
00044   if (!have_warned)
00045     {
00046       have_warned = 1;
00047       warning (_("Can not parse XML target description; XML support was "
00048                  "disabled at compile time"));
00049     }
00050 
00051   return NULL;
00052 }
00053 
00054 #else /* HAVE_LIBEXPAT */
00055 
00056 /* A record of every XML description we have parsed.  We never discard
00057    old descriptions, because we never discard gdbarches.  As long as we
00058    have a gdbarch referencing this description, we want to have a copy
00059    of it here, so that if we parse the same XML document again we can
00060    return the same "struct target_desc *"; if they are not singletons,
00061    then we will create unnecessary duplicate gdbarches.  See
00062    gdbarch_list_lookup_by_info.  */
00063 
00064 struct tdesc_xml_cache
00065 {
00066   const char *xml_document;
00067   struct target_desc *tdesc;
00068 };
00069 typedef struct tdesc_xml_cache tdesc_xml_cache_s;
00070 DEF_VEC_O(tdesc_xml_cache_s);
00071 
00072 static VEC(tdesc_xml_cache_s) *xml_cache;
00073 
00074 /* Callback data for target description parsing.  */
00075 
00076 struct tdesc_parsing_data
00077 {
00078   /* The target description we are building.  */
00079   struct target_desc *tdesc;
00080 
00081   /* The target feature we are currently parsing, or last parsed.  */
00082   struct tdesc_feature *current_feature;
00083 
00084   /* The register number to use for the next register we see, if
00085      it does not have its own.  This starts at zero.  */
00086   int next_regnum;
00087 
00088   /* The struct or union we are currently parsing, or last parsed.  */
00089   struct tdesc_type *current_type;
00090 
00091   /* The byte size of the current struct type, if specified.  Zero
00092      if not specified.  */
00093   int current_type_size;
00094 
00095   /* Whether the current type is a flags type.  */
00096   int current_type_is_flags;
00097 };
00098 
00099 /* Handle the end of an <architecture> element and its value.  */
00100 
00101 static void
00102 tdesc_end_arch (struct gdb_xml_parser *parser,
00103                 const struct gdb_xml_element *element,
00104                 void *user_data, const char *body_text)
00105 {
00106   struct tdesc_parsing_data *data = user_data;
00107   const struct bfd_arch_info *arch;
00108 
00109   arch = bfd_scan_arch (body_text);
00110   if (arch == NULL)
00111     gdb_xml_error (parser, _("Target description specified unknown "
00112                              "architecture \"%s\""), body_text);
00113   set_tdesc_architecture (data->tdesc, arch);
00114 }
00115 
00116 /* Handle the end of an <osabi> element and its value.  */
00117 
00118 static void
00119 tdesc_end_osabi (struct gdb_xml_parser *parser,
00120                  const struct gdb_xml_element *element,
00121                  void *user_data, const char *body_text)
00122 {
00123   struct tdesc_parsing_data *data = user_data;
00124   enum gdb_osabi osabi;
00125 
00126   osabi = osabi_from_tdesc_string (body_text);
00127   if (osabi == GDB_OSABI_UNKNOWN)
00128     warning (_("Target description specified unknown osabi \"%s\""),
00129              body_text);
00130   else
00131     set_tdesc_osabi (data->tdesc, osabi);
00132 }
00133 
00134 /* Handle the end of a <compatible> element and its value.  */
00135 
00136 static void
00137 tdesc_end_compatible (struct gdb_xml_parser *parser,
00138                       const struct gdb_xml_element *element,
00139                       void *user_data, const char *body_text)
00140 {
00141   struct tdesc_parsing_data *data = user_data;
00142   const struct bfd_arch_info *arch;
00143 
00144   arch = bfd_scan_arch (body_text);
00145   tdesc_add_compatible (data->tdesc, arch);
00146 }
00147 
00148 /* Handle the start of a <target> element.  */
00149 
00150 static void
00151 tdesc_start_target (struct gdb_xml_parser *parser,
00152                     const struct gdb_xml_element *element,
00153                     void *user_data, VEC(gdb_xml_value_s) *attributes)
00154 {
00155   char *version = xml_find_attribute (attributes, "version")->value;
00156 
00157   if (strcmp (version, "1.0") != 0)
00158     gdb_xml_error (parser,
00159                    _("Target description has unsupported version \"%s\""),
00160                    version);
00161 }
00162 
00163 /* Handle the start of a <feature> element.  */
00164 
00165 static void
00166 tdesc_start_feature (struct gdb_xml_parser *parser,
00167                      const struct gdb_xml_element *element,
00168                      void *user_data, VEC(gdb_xml_value_s) *attributes)
00169 {
00170   struct tdesc_parsing_data *data = user_data;
00171   char *name = xml_find_attribute (attributes, "name")->value;
00172 
00173   data->current_feature = tdesc_create_feature (data->tdesc, name);
00174 }
00175 
00176 /* Handle the start of a <reg> element.  Fill in the optional
00177    attributes and attach it to the containing feature.  */
00178 
00179 static void
00180 tdesc_start_reg (struct gdb_xml_parser *parser,
00181                  const struct gdb_xml_element *element,
00182                  void *user_data, VEC(gdb_xml_value_s) *attributes)
00183 {
00184   struct tdesc_parsing_data *data = user_data;
00185   struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
00186   int ix = 0, length;
00187   char *name, *group, *type;
00188   int bitsize, regnum, save_restore;
00189 
00190   length = VEC_length (gdb_xml_value_s, attributes);
00191 
00192   name = attrs[ix++].value;
00193   bitsize = * (ULONGEST *) attrs[ix++].value;
00194 
00195   if (ix < length && strcmp (attrs[ix].name, "regnum") == 0)
00196     regnum = * (ULONGEST *) attrs[ix++].value;
00197   else
00198     regnum = data->next_regnum;
00199 
00200   if (ix < length && strcmp (attrs[ix].name, "type") == 0)
00201     type = attrs[ix++].value;
00202   else
00203     type = "int";
00204 
00205   if (ix < length && strcmp (attrs[ix].name, "group") == 0)
00206     group = attrs[ix++].value;
00207   else
00208     group = NULL;
00209 
00210   if (ix < length && strcmp (attrs[ix].name, "save-restore") == 0)
00211     save_restore = * (ULONGEST *) attrs[ix++].value;
00212   else
00213     save_restore = 1;
00214 
00215   if (strcmp (type, "int") != 0
00216       && strcmp (type, "float") != 0
00217       && tdesc_named_type (data->current_feature, type) == NULL)
00218     gdb_xml_error (parser, _("Register \"%s\" has unknown type \"%s\""),
00219                    name, type);
00220 
00221   tdesc_create_reg (data->current_feature, name, regnum, save_restore, group,
00222                     bitsize, type);
00223 
00224   data->next_regnum = regnum + 1;
00225 }
00226 
00227 /* Handle the start of a <union> element.  Initialize the type and
00228    record it with the current feature.  */
00229 
00230 static void
00231 tdesc_start_union (struct gdb_xml_parser *parser,
00232                    const struct gdb_xml_element *element,
00233                    void *user_data, VEC(gdb_xml_value_s) *attributes)
00234 {
00235   struct tdesc_parsing_data *data = user_data;
00236   char *id = xml_find_attribute (attributes, "id")->value;
00237 
00238   data->current_type = tdesc_create_union (data->current_feature, id);
00239   data->current_type_size = 0;
00240   data->current_type_is_flags = 0;
00241 }
00242 
00243 /* Handle the start of a <struct> element.  Initialize the type and
00244    record it with the current feature.  */
00245 
00246 static void
00247 tdesc_start_struct (struct gdb_xml_parser *parser,
00248                    const struct gdb_xml_element *element,
00249                    void *user_data, VEC(gdb_xml_value_s) *attributes)
00250 {
00251   struct tdesc_parsing_data *data = user_data;
00252   char *id = xml_find_attribute (attributes, "id")->value;
00253   struct tdesc_type *type;
00254   struct gdb_xml_value *attr;
00255 
00256   type = tdesc_create_struct (data->current_feature, id);
00257   data->current_type = type;
00258   data->current_type_size = 0;
00259   data->current_type_is_flags = 0;
00260 
00261   attr = xml_find_attribute (attributes, "size");
00262   if (attr != NULL)
00263     {
00264       int size = (int) * (ULONGEST *) attr->value;
00265 
00266       tdesc_set_struct_size (type, size);
00267       data->current_type_size = size;
00268     }
00269 }
00270 
00271 static void
00272 tdesc_start_flags (struct gdb_xml_parser *parser,
00273                    const struct gdb_xml_element *element,
00274                    void *user_data, VEC(gdb_xml_value_s) *attributes)
00275 {
00276   struct tdesc_parsing_data *data = user_data;
00277   char *id = xml_find_attribute (attributes, "id")->value;
00278   int length = (int) * (ULONGEST *)
00279     xml_find_attribute (attributes, "size")->value;
00280   struct tdesc_type *type;
00281 
00282   type = tdesc_create_flags (data->current_feature, id, length);
00283 
00284   data->current_type = type;
00285   data->current_type_size = 0;
00286   data->current_type_is_flags = 1;
00287 }
00288 
00289 /* Handle the start of a <field> element.  Attach the field to the
00290    current struct or union.  */
00291 
00292 static void
00293 tdesc_start_field (struct gdb_xml_parser *parser,
00294                    const struct gdb_xml_element *element,
00295                    void *user_data, VEC(gdb_xml_value_s) *attributes)
00296 {
00297   struct tdesc_parsing_data *data = user_data;
00298   struct gdb_xml_value *attr;
00299   struct tdesc_type *field_type;
00300   char *field_name, *field_type_id;
00301   int start, end;
00302 
00303   field_name = xml_find_attribute (attributes, "name")->value;
00304 
00305   attr = xml_find_attribute (attributes, "type");
00306   if (attr != NULL)
00307     field_type_id = attr->value;
00308   else
00309     field_type_id = NULL;
00310 
00311   attr = xml_find_attribute (attributes, "start");
00312   if (attr != NULL)
00313     start = * (ULONGEST *) attr->value;
00314   else
00315     start = -1;
00316 
00317   attr = xml_find_attribute (attributes, "end");
00318   if (attr != NULL)
00319     end = * (ULONGEST *) attr->value;
00320   else
00321     end = -1;
00322 
00323   if (field_type_id != NULL)
00324     {
00325       if (data->current_type_is_flags)
00326         gdb_xml_error (parser, _("Cannot add typed field \"%s\" to flags"), 
00327                        field_name);
00328       if (data->current_type_size != 0)
00329         gdb_xml_error (parser,
00330                        _("Explicitly sized type can not "
00331                          "contain non-bitfield \"%s\""), 
00332                        field_name);
00333 
00334       field_type = tdesc_named_type (data->current_feature, field_type_id);
00335       if (field_type == NULL)
00336         gdb_xml_error (parser, _("Field \"%s\" references undefined "
00337                                  "type \"%s\""),
00338                        field_name, field_type_id);
00339 
00340       tdesc_add_field (data->current_type, field_name, field_type);
00341     }
00342   else if (start != -1 && end != -1)
00343     {
00344       struct tdesc_type *t = data->current_type;
00345 
00346       if (data->current_type_is_flags)
00347         tdesc_add_flag (t, start, field_name);
00348       else
00349         {
00350           if (data->current_type_size == 0)
00351             gdb_xml_error (parser,
00352                            _("Implicitly sized type can "
00353                              "not contain bitfield \"%s\""), 
00354                            field_name);
00355 
00356           if (end >= 64)
00357             gdb_xml_error (parser,
00358                            _("Bitfield \"%s\" goes past "
00359                              "64 bits (unsupported)"),
00360                            field_name);
00361 
00362           /* Assume that the bit numbering in XML is "lsb-zero".  Most
00363              architectures other than PowerPC use this ordering.  In
00364              the future, we can add an XML tag to indicate "msb-zero"
00365              numbering.  */
00366           if (start > end)
00367             gdb_xml_error (parser, _("Bitfield \"%s\" has start after end"),
00368                            field_name);
00369 
00370           if (end >= data->current_type_size * TARGET_CHAR_BIT)
00371             gdb_xml_error (parser,
00372                            _("Bitfield \"%s\" does not fit in struct"));
00373 
00374           tdesc_add_bitfield (t, field_name, start, end);
00375         }
00376     }
00377   else
00378     gdb_xml_error (parser, _("Field \"%s\" has neither type nor bit position"),
00379                    field_name);
00380 }
00381 
00382 /* Handle the start of a <vector> element.  Initialize the type and
00383    record it with the current feature.  */
00384 
00385 static void
00386 tdesc_start_vector (struct gdb_xml_parser *parser,
00387                     const struct gdb_xml_element *element,
00388                     void *user_data, VEC(gdb_xml_value_s) *attributes)
00389 {
00390   struct tdesc_parsing_data *data = user_data;
00391   struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
00392   struct tdesc_type *field_type;
00393   char *id, *field_type_id;
00394   int count;
00395 
00396   id = attrs[0].value;
00397   field_type_id = attrs[1].value;
00398   count = * (ULONGEST *) attrs[2].value;
00399 
00400   field_type = tdesc_named_type (data->current_feature, field_type_id);
00401   if (field_type == NULL)
00402     gdb_xml_error (parser, _("Vector \"%s\" references undefined type \"%s\""),
00403                    id, field_type_id);
00404 
00405   tdesc_create_vector (data->current_feature, id, field_type, count);
00406 }
00407 
00408 /* The elements and attributes of an XML target description.  */
00409 
00410 static const struct gdb_xml_attribute field_attributes[] = {
00411   { "name", GDB_XML_AF_NONE, NULL, NULL },
00412   { "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
00413   { "start", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
00414   { "end", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
00415   { NULL, GDB_XML_AF_NONE, NULL, NULL }
00416 };
00417 
00418 static const struct gdb_xml_element struct_union_children[] = {
00419   { "field", field_attributes, NULL, GDB_XML_EF_REPEATABLE,
00420     tdesc_start_field, NULL },
00421   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
00422 };
00423 
00424 static const struct gdb_xml_attribute reg_attributes[] = {
00425   { "name", GDB_XML_AF_NONE, NULL, NULL },
00426   { "bitsize", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
00427   { "regnum", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
00428   { "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
00429   { "group", GDB_XML_AF_OPTIONAL, NULL, NULL },
00430   { "save-restore", GDB_XML_AF_OPTIONAL,
00431     gdb_xml_parse_attr_enum, gdb_xml_enums_boolean },
00432   { NULL, GDB_XML_AF_NONE, NULL, NULL }
00433 };
00434 
00435 static const struct gdb_xml_attribute struct_union_attributes[] = {
00436   { "id", GDB_XML_AF_NONE, NULL, NULL },
00437   { "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL},
00438   { NULL, GDB_XML_AF_NONE, NULL, NULL }
00439 };
00440 
00441 static const struct gdb_xml_attribute flags_attributes[] = {
00442   { "id", GDB_XML_AF_NONE, NULL, NULL },
00443   { "size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL},
00444   { NULL, GDB_XML_AF_NONE, NULL, NULL }
00445 };
00446 
00447 static const struct gdb_xml_attribute vector_attributes[] = {
00448   { "id", GDB_XML_AF_NONE, NULL, NULL },
00449   { "type", GDB_XML_AF_NONE, NULL, NULL },
00450   { "count", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
00451   { NULL, GDB_XML_AF_NONE, NULL, NULL }
00452 };
00453 
00454 static const struct gdb_xml_attribute feature_attributes[] = {
00455   { "name", GDB_XML_AF_NONE, NULL, NULL },
00456   { NULL, GDB_XML_AF_NONE, NULL, NULL }
00457 };
00458 
00459 static const struct gdb_xml_element feature_children[] = {
00460   { "reg", reg_attributes, NULL,
00461     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
00462     tdesc_start_reg, NULL },
00463   { "struct", struct_union_attributes, struct_union_children,
00464     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
00465     tdesc_start_struct, NULL },
00466   { "union", struct_union_attributes, struct_union_children,
00467     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
00468     tdesc_start_union, NULL },
00469   { "flags", flags_attributes, struct_union_children,
00470     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
00471     tdesc_start_flags, NULL },    
00472   { "vector", vector_attributes, NULL,
00473     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
00474     tdesc_start_vector, NULL },
00475   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
00476 };
00477 
00478 static const struct gdb_xml_attribute target_attributes[] = {
00479   { "version", GDB_XML_AF_NONE, NULL, NULL },
00480   { NULL, GDB_XML_AF_NONE, NULL, NULL }
00481 };
00482 
00483 static const struct gdb_xml_element target_children[] = {
00484   { "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
00485     NULL, tdesc_end_arch },
00486   { "osabi", NULL, NULL, GDB_XML_EF_OPTIONAL,
00487     NULL, tdesc_end_osabi },
00488   { "compatible", NULL, NULL, GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
00489     NULL, tdesc_end_compatible },
00490   { "feature", feature_attributes, feature_children,
00491     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
00492     tdesc_start_feature, NULL },
00493   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
00494 };
00495 
00496 static const struct gdb_xml_element tdesc_elements[] = {
00497   { "target", target_attributes, target_children, GDB_XML_EF_NONE,
00498     tdesc_start_target, NULL },
00499   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
00500 };
00501 
00502 /* Parse DOCUMENT into a target description and return it.  */
00503 
00504 static struct target_desc *
00505 tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
00506                  void *fetcher_baton)
00507 {
00508   struct cleanup *back_to, *result_cleanup;
00509   struct tdesc_parsing_data data;
00510   struct tdesc_xml_cache *cache;
00511   char *expanded_text;
00512   int ix;
00513 
00514   /* Expand all XInclude directives.  */
00515   expanded_text = xml_process_xincludes (_("target description"),
00516                                          document, fetcher, fetcher_baton, 0);
00517   if (expanded_text == NULL)
00518     {
00519       warning (_("Could not load XML target description; ignoring"));
00520       return NULL;
00521     }
00522 
00523   /* Check for an exact match in the list of descriptions we have
00524      previously parsed.  strcmp is a slightly inefficient way to
00525      do this; an SHA-1 checksum would work as well.  */
00526   for (ix = 0; VEC_iterate (tdesc_xml_cache_s, xml_cache, ix, cache); ix++)
00527     if (strcmp (cache->xml_document, expanded_text) == 0)
00528       {
00529        xfree (expanded_text);
00530        return cache->tdesc;
00531       }
00532 
00533   back_to = make_cleanup (null_cleanup, NULL);
00534 
00535   memset (&data, 0, sizeof (struct tdesc_parsing_data));
00536   data.tdesc = allocate_target_description ();
00537   result_cleanup = make_cleanup_free_target_description (data.tdesc);
00538   make_cleanup (xfree, expanded_text);
00539 
00540   if (gdb_xml_parse_quick (_("target description"), "gdb-target.dtd",
00541                            tdesc_elements, expanded_text, &data) == 0)
00542     {
00543       /* Parsed successfully.  */
00544       struct tdesc_xml_cache new_cache;
00545 
00546       new_cache.xml_document = expanded_text;
00547       new_cache.tdesc = data.tdesc;
00548       VEC_safe_push (tdesc_xml_cache_s, xml_cache, &new_cache);
00549       discard_cleanups (result_cleanup);
00550       do_cleanups (back_to);
00551       return data.tdesc;
00552     }
00553   else
00554     {
00555       warning (_("Could not load XML target description; ignoring"));
00556       do_cleanups (back_to);
00557       return NULL;
00558     }
00559 }
00560 #endif /* HAVE_LIBEXPAT */
00561 
00562 
00563 /* Read an XML target description from FILENAME.  Parse it, and return
00564    the parsed description.  */
00565 
00566 const struct target_desc *
00567 file_read_description_xml (const char *filename)
00568 {
00569   struct target_desc *tdesc;
00570   char *tdesc_str;
00571   struct cleanup *back_to;
00572   char *dirname;
00573 
00574   tdesc_str = xml_fetch_content_from_file (filename, NULL);
00575   if (tdesc_str == NULL)
00576     {
00577       warning (_("Could not open \"%s\""), filename);
00578       return NULL;
00579     }
00580 
00581   back_to = make_cleanup (xfree, tdesc_str);
00582 
00583   dirname = ldirname (filename);
00584   if (dirname != NULL)
00585     make_cleanup (xfree, dirname);
00586 
00587   tdesc = tdesc_parse_xml (tdesc_str, xml_fetch_content_from_file, dirname);
00588   do_cleanups (back_to);
00589 
00590   return tdesc;
00591 }
00592 
00593 /* Read a string representation of available features from the target,
00594    using TARGET_OBJECT_AVAILABLE_FEATURES.  The returned string is
00595    malloc allocated and NUL-terminated.  NAME should be a non-NULL
00596    string identifying the XML document we want; the top level document
00597    is "target.xml".  Other calls may be performed for the DTD or
00598    for <xi:include>.  */
00599 
00600 static char *
00601 fetch_available_features_from_target (const char *name, void *baton_)
00602 {
00603   struct target_ops *ops = baton_;
00604 
00605   /* Read this object as a string.  This ensures that a NUL
00606      terminator is added.  */
00607   return target_read_stralloc (ops,
00608                                TARGET_OBJECT_AVAILABLE_FEATURES,
00609                                name);
00610 }
00611 
00612 
00613 /* Read an XML target description using OPS.  Parse it, and return the
00614    parsed description.  */
00615 
00616 const struct target_desc *
00617 target_read_description_xml (struct target_ops *ops)
00618 {
00619   struct target_desc *tdesc;
00620   char *tdesc_str;
00621   struct cleanup *back_to;
00622 
00623   tdesc_str = fetch_available_features_from_target ("target.xml", ops);
00624   if (tdesc_str == NULL)
00625     return NULL;
00626 
00627   back_to = make_cleanup (xfree, tdesc_str);
00628   tdesc = tdesc_parse_xml (tdesc_str,
00629                            fetch_available_features_from_target,
00630                            ops);
00631   do_cleanups (back_to);
00632 
00633   return tdesc;
00634 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines