Implement catch syscall group

Implement support to add catchpoints for a group of related syscalls
using the syntax:

(gdb) catch syscall group:<group>
or
(gdb) catch syscall g:<group>

Several groups are predefined in the xml files for all architectures
supported by GDB over Linux.  They are based on the groups defined by
strace.

gdb/

	* 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.
	* break-catch-syscall.c (catch_syscall_split_args): Verify if
	argument is a syscall group and expand it to a list of syscalls
	when creating catchpoints.
	(catch_syscall_completer): Add word completion for system call
	groups.
	* configure.ac: Include dependency for xsltproc when building
	in maintainer-mode.
	* break-catch-syscall.c (_initialize_breakpoint): Update catch
	syscall command documentation.
	* NEWS: Include section about catching groups of syscalls.
	* configure: Regenerate.
	* data-directory/Makefile.in: Generate syscall xml when building
	in maintainer mode.
	* syscalls/gdb-syscalls.dtd: Include group attribute to the
	syscall element.
	* syscalls/apply-defaults.xsl: New.
	* syscalls/linux-defaults.xml.in: New.
	* syscalls/aarch64-linux.xml: Rename to aarch64-linux.xml.in.
	* syscalls/amd64-linux.xml: Rename to amd64-linux.xml.in.
	* syscalls/arm-linux.xml: Rename to arm-linux.xml.in.
	* syscalls/bfin-linux.xml: Rename to bfin-linux.xml.in.
	* syscalls/i386-linux.xml: Rename to i386-linux.xml.in.
	* syscalls/mips-n32-linux.xml: Rename to mips-n32-linux.xml.in.
	* syscalls/mips-n64-linux.xml: Rename to mips-n64-linux.xml.in.
	* syscalls/mips-o32-linux.xml: Rename to mips-o32-linux.xml.in.
	* syscalls/ppc-linux.xml: Rename to ppc-linux.xml.in.
	* syscalls/ppc64-linux.xml: Rename to ppc64-linux.xml.in.
	* syscalls/s390-linux.xml: Rename to s390-linux.xml.in.
	* syscalls/s390x-linux.xml: Rename to s390x-linux.xml.in.
	* syscalls/sparc-linux.xml: Rename to sparc-linux.xml.in.
	* syscalls/sparc64-linux.xml: Rename to sparc64-linux.xml.in.
	* syscalls/aarch64-linux.xml: Regenerate.
	* syscalls/amd64-linux.xml: Regenerate.
	* syscalls/arm-linux.xml: Regenerate.
	* syscalls/i386-linux.xml: Regenerate.
	* syscalls/mips-n32-linux.xml: Regenerate.
	* syscalls/mips-n64-linux.xml: Regenerate.
	* syscalls/mips-o32-linux.xml: Regenerate.
	* syscalls/ppc-linux.xml: Regenerate.
	* syscalls/ppc64-linux.xml: Regenerate.
	* syscalls/s390-linux.xml: Regenerate.
	* syscalls/s390x-linux.xml: Regenerate.
	* syscalls/sparc-linux.xml: Regenerate.
	* syscalls/sparc64-linux.xml: Regenerate.

gdb/testsuite/

	* gdb.base/catch-syscall.exp (do_syscall_tests): Add call
	to test_catch_syscall_group.
	(test_catch_syscall_group): New.

gdb/doc/

	* gdb.texinfo (Set Catchpoints): Add 'group' argument to catch
	syscall.
This commit is contained in:
Gabriel Krisman Bertazi 2016-07-23 18:38:24 -03:00
parent 49ecef2a7d
commit e34879080d
42 changed files with 7538 additions and 2468 deletions

View file

@ -464,10 +464,38 @@ catch_syscall_split_args (char *arg)
cur_name[i] = '\0';
arg += i;
/* Check if the user provided a syscall name or a number. */
/* Check if the user provided a syscall name, group, or a number. */
syscall_number = (int) strtol (cur_name, &endptr, 0);
if (*endptr == '\0')
get_syscall_by_number (gdbarch, syscall_number, &s);
{
get_syscall_by_number (gdbarch, syscall_number, &s);
VEC_safe_push (int, result, s.number);
}
else if (startswith (cur_name, "g:")
|| startswith (cur_name, "group:"))
{
/* We have a syscall group. Let's expand it into a syscall
list before inserting. */
struct syscall *syscall_list;
const char *group_name;
/* Skip over "g:" and "group:" prefix strings. */
group_name = strchr (cur_name, ':') + 1;
syscall_list = get_syscalls_by_group (gdbarch, group_name);
if (syscall_list == NULL)
error (_("Unknown syscall group '%s'."), group_name);
for (i = 0; syscall_list[i].name != NULL; i++)
{
/* Insert each syscall that are part of the group. No
need to check if it is valid. */
VEC_safe_push (int, result, syscall_list[i].number);
}
xfree (syscall_list);
}
else
{
/* We have a name. Let's check if it's valid and convert it
@ -479,10 +507,10 @@ catch_syscall_split_args (char *arg)
because GDB cannot do anything useful if there's no
syscall number to be caught. */
error (_("Unknown syscall name '%s'."), cur_name);
}
/* Ok, it's valid. */
VEC_safe_push (int, result, s.number);
/* Ok, it's valid. */
VEC_safe_push (int, result, s.number);
}
}
discard_cleanups (cleanup);
@ -597,11 +625,58 @@ static VEC (char_ptr) *
catch_syscall_completer (struct cmd_list_element *cmd,
const char *text, const char *word)
{
const char **list = get_syscall_names (get_current_arch ());
VEC (char_ptr) *retlist
= (list == NULL) ? NULL : complete_on_enum (list, word, word);
struct gdbarch *gdbarch = get_current_arch ();
struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
VEC (char_ptr) *group_retlist = NULL;
VEC (char_ptr) *syscall_retlist = NULL;
VEC (char_ptr) *retlist = NULL;
const char **group_list = NULL;
const char **syscall_list = NULL;
const char *prefix;
int i;
/* Completion considers ':' to be a word separator, so we use this to
verify whether the previous word was a group prefix. If so, we
build the completion list using group names only. */
for (prefix = word; prefix != text && prefix[-1] != ' '; prefix--)
;
if (startswith (prefix, "g:") || startswith (prefix, "group:"))
{
/* Perform completion inside 'group:' namespace only. */
group_list = get_syscall_group_names (gdbarch);
retlist = (group_list == NULL
? NULL : complete_on_enum (group_list, word, word));
}
else
{
/* Complete with both, syscall names and groups. */
syscall_list = get_syscall_names (gdbarch);
group_list = get_syscall_group_names (gdbarch);
/* Append "group:" prefix to syscall groups. */
for (i = 0; group_list[i] != NULL; i++)
{
char *prefixed_group = xstrprintf ("group:%s", group_list[i]);
group_list[i] = prefixed_group;
make_cleanup (xfree, prefixed_group);
}
syscall_retlist = ((syscall_list == NULL)
? NULL : complete_on_enum (syscall_list, word, word));
group_retlist = ((group_list == NULL)
? NULL : complete_on_enum (group_list, word, word));
retlist = VEC_merge (char_ptr, syscall_retlist, group_retlist);
}
VEC_free (char_ptr, syscall_retlist);
VEC_free (char_ptr, group_retlist);
xfree (syscall_list);
xfree (group_list);
do_cleanups (cleanups);
xfree (list);
return retlist;
}
@ -649,11 +724,11 @@ _initialize_break_catch_syscall (void)
catch_syscall_inferior_data_cleanup);
add_catch_command ("syscall", _("\
Catch system calls by their names and/or numbers.\n\
Arguments say which system calls to catch. If no arguments\n\
are given, every system call will be caught.\n\
Arguments, if given, should be one or more system call names\n\
(if your system supports that), or system call numbers."),
Catch system calls by their names, groups and/or numbers.\n\
Arguments say which system calls to catch. If no arguments are given,\n\
every system call will be caught. Arguments, if given, should be one\n\
or more system call names (if your system supports that), system call\n\
groups or system call numbers."),
catch_syscall_command_1,
catch_syscall_completer,
CATCH_PERMANENT,