]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/xml-tdesc.c
Updated copyright notices for most files.
[thirdparty/binutils-gdb.git] / gdb / xml-tdesc.c
CommitLineData
23181151
DJ
1/* XML target description support for GDB.
2
0fb0cc75 3 Copyright (C) 2006, 2008, 2009 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
23181151
DJ
424/* Open FILENAME, read all its text into memory, close it, and return
425 the text. If something goes wrong, return NULL and warn. */
426
427static char *
108546a0 428fetch_xml_from_file (const char *filename, void *baton)
23181151 429{
108546a0 430 const char *dirname = baton;
23181151
DJ
431 FILE *file;
432 struct cleanup *back_to;
433 char *text;
434 size_t len, offset;
435
108546a0 436 if (dirname && *dirname)
23181151 437 {
6eb7ee03 438 char *fullname = concat (dirname, "/", filename, (char *) NULL);
108546a0
DJ
439 if (fullname == NULL)
440 nomem (0);
441 file = fopen (fullname, FOPEN_RT);
442 xfree (fullname);
23181151 443 }
108546a0
DJ
444 else
445 file = fopen (filename, FOPEN_RT);
446
447 if (file == NULL)
448 return NULL;
449
7c8a8b04 450 back_to = make_cleanup_fclose (file);
23181151
DJ
451
452 /* Read in the whole file, one chunk at a time. */
453 len = 4096;
454 offset = 0;
455 text = xmalloc (len);
456 make_cleanup (free_current_contents, &text);
457 while (1)
458 {
459 size_t bytes_read;
460
461 /* Continue reading where the last read left off. Leave at least
462 one byte so that we can NUL-terminate the result. */
463 bytes_read = fread (text + offset, 1, len - offset - 1, file);
464 if (ferror (file))
465 {
466 warning (_("Read error from \"%s\""), filename);
467 do_cleanups (back_to);
468 return NULL;
469 }
470
471 offset += bytes_read;
472
473 if (feof (file))
474 break;
475
476 len = len * 2;
477 text = xrealloc (text, len);
478 }
479
480 fclose (file);
481 discard_cleanups (back_to);
482
483 text[offset] = '\0';
484 return text;
485}
486
487/* Read an XML target description from FILENAME. Parse it, and return
488 the parsed description. */
489
490const struct target_desc *
491file_read_description_xml (const char *filename)
492{
493 struct target_desc *tdesc;
494 char *tdesc_str;
495 struct cleanup *back_to;
108546a0 496 char *dirname;
23181151 497
108546a0 498 tdesc_str = fetch_xml_from_file (filename, NULL);
23181151 499 if (tdesc_str == NULL)
108546a0
DJ
500 {
501 warning (_("Could not open \"%s\""), filename);
502 return NULL;
503 }
23181151
DJ
504
505 back_to = make_cleanup (xfree, tdesc_str);
108546a0 506
e1024ff1
DJ
507 dirname = ldirname (filename);
508 if (dirname != NULL)
509 make_cleanup (xfree, dirname);
108546a0
DJ
510
511 tdesc = tdesc_parse_xml (tdesc_str, fetch_xml_from_file, dirname);
23181151
DJ
512 do_cleanups (back_to);
513
514 return tdesc;
515}
516
108546a0
DJ
517/* Read a string representation of available features from the target,
518 using TARGET_OBJECT_AVAILABLE_FEATURES. The returned string is
519 malloc allocated and NUL-terminated. NAME should be a non-NULL
520 string identifying the XML document we want; the top level document
521 is "target.xml". Other calls may be performed for the DTD or
522 for <xi:include>. */
523
524static char *
525fetch_available_features_from_target (const char *name, void *baton_)
526{
527 struct target_ops *ops = baton_;
528
529 /* Read this object as a string. This ensures that a NUL
530 terminator is added. */
531 return target_read_stralloc (ops,
532 TARGET_OBJECT_AVAILABLE_FEATURES,
533 name);
534}
535\f
536
23181151
DJ
537/* Read an XML target description using OPS. Parse it, and return the
538 parsed description. */
539
540const struct target_desc *
541target_read_description_xml (struct target_ops *ops)
542{
543 struct target_desc *tdesc;
544 char *tdesc_str;
545 struct cleanup *back_to;
546
108546a0 547 tdesc_str = fetch_available_features_from_target ("target.xml", ops);
23181151
DJ
548 if (tdesc_str == NULL)
549 return NULL;
550
551 back_to = make_cleanup (xfree, tdesc_str);
108546a0
DJ
552 tdesc = tdesc_parse_xml (tdesc_str,
553 fetch_available_features_from_target,
554 ops);
23181151
DJ
555 do_cleanups (back_to);
556
557 return tdesc;
558}