[PATCH 2/2] asinfo: Introduce static query tool asinfo

Eugene Syromiatnikov esyr at redhat.com
Mon Jul 10 05:16:00 UTC 2017


On Wed, Jun 28, 2017 at 05:56:40AM +0300, Edgar Kaziahmedov wrote:
> From: Edgar Kaziahmedov <edos at linux.com>
> 
> The first version of asinfo tool. The asinfo tool has the
> following architecture:
> architecture dispatcher->system call dispatcher->filter dispatcher
> 
> As for arch. dispatcher, the asinfo has get-arch, list-arch, set-arch
> %name_of_arch options, arch_dispatcher is purposed to process them.
> Now, to find out the main principle of working, let’s consider the next
> one case:
> $ asinfo list-syscall set-filter signal
> Firstly, arch_dispatcher will return the current architecture, after
> that syscall_dispatcher will provide the list of system calls
> (struct sc_base_info) for this architecture, finally filter_dispatcher,
> working with syscallent’s database, will drop all system calls, which
> are not signal-related.
> For now, tool is able to show syscall typing its sequence number.
> 
> * Makefile.am (SUBDIRS): Add tools directory.
> * configure.ac (AC_CONFIG_FILES): Add Makefile's.
> * tools/Makefile.am: New file.
> * tools/asinfo/Makefile.am: New file.
> * tools/asinfo/arch_list.h: New file.
> * tools/asinfo/dispatchers.h: New file. Prototype syscall_dispatcher
> and arch_dispatcher.
> * tools/asinfo/dispatchers.c: New file. Implement arch_dispatcher.
> Import syscallent.h files.
> * tools/asinfo/arch_interface.h: New file. Prototype methods to simplify
> work with the list of arch_descriptor. Introduce struct arch_descriptor.
> * tools/asinfo/arch_interface.c: New file. Implement them.
> * tools/asinfo/request_msgs.h: New file. Introduce main type of requests.
> Introduce structures for syscall_dispatcher.
> * tools/asinfo/asinfo.c: New file. Implement support of all arch options and
> initial support of syscall options.
> * tools/asinfo/asinfo.1: New file. Empty man.
> 
> Signed-off-by: Edgar Kaziahmedov <edos at linux.com>
This and previous commit are signed with different e-mails, is this on
purpose?

> ---
>  Makefile.am                   |   2 +-
>  configure.ac                  |   2 +
>  tools/Makefile.am             |  28 ++++++
>  tools/asinfo/Makefile.am      |  56 ++++++++++++
>  tools/asinfo/arch_interface.c | 101 ++++++++++++++++++++++
>  tools/asinfo/arch_interface.h |  75 +++++++++++++++++
>  tools/asinfo/arch_list.h      |   4 +
>  tools/asinfo/asinfo.1         |   0
>  tools/asinfo/asinfo.c         | 192 ++++++++++++++++++++++++++++++++++++++++++
>  tools/asinfo/dispatchers.c    | 184 ++++++++++++++++++++++++++++++++++++++++
>  tools/asinfo/dispatchers.h    |  54 ++++++++++++
>  tools/asinfo/request_msgs.h   |  80 ++++++++++++++++++
>  12 files changed, 777 insertions(+), 1 deletion(-)
>  create mode 100644 tools/Makefile.am
>  create mode 100644 tools/asinfo/Makefile.am
>  create mode 100644 tools/asinfo/arch_interface.c
>  create mode 100644 tools/asinfo/arch_interface.h
>  create mode 100644 tools/asinfo/arch_list.h
>  create mode 100644 tools/asinfo/asinfo.1
>  create mode 100644 tools/asinfo/asinfo.c
>  create mode 100644 tools/asinfo/dispatchers.c
>  create mode 100644 tools/asinfo/dispatchers.h
>  create mode 100644 tools/asinfo/request_msgs.h
> 
> diff --git a/Makefile.am b/Makefile.am
> index 233796b6..3dc78eb5 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -35,7 +35,7 @@ endif
>  if HAVE_MX32_RUNTIME
>  TESTS_MX32 = tests-mx32
>  endif
> -SUBDIRS = tests $(TESTS_M32) $(TESTS_MX32)
> +SUBDIRS = tests $(TESTS_M32) $(TESTS_MX32) tools
>  
>  bin_PROGRAMS = strace
>  man_MANS = strace.1
> diff --git a/configure.ac b/configure.ac
> index bc7b637d..55fb978d 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -825,6 +825,8 @@ AC_CONFIG_FILES([Makefile
>  		 tests/Makefile
>  		 tests-m32/Makefile
>  		 tests-mx32/Makefile
> +		 tools/Makefile
> +		 tools/asinfo/Makefile
>  		 strace.spec
>  		 debian/changelog])
>  AC_OUTPUT
> diff --git a/tools/Makefile.am b/tools/Makefile.am
> new file mode 100644
> index 00000000..6044e9ae
> --- /dev/null
> +++ b/tools/Makefile.am
> @@ -0,0 +1,28 @@
> +# Automake input for strace tools.
> +#
> +# Copyright (c) 2017 Edgar A. Kaziakhmedov <edos at linux.com>
> +# All rights reserved.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +# 1. Redistributions of source code must retain the above copyright
> +#    notice, this list of conditions and the following disclaimer.
> +# 2. Redistributions in binary form must reproduce the above copyright
> +#    notice, this list of conditions and the following disclaimer in the
> +#    documentation and/or other materials provided with the distribution.
> +# 3. The name of the author may not be used to endorse or promote products
> +#    derived from this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +SUBDIRS = asinfo
> diff --git a/tools/asinfo/Makefile.am b/tools/asinfo/Makefile.am
> new file mode 100644
> index 00000000..195dfe84
> --- /dev/null
> +++ b/tools/asinfo/Makefile.am
> @@ -0,0 +1,56 @@
> +# Automake input for strace.
"for strace"?

> +#
> +# Copyright (c) 2017 Edgar Kaziakhmedov <edos at linux.com>
> +# All rights reserved.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +# 1. Redistributions of source code must retain the above copyright
> +#    notice, this list of conditions and the following disclaimer.
> +# 2. Redistributions in binary form must reproduce the above copyright
> +#    notice, this list of conditions and the following disclaimer in the
> +#    documentation and/or other materials provided with the distribution.
> +# 3. The name of the author may not be used to endorse or promote products
> +#    derived from this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +bin_PROGRAMS = asinfo
> +man_MANS = asinfo.1
> +
> +OS = linux
> +ARCH = @arch@
> +
> +AM_CFLAGS = $(WARN_CFLAGS)
> +AM_CPPFLAGS = -I$(builddir) \
> +	      -I$(top_builddir)/$(OS) \
> +	      -I$(top_srcdir)/$(OS) \
> +	      -I$(top_builddir) \
> +	      -I$(top_srcdir)
> +asinfo_CPPFLAGS = $(AM_CPPFLAGS)
> +asinfo_CFLAGS = $(AM_CFLAGS)
> +
> +asinfo_SOURCES = 		\
Tabs after space.

> +	arch_interface.c	\
> +	arch_interface.h	\
> +	arch_list.h		\
> +	asinfo.c		\
> +	dispatchers.c		\
> +	dispatchers.h		\
> +	../../error_prints.c	\
> +	../../error_prints.h	\
> +	../../macros.h		\
> +	requests_msgs.h		\
> +	../../xmalloc.c		\
> +	../../xmalloc.h		\
> +	#end of asinfo_SOURCES
> diff --git a/tools/asinfo/arch_interface.c b/tools/asinfo/arch_interface.c
> new file mode 100644
> index 00000000..3c11beae
> --- /dev/null
> +++ b/tools/asinfo/arch_interface.c
> @@ -0,0 +1,101 @@
> +/*
File description will not harm here.

> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edos at linux.com>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + *    derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include "arch_interface.h"
> +#include "xmalloc.h"
> +
> +struct arch_service *arch_list_create(unsigned size)
Shouldn't the argument be called "capacity"?

Function return type should be on a separate line.

> +{
> +	struct arch_service *as = (struct arch_service *) \
Newline escaping is not needed here.

> +				  xcalloc(sizeof(*as), 1);
It's better to format line continuation like this:

	struct arch_service *as =
		(struct arch_service *) xcalloc(sizeof(*as), 1);

Moreover, this cast is not needed.

> +	if (size) {
> +		as->arch_list = (struct arch_descriptor **) \
> +				xcalloc(sizeof(*(as->arch_list)), size);
The same regarding line continuation formatting and cast.

> +	}
Compound statement braces can be omitted in this case.

> +	as->capacity = size;
> +	as->next_free = 0;
> +	return as;
> +}
> +
> +int arch_list_push(struct arch_service *m, struct arch_descriptor *element)
Function return type should be on a separate line.

> +{
> +	if (m->next_free >= m->capacity) {
> +		return -1;
> +	}
Compound statement braces can be omitted in this case.

> +	m->arch_list[m->next_free] = element;
> +	(m->next_free)++;
Parentheses are not needed here.

> +	return 0;
> +}
> +
> +struct arch_descriptor *arch_list_get(struct arch_service *m, unsigned index)
Function return type should be on a separate line.

> +{
> +	if (index >= m->next_free) {
> +		return NULL;
> +	}
Compound statement braces can be omitted in this case.

> +	return m->arch_list[index];
> +}
> +
> +unsigned arch_list_size(struct arch_service *m)
Function return type should be on a separate line.

> +{
> +	return m->next_free;
> +}
> +
> +void arch_list_free(struct arch_service *m)
Function return type should be on a separate line.

> +{
> +	free(m->arch_list);
> +	free(m);
> +}
> +
> +const char* arch_list_name(struct arch_service *m, unsigned index)
Function return type should be on a separate line.

> +{
Why there's no next_free check? I'd implement it via arch_list_get with
a check for NULL afterwards.

> +	return m->arch_list[index]->arch_name;
> +}
> +
> +int arch_list_snum(struct arch_service *m, unsigned index)
Function return type should be on a separate line.

> +{
The same regarding next_free check.

> +	return m->arch_list[index]->max_scn;
> +}
> +
> +void arch_list_print(struct arch_service *m, const char *delim)
Function return type should be on a separate line.

> +{
> +	unsigned i = 0;
> +	unsigned max_len = 0;
No newline after declarations.

> +	for (i = 0; i < arch_list_size(m); i++) {
> +		unsigned temp = strlen(m->arch_list[i]->arch_name);
Why direct access if the accessor function was defined?

Btw, since arch_name values are static strings, one can calculate their
length in compile-time in store in a separate field. So much for
premature optimisation.

> +		if (temp > max_len) {
> +			max_len = temp;
> +		}
Braces can be omitted here.

> +	}
> +	for (i = 0; i < arch_list_size(m); i++) {
> +		printf("[%u] %*s %s %d\n", i + 1, max_len, arch_list_name(m, i),
This output will be unaligned once arch_list_size will be grown up to 11.

> +					   delim, arch_list_snum(m, i));
> +	}
Braces can be omitted here.

> +}
> diff --git a/tools/asinfo/arch_interface.h b/tools/asinfo/arch_interface.h
> new file mode 100644
> index 00000000..5e9a8256
> --- /dev/null
> +++ b/tools/asinfo/arch_interface.h
> @@ -0,0 +1,75 @@
> +/*
File description will not harm here.

> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edos at linux.com>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + *    derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
Missing newline.

> +#ifndef ASINFO_ARCH_INTERFACE
> +#define ASINFO_ARCH_INTERFACE
> +
> +#include "sysent.h"
> +
> +enum arch_types {
"enum arch_type" would be better.

> +	AARCH64,
> +	ARM,
> +	x86_64,
> +	x32
> +};
> +
> +struct arch_descriptor {
> +	enum arch_types arch_num;
> +	const char *arch_name;
> +	int max_scn;
> +	struct_sysent *list_of_syscall;
> +};
> +
> +/* To provide push-back interface with arch_list */
> +struct arch_service {
> +	struct arch_descriptor **arch_list;
> +	unsigned capacity;
> +	unsigned next_free;
> +};
> +
> +#define ARCH_LIST_DEFINE(name) \
> +	struct arch_service *(name)
> +
> +/* Push-back interface is purposed to simplify interaction with
> +   array of struct arch_descriptor's pointers */
> +
> +struct arch_service *arch_list_create(unsigned size);
> +
> +int arch_list_push(struct arch_service *m, struct arch_descriptor *element);
> +
> +struct arch_descriptor *arch_list_get(struct arch_service *m, unsigned index);
Oversized line.

> +
> +unsigned arch_list_size(struct arch_service *m);
> +
> +void arch_list_free(struct arch_service *m);
> +
> +const char* arch_list_name(struct arch_service *m, unsigned index);
> +
> +int arch_list_snum(struct arch_service *m, unsigned index);
> +
> +void arch_list_print(struct arch_service *m, const char *delim);
> +
> +#endif /* !ASINFO_ARCH_INTERFACE */
> diff --git a/tools/asinfo/arch_list.h b/tools/asinfo/arch_list.h
> new file mode 100644
> index 00000000..4a7accf7
> --- /dev/null
> +++ b/tools/asinfo/arch_list.h
> @@ -0,0 +1,4 @@
> +[0] = { AARCH64,	"aarch64",	ARRAY_SIZE(aarch64_sysent0),	aarch64_sysent0		},
> +[1] = { ARM,		"arm",		ARRAY_SIZE(arm_sysent0),	arm_sysent0		},
> +[2] = { x86_64,		"x86_64",	ARRAY_SIZE(x86_64_sysent0),	x86_64_sysent0		},
> +[3] = { x32,		"x32",		ARRAY_SIZE(x32_sysent0),	x32_sysent0		},

You can define utility macro which allows avoiding most of the
duplication (assuming that you rename arch names in enum to ARCH_*):

	#define ARCH_DESC_DEFINE(arch) \
		[ARCH_##arch] = { \
			.arch_num        = ARCH_##arch, \
			.arch_name       = #arch, \
			.max_scn         = ARRAY_SIZE(arch##_sysent0), \
			.list_of_syscall = arch##_sysent0, \
		} \

Moreover, as of now, I do not see why storing this list in a separate
file is needed, it is included currently only in a single place and it's
not going to be extremely big and frequently-updated.

> diff --git a/tools/asinfo/asinfo.1 b/tools/asinfo/asinfo.1
> new file mode 100644
> index 00000000..e69de29b
> diff --git a/tools/asinfo/asinfo.c b/tools/asinfo/asinfo.c
> new file mode 100644
> index 00000000..020ef7c8
> --- /dev/null
> +++ b/tools/asinfo/asinfo.c
> @@ -0,0 +1,192 @@
> +/*
File description will not harm here.

> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edos at linux.com>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + *    derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <stdarg.h>
> +#include <stdbool.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <limits.h>
It's better to have this list sorted.

> +
> +#include "arch_interface.h"
> +#include "dispatchers.h"
> +#include "error_prints.h"
> +#include "macros.h"
> +#include "request_msgs.h"
> +#include "xmalloc.h"
> +
> +const char *progname;
> +static const char *def_delim = ":";
> +
> +void ATTRIBUTE_NOINLINE
Maybe ATTRIBUTE_NORETURN too? Also, I do not really grasp the need of
making this function strictly non-inline. In both cases where this
attribute is used in strace.c, the usage is this attribute is justified.

> +die(void)
> +{
> +	exit(1);
> +}
> +
> +/* To calculate sequence number of set bit */
https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup

> +static inline unsigned
> +fsbit_num(unsigned flag)
> +{
> +	unsigned i = 0;
> +	while ((flag >>= 1) != 0) i++;
> +	return i;
> +}
> +
> +static unsigned
> +option_to_request(char *option)
> +{
> +	const struct opt_to_req requests[] = {
static?

> +	[ 0] = { AD_REQ_SET_ARCH,	"set-arch"		},
> +	[ 1] = { AD_REQ_GET_ARCH,	"get-arch"		},
> +	[ 2] = { AD_REQ_LIST_ARCH,	"list-arch"		},
> +	[ 3] = { SD_REQ_GET_NAME,	"get-name"		},
> +	//[ 4] = { SD_REQ_GET_NUMBER,	"get-num"		},
> +	//[ 5] = { SD_REQ_GET_NARGS,	"get-nargs"		},
> +	//[ 6] = { SD_REQ_GET_PROTO,	"get-proto"		},
> +	//[ 7] = { SD_REQ_GET_KERNEL,	"get-kernel"		},
> +	//[ 8] = { SD_REQ_GET_LIST,	"list-syscall"		},
> +	//[ 9] = { FD_SET_BASE_FILTER,	"set-filter"		},
> +	//[10] = { FD_SET_ADV_FILTER,	"set-adv-filter"	}
Why do you need array indices in this definition?

> +	};
> +	unsigned i;
> +
> +	for (i = 0; i < ARRAY_SIZE(requests); i++) {
> +		if (strcasecmp(option, requests[i].option) == 0)
> +			return requests[i].req_t;
> +	}
> +	return 0;
> +}
> +
> +static unsigned ATTRIBUTE_NOINLINE
Why noinline?

> +form_req(int argc, char *argv[], char *args[])
> +{
> +	progname = argv[0] ? argv[0] : "asinfo";
I would probably like to check for argc here too, see zerorgc test.

> +	int i;
> +	unsigned ret_val = 0;
> +	unsigned temp_ret = 0;
> +	unsigned bit_pos = 0;
> +
> +	for (i = 1; i < argc; i++) {
> +		if ((temp_ret = option_to_request(argv[i])) != 0) {
> +			if ((ret_val & temp_ret) ||
> +			    (!(temp_ret & (SD_REQ_GET_LIST +
It's better to use bitwise or and not arithmetic plus here.

> +					   AD_REQ_LIST_ARCH +
> +					   AD_REQ_GET_ARCH)) &&
> +			    (i + 1 >= argc))) {
> +				error_msg_and_help("option '%s' requires "
> +						   "argument", argv[i]);

$ ./asinfo get-name 0 get-name 1
./asinfo: option 'get-name' requires argument
Try './asinfo -h' for more information.
$

> +			}
> +			ret_val |= temp_ret;
> +			bit_pos = fsbit_num(temp_ret);
> +			if (!(temp_ret & (SD_REQ_GET_LIST + AD_REQ_LIST_ARCH +
> +					  AD_REQ_GET_ARCH))) {
Since this check is here for the second time, I think it can be
refactored and the related flag can be a part of some request description
struct.

> +				args[bit_pos] = argv[i + 1];
> +				i += 1;
> +			}
> +		} else {
> +			error_msg_and_help("unrecognized option '%s'", argv[i]);
> +		}
> +	}
> +	return ret_val;
> +}
> +
> +static int
> +check_req(unsigned *request, char *args[])
> +{
> +	int a_flag = *request & (AD_REQ_MASK ^ AD_REQ_SET_ARCH);
> +	int s_flag = *request & SD_REQ_MASK;
> +	int dump = 1;
> +	/* Check arch flags */
> +	if (!(*request & AD_REQ_MASK)) {
> +		*request |= AD_REQ_GET_ARCH;
> +		dump = 0;
> +	}
> +	if (*request & AD_REQ_SET_ARCH) {
> +		dump = 0;
> +	}
> +	/* Check for ambiguity */
> +	if (!((*request & AD_REQ_MASK) == AD_REQ_SET_ARCH ||
> +	      (*request & AD_REQ_MASK) == AD_REQ_GET_ARCH ||
> +	      (*request & AD_REQ_MASK) == AD_REQ_LIST_ARCH)) {
> +		return -1;
> +	}
> +	if (a_flag != 0 && s_flag != 0) {
> +		return -1;
> +	}
> +	/* Check syscall flags, ambiguity */
> +	if (!(*request & SD_REQ_MASK)) {
> +		*request |= SD_REQ_GET_LIST;
> +	}
> +	if (!((*request & SD_REQ_MASK) == SD_REQ_GET_NAME ||
> +	      (*request & SD_REQ_MASK) == SD_REQ_GET_NUMBER ||
> +	      (*request & SD_REQ_MASK) == SD_REQ_GET_LIST)) {
> +		return -1;
> +	}
> +	return dump;
> +}
This whole function is very cryptic.

> +
> +int
> +main(int argc, char *argv[])
> +{
> +	char **input_args = (char**)xcalloc(sizeof(char*),
Missing space before xcalloc. Also this cast is not needed.
Missing spaces after "char".

> +			    sizeof(unsigned) * CHAR_BIT);
Line continuation should be aligned to opening parenthesis of xcalloc call.

> +	unsigned requests;
> +	int dump;
> +
> +	if ((requests = form_req(argc, argv, input_args)) == 0)
> +		error_msg_and_help("must have OPTIONS");
> +	if ((dump = check_req(&requests, input_args)) == -1)
> +		error_msg_and_help("ambiguous options");
> +

> +	/* arch_dispatcher work */
> +	ARCH_LIST_DEFINE(arch_list);
> +	arch_list = arch_dispatcher(requests,
> +				    input_args[fsbit_num(AD_REQ_SET_ARCH)]);
> +	if (dump) {
> +		arch_list_print(arch_list, def_delim);
> +		goto done;
> +	}
> +	if (arch_list_size(arch_list) == 0) {
> +		error_msg_and_help("unrecognized architecture '%s'",
> +				   input_args[fsbit_num(AD_REQ_SET_ARCH)]);
> +	}
Braces can be omitted here.

> +	/* syscall_dispatcher work */
> +	SYSCALL_LIST_DEFINE(syscall_list);
> +	syscall_list = syscall_dispatcher(arch_list, requests,
> +			   input_args[fsbit_num(requests & SD_REQ_MASK)]);
> +	if (syscall_list[0].sys_name != NULL) {
> +		printf("%s\n", syscall_list[0].sys_name);
> +	} else {
> +		error_msg_and_help("unrecognized syscall number '%s'",
> +				input_args[fsbit_num(requests & SD_REQ_MASK)]);
> +	}
I do not really understand why exactly this logic is realized.

For example, how can one lookup syscall statistics ("dump") for a
specific architecture?

> +done:
> +	arch_list_free(arch_list);
> +	free(input_args);
There's no need to free allocated memory right before the exit.

> +	return 0;
> +}
> diff --git a/tools/asinfo/dispatchers.c b/tools/asinfo/dispatchers.c
> new file mode 100644
> index 00000000..95ca4923
> --- /dev/null
> +++ b/tools/asinfo/dispatchers.c
> @@ -0,0 +1,184 @@
> +/*
File description will not harm here.

> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edos at linux.com>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + *    derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +# include "config.h"
> +#endif
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <sys/utsname.h>
It's better to have this list sorted.

> +
> +#include "arch_interface.h"
> +#include "dispatchers.h"
> +#include "macros.h"
> +#include "request_msgs.h"
> +#include "sysent.h"
> +#include "xmalloc.h"
> +
> +/* Define these shorthand notations to simplify the syscallent files. */
> +/* These flags could be useful to print group of syscalls */
> +#define TD TRACE_DESC
> +#define TF TRACE_FILE
> +#define TI TRACE_IPC
> +#define TN TRACE_NETWORK
> +#define TP TRACE_PROCESS
> +#define TS TRACE_SIGNAL
> +#define TM TRACE_MEMORY
> +#define TST TRACE_STAT
> +#define TLST TRACE_LSTAT
> +#define TFST TRACE_FSTAT
> +#define TSTA TRACE_STAT_LIKE
> +#define TSF TRACE_STATFS
> +#define TFSF TRACE_FSTATFS
> +#define TSFA TRACE_STATFS_LIKE
> +#define NF SYSCALL_NEVER_FAILS
> +#define MA MAX_ARGS
> +#define SI STACKTRACE_INVALIDATE_CACHE
> +#define SE STACKTRACE_CAPTURE_ON_ENTER
> +#define CST COMPAT_SYSCALL_TYPES
> +
> +/*
> + * For the current functionality there is no need
> + * to use sen and (*sys_func)() fields in sysent struct
> + */
> +#define SEN(syscall_name) 0, NULL
> +
> +struct_sysent aarch64_sysent0[] = {
> +#include "aarch64/syscallent.h"
> +};
> +
> +struct_sysent arm_sysent0[] = {
> +#include "arm/syscallent.h"
> +};
> +
> +struct_sysent x32_sysent0[] = {
> +#include "x32/syscallent.h"
> +};
> +
> +struct_sysent x86_64_sysent0[] = {
> +#include "x86_64/syscallent.h"
> +};
> +
> +#undef SEN
> +#undef TD
> +#undef TF
> +#undef TI
> +#undef TN
> +#undef TP
> +#undef TS
> +#undef TM
> +#undef TST
> +#undef TLST
> +#undef TFST
> +#undef TSTA
> +#undef TSF
> +#undef TFSF
> +#undef TSFA
> +#undef NF
> +#undef MA
> +#undef SI
> +#undef SE
> +#undef CST
> +
> +struct arch_descriptor architectures[] = {
> +#include "arch_list.h"
> +};
> +
> +struct sc_base_info *
> +syscall_dispatcher(struct arch_service *arch, int request_type,
> +		   const char *data)
> +{
> +	SYSCALL_LIST_DEFINE(syscall_list);
> +
> +	if (request_type & SD_REQ_GET_NAME) {
> +		long int nsys;
> +		char *endptr;
> +		nsys = strtol(data, &endptr, 10);
Why base 10?

> +		if (*endptr != '\0' || nsys < 0 ||
> +		    nsys >= arch->arch_list[0]->max_scn) {
> +			goto fail;
> +		}

$ ./asinfo get-name ""
read
$

> +		SYSCALL_LIST_ALLOC(syscall_list, 1);
> +		syscall_list[0].sys_name =
> +			arch->arch_list[0]->list_of_syscall[nsys].sys_name;
> +		goto done;
> +	}
> +
> +fail:
> +	SYSCALL_LIST_ALLOC(syscall_list, 0);
> +done:
> +	return syscall_list;
> +}
Why creating a list and populating only a single entry?

> +
> +struct arch_service *
> +arch_dispatcher(unsigned request_type, const char* arch)
> +{
> +	struct utsname info_uname;
> +	const char *loc_arch;
> +	unsigned i;
> +	ARCH_LIST_DEFINE(arch_list);
> +	if ((!arch) && (request_type & AD_REQ_SET_ARCH)) {
> +		goto fail;
> +	}
Braces can be omitted here.

> +
> +	if (request_type & AD_REQ_GET_ARCH) {
> +		uname(&info_uname);
> +		for (i = 0; i < ARRAY_SIZE(architectures); i++) {
> +			loc_arch = architectures[i].arch_name;
> +			if (strcasestr(info_uname.machine, loc_arch) != NULL) {
I really wonder how this will behave in case of mips or powerpc.

> +				arch_list = arch_list_create(1);
> +				arch_list_push(arch_list, &(architectures[i]));
> +				goto done;
> +			}
> +		}
> +	}
> +
> +	if (request_type & AD_REQ_SET_ARCH) {
> +		for (i = 0; i < ARRAY_SIZE(architectures); i++) {
> +			loc_arch = architectures[i].arch_name;
> +			if (strcasestr(arch, loc_arch) != NULL) {
> +				arch_list = arch_list_create(1);
> +				arch_list_push(arch_list, &(architectures[i]));
> +				goto done;
> +			}
> +		}
This loop is almost identical to the previous one, it should probably be
refactored in a separate function.

> +	}
> +
> +	if (request_type & AD_REQ_LIST_ARCH) {
> +		arch_list = arch_list_create(ARRAY_SIZE(architectures));
> +		for (i = 0; i < ARRAY_SIZE(architectures); i++) {
> +			arch_list_push(arch_list, &(architectures[i]));
> +		}
> +		goto done;
> +	}
> +
> +fail:
> +	arch_list = arch_list_create(0);
> +done:
> +	return arch_list;
> +}
> diff --git a/tools/asinfo/dispatchers.h b/tools/asinfo/dispatchers.h
> new file mode 100644
> index 00000000..a60f1595
> --- /dev/null
> +++ b/tools/asinfo/dispatchers.h
> @@ -0,0 +1,54 @@
> +/*
File description will not harm here.

> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edos at linux.com>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + *    derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef STRACE_ASINFO_COM_SCALLENT
> +#define STRACE_ASINFO_COM_SCALLENT
> +
> +#include "arch_interface.h"
> +#include "request_msgs.h"
> +#include "sysent.h"
> +
> +#define SYSCALL_LIST_DEFINE(name) \
> +	struct sc_base_info *(name)
> +
> +#define SYSCALL_LIST_ALLOC(name, size) \
> +	(name) = (struct sc_base_info*) xcalloc(sizeof(*(name)), (size + 1))
The cast is not needed here. Missing space after sc_base_info.

> +
> +/* The main interaction with low-level structures, such as for now,
> + * struct_sysent, is happening here, the remaining processing should
> + * be done on the other levels.
> + */
> +struct sc_base_info *syscall_dispatcher(struct arch_service *arch,
> +					int request_type,
> +					const char *arg);
> +
> +/* The function is purposed to interact with uname syscall
> + */
> +struct arch_service *arch_dispatcher(unsigned request_type,
> +				     const char* arch);
> +
> +#endif /* !STRACE_ASINFO_COM_SCALLENT */
> diff --git a/tools/asinfo/request_msgs.h b/tools/asinfo/request_msgs.h
> new file mode 100644
> index 00000000..575e2735
> --- /dev/null
> +++ b/tools/asinfo/request_msgs.h
> @@ -0,0 +1,80 @@
> +/*
File description will not harm here.

> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edos at linux.com>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + *    derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef STRACE_ASINFO_REQ_MSGS
> +#define STRACE_ASINFO_REQ_MSGS
> +
> +/* Request types for syscall_dispatcher,
> + * arch_dispatcher, and filter_dispatcher,
> + * which, in turn, could be combined
> + */
> +enum request_types {
> +	SD_REQ_GET_NAME		= 0x1<<0,
> +	SD_REQ_GET_NUMBER	= 0x1<<1,
> +	SD_REQ_GET_NARGS	= 0x1<<2,
> +	SD_REQ_GET_PROTO	= 0x1<<3,
> +	SD_REQ_GET_KERNEL	= 0x1<<4,
> +	SD_REQ_GET_LIST		= 0x1<<5,
> +	/* Reserved */
> +	AD_REQ_SET_ARCH		= 0x1<<16,
> +	AD_REQ_GET_ARCH		= 0x1<<17,
> +	AD_REQ_LIST_ARCH	= 0x1<<18,
> +	/* Reserved */
> +	FD_SET_BASE_FILTER	= 0x1<<24,
> +	FD_SET_ADV_FILTER	= 0x1<<25
What for is FD, anyway?

> +};
> +
> +#define SD_REQ_MASK (0x0000FFFFU)
> +#define AD_REQ_MASK (0x00FF0000U)
> +#define FD_REQ_MASK (0xFF000000U)
I'd have simple set of enums which calculate all this stuff for me, like
this:

	enum syscall_req_bit {
		SD_REQ_GET_NAME_BIT,
		SD_REQ_GET_NUMBER_BIT,
		SD_REQ_GET_NARGS_BIT,
		SD_REQ_GET_PROTO_BIT,
		SD_REQ_GET_KERNEL_BIT,
		SD_REQ_GET_LIST_BIT,

		SYSCALL_REQ_BIT_LAST
	};
	enum arch_req_bit {
		AD_REQ_SET_ARCH_BIT = SYSCALL_REQ_BIT_LAST,
		AD_REQ_GET_ARCH_BIT,
		AD_REQ_LIST_ARCH_BIT,

		ARCH_REQ_BIT_LAST
	};
	enum fd_req_bit {
		FD_SET_BASE_FILTER_BIT = ARCH_REQ_BIT_LAST,
		FD_SET_ADV_FILTER,

		FD_REQ_BIT_LAST
	};
	#define ENUM_FLAG(name) name = name##_BIT
	enum request_type {
		ENUM_FLAG(SD_REQ_GET_NAME),
		ENUM_FLAG(SD_REQ_GET_NUMBER),
		ENUM_FLAG(SD_REQ_GET_NARGS),
		ENUM_FLAG(SD_REQ_GET_PROTO),
		ENUM_FLAG(SD_REQ_GET_KERNEL),
		ENUM_FLAG(SD_REQ_GET_LIST),
		ENUM_FLAG(AD_REQ_SET_ARCH),
		ENUM_FLAG(AD_REQ_GET_ARCH),
		ENUM_FLAG(AD_REQ_LIST_ARCH),
		ENUM_FLAG(FD_REQ_SET_BASE_FILTER),
		ENUM_FLAG(FD_REQ_SET_ADV_FILTER),
	};
	#undef ENUM_FLAG

	#define BITMASK(hi, lo) (1 << (hi) - 1 << (lo))
	#define REQ_LAST_BIT FD_REQ_BIT_LAST /* Can be used in input_args calloc*/
	#define SD_REQ_MASK BITMASK(SYSCALL_REQ_BIT_LAST, 0)
	#define AD_REQ_MASK BITMASK(ARCH_REQ_BIT_LAST,    SYSCALL_REQ_BIT_LAST)
	#define FD_REQ_MASK BITMASK(FD_REQ_BIT_LAST,      ARCH_REQ_BIT_LAST)
	#undef BITMASK

This would also allow avoiding fsbit_num calls with constant operands.

> +
> +/* To convert options to req_types */
> +struct opt_to_req {
> +	enum request_types req_t;
> +	const char *option;
> +};
> +
> +/* SD_REQ_GET_NAME, SD_REQ_GET_NUMBER */
> +struct sc_base_info {
> +	int sys_number;
> +	const char *sys_name;
> +	int sys_flags;
> +};
> +
> +/* SD_REQ_GET_NARGS */
> +struct sc_nargs {
> +	struct sc_base_info sys_bi;
> +	int nargs;
> +};
> +
> +/* FD_SET_BASE_FILTER */
> +struct sc_filter {
> +	struct sc_base_info sys_bi;
> +	int filter_options;
> +};
> +
> +#endif /* !STRACE_ASINFO_REQ_MSGS */
> -- 
> 2.11.0

$ ./asinfo -h
./asinfo: unrecognized option '-h'
Try './asinfo -h' for more information.
$

Overall, the whole thing now looks over-engineered with no significant
reason for that. Maybe future commits which implement more functionality
will solve that.




More information about the Strace-devel mailing list