gdb/xml-syscall.c - gdb

Global variables defined

Data types defined

Functions defined

Source code

  1. /* Functions that provide the mechanism to parse a syscall XML file
  2.    and get its values.

  3.    Copyright (C) 2009-2015 Free Software Foundation, Inc.

  4.    This file is part of GDB.

  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 3 of the License, or
  8.    (at your option) any later version.

  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.

  13.    You should have received a copy of the GNU General Public License
  14.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  15. #include "defs.h"
  16. #include "gdbtypes.h"
  17. #include "xml-support.h"
  18. #include "xml-syscall.h"
  19. #include "gdbarch.h"

  20. /* For the struct syscall definition.  */
  21. #include "target.h"

  22. #include "filenames.h"

  23. #ifndef HAVE_LIBEXPAT

  24. /* Dummy functions to indicate that there's no support for fetching
  25.    syscalls information.  */

  26. static void
  27. syscall_warn_user (void)
  28. {
  29.   static int have_warned = 0;
  30.   if (!have_warned)
  31.     {
  32.       have_warned = 1;
  33.       warning (_("Can not parse XML syscalls information; XML support was "
  34.                  "disabled at compile time."));
  35.     }
  36. }

  37. void
  38. set_xml_syscall_file_name (struct gdbarch *gdbarch, const char *name)
  39. {
  40.   return;
  41. }

  42. void
  43. get_syscall_by_number (struct gdbarch *gdbarch,
  44.                        int syscall_number, struct syscall *s)
  45. {
  46.   syscall_warn_user ();
  47.   s->number = syscall_number;
  48.   s->name = NULL;
  49. }

  50. void
  51. get_syscall_by_name (struct gdbarch *gdbarch, const char *syscall_name,
  52.                      struct syscall *s)
  53. {
  54.   syscall_warn_user ();
  55.   s->number = UNKNOWN_SYSCALL;
  56.   s->name = syscall_name;
  57. }

  58. const char **
  59. get_syscall_names (struct gdbarch *gdbarch)
  60. {
  61.   syscall_warn_user ();
  62.   return NULL;
  63. }

  64. #else /* ! HAVE_LIBEXPAT */

  65. /* Structure which describes a syscall.  */
  66. typedef struct syscall_desc
  67. {
  68.   /* The syscall number.  */

  69.   int number;

  70.   /* The syscall name.  */

  71.   char *name;
  72. } *syscall_desc_p;
  73. DEF_VEC_P(syscall_desc_p);

  74. /* Structure that represents syscalls information.  */
  75. struct syscalls_info
  76. {
  77.   /* The syscalls.  */

  78.   VEC(syscall_desc_p) *syscalls;

  79.   /* Variable that will hold the last known data-directory.  This is
  80.      useful to know whether we should re-read the XML info for the
  81.      target.  */

  82.   char *my_gdb_datadir;
  83. };

  84. /* Callback data for syscall information parsing.  */
  85. struct syscall_parsing_data
  86. {
  87.   /* The syscalls_info we are building.  */

  88.   struct syscalls_info *syscalls_info;
  89. };

  90. static struct syscalls_info *
  91. allocate_syscalls_info (void)
  92. {
  93.   return XCNEW (struct syscalls_info);
  94. }

  95. static void
  96. syscalls_info_free_syscalls_desc (struct syscall_desc *sd)
  97. {
  98.   xfree (sd->name);
  99. }

  100. static void
  101. free_syscalls_info (void *arg)
  102. {
  103.   struct syscalls_info *syscalls_info = arg;
  104.   struct syscall_desc *sysdesc;
  105.   int i;

  106.   xfree (syscalls_info->my_gdb_datadir);

  107.   if (syscalls_info->syscalls != NULL)
  108.     {
  109.       for (i = 0;
  110.            VEC_iterate (syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
  111.            i++)
  112.         syscalls_info_free_syscalls_desc (sysdesc);
  113.       VEC_free (syscall_desc_p, syscalls_info->syscalls);
  114.     }

  115.   xfree (syscalls_info);
  116. }

  117. static struct cleanup *
  118. make_cleanup_free_syscalls_info (struct syscalls_info *syscalls_info)
  119. {
  120.   return make_cleanup (free_syscalls_info, syscalls_info);
  121. }

  122. static void
  123. syscall_create_syscall_desc (struct syscalls_info *syscalls_info,
  124.                              const char *name, int number)
  125. {
  126.   struct syscall_desc *sysdesc = XCNEW (struct syscall_desc);

  127.   sysdesc->name = xstrdup (name);
  128.   sysdesc->number = number;

  129.   VEC_safe_push (syscall_desc_p, syscalls_info->syscalls, sysdesc);
  130. }

  131. /* Handle the start of a <syscall> element.  */
  132. static void
  133. syscall_start_syscall (struct gdb_xml_parser *parser,
  134.                        const struct gdb_xml_element *element,
  135.                        void *user_data, VEC(gdb_xml_value_s) *attributes)
  136. {
  137.   struct syscall_parsing_data *data = user_data;
  138.   struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
  139.   int len, i;
  140.   /* syscall info.  */
  141.   char *name = NULL;
  142.   int number = 0;

  143.   len = VEC_length (gdb_xml_value_s, attributes);

  144.   for (i = 0; i < len; i++)
  145.     {
  146.       if (strcmp (attrs[i].name, "name") == 0)
  147.         name = attrs[i].value;
  148.       else if (strcmp (attrs[i].name, "number") == 0)
  149.         number = * (ULONGEST *) attrs[i].value;
  150.       else
  151.         internal_error (__FILE__, __LINE__,
  152.                         _("Unknown attribute name '%s'."), attrs[i].name);
  153.     }

  154.   gdb_assert (name);
  155.   syscall_create_syscall_desc (data->syscalls_info, name, number);
  156. }


  157. /* The elements and attributes of an XML syscall document.  */
  158. static const struct gdb_xml_attribute syscall_attr[] = {
  159.   { "number", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
  160.   { "name", GDB_XML_AF_NONE, NULL, NULL },
  161.   { NULL, GDB_XML_AF_NONE, NULL, NULL }
  162. };

  163. static const struct gdb_xml_element syscalls_info_children[] = {
  164.   { "syscall", syscall_attr, NULL,
  165.     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
  166.     syscall_start_syscall, NULL },
  167.   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
  168. };

  169. static const struct gdb_xml_element syselements[] = {
  170.   { "syscalls_info", NULL, syscalls_info_children,
  171.     GDB_XML_EF_NONE, NULL, NULL },
  172.   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
  173. };

  174. static struct syscalls_info *
  175. syscall_parse_xml (const char *document, xml_fetch_another fetcher,
  176.                    void *fetcher_baton)
  177. {
  178.   struct cleanup *result_cleanup;
  179.   struct syscall_parsing_data data;

  180.   data.syscalls_info = allocate_syscalls_info ();
  181.   result_cleanup = make_cleanup_free_syscalls_info (data.syscalls_info);

  182.   if (gdb_xml_parse_quick (_("syscalls info"), NULL,
  183.                            syselements, document, &data) == 0)
  184.     {
  185.       /* Parsed successfully.  */
  186.       discard_cleanups (result_cleanup);
  187.       return data.syscalls_info;
  188.     }
  189.   else
  190.     {
  191.       warning (_("Could not load XML syscalls info; ignoring"));
  192.       do_cleanups (result_cleanup);
  193.       return NULL;
  194.     }
  195. }

  196. /* Function responsible for initializing the information
  197.    about the syscalls.  It reads the XML file and fills the
  198.    struct syscalls_info with the values.

  199.    Returns the struct syscalls_info if the file is valid, NULL otherwise.  */
  200. static struct syscalls_info *
  201. xml_init_syscalls_info (const char *filename)
  202. {
  203.   char *full_file;
  204.   char *dirname;
  205.   struct syscalls_info *syscalls_info;
  206.   struct cleanup *back_to;

  207.   full_file = xml_fetch_content_from_file (filename, gdb_datadir);
  208.   if (full_file == NULL)
  209.     return NULL;

  210.   back_to = make_cleanup (xfree, full_file);

  211.   dirname = ldirname (filename);
  212.   if (dirname != NULL)
  213.     make_cleanup (xfree, dirname);

  214.   syscalls_info = syscall_parse_xml (full_file,
  215.                                      xml_fetch_content_from_file, dirname);
  216.   do_cleanups (back_to);

  217.   return syscalls_info;
  218. }

  219. /* Initializes the syscalls_info structure according to the
  220.    architecture.  */
  221. static void
  222. init_syscalls_info (struct gdbarch *gdbarch)
  223. {
  224.   struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
  225.   const char *xml_syscall_file = gdbarch_xml_syscall_file (gdbarch);

  226.   /* Should we re-read the XML info for this target?  */
  227.   if (syscalls_info != NULL && syscalls_info->my_gdb_datadir != NULL
  228.       && filename_cmp (syscalls_info->my_gdb_datadir, gdb_datadir) != 0)
  229.     {
  230.       /* The data-directory changed from the last time we used it.
  231.          It means that we have to re-read the XML info.  */
  232.       free_syscalls_info (syscalls_info);
  233.       syscalls_info = NULL;
  234.       set_gdbarch_syscalls_info (gdbarch, NULL);
  235.     }

  236.   /* Did we succeed at initializing this?  */
  237.   if (syscalls_info != NULL)
  238.     return;

  239.   syscalls_info = xml_init_syscalls_info (xml_syscall_file);

  240.   /* If there was some error reading the XML file, we initialize
  241.      gdbarch->syscalls_info anyway, in order to store information
  242.      about our attempt.  */
  243.   if (syscalls_info == NULL)
  244.     syscalls_info = allocate_syscalls_info ();

  245.   if (syscalls_info->syscalls == NULL)
  246.     {
  247.       if (xml_syscall_file != NULL)
  248.         warning (_("Could not load the syscall XML file `%s/%s'."),
  249.                  gdb_datadir, xml_syscall_file);
  250.       else
  251.         warning (_("There is no XML file to open."));

  252.       warning (_("GDB will not be able to display "
  253.                  "syscall names nor to verify if\n"
  254.                  "any provided syscall numbers are valid."));
  255.     }

  256.   /* Saving the data-directory used to read this XML info.  */
  257.   syscalls_info->my_gdb_datadir = xstrdup (gdb_datadir);

  258.   set_gdbarch_syscalls_info (gdbarch, syscalls_info);
  259. }

  260. static int
  261. xml_get_syscall_number (struct gdbarch *gdbarch,
  262.                         const char *syscall_name)
  263. {
  264.   struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
  265.   struct syscall_desc *sysdesc;
  266.   int i;

  267.   if (syscalls_info == NULL
  268.       || syscall_name == NULL)
  269.     return UNKNOWN_SYSCALL;

  270.   for (i = 0;
  271.        VEC_iterate(syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
  272.        i++)
  273.     if (strcmp (sysdesc->name, syscall_name) == 0)
  274.       return sysdesc->number;

  275.   return UNKNOWN_SYSCALL;
  276. }

  277. static const char *
  278. xml_get_syscall_name (struct gdbarch *gdbarch,
  279.                       int syscall_number)
  280. {
  281.   struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
  282.   struct syscall_desc *sysdesc;
  283.   int i;

  284.   if (syscalls_info == NULL
  285.       || syscall_number < 0)
  286.     return NULL;

  287.   for (i = 0;
  288.        VEC_iterate(syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
  289.        i++)
  290.     if (sysdesc->number == syscall_number)
  291.       return sysdesc->name;

  292.   return NULL;
  293. }

  294. static const char **
  295. xml_list_of_syscalls (struct gdbarch *gdbarch)
  296. {
  297.   struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
  298.   struct syscall_desc *sysdesc;
  299.   const char **names = NULL;
  300.   int nsyscalls;
  301.   int i;

  302.   if (syscalls_info == NULL)
  303.     return NULL;

  304.   nsyscalls = VEC_length (syscall_desc_p, syscalls_info->syscalls);
  305.   names = xmalloc ((nsyscalls + 1) * sizeof (char *));

  306.   for (i = 0;
  307.        VEC_iterate (syscall_desc_p, syscalls_info->syscalls, i, sysdesc);
  308.        i++)
  309.     names[i] = sysdesc->name;

  310.   names[i] = NULL;

  311.   return names;
  312. }

  313. void
  314. set_xml_syscall_file_name (struct gdbarch *gdbarch, const char *name)
  315. {
  316.   set_gdbarch_xml_syscall_file (gdbarch, name);
  317. }

  318. void
  319. get_syscall_by_number (struct gdbarch *gdbarch,
  320.                        int syscall_number, struct syscall *s)
  321. {
  322.   init_syscalls_info (gdbarch);

  323.   s->number = syscall_number;
  324.   s->name = xml_get_syscall_name (gdbarch, syscall_number);
  325. }

  326. void
  327. get_syscall_by_name (struct gdbarch *gdbarch,
  328.                      const char *syscall_name, struct syscall *s)
  329. {
  330.   init_syscalls_info (gdbarch);

  331.   s->number = xml_get_syscall_number (gdbarch, syscall_name);
  332.   s->name = syscall_name;
  333. }

  334. const char **
  335. get_syscall_names (struct gdbarch *gdbarch)
  336. {
  337.   init_syscalls_info (gdbarch);

  338.   return xml_list_of_syscalls (gdbarch);
  339. }

  340. #endif /* ! HAVE_LIBEXPAT */