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

Eugene Syromiatnikov esyr at redhat.com
Mon Jul 31 04:19:23 UTC 2017


On Fri, Jul 28, 2017 at 06:43:25PM +0300, Edgar Kaziakhmedov wrote:
> From: Edgar Kaziakhmedov <edgar.kaziakhmedov at virtuzzo.com>
> 
> The 1.2 version of asinfo tool. The asinfo tool has the
This version is not mentioned anywhere else.

> following architecture:
> commnand dispatcher->architecture dispatcher->abi dispatcher->
"command"

> 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.
> As for abi dispatcher, the asinfo has get-abi, list-abi, set-abi
> %name_of_abi options, abi_dispatcher is putposed to process it.
"purposed"

> As for command_dispatcher, for now it checks all options for
> correctness.
> Now, to find out the main principle of working, let’s consider next
> one case:
> $ asinfo get-arch
> Firstly, arch_dispatcher will return the current architecture, based on
> uname return value, after that in case of no options for abi_dispatcher,
> AD perceives it as get-abi option and returns corresponding for the set
> arch value.
> 
> NOTE: syscall_dispatcher for now is not supported
> 
> It is worth mentioning that this tool supports almostly all
> architectures supporting by Linux kernel.
More precisely, it supports (or, at least, should support) all
architectures/ABIs supported by strace (AFAIR RISC-V is not yet supported
by the Linux mainline kernel, for example).

> 
> * 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/dispatchers.h: New file. Prototype abi_dispatcher,
> arch_dispatcher, and syscall_dispatcher.
> * tools/asinfo/dispatchers.c: New file. Implement it.
> * 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 it.
> * tools/asinfo/request_msgs.h: New file. Introduce main types of requests.
> Introduce structures for syscall_dispatcher.
> * tools/asinfo/asinfo.c: New file. Implement support of all options.
> * tools/asinfo/asinfo.1: New file. Empty man.
> 
> Signed-off-by: Edgar Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.com>
> ---
>  Makefile.am                   |   2 +-
>  configure.ac                  |   2 +
>  tools/Makefile.am             |  28 ++
>  tools/asinfo/Makefile.am      |  56 +++
>  tools/asinfo/arch_interface.c | 888 ++++++++++++++++++++++++++++++++++++++++++
>  tools/asinfo/arch_interface.h | 184 +++++++++
>  tools/asinfo/asinfo.1         |   0
>  tools/asinfo/asinfo.c         | 196 ++++++++++
>  tools/asinfo/dispatchers.c    | 242 ++++++++++++
>  tools/asinfo/dispatchers.h    |  60 +++
>  tools/asinfo/request_msgs.h   | 115 ++++++
>  11 files changed, 1772 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/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 da175a27..ac40a8f2 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 0d407aff..ea14e270 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -842,6 +842,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..f1c75cfb
> --- /dev/null
> +++ b/tools/Makefile.am
> @@ -0,0 +1,28 @@
> +# Automake input for strace tools.
> +#
> +# Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.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..c2d5d8b2
> --- /dev/null
> +++ b/tools/asinfo/Makefile.am
> @@ -0,0 +1,56 @@
> +# Automake input for asinfo.
> +#
> +# Copyright (c) 2017 Edgar Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.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
> +
> +AUTOMAKE_OPTIONS = subdir-objects
> +
> +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 spaces.

> +	arch_interface.c	\
> +	arch_interface.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..6de6b830
> --- /dev/null
> +++ b/tools/asinfo/arch_interface.c
> @@ -0,0 +1,888 @@
> +/*
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.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 "defs.h"
> +#include "macros.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
Ugh. Looks like these shorthand definitions should be put in a separate
header.

> +
> +/*
> + * For the current functionality there is no need
> + * to use sen and (*sys_func)() fields in sysent struct
> + */
> +#define SEN(syscall_name) 0, NULL
> +
> +/* dummy_sysent is purposed to set syscall_list field in
> + * inherited architectures */
> +struct_sysent dummy_sysent[] = {};
> +
> +/* ARCH_blackfin */
> +struct_sysent blackfin_32bit_sysent[] = {
> +	#include "bfin/syscallent.h"
> +};
> +const int blackfin_32bit_usr1 = 0;
> +const int blackfin_32bit_usr2 = 0;
> +/* ARCH_ia64 */
> +struct_sysent ia64_64bit_sysent[] = {
> +	#include "ia64/syscallent.h"
> +};
> +const int ia64_64bit_usr1 = SYS_socket_subcall;
> +const int ia64_64bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_m68k */
> +struct_sysent m68k_32bit_sysent[] = {
> +	#include "m68k/syscallent.h"
> +};
> +const int m68k_32bit_usr1 = SYS_socket_subcall;
> +const int m68k_32bit_usr2 = 0;
> +/* ARCH_sparc64 64bit ABI */
> +struct_sysent sparc64_64bit_sysent[] = {
> +	#include "sparc64/syscallent.h"
> +};
> +const int sparc64_64bit_usr1 = SYS_socket_subcall;
> +const int sparc64_64bit_usr2 = 0;
> +/* ARCH_sparc64 32bit ABI */
> +struct_sysent sparc64_32bit_sysent[] = {
> +	#include "sparc64/syscallent1.h"
> +};
> +const int sparc64_32bit_usr1 = SYS_socket_subcall;
> +const int sparc64_32bit_usr2 = 0;
> +/* ARCH_sparc */
> +struct_sysent sparc_32bit_sysent[] = {
> +	#include "sparc/syscallent.h"
> +};
> +const int sparc_32bit_usr1 = SYS_socket_subcall;
> +const int sparc_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_metag */
> +struct_sysent metag_32bit_sysent[] = {
> +	#include "metag/syscallent.h"
> +};
> +const int metag_32bit_usr1 = 0;
> +const int metag_32bit_usr2 = 0;
> +/* ARCH_mips o32 ABI */
> +#ifndef LINUX_MIPSO32
> +# define LINUX_MIPSO32 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent mips_o32_sysent[] = {
> +	#include "dummy.h"
> +	#include "mips/syscallent-compat.h"
> +	#include "mips/syscallent-o32.h"
> +};
> +#ifdef NOW_DEFINED
> +# undef LINUX_MIPSO32
> +# undef NOW_DEFINED
> +#endif
> +const int mips_o32_usr1 = SYS_socket_subcall;
> +const int mips_o32_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_mips n32 ABI */
> +#ifndef LINUX_MIPSN32
> +# define LINUX_MIPSN32 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent mips_n32_sysent[] = {
> +	#include "dummy.h"
> +	#include "mips/syscallent-compat.h"
> +	#include "mips/syscallent-n32.h"
> +};
> +#ifdef NOW_DEFINED
> +# undef LINUX_MIPSN32
> +# undef NOW_DEFINED
> +#endif
> +const int mips_n32_usr1 = SYS_socket_subcall;
> +const int mips_n32_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_mips n64 ABI */
> +#ifndef LINUX_MIPSN64
> +# define LINUX_MIPSN64 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent mips_n64_sysent[] = {
> +	#include "dummy.h"
> +	#include "mips/syscallent-compat.h"
> +	#include "mips/syscallent-n64.h"
> +};
> +#ifdef NOW_DEFINED
> +# undef LINUX_MIPSN32
> +# undef NOW_DEFINED
> +#endif
> +const int mips_n64_usr1 = SYS_socket_subcall;
> +const int mips_n64_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_alpha */
> +struct_sysent alpha_64bit_sysent[] = {
> +	#include "alpha/syscallent.h"
> +};
> +const int alpha_64bit_usr1 = 0;
> +const int alpha_64bit_usr2 = 0;
> +/* ARCH_ppc */
> +struct_sysent ppc_32bit_sysent[] = {
> +	#include "powerpc/syscallent.h"
> +};
> +const int ppc_32bit_usr1 = SYS_socket_subcall;
> +const int ppc_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_ppc64 64bit ABI */
> +struct_sysent ppc64_64bit_sysent[] = {
> +	#include "powerpc64/syscallent.h"
> +};
> +const int ppc64_64bit_usr1 = SYS_socket_subcall;
> +const int ppc64_64bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_ppc64 32bit ABI */
> +struct_sysent ppc64_32bit_sysent[] = {
> +	#include "powerpc64/syscallent1.h"
> +};
> +const int ppc64_32bit_usr1 = SYS_socket_subcall;
> +const int ppc64_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_arm OABI*/
> +#ifdef __ARM_EABI__
> +# undef __ARM_EABI__
> +# define NOW_UNDEFINED 1
> +#endif
> +struct_sysent arm_oabi_sysent[] = {
> +	#include "arm/syscallent.h"
> +};
> +const int arm_oabi_usr1 = SYS_socket_subcall;
> +const int arm_oabi_usr2 = ARM_FIRST_SHUFFLED_SYSCALL;
> +#undef ARM_FIRST_SHUFFLED_SYSCALL
> +#undef SYS_socket_subcall
> +#ifdef NOW_UNDEFINED
> +# define __ARM_EABI__ 1
> +# undef NOW_UNDEFINED
> +#endif
> +/* ARCH_arm EABI*/
> +#ifndef __ARM_EABI__
> +# define __ARM_EABI__ 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent arm_eabi_sysent[] = {
> +	#include "arm/syscallent.h"
> +};
> +const int arm_eabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
> +const int arm_eabi_usr2 = 0;
> +#undef ARM_FIRST_SHUFFLED_SYSCALL
> +#ifdef NOW_DEFINED
> +# undef __ARM_EABI__
> +# undef NOW_DEFINED
> +#endif
> +/* ARCH_aarch64 64bit ABI */
> +struct_sysent aarch64_64bit_sysent[] = {
> +	#include "aarch64/syscallent.h"
> +};
> +const int aarch64_64bit_usr1 = 0;
> +const int aarch64_64bit_usr2 = 0;
> +/* ARCH_aarch64 32bit ABI */
> +#ifndef __ARM_EABI__
> +# define __ARM_EABI__ 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent aarch64_32bit_sysent[] = {
> +	#include "aarch64/syscallent1.h"
> +};
> +const int aarch64_32bit_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
> +const int aarch64_32bit_usr2 = ARM_LAST_SPECIAL_SYSCALL;
> +#undef ARM_FIRST_SHUFFLED_SYSCALL
> +#undef ARM_LAST_SPECIAL_SYSCALL
> +#ifdef NOW_DEFINED
> +# undef __ARM_EABI__
> +# undef NOW_DEFINED
> +#endif
> +/* ARCH_avr32 */
> +struct_sysent avr32_32bit_sysent[] = {
> +	#include "avr32/syscallent.h"
> +};
> +const int avr32_32bit_usr1 = 0;
> +const int avr32_32bit_usr2 = 0;
> +/* ARCH_arc */
> +struct_sysent arc_32bit_sysent[] = {
> +	#include "arc/syscallent.h"
> +};
> +const int arc_32bit_usr1 = 0;
> +const int arc_32bit_usr2 = 0;
> +/* ARCH_s390 */
> +struct_sysent s390_32bit_sysent[] = {
> +	#include "s390/syscallent.h"
> +};
> +const int s390_32bit_usr1 = SYS_socket_subcall;
> +const int s390_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_s390x */
> +struct_sysent s390x_64bit_sysent[] = {
> +	#include "s390x/syscallent.h"
> +};
> +const int s390x_64bit_usr1 = SYS_socket_subcall;
> +const int s390x_64bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_hppa */
> +struct_sysent hppa_32bit_sysent[] = {
> +	#include "hppa/syscallent.h"
> +};
> +const int hppa_32bit_usr1 = 0;
> +const int hppa_32bit_usr2 = 0;
> +/* ARCH_parisc */
> +#define parisc_32bit_sysent dummy_sysent
> +const int parisc_32bit_usr1 = 0;
> +const int parisc_32bit_usr2 = 0;
> +/* ARCH_sh */
> +struct_sysent sh_32bit_sysent[] = {
> +	#include "sh/syscallent.h"
> +};
> +const int sh_32bit_usr1 = SYS_socket_subcall;
> +const int sh_32bit_usr2 = 0;
> +/* ARCH_sh64 */
> +struct_sysent sh64_64bit_sysent[] = {
> +	#include "sh64/syscallent.h"
> +};
> +const int sh64_64bit_usr1 = SYS_socket_subcall;
> +const int sh64_64bit_usr2 = 0;
> +/* ARCH_x86 */
> +struct_sysent x86_32bit_sysent[] = {
> +	#include "i386/syscallent.h"
> +};
> +const int x86_32bit_usr1 = SYS_socket_subcall;
> +const int x86_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_i386 */
> +#define i386_32bit_sysent dummy_sysent
> +const int i386_32bit_usr1 = 0;
> +const int i386_32bit_usr2 = 0;
> +/* ARCH_i486 */
> +#define i486_32bit_sysent dummy_sysent
> +const int i486_32bit_usr1 = 0;
> +const int i486_32bit_usr2 = 0;
> +/* ARCH_i586 */
> +#define i586_32bit_sysent dummy_sysent
> +const int i586_32bit_usr1 = 0;
> +const int i586_32bit_usr2 = 0;
> +/* ARCH_i686 */
> +#define i686_32bit_sysent dummy_sysent
> +const int i686_32bit_usr1 = 0;
> +const int i686_32bit_usr2 = 0;
> +/* ARCH_x86_64 64bit ABI mode */
> +struct_sysent x86_64_64bit_sysent[] = {
> +	#include "x86_64/syscallent.h"
> +};
> +const int x86_64_64bit_usr1 = 0;
> +const int x86_64_64bit_usr2 = 0;
> +/* ARCH_x86_64 32bit ABI mode */
> +struct_sysent x86_64_32bit_sysent[] = {
> +	#include "x86_64/syscallent1.h"
> +};
> +const int x86_64_32bit_usr1 = SYS_socket_subcall;
> +const int x86_64_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_x86_64 x32 ABI mode */
> +struct_sysent x86_64_x32_sysent[] = {
> +	#include "x86_64/syscallent2.h"
> +};
> +const int x86_64_x32_usr1 = 0;
> +const int x86_64_x32_usr2 = 0;
> +/* ARCH_amd64 */
> +#define amd64_64bit_sysent dummy_sysent
> +const int amd64_64bit_usr1 = 0;
> +const int amd64_64bit_usr2 = 0;
> +/* ARCH_cris */
> +struct_sysent cris_32bit_sysent[] = {
> +	#include "crisv10/syscallent.h"
> +};
> +const int cris_32bit_usr1 = SYS_socket_subcall;
> +const int cris_32bit_usr2 = 0;
> +/* ARCH_crisv10 */
> +#define crisv10_32bit_sysent dummy_sysent
> +const int crisv10_32bit_usr1 = 0;
> +const int crisv10_32bit_usr2 = 0;
> +/* ARCH_crisv32 */
> +struct_sysent crisv32_32bit_sysent[] = {
> +	#include "crisv32/syscallent.h"
> +};
> +const int crisv32_32bit_usr1 = SYS_socket_subcall;
> +const int crisv32_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_tile 64bit ABI mode */
> +struct_sysent tile_64bit_sysent[] = {
> +	#include "tile/syscallent.h"
> +};
> +const int tile_64bit_usr1 = 0;
> +const int tile_64bit_usr2 = 0;
> +/* ARCH_tile 32bit ABI mode */
> +struct_sysent tile_32bit_sysent[] = {
> +	#include "tile/syscallent1.h"
> +};
> +const int tile_32bit_usr1 = 0;
> +const int tile_32bit_usr2 = 0;
> +/* ARCH_microblaze */
> +struct_sysent microblaze_32bit_sysent[] = {
> +	#include "microblaze/syscallent.h"
> +};
> +const int microblaze_32bit_usr1 = 0;
> +const int microblaze_32bit_usr2 = 0;
> +/* ARCH_nios2 */
> +struct_sysent nios2_32bit_sysent[] = {
> +	#include "nios2/syscallent.h"
> +};
> +const int nios2_32bit_usr1 = 0;
> +const int nios2_32bit_usr2 = 0;
> +/* ARCH_openrisc */
> +struct_sysent openrisc_32bit_sysent[] = {
> +	#include "or1k/syscallent.h"
> +};
> +const int openrisc_32bit_usr1 = 0;
> +const int openrisc_32bit_usr2 = 0;
> +/* ARCH_xtensa */
> +struct_sysent xtensa_32bit_sysent[] = {
> +	#include "xtensa/syscallent.h"
> +};
> +const int xtensa_32bit_usr1 = 0;
> +const int xtensa_32bit_usr2 = 0;
> +/* ARCH_riscv 64bit ABI mode */
> +struct_sysent riscv_64bit_sysent[] = {
> +	#include "riscv/syscallent.h"
> +};
> +const int riscv_64bit_usr1 = 0;
> +const int riscv_64bit_usr2 = 0;
> +/* ARCH_riscv 32bit ABI mode */
> +struct_sysent riscv_32bit_sysent[] = {
> +	#include "riscv/syscallent1.h"
> +};
> +const int riscv_32bit_usr1 = 0;
> +const int riscv_32bit_usr2 = 0;

I'd strongly prefer this code being generated.  There's already too much
burden for adding a new architecture support.

> +
> +#undef DEFINE_SYSCALLENT
> +
> +#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
> +
> +#define ARCH_DESC_DEFINE(arch, base_arch, mode) \
> +	[ARCH_##arch##_##mode] = { \
> +		.arch_num		= ARCH_##arch##_##mode, \
> +		.arch_name		= #arch, \
> +		.arch_name_len		= ARRAY_SIZE(#arch) - 1, \
> +		.arch_base_num		= ARCH_##base_arch##_##mode, \
> +		.abi_mode		= #mode, \
> +		.abi_mode_len		= ARRAY_SIZE(#arch) - 1, \
> +		.max_scn		= ARRAY_SIZE(arch##_##mode##_sysent), \
> +		.list_of_syscall	= arch##_##mode##_sysent, \
"syscall_list" sounds more natural.

> +		.user_num1		= &arch##_##mode##_usr1, \
> +		.user_num2		= &arch##_##mode##_usr2, \
> +		.flag			= AD_FLAG_EMPTY \
> +	}
> +
> +/* Generate array of arch_descriptors for each architecture and mode */
> +struct arch_descriptor architectures[] = {
> +	ARCH_DESC_DEFINE(blackfin,	blackfin,	32bit	),
> +	ARCH_DESC_DEFINE(ia64,		ia64,		64bit	),
> +	ARCH_DESC_DEFINE(m68k,		m68k,		32bit	),
> +	ARCH_DESC_DEFINE(sparc64,	sparc64,	64bit	),
> +	ARCH_DESC_DEFINE(sparc64,	sparc64,	32bit	),
> +	ARCH_DESC_DEFINE(sparc,		sparc,		32bit	),
> +	ARCH_DESC_DEFINE(metag,		metag,		32bit	),
> +	ARCH_DESC_DEFINE(mips,		mips,		o32	),
> +	ARCH_DESC_DEFINE(mips,		mips,		n32	),
> +	ARCH_DESC_DEFINE(mips,		mips,		n64	),
> +	ARCH_DESC_DEFINE(alpha,		alpha,		64bit	),
> +	ARCH_DESC_DEFINE(ppc,		ppc,		32bit	),
> +	ARCH_DESC_DEFINE(ppc64,		ppc64,		64bit	),
> +	ARCH_DESC_DEFINE(ppc64,		ppc64,		32bit	),
> +	ARCH_DESC_DEFINE(arm,		arm,		oabi	),
> +	ARCH_DESC_DEFINE(arm,		arm,		eabi	),
> +	ARCH_DESC_DEFINE(aarch64,	aarch64,	64bit	),
> +	ARCH_DESC_DEFINE(aarch64,	aarch64,	32bit	),
> +	ARCH_DESC_DEFINE(avr32,		avr32,		32bit	),
> +	ARCH_DESC_DEFINE(arc,		arc,		32bit	),
> +	ARCH_DESC_DEFINE(s390,		s390,		32bit	),
> +	ARCH_DESC_DEFINE(s390x,		s390x,		64bit	),
> +	ARCH_DESC_DEFINE(hppa,		hppa,		32bit	),
> +	ARCH_DESC_DEFINE(parisc,	hppa,		32bit	),
> +	ARCH_DESC_DEFINE(sh,		sh,		32bit	),
> +	ARCH_DESC_DEFINE(sh64,		sh64,		64bit	),
> +	ARCH_DESC_DEFINE(x86,		x86,		32bit	),
> +	ARCH_DESC_DEFINE(i386,		x86,		32bit	),
> +	ARCH_DESC_DEFINE(i486,		x86,		32bit	),
> +	ARCH_DESC_DEFINE(i586,		x86,		32bit	),
> +	ARCH_DESC_DEFINE(i686,		x86,		32bit	),
> +	ARCH_DESC_DEFINE(x86_64,	x86_64,		64bit	),
> +	ARCH_DESC_DEFINE(x86_64,	x86_64,		32bit	),
> +	ARCH_DESC_DEFINE(x86_64,	x86_64,		x32	),
> +	ARCH_DESC_DEFINE(amd64,		x86_64,		64bit	),
> +	ARCH_DESC_DEFINE(cris,		cris,		32bit	),
> +	ARCH_DESC_DEFINE(crisv10,	cris,		32bit	),
> +	ARCH_DESC_DEFINE(crisv32,	crisv32,	32bit	),
> +	ARCH_DESC_DEFINE(tile,		tile,		64bit	),
> +	ARCH_DESC_DEFINE(tile,		tile,		32bit	),
> +	ARCH_DESC_DEFINE(microblaze,	microblaze,	32bit	),
> +	ARCH_DESC_DEFINE(nios2,		nios2,		32bit	),
> +	ARCH_DESC_DEFINE(openrisc,	openrisc,	32bit	),
> +	ARCH_DESC_DEFINE(xtensa,	xtensa,		32bit	),
> +	ARCH_DESC_DEFINE(riscv,		riscv,		64bit	),
> +	ARCH_DESC_DEFINE(riscv,		riscv,		32bit	)
Looks like we definitely need list of personality names for each
architecture.

> +};
> +
> +/* To make architectures array usable for dispatchers.c */
> +const int architectures_size = ARRAY_SIZE(architectures);
> +
> +#undef ARCH_DESC_DEFINE
> +
> +struct arch_service *
> +al_create(unsigned int capacity)
> +{
> +	struct arch_service *as = xcalloc(sizeof(*as), 1);
> +
> +	if (capacity)
> +		as->arch_list = xcalloc(sizeof(*(as->arch_list)), capacity);
> +	as->capacity = capacity;
> +	as->next_free = 0;
> +	return as;
> +}
> +
> +int
> +al_push(struct arch_service *m, struct arch_descriptor *element)
> +{
> +	if (m->next_free >= m->capacity)
> +		return -1;
> +	m->arch_list[m->next_free] = element;
> +	m->arch_list[m->next_free]->flag = AD_FLAG_EMPTY;
I'd prefer having arch descriptors immutable and mutable flag being
outside them, as a part of arch_service container.

> +	m->next_free++;
> +	return 0;
> +}
> +
> +static inline int
> +al_is_index_ok(struct arch_service *m, unsigned index) {
> +	if (index >= m->next_free)
> +		return -1;
> +	return 0;
> +}
> +
> +int
> +al_set_flag(struct arch_service *m, unsigned index, int flag)
> +{
> +	if (al_is_index_ok(m, index) == 0) {
> +		m->arch_list[index]->flag = flag;
> +		return 0;
> +	}
> +	return -1;
> +}
> +
> +struct arch_descriptor *
> +al_get(struct arch_service *m, unsigned index)
> +{
> +	if (al_is_index_ok(m, index) != 0)
> +		return NULL;
> +	return m->arch_list[index];
> +}
> +
> +unsigned int
> +al_size(struct arch_service *m)
> +{
> +	return m->next_free;
> +}
> +
> +unsigned int
> +al_base_size(struct arch_service *m)
> +{
> +	int arch_size = al_size(m);
> +	int i = 0;
> +	unsigned count = 0;
> +
> +	for (i = 0; i < arch_size; i++)
> +		if (m->arch_list[i]->arch_num ==
> +		    m->arch_list[i]->arch_base_num)
> +			count++;
> +	return count;
> +}
> +
> +void
> +al_free(struct arch_service *m)
> +{
> +	free(m->arch_list);
> +	free(m);
> +}
> +
> +enum arch_type
> +al_arch_num(struct arch_service *m, unsigned index)
> +{
> +	struct arch_descriptor *elem = al_get(m, index);
> +
> +	return (elem ? elem->arch_num : ARCH_no_arch);
> +}
> +
> +const char *
> +al_arch_name(struct arch_service *m, unsigned index)
> +{
> +	struct arch_descriptor *elem = al_get(m, index);
> +
> +	return (elem ? elem->arch_name : NULL);
> +}
> +
> +int
> +al_arch_name_len(struct arch_service *m, unsigned index)
> +{
> +	struct arch_descriptor *elem = al_get(m, index);
> +
> +	return (elem ? elem->arch_name_len : -1);
> +}
> +
> +enum arch_type
> +al_arch_base_num(struct arch_service *m, unsigned index)
> +{
> +	struct arch_descriptor *elem = al_get(m, index);
> +
> +	return (elem ? elem->arch_base_num : ARCH_no_arch);
> +}
> +
> +const char *
> +al_abi_mode(struct arch_service *m, unsigned index)
> +{
> +	struct arch_descriptor *elem = al_get(m, index);
> +
> +	return (elem ? elem->abi_mode : NULL);
> +}
> +
> +int
> +al_abi_mode_len(struct arch_service *m, unsigned index)
> +{
> +	struct arch_descriptor *elem = al_get(m, index);
> +
> +	return (elem ? elem->abi_mode_len : -1);
> +}
> +
> +int
> +al_flag(struct arch_service *m, unsigned index)
> +{
> +	struct arch_descriptor *elem = al_get(m, index);
> +
> +	return (elem ? elem->flag : -1);
> +}
> +
> +int
> +al_syscall_impl(struct arch_service *m, unsigned index)
> +{
> +	struct arch_descriptor *elem = al_get(m, index);
> +	int i = 0;
> +	int count = 0;
> +
> +	if (elem == NULL)
> +		return -1;
> +	for (i = 0; i < elem->max_scn; i++) {
> +		if (elem->list_of_syscall[i].sys_name &&
> +		   !(elem->list_of_syscall[i].sys_flags &
> +		   TRACE_INDIRECT_SUBCALL))
> +			count++;
> +	}
> +	return count;
> +}
> +
> +/* This method is purposed to find base arch
> + * NOTE: base arch is the arch, where arch_num is equal to arch_base_num
> + * with default ABI mode */
> +int
> +al_find_base_arch(struct arch_service *m, unsigned index)
> +{
> +	enum arch_type base_arch = ARCH_no_arch;
> +	int arch_size = al_size(m);
> +	int i = 0;
> +
> +	/* If given arch meets conditions above then return this index */
> +	if (al_is_index_ok(m, index) != 0)
> +		return -1;
> +	/* Search base arch */
> +	base_arch = al_arch_base_num(m, index);
> +	for (i = 0; i < arch_size; i++)
> +		if ((strcmp(al_arch_name(m, index), al_arch_name(m, i)) == 0)
> +		    || (al_arch_base_num(m, i) == base_arch))
> +			return i;
> +	return -1;
> +}
> +
> +/* This method is purposed to count the supported ABI modes for the given
> +   arch
> +   NOTE: Firstly, do not forget to find base arch */
> +int
> +al_get_abi_modes(struct arch_service *m, unsigned index)
> +{
> +	const char *arch_name = al_arch_name(m, index);
> +	int arch_size = al_size(m);
> +	int i = 0;
> +	int abi_count = 0;
> +
> +	if (!arch_name)
> +		return -1;
> +	for (i = 0; i < arch_size; i++)
> +		if (strcmp(arch_name, al_arch_name(m, i)) == 0)
> +			abi_count++;
> +	return abi_count;
> +}
> +
> +/* This method is purposed to check on uniqueness, in sense of arch name,
> +   without taking into account ABI modes */
> +int
> +al_is_arch_unique(struct arch_service *m, unsigned index)
> +{
> +	enum arch_type base_arch = ARCH_no_arch;
> +	int arch_size = al_size(m);
> +	int i = 0;
> +
> +	if (al_arch_num(m, index) != al_arch_base_num(m, index) ||
> +	    al_arch_num(m, index) == ARCH_no_arch)
> +		return -1;
> +	base_arch = al_arch_base_num(m, index);
> +	for (i = 0; i < arch_size; i++)
> +		if ((al_arch_num(m, i) == base_arch) &&
> +		    (i != (int)index))
> +			return -1;
> +	return 0;
> +}
> +

> +enum impl_type
> +al_ipc_syscall(struct arch_service *m, unsigned index)
> +{
> +	struct arch_descriptor *elem = al_get(m, index);
> +	int i;
> +	enum impl_type impl_buf = IMPL_int;
> +
> +	for (i = 0; i < elem->max_scn; i++) {
> +		if (elem->list_of_syscall[i].sys_name == NULL)
> +			continue;
> +		if (strcmp(elem->list_of_syscall[i].sys_name, "ipc") == 0)
> +			impl_buf = IMPL_int;
> +		/* It is enough to find just semop sybcall */
> +		if ((strcmp(elem->list_of_syscall[i].sys_name, "semop") == 0)
> +		    && !((elem->list_of_syscall[i].sys_flags &
> +		    TRACE_INDIRECT_SUBCALL))) {
> +			if (impl_buf == IMPL_int)
> +				impl_buf = IMPL_int_ext;
> +			else
> +				impl_buf = IMPL_ext;
> +		}
> +	}
> +	return impl_buf;
> +}
> +
> +enum impl_type
> +al_sck_syscall(struct arch_service *m, unsigned index)
> +{
> +	struct arch_descriptor *elem = al_get(m, index);
> +	int i;
> +	enum impl_type impl_buf = IMPL_int;
> +
> +	for (i = 0; i < elem->max_scn; i++) {
> +		if (elem->list_of_syscall[i].sys_name == NULL)
> +			continue;
> +		if (strcmp(elem->list_of_syscall[i].sys_name,
> +			   "socketcall") == 0)
> +			impl_buf = IMPL_int;
> +		/* It is enough to find just socket sybcall */
> +		if ((strcmp(elem->list_of_syscall[i].sys_name, "socket") == 0)
> +		    && (!(elem->list_of_syscall[i].sys_flags &
> +		    TRACE_INDIRECT_SUBCALL))) {
> +			if (impl_buf == IMPL_int)
> +				impl_buf = IMPL_int_ext;
> +			else
> +				impl_buf = IMPL_ext;
> +		}
> +	}
> +	return impl_buf;
> +}
For this, I think some generator similar to ioctlsort could be used,
which allows generating list of ID's of syscalls on different
architectures. Or simple wrapper for generate_sen.h, which allows
accessing them vis SEN_<arch>_<syscall> constants.

> +
> +int al_find_arch(struct arch_service *m, enum arch_type a_type)
> +{
> +	int arch_size = al_size(m);
> +	int i;
> +
> +	for (i = 0; i < arch_size; i++)
> +		if (al_arch_num(m, i) == a_type)
> +			return i;
> +	return -1;
> +}
> +
> +/* This method is purposed to find next one name of the same architecture.
> +   For instance, x86_64 = amd64 */
> +int
> +al_next_arch_name(struct arch_service *m, unsigned index)
> +{
> +	static int next_arch = -1;
> +	int i = 0;
> +	int arch_size = al_size(m);
> +
> +	if (next_arch == -1)
> +		next_arch = index;
> +	else
> +		next_arch++;
> +	if (al_arch_num(m, index) != al_arch_base_num(m, index) ||
> +	    al_arch_num(m, index) == ARCH_no_arch)
> +		return -1;
> +	for (i = next_arch; i < arch_size; i++) {
> +		next_arch = -1;
> +		if (strcmp(al_arch_name(m, index), al_arch_name(m, i)) == 0)
> +			continue;
> +		if (al_arch_base_num(m, index) == al_arch_base_num(m, i)) {
> +			next_arch = i;
> +			break;
> +		}
> +		break;
> +	}
> +	if (next_arch >= arch_size)
> +		next_arch = -1;
> +	return next_arch;
> +}
> +
> +//len could optimized
> +//arch_list_size 11
> +void
> +al_dump(struct arch_service *m)
> +{
> +	const char *title[] = {
> +		"N",
> +		"Architecture name",
> +		"ABI mode",
> +		/* Implemented syscalls */
> +		"IMPL syscalls",
> +		/* IPC implementation */
> +		"IPC IMPL",
> +		/* SOCKET implementation */
> +		"SOCKET IMPL"
> +	};
> +	const char *impl_st[] = {
> +		"external",
> +		"internal",
> +		"int/ext"
> +	};
> +	int i = 0;
> +	int lbase_arch = 0;
> +	int temp_len = 0;
> +	int arch_number_col = 0;
> +	int arch_name_col = strlen(title[1]);
> +	int arch_abi_col = strlen(title[2]);
> +	/* It is hard to imagine arch with more than 10^13 syscalls */
Actually, it's difficult to have more than 2^32 syscalls.

> +	int arch_impl_sc_col = strlen(title[3]);
> +	int arch_ipc_col = strlen(title[4]);
> +	int arch_sck_col = strlen(title[5]);
> +	int arch_size = al_size(m);
> +	int arch_base_size = al_base_size(m);
> +	int N = 0;
> +	int next_name = 0;
> +	char *arch_name_buf;
> +
> +	/* Calculate length of the column with the number of architectures */
> +	for (i = 1; arch_base_size/i != 0; i *= 10)
> +		arch_number_col++;
> +	for (i = 0; i < arch_size; i++) {
> +		/* Calculate length of the column with the
> +		   architectures name */
> +		if (al_is_arch_unique(m, i) == -1)
> +			continue;
> +		lbase_arch = al_find_base_arch(m, i);
> +		temp_len = al_arch_name_len(m, lbase_arch);
> +		while ((next_name = al_next_arch_name(m, lbase_arch)) != -1) {
> +			temp_len += al_arch_name_len(m, next_name);
> +			/* To take into account delim symbol */
> +			temp_len++;
> +		}
> +		if (temp_len > arch_name_col) {
> +			arch_name_col = temp_len;
> +		}
Braces can be omitted here.

> +		/* Calculate length of the column with the ABI mode */
> +		if (al_abi_mode_len(m, i) > arch_abi_col)
> +			arch_abi_col = al_abi_mode_len(m, i);
> +
Stay empty line.

> +	}
The complexity of this loop frightens me. Is it n^3?

> +	arch_name_buf = xcalloc(arch_name_col, sizeof(*arch_name_buf));
> +	/* Output title */
> +	printf("| %*s | %*s | %*s | %*s | %*s | %*s |\n",
> +		arch_number_col, title[0], arch_name_col, title[1],
> +		arch_abi_col, title[2], arch_impl_sc_col, title[3],
> +		arch_ipc_col, title[4], arch_sck_col, title[5]);
> +	/* Output architectures */
> +	for (i = 0; i < arch_size; i++) {
> +		if ((al_is_arch_unique(m, i) == -1) ||
> +		    !(al_flag(m, i) & AD_FLAG_PRINT))
> +			continue;
> +		printf("| %*u | ", arch_number_col, N + 1);
> +		/* Put all the same arch back together */
> +		strcat(arch_name_buf, al_arch_name(m, i));
> +		lbase_arch = al_find_base_arch(m, i);
> +		while ((next_name = al_next_arch_name(m, lbase_arch)) != -1) {
> +			strcat(arch_name_buf, "/");
> +			strcat(arch_name_buf, al_arch_name(m, next_name));
> +		}
> +		printf("%*s | ", arch_name_col, arch_name_buf);
> +		printf("%*s | ", arch_abi_col, al_abi_mode(m, i));
> +		printf("%*d | ", arch_impl_sc_col, al_syscall_impl(m, i));
> +		printf("%*s | ", arch_ipc_col, impl_st[al_ipc_syscall(m, i)]);
> +		printf("%*s |\n", arch_sck_col, impl_st[al_sck_syscall(m, i)]);
> +		N++;
> +		memset(arch_name_buf, 0, arch_name_col);
> +	}
> +	free(arch_name_buf);
> +}
> diff --git a/tools/asinfo/arch_interface.h b/tools/asinfo/arch_interface.h
> new file mode 100644
> index 00000000..a7a6d320
> --- /dev/null
> +++ b/tools/asinfo/arch_interface.h
> @@ -0,0 +1,184 @@
> +/*
> + * The arch_interface.h is purposed to interact with the basic data structure
> + * based on arch_descriptor struct. Mainly this set of methods are used by
> + * arch_dispatcher.
> + *
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedv at virtuozzo.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 ASINFO_ARCH_INTERFACE
> +#define ASINFO_ARCH_INTERFACE
> +
> +#include "sysent.h"
> +
> +/* Type implementaion of syscall, internal means as a subcall,
> +   external means a separate syscall, this enum is purposed for
> +   well-known ipc and socket subcall group */
> +enum impl_type {
> +	IMPL_ext,
> +	IMPL_int,
> +	IMPL_int_ext
> +};
> +
> +/* Names of architectures
> + * arch_type format name_arch = ARCH_ + kernel_arch/others_name + abi_mode */
> +enum arch_type {
So, are these architecture types or architecture names?

> +	ARCH_blackfin_32bit,
> +	ARCH_ia64_64bit,
> +	ARCH_m68k_32bit,
> +	ARCH_sparc64_64bit,
> +	ARCH_sparc64_32bit,
> +	ARCH_sparc_32bit,
> +	ARCH_metag_32bit,
> +	ARCH_mips_o32,
> +	ARCH_mips_n32,
> +	ARCH_mips_n64,
> +	ARCH_alpha_64bit,
> +	ARCH_ppc_32bit,
> +	ARCH_ppc64_64bit,
> +	ARCH_ppc64_32bit,
> +	ARCH_arm_oabi,
> +	ARCH_arm_eabi,
> +	ARCH_aarch64_64bit,
> +	ARCH_aarch64_32bit,
> +	ARCH_avr32_32bit,
> +	ARCH_arc_32bit,
> +	ARCH_s390_32bit,
> +	ARCH_s390x_64bit,
> +	ARCH_hppa_32bit,
> +	ARCH_parisc_32bit,
> +	ARCH_sh_32bit,
> +	ARCH_sh64_64bit,
> +	ARCH_x86_32bit,
> +	ARCH_i386_32bit,
> +	ARCH_i486_32bit,
> +	ARCH_i586_32bit,
> +	ARCH_i686_32bit,
> +	ARCH_x86_64_64bit,
> +	ARCH_x86_64_32bit,
> +	ARCH_x86_64_x32,
> +	ARCH_amd64_64bit,
> +	ARCH_cris_32bit,
> +	ARCH_crisv10_32bit,
> +	ARCH_crisv32_32bit,
> +	ARCH_tile_64bit,
> +	ARCH_tile_32bit,
> +	ARCH_microblaze_32bit,
> +	ARCH_nios2_32bit,
> +	ARCH_openrisc_32bit,
> +	ARCH_xtensa_32bit,
> +	ARCH_riscv_64bit,
> +	ARCH_riscv_32bit,
> +	ARCH_no_arch
> +};
> +
> +#define AD_FLAG_EMPTY 0
> +/* Actually, this flag is purposed to hide some abi modes while printing in
> +   one arch group
> +   NOTE: arch group means base arch name + others */
> +#define AD_FLAG_PRINT 1
> +
> +struct arch_descriptor {
> +	enum arch_type arch_num;
> +	const char *arch_name;
> +	const int arch_name_len;
> +	enum arch_type arch_base_num;
> +	//enum abi_type abi_mode;
> +	const char *abi_mode;
> +	const int abi_mode_len;
> +	const int max_scn;
> +	struct_sysent *list_of_syscall;
> +	/* In the most cases these fields are purposed to store specific for
> +	   given arch constants, for instance, socket_subcall index etc */
This sounds scary, taking into account the fact that these fields are not used,
actually.

> +	const int *user_num1;
> +	const int *user_num2;
> +	/* User flags */
> +	int flag;
> +};
> +
> +/* 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
> +   arch_service struct
> +   NOTE: al - architecture list */
> +
> +/* base methods */
> +struct arch_service *al_create(unsigned int capacity);
> +
> +int al_push(struct arch_service *m, struct arch_descriptor *element);
> +
> +int al_set_flag(struct arch_service *m, unsigned index, int flag);
> +
> +struct arch_descriptor *al_get(struct arch_service *m, unsigned index);
> +
> +unsigned int al_size(struct arch_service *m);
> +
> +unsigned int al_base_size(struct arch_service *m);
> +
> +void al_free(struct arch_service *m);
> +
> +/* methods returning fields with error check */
> +enum arch_type al_arch_num(struct arch_service *m, unsigned index);
> +
> +const char *al_arch_name(struct arch_service *m, unsigned index);
> +
> +int al_arch_name_len(struct arch_service *m, unsigned index);
> +
> +enum arch_type al_arch_base_num(struct arch_service *m, unsigned index);
> +
> +const char *al_abi_mode(struct arch_service *m, unsigned index);
> +
> +int al_abi_mode_len(struct arch_service *m, unsigned index);
> +
> +int al_flag(struct arch_service *m, unsigned index);
> +
> +/* calculating methods */
> +int al_syscall_impl(struct arch_service *m, unsigned index);
> +
> +int al_find_base_arch(struct arch_service *m, unsigned index);
> +
> +int al_get_abi_modes(struct arch_service *m, unsigned index);
> +
> +int al_is_arch_unique(struct arch_service *m, unsigned index);
> +
> +enum impl_type al_ipc_syscall(struct arch_service *m, unsigned index);
> +
> +enum impl_type al_sck_syscall(struct arch_service *m, unsigned index);
> +
> +int al_find_arch(struct arch_service *m, enum arch_type a_type);
> +
> +int al_next_arch_name(struct arch_service *m, unsigned index);
> +
> +void al_dump(struct arch_service *m);
> +
> +#endif /* !ASINFO_ARCH_INTERFACE */
> 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..195c1d09
> --- /dev/null
> +++ b/tools/asinfo/asinfo.c
> @@ -0,0 +1,196 @@
> +/*
> + * The asinfo main source. The asinfo tool is purposed to operate
> + * with system calls and provide information about it.
> + *
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.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 <errno.h>
> +#include <limits.h>
> +#include <stdarg.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include "arch_interface.h"
> +#include "dispatchers.h"
> +#include "error_prints.h"
> +#include "macros.h"
> +#include "request_msgs.h"
> +#include "xmalloc.h"
> +
> +#ifndef HAVE_PROGRAM_INVOCATION_NAME
> +char *program_invocation_name;
> +#endif
> +
> +void
> +die(void)
> +{
> +	exit(1);
> +}
> +
> +static int
> +is_more1bit(unsigned int num)
> +{
> +	return !(num & (num - 1));
> +}
Usually such function is called "is_power_of_two" or something like that.

In your case it's (or, more precisely, its inverse) probably should be named
"is_single_bit" or something like this.

Note that this function return true for num == 0.

> +
> +static unsigned
> +option_to_request(char *option)
> +{
> +	/* Convertion table to store string with options */
> +	const char *options[] = {
> +	[SD_REQ_GET_NAME_BIT]	= "get-name",
> +	[SD_REQ_GET_NUMBER_BIT]	= "get-num",
> +	[SD_REQ_GET_NARGS_BIT]  = "get-nargs",
> +	[AD_REQ_SET_ARCH_BIT]	= "set-arch",
> +	[AD_REQ_GET_ARCH_BIT]	= "get-arch",
> +	[AD_REQ_LIST_ARCH_BIT]	= "list-arch",
> +	[ABD_REQ_SET_ABI]	= "set-abi",
> +	[ABD_REQ_GET_ABI]	= "get-abi",
> +	[ABD_REQ_LIST_ABI]	= "list-abi",
Why last three do not have "_BIT" suffix?

> +	};
> +	unsigned i;
> +
> +	for (i = 0; i < ARRAY_SIZE(options); i++) {
> +		if (options[i] && strcmp(option, options[i]) == 0)
> +			return i;
> +	}
> +	return UINT_MAX;
> +}
> +
> +static unsigned
> +command_dispatcher(int argc, char *argv[], char *args[])
> +{
> +	int i;
> +	unsigned final_req = 0;
> +	unsigned temp_req = 0;
> +	unsigned non_req_arg = (1 << AD_REQ_GET_ARCH_BIT)	|
> +			       (1 << AD_REQ_LIST_ARCH_BIT)	|
> +			       (1 << ABD_REQ_GET_ABI_BIT)	|
> +			       (1 << ABD_REQ_LIST_ABI_BIT)	|
> +			       (1 << SD_REQ_GET_LIST_BIT);
> +
> +	if (!program_invocation_name || !*program_invocation_name) {
> +		static char name[] = "asinfo";
> +		program_invocation_name =
> +			(argv[0] && *argv[0]) ? argv[0] : name;
> +	}
> +
> +	/* Firstly, is is necessary to convert and make basic check */
To convert what?

> +	for (i = 1; i < argc; i++) {
> +		if ((temp_req = option_to_request(argv[i])) == UINT_MAX)
> +			error_msg_and_help("unrecognized option '%s'", argv[i]);
> +		if (final_req & (1 << temp_req))
> +			error_msg_and_help("option '%s' has been used more than "
> +					   "once", argv[i]);
> +		if (!((1 << temp_req) & non_req_arg) &&
> +		     ((i + 1 >= argc) || strlen(argv[i + 1]) == 0))
> +			error_msg_and_help("option '%s' requires "
> +					   "argument", argv[i]);
> +		final_req |= (1 << temp_req);
> +		if (!((1 << temp_req) & non_req_arg)) {
> +			args[temp_req] = argv[i + 1];
> +			i++;
> +		}
> +	}
> +	/* Secondly, final_req should be logically checked,
> +	   here the only error is 'mixed options' */
> +	/* More than one option from the one request group couldn't be set*/
> +	if ((is_more1bit(final_req & SD_REQ_MASK) == 0) ||
> +	    (is_more1bit(final_req & AD_REQ_MASK) == 0) ||
> +	    (is_more1bit(final_req & ABD_REQ_MASK) == 0) ||
> +	    (is_more1bit(final_req & FD_REQ_MASK) == 0))
> +		error_msg_and_help("mixed options");
This error message is quite uninformative.

> +	/* Check on mutually exclusive options chain */
> +	/* If at least one syscall option has been typed, therefore
> +	   arch_options could be only empty or set-arch and
> +	   abi_option could be only empty or set-abi */
> +	if ((final_req & SD_REQ_MASK) &&
> +	    (((final_req & AD_REQ_MASK) &&
> +	      !(final_req & (1 << AD_REQ_SET_ARCH_BIT))) ||
> +	     ((final_req & ABD_REQ_MASK) &&
> +	      !(final_req & (1 << ABD_REQ_SET_ABI_BIT)))))
> +		error_msg_and_help("mixed options");
This too.

> +
> +	/* list-arch couldn't be used with any abi options */
> +	if ((final_req & (1 << AD_REQ_LIST_ARCH_BIT) &&
> +	    (final_req & ABD_REQ_MASK)))
> +		error_msg_and_help("mixed options");
And this.

> +
> +	return final_req;
> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> +	ARCH_LIST_DEFINE(arch_list);
> +	/* This array is purposed to store arguments for options in the
> +	   most convinient way */
"convenient"

> +	char **input_args = xcalloc(sizeof(*input_args), REQ_LAST_BIT);
> +	unsigned reqs;
> +	int ret = 0;
> +
> +	/* command_dispatcher turn */
> +	reqs = command_dispatcher(argc, argv, input_args);
> +	if (reqs == 0)
> +		error_msg_and_help("must have OPTIONS");
> +
> +	/* arch_dispatcher turn */
> +	arch_list = arch_dispatcher(reqs, input_args[AD_REQ_SET_ARCH]);
> +	if (arch_list == NULL)
> +		error_msg_and_help("unrecognized architecture '%s'",
> +				   input_args[AD_REQ_SET_ARCH]);
> +	/* abi_dispatcher turn */
> +	ret = abi_dispatcher(arch_list, reqs, input_args[ABD_REQ_SET_ABI]);
> +	if (ret != 0)
> +		error_msg_and_help("unrecognized ABI mode '%s'",
> +				   input_args[ABD_REQ_SET_ABI]);
> +	/* syscall_dispatcher work */
> +#if 0
> +	SYSCALL_LIST_DEFINE(syscall_list);
> +	syscall_list = syscall_dispatcher(arch_list, requests,
> +			   input_args[IS_OWNrequests & 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)]);
> +	}
> +#endif
> +	/* If we want to get info about just architectures thus we dump just
> +	   info about archs, otherwise only about syscalls */
> +	if (!(reqs & SD_REQ_MASK))
> +		al_dump(arch_list);
> +	else
> +		//sl_dump
> +		error_msg_and_die("syscall dispatcher isn't supported for now");
> +	return 0;
> +}
> diff --git a/tools/asinfo/dispatchers.c b/tools/asinfo/dispatchers.c
> new file mode 100644
> index 00000000..101f9f14
> --- /dev/null
> +++ b/tools/asinfo/dispatchers.c
> @@ -0,0 +1,242 @@
> +/*
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.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>
> +
> +#include "arch_interface.h"
> +#include "dispatchers.h"
> +#include "macros.h"
> +#include "request_msgs.h"
> +#include "sysent.h"
> +#include "xmalloc.h"
> +
> +extern struct arch_descriptor architectures[];
> +extern const int architectures_size;
> +
> +struct sc_base_info *
> +syscall_dispatcher(struct arch_service *arch, int request_type,
> +		   const char *data)
> +{
> +	SYSCALL_LIST_DEFINE(syscall_list);
> +
> +	if (request_type & (1 << SD_REQ_GET_NAME_BIT)) {
> +		long int nsys;
> +		char *endptr;
> +		nsys = strtol(data, &endptr, 10);
> +		if (*endptr != '\0' || nsys < 0 ||
> +		    nsys >= arch->arch_list[0]->max_scn) {
> +			goto fail;
> +		}
> +		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;
> +}
> +
> +static int
> +form_arch_list(struct arch_service **arch, char *arch_str)
> +{
> +	ARCH_LIST_DEFINE(a_full_list) = al_create(architectures_size);
> +	int arch_match = -1;
> +	char *match_pointer = NULL;
> +	int al_size_ret = 0;
> +	int al_size_full = 0;
> +	int i;
> +
> +	if (arch_str == NULL)
> +		return -1;
> +	/* Firstly, generate full list of arch to simplify firther work */
> +	for (i = 0; i < architectures_size; i++)
> +		al_push(a_full_list, &architectures[i]);
> +	al_size_full = al_size(a_full_list);
> +	/* Here we find the best match in architecture list */
> +	for (i = 0; i < al_size_full; i++) {
> +		match_pointer = strstr(arch_str, al_arch_name(a_full_list, i));
> +		if (match_pointer == NULL || match_pointer != arch_str)
> +			continue;
> +		if (arch_match == -1 ||
> +		    al_arch_name_len(a_full_list, i) >
> +		    al_arch_name_len(a_full_list, arch_match))
> +			arch_match = i;
> +	}
> +	if (arch_match == -1)
> +		goto fail;
> +	/* Now we find all ABI modes related to the architecture and its other
> +	   names */
> +	/* Firstly, find the base arch */
> +	arch_match = al_find_base_arch(a_full_list, arch_match);
> +	/* Secondly, it is necessary to calculate size of arch list */
> +	al_size_ret = al_get_abi_modes(a_full_list, arch_match);
> +	while ((i = al_next_arch_name(a_full_list, arch_match)) != -1)
> +		al_size_ret++;
> +	if (al_size_ret == 0)
> +		goto fail;
> +	/* Finally, Create arch_list and fill it */
> +	*arch = al_create(al_size_ret);
> +	for (i = arch_match; i < (arch_match + al_size_ret); i++)
> +		al_push(*arch, &architectures[i]);
> +
> +	free(a_full_list);
> +	return 0;
> +fail:
> +	free(a_full_list);
> +	return -1;
> +}
> +
> +struct arch_service *
> +arch_dispatcher(unsigned request_type, char *arch)
> +{
> +	struct utsname info_uname;
> +	int i;
> +	ARCH_LIST_DEFINE(arch_list) = NULL;
> +
> +	/* If user don't type any option in ARCH_REQ group, it means
> +	   get current arch */
> +	if ((request_type & (1 << AD_REQ_GET_ARCH_BIT)) ||
> +	    (!(request_type & AD_REQ_MASK))) {
> +		uname(&info_uname);
> +		if (form_arch_list(&arch_list, info_uname.machine) == -1)
> +			goto fail;
> +		goto done;
> +	}
> +
> +	if (request_type & (1 << AD_REQ_SET_ARCH_BIT)) {
> +		if (form_arch_list(&arch_list, arch) == -1)
> +			goto fail;
> +		goto done;
> +	}
> +
> +	if ((request_type & (1 << AD_REQ_LIST_ARCH_BIT))) {
> +		arch_list = al_create(architectures_size);
> +		for (i = 0; i < architectures_size; i++) {
> +			al_push(arch_list, &(architectures[i]));
> +			al_set_flag(arch_list, i, AD_FLAG_PRINT);
> +		}
> +		goto done;
> +	}
> +fail:
> +	arch_list = NULL;
> +done:
> +	return arch_list;
> +}
> +
> +int
> +abi_dispatcher(struct arch_service *a_serv, unsigned request_type, char *abi)
> +{
> +	int i = 0;
> +	enum arch_type arch_num = ARCH_no_arch;
> +	int abi_modes = 0;
> +	int arch_size = 0;
> +	int flag = 0;
> +
> +	if (a_serv == NULL)
> +		return -1;
> +	arch_size = al_size(a_serv);
> +	abi_modes = al_get_abi_modes(a_serv, 0);
> +	/* The strace package could be compiled as 32bit app on 64bit
> +	   architecture, therefore asinfo has to detect it and print out
> +	   corresponding personality. Frankly speaking, it is necessary to
> +	   detect strace package personality */
> +	if ((request_type & (1 << ABD_REQ_GET_ABI_BIT)) ||
> +	    (!(request_type & ABD_REQ_MASK))) {
> +		arch_num = al_arch_num(a_serv, 0);
> +		switch (arch_num) {
> +		case ARCH_x86_64_64bit:
> +			al_set_flag(a_serv, al_find_arch(a_serv,
> +#if defined(X86_64)
> +				    ARCH_x86_64_64bit
> +#elif defined(X32)
> +				    ARCH_x86_64_x32
> +#else
> +				    ARCH_x86_64_32bit
> +#endif
> +				    ), AD_FLAG_PRINT);
> +			break;
> +		case ARCH_arm_oabi:
> +			al_set_flag(a_serv, al_find_arch(a_serv,
> +#if defined(__ARM_EABI__)
> +				    ARCH_arm_eabi
> +#else
> +				    ARCH_arm_oabi
> +#endif
> +				    ), AD_FLAG_PRINT);
> +			break;
> +		case ARCH_mips_o32:
> +			al_set_flag(a_serv, al_find_arch(a_serv,
> +#if defined(LINUX_MIPSO32)
> +				    ARCH_mips_o32
> +#elif defined(LINUX_MIPSN32)
> +				    ARCH_mips_n32
> +#else
> +				    ARCH_mips_n64
> +#endif
> +				    ), AD_FLAG_PRINT);
> +			break;
> +		default:
> +			/* Other cases should be printed using default rule:
> +			   print first ABI mode + other arch names */
> +			al_set_flag(a_serv, 0, AD_FLAG_PRINT);
> +			for (i = abi_modes; i < arch_size; i++)
> +				al_set_flag(a_serv, i, AD_FLAG_PRINT);
> +		}
> +		goto done;
> +	}
> +
> +	if (request_type & (1 << ABD_REQ_LIST_ABI_BIT)) {
> +		for (i = 0; i < abi_modes; i++)
> +			al_set_flag(a_serv, i, AD_FLAG_PRINT);
> +		goto done;
> +	}
> +
> +	if (request_type & (1 << ABD_REQ_SET_ABI_BIT)) {
> +		if (abi == NULL)
> +			goto fail;
> +		for (i = 0; i < abi_modes; i++)
> +			if (strcmp(abi, al_abi_mode(a_serv, i)) == 0) {
> +				al_set_flag(a_serv, i, AD_FLAG_PRINT);
> +				flag = 1;
> +			}
> +		if (!flag)
> +			goto fail;
> +	}
> +done:
> +	return 0;
> +fail:
> +	return -1;
> +}
> diff --git a/tools/asinfo/dispatchers.h b/tools/asinfo/dispatchers.h
> new file mode 100644
> index 00000000..dc76feb8
> --- /dev/null
> +++ b/tools/asinfo/dispatchers.h
> @@ -0,0 +1,60 @@
> +/*
> + * The dispatchers.h contains all necessary functions to perform main
> + * work in the asinfo tool.
> + *
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.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) = xcalloc(sizeof(*(name)), (size + 1))
> +
> +/* 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 provide correct list of architectures
> + */
> +struct arch_service *arch_dispatcher(unsigned request_type, char* arch);
> +
> +/* Final filtering based on personality */
> +int abi_dispatcher(struct arch_service *a_serv, unsigned request_type,
> +		   char *abi);
> +
> +#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..895b043c
> --- /dev/null
> +++ b/tools/asinfo/request_msgs.h
> @@ -0,0 +1,115 @@
> +/*
> + * The request_msgs are messages used by dispatchers in asinfo tool to
> + * operate with static data base.
> + *
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.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 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 abi_req_bit {
> +	ABD_REQ_SET_ABI_BIT = ARCH_REQ_BIT_LAST,
> +	ABD_REQ_GET_ABI_BIT,
> +	ABD_REQ_LIST_ABI_BIT,
> +
> +	ABD_REQ_BIT_LAST
> +};
> +
> +enum fd_req_bit {
> +	FD_REQ_SET_BASE_FILTER_BIT = ABD_REQ_BIT_LAST,
> +
> +	FD_REQ_BIT_LAST
> +};
> +
> +#define ENUM_FLAG(name) name = name##_BIT
Looks like I've made a mistake when wrote a code snippet example, there
should be a bit shift by amount of bits from the bit enumeration:

	#define ENUM_FLAG(name) name = 1 << name##_BIT

> +enum req_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(ABD_REQ_SET_ABI),
> +	ENUM_FLAG(ABD_REQ_GET_ABI),
> +	ENUM_FLAG(ABD_REQ_LIST_ABI),
> +	ENUM_FLAG(FD_REQ_SET_BASE_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 ABD_REQ_MASK BITMASK(ABD_REQ_BIT_LAST, ARCH_REQ_BIT_LAST)
> +#define FD_REQ_MASK BITMASK(FD_REQ_BIT_LAST, ABD_REQ_BIT_LAST)
> +
> +/* 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.


The implementation of architecture name aliases looks pretty convoluted.
The same for arch dispatcher, especially in form_arch_list part. It's
quite difficult to evaluate tool's functionality without any user
manual.




More information about the Strace-devel mailing list