Re: [PATCH v6 1/5] Implemement support for groups of syscalls in the xml-syscall interface.

Sergio Durigan Junior
2016-05-26T18:22:48Z

On Thursday, May 19 2016, Gabriel Krisman Bertazi wrote:

> This is done by maintaining a list of syscall_group_desc for each
> syscall group inside the syscalls_info structure. Inside each
> syscall_group_desc we have a vector of pointers to the syscalls that are
> part of that group.
>
> gdb/
>
> * syscalls/gdb-syscalls.dtd: Include group attribute to the
> syscall element.
> * xml-syscall.c (get_syscalls_by_group): New.
> (get_syscall_group_names): New.
> (struct syscall_group_desc): New structure to store group data.
> (struct syscalls_info): Include field to store the group list.
> (sysinfo_free_syscall_group_desc): New.
> (free_syscalls_info): Free group list.
> (syscall_group_create_syscall_group_desc): New.
> (syscall_group_add_syscall): New.
> (syscall_create_syscall_desc): Add syscall to its groups.
> (syscall_start_syscall): Load group attribute.
> (syscall_group_get_group_by_name): New.
> (xml_list_syscalls_by_group): New.
> (xml_list_of_groups): New.
> * xml-syscall.h (get_syscalls_by_group): Export function
> to retrieve a list of syscalls filtered by the group name.
> (get_syscall_group_names): Export function to retrieve the list
> of syscall groups.
> ---
> gdb/syscalls/gdb-syscalls.dtd | 3 +-
> gdb/xml-syscall.c | 234 +++++++++++++++++++++++++++++++++++++++++-
> gdb/xml-syscall.h | 16 +++
> 3 files changed, 250 insertions(+), 3 deletions(-)
>
> diff --git a/gdb/syscalls/gdb-syscalls.dtd b/gdb/syscalls/gdb-syscalls.dtd
> index 3deda12..de47d4d 100644
> --- a/gdb/syscalls/gdb-syscalls.dtd
> +++ b/gdb/syscalls/gdb-syscalls.dtd
> @@ -11,4 +11,5 @@
> <!ELEMENT syscall EMPTY>
> <!ATTLIST syscall
> name CDATA #REQUIRED
> - number CDATA #REQUIRED>
> + number CDATA #REQUIRED
> + groups CDATA #IMPLIED>
> diff --git a/gdb/xml-syscall.c b/gdb/xml-syscall.c
> index ceaf750..c7c307e 100644
> --- a/gdb/xml-syscall.c
> +++ b/gdb/xml-syscall.c
> @@ -77,6 +77,20 @@ get_syscall_names (struct gdbarch *gdbarch)
> return NULL;
> }
>
> +struct syscall *
> +get_syscalls_by_group (struct gdbarch *gdbarch, const char *group)
> +{
> + syscall_warn_user ();
> + return NULL;
> +}
> +
> +const char **
> +get_syscall_group_names (struct gdbarch *gdbarch)
> +{
> + syscall_warn_user ();
> + return NULL;
> +}
> +
> #else /* ! HAVE_LIBEXPAT */
>
> /* Structure which describes a syscall. */
> @@ -92,6 +106,19 @@ typedef struct syscall_desc
> } *syscall_desc_p;
> DEF_VEC_P(syscall_desc_p);
>
> +/* Structure of a syscall group. */
> +typedef struct syscall_group_desc
> +{
> + /* The group name. */
> +
> + char *name;
> +
> + /* The syscalls that are part of the group. */
> +
> + VEC(syscall_desc_p) *syscalls;
> +} *syscall_group_desc_p;
> +DEF_VEC_P(syscall_group_desc_p);
> +
> /* Structure that represents syscalls information. */
> struct syscalls_info
> {
> @@ -99,6 +126,10 @@ struct syscalls_info
>
> VEC(syscall_desc_p) *syscalls;
>
> + /* The syscall groups. */
> +
> + VEC(syscall_group_desc_p) *groups;
> +
> /* Variable that will hold the last known data-directory. This is
> useful to know whether we should re-read the XML info for the
> target. */
> @@ -126,11 +157,21 @@ syscalls_info_free_syscalls_desc (struct syscall_desc *sd)
> xfree (sd->name);
> }
>
> +/* Free syscall_group_desc members but not the structure itself. */
> +
> +static void
> +syscalls_info_free_syscall_group_desc (struct syscall_group_desc *sd)
> +{
> + VEC_free (syscall_desc_p, sd->syscalls);
> + xfree (sd->name);
> +}
> +
> static void
> free_syscalls_info (void *arg)
> {
> struct syscalls_info *syscalls_info = (struct syscalls_info *) arg;
> struct syscall_desc *sysdesc;
> + struct syscall_group_desc *groupdesc;
> int i;
>
> xfree (syscalls_info->my_gdb_datadir);
> @@ -144,6 +185,17 @@ free_syscalls_info (void *arg)
> VEC_free (syscall_desc_p, syscalls_info->syscalls);
> }
>
> + if (syscalls_info->groups != NULL)
> + {
> + for (i = 0;
> + VEC_iterate (syscall_group_desc_p,
> + syscalls_info->groups, i, groupdesc);
> + i++)
> + syscalls_info_free_syscall_group_desc (groupdesc);
> +
> + VEC_free (syscall_group_desc_p, syscalls_info->groups);
> + }
> +
> xfree (syscalls_info);
> }
>
> @@ -153,16 +205,73 @@ make_cleanup_free_syscalls_info (struct syscalls_info *syscalls_info)
> return make_cleanup (free_syscalls_info, syscalls_info);
> }
>
> +/* Create a new syscall group. Return pointer to the
> + syscall_group_desc structure that represents the new group. */
> +
> +static struct syscall_group_desc *
> +syscall_group_create_syscall_group_desc (struct syscalls_info *syscalls_info,
> + const char *group)
> +{
> + struct syscall_group_desc *groupdesc = XCNEW (struct syscall_group_desc);
> +
> + groupdesc->name = xstrdup (group);
> +
> + VEC_safe_push (syscall_group_desc_p, syscalls_info->groups, groupdesc);
> +
> + return groupdesc;
> +}
> +
> +/* Add a syscall to the group. If group doesn't exist, create it. */
> +
> +static void
> +syscall_group_add_syscall (struct syscalls_info *syscalls_info,
> + struct syscall_desc *syscall,
> + const char *group)
> +{
> + struct syscall_group_desc *groupdesc;

Minor nit: assign NULL to this variable here.

> + int i;
> +
> + /* Search for an existing group. */
> + for (i = 0;
> + VEC_iterate (syscall_group_desc_p, syscalls_info->groups, i, groupdesc);
> + i++)
> + {
> + if (strcmp (groupdesc->name, group) == 0)
> + break;
> + }
> +
> + if (groupdesc == NULL)
> + {
> + /* No group was found with this name. We must create a new
> + one. */
> + groupdesc = syscall_group_create_syscall_group_desc (syscalls_info,
> + group);
> + }
> +
> + VEC_safe_push (syscall_desc_p, groupdesc->syscalls, syscall);
> +}
> +
> static void
> syscall_create_syscall_desc (struct syscalls_info *syscalls_info,
> - const char *name, int number)
> + const char *name, int number,
> + char *groups)
> {
> struct syscall_desc *sysdesc = XCNEW (struct syscall_desc);
> + char *group;
>
> sysdesc->name = xstrdup (name);
> sysdesc->number = number;
>
> VEC_safe_push (syscall_desc_p, syscalls_info->syscalls, sysdesc);
> +
> + /* Add syscall to its groups. */
> + if (groups != NULL)
> + {
> + for (group = strtok (groups, ",");
> + group != NULL;
> + group = strtok (NULL, ","))
> + syscall_group_add_syscall (syscalls_info, sysdesc, group);
> + }
> }
>
> /* Handle the start of a <syscall> element. */
> @@ -177,6 +286,7 @@ syscall_start_syscall (struct gdb_xml_parser *parser,
> /* syscall info. */
> char *name = NULL;
> int number = 0;
> + char *groups = NULL;
>
> len = VEC_length (gdb_xml_value_s, attributes);
>
> @@ -186,13 +296,15 @@ syscall_start_syscall (struct gdb_xml_parser *parser,
> name = (char *) attrs[i].value;
> else if (strcmp (attrs[i].name, "number") == 0)
> number = * (ULONGEST *) attrs[i].value;
> + else if (strcmp (attrs[i].name, "groups") == 0)
> + groups = (char *) attrs[i].value;
> else
> internal_error (__FILE__, __LINE__,
> _("Unknown attribute name '%s'."), attrs[i].name);
> }
>
> gdb_assert (name);
> - syscall_create_syscall_desc (data->syscalls_info, name, number);
> + syscall_create_syscall_desc (data->syscalls_info, name, number, groups);
> }
>
>
> @@ -200,6 +312,7 @@ syscall_start_syscall (struct gdb_xml_parser *parser,
> static const struct gdb_xml_attribute syscall_attr[] = {
> { "number", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
> { "name", GDB_XML_AF_NONE, NULL, NULL },
> + { "groups", GDB_XML_AF_OPTIONAL, NULL, NULL },
> { NULL, GDB_XML_AF_NONE, NULL, NULL }
> };
>
> @@ -321,6 +434,34 @@ init_syscalls_info (struct gdbarch *gdbarch)
> set_gdbarch_syscalls_info (gdbarch, syscalls_info);
> }
>
> +/* Search for a syscall group by its name. Return syscall_group_desc
> + structure for the group if found or NULL otherwise. */
> +
> +static struct syscall_group_desc *
> +syscall_group_get_group_by_name (const struct syscalls_info *syscalls_info,
> + const char *group)
> +{
> + struct syscall_group_desc *groupdesc;
> + int i;
> +
> + if (syscalls_info == NULL)
> + return NULL;
> +
> + if (group == NULL)
> + return NULL;
> +
> + /* Search for existing group. */
> + for (i = 0;
> + VEC_iterate (syscall_group_desc_p, syscalls_info->groups, i, groupdesc);
> + i++)
> + {
> + if (strcmp (groupdesc->name, group) == 0)
> + return groupdesc;
> + }
> +
> + return NULL;
> +}
> +
> static int
> xml_get_syscall_number (struct gdbarch *gdbarch,
> const char *syscall_name)
> @@ -388,6 +529,75 @@ xml_list_of_syscalls (struct gdbarch *gdbarch)
> return names;
> }
>
> +/* Iterate over the syscall_group_desc element to return a list of
> + syscalls that are part of the given group, terminated by an empty
> + element. If the syscall group doesn't exist, return NULL. */
> +
> +static struct syscall *
> +xml_list_syscalls_by_group (struct gdbarch *gdbarch, const char *group)
> +{
> + struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
> + struct syscall_group_desc *groupdesc;
> + struct syscall_desc *sysdesc;
> + struct syscall *syscalls = NULL;
> + int nsyscalls;
> + int i;
> +
> + if (syscalls_info == NULL)
> + return NULL;
> +
> + groupdesc = syscall_group_get_group_by_name (syscalls_info, group);
> + if (groupdesc == NULL)
> + return NULL;
> +
> + nsyscalls = VEC_length (syscall_desc_p, groupdesc->syscalls);
> + syscalls = (struct syscall*) xmalloc ((nsyscalls + 1)
> + * sizeof (struct syscall));
> +
> + for (i = 0;
> + VEC_iterate (syscall_desc_p, groupdesc->syscalls, i, sysdesc);
> + i++)
> + {
> + syscalls[i].name = sysdesc->name;
> + syscalls[i].number = sysdesc->number;
> + }
> +
> + /* Add final element marker. */
> + syscalls[i].name = NULL;
> + syscalls[i].number = 0;
> +
> + return syscalls;
> +}
> +
> +/* Return a NULL terminated list of syscall groups or an empty list, if
> + no syscall group is available. Return NULL, if there is no syscall
> + information available. */
> +
> +static const char **
> +xml_list_of_groups (struct gdbarch *gdbarch)
> +{
> + struct syscalls_info *syscalls_info = gdbarch_syscalls_info (gdbarch);
> + struct syscall_group_desc *groupdesc;
> + const char **names = NULL;
> + int i;
> + int ngroups;
> +
> + if (syscalls_info == NULL)
> + return NULL;
> +
> + ngroups = VEC_length (syscall_group_desc_p, syscalls_info->groups);
> + names = (const char**) xmalloc ((ngroups + 1) * sizeof (char *));
> +
> + for (i = 0;
> + VEC_iterate (syscall_group_desc_p, syscalls_info->groups, i, groupdesc);
> + i++)
> + names[i] = groupdesc->name;
> +
> + names[i] = NULL;
> +
> + return names;
> +}
> +
> void
> set_xml_syscall_file_name (struct gdbarch *gdbarch, const char *name)
> {
> @@ -422,4 +632,24 @@ get_syscall_names (struct gdbarch *gdbarch)
> return xml_list_of_syscalls (gdbarch);
> }
>
> +/* See comment in xml-syscall.h. */
> +
> +struct syscall *
> +get_syscalls_by_group (struct gdbarch *gdbarch, const char *group)
> +{
> + init_syscalls_info (gdbarch);
> +
> + return xml_list_syscalls_by_group (gdbarch, group);
> +}
> +
> +/* See comment in xml-syscall.h. */
> +
> +const char **
> +get_syscall_group_names (struct gdbarch *gdbarch)
> +{
> + init_syscalls_info (gdbarch);
> +
> + return xml_list_of_groups (gdbarch);
> +}
> +
> #endif /* ! HAVE_LIBEXPAT */
> diff --git a/gdb/xml-syscall.h b/gdb/xml-syscall.h
> index b0dd401..407613e 100644
> --- a/gdb/xml-syscall.h
> +++ b/gdb/xml-syscall.h
> @@ -50,4 +50,20 @@ void get_syscall_by_name (struct gdbarch *gdbarch,
>
> const char **get_syscall_names (struct gdbarch *gdbarch);
>
> +/* Function used to retrieve the list of syscalls of a given group in
> + the system. Return a list of syscalls that are element of the
> + group, terminated by an empty element. The list is malloc'ed
> + and must be freed by the caller. If group doesn't exist, return
> + NULL. */
> +
> +struct syscall *get_syscalls_by_group (struct gdbarch *gdbarch,
> + const char *group);
> +
> +/* Function used to retrieve the list of syscall groups in the system.
> + Return an array of strings terminated by a NULL element. The list
> + must be freed by the caller. Return NULL if there is no syscall
> + information available. */
> +
> +const char **get_syscall_group_names (struct gdbarch *gdbarch);
> +
> #endif /* XML_SYSCALL_H */
> --
> 2.4.11

Just one minor nit (above). Otherwise, LGTM.

--
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF 31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible