1 /* Functions that provide the mechanism to parse a syscall XML file
4 Copyright (C) 2009-2017 Free Software Foundation, Inc.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include "xml-support.h"
24 #include "xml-syscall.h"
27 /* For the struct syscall definition. */
30 #include "filenames.h"
34 /* Dummy functions to indicate that there's no support for fetching
35 syscalls information. */
38 syscall_warn_user (void)
40 static int have_warned
= 0;
44 warning (_("Can not parse XML syscalls information; XML support was "
45 "disabled at compile time."));
50 set_xml_syscall_file_name (struct gdbarch
*gdbarch
, const char *name
)
56 get_syscall_by_number (struct gdbarch
*gdbarch
,
57 int syscall_number
, struct syscall
*s
)
60 s
->number
= syscall_number
;
65 get_syscall_by_name (struct gdbarch
*gdbarch
, const char *syscall_name
,
69 s
->number
= UNKNOWN_SYSCALL
;
70 s
->name
= syscall_name
;
74 get_syscall_names (struct gdbarch
*gdbarch
)
81 get_syscalls_by_group (struct gdbarch
*gdbarch
, const char *group
)
88 get_syscall_group_names (struct gdbarch
*gdbarch
)
94 #else /* ! HAVE_LIBEXPAT */
96 /* Structure which describes a syscall. */
97 typedef struct syscall_desc
99 /* The syscall number. */
103 /* The syscall name. */
107 DEF_VEC_P(syscall_desc_p
);
109 /* Structure of a syscall group. */
110 typedef struct syscall_group_desc
112 /* The group name. */
116 /* The syscalls that are part of the group. */
118 VEC(syscall_desc_p
) *syscalls
;
119 } *syscall_group_desc_p
;
120 DEF_VEC_P(syscall_group_desc_p
);
122 /* Structure that represents syscalls information. */
127 VEC(syscall_desc_p
) *syscalls
;
129 /* The syscall groups. */
131 VEC(syscall_group_desc_p
) *groups
;
133 /* Variable that will hold the last known data-directory. This is
134 useful to know whether we should re-read the XML info for the
137 char *my_gdb_datadir
;
140 /* Callback data for syscall information parsing. */
141 struct syscall_parsing_data
143 /* The syscalls_info we are building. */
145 struct syscalls_info
*syscalls_info
;
148 static struct syscalls_info
*
149 allocate_syscalls_info (void)
151 return XCNEW (struct syscalls_info
);
155 syscalls_info_free_syscalls_desc (struct syscall_desc
*sd
)
160 /* Free syscall_group_desc members but not the structure itself. */
163 syscalls_info_free_syscall_group_desc (struct syscall_group_desc
*sd
)
165 VEC_free (syscall_desc_p
, sd
->syscalls
);
170 free_syscalls_info (void *arg
)
172 struct syscalls_info
*syscalls_info
= (struct syscalls_info
*) arg
;
173 struct syscall_desc
*sysdesc
;
174 struct syscall_group_desc
*groupdesc
;
177 xfree (syscalls_info
->my_gdb_datadir
);
179 if (syscalls_info
->syscalls
!= NULL
)
182 VEC_iterate (syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
184 syscalls_info_free_syscalls_desc (sysdesc
);
185 VEC_free (syscall_desc_p
, syscalls_info
->syscalls
);
188 if (syscalls_info
->groups
!= NULL
)
191 VEC_iterate (syscall_group_desc_p
,
192 syscalls_info
->groups
, i
, groupdesc
);
194 syscalls_info_free_syscall_group_desc (groupdesc
);
196 VEC_free (syscall_group_desc_p
, syscalls_info
->groups
);
199 xfree (syscalls_info
);
202 static struct cleanup
*
203 make_cleanup_free_syscalls_info (struct syscalls_info
*syscalls_info
)
205 return make_cleanup (free_syscalls_info
, syscalls_info
);
208 /* Create a new syscall group. Return pointer to the
209 syscall_group_desc structure that represents the new group. */
211 static struct syscall_group_desc
*
212 syscall_group_create_syscall_group_desc (struct syscalls_info
*syscalls_info
,
215 struct syscall_group_desc
*groupdesc
= XCNEW (struct syscall_group_desc
);
217 groupdesc
->name
= xstrdup (group
);
219 VEC_safe_push (syscall_group_desc_p
, syscalls_info
->groups
, groupdesc
);
224 /* Add a syscall to the group. If group doesn't exist, create it. */
227 syscall_group_add_syscall (struct syscalls_info
*syscalls_info
,
228 struct syscall_desc
*syscall
,
231 struct syscall_group_desc
*groupdesc
= NULL
;
234 /* Search for an existing group. */
236 VEC_iterate (syscall_group_desc_p
, syscalls_info
->groups
, i
, groupdesc
);
239 if (strcmp (groupdesc
->name
, group
) == 0)
243 if (groupdesc
== NULL
)
245 /* No group was found with this name. We must create a new
247 groupdesc
= syscall_group_create_syscall_group_desc (syscalls_info
,
251 VEC_safe_push (syscall_desc_p
, groupdesc
->syscalls
, syscall
);
255 syscall_create_syscall_desc (struct syscalls_info
*syscalls_info
,
256 const char *name
, int number
,
259 struct syscall_desc
*sysdesc
= XCNEW (struct syscall_desc
);
262 sysdesc
->name
= xstrdup (name
);
263 sysdesc
->number
= number
;
265 VEC_safe_push (syscall_desc_p
, syscalls_info
->syscalls
, sysdesc
);
267 /* Add syscall to its groups. */
270 for (group
= strtok (groups
, ",");
272 group
= strtok (NULL
, ","))
273 syscall_group_add_syscall (syscalls_info
, sysdesc
, group
);
277 /* Handle the start of a <syscall> element. */
279 syscall_start_syscall (struct gdb_xml_parser
*parser
,
280 const struct gdb_xml_element
*element
,
281 void *user_data
, VEC(gdb_xml_value_s
) *attributes
)
283 struct syscall_parsing_data
*data
= (struct syscall_parsing_data
*) user_data
;
284 struct gdb_xml_value
*attrs
= VEC_address (gdb_xml_value_s
, attributes
);
291 len
= VEC_length (gdb_xml_value_s
, attributes
);
293 for (i
= 0; i
< len
; i
++)
295 if (strcmp (attrs
[i
].name
, "name") == 0)
296 name
= (char *) attrs
[i
].value
;
297 else if (strcmp (attrs
[i
].name
, "number") == 0)
298 number
= * (ULONGEST
*) attrs
[i
].value
;
299 else if (strcmp (attrs
[i
].name
, "groups") == 0)
300 groups
= (char *) attrs
[i
].value
;
302 internal_error (__FILE__
, __LINE__
,
303 _("Unknown attribute name '%s'."), attrs
[i
].name
);
307 syscall_create_syscall_desc (data
->syscalls_info
, name
, number
, groups
);
311 /* The elements and attributes of an XML syscall document. */
312 static const struct gdb_xml_attribute syscall_attr
[] = {
313 { "number", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
314 { "name", GDB_XML_AF_NONE
, NULL
, NULL
},
315 { "groups", GDB_XML_AF_OPTIONAL
, NULL
, NULL
},
316 { NULL
, GDB_XML_AF_NONE
, NULL
, NULL
}
319 static const struct gdb_xml_element syscalls_info_children
[] = {
320 { "syscall", syscall_attr
, NULL
,
321 GDB_XML_EF_OPTIONAL
| GDB_XML_EF_REPEATABLE
,
322 syscall_start_syscall
, NULL
},
323 { NULL
, NULL
, NULL
, GDB_XML_EF_NONE
, NULL
, NULL
}
326 static const struct gdb_xml_element syselements
[] = {
327 { "syscalls_info", NULL
, syscalls_info_children
,
328 GDB_XML_EF_NONE
, NULL
, NULL
},
329 { NULL
, NULL
, NULL
, GDB_XML_EF_NONE
, NULL
, NULL
}
332 static struct syscalls_info
*
333 syscall_parse_xml (const char *document
, xml_fetch_another fetcher
,
336 struct cleanup
*result_cleanup
;
337 struct syscall_parsing_data data
;
339 data
.syscalls_info
= allocate_syscalls_info ();
340 result_cleanup
= make_cleanup_free_syscalls_info (data
.syscalls_info
);
342 if (gdb_xml_parse_quick (_("syscalls info"), NULL
,
343 syselements
, document
, &data
) == 0)
345 /* Parsed successfully. */
346 discard_cleanups (result_cleanup
);
347 return data
.syscalls_info
;
351 warning (_("Could not load XML syscalls info; ignoring"));
352 do_cleanups (result_cleanup
);
357 /* Function responsible for initializing the information
358 about the syscalls. It reads the XML file and fills the
359 struct syscalls_info with the values.
361 Returns the struct syscalls_info if the file is valid, NULL otherwise. */
362 static struct syscalls_info
*
363 xml_init_syscalls_info (const char *filename
)
367 struct syscalls_info
*syscalls_info
;
368 struct cleanup
*back_to
;
370 full_file
= xml_fetch_content_from_file (filename
, gdb_datadir
);
371 if (full_file
== NULL
)
374 back_to
= make_cleanup (xfree
, full_file
);
376 dirname
= ldirname (filename
);
378 make_cleanup (xfree
, dirname
);
380 syscalls_info
= syscall_parse_xml (full_file
,
381 xml_fetch_content_from_file
, dirname
);
382 do_cleanups (back_to
);
384 return syscalls_info
;
387 /* Initializes the syscalls_info structure according to the
390 init_syscalls_info (struct gdbarch
*gdbarch
)
392 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
393 const char *xml_syscall_file
= gdbarch_xml_syscall_file (gdbarch
);
395 /* Should we re-read the XML info for this target? */
396 if (syscalls_info
!= NULL
&& syscalls_info
->my_gdb_datadir
!= NULL
397 && filename_cmp (syscalls_info
->my_gdb_datadir
, gdb_datadir
) != 0)
399 /* The data-directory changed from the last time we used it.
400 It means that we have to re-read the XML info. */
401 free_syscalls_info (syscalls_info
);
402 syscalls_info
= NULL
;
403 set_gdbarch_syscalls_info (gdbarch
, NULL
);
406 /* Did we succeed at initializing this? */
407 if (syscalls_info
!= NULL
)
410 syscalls_info
= xml_init_syscalls_info (xml_syscall_file
);
412 /* If there was some error reading the XML file, we initialize
413 gdbarch->syscalls_info anyway, in order to store information
414 about our attempt. */
415 if (syscalls_info
== NULL
)
416 syscalls_info
= allocate_syscalls_info ();
418 if (syscalls_info
->syscalls
== NULL
)
420 if (xml_syscall_file
!= NULL
)
421 warning (_("Could not load the syscall XML file `%s/%s'."),
422 gdb_datadir
, xml_syscall_file
);
424 warning (_("There is no XML file to open."));
426 warning (_("GDB will not be able to display "
427 "syscall names nor to verify if\n"
428 "any provided syscall numbers are valid."));
431 /* Saving the data-directory used to read this XML info. */
432 syscalls_info
->my_gdb_datadir
= xstrdup (gdb_datadir
);
434 set_gdbarch_syscalls_info (gdbarch
, syscalls_info
);
437 /* Search for a syscall group by its name. Return syscall_group_desc
438 structure for the group if found or NULL otherwise. */
440 static struct syscall_group_desc
*
441 syscall_group_get_group_by_name (const struct syscalls_info
*syscalls_info
,
444 struct syscall_group_desc
*groupdesc
;
447 if (syscalls_info
== NULL
)
453 /* Search for existing group. */
455 VEC_iterate (syscall_group_desc_p
, syscalls_info
->groups
, i
, groupdesc
);
458 if (strcmp (groupdesc
->name
, group
) == 0)
466 xml_get_syscall_number (struct gdbarch
*gdbarch
,
467 const char *syscall_name
)
469 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
470 struct syscall_desc
*sysdesc
;
473 if (syscalls_info
== NULL
474 || syscall_name
== NULL
)
475 return UNKNOWN_SYSCALL
;
478 VEC_iterate(syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
480 if (strcmp (sysdesc
->name
, syscall_name
) == 0)
481 return sysdesc
->number
;
483 return UNKNOWN_SYSCALL
;
487 xml_get_syscall_name (struct gdbarch
*gdbarch
,
490 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
491 struct syscall_desc
*sysdesc
;
494 if (syscalls_info
== NULL
495 || syscall_number
< 0)
499 VEC_iterate(syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
501 if (sysdesc
->number
== syscall_number
)
502 return sysdesc
->name
;
508 xml_list_of_syscalls (struct gdbarch
*gdbarch
)
510 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
511 struct syscall_desc
*sysdesc
;
512 const char **names
= NULL
;
516 if (syscalls_info
== NULL
)
519 nsyscalls
= VEC_length (syscall_desc_p
, syscalls_info
->syscalls
);
520 names
= XNEWVEC (const char *, nsyscalls
+ 1);
523 VEC_iterate (syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
525 names
[i
] = sysdesc
->name
;
532 /* Iterate over the syscall_group_desc element to return a list of
533 syscalls that are part of the given group, terminated by an empty
534 element. If the syscall group doesn't exist, return NULL. */
536 static struct syscall
*
537 xml_list_syscalls_by_group (struct gdbarch
*gdbarch
, const char *group
)
539 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
540 struct syscall_group_desc
*groupdesc
;
541 struct syscall_desc
*sysdesc
;
542 struct syscall
*syscalls
= NULL
;
546 if (syscalls_info
== NULL
)
549 groupdesc
= syscall_group_get_group_by_name (syscalls_info
, group
);
550 if (groupdesc
== NULL
)
553 nsyscalls
= VEC_length (syscall_desc_p
, groupdesc
->syscalls
);
554 syscalls
= (struct syscall
*) xmalloc ((nsyscalls
+ 1)
555 * sizeof (struct syscall
));
558 VEC_iterate (syscall_desc_p
, groupdesc
->syscalls
, i
, sysdesc
);
561 syscalls
[i
].name
= sysdesc
->name
;
562 syscalls
[i
].number
= sysdesc
->number
;
565 /* Add final element marker. */
566 syscalls
[i
].name
= NULL
;
567 syscalls
[i
].number
= 0;
572 /* Return a NULL terminated list of syscall groups or an empty list, if
573 no syscall group is available. Return NULL, if there is no syscall
574 information available. */
577 xml_list_of_groups (struct gdbarch
*gdbarch
)
579 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
580 struct syscall_group_desc
*groupdesc
;
581 const char **names
= NULL
;
585 if (syscalls_info
== NULL
)
588 ngroups
= VEC_length (syscall_group_desc_p
, syscalls_info
->groups
);
589 names
= (const char**) xmalloc ((ngroups
+ 1) * sizeof (char *));
592 VEC_iterate (syscall_group_desc_p
, syscalls_info
->groups
, i
, groupdesc
);
594 names
[i
] = groupdesc
->name
;
602 set_xml_syscall_file_name (struct gdbarch
*gdbarch
, const char *name
)
604 set_gdbarch_xml_syscall_file (gdbarch
, name
);
608 get_syscall_by_number (struct gdbarch
*gdbarch
,
609 int syscall_number
, struct syscall
*s
)
611 init_syscalls_info (gdbarch
);
613 s
->number
= syscall_number
;
614 s
->name
= xml_get_syscall_name (gdbarch
, syscall_number
);
618 get_syscall_by_name (struct gdbarch
*gdbarch
,
619 const char *syscall_name
, struct syscall
*s
)
621 init_syscalls_info (gdbarch
);
623 s
->number
= xml_get_syscall_number (gdbarch
, syscall_name
);
624 s
->name
= syscall_name
;
628 get_syscall_names (struct gdbarch
*gdbarch
)
630 init_syscalls_info (gdbarch
);
632 return xml_list_of_syscalls (gdbarch
);
635 /* See comment in xml-syscall.h. */
638 get_syscalls_by_group (struct gdbarch
*gdbarch
, const char *group
)
640 init_syscalls_info (gdbarch
);
642 return xml_list_syscalls_by_group (gdbarch
, group
);
645 /* See comment in xml-syscall.h. */
648 get_syscall_group_names (struct gdbarch
*gdbarch
)
650 init_syscalls_info (gdbarch
);
652 return xml_list_of_groups (gdbarch
);
655 #endif /* ! HAVE_LIBEXPAT */