daily update
[deliverable/binutils-gdb.git] / gdb / xml-tdesc.c
CommitLineData
23181151
DJ
1/* XML target description support for GDB.
2
9b254dd1 3 Copyright (C) 2006, 2008 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"
123dc839 23#include "gdbtypes.h"
23181151
DJ
24#include "target.h"
25#include "target-descriptions.h"
26#include "xml-support.h"
27#include "xml-tdesc.h"
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
88 /* The union we are currently parsing, or last parsed. */
89 struct type *current_union;
23181151
DJ
90};
91
92/* Handle the end of an <architecture> element and its value. */
93
94static void
95tdesc_end_arch (struct gdb_xml_parser *parser,
96 const struct gdb_xml_element *element,
97 void *user_data, const char *body_text)
98{
99 struct tdesc_parsing_data *data = user_data;
100 const struct bfd_arch_info *arch;
101
102 arch = bfd_scan_arch (body_text);
103 if (arch == NULL)
104 gdb_xml_error (parser, _("Target description specified unknown "
105 "architecture \"%s\""), body_text);
106 set_tdesc_architecture (data->tdesc, arch);
107}
108
1780a0ed
DJ
109/* Handle the start of a <target> element. */
110
111static void
112tdesc_start_target (struct gdb_xml_parser *parser,
113 const struct gdb_xml_element *element,
114 void *user_data, VEC(gdb_xml_value_s) *attributes)
115{
116 struct tdesc_parsing_data *data = user_data;
117 char *version = VEC_index (gdb_xml_value_s, attributes, 0)->value;
118
119 if (strcmp (version, "1.0") != 0)
120 gdb_xml_error (parser,
121 _("Target description has unsupported version \"%s\""),
122 version);
123}
124
123dc839
DJ
125/* Handle the start of a <feature> element. */
126
127static void
128tdesc_start_feature (struct gdb_xml_parser *parser,
129 const struct gdb_xml_element *element,
130 void *user_data, VEC(gdb_xml_value_s) *attributes)
131{
132 struct tdesc_parsing_data *data = user_data;
133 char *name = VEC_index (gdb_xml_value_s, attributes, 0)->value;
134
135 data->current_feature = tdesc_create_feature (data->tdesc, name);
136}
137
138/* Handle the start of a <reg> element. Fill in the optional
139 attributes and attach it to the containing feature. */
140
141static void
142tdesc_start_reg (struct gdb_xml_parser *parser,
143 const struct gdb_xml_element *element,
144 void *user_data, VEC(gdb_xml_value_s) *attributes)
145{
146 struct tdesc_parsing_data *data = user_data;
147 struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
148 int ix = 0, length;
149 char *name, *group, *type;
150 int bitsize, regnum, save_restore;
151
152 length = VEC_length (gdb_xml_value_s, attributes);
153
154 name = attrs[ix++].value;
155 bitsize = * (ULONGEST *) attrs[ix++].value;
156
157 if (ix < length && strcmp (attrs[ix].name, "regnum") == 0)
158 regnum = * (ULONGEST *) attrs[ix++].value;
159 else
160 regnum = data->next_regnum;
161
162 if (ix < length && strcmp (attrs[ix].name, "type") == 0)
163 type = attrs[ix++].value;
164 else
165 type = "int";
166
167 if (ix < length && strcmp (attrs[ix].name, "group") == 0)
168 group = attrs[ix++].value;
169 else
170 group = NULL;
171
172 if (ix < length && strcmp (attrs[ix].name, "save-restore") == 0)
173 save_restore = * (ULONGEST *) attrs[ix++].value;
174 else
175 save_restore = 1;
176
177 if (strcmp (type, "int") != 0
178 && strcmp (type, "float") != 0
d9cc5895
DJ
179 && strcmp (type, "code_ptr") != 0
180 && strcmp (type, "data_ptr") != 0
123dc839
DJ
181 && tdesc_named_type (data->current_feature, type) == NULL)
182 gdb_xml_error (parser, _("Register \"%s\" has unknown type \"%s\""),
183 name, type);
184
185 tdesc_create_reg (data->current_feature, name, regnum, save_restore, group,
186 bitsize, type);
187
188 data->next_regnum = regnum + 1;
189}
190
191/* Handle the start of a <union> element. Initialize the type and
192 record it with the current feature. */
193
194static void
195tdesc_start_union (struct gdb_xml_parser *parser,
196 const struct gdb_xml_element *element,
197 void *user_data, VEC(gdb_xml_value_s) *attributes)
198{
199 struct tdesc_parsing_data *data = user_data;
200 char *id = VEC_index (gdb_xml_value_s, attributes, 0)->value;
201 struct type *type;
202
203 type = init_composite_type (NULL, TYPE_CODE_UNION);
204 TYPE_NAME (type) = xstrdup (id);
205 tdesc_record_type (data->current_feature, type);
206 data->current_union = type;
207}
208
209/* Handle the end of a <union> element. */
210
211static void
212tdesc_end_union (struct gdb_xml_parser *parser,
213 const struct gdb_xml_element *element,
214 void *user_data, const char *body_text)
215{
216 struct tdesc_parsing_data *data = user_data;
217 int i;
218
219 /* If any of the children of this union are vectors, flag the union
220 as a vector also. This allows e.g. a union of two vector types
221 to show up automatically in "info vector". */
222 for (i = 0; i < TYPE_NFIELDS (data->current_union); i++)
223 if (TYPE_VECTOR (TYPE_FIELD_TYPE (data->current_union, i)))
224 {
876cecd0 225 TYPE_VECTOR (data->current_union) = 1;
123dc839
DJ
226 break;
227 }
228}
229
230/* Handle the start of a <field> element. Attach the field to the
231 current union. */
232
233static void
234tdesc_start_field (struct gdb_xml_parser *parser,
235 const struct gdb_xml_element *element,
236 void *user_data, VEC(gdb_xml_value_s) *attributes)
237{
238 struct tdesc_parsing_data *data = user_data;
239 struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
240 struct type *type, *field_type;
241 char *field_name, *field_type_id;
242
243 field_name = attrs[0].value;
244 field_type_id = attrs[1].value;
245
246 field_type = tdesc_named_type (data->current_feature, field_type_id);
247 if (field_type == NULL)
248 gdb_xml_error (parser, _("Union field \"%s\" references undefined "
249 "type \"%s\""),
250 field_name, field_type_id);
251
252 append_composite_type_field (data->current_union, xstrdup (field_name),
253 field_type);
254}
255
256/* Handle the start of a <vector> element. Initialize the type and
257 record it with the current feature. */
258
259static void
260tdesc_start_vector (struct gdb_xml_parser *parser,
261 const struct gdb_xml_element *element,
262 void *user_data, VEC(gdb_xml_value_s) *attributes)
263{
264 struct tdesc_parsing_data *data = user_data;
265 struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
266 struct type *type, *field_type, *range_type;
267 char *id, *field_type_id;
268 int count;
269
270 id = attrs[0].value;
271 field_type_id = attrs[1].value;
272 count = * (ULONGEST *) attrs[2].value;
273
274 field_type = tdesc_named_type (data->current_feature, field_type_id);
275 if (field_type == NULL)
276 gdb_xml_error (parser, _("Vector \"%s\" references undefined type \"%s\""),
277 id, field_type_id);
278
ea37ba09 279 type = init_vector_type (field_type, count);
123dc839
DJ
280 TYPE_NAME (type) = xstrdup (id);
281
123dc839
DJ
282 tdesc_record_type (data->current_feature, type);
283}
284
23181151
DJ
285/* The elements and attributes of an XML target description. */
286
123dc839
DJ
287static const struct gdb_xml_attribute field_attributes[] = {
288 { "name", GDB_XML_AF_NONE, NULL, NULL },
289 { "type", GDB_XML_AF_NONE, NULL, NULL },
290 { NULL, GDB_XML_AF_NONE, NULL, NULL }
291};
292
293static const struct gdb_xml_element union_children[] = {
294 { "field", field_attributes, NULL, GDB_XML_EF_REPEATABLE,
295 tdesc_start_field, NULL },
296 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
297};
298
299static const struct gdb_xml_attribute reg_attributes[] = {
300 { "name", GDB_XML_AF_NONE, NULL, NULL },
301 { "bitsize", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
302 { "regnum", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
303 { "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
304 { "group", GDB_XML_AF_OPTIONAL, NULL, NULL },
305 { "save-restore", GDB_XML_AF_OPTIONAL,
306 gdb_xml_parse_attr_enum, gdb_xml_enums_boolean },
307 { NULL, GDB_XML_AF_NONE, NULL, NULL }
308};
309
310static const struct gdb_xml_attribute union_attributes[] = {
311 { "id", GDB_XML_AF_NONE, NULL, NULL },
312 { NULL, GDB_XML_AF_NONE, NULL, NULL }
313};
314
315static const struct gdb_xml_attribute vector_attributes[] = {
316 { "id", GDB_XML_AF_NONE, NULL, NULL },
317 { "type", GDB_XML_AF_NONE, NULL, NULL },
318 { "count", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
319 { NULL, GDB_XML_AF_NONE, NULL, NULL }
320};
321
322static const struct gdb_xml_attribute feature_attributes[] = {
323 { "name", GDB_XML_AF_NONE, NULL, NULL },
324 { NULL, GDB_XML_AF_NONE, NULL, NULL }
325};
326
327static const struct gdb_xml_element feature_children[] = {
328 { "reg", reg_attributes, NULL,
329 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
330 tdesc_start_reg, NULL },
331 { "union", union_attributes, union_children,
332 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
333 tdesc_start_union, tdesc_end_union },
334 { "vector", vector_attributes, NULL,
335 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
336 tdesc_start_vector, NULL },
337 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
338};
339
1780a0ed
DJ
340static const struct gdb_xml_attribute target_attributes[] = {
341 { "version", GDB_XML_AF_NONE, NULL, NULL },
342 { NULL, GDB_XML_AF_NONE, NULL, NULL }
343};
344
123dc839 345static const struct gdb_xml_element target_children[] = {
23181151
DJ
346 { "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
347 NULL, tdesc_end_arch },
123dc839
DJ
348 { "feature", feature_attributes, feature_children,
349 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
350 tdesc_start_feature, NULL },
23181151
DJ
351 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
352};
353
123dc839 354static const struct gdb_xml_element tdesc_elements[] = {
1780a0ed
DJ
355 { "target", target_attributes, target_children, GDB_XML_EF_NONE,
356 tdesc_start_target, NULL },
23181151
DJ
357 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
358};
359
360/* Parse DOCUMENT into a target description and return it. */
361
362static struct target_desc *
108546a0
DJ
363tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
364 void *fetcher_baton)
23181151
DJ
365{
366 struct cleanup *back_to, *result_cleanup;
367 struct gdb_xml_parser *parser;
368 struct tdesc_parsing_data data;
fc6e0168 369 struct tdesc_xml_cache *cache;
108546a0 370 char *expanded_text;
fc6e0168 371 int ix;
23181151 372
108546a0
DJ
373 /* Expand all XInclude directives. */
374 expanded_text = xml_process_xincludes (_("target description"),
375 document, fetcher, fetcher_baton, 0);
376 if (expanded_text == NULL)
377 {
378 warning (_("Could not load XML target description; ignoring"));
379 return NULL;
380 }
23181151 381
fc6e0168
DJ
382 /* Check for an exact match in the list of descriptions we have
383 previously parsed. strcmp is a slightly inefficient way to
384 do this; an SHA-1 checksum would work as well. */
385 for (ix = 0; VEC_iterate (tdesc_xml_cache_s, xml_cache, ix, cache); ix++)
386 if (strcmp (cache->xml_document, expanded_text) == 0)
387 {
388 xfree (expanded_text);
389 return cache->tdesc;
390 }
391
392 back_to = make_cleanup (null_cleanup, NULL);
23181151
DJ
393 parser = gdb_xml_create_parser_and_cleanup (_("target description"),
394 tdesc_elements, &data);
108546a0 395 gdb_xml_use_dtd (parser, "gdb-target.dtd");
23181151 396
108546a0 397 memset (&data, 0, sizeof (struct tdesc_parsing_data));
23181151
DJ
398 data.tdesc = allocate_target_description ();
399 result_cleanup = make_cleanup_free_target_description (data.tdesc);
fc6e0168 400 make_cleanup (xfree, expanded_text);
23181151 401
108546a0 402 if (gdb_xml_parse (parser, expanded_text) == 0)
23181151
DJ
403 {
404 /* Parsed successfully. */
fc6e0168
DJ
405 struct tdesc_xml_cache new_cache;
406
407 new_cache.xml_document = expanded_text;
408 new_cache.tdesc = data.tdesc;
409 VEC_safe_push (tdesc_xml_cache_s, xml_cache, &new_cache);
23181151
DJ
410 discard_cleanups (result_cleanup);
411 do_cleanups (back_to);
412 return data.tdesc;
413 }
414 else
415 {
416 warning (_("Could not load XML target description; ignoring"));
417 do_cleanups (back_to);
418 return NULL;
419 }
420}
23181151
DJ
421#endif /* HAVE_LIBEXPAT */
422\f
423
424/* Close FILE. */
425
426static void
427do_cleanup_fclose (void *file)
428{
429 fclose (file);
430}
431
432/* Open FILENAME, read all its text into memory, close it, and return
433 the text. If something goes wrong, return NULL and warn. */
434
435static char *
108546a0 436fetch_xml_from_file (const char *filename, void *baton)
23181151 437{
108546a0 438 const char *dirname = baton;
23181151
DJ
439 FILE *file;
440 struct cleanup *back_to;
441 char *text;
442 size_t len, offset;
443
108546a0 444 if (dirname && *dirname)
23181151 445 {
6eb7ee03 446 char *fullname = concat (dirname, "/", filename, (char *) NULL);
108546a0
DJ
447 if (fullname == NULL)
448 nomem (0);
449 file = fopen (fullname, FOPEN_RT);
450 xfree (fullname);
23181151 451 }
108546a0
DJ
452 else
453 file = fopen (filename, FOPEN_RT);
454
455 if (file == NULL)
456 return NULL;
457
23181151
DJ
458 back_to = make_cleanup (do_cleanup_fclose, file);
459
460 /* Read in the whole file, one chunk at a time. */
461 len = 4096;
462 offset = 0;
463 text = xmalloc (len);
464 make_cleanup (free_current_contents, &text);
465 while (1)
466 {
467 size_t bytes_read;
468
469 /* Continue reading where the last read left off. Leave at least
470 one byte so that we can NUL-terminate the result. */
471 bytes_read = fread (text + offset, 1, len - offset - 1, file);
472 if (ferror (file))
473 {
474 warning (_("Read error from \"%s\""), filename);
475 do_cleanups (back_to);
476 return NULL;
477 }
478
479 offset += bytes_read;
480
481 if (feof (file))
482 break;
483
484 len = len * 2;
485 text = xrealloc (text, len);
486 }
487
488 fclose (file);
489 discard_cleanups (back_to);
490
491 text[offset] = '\0';
492 return text;
493}
494
495/* Read an XML target description from FILENAME. Parse it, and return
496 the parsed description. */
497
498const struct target_desc *
499file_read_description_xml (const char *filename)
500{
501 struct target_desc *tdesc;
502 char *tdesc_str;
503 struct cleanup *back_to;
108546a0 504 char *dirname;
23181151 505
108546a0 506 tdesc_str = fetch_xml_from_file (filename, NULL);
23181151 507 if (tdesc_str == NULL)
108546a0
DJ
508 {
509 warning (_("Could not open \"%s\""), filename);
510 return NULL;
511 }
23181151
DJ
512
513 back_to = make_cleanup (xfree, tdesc_str);
108546a0 514
e1024ff1
DJ
515 dirname = ldirname (filename);
516 if (dirname != NULL)
517 make_cleanup (xfree, dirname);
108546a0
DJ
518
519 tdesc = tdesc_parse_xml (tdesc_str, fetch_xml_from_file, dirname);
23181151
DJ
520 do_cleanups (back_to);
521
522 return tdesc;
523}
524
108546a0
DJ
525/* Read a string representation of available features from the target,
526 using TARGET_OBJECT_AVAILABLE_FEATURES. The returned string is
527 malloc allocated and NUL-terminated. NAME should be a non-NULL
528 string identifying the XML document we want; the top level document
529 is "target.xml". Other calls may be performed for the DTD or
530 for <xi:include>. */
531
532static char *
533fetch_available_features_from_target (const char *name, void *baton_)
534{
535 struct target_ops *ops = baton_;
536
537 /* Read this object as a string. This ensures that a NUL
538 terminator is added. */
539 return target_read_stralloc (ops,
540 TARGET_OBJECT_AVAILABLE_FEATURES,
541 name);
542}
543\f
544
23181151
DJ
545/* Read an XML target description using OPS. Parse it, and return the
546 parsed description. */
547
548const struct target_desc *
549target_read_description_xml (struct target_ops *ops)
550{
551 struct target_desc *tdesc;
552 char *tdesc_str;
553 struct cleanup *back_to;
554
108546a0 555 tdesc_str = fetch_available_features_from_target ("target.xml", ops);
23181151
DJ
556 if (tdesc_str == NULL)
557 return NULL;
558
559 back_to = make_cleanup (xfree, tdesc_str);
108546a0
DJ
560 tdesc = tdesc_parse_xml (tdesc_str,
561 fetch_available_features_from_target,
562 ops);
23181151
DJ
563 do_cleanups (back_to);
564
565 return tdesc;
566}
This page took 0.239797 seconds and 4 git commands to generate.