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
)
366 struct syscalls_info
*syscalls_info
;
367 struct cleanup
*back_to
;
369 full_file
= xml_fetch_content_from_file (filename
, gdb_datadir
);
370 if (full_file
== NULL
)
373 back_to
= make_cleanup (xfree
, full_file
);
375 syscalls_info
= syscall_parse_xml (full_file
,
376 xml_fetch_content_from_file
,
377 (void *) ldirname (filename
).c_str ());
378 do_cleanups (back_to
);
380 return syscalls_info
;
383 /* Initializes the syscalls_info structure according to the
386 init_syscalls_info (struct gdbarch
*gdbarch
)
388 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
389 const char *xml_syscall_file
= gdbarch_xml_syscall_file (gdbarch
);
391 /* Should we re-read the XML info for this target? */
392 if (syscalls_info
!= NULL
&& syscalls_info
->my_gdb_datadir
!= NULL
393 && filename_cmp (syscalls_info
->my_gdb_datadir
, gdb_datadir
) != 0)
395 /* The data-directory changed from the last time we used it.
396 It means that we have to re-read the XML info. */
397 free_syscalls_info (syscalls_info
);
398 syscalls_info
= NULL
;
399 set_gdbarch_syscalls_info (gdbarch
, NULL
);
402 /* Did we succeed at initializing this? */
403 if (syscalls_info
!= NULL
)
406 syscalls_info
= xml_init_syscalls_info (xml_syscall_file
);
408 /* If there was some error reading the XML file, we initialize
409 gdbarch->syscalls_info anyway, in order to store information
410 about our attempt. */
411 if (syscalls_info
== NULL
)
412 syscalls_info
= allocate_syscalls_info ();
414 if (syscalls_info
->syscalls
== NULL
)
416 if (xml_syscall_file
!= NULL
)
417 warning (_("Could not load the syscall XML file `%s/%s'."),
418 gdb_datadir
, xml_syscall_file
);
420 warning (_("There is no XML file to open."));
422 warning (_("GDB will not be able to display "
423 "syscall names nor to verify if\n"
424 "any provided syscall numbers are valid."));
427 /* Saving the data-directory used to read this XML info. */
428 syscalls_info
->my_gdb_datadir
= xstrdup (gdb_datadir
);
430 set_gdbarch_syscalls_info (gdbarch
, syscalls_info
);
433 /* Search for a syscall group by its name. Return syscall_group_desc
434 structure for the group if found or NULL otherwise. */
436 static struct syscall_group_desc
*
437 syscall_group_get_group_by_name (const struct syscalls_info
*syscalls_info
,
440 struct syscall_group_desc
*groupdesc
;
443 if (syscalls_info
== NULL
)
449 /* Search for existing group. */
451 VEC_iterate (syscall_group_desc_p
, syscalls_info
->groups
, i
, groupdesc
);
454 if (strcmp (groupdesc
->name
, group
) == 0)
462 xml_get_syscall_number (struct gdbarch
*gdbarch
,
463 const char *syscall_name
)
465 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
466 struct syscall_desc
*sysdesc
;
469 if (syscalls_info
== NULL
470 || syscall_name
== NULL
)
471 return UNKNOWN_SYSCALL
;
474 VEC_iterate(syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
476 if (strcmp (sysdesc
->name
, syscall_name
) == 0)
477 return sysdesc
->number
;
479 return UNKNOWN_SYSCALL
;
483 xml_get_syscall_name (struct gdbarch
*gdbarch
,
486 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
487 struct syscall_desc
*sysdesc
;
490 if (syscalls_info
== NULL
491 || syscall_number
< 0)
495 VEC_iterate(syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
497 if (sysdesc
->number
== syscall_number
)
498 return sysdesc
->name
;
504 xml_list_of_syscalls (struct gdbarch
*gdbarch
)
506 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
507 struct syscall_desc
*sysdesc
;
508 const char **names
= NULL
;
512 if (syscalls_info
== NULL
)
515 nsyscalls
= VEC_length (syscall_desc_p
, syscalls_info
->syscalls
);
516 names
= XNEWVEC (const char *, nsyscalls
+ 1);
519 VEC_iterate (syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
521 names
[i
] = sysdesc
->name
;
528 /* Iterate over the syscall_group_desc element to return a list of
529 syscalls that are part of the given group, terminated by an empty
530 element. If the syscall group doesn't exist, return NULL. */
532 static struct syscall
*
533 xml_list_syscalls_by_group (struct gdbarch
*gdbarch
, const char *group
)
535 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
536 struct syscall_group_desc
*groupdesc
;
537 struct syscall_desc
*sysdesc
;
538 struct syscall
*syscalls
= NULL
;
542 if (syscalls_info
== NULL
)
545 groupdesc
= syscall_group_get_group_by_name (syscalls_info
, group
);
546 if (groupdesc
== NULL
)
549 nsyscalls
= VEC_length (syscall_desc_p
, groupdesc
->syscalls
);
550 syscalls
= (struct syscall
*) xmalloc ((nsyscalls
+ 1)
551 * sizeof (struct syscall
));
554 VEC_iterate (syscall_desc_p
, groupdesc
->syscalls
, i
, sysdesc
);
557 syscalls
[i
].name
= sysdesc
->name
;
558 syscalls
[i
].number
= sysdesc
->number
;
561 /* Add final element marker. */
562 syscalls
[i
].name
= NULL
;
563 syscalls
[i
].number
= 0;
568 /* Return a NULL terminated list of syscall groups or an empty list, if
569 no syscall group is available. Return NULL, if there is no syscall
570 information available. */
573 xml_list_of_groups (struct gdbarch
*gdbarch
)
575 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
576 struct syscall_group_desc
*groupdesc
;
577 const char **names
= NULL
;
581 if (syscalls_info
== NULL
)
584 ngroups
= VEC_length (syscall_group_desc_p
, syscalls_info
->groups
);
585 names
= (const char**) xmalloc ((ngroups
+ 1) * sizeof (char *));
588 VEC_iterate (syscall_group_desc_p
, syscalls_info
->groups
, i
, groupdesc
);
590 names
[i
] = groupdesc
->name
;
598 set_xml_syscall_file_name (struct gdbarch
*gdbarch
, const char *name
)
600 set_gdbarch_xml_syscall_file (gdbarch
, name
);
604 get_syscall_by_number (struct gdbarch
*gdbarch
,
605 int syscall_number
, struct syscall
*s
)
607 init_syscalls_info (gdbarch
);
609 s
->number
= syscall_number
;
610 s
->name
= xml_get_syscall_name (gdbarch
, syscall_number
);
614 get_syscall_by_name (struct gdbarch
*gdbarch
,
615 const char *syscall_name
, struct syscall
*s
)
617 init_syscalls_info (gdbarch
);
619 s
->number
= xml_get_syscall_number (gdbarch
, syscall_name
);
620 s
->name
= syscall_name
;
624 get_syscall_names (struct gdbarch
*gdbarch
)
626 init_syscalls_info (gdbarch
);
628 return xml_list_of_syscalls (gdbarch
);
631 /* See comment in xml-syscall.h. */
634 get_syscalls_by_group (struct gdbarch
*gdbarch
, const char *group
)
636 init_syscalls_info (gdbarch
);
638 return xml_list_syscalls_by_group (gdbarch
, group
);
641 /* See comment in xml-syscall.h. */
644 get_syscall_group_names (struct gdbarch
*gdbarch
)
646 init_syscalls_info (gdbarch
);
648 return xml_list_of_groups (gdbarch
);
651 #endif /* ! HAVE_LIBEXPAT */