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