1 /* Functions that provide the mechanism to parse a syscall XML file 2 and get its values. 3 4 Copyright (C) 2009-2015 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 #else /* ! HAVE_LIBEXPAT */ 81 82 /* Structure which describes a syscall. */ 83 typedef struct syscall_desc 84 { 85 /* The syscall number. */ 86 87 int number; 88 89 /* The syscall name. */ 90 91 char *name; 92 } *syscall_desc_p; 93 DEF_VEC_P(syscall_desc_p); 94 95 /* Structure that represents syscalls information. */ 96 struct syscalls_info 97 { 98 /* The syscalls. */ 99 100 VEC(syscall_desc_p) *syscalls; 101 102 /* Variable that will hold the last known data-directory. This is 103 useful to know whether we should re-read the XML info for the 104 target. */ 105 106 char *my_gdb_datadir; 107 }; 108 109 /* Callback data for syscall information parsing. */ 110 struct syscall_parsing_data 111 { 112 /* The syscalls_info we are building. */ 113 114 struct syscalls_info *syscalls_info; 115 }; 116 117 static struct syscalls_info * 118 allocate_syscalls_info (void) 119 { 120 return XCNEW (struct syscalls_info); 121 } 122 123 static void 124 syscalls_info_free_syscalls_desc (struct syscall_desc *sd) 125 { 126 xfree (sd->name); 127 } 128 129 static void 130 free_syscalls_info (void *arg) 131 { 132 struct syscalls_info *syscalls_info = arg; 133 struct syscall_desc *sysdesc; 134 int i; 135 136 xfree (syscalls_info->my_gdb_datadir); 137 138 if (syscalls_info->syscalls != NULL) 139 { 140 for (i = 0; 141 VEC_iterate (syscall_desc_p, syscalls_info->syscalls, i, sysdesc); 142 i++) 143 syscalls_info_free_syscalls_desc (sysdesc); 144 VEC_free (syscall_desc_p, syscalls_info->syscalls); 145 } 146 147 xfree (syscalls_info); 148 } 149 150 static struct cleanup * 151 make_cleanup_free_syscalls_info (struct syscalls_info *syscalls_info) 152 { 153 return make_cleanup (free_syscalls_info, syscalls_info); 154 } 155 156 static void 157 syscall_create_syscall_desc (struct syscalls_info *syscalls_info, 158 const char *name, int number) 159 { 160 struct syscall_desc *sysdesc = XCNEW (struct syscall_desc); 161 162 sysdesc->name = xstrdup (name); 163 sysdesc->number = number; 164 165 VEC_safe_push (syscall_desc_p, syscalls_info->syscalls, sysdesc); 166 } 167 168 /* Handle the start of a <syscall> element. */ 169 static void 170 syscall_start_syscall (struct gdb_xml_parser *parser, 171 const struct gdb_xml_element *element, 172 void *user_data, VEC(gdb_xml_value_s) *attributes) 173 { 174 struct syscall_parsing_data *data = user_data; 175 struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes); 176 int len, i; 177 /* syscall info. */ 178 char *name = NULL; 179 int number = 0; 180 181 len = VEC_length (gdb_xml_value_s, attributes); 182 183 for (i = 0; i < len; i++) 184 { 185 if (strcmp (attrs[i].name, "name") == 0) 186 name = attrs[i].value; 187 else if (strcmp (attrs[i].name, "number") == 0) 188 number = * (ULONGEST *) attrs[i].value; 189 else 190 internal_error (__FILE__, __LINE__, 191 _("Unknown attribute name '%s'."), attrs[i].name); 192 } 193 194 gdb_assert (name); 195 syscall_create_syscall_desc (data->syscalls_info, name, number); 196 } 197 198 199 /* The elements and attributes of an XML syscall document. */ 200 static const struct gdb_xml_attribute syscall_attr[] = { 201 { "number", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 202 { "name", GDB_XML_AF_NONE, NULL, NULL }, 203 { NULL, GDB_XML_AF_NONE, NULL, NULL } 204 }; 205 206 static const struct gdb_xml_element syscalls_info_children[] = { 207 { "syscall", syscall_attr, NULL, 208 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, 209 syscall_start_syscall, NULL }, 210 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 211 }; 212 213 static const struct gdb_xml_element syselements[] = { 214 { "syscalls_info", NULL, syscalls_info_children, 215 GDB_XML_EF_NONE, NULL, NULL }, 216 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 217 }; 218 219 static struct syscalls_info * 220 syscall_parse_xml (const char *document, xml_fetch_another fetcher, 221 void *fetcher_baton) 222 { 223 struct cleanup *result_cleanup; 224 struct syscall_parsing_data data; 225 226 data.syscalls_info = allocate_syscalls_info (); 227 result_cleanup = make_cleanup_free_syscalls_info (data.syscalls_info); 228 229 if (gdb_xml_parse_quick (_("syscalls info"), NULL, 230 syselements, document, &data) == 0) 231 { 232 /* Parsed successfully. */ 233 discard_cleanups (result_cleanup); 234 return data.syscalls_info; 235 } 236 else 237 { 238 warning (_("Could not load XML syscalls info; ignoring")); 239 do_cleanups (result_cleanup); 240 return NULL; 241 } 242 } 243 244 /* Function responsible for initializing the information 245 about the syscalls. It reads the XML file and fills the 246 struct syscalls_info with the values. 247 248 Returns the struct syscalls_info if the file is valid, NULL otherwise. */ 249 static struct syscalls_info * 250 xml_init_syscalls_info (const char *filename) 251 { 252 char *full_file; 253 char *dirname; 254 struct syscalls_info *syscalls_info; 255 struct cleanup *back_to; 256 257 full_file = xml_fetch_content_from_file (filename, gdb_datadir); 258 if (full_file == NULL) 259 return NULL; 260 261 back_to = make_cleanup (xfree, full_file); 262 263 dirname = ldirname (filename); 264 if (dirname != NULL) 265 make_cleanup (xfree, dirname); 266 267 syscalls_info = syscall_parse_xml (full_file, 268 xml_fetch_content_from_file, dirname); 269 do_cleanups (back_to); 270 271 return syscalls_info; 272 } 273 274 /* Initializes the syscalls_info structure according to the 275 architecture. */ 276 static void 277 init_syscalls_info (struct gdbarch *gdbarch) 278 { 279 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); 280 const char *xml_syscall_file = gdbarch_xml_syscall_file (gdbarch); 281 282 /* Should we re-read the XML info for this target? */ 283 if (syscalls_info != NULL && syscalls_info->my_gdb_datadir != NULL 284 && filename_cmp (syscalls_info->my_gdb_datadir, gdb_datadir) != 0) 285 { 286 /* The data-directory changed from the last time we used it. 287 It means that we have to re-read the XML info. */ 288 free_syscalls_info (syscalls_info); 289 syscalls_info = NULL; 290 set_gdbarch_syscalls_info (gdbarch, NULL); 291 } 292 293 /* Did we succeed at initializing this? */ 294 if (syscalls_info != NULL) 295 return; 296 297 syscalls_info = xml_init_syscalls_info (xml_syscall_file); 298 299 /* If there was some error reading the XML file, we initialize 300 gdbarch->syscalls_info anyway, in order to store information 301 about our attempt. */ 302 if (syscalls_info == NULL) 303 syscalls_info = allocate_syscalls_info (); 304 305 if (syscalls_info->syscalls == NULL) 306 { 307 if (xml_syscall_file != NULL) 308 warning (_("Could not load the syscall XML file `%s/%s'."), 309 gdb_datadir, xml_syscall_file); 310 else 311 warning (_("There is no XML file to open.")); 312 313 warning (_("GDB will not be able to display " 314 "syscall names nor to verify if\n" 315 "any provided syscall numbers are valid.")); 316 } 317 318 /* Saving the data-directory used to read this XML info. */ 319 syscalls_info->my_gdb_datadir = xstrdup (gdb_datadir); 320 321 set_gdbarch_syscalls_info (gdbarch, syscalls_info); 322 } 323 324 static int 325 xml_get_syscall_number (struct gdbarch *gdbarch, 326 const char *syscall_name) 327 { 328 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); 329 struct syscall_desc *sysdesc; 330 int i; 331 332 if (syscalls_info == NULL 333 || syscall_name == NULL) 334 return UNKNOWN_SYSCALL; 335 336 for (i = 0; 337 VEC_iterate(syscall_desc_p, syscalls_info->syscalls, i, sysdesc); 338 i++) 339 if (strcmp (sysdesc->name, syscall_name) == 0) 340 return sysdesc->number; 341 342 return UNKNOWN_SYSCALL; 343 } 344 345 static const char * 346 xml_get_syscall_name (struct gdbarch *gdbarch, 347 int syscall_number) 348 { 349 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); 350 struct syscall_desc *sysdesc; 351 int i; 352 353 if (syscalls_info == NULL 354 || syscall_number < 0) 355 return NULL; 356 357 for (i = 0; 358 VEC_iterate(syscall_desc_p, syscalls_info->syscalls, i, sysdesc); 359 i++) 360 if (sysdesc->number == syscall_number) 361 return sysdesc->name; 362 363 return NULL; 364 } 365 366 static const char ** 367 xml_list_of_syscalls (struct gdbarch *gdbarch) 368 { 369 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); 370 struct syscall_desc *sysdesc; 371 const char **names = NULL; 372 int nsyscalls; 373 int i; 374 375 if (syscalls_info == NULL) 376 return NULL; 377 378 nsyscalls = VEC_length (syscall_desc_p, syscalls_info->syscalls); 379 names = xmalloc ((nsyscalls + 1) * sizeof (char *)); 380 381 for (i = 0; 382 VEC_iterate (syscall_desc_p, syscalls_info->syscalls, i, sysdesc); 383 i++) 384 names[i] = sysdesc->name; 385 386 names[i] = NULL; 387 388 return names; 389 } 390 391 void 392 set_xml_syscall_file_name (struct gdbarch *gdbarch, const char *name) 393 { 394 set_gdbarch_xml_syscall_file (gdbarch, name); 395 } 396 397 void 398 get_syscall_by_number (struct gdbarch *gdbarch, 399 int syscall_number, struct syscall *s) 400 { 401 init_syscalls_info (gdbarch); 402 403 s->number = syscall_number; 404 s->name = xml_get_syscall_name (gdbarch, syscall_number); 405 } 406 407 void 408 get_syscall_by_name (struct gdbarch *gdbarch, 409 const char *syscall_name, struct syscall *s) 410 { 411 init_syscalls_info (gdbarch); 412 413 s->number = xml_get_syscall_number (gdbarch, syscall_name); 414 s->name = syscall_name; 415 } 416 417 const char ** 418 get_syscall_names (struct gdbarch *gdbarch) 419 { 420 init_syscalls_info (gdbarch); 421 422 return xml_list_of_syscalls (gdbarch); 423 } 424 425 #endif /* ! HAVE_LIBEXPAT */ 426