1 /* Functions that provide the mechanism to parse a syscall XML file
4 Copyright (C) 2009-2014 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 (const struct gdbarch
*gdbarch
,
57 get_syscall_by_number (const struct gdbarch
*gdbarch
,
58 int syscall_number
, struct syscall
*s
)
61 s
->number
= syscall_number
;
66 get_syscall_by_name (const struct gdbarch
*gdbarch
,
67 const char *syscall_name
, struct syscall
*s
)
70 s
->number
= UNKNOWN_SYSCALL
;
71 s
->name
= syscall_name
;
75 get_syscall_names (const struct gdbarch
*gdbarch
)
81 #else /* ! HAVE_LIBEXPAT */
83 /* Structure which describes a syscall. */
84 typedef struct syscall_desc
86 /* The syscall number. */
90 /* The syscall name. */
94 DEF_VEC_P(syscall_desc_p
);
96 /* Structure that represents syscalls information. */
101 VEC(syscall_desc_p
) *syscalls
;
103 /* Variable that will hold the last known data-directory. This is
104 useful to know whether we should re-read the XML info for the
107 char *my_gdb_datadir
;
110 /* Callback data for syscall information parsing. */
111 struct syscall_parsing_data
113 /* The syscalls_info we are building. */
115 struct syscalls_info
*syscalls_info
;
118 static struct syscalls_info
*
119 allocate_syscalls_info (void)
121 return XCNEW (struct syscalls_info
);
125 syscalls_info_free_syscalls_desc (struct syscall_desc
*sd
)
131 free_syscalls_info (void *arg
)
133 struct syscalls_info
*syscalls_info
= arg
;
134 struct syscall_desc
*sysdesc
;
137 xfree (syscalls_info
->my_gdb_datadir
);
139 if (syscalls_info
->syscalls
!= NULL
)
142 VEC_iterate (syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
144 syscalls_info_free_syscalls_desc (sysdesc
);
145 VEC_free (syscall_desc_p
, syscalls_info
->syscalls
);
148 xfree (syscalls_info
);
151 static struct cleanup
*
152 make_cleanup_free_syscalls_info (struct syscalls_info
*syscalls_info
)
154 return make_cleanup (free_syscalls_info
, syscalls_info
);
158 syscall_create_syscall_desc (struct syscalls_info
*syscalls_info
,
159 const char *name
, int number
)
161 struct syscall_desc
*sysdesc
= XCNEW (struct syscall_desc
);
163 sysdesc
->name
= xstrdup (name
);
164 sysdesc
->number
= number
;
166 VEC_safe_push (syscall_desc_p
, syscalls_info
->syscalls
, sysdesc
);
169 /* Handle the start of a <syscall> element. */
171 syscall_start_syscall (struct gdb_xml_parser
*parser
,
172 const struct gdb_xml_element
*element
,
173 void *user_data
, VEC(gdb_xml_value_s
) *attributes
)
175 struct syscall_parsing_data
*data
= user_data
;
176 struct gdb_xml_value
*attrs
= VEC_address (gdb_xml_value_s
, attributes
);
182 len
= VEC_length (gdb_xml_value_s
, attributes
);
184 for (i
= 0; i
< len
; i
++)
186 if (strcmp (attrs
[i
].name
, "name") == 0)
187 name
= attrs
[i
].value
;
188 else if (strcmp (attrs
[i
].name
, "number") == 0)
189 number
= * (ULONGEST
*) attrs
[i
].value
;
191 internal_error (__FILE__
, __LINE__
,
192 _("Unknown attribute name '%s'."), attrs
[i
].name
);
196 syscall_create_syscall_desc (data
->syscalls_info
, name
, number
);
200 /* The elements and attributes of an XML syscall document. */
201 static const struct gdb_xml_attribute syscall_attr
[] = {
202 { "number", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
203 { "name", GDB_XML_AF_NONE
, NULL
, NULL
},
204 { NULL
, GDB_XML_AF_NONE
, NULL
, NULL
}
207 static const struct gdb_xml_element syscalls_info_children
[] = {
208 { "syscall", syscall_attr
, NULL
,
209 GDB_XML_EF_OPTIONAL
| GDB_XML_EF_REPEATABLE
,
210 syscall_start_syscall
, NULL
},
211 { NULL
, NULL
, NULL
, GDB_XML_EF_NONE
, NULL
, NULL
}
214 static const struct gdb_xml_element syselements
[] = {
215 { "syscalls_info", NULL
, syscalls_info_children
,
216 GDB_XML_EF_NONE
, NULL
, NULL
},
217 { NULL
, NULL
, NULL
, GDB_XML_EF_NONE
, NULL
, NULL
}
220 static struct syscalls_info
*
221 syscall_parse_xml (const char *document
, xml_fetch_another fetcher
,
224 struct cleanup
*result_cleanup
;
225 struct syscall_parsing_data data
;
227 data
.syscalls_info
= allocate_syscalls_info ();
228 result_cleanup
= make_cleanup_free_syscalls_info (data
.syscalls_info
);
230 if (gdb_xml_parse_quick (_("syscalls info"), NULL
,
231 syselements
, document
, &data
) == 0)
233 /* Parsed successfully. */
234 discard_cleanups (result_cleanup
);
235 return data
.syscalls_info
;
239 warning (_("Could not load XML syscalls info; ignoring"));
240 do_cleanups (result_cleanup
);
245 /* Function responsible for initializing the information
246 about the syscalls. It reads the XML file and fills the
247 struct syscalls_info with the values.
249 Returns the struct syscalls_info if the file is valid, NULL otherwise. */
250 static struct syscalls_info
*
251 xml_init_syscalls_info (const char *filename
)
255 struct syscalls_info
*syscalls_info
;
256 struct cleanup
*back_to
;
258 full_file
= xml_fetch_content_from_file (filename
, gdb_datadir
);
259 if (full_file
== NULL
)
262 back_to
= make_cleanup (xfree
, full_file
);
264 dirname
= ldirname (filename
);
266 make_cleanup (xfree
, dirname
);
268 syscalls_info
= syscall_parse_xml (full_file
,
269 xml_fetch_content_from_file
, dirname
);
270 do_cleanups (back_to
);
272 return syscalls_info
;
275 /* Initializes the syscalls_info structure according to the
278 init_syscalls_info (struct gdbarch
*gdbarch
)
280 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
281 const char *xml_syscall_file
= gdbarch_xml_syscall_file (gdbarch
);
283 /* Should we re-read the XML info for this target? */
284 if (syscalls_info
!= NULL
&& syscalls_info
->my_gdb_datadir
!= NULL
285 && filename_cmp (syscalls_info
->my_gdb_datadir
, gdb_datadir
) != 0)
287 /* The data-directory changed from the last time we used it.
288 It means that we have to re-read the XML info. */
289 free_syscalls_info (syscalls_info
);
290 syscalls_info
= NULL
;
291 set_gdbarch_syscalls_info (gdbarch
, NULL
);
294 /* Did we succeed at initializing this? */
295 if (syscalls_info
!= NULL
)
298 syscalls_info
= xml_init_syscalls_info (xml_syscall_file
);
300 /* If there was some error reading the XML file, we initialize
301 gdbarch->syscalls_info anyway, in order to store information
302 about our attempt. */
303 if (syscalls_info
== NULL
)
304 syscalls_info
= allocate_syscalls_info ();
306 if (syscalls_info
->syscalls
== NULL
)
308 if (xml_syscall_file
!= NULL
)
309 warning (_("Could not load the syscall XML file `%s/%s'."),
310 gdb_datadir
, xml_syscall_file
);
312 warning (_("There is no XML file to open."));
314 warning (_("GDB will not be able to display "
315 "syscall names nor to verify if\n"
316 "any provided syscall numbers are valid."));
319 /* Saving the data-directory used to read this XML info. */
320 syscalls_info
->my_gdb_datadir
= xstrdup (gdb_datadir
);
322 set_gdbarch_syscalls_info (gdbarch
, syscalls_info
);
326 xml_get_syscall_number (struct gdbarch
*gdbarch
,
327 const char *syscall_name
)
329 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
330 struct syscall_desc
*sysdesc
;
333 if (syscalls_info
== NULL
334 || syscall_name
== NULL
)
335 return UNKNOWN_SYSCALL
;
338 VEC_iterate(syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
340 if (strcmp (sysdesc
->name
, syscall_name
) == 0)
341 return sysdesc
->number
;
343 return UNKNOWN_SYSCALL
;
347 xml_get_syscall_name (struct gdbarch
*gdbarch
,
350 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
351 struct syscall_desc
*sysdesc
;
354 if (syscalls_info
== NULL
355 || syscall_number
< 0)
359 VEC_iterate(syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
361 if (sysdesc
->number
== syscall_number
)
362 return sysdesc
->name
;
368 xml_list_of_syscalls (struct gdbarch
*gdbarch
)
370 struct syscalls_info
*syscalls_info
= gdbarch_syscalls_info (gdbarch
);
371 struct syscall_desc
*sysdesc
;
372 const char **names
= NULL
;
376 if (syscalls_info
== NULL
)
379 nsyscalls
= VEC_length (syscall_desc_p
, syscalls_info
->syscalls
);
380 names
= xmalloc ((nsyscalls
+ 1) * sizeof (char *));
383 VEC_iterate (syscall_desc_p
, syscalls_info
->syscalls
, i
, sysdesc
);
385 names
[i
] = sysdesc
->name
;
393 set_xml_syscall_file_name (struct gdbarch
*gdbarch
, const char *name
)
395 set_gdbarch_xml_syscall_file (gdbarch
, name
);
399 get_syscall_by_number (struct gdbarch
*gdbarch
,
400 int syscall_number
, struct syscall
*s
)
402 init_syscalls_info (gdbarch
);
404 s
->number
= syscall_number
;
405 s
->name
= xml_get_syscall_name (gdbarch
, syscall_number
);
409 get_syscall_by_name (struct gdbarch
*gdbarch
,
410 const char *syscall_name
, struct syscall
*s
)
412 init_syscalls_info (gdbarch
);
414 s
->number
= xml_get_syscall_number (gdbarch
, syscall_name
);
415 s
->name
= syscall_name
;
419 get_syscall_names (struct gdbarch
*gdbarch
)
421 init_syscalls_info (gdbarch
);
423 return xml_list_of_syscalls (gdbarch
);
426 #endif /* ! HAVE_LIBEXPAT */