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