Home | History | Annotate | Line # | Download | only in gdb
xml-syscall.c revision 1.6
      1  1.1  christos /* Functions that provide the mechanism to parse a syscall XML file
      2  1.1  christos    and get its values.
      3  1.1  christos 
      4  1.6  christos    Copyright (C) 2009-2016 Free Software Foundation, Inc.
      5  1.1  christos 
      6  1.1  christos    This file is part of GDB.
      7  1.1  christos 
      8  1.1  christos    This program is free software; you can redistribute it and/or modify
      9  1.1  christos    it under the terms of the GNU General Public License as published by
     10  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     11  1.1  christos    (at your option) any later version.
     12  1.1  christos 
     13  1.1  christos    This program is distributed in the hope that it will be useful,
     14  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  1.1  christos    GNU General Public License for more details.
     17  1.1  christos 
     18  1.1  christos    You should have received a copy of the GNU General Public License
     19  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20  1.1  christos 
     21  1.1  christos #include "defs.h"
     22  1.1  christos #include "gdbtypes.h"
     23  1.1  christos #include "xml-support.h"
     24  1.1  christos #include "xml-syscall.h"
     25  1.3  christos #include "gdbarch.h"
     26  1.1  christos 
     27  1.1  christos /* For the struct syscall definition.  */
     28  1.1  christos #include "target.h"
     29  1.1  christos 
     30  1.1  christos #include "filenames.h"
     31  1.1  christos 
     32  1.1  christos #ifndef HAVE_LIBEXPAT
     33  1.1  christos 
     34  1.1  christos /* Dummy functions to indicate that there's no support for fetching
     35  1.1  christos    syscalls information.  */
     36  1.1  christos 
     37  1.1  christos static void
     38  1.1  christos syscall_warn_user (void)
     39  1.1  christos {
     40  1.1  christos   static int have_warned = 0;
     41  1.1  christos   if (!have_warned)
     42  1.1  christos     {
     43  1.1  christos       have_warned = 1;
     44  1.1  christos       warning (_("Can not parse XML syscalls information; XML support was "
     45  1.1  christos 		 "disabled at compile time."));
     46  1.1  christos     }
     47  1.1  christos }
     48  1.1  christos 
     49  1.1  christos void
     50  1.3  christos set_xml_syscall_file_name (struct gdbarch *gdbarch, const char *name)
     51  1.1  christos {
     52  1.1  christos   return;
     53  1.1  christos }
     54  1.1  christos 
     55  1.1  christos void
     56  1.3  christos get_syscall_by_number (struct gdbarch *gdbarch,
     57  1.3  christos 		       int syscall_number, struct syscall *s)
     58  1.1  christos {
     59  1.1  christos   syscall_warn_user ();
     60  1.1  christos   s->number = syscall_number;
     61  1.1  christos   s->name = NULL;
     62  1.1  christos }
     63  1.1  christos 
     64  1.1  christos void
     65  1.3  christos get_syscall_by_name (struct gdbarch *gdbarch, const char *syscall_name,
     66  1.3  christos 		     struct syscall *s)
     67  1.1  christos {
     68  1.1  christos   syscall_warn_user ();
     69  1.1  christos   s->number = UNKNOWN_SYSCALL;
     70  1.1  christos   s->name = syscall_name;
     71  1.1  christos }
     72  1.1  christos 
     73  1.1  christos const char **
     74  1.3  christos get_syscall_names (struct gdbarch *gdbarch)
     75  1.1  christos {
     76  1.1  christos   syscall_warn_user ();
     77  1.1  christos   return NULL;
     78  1.1  christos }
     79  1.1  christos 
     80  1.6  christos struct syscall *
     81  1.6  christos get_syscalls_by_group (struct gdbarch *gdbarch, const char *group)
     82  1.6  christos {
     83  1.6  christos   syscall_warn_user ();
     84  1.6  christos   return NULL;
     85  1.6  christos }
     86  1.6  christos 
     87  1.6  christos const char **
     88  1.6  christos get_syscall_group_names (struct gdbarch *gdbarch)
     89  1.6  christos {
     90  1.6  christos   syscall_warn_user ();
     91  1.6  christos   return NULL;
     92  1.6  christos }
     93  1.6  christos 
     94  1.1  christos #else /* ! HAVE_LIBEXPAT */
     95  1.1  christos 
     96  1.1  christos /* Structure which describes a syscall.  */
     97  1.1  christos typedef struct syscall_desc
     98  1.1  christos {
     99  1.1  christos   /* The syscall number.  */
    100  1.1  christos 
    101  1.1  christos   int number;
    102  1.1  christos 
    103  1.1  christos   /* The syscall name.  */
    104  1.1  christos 
    105  1.1  christos   char *name;
    106  1.1  christos } *syscall_desc_p;
    107  1.1  christos DEF_VEC_P(syscall_desc_p);
    108  1.1  christos 
    109  1.6  christos /* Structure of a syscall group.  */
    110  1.6  christos typedef struct syscall_group_desc
    111  1.6  christos {
    112  1.6  christos   /* The group name.  */
    113  1.6  christos 
    114  1.6  christos   char *name;
    115  1.6  christos 
    116  1.6  christos   /* The syscalls that are part of the group.  */
    117  1.6  christos 
    118  1.6  christos   VEC(syscall_desc_p) *syscalls;
    119  1.6  christos } *syscall_group_desc_p;
    120  1.6  christos DEF_VEC_P(syscall_group_desc_p);
    121  1.6  christos 
    122  1.1  christos /* Structure that represents syscalls information.  */
    123  1.1  christos struct syscalls_info
    124  1.1  christos {
    125  1.1  christos   /* The syscalls.  */
    126  1.1  christos 
    127  1.1  christos   VEC(syscall_desc_p) *syscalls;
    128  1.3  christos 
    129  1.6  christos   /* The syscall groups.  */
    130  1.6  christos 
    131  1.6  christos   VEC(syscall_group_desc_p) *groups;
    132  1.6  christos 
    133  1.3  christos   /* Variable that will hold the last known data-directory.  This is
    134  1.3  christos      useful to know whether we should re-read the XML info for the
    135  1.3  christos      target.  */
    136  1.3  christos 
    137  1.3  christos   char *my_gdb_datadir;
    138  1.1  christos };
    139  1.1  christos 
    140  1.1  christos /* Callback data for syscall information parsing.  */
    141  1.1  christos struct syscall_parsing_data
    142  1.1  christos {
    143  1.1  christos   /* The syscalls_info we are building.  */
    144  1.1  christos 
    145  1.3  christos   struct syscalls_info *syscalls_info;
    146  1.1  christos };
    147  1.1  christos 
    148  1.1  christos static struct syscalls_info *
    149  1.1  christos allocate_syscalls_info (void)
    150  1.1  christos {
    151  1.3  christos   return XCNEW (struct syscalls_info);
    152  1.1  christos }
    153  1.1  christos 
    154  1.1  christos static void
    155  1.3  christos syscalls_info_free_syscalls_desc (struct syscall_desc *sd)
    156  1.1  christos {
    157  1.1  christos   xfree (sd->name);
    158  1.1  christos }
    159  1.1  christos 
    160  1.6  christos /* Free syscall_group_desc members but not the structure itself.  */
    161  1.6  christos 
    162  1.6  christos static void
    163  1.6  christos syscalls_info_free_syscall_group_desc (struct syscall_group_desc *sd)
    164  1.6  christos {
    165  1.6  christos   VEC_free (syscall_desc_p, sd->syscalls);
    166  1.6  christos   xfree (sd->name);
    167  1.6  christos }
    168  1.6  christos 
    169  1.1  christos static void
    170  1.1  christos free_syscalls_info (void *arg)
    171  1.1  christos {
    172  1.6  christos   struct syscalls_info *syscalls_info = (struct syscalls_info *) arg;
    173  1.1  christos   struct syscall_desc *sysdesc;
    174  1.6  christos   struct syscall_group_desc *groupdesc;
    175  1.1  christos   int i;
    176  1.1  christos 
    177  1.3  christos   xfree (syscalls_info->my_gdb_datadir);
    178  1.3  christos 
    179  1.3  christos   if (syscalls_info->syscalls != NULL)
    180  1.3  christos     {
    181  1.3  christos       for (i = 0;
    182  1.3  christos 	   VEC_iterate (syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
    183  1.3  christos 	   i++)
    184  1.3  christos 	syscalls_info_free_syscalls_desc (sysdesc);
    185  1.3  christos       VEC_free (syscall_desc_p, syscalls_info->syscalls);
    186  1.3  christos     }
    187  1.1  christos 
    188  1.6  christos   if (syscalls_info->groups != NULL)
    189  1.6  christos     {
    190  1.6  christos       for (i = 0;
    191  1.6  christos 	   VEC_iterate (syscall_group_desc_p,
    192  1.6  christos 			syscalls_info->groups, i, groupdesc);
    193  1.6  christos 	   i++)
    194  1.6  christos 	syscalls_info_free_syscall_group_desc (groupdesc);
    195  1.6  christos 
    196  1.6  christos       VEC_free (syscall_group_desc_p, syscalls_info->groups);
    197  1.6  christos     }
    198  1.6  christos 
    199  1.3  christos   xfree (syscalls_info);
    200  1.1  christos }
    201  1.1  christos 
    202  1.1  christos static struct cleanup *
    203  1.3  christos make_cleanup_free_syscalls_info (struct syscalls_info *syscalls_info)
    204  1.1  christos {
    205  1.3  christos   return make_cleanup (free_syscalls_info, syscalls_info);
    206  1.1  christos }
    207  1.1  christos 
    208  1.6  christos /* Create a new syscall group.  Return pointer to the
    209  1.6  christos    syscall_group_desc structure that represents the new group.  */
    210  1.6  christos 
    211  1.6  christos static struct syscall_group_desc *
    212  1.6  christos syscall_group_create_syscall_group_desc (struct syscalls_info *syscalls_info,
    213  1.6  christos 					 const char *group)
    214  1.6  christos {
    215  1.6  christos   struct syscall_group_desc *groupdesc = XCNEW (struct syscall_group_desc);
    216  1.6  christos 
    217  1.6  christos   groupdesc->name = xstrdup (group);
    218  1.6  christos 
    219  1.6  christos   VEC_safe_push (syscall_group_desc_p, syscalls_info->groups, groupdesc);
    220  1.6  christos 
    221  1.6  christos   return groupdesc;
    222  1.6  christos }
    223  1.6  christos 
    224  1.6  christos /* Add a syscall to the group.  If group doesn't exist, create it.  */
    225  1.6  christos 
    226  1.6  christos static void
    227  1.6  christos syscall_group_add_syscall (struct syscalls_info *syscalls_info,
    228  1.6  christos 			   struct syscall_desc *syscall,
    229  1.6  christos 			   const char *group)
    230  1.6  christos {
    231  1.6  christos   struct syscall_group_desc *groupdesc = NULL;
    232  1.6  christos   int i;
    233  1.6  christos 
    234  1.6  christos   /* Search for an existing group.  */
    235  1.6  christos   for (i = 0;
    236  1.6  christos        VEC_iterate (syscall_group_desc_p, syscalls_info->groups, i, groupdesc);
    237  1.6  christos        i++)
    238  1.6  christos     {
    239  1.6  christos       if (strcmp (groupdesc->name, group) == 0)
    240  1.6  christos 	break;
    241  1.6  christos     }
    242  1.6  christos 
    243  1.6  christos   if (groupdesc == NULL)
    244  1.6  christos     {
    245  1.6  christos       /* No group was found with this name.  We must create a new
    246  1.6  christos 	 one.  */
    247  1.6  christos       groupdesc = syscall_group_create_syscall_group_desc (syscalls_info,
    248  1.6  christos 							   group);
    249  1.6  christos     }
    250  1.6  christos 
    251  1.6  christos   VEC_safe_push (syscall_desc_p, groupdesc->syscalls, syscall);
    252  1.6  christos }
    253  1.6  christos 
    254  1.1  christos static void
    255  1.3  christos syscall_create_syscall_desc (struct syscalls_info *syscalls_info,
    256  1.6  christos 			     const char *name, int number,
    257  1.6  christos 			     char *groups)
    258  1.1  christos {
    259  1.3  christos   struct syscall_desc *sysdesc = XCNEW (struct syscall_desc);
    260  1.6  christos   char *group;
    261  1.1  christos 
    262  1.1  christos   sysdesc->name = xstrdup (name);
    263  1.1  christos   sysdesc->number = number;
    264  1.1  christos 
    265  1.3  christos   VEC_safe_push (syscall_desc_p, syscalls_info->syscalls, sysdesc);
    266  1.6  christos 
    267  1.6  christos   /*  Add syscall to its groups.  */
    268  1.6  christos   if (groups != NULL)
    269  1.6  christos     {
    270  1.6  christos       for (group = strtok (groups, ",");
    271  1.6  christos 	   group != NULL;
    272  1.6  christos 	   group = strtok (NULL, ","))
    273  1.6  christos 	syscall_group_add_syscall (syscalls_info, sysdesc, group);
    274  1.6  christos     }
    275  1.1  christos }
    276  1.1  christos 
    277  1.1  christos /* Handle the start of a <syscall> element.  */
    278  1.1  christos static void
    279  1.1  christos syscall_start_syscall (struct gdb_xml_parser *parser,
    280  1.1  christos                        const struct gdb_xml_element *element,
    281  1.1  christos                        void *user_data, VEC(gdb_xml_value_s) *attributes)
    282  1.1  christos {
    283  1.6  christos   struct syscall_parsing_data *data = (struct syscall_parsing_data *) user_data;
    284  1.1  christos   struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
    285  1.1  christos   int len, i;
    286  1.1  christos   /* syscall info.  */
    287  1.1  christos   char *name = NULL;
    288  1.1  christos   int number = 0;
    289  1.6  christos   char *groups = NULL;
    290  1.1  christos 
    291  1.1  christos   len = VEC_length (gdb_xml_value_s, attributes);
    292  1.1  christos 
    293  1.1  christos   for (i = 0; i < len; i++)
    294  1.1  christos     {
    295  1.1  christos       if (strcmp (attrs[i].name, "name") == 0)
    296  1.6  christos         name = (char *) attrs[i].value;
    297  1.1  christos       else if (strcmp (attrs[i].name, "number") == 0)
    298  1.1  christos         number = * (ULONGEST *) attrs[i].value;
    299  1.6  christos       else if (strcmp (attrs[i].name, "groups") == 0)
    300  1.6  christos         groups = (char *) attrs[i].value;
    301  1.1  christos       else
    302  1.1  christos         internal_error (__FILE__, __LINE__,
    303  1.1  christos                         _("Unknown attribute name '%s'."), attrs[i].name);
    304  1.1  christos     }
    305  1.1  christos 
    306  1.1  christos   gdb_assert (name);
    307  1.6  christos   syscall_create_syscall_desc (data->syscalls_info, name, number, groups);
    308  1.1  christos }
    309  1.1  christos 
    310  1.1  christos 
    311  1.1  christos /* The elements and attributes of an XML syscall document.  */
    312  1.1  christos static const struct gdb_xml_attribute syscall_attr[] = {
    313  1.1  christos   { "number", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
    314  1.1  christos   { "name", GDB_XML_AF_NONE, NULL, NULL },
    315  1.6  christos   { "groups", GDB_XML_AF_OPTIONAL, NULL, NULL },
    316  1.1  christos   { NULL, GDB_XML_AF_NONE, NULL, NULL }
    317  1.1  christos };
    318  1.1  christos 
    319  1.1  christos static const struct gdb_xml_element syscalls_info_children[] = {
    320  1.1  christos   { "syscall", syscall_attr, NULL,
    321  1.1  christos     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
    322  1.1  christos     syscall_start_syscall, NULL },
    323  1.1  christos   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
    324  1.1  christos };
    325  1.1  christos 
    326  1.1  christos static const struct gdb_xml_element syselements[] = {
    327  1.1  christos   { "syscalls_info", NULL, syscalls_info_children,
    328  1.1  christos     GDB_XML_EF_NONE, NULL, NULL },
    329  1.1  christos   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
    330  1.1  christos };
    331  1.1  christos 
    332  1.1  christos static struct syscalls_info *
    333  1.1  christos syscall_parse_xml (const char *document, xml_fetch_another fetcher,
    334  1.1  christos                    void *fetcher_baton)
    335  1.1  christos {
    336  1.1  christos   struct cleanup *result_cleanup;
    337  1.1  christos   struct syscall_parsing_data data;
    338  1.1  christos 
    339  1.3  christos   data.syscalls_info = allocate_syscalls_info ();
    340  1.3  christos   result_cleanup = make_cleanup_free_syscalls_info (data.syscalls_info);
    341  1.1  christos 
    342  1.1  christos   if (gdb_xml_parse_quick (_("syscalls info"), NULL,
    343  1.1  christos 			   syselements, document, &data) == 0)
    344  1.1  christos     {
    345  1.1  christos       /* Parsed successfully.  */
    346  1.1  christos       discard_cleanups (result_cleanup);
    347  1.3  christos       return data.syscalls_info;
    348  1.1  christos     }
    349  1.1  christos   else
    350  1.1  christos     {
    351  1.1  christos       warning (_("Could not load XML syscalls info; ignoring"));
    352  1.1  christos       do_cleanups (result_cleanup);
    353  1.1  christos       return NULL;
    354  1.1  christos     }
    355  1.1  christos }
    356  1.1  christos 
    357  1.1  christos /* Function responsible for initializing the information
    358  1.1  christos    about the syscalls.  It reads the XML file and fills the
    359  1.1  christos    struct syscalls_info with the values.
    360  1.1  christos 
    361  1.1  christos    Returns the struct syscalls_info if the file is valid, NULL otherwise.  */
    362  1.3  christos static struct syscalls_info *
    363  1.1  christos xml_init_syscalls_info (const char *filename)
    364  1.1  christos {
    365  1.1  christos   char *full_file;
    366  1.1  christos   char *dirname;
    367  1.3  christos   struct syscalls_info *syscalls_info;
    368  1.1  christos   struct cleanup *back_to;
    369  1.1  christos 
    370  1.1  christos   full_file = xml_fetch_content_from_file (filename, gdb_datadir);
    371  1.1  christos   if (full_file == NULL)
    372  1.1  christos     return NULL;
    373  1.1  christos 
    374  1.1  christos   back_to = make_cleanup (xfree, full_file);
    375  1.1  christos 
    376  1.1  christos   dirname = ldirname (filename);
    377  1.1  christos   if (dirname != NULL)
    378  1.1  christos     make_cleanup (xfree, dirname);
    379  1.1  christos 
    380  1.3  christos   syscalls_info = syscall_parse_xml (full_file,
    381  1.3  christos 				     xml_fetch_content_from_file, dirname);
    382  1.1  christos   do_cleanups (back_to);
    383  1.1  christos 
    384  1.3  christos   return syscalls_info;
    385  1.1  christos }
    386  1.1  christos 
    387  1.1  christos /* Initializes the syscalls_info structure according to the
    388  1.1  christos    architecture.  */
    389  1.1  christos static void
    390  1.3  christos init_syscalls_info (struct gdbarch *gdbarch)
    391  1.1  christos {
    392  1.3  christos   struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
    393  1.3  christos   const char *xml_syscall_file = gdbarch_xml_syscall_file (gdbarch);
    394  1.3  christos 
    395  1.1  christos   /* Should we re-read the XML info for this target?  */
    396  1.3  christos   if (syscalls_info != NULL && syscalls_info->my_gdb_datadir != NULL
    397  1.3  christos       && filename_cmp (syscalls_info->my_gdb_datadir, gdb_datadir) != 0)
    398  1.1  christos     {
    399  1.1  christos       /* The data-directory changed from the last time we used it.
    400  1.1  christos 	 It means that we have to re-read the XML info.  */
    401  1.3  christos       free_syscalls_info (syscalls_info);
    402  1.3  christos       syscalls_info = NULL;
    403  1.3  christos       set_gdbarch_syscalls_info (gdbarch, NULL);
    404  1.1  christos     }
    405  1.1  christos 
    406  1.3  christos   /* Did we succeed at initializing this?  */
    407  1.3  christos   if (syscalls_info != NULL)
    408  1.1  christos     return;
    409  1.1  christos 
    410  1.3  christos   syscalls_info = xml_init_syscalls_info (xml_syscall_file);
    411  1.1  christos 
    412  1.3  christos   /* If there was some error reading the XML file, we initialize
    413  1.3  christos      gdbarch->syscalls_info anyway, in order to store information
    414  1.3  christos      about our attempt.  */
    415  1.3  christos   if (syscalls_info == NULL)
    416  1.3  christos     syscalls_info = allocate_syscalls_info ();
    417  1.1  christos 
    418  1.3  christos   if (syscalls_info->syscalls == NULL)
    419  1.1  christos     {
    420  1.3  christos       if (xml_syscall_file != NULL)
    421  1.1  christos 	warning (_("Could not load the syscall XML file `%s/%s'."),
    422  1.1  christos 		 gdb_datadir, xml_syscall_file);
    423  1.1  christos       else
    424  1.1  christos 	warning (_("There is no XML file to open."));
    425  1.1  christos 
    426  1.1  christos       warning (_("GDB will not be able to display "
    427  1.1  christos 		 "syscall names nor to verify if\n"
    428  1.1  christos 		 "any provided syscall numbers are valid."));
    429  1.1  christos     }
    430  1.1  christos 
    431  1.1  christos   /* Saving the data-directory used to read this XML info.  */
    432  1.3  christos   syscalls_info->my_gdb_datadir = xstrdup (gdb_datadir);
    433  1.3  christos 
    434  1.3  christos   set_gdbarch_syscalls_info (gdbarch, syscalls_info);
    435  1.1  christos }
    436  1.1  christos 
    437  1.6  christos /* Search for a syscall group by its name.  Return syscall_group_desc
    438  1.6  christos    structure for the group if found or NULL otherwise.  */
    439  1.6  christos 
    440  1.6  christos static struct syscall_group_desc *
    441  1.6  christos syscall_group_get_group_by_name (const struct syscalls_info *syscalls_info,
    442  1.6  christos 				 const char *group)
    443  1.6  christos {
    444  1.6  christos   struct syscall_group_desc *groupdesc;
    445  1.6  christos   int i;
    446  1.6  christos 
    447  1.6  christos   if (syscalls_info == NULL)
    448  1.6  christos     return NULL;
    449  1.6  christos 
    450  1.6  christos   if (group == NULL)
    451  1.6  christos     return NULL;
    452  1.6  christos 
    453  1.6  christos    /* Search for existing group.  */
    454  1.6  christos   for (i = 0;
    455  1.6  christos        VEC_iterate (syscall_group_desc_p, syscalls_info->groups, i, groupdesc);
    456  1.6  christos        i++)
    457  1.6  christos     {
    458  1.6  christos       if (strcmp (groupdesc->name, group) == 0)
    459  1.6  christos 	return groupdesc;
    460  1.6  christos     }
    461  1.6  christos 
    462  1.6  christos   return NULL;
    463  1.6  christos }
    464  1.6  christos 
    465  1.1  christos static int
    466  1.3  christos xml_get_syscall_number (struct gdbarch *gdbarch,
    467  1.1  christos                         const char *syscall_name)
    468  1.1  christos {
    469  1.3  christos   struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
    470  1.1  christos   struct syscall_desc *sysdesc;
    471  1.1  christos   int i;
    472  1.1  christos 
    473  1.3  christos   if (syscalls_info == NULL
    474  1.1  christos       || syscall_name == NULL)
    475  1.1  christos     return UNKNOWN_SYSCALL;
    476  1.1  christos 
    477  1.1  christos   for (i = 0;
    478  1.3  christos        VEC_iterate(syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
    479  1.1  christos        i++)
    480  1.1  christos     if (strcmp (sysdesc->name, syscall_name) == 0)
    481  1.1  christos       return sysdesc->number;
    482  1.1  christos 
    483  1.1  christos   return UNKNOWN_SYSCALL;
    484  1.1  christos }
    485  1.1  christos 
    486  1.1  christos static const char *
    487  1.3  christos xml_get_syscall_name (struct gdbarch *gdbarch,
    488  1.1  christos                       int syscall_number)
    489  1.1  christos {
    490  1.3  christos   struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
    491  1.1  christos   struct syscall_desc *sysdesc;
    492  1.1  christos   int i;
    493  1.1  christos 
    494  1.3  christos   if (syscalls_info == NULL
    495  1.1  christos       || syscall_number < 0)
    496  1.1  christos     return NULL;
    497  1.1  christos 
    498  1.1  christos   for (i = 0;
    499  1.3  christos        VEC_iterate(syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
    500  1.1  christos        i++)
    501  1.1  christos     if (sysdesc->number == syscall_number)
    502  1.1  christos       return sysdesc->name;
    503  1.1  christos 
    504  1.1  christos   return NULL;
    505  1.1  christos }
    506  1.1  christos 
    507  1.1  christos static const char **
    508  1.3  christos xml_list_of_syscalls (struct gdbarch *gdbarch)
    509  1.1  christos {
    510  1.3  christos   struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
    511  1.1  christos   struct syscall_desc *sysdesc;
    512  1.1  christos   const char **names = NULL;
    513  1.1  christos   int nsyscalls;
    514  1.1  christos   int i;
    515  1.1  christos 
    516  1.3  christos   if (syscalls_info == NULL)
    517  1.1  christos     return NULL;
    518  1.1  christos 
    519  1.3  christos   nsyscalls = VEC_length (syscall_desc_p, syscalls_info->syscalls);
    520  1.6  christos   names = XNEWVEC (const char *, nsyscalls + 1);
    521  1.1  christos 
    522  1.1  christos   for (i = 0;
    523  1.3  christos        VEC_iterate (syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
    524  1.1  christos        i++)
    525  1.1  christos     names[i] = sysdesc->name;
    526  1.1  christos 
    527  1.1  christos   names[i] = NULL;
    528  1.1  christos 
    529  1.1  christos   return names;
    530  1.1  christos }
    531  1.1  christos 
    532  1.6  christos /* Iterate over the syscall_group_desc element to return a list of
    533  1.6  christos    syscalls that are part of the given group, terminated by an empty
    534  1.6  christos    element.  If the syscall group doesn't exist, return NULL.  */
    535  1.6  christos 
    536  1.6  christos static struct syscall *
    537  1.6  christos xml_list_syscalls_by_group (struct gdbarch *gdbarch, const char *group)
    538  1.6  christos {
    539  1.6  christos   struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
    540  1.6  christos   struct syscall_group_desc *groupdesc;
    541  1.6  christos   struct syscall_desc *sysdesc;
    542  1.6  christos   struct syscall *syscalls = NULL;
    543  1.6  christos   int nsyscalls;
    544  1.6  christos   int i;
    545  1.6  christos 
    546  1.6  christos   if (syscalls_info == NULL)
    547  1.6  christos     return NULL;
    548  1.6  christos 
    549  1.6  christos   groupdesc = syscall_group_get_group_by_name (syscalls_info, group);
    550  1.6  christos   if (groupdesc == NULL)
    551  1.6  christos     return NULL;
    552  1.6  christos 
    553  1.6  christos   nsyscalls = VEC_length (syscall_desc_p, groupdesc->syscalls);
    554  1.6  christos   syscalls = (struct syscall*) xmalloc ((nsyscalls + 1)
    555  1.6  christos 					* sizeof (struct syscall));
    556  1.6  christos 
    557  1.6  christos   for (i = 0;
    558  1.6  christos        VEC_iterate (syscall_desc_p, groupdesc->syscalls, i, sysdesc);
    559  1.6  christos        i++)
    560  1.6  christos     {
    561  1.6  christos       syscalls[i].name = sysdesc->name;
    562  1.6  christos       syscalls[i].number = sysdesc->number;
    563  1.6  christos     }
    564  1.6  christos 
    565  1.6  christos   /* Add final element marker.  */
    566  1.6  christos   syscalls[i].name = NULL;
    567  1.6  christos   syscalls[i].number = 0;
    568  1.6  christos 
    569  1.6  christos   return syscalls;
    570  1.6  christos }
    571  1.6  christos 
    572  1.6  christos /* Return a NULL terminated list of syscall groups or an empty list, if
    573  1.6  christos    no syscall group is available.  Return NULL, if there is no syscall
    574  1.6  christos    information available.  */
    575  1.6  christos 
    576  1.6  christos static const char **
    577  1.6  christos xml_list_of_groups (struct gdbarch *gdbarch)
    578  1.6  christos {
    579  1.6  christos   struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
    580  1.6  christos   struct syscall_group_desc *groupdesc;
    581  1.6  christos   const char **names = NULL;
    582  1.6  christos   int i;
    583  1.6  christos   int ngroups;
    584  1.6  christos 
    585  1.6  christos   if (syscalls_info == NULL)
    586  1.6  christos     return NULL;
    587  1.6  christos 
    588  1.6  christos   ngroups = VEC_length (syscall_group_desc_p, syscalls_info->groups);
    589  1.6  christos   names = (const char**) xmalloc ((ngroups + 1) * sizeof (char *));
    590  1.6  christos 
    591  1.6  christos   for (i = 0;
    592  1.6  christos        VEC_iterate (syscall_group_desc_p, syscalls_info->groups, i, groupdesc);
    593  1.6  christos        i++)
    594  1.6  christos     names[i] = groupdesc->name;
    595  1.6  christos 
    596  1.6  christos   names[i] = NULL;
    597  1.6  christos 
    598  1.6  christos   return names;
    599  1.6  christos }
    600  1.6  christos 
    601  1.1  christos void
    602  1.3  christos set_xml_syscall_file_name (struct gdbarch *gdbarch, const char *name)
    603  1.1  christos {
    604  1.3  christos   set_gdbarch_xml_syscall_file (gdbarch, name);
    605  1.1  christos }
    606  1.1  christos 
    607  1.1  christos void
    608  1.3  christos get_syscall_by_number (struct gdbarch *gdbarch,
    609  1.3  christos 		       int syscall_number, struct syscall *s)
    610  1.1  christos {
    611  1.3  christos   init_syscalls_info (gdbarch);
    612  1.1  christos 
    613  1.1  christos   s->number = syscall_number;
    614  1.3  christos   s->name = xml_get_syscall_name (gdbarch, syscall_number);
    615  1.1  christos }
    616  1.1  christos 
    617  1.1  christos void
    618  1.3  christos get_syscall_by_name (struct gdbarch *gdbarch,
    619  1.3  christos 		     const char *syscall_name, struct syscall *s)
    620  1.1  christos {
    621  1.3  christos   init_syscalls_info (gdbarch);
    622  1.1  christos 
    623  1.3  christos   s->number = xml_get_syscall_number (gdbarch, syscall_name);
    624  1.1  christos   s->name = syscall_name;
    625  1.1  christos }
    626  1.1  christos 
    627  1.1  christos const char **
    628  1.3  christos get_syscall_names (struct gdbarch *gdbarch)
    629  1.1  christos {
    630  1.3  christos   init_syscalls_info (gdbarch);
    631  1.1  christos 
    632  1.3  christos   return xml_list_of_syscalls (gdbarch);
    633  1.1  christos }
    634  1.1  christos 
    635  1.6  christos /* See comment in xml-syscall.h.  */
    636  1.6  christos 
    637  1.6  christos struct syscall *
    638  1.6  christos get_syscalls_by_group (struct gdbarch *gdbarch, const char *group)
    639  1.6  christos {
    640  1.6  christos   init_syscalls_info (gdbarch);
    641  1.6  christos 
    642  1.6  christos   return xml_list_syscalls_by_group (gdbarch, group);
    643  1.6  christos }
    644  1.6  christos 
    645  1.6  christos /* See comment in xml-syscall.h.  */
    646  1.6  christos 
    647  1.6  christos const char **
    648  1.6  christos get_syscall_group_names (struct gdbarch *gdbarch)
    649  1.6  christos {
    650  1.6  christos   init_syscalls_info (gdbarch);
    651  1.6  christos 
    652  1.6  christos   return xml_list_of_groups (gdbarch);
    653  1.6  christos }
    654  1.6  christos 
    655  1.1  christos #endif /* ! HAVE_LIBEXPAT */
    656