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