On Sat, Aug 05, 2017 at 04:57:36AM +0300, Edgar Kaziakhmedov wrote:
> From: Edgar Kaziakhmedov <edgar.kaziakhme...@virtuzzo.com>
"virtuozzo"

> 
> The main purpose of this program is to present all information concluded
> at sysent.h files as a query tool.
> The asinfo tool has the following architecture:
> command dispatcher->architecture dispatcher->abi dispatcher->
> system call dispatcher->filter dispatcher.
> Each dispatcher accepts proccesed data from previous one.
> 
> This point is illustrated by the following example:
> $ asinfo --get-arch --get-sysc write
> 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 ABI mode set at compile
Does AD stand for "architecture dispatcher" or "ABI dispatcher"?

> time of strace package. Therefore, syscall_dispatcher accepts this
> architecture/ABI and works with specific set of system calls. It is worth
> mentioning that it supports all architectures/ABIs supported by strace.
> 
> * Makefile.am (SUBDIRS): Add tools directory.
> * configure.ac (AC_CONFIG_FILES): Add Makefile's.
"Makefiles"

> * 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. Introduce struct
> arch_descriptor. Introduce arch_service. Prototype methods to simplify
> work with the arch_service.
> * tools/asinfo/arch_interface.c: New file. Implement it.
> * tools/asinfo/syscall_interface.h: New file. Introduce syscall_service.
> Prototype methods to simplify work with syscall_service.
> * tools/asinfo/syscall_interface.c: New file. Implement it.
> * tools/asinfo/request_msgs.h: New file. Introduce main requests.
> * tools/asinfo/asinfo.c: New file. Implement support of all options.
> Implement usage.
> * tools/asinfo/asinfo.1: New file. Empty man.
> 
> Signed-off-by: Edgar Kaziakhmedov <edgar.kaziakhme...@virtuozzo.com>
> ---
>  Makefile.am                      |   2 +-
>  configure.ac                     |   2 +
>  tools/Makefile.am                |  28 ++
>  tools/asinfo/Makefile.am         |  59 +++
>  tools/asinfo/arch_interface.c    | 865 
> +++++++++++++++++++++++++++++++++++++++
>  tools/asinfo/arch_interface.h    | 185 +++++++++
>  tools/asinfo/asinfo.1            |   0
>  tools/asinfo/asinfo.c            | 245 +++++++++++
>  tools/asinfo/dispatchers.c       | 253 ++++++++++++
>  tools/asinfo/dispatchers.h       |  48 +++
>  tools/asinfo/request_msgs.h      | 100 +++++
>  tools/asinfo/syscall_interface.c | 339 +++++++++++++++
>  tools/asinfo/syscall_interface.h | 114 ++++++
>  13 files changed, 2239 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
>  create mode 100644 tools/asinfo/syscall_interface.c
>  create mode 100644 tools/asinfo/syscall_interface.h
> 
> diff --git a/Makefile.am b/Makefile.am
> index ae119a75..ff89f3c5 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 7a9abf8f..ee5f651c 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -814,6 +814,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.kaziakhme...@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..924e3585
> --- /dev/null
> +++ b/tools/asinfo/Makefile.am
> @@ -0,0 +1,59 @@
> +# Automake input for asinfo.
> +#
> +# Copyright (c) 2017 Edgar Kaziakhmedov <edgar.kaziakhme...@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 =             \
> +     arch_interface.c        \
> +     arch_interface.h        \
> +     asinfo.c                \
> +     dispatchers.c           \
> +     dispatchers.h           \
> +     ../../error_prints.c    \
> +     ../../error_prints.h    \
> +     ../../macros.h          \
> +     requests_msgs.h         \
"request_msgs.h"

> +     ../../shorthand-def.h   \
"../../shorthand_def.h"

> +     syscall_interface.c     \
> +     syscall_interface.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..efd2def4
> --- /dev/null
> +++ b/tools/asinfo/arch_interface.c
> @@ -0,0 +1,865 @@
> +/*
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov 
> <edgar.kaziakhme...@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 DEFINE_SHORTHAND
> +#include "shorthand_def.h"
> +
> +/*
> + * 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[] = {};
static const

> +
> +/* ARCH_blackfin */
> +struct_sysent blackfin_32bit_sysent[] = {
static const

> +     #include "bfin/syscallent.h"
> +};
> +const int blackfin_32bit_usr1 = 0;
static

> +const int blackfin_32bit_usr2 = 0;
static

> +/* ARCH_ia64 */
> +struct_sysent ia64_64bit_sysent[] = {
static const

> +     #include "ia64/syscallent.h"
> +};
> +const int ia64_64bit_usr1 = 0;
static

> +const int ia64_64bit_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_m68k */
> +struct_sysent m68k_32bit_sysent[] = {
static const

> +     #include "m68k/syscallent.h"
> +};
> +const int m68k_32bit_usr1 = 0;
static

> +const int m68k_32bit_usr2 = 0;
static

> +/* ARCH_sparc64 64bit ABI */
> +struct_sysent sparc64_64bit_sysent[] = {
static const

> +     #include "sparc64/syscallent.h"
> +};
> +const int sparc64_64bit_usr1 = 0;
static

> +const int sparc64_64bit_usr2 = 0;
static

> +/* ARCH_sparc64 32bit ABI */
> +struct_sysent sparc64_32bit_sysent[] = {
static const

> +     #include "sparc64/syscallent1.h"
> +};
> +const int sparc64_32bit_usr1 = 0;
static

> +const int sparc64_32bit_usr2 = 0;
static

> +/* ARCH_sparc */
> +struct_sysent sparc_32bit_sysent[] = {
static const

> +     #include "sparc/syscallent.h"
> +};
> +const int sparc_32bit_usr1 = 0;
static

> +const int sparc_32bit_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_metag */
> +struct_sysent metag_32bit_sysent[] = {
static const

> +     #include "metag/syscallent.h"
> +};
> +const int metag_32bit_usr1 = 0;
static

> +const int metag_32bit_usr2 = 0;
static

> +/* ARCH_mips o32 ABI */
> +#ifndef LINUX_MIPSO32
> +# define LINUX_MIPSO32 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent mips_o32_sysent[] = {
static const

> +     #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 = 0;
static

> +const int mips_o32_usr2 = 0;
static

> +#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[] = {
static const

> +     #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 = 0;
static

> +const int mips_n32_usr2 = 0;
static

> +#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[] = {
static const

> +     #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 = 0;
static

> +const int mips_n64_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_alpha */
> +struct_sysent alpha_64bit_sysent[] = {
static const

> +     #include "alpha/syscallent.h"
> +};
> +const int alpha_64bit_usr1 = 0;
static

> +const int alpha_64bit_usr2 = 0;
static

> +/* ARCH_ppc */
> +struct_sysent ppc_32bit_sysent[] = {
static const

> +     #include "powerpc/syscallent.h"
> +};
> +const int ppc_32bit_usr1 = 0;
static

> +const int ppc_32bit_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_ppc64 64bit ABI */
> +struct_sysent ppc64_64bit_sysent[] = {
static const

> +     #include "powerpc64/syscallent.h"
> +};
> +const int ppc64_64bit_usr1 = 0;
static

> +const int ppc64_64bit_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_ppc64 32bit ABI */
> +struct_sysent ppc64_32bit_sysent[] = {
static const

> +     #include "powerpc64/syscallent1.h"
> +};
> +const int ppc64_32bit_usr1 = 0;
static

> +const int ppc64_32bit_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_arm OABI*/
> +#ifdef __ARM_EABI__
> +# undef __ARM_EABI__
> +# define NOW_UNDEFINED 1
> +#endif
> +struct_sysent arm_oabi_sysent[] = {
static const

> +     #include "arm/syscallent.h"
> +};
> +const int arm_oabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
static

> +const int arm_oabi_usr2 = ARM_LAST_SPECIAL_SYSCALL;
static

> +#undef ARM_FIRST_SHUFFLED_SYSCALL
> +#undef ARM_LAST_SPECIAL_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[] = {
static const

> +     #include "arm/syscallent.h"
> +};
> +const int arm_eabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
static

> +const int arm_eabi_usr2 = ARM_LAST_SPECIAL_SYSCALL;
static

> +#undef ARM_FIRST_SHUFFLED_SYSCALL
> +#undef ARM_LAST_SPECIAL_SYSCALL
> +#ifdef NOW_DEFINED
> +# undef __ARM_EABI__
> +# undef NOW_DEFINED
> +#endif
> +/* ARCH_aarch64 64bit ABI */
> +struct_sysent aarch64_64bit_sysent[] = {
static const

> +     #include "aarch64/syscallent.h"
> +};
> +const int aarch64_64bit_usr1 = 0;
static

> +const int aarch64_64bit_usr2 = 0;
static

> +/* ARCH_aarch64 32bit ABI */
> +#ifndef __ARM_EABI__
> +# define __ARM_EABI__ 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent aarch64_32bit_sysent[] = {
static const

> +     #include "aarch64/syscallent1.h"
> +};
> +const int aarch64_32bit_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
static

> +const int aarch64_32bit_usr2 = ARM_LAST_SPECIAL_SYSCALL;
static

> +#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[] = {
static const

> +     #include "avr32/syscallent.h"
> +};
> +const int avr32_32bit_usr1 = 0;
static

> +const int avr32_32bit_usr2 = 0;
static

> +/* ARCH_arc */
> +struct_sysent arc_32bit_sysent[] = {
static const

> +     #include "arc/syscallent.h"
> +};
> +const int arc_32bit_usr1 = 0;
static

> +const int arc_32bit_usr2 = 0;
static

> +/* ARCH_s390 */
> +struct_sysent s390_32bit_sysent[] = {
static const

> +     #include "s390/syscallent.h"
> +};
> +const int s390_32bit_usr1 = 0;
static

> +const int s390_32bit_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_s390x */
> +struct_sysent s390x_64bit_sysent[] = {
static const

> +     #include "s390x/syscallent.h"
> +};
> +const int s390x_64bit_usr1 = 0;
static

> +const int s390x_64bit_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_hppa */
> +struct_sysent hppa_32bit_sysent[] = {
static const

> +     #include "hppa/syscallent.h"
> +};
> +const int hppa_32bit_usr1 = 0;
static

> +const int hppa_32bit_usr2 = 0;
static

> +/* ARCH_parisc */
> +#define parisc_32bit_sysent dummy_sysent
> +const int parisc_32bit_usr1 = 0;
static

> +const int parisc_32bit_usr2 = 0;
static

> +/* ARCH_sh */
> +struct_sysent sh_32bit_sysent[] = {
static const

> +     #include "sh/syscallent.h"
> +};
> +const int sh_32bit_usr1 = 0;
static

> +const int sh_32bit_usr2 = 0;
static

> +/* ARCH_sh64 */
> +struct_sysent sh64_64bit_sysent[] = {
static const

> +     #include "sh64/syscallent.h"
> +};
> +const int sh64_64bit_usr1 = 0;
static

> +const int sh64_64bit_usr2 = 0;
static

> +/* ARCH_x86 */
> +struct_sysent x86_32bit_sysent[] = {
static const

> +     #include "i386/syscallent.h"
> +};
> +const int x86_32bit_usr1 = 0;
static

> +const int x86_32bit_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_i386 */
> +#define i386_32bit_sysent dummy_sysent
> +const int i386_32bit_usr1 = 0;
static

> +const int i386_32bit_usr2 = 0;
static

> +/* ARCH_i486 */
> +#define i486_32bit_sysent dummy_sysent
> +const int i486_32bit_usr1 = 0;
static

> +const int i486_32bit_usr2 = 0;
static

> +/* ARCH_i586 */
> +#define i586_32bit_sysent dummy_sysent
> +const int i586_32bit_usr1 = 0;
static

> +const int i586_32bit_usr2 = 0;
static

> +/* ARCH_i686 */
> +#define i686_32bit_sysent dummy_sysent
> +const int i686_32bit_usr1 = 0;
static

> +const int i686_32bit_usr2 = 0;
static

I don't quite understand why these definitions are per-alias and not
per-ABI.

> +/* ARCH_x86_64 64bit ABI mode */
> +struct_sysent x86_64_64bit_sysent[] = {
static const

> +     #include "x86_64/syscallent.h"
> +};
> +const int x86_64_64bit_usr1 = 0;
static

> +const int x86_64_64bit_usr2 = 0;
static

> +/* ARCH_x86_64 32bit ABI mode */
> +struct_sysent x86_64_32bit_sysent[] = {
static const

> +     #include "x86_64/syscallent1.h"
> +};
> +const int x86_64_32bit_usr1 = 0;
static

> +const int x86_64_32bit_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_x86_64 x32 ABI mode */
> +struct_sysent x86_64_x32_sysent[] = {
static const

> +     #include "x86_64/syscallent2.h"
> +};
> +const int x86_64_x32_usr1 = 0;
static

> +const int x86_64_x32_usr2 = 0;
static

> +/* ARCH_amd64 */
> +#define amd64_64bit_sysent dummy_sysent
> +const int amd64_64bit_usr1 = 0;
static

> +const int amd64_64bit_usr2 = 0;
static

> +/* ARCH_cris */
> +struct_sysent cris_32bit_sysent[] = {
static const

> +     #include "crisv10/syscallent.h"
> +};
> +const int cris_32bit_usr1 = 0;
static

> +const int cris_32bit_usr2 = 0;
static

> +/* ARCH_crisv10 */
> +#define crisv10_32bit_sysent dummy_sysent
> +const int crisv10_32bit_usr1 = 0;
static

> +const int crisv10_32bit_usr2 = 0;
static

> +/* ARCH_crisv32 */
> +struct_sysent crisv32_32bit_sysent[] = {
static const

> +     #include "crisv32/syscallent.h"
> +};
> +const int crisv32_32bit_usr1 = 0;
static

> +const int crisv32_32bit_usr2 = 0;
static

> +#undef SYS_socket_subcall
> +/* ARCH_tile 64bit ABI mode */
> +struct_sysent tile_64bit_sysent[] = {
static const

> +     #include "tile/syscallent.h"
> +};
> +const int tile_64bit_usr1 = 0;
static

> +const int tile_64bit_usr2 = 0;
static

> +/* ARCH_tile 32bit ABI mode */
> +struct_sysent tile_32bit_sysent[] = {
static const

> +     #include "tile/syscallent1.h"
> +};
> +const int tile_32bit_usr1 = 0;
static

> +const int tile_32bit_usr2 = 0;
static

> +/* ARCH_microblaze */
> +struct_sysent microblaze_32bit_sysent[] = {
static const

> +     #include "microblaze/syscallent.h"
> +};
> +const int microblaze_32bit_usr1 = 0;
static

> +const int microblaze_32bit_usr2 = 0;
static

> +/* ARCH_nios2 */
> +struct_sysent nios2_32bit_sysent[] = {
static const

> +     #include "nios2/syscallent.h"
> +};
> +const int nios2_32bit_usr1 = 0;
static

> +const int nios2_32bit_usr2 = 0;
static

> +/* ARCH_openrisc */
> +struct_sysent openrisc_32bit_sysent[] = {
static const

> +     #include "or1k/syscallent.h"
> +};
> +const int openrisc_32bit_usr1 = 0;
static

> +const int openrisc_32bit_usr2 = 0;
static

> +/* ARCH_xtensa */
> +struct_sysent xtensa_32bit_sysent[] = {
static const

> +     #include "xtensa/syscallent.h"
> +};
> +const int xtensa_32bit_usr1 = 0;
static

> +const int xtensa_32bit_usr2 = 0;
static

> +/* ARCH_riscv 64bit ABI mode */
> +struct_sysent riscv_64bit_sysent[] = {
static const

> +     #include "riscv/syscallent.h"
> +};
> +const int riscv_64bit_usr1 = 0;
static

> +const int riscv_64bit_usr2 = 0;
static

> +/* ARCH_riscv 32bit ABI mode */
> +struct_sysent riscv_32bit_sysent[] = {
static const

> +     #include "riscv/syscallent1.h"
> +};
> +const int riscv_32bit_usr1 = 0;
static

> +const int riscv_32bit_usr2 = 0;
static

> +
> +#undef DEFINE_SYSCALLENT
> +
> +#define DEFINE_SHORTHAND
> +#include "shorthand_def.h"
> +
> +#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), \
> +             .syscall_list           = arch##_##mode##_sysent, \
> +             .user_num1              = &arch##_##mode##_usr1, \
> +             .user_num2              = &arch##_##mode##_usr2, \
> +     }
I think that having list of aliases defined as a list of strings inside
of ABI descriptor would significantly ease many things.

The other thing I think superfluous is things like x86_64_32bit. I
think, we can provide the information about compatible ABIs (other than
native one) in yet another field.

So something like this should be fine:

        #define MAX_ALIASES  6
        #define MAX_ALT_PERS 4

        struct arch_descriptor {
                /* enum arch_name_abi arch_num; */
                        /* This should be equivalent to array index, but if
                         * you want to pass the pointer to arch_descriptor
                         * outside array, it probably makes sense to leave
                         * it here as is */

                const char *arch_names[MAX_ALIASES];
                const char *abi_mode;
                int abi_mode_len;
                const int max_scn;
                struct_sysent *syscall_list;
                uint64_t compatible_pers;
                const int *user_num1;
                const int *user_num2;
        }

And the definition macro like this:

        #define ARCH_DESC_DEFINE(arch, mode, compat_pers, ...) \
                [ARCH_##arch##_##mode] = { \
                        /* .arch_num            = ARCH_##arch##_##mode, */ \
                        .arch_names             = { __VA_ARGS__ }, \
                        .abi_mode               = #mode, \
                        .abi_mode_len           = ARRAY_SIZE(#arch) - 1, \
                        .max_scn                = 
ARRAY_SIZE(arch##_##mode##_sysent), \
                        .syscall_list           = arch##_##mode##_sysent, \
                        .user_num1              = &arch##_##mode##_usr1, \
                        .user_num2              = &arch##_##mode##_usr2, \
                }

And definitions like this:

        ARCH_DESC_DEFINE(x86,    32bit, 0, "x86", "i386", "i486", "i586", 
"i686"),
        ARCH_DESC_DEFINE(x86_64, 64bit, 1 << ARCH_x86_32bit | 1 << 
ARCH_x86_64_x32, "x86_64", "amd64", "EM64T"),
        ARCH_DESC_DEFINE(x86_64, x32, 1 << ARCH_x86_32bit, "x32"),
        ...

This way, you're getting rid of "base_arch" concept, needless
duplication of variables, leaving other places essentially the same (the
search is still linear, just over jagged two-dimensional array
containing the same amount of element, output alignment code, however,
is going to be a little worse, as I dropped arch_name_len, since I don't
see an easy way to derive it with this setup)




> +/* Generate array of arch_descriptors for each architecture and mode */
> +struct arch_descriptor architectures[] = {
const

> +     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   )
> +};
> +
> +/* 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 = NULL;
> +
> +     if (!capacity)
> +             return NULL;
> +     as = xcalloc(sizeof(*as), 1);
> +     as->arch_list = xcalloc(sizeof(*(as->arch_list)), capacity);
> +     as->flag = xcalloc(sizeof(*(as->flag)), 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->flag[m->next_free] = AD_FLAG_EMPTY;
> +     m->next_free++;
> +     return 0;
> +}
> +
> +static inline int
> +al_is_index_ok(struct arch_service *m, unsigned index) {
Opening brace should be on a separate line.

> +     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->flag[index] = 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->flag)?

> +     free(m);
> +}
> +
> +enum arch_name_abi
> +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_name_abi
> +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)
> +{
> +     int status = al_is_index_ok(m, index);
> +
> +     return (!status ? m->flag[index] : -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->syscall_list[i].sys_name &&
> +                !(elem->syscall_list[i].sys_flags &
> +                TRACE_INDIRECT_SUBCALL))
Condition continuation should be indented with 4 spaces.

> +                     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_name_abi base_arch = ARCH_no_arch;
> +     const char *arch_name = NULL;
> +     int mode = 0;
> +     int i = 0;
> +
> +     if (al_is_index_ok(m, index) != 0)
> +             return -1;
> +     /* Is input arch ABI mode? */
> +     if (al_arch_base_num(m, index) == al_arch_num(m, index))
> +             mode = 1;
> +     /* Search base arch */
> +     base_arch = al_arch_base_num(m, index);
> +     arch_name = al_arch_name(m, index);
> +     for (i = index; i >= 0; i--) {
> +             if (!mode && (al_arch_num(m, i) != base_arch))
> +                     continue;
> +             else {
> +                     if (!mode)
> +                             arch_name = al_arch_name(m, i);
> +                     mode = 1;
> +             }
> +             if (mode && !strcmp(arch_name, al_arch_name(m, i)))
> +                     continue;
> +             break;
> +     }
> +     return i + 1;
> +}
> +
> +/* This method is purposed to count the supported ABI modes for the given
> +   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;
> +     index = al_find_base_arch(m, index);
> +     for (i = index; i < arch_size; i++) {
> +             if (strcmp(arch_name, al_arch_name(m, i)) == 0) {
> +                     abi_count++;
> +                     continue;
> +             }
> +             break;
> +     }
> +     return abi_count;
> +}
> +
> +/* If index is related to the first definition of arch in arch_list -> 0 */
> +int
> +al_is_arch_source(struct arch_service *m, unsigned index)
> +{
> +     int abi_modes = 0;
> +     unsigned base_index = 0;
> +
> +     if (al_arch_num(m, index) != al_arch_base_num(m, index) ||
> +         al_arch_num(m, index) == ARCH_no_arch)
> +             return -1;
> +     base_index = al_find_base_arch(m, index);
> +     abi_modes = al_get_abi_modes(m, index);
> +     if ((index >= base_index) && (index < base_index + abi_modes))
> +             return 0;
> +     return -1;
> +}
> +
> +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->syscall_list[i].sys_name == NULL)
> +                     continue;
> +             /* It is enough to find just semop sybcall */
> +             if (!strcmp(elem->syscall_list[i].sys_name, "semop")) {
> +                     if (!(elem->syscall_list[i].sys_flags &
> +                          TRACE_INDIRECT_SUBCALL))
> +                             impl_buf = IMPL_ext;
> +                     else if (impl_buf == IMPL_ext)
> +                             impl_buf = IMPL_int_ext;
> +                     else
> +                             impl_buf = IMPL_int;
> +             }
> +     }
> +     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->syscall_list[i].sys_name == NULL)
> +                     continue;
> +             /* It is enough to find just socket sybcall */
> +             if (!strcmp(elem->syscall_list[i].sys_name, "socket")) {
> +                     if (!(elem->syscall_list[i].sys_flags &
> +                          TRACE_INDIRECT_SUBCALL))
> +                             impl_buf = IMPL_ext;
> +                     else if (impl_buf == IMPL_ext)
> +                             impl_buf = IMPL_int_ext;
> +                     else
> +                             impl_buf = IMPL_int;
> +             }
> +     }
> +     return impl_buf;
> +}
All this information can be generated statically by some build-time
script.

> +
> +int al_find_arch(struct arch_service *m, enum arch_name_abi 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;
> +}
> +
> +void
> +al_dump(struct arch_service *m)
> +{
> +     const char *title[] = {
static

> +             "N",
> +             "Architecture name",
> +             "ABI mode",
> +             /* Implemented syscalls */
> +             "IMPL syscalls",
> +             /* IPC implementation */
> +             "IPC IMPL",
> +             /* SOCKET implementation */
> +             "SOCKET IMPL"
> +     };
> +     int title_len[] = {
> +             0,
> +             strlen(title[1]),
> +             strlen(title[2]),
> +             strlen(title[3]),
> +             strlen(title[4]),
> +             strlen(title[5]),
> +     };
> +     const char *impl_st[] = {
static

> +             "external",
> +             "internal",
> +             "int/ext"
> +     };
> +     int i = 0;
> +     int lbase_arch = 0;
> +     int temp_len = 0;
> +     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)
> +             title_len[0]++;
> +     for (i = 0; i < arch_size; i++) {
> +             /* Calculate length of the column with the
> +                architectures name */
> +             if (al_is_arch_source(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 > title_len[1])
> +                     title_len[1] = temp_len;
> +             /* Calculate length of the column with the ABI mode */
> +             if (al_abi_mode_len(m, i) > title_len[2])
> +                     title_len[2] = al_abi_mode_len(m, i);
> +     }
> +
> +     arch_name_buf = xcalloc(title_len[1], sizeof(*arch_name_buf));
> +     /* Output title */
> +     printf("| %*s | %*s | %*s | %*s | %*s | %*s |\n",
> +             title_len[0], title[0], title_len[1], title[1],
> +             title_len[2], title[2], title_len[3], title[3],
> +             title_len[4], title[4], title_len[5], title[5]);
> +     /* Output architectures */
> +     for (i = 0; i < arch_size; i++) {
> +             if ((al_is_arch_source(m, i) == -1) ||
> +                 !(al_flag(m, i) & AD_FLAG_PRINT))
> +                     continue;
> +             printf("| %*u | ", title_len[0], 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 | ", title_len[1], arch_name_buf);
> +             printf("%*s | ", title_len[2], al_abi_mode(m, i));
> +             printf("%*d | ", title_len[3], al_syscall_impl(m, i));
> +             printf("%*s | ", title_len[4], impl_st[al_ipc_syscall(m, i)]);
> +             printf("%*s |\n", title_len[5], impl_st[al_sck_syscall(m, i)]);
> +             N++;
> +             memset(arch_name_buf, 0, title_len[1]);
> +     }
> +     free(arch_name_buf);
> +}
> diff --git a/tools/asinfo/arch_interface.h b/tools/asinfo/arch_interface.h
> new file mode 100644
> index 00000000..052e4716
> --- /dev/null
> +++ b/tools/asinfo/arch_interface.h
> @@ -0,0 +1,185 @@
> +/*
> + * 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.kaziakhm...@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_name_abi format name_arch = ARCH_ + kernel_kernel/other_name +
> +   abi_mode */
> +enum arch_name_abi {
> +     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
> +};
> +
> +struct arch_descriptor {
> +     enum arch_name_abi arch_num;
> +     const char *arch_name;
> +     const int arch_name_len;
> +     enum arch_name_abi arch_base_num;
> +     const char *abi_mode;
> +     const int abi_mode_len;
> +     const int max_scn;
> +     struct_sysent *syscall_list;
> +     /* In the most cases these fields are purposed to store specific for
> +        given arch constants, for instance, ARM_FIRST_SHUFFLED_SYSCALL */
> +     const int *user_num1;
> +     const int *user_num2;
> +};
> +
> +#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
> +
> +/* To provide push-back interface with arch_list */
> +struct arch_service {
> +     /* immutable field */
> +     struct arch_descriptor **arch_list;
> +     /* User flags for each arch_descriptor */
> +     int *flag;
> +     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_name_abi 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_name_abi 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_source(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_name_abi 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..a3ad9933
> --- /dev/null
> +++ b/tools/asinfo/asinfo.c
> @@ -0,0 +1,245 @@
> +/*
> + * 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.kaziakhme...@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 "syscall_interface.h"
> +#include "xmalloc.h"
> +
> +#ifndef HAVE_PROGRAM_INVOCATION_NAME
> +char *program_invocation_name;
> +#endif
> +
> +static void
> +usage(void)
> +{
> +     printf("\
> +usage: asinfo (--set-arch arch | --get-arch | --list-arch)\n\
> +              [--set-abi abi | --get-abi | --list-abi]\n\
> +   or: asinfo [(--set-arch arch | --get-arch) [--set-abi abi | --get-abi]]\n\
> +              (--get-sysc num | name) | (--get-nargs num | name)\n\
> +\n\
> +Architecture:\n\
> +  --set-arch arch  use architecture ARCH for further operations\n\
> +  --get-arch       use architecture returned by uname for further 
> operations\n\
> +  --list-arch      print out all architectures supported by strace\n\
> +                   (combined use list-arch and any ABI option is 
> permitted)\n\
> +\n\
> +ABI:\n\
> +  --set-abi abi    use application binary interface ABI for further 
> operations\n\
> +  --get-arch       use ABI mode used at compile time for further 
> operations\n\
--get-abi?

> +  --list-arch      print out all ABIs for specified architecture\n\
--list-abi?

> +\n\
> +System call:\n\
> +  --get-sysc num   print name of system call with the NUM number\n\
> +  --get-sysc name  print number of all system calls with NAME substring\n\
> +  --get-nargs num  get number of arguments of system call with the NUM 
> number\n\
> +  --get-nargs name get number of arguments of system calls with NAME 
> substring\n\
> +\n\
> +Miscellaneous:\n\
> +  -h               print help message\n");
> +     exit(0);
You can also format it as

        printf(
                "usage: asinfo (--set-arch arch | --get-arch | --list-arch)\n"
                "              [--set-abi abi | --get-abi | --list-abi]\n"
                "   or: asinfo [(--set-arch arch | --get-arch) [--set-abi abi | 
--get-abi]]\n"
                "              (--get-sysc num | name) | (--get-nargs num | 
name)\n"
                ...

without breaking indentation. Also, since you have no arguments to
format, you can use puts() instead.

> +}
> +
> +void
> +die(void)
> +{
> +     exit(1);
> +}
> +
> +static int
> +is_more1bit(unsigned int num)
> +{
> +     return !(num & (num - 1));
> +}
> +
> +static unsigned
> +strpar2req(char *option)
> +{
> +     /* Convertion table to store string with options */
> +     const char *options[] = {
static

> +             [SD_REQ_GET_SYSC_BIT]   = "--get-sysc",
> +             [SD_REQ_GET_NARGS_BIT]  = "--get-nargs",
> +             [SD_REQ_GET_LIST_BIT]   = "--list-sysc",
> +             [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_BIT]   = "--set-abi",
> +             [ABD_REQ_GET_ABI_BIT]   = "--get-abi",
> +             [ABD_REQ_LIST_ABI_BIT]  = "--list-abi",
> +             [SERV_REQ_HELP_BIT]     = "-h",
> +     };
> +     unsigned i;
> +
> +     for (i = 0; i < ARRAY_SIZE(options); i++) {
> +             if (options[i] && strcmp(option, options[i]) == 0)
> +                     return i;
> +     }
> +     return SERV_REQ_ERROR_BIT;
> +}
> +
> +static unsigned
> +command_dispatcher(int argc, char *argv[], char *args[])
> +{
> +     int i;
> +     unsigned final_req = 0;
> +     unsigned temp_req = 0;
> +     unsigned non_req_arg = AD_REQ_GET_ARCH | AD_REQ_LIST_ARCH       |
> +                            ABD_REQ_GET_ABI | ABD_REQ_LIST_ABI       |
> +                            SD_REQ_GET_LIST;
> +
> +     if (!program_invocation_name || !*program_invocation_name) {
> +             static char name[] = "asinfo";
> +             program_invocation_name =
> +                     (argv[0] && *argv[0]) ? argv[0] : name;
> +     }
> +
> +     /* Try to find help option firstly */
"first"

> +     for (i = 1; i < argc; i++) {
> +             if (strpar2req(argv[i]) == SERV_REQ_HELP_BIT)
> +                     usage();
> +     }
> +     /* For now, is is necessary to convert string parameter to number of
> +        request and make basic check */
> +     for (i = 1; i < argc; i++) {
> +             if ((temp_req = strpar2req(argv[i])) == SERV_REQ_ERROR_BIT)
> +                     error_msg_and_help("unrecognized option '%s'",
> +                                        argv[i]);
> +             if (final_req & 1 << temp_req)
> +                     error_msg_and_help("parameter '%s' has been used "
> +                                        "more than once", argv[i]);
> +             if (!((1 << temp_req) & non_req_arg) &&
> +                  (i + 1 >= argc || strlen(argv[i + 1]) == 0 ||
> +                   strpar2req(argv[i + 1]) != SERV_REQ_ERROR_BIT))
> +                     error_msg_and_help("parameter '%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 */
> +     /* More than one option from 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("exclusive parameters");
> +     /* Check on mutually exclusive options chain */
> +     /* If at least one syscall option has been typed, therefore
> +        arch_options couldn't be list-arch and
> +        abi_option couldn't be list-abi */
> +     if ((final_req & SD_REQ_MASK) &&
> +         (((final_req & AD_REQ_MASK) && (final_req & AD_REQ_LIST_ARCH)) ||
> +          ((final_req & ABD_REQ_MASK) && (final_req & ABD_REQ_LIST_ABI))))
> +             error_msg_and_help("wrong parameters");
> +
> +     /* list-arch couldn't be used with any abi options */
> +     if ((final_req & AD_REQ_LIST_ARCH) &&
> +         (final_req & ABD_REQ_MASK))
> +             error_msg_and_help("--list-arch cannot be used with any "
> +                                "ABI parameters");
> +
> +     /* ABI requests could be used just in a combination with arch
> +        requests */
> +     if ((final_req & ABD_REQ_MASK) &&
> +         !(final_req & AD_REQ_MASK))
> +             error_msg_and_help("ABI parameters could be used only with "
> +                                "architecture parameter");
> +     return final_req;
> +}
This function is very opaque.

> +
> +static char *
> +seek_sc_arg(char **input_args)
> +{
> +     int i;
> +
> +     for (i = SD_REQ_GET_SYSC_BIT; i < SYSCALL_REQ_BIT_LAST; i++)
> +             if (input_args[i] != NULL)
> +                     return input_args[i];
> +     return NULL;
> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> +     ARCH_LIST_DEFINE(arch_list);
> +     SYSCALL_LIST_DEFINE(sc_list);
> +     /* This array is purposed to store arguments for options in the
> +        most convenient way */
> +     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_BIT]);
> +     if (arch_list == NULL)
> +             perror_msg_and_die("unrecognized architecture '%s'",
> +                                input_args[AD_REQ_SET_ARCH_BIT]);
> +     /* abi_dispatcher turn */
> +     ret = abi_dispatcher(arch_list, reqs, input_args[ABD_REQ_SET_ABI_BIT]);
> +     if (ret != 0)
> +             perror_msg_and_die("unrecognized ABI mode '%s' for a given "
> +                                "architecture",
> +                                input_args[ABD_REQ_SET_ABI_BIT]);
> +     if (ret != 0 && !input_args[ABD_REQ_SET_ABI_BIT])
> +             perror_msg_and_die("current architecture isn't supported");
> +     /* syscall_dispatcher turn */
> +     sc_list = syscall_dispatcher(arch_list, reqs, seek_sc_arg(input_args));
> +     if (ss_error(sc_list))
> +             perror_msg_and_die("%s", ss_get_serror(sc_list));
> +     /* If we want to get info about only architectures thus we print out
> +        architectures, otherwise system calls */
> +     if (!(reqs & SD_REQ_MASK))
> +             al_dump(arch_list);
> +     else
> +             ss_dump(sc_list);
> +     return 0;
> +}
> diff --git a/tools/asinfo/dispatchers.c b/tools/asinfo/dispatchers.c
> new file mode 100644
> index 00000000..11122f09
> --- /dev/null
> +++ b/tools/asinfo/dispatchers.c
> @@ -0,0 +1,253 @@
> +/*
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov 
> <edgar.kaziakhme...@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 "syscall_interface.h"
> +#include "sysent.h"
> +#include "xmalloc.h"
> +
> +extern struct arch_descriptor architectures[];
const

> +extern const int architectures_size;
> +
> +static int
> +lookup_arch(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 further 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 for arch_str in architecture list.
> +        Best match means here that we have to find the longest name of
> +        architecture in a_full_list with arch_str substring, beginning
> +        from the first letter */
sh63/sh64

> +     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 */
"First"

> +     arch_match = al_find_base_arch(a_full_list, arch_match);
> +     /* Secondly, it is necessary to calculate size of final arch_list */
"Second"

> +     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 & AD_REQ_GET_ARCH) ||
> +         (!(request_type & AD_REQ_MASK))) {
> +             uname(&info_uname);
> +             if (lookup_arch(&arch_list, info_uname.machine) == -1)
> +                     goto fail;
> +             goto done;
> +     }
> +
> +     if (request_type & AD_REQ_SET_ARCH) {
> +             if (lookup_arch(&arch_list, arch) == -1)
> +                     goto fail;
> +             goto done;
> +     }
> +
> +     if ((request_type & AD_REQ_LIST_ARCH)) {
> +             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_name_abi 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 */
I assume you can obtain this information from config.h.

> +     if ((request_type & ABD_REQ_GET_ABI) ||
> +         (!(request_type & ABD_REQ_MASK))) {
> +             arch_num = al_arch_num(a_serv, 0);
> +             switch (arch_num) {
> +             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;
> +             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_aarch64_64bit:
> +                     al_set_flag(a_serv, al_find_arch(a_serv,
> +#if defined(__ARM_EABI__)
> +                                 ARCH_aarch64_32bit
> +#else
> +                                 ARCH_aarch64_64bit
> +#endif
> +                                 ), AD_FLAG_PRINT);
> +                     break;
> +             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_tile_64bit:
> +                     al_set_flag(a_serv, al_find_arch(a_serv,
> +#if defined(__tilepro__)
> +                                 ARCH_tile_32bit
> +#else
> +                                 ARCH_tile_64bit
> +#endif
> +                                 ), AD_FLAG_PRINT);
Yet another reason for storing mask of compativle ABIs in arch
descriptor.

> +                     break;
> +             default:
> +                     /* Other cases should be printed using default rule:
> +                        print main(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 & ABD_REQ_LIST_ABI) {
> +             for (i = 0; i < abi_modes; i++)
> +                     al_set_flag(a_serv, i, AD_FLAG_PRINT);
> +             goto done;
> +     }
> +
> +     if (request_type & ABD_REQ_SET_ABI) {
> +             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;
> +}
> +
> +struct syscall_service *
> +syscall_dispatcher(struct arch_service *arch, int request_type, char *arg)
> +{
> +     SYSCALL_LIST_DEFINE(syscall_list) = ss_create(arch, request_type);
> +
> +     if (request_type & SD_REQ_MASK) {
> +             ss_update_sc_num(syscall_list);
> +             ss_mark_matches(syscall_list, arg);
> +     }
> +
> +     return syscall_list;
> +}
> +
> +
Applying: asinfo: Introduce static query tool asinfo
/home/esyr/dev/strace/.git/rebase-apply/patch:1726: new blank line at
EOF.
+
warning: 1 line adds whitespace errors.

> diff --git a/tools/asinfo/dispatchers.h b/tools/asinfo/dispatchers.h
> new file mode 100644
> index 00000000..2a62cff0
> --- /dev/null
> +++ b/tools/asinfo/dispatchers.h
> @@ -0,0 +1,48 @@
> +/*
> + * The dispatchers.h contains all necessary functions to perform main
> + * work in the asinfo tool.
> + *
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov 
> <edgar.kaziakhme...@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 "syscall_interface.h"
> +
> +/* The function is purposed to provide correct list of architectures */
> +struct arch_service *arch_dispatcher(unsigned request_type, char *arch);
> +
> +/* Final arch filtering based on personality */
> +int abi_dispatcher(struct arch_service *a_serv, unsigned request_type,
> +                char *abi);
> +
> +/* The last stage of main filtering */
> +struct syscall_service *syscall_dispatcher(struct arch_service *arch,
> +                                        int request_type, char *arg);
> +
> +#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..ea9c1337
> --- /dev/null
> +++ b/tools/asinfo/request_msgs.h
> @@ -0,0 +1,100 @@
> +/*
> + * The request_msgs are messages used by dispatchers in asinfo tool to
> + * operate with static data base.
> + *
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov 
> <edgar.kaziakhme...@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_SYSC_BIT,
> +     SD_REQ_GET_NARGS_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
> +};
> +
> +enum serv_req_bit {
> +     SERV_REQ_HELP_BIT = FD_REQ_BIT_LAST,
> +     SERV_REQ_ERROR_BIT,
> +
> +     SERV_REQ_BIT_LAST
> +};
> +
> +#define ENUM_FLAG(name) name = 1 << name##_BIT
> +enum req_type {
> +     ENUM_FLAG(SD_REQ_GET_SYSC),
> +     ENUM_FLAG(SD_REQ_GET_NARGS),
> +     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),
> +     ENUM_FLAG(SERV_REQ_HELP),
> +     ENUM_FLAG(SERV_REQ_ERROR)
> +};
> +#undef ENUM_FLAG
> +
> +#define BITMASK(hi, lo) ((1 << (hi)) - (1 << (lo)))
> +#define REQ_LAST_BIT SERV_REQ_BIT_LAST
> +#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)
> +#define SERV_REQ_MASK BITMASK(SERV_REQ_BIT_LAST, FD_REQ_BIT_LAST)
> +
> +#endif /* !STRACE_ASINFO_REQ_MSGS */
> diff --git a/tools/asinfo/syscall_interface.c 
> b/tools/asinfo/syscall_interface.c
> new file mode 100644
> index 00000000..a43ba9e7
> --- /dev/null
> +++ b/tools/asinfo/syscall_interface.c
> @@ -0,0 +1,339 @@
> +/*
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhm...@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 <stdbool.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include "arch_interface.h"
> +#include "syscall_interface.h"
> +#include "request_msgs.h"
> +#include "xmalloc.h"
> +
> +struct syscall_service *
> +ss_create(struct arch_service *m, int request_type)
> +{
> +     int i;
> +     int arch_list_size = al_size(m);
> +     struct arch_descriptor *ad = NULL;
> +     struct syscall_service *ss = NULL;
> +
> +     /* Function calling syscall_service should make sure,
> +        that there is just one arch with AD_FLAG_PRINT flag */
> +     for (i = 0; i < arch_list_size; i++)
> +             if (al_flag(m, i) & AD_FLAG_PRINT)
> +                     ad = al_get(m, i);
> +     ss = xcalloc(sizeof(*ss), 1);
> +     ss->flag = xcalloc(sizeof(*(ss->flag)), ad->max_scn);
> +     ss->real_sys_num = xcalloc(sizeof(*(ss->real_sys_num)), ad->max_scn);
> +     ss->arch = ad;
> +     ss->request_type = request_type;
> +     return ss;
> +}
> +
> +int
> +ss_flag(struct syscall_service *s, int num)
> +{
> +     if (num >= s->arch->max_scn)
> +             return -1;
> +     return s->flag[num];
> +}
> +
> +int
> +ss_set_flag(struct syscall_service *s, int num, int flag)
> +{
> +     if (num >= s->arch->max_scn)
> +             return -1;
> +     s->flag[num] = flag;
> +     return 0;
> +}
> +
> +enum input_type
> +ss_it(struct syscall_service *s)
> +{
> +     return s->it;
> +}
> +
> +void
> +ss_set_input(struct syscall_service *s, enum input_type it)
> +{
> +     s->it = it;
> +}
> +
> +int
> +ss_max_scn(struct syscall_service *s)
> +{
> +     return s->arch->max_scn;
> +}
> +
> +int
> +ss_real_num(struct syscall_service *s, int num)
> +{
> +     if (num >= s->arch->max_scn)
> +             return -1;
> +     return s->real_sys_num[num];
> +}
> +
> +int
> +ss_set_real_num(struct syscall_service *s, int num, int real_num)
> +{
> +     if (num >= s->arch->max_scn)
> +             return -1;
> +     s->real_sys_num[num] = real_num;
> +     return 0;
> +}
> +
> +const char *
> +ss_syscall_name(struct syscall_service *s, int num)
> +{
> +     return s->arch->syscall_list[num].sys_name;
> +}
> +
> +int
> +ss_syscall_flag(struct syscall_service *s, int num)
> +{
> +     return s->arch->syscall_list[num].sys_flags;
> +}
> +
> +unsigned
> +ss_syscall_nargs(struct syscall_service *s, int num)
> +{
> +     return s->arch->syscall_list[num].nargs;
> +}
> +
> +int
> +ss_user_num1(struct syscall_service *s)
> +{
> +     return *(s->arch->user_num1);
> +}
> +
> +int
> +ss_user_num2(struct syscall_service *s)
> +{
> +     return *(s->arch->user_num2);
> +}
> +
> +void
> +ss_free(struct syscall_service *s)
> +{
> +     free(s->flag);
> +     free(s);
> +}
> +
> +enum sc_error
> +ss_error(struct syscall_service *s)
> +{
> +     return s->last_error;
> +}
> +
> +void
> +ss_set_error(struct syscall_service *s, enum sc_error se)
> +{
> +     s->last_error = se;
> +}
> +
> +static const char *serrors[] = {

> +[SE_WRONG_NUMBER] = "wrong syscall number",
> +[SE_NUMBER_NON_EXIST] = "syscall with that number was not implemented",
> +[SE_NAME_NON_EXIST] = "syscall with that name doesn't exist"
Items should be indented.

> +};
> +
> +const char *
> +ss_get_serror(struct syscall_service *s)
> +{
> +     return serrors[s->last_error];
> +}
> +
> +int
> +ss_find_num(struct syscall_service *s, int real_num)
> +{
> +     int i;
> +     int max_scn = ss_max_scn(s);
> +
> +     for (i = 0; i < max_scn; i++)
> +             if (ss_real_num(s, i) == real_num)
> +                     return i;
> +     return -1;
> +}
> +
> +bool
> +ss_is_syscall_valid(struct syscall_service *s, int num)
> +{
> +     if ((num >= s->arch->max_scn) || (num < 0))
> +             return 0;
> +     return ss_syscall_name(s, num) &&
> +            !(ss_syscall_flag(s, num) & TRACE_INDIRECT_SUBCALL);
> +}
> +
> +int
> +ss_mark_matches(struct syscall_service *s, char *arg)
> +{
> +     int sc_real_number;
> +     int sc_num;
> +     char sym = 0;
> +     char *sc_name = NULL;
> +     int sc_count = 0;
> +     int i = 0;
> +     int max_scn = ss_max_scn(s);
> +
> +     /* In case of --list-sysc */
> +     if (arg == NULL) {
> +             for (i = 0; i < max_scn; i++)
> +                     if (ss_is_syscall_valid(s, i))
> +                             ss_set_flag(s, i, SS_FLAG_PRINT);
> +             return 0;
> +     }
> +
> +     /* Is it a number? */
> +     if ((sscanf(arg, "%d%c", &sc_real_number, &sym) == 0) || sym != '\0')
> +             sc_name = arg;
> +     else if (sc_real_number < 0) {
> +             ss_set_error(s, SE_WRONG_NUMBER);
> +             return -1;
> +     }
> +
> +     /* In case of name -> find arg as a substring and mark */
> +     if (sc_name != NULL) {
> +             for (i = 0; i < max_scn; i++)
> +                     if (ss_is_syscall_valid(s, i) &&
> +                         strstr(ss_syscall_name(s, i), sc_name) != NULL) {
> +                             ss_set_flag(s, i, SS_FLAG_PRINT);
> +                             sc_count++;
> +                     }
> +             if (sc_count == 0) {
> +                     ss_set_error(s, SE_NAME_NON_EXIST);
> +                     return -1;
> +             }
> +             ss_set_input(s, IT_STRING);
> +             return 0;
> +     }
> +     /* In case of number -> check and mark */
> +     sc_num = ss_find_num(s, sc_real_number);
> +     if (ss_is_syscall_valid(s, sc_num)) {
> +             ss_set_flag(s, sc_num, SS_FLAG_PRINT);
> +             ss_set_input(s, IT_NUMBER);
> +             return 0;
> +     }
> +     ss_set_error(s, SE_NUMBER_NON_EXIST);
> +     return -1;
> +}
> +
> +#ifndef __X32_SYSCALL_BIT
> +# define __X32_SYSCALL_BIT   0x40000000
> +#endif
> +
> +int
> +ss_update_sc_num(struct syscall_service *s)
> +{
> +     int i = 0;
> +     int max_scn = ss_max_scn(s);
> +     for (i = 0; i < max_scn; i++) {
> +             if (!ss_is_syscall_valid(s, i)) {
> +                     ss_set_real_num(s, i, -1);
> +                     continue;
> +             }
> +             switch (s->arch->arch_num) {
> +             case ARCH_x86_64_x32:
> +                     ss_set_real_num(s, i, i + __X32_SYSCALL_BIT);
> +                     break;
> +             case ARCH_arm_oabi:
> +             case ARCH_arm_eabi:
> +             case ARCH_aarch64_32bit:
> +                     if (i == ss_user_num1(s))
> +                             ss_set_real_num(s, i, 0x000ffff0);
> +                     if ((i >= ss_user_num1(s) + 1) &&
> +                         (i <= ss_user_num1(s) + ss_user_num2(s) + 1))
> +                             ss_set_real_num(s, i, i + 0x000f0000 -
> +                                                   ss_user_num1(s) - 1);
> +                     if (i < ss_user_num1(s))
> +                             ss_set_real_num(s, i, i);
> +                     break;
> +             case ARCH_sh64_64bit:
> +                     ss_set_real_num(s, i, i & 0xffff);
> +             default:
> +                     ss_set_real_num(s, i, i);
> +             }
> +     }
> +     return 0;
> +}
> +
> +void
> +ss_dump(struct syscall_service *s)
> +{
> +     const char *title[] = {
> +             "System call name",
> +             "Syscall num",
> +             "Nargs",
> +     };
> +     int title_len[] = {
> +             strlen(title[0]),
> +             strlen(title[1]),
> +             strlen(title[2]),
> +     };
> +     int i;
> +     int max_scn = ss_max_scn(s);
> +     int temp_len = 0;
> +
> +     /* Update title_len[0] */
> +     for (i = 0; i < max_scn; i++) {
> +             if (!(ss_flag(s, i) & SS_FLAG_PRINT))
> +                     continue;
> +             temp_len = strlen(ss_syscall_name(s, i));
> +             if (temp_len > title_len[0])
> +                     title_len[0] = temp_len;
> +     }
> +     /* Print title */
> +     if (s->request_type & SD_REQ_GET_LIST)
> +             printf("| %*s | %*s | %*s |\n", title_len[0], title[0],
> +                                             title_len[1], title[1],
> +                                             title_len[2], title[2]);
> +     if (s->request_type & SD_REQ_GET_SYSC)
> +             printf("| %*s | %*s |\n", title_len[0], title[0],
> +                                       title_len[1], title[1]);
> +     if (s->request_type & SD_REQ_GET_NARGS)
> +             printf("| %*s | %*s |\n", title_len[0], title[0],
> +                                       title_len[2], title[2]);
> +     /* Print out syscall or list of syscalls */
> +     for (i = 0; i < max_scn; i++) {
> +             if (!(ss_flag(s, i) & SS_FLAG_PRINT))
> +                     continue;
> +             if (s->request_type & SD_REQ_GET_LIST)
> +                     printf("| %*s | %*d | %*u |\n",
> +                             title_len[0], ss_syscall_name(s, i),
> +                             title_len[1], ss_real_num(s, i),
> +                             title_len[2], ss_syscall_nargs(s, i));
> +             if (s->request_type & SD_REQ_GET_SYSC)
> +                     printf("| %*s | %*d |\n",
> +                             title_len[0], ss_syscall_name(s, i),
> +                             title_len[1], ss_real_num(s, i));
> +             if (s->request_type & SD_REQ_GET_NARGS)
> +                     printf("| %*s | %*u |\n",
> +                             title_len[0], ss_syscall_name(s, i),
> +                             title_len[2], ss_syscall_nargs(s, i));
> +     }
> +}
> diff --git a/tools/asinfo/syscall_interface.h 
> b/tools/asinfo/syscall_interface.h
> new file mode 100644
> index 00000000..a8adf247
> --- /dev/null
> +++ b/tools/asinfo/syscall_interface.h
> @@ -0,0 +1,114 @@
> +/*
> + * The syscall_interface.h is purposed to interact with the basic data
> + * structure based on arch_descriptor struct. Mainly this set of methods are
> + * used by syscall_dispatcher.
> + *
> + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhm...@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_SYSCALL_INTERFACE
> +#define ASINFO_SYSCALL_INTERFACE
> +
> +#include <stdbool.h>
> +
> +#include "arch_interface.h"
> +
> +#define SS_FLAG_EMPTY 0
> +#define SS_FLAG_PRINT 1
> +
> +enum input_type {
> +     IT_STRING = 1,
> +     IT_NUMBER
> +};
> +
> +enum sc_error {
> +     SE_WRONG_NUMBER = 1,
> +     SE_NUMBER_NON_EXIST,
> +     SE_NAME_NON_EXIST,
> +};
> +
> +struct syscall_service {
> +     struct arch_descriptor *arch;
> +     /* Mutable user flags for each syscall */
> +     int *flag;
> +     int *real_sys_num;
> +     /* To choose the format while dumping */
> +     int request_type;
> +     /* To detect input type */
> +     enum input_type it;
> +     enum sc_error last_error;
> +};
> +
> +#define SYSCALL_LIST_DEFINE(name) \
> +     struct syscall_service *(name)
> +
> +/* base methods */
> +struct syscall_service *ss_create(struct arch_service *m, int request_type);
> +
> +int ss_flag(struct syscall_service *s, int num);
> +
> +int ss_set_flag(struct syscall_service *s, int num, int flag);
> +
> +enum input_type ss_it(struct syscall_service *s);
> +
> +void ss_set_input(struct syscall_service *s, enum input_type it);
> +
> +int ss_max_scn(struct syscall_service *s);
> +
> +int ss_real_num(struct syscall_service *s, int num);
> +
> +int ss_set_real_num(struct syscall_service *s, int num, int real_num);
> +
> +const char *ss_syscall_name(struct syscall_service *s, int num);
> +
> +int ss_syscall_flag(struct syscall_service *s, int num);
> +
> +unsigned ss_syscall_nargs(struct syscall_service *s, int num);
> +
> +int ss_user_num1(struct syscall_service *s);
> +
> +int ss_user_num2(struct syscall_service *s);
> +
> +void ss_free(struct syscall_service *s);
> +
> +/* error group methods */
> +enum sc_error ss_error(struct syscall_service *s);
> +
> +void ss_set_error(struct syscall_service *s, enum sc_error se);
> +
> +const char *ss_get_serror(struct syscall_service *s);
> +
> +/* calculating methods */
> +int ss_find_num(struct syscall_service *s, int real_num);
> +
> +bool ss_is_syscall_valid(struct syscall_service *s, int num);
> +
> +int ss_mark_matches(struct syscall_service *s, char *arg);
> +
> +int ss_update_sc_num(struct syscall_service *s);
> +
> +void ss_dump(struct syscall_service *s);
> +
> +#endif /* !ASINFO_SYSCALL_INTERFACE */
> -- 
> 2.11.0

So, after playing with tool a little:
 * I miss "bfin" alias for blackfin
 * For some reason, mips assumes o32/n32/n64
 * There's not be/le differentiation (I'm not sure it's needed, however,
   but I think aliases, at least, may be useful, like mipsle/mips64le
   for mips/mips64, respectively)

The features I am missing:
 * How can I select multiple architectures/ABIs? In order to see what
   are the discrepancies in numbering of specific syscall or its
   presence on specific architecture.
 * How can I select syscall classes?
 * (Looking at x32 syscall numbers) some option for hexadecimal output
   could be also useful.
 * Syscall count can be more useful, if it is calculated for the
   generated list of syscalls.
 * Matching different from substring match - what if I want to request
   open syscall specifically? Regex matching for syscall names could
   probably solve any desire in this regard. You can even employ the
   same convention as strace itself uses — no prefix means strict match,
   "%" prefix for syscall groups, "/" prefix for regex match.
 * Information about classes specific syscall belongs to may be also fo
   use.

The features this patch also lacking:
 * NEWS entry
 * man page
 * Installation rules in spec/debian directory.

------------------------------------------------------------------------------
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@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to