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

Edgar Kaziakhmedov edgar.kaziakhmedov at virtuozzo.com
Mon Jul 31 22:13:56 UTC 2017


On Mon, 31 Jul 2017 06:19:23 +0200
Eugene Syromiatnikov <esyr at redhat.com> wrote:

> 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.
Ok, It makes sense
> 
> > +
> > +/*
> > + * 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.
When we don't have a several personalities for architecture, we just
set the default bitness.
> 
> > +};
> > +
> > +/* 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.
Is sounds reasonable.
> 
> > +	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.
To get rid of strcmp as I understand?
> 
> > +
> > +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?
Sure, it is disgusting, I have reduced complexity to n.
> 
> > +	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.
For now, yes, but later it will be used to find subcalls in syscallent
array.
> 
> > +	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.
Yes, I see, I called it this way, because I'd catch cases when there is
one bit or no set bit, therefore names speak about it.
> 
> > +
> > +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.
> 
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Strace-devel mailing list
> Strace-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/strace-devel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20170801/5b97608b/attachment.bin>


More information about the Strace-devel mailing list