1 /* Functions that provide the mechanism to parse a syscall XML file 2 and get its values. 3 4 Copyright (C) 2009-2016 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 struct syscall * 81 get_syscalls_by_group (struct gdbarch *gdbarch, const char *group) 82 { 83 syscall_warn_user (); 84 return NULL; 85 } 86 87 const char ** 88 get_syscall_group_names (struct gdbarch *gdbarch) 89 { 90 syscall_warn_user (); 91 return NULL; 92 } 93 94 #else /* ! HAVE_LIBEXPAT */ 95 96 /* Structure which describes a syscall. */ 97 typedef struct syscall_desc 98 { 99 /* The syscall number. */ 100 101 int number; 102 103 /* The syscall name. */ 104 105 char *name; 106 } *syscall_desc_p; 107 DEF_VEC_P(syscall_desc_p); 108 109 /* Structure of a syscall group. */ 110 typedef struct syscall_group_desc 111 { 112 /* The group name. */ 113 114 char *name; 115 116 /* The syscalls that are part of the group. */ 117 118 VEC(syscall_desc_p) *syscalls; 119 } *syscall_group_desc_p; 120 DEF_VEC_P(syscall_group_desc_p); 121 122 /* Structure that represents syscalls information. */ 123 struct syscalls_info 124 { 125 /* The syscalls. */ 126 127 VEC(syscall_desc_p) *syscalls; 128 129 /* The syscall groups. */ 130 131 VEC(syscall_group_desc_p) *groups; 132 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 135 target. */ 136 137 char *my_gdb_datadir; 138 }; 139 140 /* Callback data for syscall information parsing. */ 141 struct syscall_parsing_data 142 { 143 /* The syscalls_info we are building. */ 144 145 struct syscalls_info *syscalls_info; 146 }; 147 148 static struct syscalls_info * 149 allocate_syscalls_info (void) 150 { 151 return XCNEW (struct syscalls_info); 152 } 153 154 static void 155 syscalls_info_free_syscalls_desc (struct syscall_desc *sd) 156 { 157 xfree (sd->name); 158 } 159 160 /* Free syscall_group_desc members but not the structure itself. */ 161 162 static void 163 syscalls_info_free_syscall_group_desc (struct syscall_group_desc *sd) 164 { 165 VEC_free (syscall_desc_p, sd->syscalls); 166 xfree (sd->name); 167 } 168 169 static void 170 free_syscalls_info (void *arg) 171 { 172 struct syscalls_info *syscalls_info = (struct syscalls_info *) arg; 173 struct syscall_desc *sysdesc; 174 struct syscall_group_desc *groupdesc; 175 int i; 176 177 xfree (syscalls_info->my_gdb_datadir); 178 179 if (syscalls_info->syscalls != NULL) 180 { 181 for (i = 0; 182 VEC_iterate (syscall_desc_p, syscalls_info->syscalls, i, sysdesc); 183 i++) 184 syscalls_info_free_syscalls_desc (sysdesc); 185 VEC_free (syscall_desc_p, syscalls_info->syscalls); 186 } 187 188 if (syscalls_info->groups != NULL) 189 { 190 for (i = 0; 191 VEC_iterate (syscall_group_desc_p, 192 syscalls_info->groups, i, groupdesc); 193 i++) 194 syscalls_info_free_syscall_group_desc (groupdesc); 195 196 VEC_free (syscall_group_desc_p, syscalls_info->groups); 197 } 198 199 xfree (syscalls_info); 200 } 201 202 static struct cleanup * 203 make_cleanup_free_syscalls_info (struct syscalls_info *syscalls_info) 204 { 205 return make_cleanup (free_syscalls_info, syscalls_info); 206 } 207 208 /* Create a new syscall group. Return pointer to the 209 syscall_group_desc structure that represents the new group. */ 210 211 static struct syscall_group_desc * 212 syscall_group_create_syscall_group_desc (struct syscalls_info *syscalls_info, 213 const char *group) 214 { 215 struct syscall_group_desc *groupdesc = XCNEW (struct syscall_group_desc); 216 217 groupdesc->name = xstrdup (group); 218 219 VEC_safe_push (syscall_group_desc_p, syscalls_info->groups, groupdesc); 220 221 return groupdesc; 222 } 223 224 /* Add a syscall to the group. If group doesn't exist, create it. */ 225 226 static void 227 syscall_group_add_syscall (struct syscalls_info *syscalls_info, 228 struct syscall_desc *syscall, 229 const char *group) 230 { 231 struct syscall_group_desc *groupdesc = NULL; 232 int i; 233 234 /* Search for an existing group. */ 235 for (i = 0; 236 VEC_iterate (syscall_group_desc_p, syscalls_info->groups, i, groupdesc); 237 i++) 238 { 239 if (strcmp (groupdesc->name, group) == 0) 240 break; 241 } 242 243 if (groupdesc == NULL) 244 { 245 /* No group was found with this name. We must create a new 246 one. */ 247 groupdesc = syscall_group_create_syscall_group_desc (syscalls_info, 248 group); 249 } 250 251 VEC_safe_push (syscall_desc_p, groupdesc->syscalls, syscall); 252 } 253 254 static void 255 syscall_create_syscall_desc (struct syscalls_info *syscalls_info, 256 const char *name, int number, 257 char *groups) 258 { 259 struct syscall_desc *sysdesc = XCNEW (struct syscall_desc); 260 char *group; 261 262 sysdesc->name = xstrdup (name); 263 sysdesc->number = number; 264 265 VEC_safe_push (syscall_desc_p, syscalls_info->syscalls, sysdesc); 266 267 /* Add syscall to its groups. */ 268 if (groups != NULL) 269 { 270 for (group = strtok (groups, ","); 271 group != NULL; 272 group = strtok (NULL, ",")) 273 syscall_group_add_syscall (syscalls_info, sysdesc, group); 274 } 275 } 276 277 /* Handle the start of a <syscall> element. */ 278 static void 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) 282 { 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); 285 int len, i; 286 /* syscall info. */ 287 char *name = NULL; 288 int number = 0; 289 char *groups = NULL; 290 291 len = VEC_length (gdb_xml_value_s, attributes); 292 293 for (i = 0; i < len; i++) 294 { 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; 301 else 302 internal_error (__FILE__, __LINE__, 303 _("Unknown attribute name '%s'."), attrs[i].name); 304 } 305 306 gdb_assert (name); 307 syscall_create_syscall_desc (data->syscalls_info, name, number, groups); 308 } 309 310 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 } 317 }; 318 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 } 324 }; 325 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 } 330 }; 331 332 static struct syscalls_info * 333 syscall_parse_xml (const char *document, xml_fetch_another fetcher, 334 void *fetcher_baton) 335 { 336 struct cleanup *result_cleanup; 337 struct syscall_parsing_data data; 338 339 data.syscalls_info = allocate_syscalls_info (); 340 result_cleanup = make_cleanup_free_syscalls_info (data.syscalls_info); 341 342 if (gdb_xml_parse_quick (_("syscalls info"), NULL, 343 syselements, document, &data) == 0) 344 { 345 /* Parsed successfully. */ 346 discard_cleanups (result_cleanup); 347 return data.syscalls_info; 348 } 349 else 350 { 351 warning (_("Could not load XML syscalls info; ignoring")); 352 do_cleanups (result_cleanup); 353 return NULL; 354 } 355 } 356 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. 360 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) 364 { 365 char *full_file; 366 char *dirname; 367 struct syscalls_info *syscalls_info; 368 struct cleanup *back_to; 369 370 full_file = xml_fetch_content_from_file (filename, gdb_datadir); 371 if (full_file == NULL) 372 return NULL; 373 374 back_to = make_cleanup (xfree, full_file); 375 376 dirname = ldirname (filename); 377 if (dirname != NULL) 378 make_cleanup (xfree, dirname); 379 380 syscalls_info = syscall_parse_xml (full_file, 381 xml_fetch_content_from_file, dirname); 382 do_cleanups (back_to); 383 384 return syscalls_info; 385 } 386 387 /* Initializes the syscalls_info structure according to the 388 architecture. */ 389 static void 390 init_syscalls_info (struct gdbarch *gdbarch) 391 { 392 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); 393 const char *xml_syscall_file = gdbarch_xml_syscall_file (gdbarch); 394 395 /* Should we re-read the XML info for this target? */ 396 if (syscalls_info != NULL && syscalls_info->my_gdb_datadir != NULL 397 && filename_cmp (syscalls_info->my_gdb_datadir, gdb_datadir) != 0) 398 { 399 /* The data-directory changed from the last time we used it. 400 It means that we have to re-read the XML info. */ 401 free_syscalls_info (syscalls_info); 402 syscalls_info = NULL; 403 set_gdbarch_syscalls_info (gdbarch, NULL); 404 } 405 406 /* Did we succeed at initializing this? */ 407 if (syscalls_info != NULL) 408 return; 409 410 syscalls_info = xml_init_syscalls_info (xml_syscall_file); 411 412 /* If there was some error reading the XML file, we initialize 413 gdbarch->syscalls_info anyway, in order to store information 414 about our attempt. */ 415 if (syscalls_info == NULL) 416 syscalls_info = allocate_syscalls_info (); 417 418 if (syscalls_info->syscalls == NULL) 419 { 420 if (xml_syscall_file != NULL) 421 warning (_("Could not load the syscall XML file `%s/%s'."), 422 gdb_datadir, xml_syscall_file); 423 else 424 warning (_("There is no XML file to open.")); 425 426 warning (_("GDB will not be able to display " 427 "syscall names nor to verify if\n" 428 "any provided syscall numbers are valid.")); 429 } 430 431 /* Saving the data-directory used to read this XML info. */ 432 syscalls_info->my_gdb_datadir = xstrdup (gdb_datadir); 433 434 set_gdbarch_syscalls_info (gdbarch, syscalls_info); 435 } 436 437 /* Search for a syscall group by its name. Return syscall_group_desc 438 structure for the group if found or NULL otherwise. */ 439 440 static struct syscall_group_desc * 441 syscall_group_get_group_by_name (const struct syscalls_info *syscalls_info, 442 const char *group) 443 { 444 struct syscall_group_desc *groupdesc; 445 int i; 446 447 if (syscalls_info == NULL) 448 return NULL; 449 450 if (group == NULL) 451 return NULL; 452 453 /* Search for existing group. */ 454 for (i = 0; 455 VEC_iterate (syscall_group_desc_p, syscalls_info->groups, i, groupdesc); 456 i++) 457 { 458 if (strcmp (groupdesc->name, group) == 0) 459 return groupdesc; 460 } 461 462 return NULL; 463 } 464 465 static int 466 xml_get_syscall_number (struct gdbarch *gdbarch, 467 const char *syscall_name) 468 { 469 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); 470 struct syscall_desc *sysdesc; 471 int i; 472 473 if (syscalls_info == NULL 474 || syscall_name == NULL) 475 return UNKNOWN_SYSCALL; 476 477 for (i = 0; 478 VEC_iterate(syscall_desc_p, syscalls_info->syscalls, i, sysdesc); 479 i++) 480 if (strcmp (sysdesc->name, syscall_name) == 0) 481 return sysdesc->number; 482 483 return UNKNOWN_SYSCALL; 484 } 485 486 static const char * 487 xml_get_syscall_name (struct gdbarch *gdbarch, 488 int syscall_number) 489 { 490 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); 491 struct syscall_desc *sysdesc; 492 int i; 493 494 if (syscalls_info == NULL 495 || syscall_number < 0) 496 return NULL; 497 498 for (i = 0; 499 VEC_iterate(syscall_desc_p, syscalls_info->syscalls, i, sysdesc); 500 i++) 501 if (sysdesc->number == syscall_number) 502 return sysdesc->name; 503 504 return NULL; 505 } 506 507 static const char ** 508 xml_list_of_syscalls (struct gdbarch *gdbarch) 509 { 510 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); 511 struct syscall_desc *sysdesc; 512 const char **names = NULL; 513 int nsyscalls; 514 int i; 515 516 if (syscalls_info == NULL) 517 return NULL; 518 519 nsyscalls = VEC_length (syscall_desc_p, syscalls_info->syscalls); 520 names = XNEWVEC (const char *, nsyscalls + 1); 521 522 for (i = 0; 523 VEC_iterate (syscall_desc_p, syscalls_info->syscalls, i, sysdesc); 524 i++) 525 names[i] = sysdesc->name; 526 527 names[i] = NULL; 528 529 return names; 530 } 531 532 /* Iterate over the syscall_group_desc element to return a list of 533 syscalls that are part of the given group, terminated by an empty 534 element. If the syscall group doesn't exist, return NULL. */ 535 536 static struct syscall * 537 xml_list_syscalls_by_group (struct gdbarch *gdbarch, const char *group) 538 { 539 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); 540 struct syscall_group_desc *groupdesc; 541 struct syscall_desc *sysdesc; 542 struct syscall *syscalls = NULL; 543 int nsyscalls; 544 int i; 545 546 if (syscalls_info == NULL) 547 return NULL; 548 549 groupdesc = syscall_group_get_group_by_name (syscalls_info, group); 550 if (groupdesc == NULL) 551 return NULL; 552 553 nsyscalls = VEC_length (syscall_desc_p, groupdesc->syscalls); 554 syscalls = (struct syscall*) xmalloc ((nsyscalls + 1) 555 * sizeof (struct syscall)); 556 557 for (i = 0; 558 VEC_iterate (syscall_desc_p, groupdesc->syscalls, i, sysdesc); 559 i++) 560 { 561 syscalls[i].name = sysdesc->name; 562 syscalls[i].number = sysdesc->number; 563 } 564 565 /* Add final element marker. */ 566 syscalls[i].name = NULL; 567 syscalls[i].number = 0; 568 569 return syscalls; 570 } 571 572 /* Return a NULL terminated list of syscall groups or an empty list, if 573 no syscall group is available. Return NULL, if there is no syscall 574 information available. */ 575 576 static const char ** 577 xml_list_of_groups (struct gdbarch *gdbarch) 578 { 579 struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch); 580 struct syscall_group_desc *groupdesc; 581 const char **names = NULL; 582 int i; 583 int ngroups; 584 585 if (syscalls_info == NULL) 586 return NULL; 587 588 ngroups = VEC_length (syscall_group_desc_p, syscalls_info->groups); 589 names = (const char**) xmalloc ((ngroups + 1) * sizeof (char *)); 590 591 for (i = 0; 592 VEC_iterate (syscall_group_desc_p, syscalls_info->groups, i, groupdesc); 593 i++) 594 names[i] = groupdesc->name; 595 596 names[i] = NULL; 597 598 return names; 599 } 600 601 void 602 set_xml_syscall_file_name (struct gdbarch *gdbarch, const char *name) 603 { 604 set_gdbarch_xml_syscall_file (gdbarch, name); 605 } 606 607 void 608 get_syscall_by_number (struct gdbarch *gdbarch, 609 int syscall_number, struct syscall *s) 610 { 611 init_syscalls_info (gdbarch); 612 613 s->number = syscall_number; 614 s->name = xml_get_syscall_name (gdbarch, syscall_number); 615 } 616 617 void 618 get_syscall_by_name (struct gdbarch *gdbarch, 619 const char *syscall_name, struct syscall *s) 620 { 621 init_syscalls_info (gdbarch); 622 623 s->number = xml_get_syscall_number (gdbarch, syscall_name); 624 s->name = syscall_name; 625 } 626 627 const char ** 628 get_syscall_names (struct gdbarch *gdbarch) 629 { 630 init_syscalls_info (gdbarch); 631 632 return xml_list_of_syscalls (gdbarch); 633 } 634 635 /* See comment in xml-syscall.h. */ 636 637 struct syscall * 638 get_syscalls_by_group (struct gdbarch *gdbarch, const char *group) 639 { 640 init_syscalls_info (gdbarch); 641 642 return xml_list_syscalls_by_group (gdbarch, group); 643 } 644 645 /* See comment in xml-syscall.h. */ 646 647 const char ** 648 get_syscall_group_names (struct gdbarch *gdbarch) 649 { 650 init_syscalls_info (gdbarch); 651 652 return xml_list_of_groups (gdbarch); 653 } 654 655 #endif /* ! HAVE_LIBEXPAT */ 656