Partial fix for PR breakpoints/10737: Make syscall info be per-arch instead of global
[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-2014 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 (const struct gdbarch *gdbarch,
51 const char *name)
52 {
53 return;
54 }
55
56 void
57 get_syscall_by_number (const struct gdbarch *gdbarch,
58 int syscall_number, struct syscall *s)
59 {
60 syscall_warn_user ();
61 s->number = syscall_number;
62 s->name = NULL;
63 }
64
65 void
66 get_syscall_by_name (const struct gdbarch *gdbarch,
67 const char *syscall_name, struct syscall *s)
68 {
69 syscall_warn_user ();
70 s->number = UNKNOWN_SYSCALL;
71 s->name = syscall_name;
72 }
73
74 const char **
75 get_syscall_names (const struct gdbarch *gdbarch)
76 {
77 syscall_warn_user ();
78 return NULL;
79 }
80
81 #else /* ! HAVE_LIBEXPAT */
82
83 /* Structure which describes a syscall. */
84 typedef struct syscall_desc
85 {
86 /* The syscall number. */
87
88 int number;
89
90 /* The syscall name. */
91
92 char *name;
93 } *syscall_desc_p;
94 DEF_VEC_P(syscall_desc_p);
95
96 /* Structure that represents syscalls information. */
97 struct syscalls_info
98 {
99 /* The syscalls. */
100
101 VEC(syscall_desc_p) *syscalls;
102
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
105 target. */
106
107 char *my_gdb_datadir;
108 };
109
110 /* Callback data for syscall information parsing. */
111 struct syscall_parsing_data
112 {
113 /* The syscalls_info we are building. */
114
115 struct syscalls_info *syscalls_info;
116 };
117
118 static struct syscalls_info *
119 allocate_syscalls_info (void)
120 {
121 return XCNEW (struct syscalls_info);
122 }
123
124 static void
125 syscalls_info_free_syscalls_desc (struct syscall_desc *sd)
126 {
127 xfree (sd->name);
128 }
129
130 static void
131 free_syscalls_info (void *arg)
132 {
133 struct syscalls_info *syscalls_info = arg;
134 struct syscall_desc *sysdesc;
135 int i;
136
137 xfree (syscalls_info->my_gdb_datadir);
138
139 if (syscalls_info->syscalls != NULL)
140 {
141 for (i = 0;
142 VEC_iterate (syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
143 i++)
144 syscalls_info_free_syscalls_desc (sysdesc);
145 VEC_free (syscall_desc_p, syscalls_info->syscalls);
146 }
147
148 xfree (syscalls_info);
149 }
150
151 static struct cleanup *
152 make_cleanup_free_syscalls_info (struct syscalls_info *syscalls_info)
153 {
154 return make_cleanup (free_syscalls_info, syscalls_info);
155 }
156
157 static void
158 syscall_create_syscall_desc (struct syscalls_info *syscalls_info,
159 const char *name, int number)
160 {
161 struct syscall_desc *sysdesc = XCNEW (struct syscall_desc);
162
163 sysdesc->name = xstrdup (name);
164 sysdesc->number = number;
165
166 VEC_safe_push (syscall_desc_p, syscalls_info->syscalls, sysdesc);
167 }
168
169 /* Handle the start of a <syscall> element. */
170 static void
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)
174 {
175 struct syscall_parsing_data *data = user_data;
176 struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
177 int len, i;
178 /* syscall info. */
179 char *name = NULL;
180 int number = 0;
181
182 len = VEC_length (gdb_xml_value_s, attributes);
183
184 for (i = 0; i < len; i++)
185 {
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;
190 else
191 internal_error (__FILE__, __LINE__,
192 _("Unknown attribute name '%s'."), attrs[i].name);
193 }
194
195 gdb_assert (name);
196 syscall_create_syscall_desc (data->syscalls_info, name, number);
197 }
198
199
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 }
205 };
206
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 }
212 };
213
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 }
218 };
219
220 static struct syscalls_info *
221 syscall_parse_xml (const char *document, xml_fetch_another fetcher,
222 void *fetcher_baton)
223 {
224 struct cleanup *result_cleanup;
225 struct syscall_parsing_data data;
226
227 data.syscalls_info = allocate_syscalls_info ();
228 result_cleanup = make_cleanup_free_syscalls_info (data.syscalls_info);
229
230 if (gdb_xml_parse_quick (_("syscalls info"), NULL,
231 syselements, document, &data) == 0)
232 {
233 /* Parsed successfully. */
234 discard_cleanups (result_cleanup);
235 return data.syscalls_info;
236 }
237 else
238 {
239 warning (_("Could not load XML syscalls info; ignoring"));
240 do_cleanups (result_cleanup);
241 return NULL;
242 }
243 }
244
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.
248
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)
252 {
253 char *full_file;
254 char *dirname;
255 struct syscalls_info *syscalls_info;
256 struct cleanup *back_to;
257
258 full_file = xml_fetch_content_from_file (filename, gdb_datadir);
259 if (full_file == NULL)
260 return NULL;
261
262 back_to = make_cleanup (xfree, full_file);
263
264 dirname = ldirname (filename);
265 if (dirname != NULL)
266 make_cleanup (xfree, dirname);
267
268 syscalls_info = syscall_parse_xml (full_file,
269 xml_fetch_content_from_file, dirname);
270 do_cleanups (back_to);
271
272 return syscalls_info;
273 }
274
275 /* Initializes the syscalls_info structure according to the
276 architecture. */
277 static void
278 init_syscalls_info (struct gdbarch *gdbarch)
279 {
280 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
281 const char *xml_syscall_file = gdbarch_xml_syscall_file (gdbarch);
282
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)
286 {
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);
292 }
293
294 /* Did we succeed at initializing this? */
295 if (syscalls_info != NULL)
296 return;
297
298 syscalls_info = xml_init_syscalls_info (xml_syscall_file);
299
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 ();
305
306 if (syscalls_info->syscalls == NULL)
307 {
308 if (xml_syscall_file != NULL)
309 warning (_("Could not load the syscall XML file `%s/%s'."),
310 gdb_datadir, xml_syscall_file);
311 else
312 warning (_("There is no XML file to open."));
313
314 warning (_("GDB will not be able to display "
315 "syscall names nor to verify if\n"
316 "any provided syscall numbers are valid."));
317 }
318
319 /* Saving the data-directory used to read this XML info. */
320 syscalls_info->my_gdb_datadir = xstrdup (gdb_datadir);
321
322 set_gdbarch_syscalls_info (gdbarch, syscalls_info);
323 }
324
325 static int
326 xml_get_syscall_number (struct gdbarch *gdbarch,
327 const char *syscall_name)
328 {
329 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
330 struct syscall_desc *sysdesc;
331 int i;
332
333 if (syscalls_info == NULL
334 || syscall_name == NULL)
335 return UNKNOWN_SYSCALL;
336
337 for (i = 0;
338 VEC_iterate(syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
339 i++)
340 if (strcmp (sysdesc->name, syscall_name) == 0)
341 return sysdesc->number;
342
343 return UNKNOWN_SYSCALL;
344 }
345
346 static const char *
347 xml_get_syscall_name (struct gdbarch *gdbarch,
348 int syscall_number)
349 {
350 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
351 struct syscall_desc *sysdesc;
352 int i;
353
354 if (syscalls_info == NULL
355 || syscall_number < 0)
356 return NULL;
357
358 for (i = 0;
359 VEC_iterate(syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
360 i++)
361 if (sysdesc->number == syscall_number)
362 return sysdesc->name;
363
364 return NULL;
365 }
366
367 static const char **
368 xml_list_of_syscalls (struct gdbarch *gdbarch)
369 {
370 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
371 struct syscall_desc *sysdesc;
372 const char **names = NULL;
373 int nsyscalls;
374 int i;
375
376 if (syscalls_info == NULL)
377 return NULL;
378
379 nsyscalls = VEC_length (syscall_desc_p, syscalls_info->syscalls);
380 names = xmalloc ((nsyscalls + 1) * sizeof (char *));
381
382 for (i = 0;
383 VEC_iterate (syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
384 i++)
385 names[i] = sysdesc->name;
386
387 names[i] = NULL;
388
389 return names;
390 }
391
392 void
393 set_xml_syscall_file_name (struct gdbarch *gdbarch, const char *name)
394 {
395 set_gdbarch_xml_syscall_file (gdbarch, name);
396 }
397
398 void
399 get_syscall_by_number (struct gdbarch *gdbarch,
400 int syscall_number, struct syscall *s)
401 {
402 init_syscalls_info (gdbarch);
403
404 s->number = syscall_number;
405 s->name = xml_get_syscall_name (gdbarch, syscall_number);
406 }
407
408 void
409 get_syscall_by_name (struct gdbarch *gdbarch,
410 const char *syscall_name, struct syscall *s)
411 {
412 init_syscalls_info (gdbarch);
413
414 s->number = xml_get_syscall_number (gdbarch, syscall_name);
415 s->name = syscall_name;
416 }
417
418 const char **
419 get_syscall_names (struct gdbarch *gdbarch)
420 {
421 init_syscalls_info (gdbarch);
422
423 return xml_list_of_syscalls (gdbarch);
424 }
425
426 #endif /* ! HAVE_LIBEXPAT */
This page took 0.045318 seconds and 5 git commands to generate.