]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/xml-tdesc.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / gdb / xml-tdesc.c
CommitLineData
23181151
DJ
1/* XML target description support for GDB.
2
8acc9f48 3 Copyright (C) 2006-2013 Free Software Foundation, Inc.
23181151
DJ
4
5 Contributed by CodeSourcery.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
23181151
DJ
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23181151
DJ
21
22#include "defs.h"
23#include "target.h"
24#include "target-descriptions.h"
25#include "xml-support.h"
26#include "xml-tdesc.h"
08d16641 27#include "osabi.h"
23181151 28
108546a0
DJ
29#include "filenames.h"
30
23181151
DJ
31#include "gdb_assert.h"
32
33#if !defined(HAVE_LIBEXPAT)
34
35/* Parse DOCUMENT into a target description. Or don't, since we don't have
36 an XML parser. */
37
38static struct target_desc *
108546a0
DJ
39tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
40 void *fetcher_baton)
23181151
DJ
41{
42 static int have_warned;
43
44 if (!have_warned)
45 {
46 have_warned = 1;
47 warning (_("Can not parse XML target description; XML support was "
48 "disabled at compile time"));
49 }
50
51 return NULL;
52}
53
54#else /* HAVE_LIBEXPAT */
55
fc6e0168
DJ
56/* A record of every XML description we have parsed. We never discard
57 old descriptions, because we never discard gdbarches. As long as we
58 have a gdbarch referencing this description, we want to have a copy
59 of it here, so that if we parse the same XML document again we can
60 return the same "struct target_desc *"; if they are not singletons,
61 then we will create unnecessary duplicate gdbarches. See
62 gdbarch_list_lookup_by_info. */
63
64struct tdesc_xml_cache
65{
66 const char *xml_document;
67 struct target_desc *tdesc;
68};
69typedef struct tdesc_xml_cache tdesc_xml_cache_s;
70DEF_VEC_O(tdesc_xml_cache_s);
71
72static VEC(tdesc_xml_cache_s) *xml_cache;
73
23181151
DJ
74/* Callback data for target description parsing. */
75
76struct tdesc_parsing_data
77{
78 /* The target description we are building. */
79 struct target_desc *tdesc;
123dc839
DJ
80
81 /* The target feature we are currently parsing, or last parsed. */
82 struct tdesc_feature *current_feature;
83
84 /* The register number to use for the next register we see, if
85 it does not have its own. This starts at zero. */
86 int next_regnum;
87
f5dff777
DJ
88 /* The struct or union we are currently parsing, or last parsed. */
89 struct tdesc_type *current_type;
90
91 /* The byte size of the current struct type, if specified. Zero
92 if not specified. */
93 int current_type_size;
94
95 /* Whether the current type is a flags type. */
96 int current_type_is_flags;
23181151
DJ
97};
98
99/* Handle the end of an <architecture> element and its value. */
100
101static void
102tdesc_end_arch (struct gdb_xml_parser *parser,
103 const struct gdb_xml_element *element,
104 void *user_data, const char *body_text)
105{
106 struct tdesc_parsing_data *data = user_data;
107 const struct bfd_arch_info *arch;
108
109 arch = bfd_scan_arch (body_text);
110 if (arch == NULL)
111 gdb_xml_error (parser, _("Target description specified unknown "
112 "architecture \"%s\""), body_text);
113 set_tdesc_architecture (data->tdesc, arch);
114}
115
08d16641
PA
116/* Handle the end of an <osabi> element and its value. */
117
118static void
119tdesc_end_osabi (struct gdb_xml_parser *parser,
120 const struct gdb_xml_element *element,
121 void *user_data, const char *body_text)
122{
123 struct tdesc_parsing_data *data = user_data;
124 enum gdb_osabi osabi;
125
126 osabi = osabi_from_tdesc_string (body_text);
127 if (osabi == GDB_OSABI_UNKNOWN)
128 warning (_("Target description specified unknown osabi \"%s\""),
129 body_text);
130 else
131 set_tdesc_osabi (data->tdesc, osabi);
132}
133
e35359c5
UW
134/* Handle the end of a <compatible> element and its value. */
135
136static void
137tdesc_end_compatible (struct gdb_xml_parser *parser,
138 const struct gdb_xml_element *element,
139 void *user_data, const char *body_text)
140{
141 struct tdesc_parsing_data *data = user_data;
142 const struct bfd_arch_info *arch;
143
144 arch = bfd_scan_arch (body_text);
145 tdesc_add_compatible (data->tdesc, arch);
146}
147
1780a0ed
DJ
148/* Handle the start of a <target> element. */
149
150static void
151tdesc_start_target (struct gdb_xml_parser *parser,
152 const struct gdb_xml_element *element,
153 void *user_data, VEC(gdb_xml_value_s) *attributes)
154{
3d2c1d41 155 char *version = xml_find_attribute (attributes, "version")->value;
1780a0ed
DJ
156
157 if (strcmp (version, "1.0") != 0)
158 gdb_xml_error (parser,
159 _("Target description has unsupported version \"%s\""),
160 version);
161}
162
123dc839
DJ
163/* Handle the start of a <feature> element. */
164
165static void
166tdesc_start_feature (struct gdb_xml_parser *parser,
167 const struct gdb_xml_element *element,
168 void *user_data, VEC(gdb_xml_value_s) *attributes)
169{
170 struct tdesc_parsing_data *data = user_data;
3d2c1d41 171 char *name = xml_find_attribute (attributes, "name")->value;
123dc839
DJ
172
173 data->current_feature = tdesc_create_feature (data->tdesc, name);
174}
175
176/* Handle the start of a <reg> element. Fill in the optional
177 attributes and attach it to the containing feature. */
178
179static void
180tdesc_start_reg (struct gdb_xml_parser *parser,
181 const struct gdb_xml_element *element,
182 void *user_data, VEC(gdb_xml_value_s) *attributes)
183{
184 struct tdesc_parsing_data *data = user_data;
185 struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
186 int ix = 0, length;
187 char *name, *group, *type;
188 int bitsize, regnum, save_restore;
189
190 length = VEC_length (gdb_xml_value_s, attributes);
191
192 name = attrs[ix++].value;
193 bitsize = * (ULONGEST *) attrs[ix++].value;
194
195 if (ix < length && strcmp (attrs[ix].name, "regnum") == 0)
196 regnum = * (ULONGEST *) attrs[ix++].value;
197 else
198 regnum = data->next_regnum;
199
200 if (ix < length && strcmp (attrs[ix].name, "type") == 0)
201 type = attrs[ix++].value;
202 else
203 type = "int";
204
205 if (ix < length && strcmp (attrs[ix].name, "group") == 0)
206 group = attrs[ix++].value;
207 else
208 group = NULL;
209
210 if (ix < length && strcmp (attrs[ix].name, "save-restore") == 0)
211 save_restore = * (ULONGEST *) attrs[ix++].value;
212 else
213 save_restore = 1;
214
215 if (strcmp (type, "int") != 0
216 && strcmp (type, "float") != 0
217 && tdesc_named_type (data->current_feature, type) == NULL)
218 gdb_xml_error (parser, _("Register \"%s\" has unknown type \"%s\""),
219 name, type);
220
221 tdesc_create_reg (data->current_feature, name, regnum, save_restore, group,
222 bitsize, type);
223
224 data->next_regnum = regnum + 1;
225}
226
227/* Handle the start of a <union> element. Initialize the type and
228 record it with the current feature. */
229
230static void
231tdesc_start_union (struct gdb_xml_parser *parser,
232 const struct gdb_xml_element *element,
233 void *user_data, VEC(gdb_xml_value_s) *attributes)
234{
235 struct tdesc_parsing_data *data = user_data;
3d2c1d41 236 char *id = xml_find_attribute (attributes, "id")->value;
123dc839 237
f5dff777
DJ
238 data->current_type = tdesc_create_union (data->current_feature, id);
239 data->current_type_size = 0;
240 data->current_type_is_flags = 0;
241}
242
243/* Handle the start of a <struct> element. Initialize the type and
244 record it with the current feature. */
245
246static void
247tdesc_start_struct (struct gdb_xml_parser *parser,
248 const struct gdb_xml_element *element,
249 void *user_data, VEC(gdb_xml_value_s) *attributes)
250{
251 struct tdesc_parsing_data *data = user_data;
3d2c1d41 252 char *id = xml_find_attribute (attributes, "id")->value;
f5dff777 253 struct tdesc_type *type;
3d2c1d41 254 struct gdb_xml_value *attr;
f5dff777
DJ
255
256 type = tdesc_create_struct (data->current_feature, id);
257 data->current_type = type;
258 data->current_type_size = 0;
259 data->current_type_is_flags = 0;
260
3d2c1d41
PA
261 attr = xml_find_attribute (attributes, "size");
262 if (attr != NULL)
f5dff777 263 {
3d2c1d41 264 int size = (int) * (ULONGEST *) attr->value;
a109c7c1 265
f5dff777
DJ
266 tdesc_set_struct_size (type, size);
267 data->current_type_size = size;
268 }
269}
270
271static void
272tdesc_start_flags (struct gdb_xml_parser *parser,
273 const struct gdb_xml_element *element,
274 void *user_data, VEC(gdb_xml_value_s) *attributes)
275{
276 struct tdesc_parsing_data *data = user_data;
3d2c1d41 277 char *id = xml_find_attribute (attributes, "id")->value;
f5dff777 278 int length = (int) * (ULONGEST *)
3d2c1d41 279 xml_find_attribute (attributes, "size")->value;
f5dff777
DJ
280 struct tdesc_type *type;
281
282 type = tdesc_create_flags (data->current_feature, id, length);
283
284 data->current_type = type;
285 data->current_type_size = 0;
286 data->current_type_is_flags = 1;
123dc839
DJ
287}
288
289/* Handle the start of a <field> element. Attach the field to the
f5dff777 290 current struct or union. */
123dc839
DJ
291
292static void
293tdesc_start_field (struct gdb_xml_parser *parser,
294 const struct gdb_xml_element *element,
295 void *user_data, VEC(gdb_xml_value_s) *attributes)
296{
297 struct tdesc_parsing_data *data = user_data;
3d2c1d41 298 struct gdb_xml_value *attr;
ad068eab 299 struct tdesc_type *field_type;
123dc839 300 char *field_name, *field_type_id;
f5dff777 301 int start, end;
123dc839 302
3d2c1d41 303 field_name = xml_find_attribute (attributes, "name")->value;
123dc839 304
3d2c1d41
PA
305 attr = xml_find_attribute (attributes, "type");
306 if (attr != NULL)
307 field_type_id = attr->value;
f5dff777
DJ
308 else
309 field_type_id = NULL;
310
3d2c1d41
PA
311 attr = xml_find_attribute (attributes, "start");
312 if (attr != NULL)
313 start = * (ULONGEST *) attr->value;
f5dff777
DJ
314 else
315 start = -1;
316
3d2c1d41
PA
317 attr = xml_find_attribute (attributes, "end");
318 if (attr != NULL)
319 end = * (ULONGEST *) attr->value;
f5dff777
DJ
320 else
321 end = -1;
322
323 if (field_type_id != NULL)
324 {
325 if (data->current_type_is_flags)
326 gdb_xml_error (parser, _("Cannot add typed field \"%s\" to flags"),
327 field_name);
328 if (data->current_type_size != 0)
329 gdb_xml_error (parser,
3e43a32a
MS
330 _("Explicitly sized type can not "
331 "contain non-bitfield \"%s\""),
f5dff777
DJ
332 field_name);
333
334 field_type = tdesc_named_type (data->current_feature, field_type_id);
335 if (field_type == NULL)
336 gdb_xml_error (parser, _("Field \"%s\" references undefined "
337 "type \"%s\""),
338 field_name, field_type_id);
339
340 tdesc_add_field (data->current_type, field_name, field_type);
341 }
342 else if (start != -1 && end != -1)
343 {
344 struct tdesc_type *t = data->current_type;
345
346 if (data->current_type_is_flags)
347 tdesc_add_flag (t, start, field_name);
348 else
349 {
350 if (data->current_type_size == 0)
351 gdb_xml_error (parser,
3e43a32a
MS
352 _("Implicitly sized type can "
353 "not contain bitfield \"%s\""),
f5dff777
DJ
354 field_name);
355
356 if (end >= 64)
357 gdb_xml_error (parser,
3e43a32a
MS
358 _("Bitfield \"%s\" goes past "
359 "64 bits (unsupported)"),
f5dff777
DJ
360 field_name);
361
362 /* Assume that the bit numbering in XML is "lsb-zero". Most
363 architectures other than PowerPC use this ordering. In
364 the future, we can add an XML tag to indicate "msb-zero"
365 numbering. */
366 if (start > end)
367 gdb_xml_error (parser, _("Bitfield \"%s\" has start after end"),
368 field_name);
369
370 if (end >= data->current_type_size * TARGET_CHAR_BIT)
3e43a32a
MS
371 gdb_xml_error (parser,
372 _("Bitfield \"%s\" does not fit in struct"));
f5dff777
DJ
373
374 tdesc_add_bitfield (t, field_name, start, end);
375 }
376 }
377 else
378 gdb_xml_error (parser, _("Field \"%s\" has neither type nor bit position"),
379 field_name);
123dc839
DJ
380}
381
382/* Handle the start of a <vector> element. Initialize the type and
383 record it with the current feature. */
384
385static void
386tdesc_start_vector (struct gdb_xml_parser *parser,
387 const struct gdb_xml_element *element,
388 void *user_data, VEC(gdb_xml_value_s) *attributes)
389{
390 struct tdesc_parsing_data *data = user_data;
391 struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
ad068eab 392 struct tdesc_type *field_type;
123dc839
DJ
393 char *id, *field_type_id;
394 int count;
395
396 id = attrs[0].value;
397 field_type_id = attrs[1].value;
398 count = * (ULONGEST *) attrs[2].value;
399
400 field_type = tdesc_named_type (data->current_feature, field_type_id);
401 if (field_type == NULL)
402 gdb_xml_error (parser, _("Vector \"%s\" references undefined type \"%s\""),
403 id, field_type_id);
404
ad068eab 405 tdesc_create_vector (data->current_feature, id, field_type, count);
123dc839
DJ
406}
407
23181151
DJ
408/* The elements and attributes of an XML target description. */
409
123dc839
DJ
410static const struct gdb_xml_attribute field_attributes[] = {
411 { "name", GDB_XML_AF_NONE, NULL, NULL },
f5dff777
DJ
412 { "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
413 { "start", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
414 { "end", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
123dc839
DJ
415 { NULL, GDB_XML_AF_NONE, NULL, NULL }
416};
417
f5dff777 418static const struct gdb_xml_element struct_union_children[] = {
123dc839
DJ
419 { "field", field_attributes, NULL, GDB_XML_EF_REPEATABLE,
420 tdesc_start_field, NULL },
421 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
422};
423
424static const struct gdb_xml_attribute reg_attributes[] = {
425 { "name", GDB_XML_AF_NONE, NULL, NULL },
426 { "bitsize", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
427 { "regnum", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
428 { "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
429 { "group", GDB_XML_AF_OPTIONAL, NULL, NULL },
430 { "save-restore", GDB_XML_AF_OPTIONAL,
431 gdb_xml_parse_attr_enum, gdb_xml_enums_boolean },
432 { NULL, GDB_XML_AF_NONE, NULL, NULL }
433};
434
f5dff777 435static const struct gdb_xml_attribute struct_union_attributes[] = {
123dc839 436 { "id", GDB_XML_AF_NONE, NULL, NULL },
f5dff777
DJ
437 { "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL},
438 { NULL, GDB_XML_AF_NONE, NULL, NULL }
439};
440
441static const struct gdb_xml_attribute flags_attributes[] = {
442 { "id", GDB_XML_AF_NONE, NULL, NULL },
443 { "size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL},
123dc839
DJ
444 { NULL, GDB_XML_AF_NONE, NULL, NULL }
445};
446
447static const struct gdb_xml_attribute vector_attributes[] = {
448 { "id", GDB_XML_AF_NONE, NULL, NULL },
449 { "type", GDB_XML_AF_NONE, NULL, NULL },
450 { "count", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
451 { NULL, GDB_XML_AF_NONE, NULL, NULL }
452};
453
454static const struct gdb_xml_attribute feature_attributes[] = {
455 { "name", GDB_XML_AF_NONE, NULL, NULL },
456 { NULL, GDB_XML_AF_NONE, NULL, NULL }
457};
458
459static const struct gdb_xml_element feature_children[] = {
460 { "reg", reg_attributes, NULL,
461 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
462 tdesc_start_reg, NULL },
f5dff777
DJ
463 { "struct", struct_union_attributes, struct_union_children,
464 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
465 tdesc_start_struct, NULL },
466 { "union", struct_union_attributes, struct_union_children,
123dc839 467 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
ad068eab 468 tdesc_start_union, NULL },
f5dff777
DJ
469 { "flags", flags_attributes, struct_union_children,
470 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
471 tdesc_start_flags, NULL },
123dc839
DJ
472 { "vector", vector_attributes, NULL,
473 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
474 tdesc_start_vector, NULL },
475 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
476};
477
1780a0ed
DJ
478static const struct gdb_xml_attribute target_attributes[] = {
479 { "version", GDB_XML_AF_NONE, NULL, NULL },
480 { NULL, GDB_XML_AF_NONE, NULL, NULL }
481};
482
123dc839 483static const struct gdb_xml_element target_children[] = {
23181151
DJ
484 { "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
485 NULL, tdesc_end_arch },
08d16641
PA
486 { "osabi", NULL, NULL, GDB_XML_EF_OPTIONAL,
487 NULL, tdesc_end_osabi },
e35359c5
UW
488 { "compatible", NULL, NULL, GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
489 NULL, tdesc_end_compatible },
123dc839
DJ
490 { "feature", feature_attributes, feature_children,
491 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
492 tdesc_start_feature, NULL },
23181151
DJ
493 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
494};
495
123dc839 496static const struct gdb_xml_element tdesc_elements[] = {
1780a0ed
DJ
497 { "target", target_attributes, target_children, GDB_XML_EF_NONE,
498 tdesc_start_target, NULL },
23181151
DJ
499 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
500};
501
502/* Parse DOCUMENT into a target description and return it. */
503
504static struct target_desc *
108546a0
DJ
505tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
506 void *fetcher_baton)
23181151
DJ
507{
508 struct cleanup *back_to, *result_cleanup;
23181151 509 struct tdesc_parsing_data data;
fc6e0168 510 struct tdesc_xml_cache *cache;
108546a0 511 char *expanded_text;
fc6e0168 512 int ix;
23181151 513
108546a0
DJ
514 /* Expand all XInclude directives. */
515 expanded_text = xml_process_xincludes (_("target description"),
516 document, fetcher, fetcher_baton, 0);
517 if (expanded_text == NULL)
518 {
519 warning (_("Could not load XML target description; ignoring"));
520 return NULL;
521 }
23181151 522
fc6e0168
DJ
523 /* Check for an exact match in the list of descriptions we have
524 previously parsed. strcmp is a slightly inefficient way to
525 do this; an SHA-1 checksum would work as well. */
526 for (ix = 0; VEC_iterate (tdesc_xml_cache_s, xml_cache, ix, cache); ix++)
527 if (strcmp (cache->xml_document, expanded_text) == 0)
528 {
529 xfree (expanded_text);
530 return cache->tdesc;
531 }
532
533 back_to = make_cleanup (null_cleanup, NULL);
23181151 534
108546a0 535 memset (&data, 0, sizeof (struct tdesc_parsing_data));
23181151
DJ
536 data.tdesc = allocate_target_description ();
537 result_cleanup = make_cleanup_free_target_description (data.tdesc);
fc6e0168 538 make_cleanup (xfree, expanded_text);
23181151 539
efc0eabd
PA
540 if (gdb_xml_parse_quick (_("target description"), "gdb-target.dtd",
541 tdesc_elements, expanded_text, &data) == 0)
23181151
DJ
542 {
543 /* Parsed successfully. */
fc6e0168
DJ
544 struct tdesc_xml_cache new_cache;
545
546 new_cache.xml_document = expanded_text;
547 new_cache.tdesc = data.tdesc;
548 VEC_safe_push (tdesc_xml_cache_s, xml_cache, &new_cache);
23181151
DJ
549 discard_cleanups (result_cleanup);
550 do_cleanups (back_to);
551 return data.tdesc;
552 }
553 else
554 {
555 warning (_("Could not load XML target description; ignoring"));
556 do_cleanups (back_to);
557 return NULL;
558 }
559}
23181151
DJ
560#endif /* HAVE_LIBEXPAT */
561\f
562
23181151
DJ
563/* Read an XML target description from FILENAME. Parse it, and return
564 the parsed description. */
565
566const struct target_desc *
567file_read_description_xml (const char *filename)
568{
569 struct target_desc *tdesc;
570 char *tdesc_str;
571 struct cleanup *back_to;
108546a0 572 char *dirname;
23181151 573
a96d9b2e 574 tdesc_str = xml_fetch_content_from_file (filename, NULL);
23181151 575 if (tdesc_str == NULL)
108546a0
DJ
576 {
577 warning (_("Could not open \"%s\""), filename);
578 return NULL;
579 }
23181151
DJ
580
581 back_to = make_cleanup (xfree, tdesc_str);
108546a0 582
e1024ff1
DJ
583 dirname = ldirname (filename);
584 if (dirname != NULL)
585 make_cleanup (xfree, dirname);
108546a0 586
a96d9b2e 587 tdesc = tdesc_parse_xml (tdesc_str, xml_fetch_content_from_file, dirname);
23181151
DJ
588 do_cleanups (back_to);
589
590 return tdesc;
591}
592
108546a0
DJ
593/* Read a string representation of available features from the target,
594 using TARGET_OBJECT_AVAILABLE_FEATURES. The returned string is
595 malloc allocated and NUL-terminated. NAME should be a non-NULL
596 string identifying the XML document we want; the top level document
597 is "target.xml". Other calls may be performed for the DTD or
598 for <xi:include>. */
599
600static char *
601fetch_available_features_from_target (const char *name, void *baton_)
602{
603 struct target_ops *ops = baton_;
604
605 /* Read this object as a string. This ensures that a NUL
606 terminator is added. */
607 return target_read_stralloc (ops,
608 TARGET_OBJECT_AVAILABLE_FEATURES,
609 name);
610}
611\f
612
23181151
DJ
613/* Read an XML target description using OPS. Parse it, and return the
614 parsed description. */
615
616const struct target_desc *
617target_read_description_xml (struct target_ops *ops)
618{
619 struct target_desc *tdesc;
620 char *tdesc_str;
621 struct cleanup *back_to;
622
108546a0 623 tdesc_str = fetch_available_features_from_target ("target.xml", ops);
23181151
DJ
624 if (tdesc_str == NULL)
625 return NULL;
626
627 back_to = make_cleanup (xfree, tdesc_str);
108546a0
DJ
628 tdesc = tdesc_parse_xml (tdesc_str,
629 fetch_available_features_from_target,
630 ops);
23181151
DJ
631 do_cleanups (back_to);
632
633 return tdesc;
634}