Change get_syscalls_by_group to append to an existing vector of integers.
[deliverable/binutils-gdb.git] / gdb / xml-syscall.c
1 /* Functions that provide the mechanism to parse a syscall XML file
2 and get its values.
3
4 Copyright (C) 2009-2018 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
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.
12
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.
17
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/>. */
20
21 #include "defs.h"
22 #include "gdbtypes.h"
23 #include "xml-support.h"
24 #include "xml-syscall.h"
25 #include "gdbarch.h"
26
27 /* For the struct syscall definition. */
28 #include "target.h"
29
30 #include "filenames.h"
31
32 #ifndef HAVE_LIBEXPAT
33
34 /* Dummy functions to indicate that there's no support for fetching
35 syscalls information. */
36
37 static void
38 syscall_warn_user (void)
39 {
40 static int have_warned = 0;
41 if (!have_warned)
42 {
43 have_warned = 1;
44 warning (_("Can not parse XML syscalls information; XML support was "
45 "disabled at compile time."));
46 }
47 }
48
49 void
50 set_xml_syscall_file_name (struct gdbarch *gdbarch, const char *name)
51 {
52 return;
53 }
54
55 void
56 get_syscall_by_number (struct gdbarch *gdbarch,
57 int syscall_number, struct syscall *s)
58 {
59 syscall_warn_user ();
60 s->number = syscall_number;
61 s->name = NULL;
62 }
63
64 void
65 get_syscall_by_name (struct gdbarch *gdbarch, const char *syscall_name,
66 struct syscall *s)
67 {
68 syscall_warn_user ();
69 s->number = UNKNOWN_SYSCALL;
70 s->name = syscall_name;
71 }
72
73 const char **
74 get_syscall_names (struct gdbarch *gdbarch)
75 {
76 syscall_warn_user ();
77 return NULL;
78 }
79
80 bool
81 get_syscalls_by_group (struct gdbarch *gdbarch, const char *group,
82 std::vector<int> *syscall_numbers)
83 {
84 syscall_warn_user ();
85 return false;
86 }
87
88 const char **
89 get_syscall_group_names (struct gdbarch *gdbarch)
90 {
91 syscall_warn_user ();
92 return NULL;
93 }
94
95 #else /* ! HAVE_LIBEXPAT */
96
97 /* Structure which describes a syscall. */
98 struct syscall_desc
99 {
100 syscall_desc (int number_, std::string name_)
101 : number (number_), name (name_)
102 {}
103
104 /* The syscall number. */
105
106 int number;
107
108 /* The syscall name. */
109
110 std::string name;
111 };
112
113 typedef std::unique_ptr<syscall_desc> syscall_desc_up;
114
115 /* Structure of a syscall group. */
116 struct syscall_group_desc
117 {
118 syscall_group_desc (const std::string &name_)
119 : name (name_)
120 {}
121
122 /* The group name. */
123
124 std::string name;
125
126 /* The syscalls that are part of the group. This is a non-owning
127 reference. */
128
129 std::vector<syscall_desc *> syscalls;
130 };
131
132 typedef std::unique_ptr<syscall_group_desc> syscall_group_desc_up;
133
134 /* Structure that represents syscalls information. */
135 struct syscalls_info
136 {
137 /* The syscalls. */
138
139 std::vector<syscall_desc_up> syscalls;
140
141 /* The syscall groups. */
142
143 std::vector<syscall_group_desc_up> groups;
144
145 /* Variable that will hold the last known data-directory. This is
146 useful to know whether we should re-read the XML info for the
147 target. */
148
149 std::string my_gdb_datadir;
150 };
151
152 typedef std::unique_ptr<syscalls_info> syscalls_info_up;
153
154 /* Callback data for syscall information parsing. */
155 struct syscall_parsing_data
156 {
157 /* The syscalls_info we are building. */
158
159 struct syscalls_info *syscalls_info;
160 };
161
162 /* Create a new syscall group. Return pointer to the
163 syscall_group_desc structure that represents the new group. */
164
165 static struct syscall_group_desc *
166 syscall_group_create_syscall_group_desc (struct syscalls_info *syscalls_info,
167 const char *group)
168 {
169 syscall_group_desc *groupdesc = new syscall_group_desc (group);
170
171 syscalls_info->groups.emplace_back (groupdesc);
172
173 return groupdesc;
174 }
175
176 /* Add a syscall to the group. If group doesn't exist, create it. */
177
178 static void
179 syscall_group_add_syscall (struct syscalls_info *syscalls_info,
180 struct syscall_desc *syscall,
181 const char *group)
182 {
183 /* Search for an existing group. */
184 std::vector<syscall_group_desc_up>::iterator it
185 = syscalls_info->groups.begin ();
186
187 for (; it != syscalls_info->groups.end (); it++)
188 {
189 if ((*it)->name == group)
190 break;
191 }
192
193 syscall_group_desc *groupdesc;
194
195 if (it != syscalls_info->groups.end ())
196 groupdesc = it->get ();
197 else
198 {
199 /* No group was found with this name. We must create a new
200 one. */
201 groupdesc = syscall_group_create_syscall_group_desc (syscalls_info,
202 group);
203 }
204
205 groupdesc->syscalls.push_back (syscall);
206 }
207
208 static void
209 syscall_create_syscall_desc (struct syscalls_info *syscalls_info,
210 const char *name, int number,
211 char *groups)
212 {
213 syscall_desc *sysdesc = new syscall_desc (number, name);
214
215 syscalls_info->syscalls.emplace_back (sysdesc);
216
217 /* Add syscall to its groups. */
218 if (groups != NULL)
219 {
220 for (char *group = strtok (groups, ",");
221 group != NULL;
222 group = strtok (NULL, ","))
223 syscall_group_add_syscall (syscalls_info, sysdesc, group);
224 }
225 }
226
227 /* Handle the start of a <syscall> element. */
228 static void
229 syscall_start_syscall (struct gdb_xml_parser *parser,
230 const struct gdb_xml_element *element,
231 void *user_data,
232 std::vector<gdb_xml_value> &attributes)
233 {
234 struct syscall_parsing_data *data = (struct syscall_parsing_data *) user_data;
235 /* syscall info. */
236 char *name = NULL;
237 int number = 0;
238 char *groups = NULL;
239
240 for (const gdb_xml_value &attr : attributes)
241 {
242 if (strcmp (attr.name, "name") == 0)
243 name = (char *) attr.value.get ();
244 else if (strcmp (attr.name, "number") == 0)
245 number = * (ULONGEST *) attr.value.get ();
246 else if (strcmp (attr.name, "groups") == 0)
247 groups = (char *) attr.value.get ();
248 else
249 internal_error (__FILE__, __LINE__,
250 _("Unknown attribute name '%s'."), attr.name);
251 }
252
253 gdb_assert (name);
254 syscall_create_syscall_desc (data->syscalls_info, name, number, groups);
255 }
256
257
258 /* The elements and attributes of an XML syscall document. */
259 static const struct gdb_xml_attribute syscall_attr[] = {
260 { "number", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
261 { "name", GDB_XML_AF_NONE, NULL, NULL },
262 { "groups", GDB_XML_AF_OPTIONAL, NULL, NULL },
263 { NULL, GDB_XML_AF_NONE, NULL, NULL }
264 };
265
266 static const struct gdb_xml_element syscalls_info_children[] = {
267 { "syscall", syscall_attr, NULL,
268 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
269 syscall_start_syscall, NULL },
270 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
271 };
272
273 static const struct gdb_xml_element syselements[] = {
274 { "syscalls_info", NULL, syscalls_info_children,
275 GDB_XML_EF_NONE, NULL, NULL },
276 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
277 };
278
279 static struct syscalls_info *
280 syscall_parse_xml (const char *document, xml_fetch_another fetcher,
281 void *fetcher_baton)
282 {
283 struct syscall_parsing_data data;
284 syscalls_info_up sysinfo (new syscalls_info ());
285
286 data.syscalls_info = sysinfo.get ();
287
288 if (gdb_xml_parse_quick (_("syscalls info"), NULL,
289 syselements, document, &data) == 0)
290 {
291 /* Parsed successfully. */
292 return sysinfo.release ();
293 }
294 else
295 {
296 warning (_("Could not load XML syscalls info; ignoring"));
297 return NULL;
298 }
299 }
300
301 /* Function responsible for initializing the information
302 about the syscalls. It reads the XML file and fills the
303 struct syscalls_info with the values.
304
305 Returns the struct syscalls_info if the file is valid, NULL otherwise. */
306 static struct syscalls_info *
307 xml_init_syscalls_info (const char *filename)
308 {
309 gdb::optional<gdb::char_vector> full_file
310 = xml_fetch_content_from_file (filename, gdb_datadir);
311 if (!full_file)
312 return NULL;
313
314 return syscall_parse_xml (full_file->data (),
315 xml_fetch_content_from_file,
316 (void *) ldirname (filename).c_str ());
317 }
318
319 /* Initializes the syscalls_info structure according to the
320 architecture. */
321 static void
322 init_syscalls_info (struct gdbarch *gdbarch)
323 {
324 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
325 const char *xml_syscall_file = gdbarch_xml_syscall_file (gdbarch);
326
327 /* Should we re-read the XML info for this target? */
328 if (syscalls_info != NULL && !syscalls_info->my_gdb_datadir.empty ()
329 && filename_cmp (syscalls_info->my_gdb_datadir.c_str (),
330 gdb_datadir) != 0)
331 {
332 /* The data-directory changed from the last time we used it.
333 It means that we have to re-read the XML info. */
334 delete syscalls_info;
335 syscalls_info = NULL;
336 set_gdbarch_syscalls_info (gdbarch, NULL);
337 }
338
339 /* Did we succeed at initializing this? */
340 if (syscalls_info != NULL)
341 return;
342
343 syscalls_info = xml_init_syscalls_info (xml_syscall_file);
344
345 /* If there was some error reading the XML file, we initialize
346 gdbarch->syscalls_info anyway, in order to store information
347 about our attempt. */
348 if (syscalls_info == NULL)
349 syscalls_info = new struct syscalls_info ();
350
351 if (syscalls_info->syscalls.empty ())
352 {
353 if (xml_syscall_file != NULL)
354 warning (_("Could not load the syscall XML file `%s/%s'."),
355 gdb_datadir, xml_syscall_file);
356 else
357 warning (_("There is no XML file to open."));
358
359 warning (_("GDB will not be able to display "
360 "syscall names nor to verify if\n"
361 "any provided syscall numbers are valid."));
362 }
363
364 /* Saving the data-directory used to read this XML info. */
365 syscalls_info->my_gdb_datadir.assign (gdb_datadir);
366
367 set_gdbarch_syscalls_info (gdbarch, syscalls_info);
368 }
369
370 /* Search for a syscall group by its name. Return syscall_group_desc
371 structure for the group if found or NULL otherwise. */
372
373 static struct syscall_group_desc *
374 syscall_group_get_group_by_name (const struct syscalls_info *syscalls_info,
375 const char *group)
376 {
377 if (syscalls_info == NULL)
378 return NULL;
379
380 if (group == NULL)
381 return NULL;
382
383 /* Search for existing group. */
384 for (const syscall_group_desc_up &groupdesc : syscalls_info->groups)
385 {
386 if (groupdesc->name == group)
387 return groupdesc.get ();
388 }
389
390 return NULL;
391 }
392
393 static int
394 xml_get_syscall_number (struct gdbarch *gdbarch,
395 const char *syscall_name)
396 {
397 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
398
399 if (syscalls_info == NULL
400 || syscall_name == NULL)
401 return UNKNOWN_SYSCALL;
402
403 for (const syscall_desc_up &sysdesc : syscalls_info->syscalls)
404 if (sysdesc->name == syscall_name)
405 return sysdesc->number;
406
407 return UNKNOWN_SYSCALL;
408 }
409
410 static const char *
411 xml_get_syscall_name (struct gdbarch *gdbarch,
412 int syscall_number)
413 {
414 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
415
416 if (syscalls_info == NULL
417 || syscall_number < 0)
418 return NULL;
419
420 for (const syscall_desc_up &sysdesc : syscalls_info->syscalls)
421 if (sysdesc->number == syscall_number)
422 return sysdesc->name.c_str ();
423
424 return NULL;
425 }
426
427 static const char **
428 xml_list_of_syscalls (struct gdbarch *gdbarch)
429 {
430 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
431
432 if (syscalls_info == NULL)
433 return NULL;
434
435 int nsyscalls = syscalls_info->syscalls.size ();
436 const char **names = XNEWVEC (const char *, nsyscalls + 1);
437
438 int i;
439 for (i = 0; i < syscalls_info->syscalls.size (); i++)
440 names[i] = syscalls_info->syscalls[i]->name.c_str ();
441
442 names[i] = NULL;
443
444 return names;
445 }
446
447 /* Iterate over the syscall_group_desc element to return a list of
448 syscalls that are part of the given group. If the syscall group
449 doesn't exist, return false. */
450
451 static bool
452 xml_list_syscalls_by_group (struct gdbarch *gdbarch, const char *group,
453 std::vector<int> *syscalls)
454 {
455 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
456 struct syscall_group_desc *groupdesc;
457
458 if (syscalls_info == NULL || syscalls == NULL)
459 return false;
460
461 groupdesc = syscall_group_get_group_by_name (syscalls_info, group);
462 if (groupdesc == NULL)
463 return false;
464
465 for (const struct syscall_desc *sysdesc : groupdesc->syscalls)
466 syscalls->push_back (sysdesc->number);
467
468 return true;
469 }
470
471 /* Return a NULL terminated list of syscall groups or an empty list, if
472 no syscall group is available. Return NULL, if there is no syscall
473 information available. */
474
475 static const char **
476 xml_list_of_groups (struct gdbarch *gdbarch)
477 {
478 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
479 const char **names = NULL;
480 int ngroups;
481 int i;
482
483 if (syscalls_info == NULL)
484 return NULL;
485
486 ngroups = syscalls_info->groups.size ();
487 names = (const char**) xmalloc ((ngroups + 1) * sizeof (char *));
488
489 for (i = 0; i < syscalls_info->groups.size (); i++)
490 names[i] = syscalls_info->groups[i]->name.c_str ();
491
492 names[i] = NULL;
493
494 return names;
495 }
496
497 void
498 set_xml_syscall_file_name (struct gdbarch *gdbarch, const char *name)
499 {
500 set_gdbarch_xml_syscall_file (gdbarch, name);
501 }
502
503 void
504 get_syscall_by_number (struct gdbarch *gdbarch,
505 int syscall_number, struct syscall *s)
506 {
507 init_syscalls_info (gdbarch);
508
509 s->number = syscall_number;
510 s->name = xml_get_syscall_name (gdbarch, syscall_number);
511 }
512
513 void
514 get_syscall_by_name (struct gdbarch *gdbarch,
515 const char *syscall_name, struct syscall *s)
516 {
517 init_syscalls_info (gdbarch);
518
519 s->number = xml_get_syscall_number (gdbarch, syscall_name);
520 s->name = syscall_name;
521 }
522
523 const char **
524 get_syscall_names (struct gdbarch *gdbarch)
525 {
526 init_syscalls_info (gdbarch);
527
528 return xml_list_of_syscalls (gdbarch);
529 }
530
531 /* See comment in xml-syscall.h. */
532
533 bool
534 get_syscalls_by_group (struct gdbarch *gdbarch, const char *group,
535 std::vector<int> *syscall_numbers)
536 {
537 init_syscalls_info (gdbarch);
538
539 return xml_list_syscalls_by_group (gdbarch, group, syscall_numbers);
540 }
541
542 /* See comment in xml-syscall.h. */
543
544 const char **
545 get_syscall_group_names (struct gdbarch *gdbarch)
546 {
547 init_syscalls_info (gdbarch);
548
549 return xml_list_of_groups (gdbarch);
550 }
551
552 #endif /* ! HAVE_LIBEXPAT */
This page took 0.050784 seconds and 5 git commands to generate.