diff --git a/gdb/syscalls/gdb-syscalls.dtd b/gdb/syscalls/gdb-syscalls.dtd
index 3ad3625..b60eb74 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	#OPTIONAL>
diff --git a/gdb/xml-syscall.c b/gdb/xml-syscall.c
index 3824468..06be330 100644
--- a/gdb/xml-syscall.c
+++ b/gdb/xml-syscall.c
@@ -76,6 +76,20 @@ get_syscall_names (void)
   return NULL;
 }
 
+struct syscall *
+get_syscalls_by_group (const char *group)
+{
+  syscall_warn_user ();
+  return NULL;
+}
+
+const char **
+get_syscall_group_names (void)
+{
+  syscall_warn_user ();
+  return NULL;
+}
+
 #else /* ! HAVE_LIBEXPAT */
 
 /* Variable that will hold the last known data-directory.  This is useful to
@@ -95,12 +109,29 @@ 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
 {
   /* The syscalls.  */
 
   VEC(syscall_desc_p) *syscalls;
+
+  /* The syscall groups.  */
+
+  VEC(syscall_group_desc_p) *groups;
 };
 
 /* Callback data for syscall information parsing.  */
@@ -134,17 +165,32 @@ sysinfo_free_syscalls_desc (struct syscall_desc *sd)
 }
 
 static void
+sysinfo_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 *sysinfo = arg;
   struct syscall_desc *sysdesc;
+  struct syscall_group_desc *groupdesc;
   int i;
 
   for (i = 0;
        VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc);
        i++)
     sysinfo_free_syscalls_desc (sysdesc);
+
+  for (i = 0;
+       VEC_iterate (syscall_group_desc_p, sysinfo->groups, i, groupdesc);
+       i++)
+    sysinfo_free_syscall_group_desc (groupdesc);
+
   VEC_free (syscall_desc_p, sysinfo->syscalls);
+  VEC_free (syscall_group_desc_p, sysinfo->groups);
 
   xfree (sysinfo);
 }
@@ -155,15 +201,66 @@ make_cleanup_free_syscalls_info (struct syscalls_info *sysinfo)
   return make_cleanup (free_syscalls_info, sysinfo);
 }
 
+/* Create a new syscall group.  Returns a 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 *sysinfo,
+					 const char *group)
+{
+  struct syscall_group_desc *groupdesc = XCNEW (struct syscall_group_desc);
+
+  groupdesc->name = xstrdup (group);
+
+  VEC_safe_push (syscall_group_desc_p, sysinfo->groups, groupdesc);
+
+  return groupdesc;
+}
+
+/* Add a syscall to a group.  If the group doesn't exist, creates
+   it.  */
+
+static void
+syscall_group_add_syscall (struct syscalls_info *sysinfo,
+			   struct syscall_desc *syscall,
+			   const char *group)
+{
+  struct syscall_group_desc *groupdesc;
+  int i;
+
+  /* Search for an existing group.  */
+  for (i = 0;
+       VEC_iterate (syscall_group_desc_p, sysinfo->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 (sysinfo, group);
+    }
+
+  VEC_safe_push (syscall_desc_p, groupdesc->syscalls, syscall);
+}
+
 static void
 syscall_create_syscall_desc (struct syscalls_info *sysinfo,
-                             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;
 
+  /*  Add syscall to its groups.  */
+  if (groups != NULL)
+    for (group = strtok (groups, ","); group; group = strtok (NULL, ","))
+      syscall_group_add_syscall (sysinfo, sysdesc, group);
+
   VEC_safe_push (syscall_desc_p, sysinfo->syscalls, sysdesc);
 }
 
@@ -179,6 +276,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);
 
@@ -188,13 +286,15 @@ syscall_start_syscall (struct gdb_xml_parser *parser,
         name = 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 = attrs[i].value;
       else
         internal_error (__FILE__, __LINE__,
                         _("Unknown attribute name '%s'."), attrs[i].name);
     }
 
   gdb_assert (name);
-  syscall_create_syscall_desc (data->sysinfo, name, number);
+  syscall_create_syscall_desc (data->sysinfo, name, number, groups);
 }
 
 
@@ -202,6 +302,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 }
 };
 
@@ -315,6 +416,32 @@ init_sysinfo (void)
   my_gdb_datadir = xstrdup (gdb_datadir);
 }
 
+/* Search for a syscall group by its name.  Returns 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 *sysinfo,
+				 const char *group)
+{
+  struct syscall_group_desc *groupdesc;
+  int i;
+
+  if (sysinfo == NULL)
+    return NULL;
+
+  if (group == NULL)
+    return NULL;
+
+   /* Search for existing group.  */
+  for (i = 0;
+       VEC_iterate (syscall_group_desc_p, sysinfo->groups, i, groupdesc);
+       i++)
+    if (strcmp (groupdesc->name, group) == 0)
+      return groupdesc;
+
+  return NULL;
+}
+
 static int
 xml_get_syscall_number (const struct syscalls_info *sysinfo,
                         const char *syscall_name)
@@ -379,6 +506,72 @@ xml_list_of_syscalls (const struct syscalls_info *sysinfo)
   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, returns NULL.  */
+
+static struct syscall *
+xml_list_syscalls_by_group (const struct syscalls_info *sysinfo,
+			    const char *group)
+{
+  struct syscall_group_desc *groupdesc;
+  struct syscall_desc *sysdesc;
+  struct syscall *syscalls = NULL;
+  int nsyscalls;
+  int i;
+
+  if (sysinfo == NULL)
+    return NULL;
+
+  groupdesc = syscall_group_get_group_by_name (sysinfo, group);
+  if (groupdesc == NULL)
+    return NULL;
+
+  nsyscalls = VEC_length (syscall_desc_p, groupdesc->syscalls);
+  syscalls = 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;
+}
+
+/* Returns the list of syscall groups.  If no syscall group is
+   available, returns NULL.  */
+
+static const char **
+xml_list_of_groups (const struct syscalls_info *sysinfo)
+{
+  struct syscall_group_desc *groupdesc;
+  const char **names = NULL;
+  int i;
+  int ngroups;
+
+  if (sysinfo == NULL)
+    return NULL;
+
+  ngroups = VEC_length (syscall_group_desc_p, sysinfo->groups);
+  names = xmalloc ((ngroups + 1) * sizeof (char *));
+
+  for (i = 0;
+       VEC_iterate (syscall_group_desc_p, sysinfo->groups, i, groupdesc);
+       i++)
+    names[i] = groupdesc->name;
+
+  names[i] = NULL;
+
+  return names;
+}
+
 void
 set_xml_syscall_file_name (const char *name)
 {
@@ -413,4 +606,26 @@ get_syscall_names (void)
   return xml_list_of_syscalls (sysinfo);
 }
 
+/* Returns a list of syscalls that are part of a group, terminated by an
+   empty element.  If group doesn't exist, returns NULL.  */
+
+struct syscall *
+get_syscalls_by_group (const char *group)
+{
+  init_sysinfo ();
+
+  return xml_list_syscalls_by_group (sysinfo, group);
+}
+
+/* Return a list of available groups.  If there are no groups available,
+   returns NULL.  */
+
+const char **
+get_syscall_group_names (void)
+{
+  init_sysinfo ();
+
+  return xml_list_of_groups (sysinfo);
+}
+
 #endif /* ! HAVE_LIBEXPAT */
diff --git a/gdb/xml-syscall.h b/gdb/xml-syscall.h
index dff389d..573b588 100644
--- a/gdb/xml-syscall.h
+++ b/gdb/xml-syscall.h
@@ -47,4 +47,16 @@ void get_syscall_by_name (const char *syscall_name, struct syscall *s);
 
 const char **get_syscall_names (void);
 
+/* Function used to retrieve the list of syscalls of a given group in
+   the system.  Returns a list of syscalls that are element of the
+   group, terminated by an empty element.  If group doesn't exist,
+   returns NULL.  */
+
+struct syscall *get_syscalls_by_group (const char *group);
+
+/* Function used to retrieve the list of syscall groups in the system.
+   Returns an array of strings terminated by a NULL element.  */
+
+const char **get_syscall_group_names (void);
+
 #endif /* XML_SYSCALL_H */
