From: Edgar Kaziakhmedov <edgar.kaziakhme...@virtuzzo.com>

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
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.
* 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         \
+       ../../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[] = {};
+
+/* ARCH_blackfin */
+struct_sysent blackfin_32bit_sysent[] = {
+       #include "bfin/syscallent.h"
+};
+const int blackfin_32bit_usr1 = 0;
+const int blackfin_32bit_usr2 = 0;
+/* ARCH_ia64 */
+struct_sysent ia64_64bit_sysent[] = {
+       #include "ia64/syscallent.h"
+};
+const int ia64_64bit_usr1 = 0;
+const int ia64_64bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_m68k */
+struct_sysent m68k_32bit_sysent[] = {
+       #include "m68k/syscallent.h"
+};
+const int m68k_32bit_usr1 = 0;
+const int m68k_32bit_usr2 = 0;
+/* ARCH_sparc64 64bit ABI */
+struct_sysent sparc64_64bit_sysent[] = {
+       #include "sparc64/syscallent.h"
+};
+const int sparc64_64bit_usr1 = 0;
+const int sparc64_64bit_usr2 = 0;
+/* ARCH_sparc64 32bit ABI */
+struct_sysent sparc64_32bit_sysent[] = {
+       #include "sparc64/syscallent1.h"
+};
+const int sparc64_32bit_usr1 = 0;
+const int sparc64_32bit_usr2 = 0;
+/* ARCH_sparc */
+struct_sysent sparc_32bit_sysent[] = {
+       #include "sparc/syscallent.h"
+};
+const int sparc_32bit_usr1 = 0;
+const int sparc_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_metag */
+struct_sysent metag_32bit_sysent[] = {
+       #include "metag/syscallent.h"
+};
+const int metag_32bit_usr1 = 0;
+const int metag_32bit_usr2 = 0;
+/* ARCH_mips o32 ABI */
+#ifndef LINUX_MIPSO32
+# define LINUX_MIPSO32 1
+# define NOW_DEFINED 1
+#endif
+struct_sysent mips_o32_sysent[] = {
+       #include "dummy.h"
+       #include "mips/syscallent-compat.h"
+       #include "mips/syscallent-o32.h"
+};
+#ifdef NOW_DEFINED
+# undef LINUX_MIPSO32
+# undef NOW_DEFINED
+#endif
+const int mips_o32_usr1 = 0;
+const int mips_o32_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_mips n32 ABI */
+#ifndef LINUX_MIPSN32
+# define LINUX_MIPSN32 1
+# define NOW_DEFINED 1
+#endif
+struct_sysent mips_n32_sysent[] = {
+       #include "dummy.h"
+       #include "mips/syscallent-compat.h"
+       #include "mips/syscallent-n32.h"
+};
+#ifdef NOW_DEFINED
+# undef LINUX_MIPSN32
+# undef NOW_DEFINED
+#endif
+const int mips_n32_usr1 = 0;
+const int mips_n32_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_mips n64 ABI */
+#ifndef LINUX_MIPSN64
+# define LINUX_MIPSN64 1
+# define NOW_DEFINED 1
+#endif
+struct_sysent mips_n64_sysent[] = {
+       #include "dummy.h"
+       #include "mips/syscallent-compat.h"
+       #include "mips/syscallent-n64.h"
+};
+#ifdef NOW_DEFINED
+# undef LINUX_MIPSN32
+# undef NOW_DEFINED
+#endif
+const int mips_n64_usr1 = 0;
+const int mips_n64_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_alpha */
+struct_sysent alpha_64bit_sysent[] = {
+       #include "alpha/syscallent.h"
+};
+const int alpha_64bit_usr1 = 0;
+const int alpha_64bit_usr2 = 0;
+/* ARCH_ppc */
+struct_sysent ppc_32bit_sysent[] = {
+       #include "powerpc/syscallent.h"
+};
+const int ppc_32bit_usr1 = 0;
+const int ppc_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_ppc64 64bit ABI */
+struct_sysent ppc64_64bit_sysent[] = {
+       #include "powerpc64/syscallent.h"
+};
+const int ppc64_64bit_usr1 = 0;
+const int ppc64_64bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_ppc64 32bit ABI */
+struct_sysent ppc64_32bit_sysent[] = {
+       #include "powerpc64/syscallent1.h"
+};
+const int ppc64_32bit_usr1 = 0;
+const int ppc64_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_arm OABI*/
+#ifdef __ARM_EABI__
+# undef __ARM_EABI__
+# define NOW_UNDEFINED 1
+#endif
+struct_sysent arm_oabi_sysent[] = {
+       #include "arm/syscallent.h"
+};
+const int arm_oabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
+const int arm_oabi_usr2 = ARM_LAST_SPECIAL_SYSCALL;
+#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[] = {
+       #include "arm/syscallent.h"
+};
+const int arm_eabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
+const int arm_eabi_usr2 = ARM_LAST_SPECIAL_SYSCALL;
+#undef ARM_FIRST_SHUFFLED_SYSCALL
+#undef ARM_LAST_SPECIAL_SYSCALL
+#ifdef NOW_DEFINED
+# undef __ARM_EABI__
+# undef NOW_DEFINED
+#endif
+/* ARCH_aarch64 64bit ABI */
+struct_sysent aarch64_64bit_sysent[] = {
+       #include "aarch64/syscallent.h"
+};
+const int aarch64_64bit_usr1 = 0;
+const int aarch64_64bit_usr2 = 0;
+/* ARCH_aarch64 32bit ABI */
+#ifndef __ARM_EABI__
+# define __ARM_EABI__ 1
+# define NOW_DEFINED 1
+#endif
+struct_sysent aarch64_32bit_sysent[] = {
+       #include "aarch64/syscallent1.h"
+};
+const int aarch64_32bit_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
+const int aarch64_32bit_usr2 = ARM_LAST_SPECIAL_SYSCALL;
+#undef ARM_FIRST_SHUFFLED_SYSCALL
+#undef ARM_LAST_SPECIAL_SYSCALL
+#ifdef NOW_DEFINED
+# undef __ARM_EABI__
+# undef NOW_DEFINED
+#endif
+/* ARCH_avr32 */
+struct_sysent avr32_32bit_sysent[] = {
+       #include "avr32/syscallent.h"
+};
+const int avr32_32bit_usr1 = 0;
+const int avr32_32bit_usr2 = 0;
+/* ARCH_arc */
+struct_sysent arc_32bit_sysent[] = {
+       #include "arc/syscallent.h"
+};
+const int arc_32bit_usr1 = 0;
+const int arc_32bit_usr2 = 0;
+/* ARCH_s390 */
+struct_sysent s390_32bit_sysent[] = {
+       #include "s390/syscallent.h"
+};
+const int s390_32bit_usr1 = 0;
+const int s390_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_s390x */
+struct_sysent s390x_64bit_sysent[] = {
+       #include "s390x/syscallent.h"
+};
+const int s390x_64bit_usr1 = 0;
+const int s390x_64bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_hppa */
+struct_sysent hppa_32bit_sysent[] = {
+       #include "hppa/syscallent.h"
+};
+const int hppa_32bit_usr1 = 0;
+const int hppa_32bit_usr2 = 0;
+/* ARCH_parisc */
+#define parisc_32bit_sysent dummy_sysent
+const int parisc_32bit_usr1 = 0;
+const int parisc_32bit_usr2 = 0;
+/* ARCH_sh */
+struct_sysent sh_32bit_sysent[] = {
+       #include "sh/syscallent.h"
+};
+const int sh_32bit_usr1 = 0;
+const int sh_32bit_usr2 = 0;
+/* ARCH_sh64 */
+struct_sysent sh64_64bit_sysent[] = {
+       #include "sh64/syscallent.h"
+};
+const int sh64_64bit_usr1 = 0;
+const int sh64_64bit_usr2 = 0;
+/* ARCH_x86 */
+struct_sysent x86_32bit_sysent[] = {
+       #include "i386/syscallent.h"
+};
+const int x86_32bit_usr1 = 0;
+const int x86_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_i386 */
+#define i386_32bit_sysent dummy_sysent
+const int i386_32bit_usr1 = 0;
+const int i386_32bit_usr2 = 0;
+/* ARCH_i486 */
+#define i486_32bit_sysent dummy_sysent
+const int i486_32bit_usr1 = 0;
+const int i486_32bit_usr2 = 0;
+/* ARCH_i586 */
+#define i586_32bit_sysent dummy_sysent
+const int i586_32bit_usr1 = 0;
+const int i586_32bit_usr2 = 0;
+/* ARCH_i686 */
+#define i686_32bit_sysent dummy_sysent
+const int i686_32bit_usr1 = 0;
+const int i686_32bit_usr2 = 0;
+/* ARCH_x86_64 64bit ABI mode */
+struct_sysent x86_64_64bit_sysent[] = {
+       #include "x86_64/syscallent.h"
+};
+const int x86_64_64bit_usr1 = 0;
+const int x86_64_64bit_usr2 = 0;
+/* ARCH_x86_64 32bit ABI mode */
+struct_sysent x86_64_32bit_sysent[] = {
+       #include "x86_64/syscallent1.h"
+};
+const int x86_64_32bit_usr1 = 0;
+const int x86_64_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_x86_64 x32 ABI mode */
+struct_sysent x86_64_x32_sysent[] = {
+       #include "x86_64/syscallent2.h"
+};
+const int x86_64_x32_usr1 = 0;
+const int x86_64_x32_usr2 = 0;
+/* ARCH_amd64 */
+#define amd64_64bit_sysent dummy_sysent
+const int amd64_64bit_usr1 = 0;
+const int amd64_64bit_usr2 = 0;
+/* ARCH_cris */
+struct_sysent cris_32bit_sysent[] = {
+       #include "crisv10/syscallent.h"
+};
+const int cris_32bit_usr1 = 0;
+const int cris_32bit_usr2 = 0;
+/* ARCH_crisv10 */
+#define crisv10_32bit_sysent dummy_sysent
+const int crisv10_32bit_usr1 = 0;
+const int crisv10_32bit_usr2 = 0;
+/* ARCH_crisv32 */
+struct_sysent crisv32_32bit_sysent[] = {
+       #include "crisv32/syscallent.h"
+};
+const int crisv32_32bit_usr1 = 0;
+const int crisv32_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_tile 64bit ABI mode */
+struct_sysent tile_64bit_sysent[] = {
+       #include "tile/syscallent.h"
+};
+const int tile_64bit_usr1 = 0;
+const int tile_64bit_usr2 = 0;
+/* ARCH_tile 32bit ABI mode */
+struct_sysent tile_32bit_sysent[] = {
+       #include "tile/syscallent1.h"
+};
+const int tile_32bit_usr1 = 0;
+const int tile_32bit_usr2 = 0;
+/* ARCH_microblaze */
+struct_sysent microblaze_32bit_sysent[] = {
+       #include "microblaze/syscallent.h"
+};
+const int microblaze_32bit_usr1 = 0;
+const int microblaze_32bit_usr2 = 0;
+/* ARCH_nios2 */
+struct_sysent nios2_32bit_sysent[] = {
+       #include "nios2/syscallent.h"
+};
+const int nios2_32bit_usr1 = 0;
+const int nios2_32bit_usr2 = 0;
+/* ARCH_openrisc */
+struct_sysent openrisc_32bit_sysent[] = {
+       #include "or1k/syscallent.h"
+};
+const int openrisc_32bit_usr1 = 0;
+const int openrisc_32bit_usr2 = 0;
+/* ARCH_xtensa */
+struct_sysent xtensa_32bit_sysent[] = {
+       #include "xtensa/syscallent.h"
+};
+const int xtensa_32bit_usr1 = 0;
+const int xtensa_32bit_usr2 = 0;
+/* ARCH_riscv 64bit ABI mode */
+struct_sysent riscv_64bit_sysent[] = {
+       #include "riscv/syscallent.h"
+};
+const int riscv_64bit_usr1 = 0;
+const int riscv_64bit_usr2 = 0;
+/* ARCH_riscv 32bit ABI mode */
+struct_sysent riscv_32bit_sysent[] = {
+       #include "riscv/syscallent1.h"
+};
+const int riscv_32bit_usr1 = 0;
+const int riscv_32bit_usr2 = 0;
+
+#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, \
+       }
+
+/* Generate array of arch_descriptors for each architecture and mode */
+struct arch_descriptor architectures[] = {
+       ARCH_DESC_DEFINE(blackfin,      blackfin,       32bit   ),
+       ARCH_DESC_DEFINE(ia64,          ia64,           64bit   ),
+       ARCH_DESC_DEFINE(m68k,          m68k,           32bit   ),
+       ARCH_DESC_DEFINE(sparc64,       sparc64,        64bit   ),
+       ARCH_DESC_DEFINE(sparc64,       sparc64,        32bit   ),
+       ARCH_DESC_DEFINE(sparc,         sparc,          32bit   ),
+       ARCH_DESC_DEFINE(metag,         metag,          32bit   ),
+       ARCH_DESC_DEFINE(mips,          mips,           o32     ),
+       ARCH_DESC_DEFINE(mips,          mips,           n32     ),
+       ARCH_DESC_DEFINE(mips,          mips,           n64     ),
+       ARCH_DESC_DEFINE(alpha,         alpha,          64bit   ),
+       ARCH_DESC_DEFINE(ppc,           ppc,            32bit   ),
+       ARCH_DESC_DEFINE(ppc64,         ppc64,          64bit   ),
+       ARCH_DESC_DEFINE(ppc64,         ppc64,          32bit   ),
+       ARCH_DESC_DEFINE(arm,           arm,            oabi    ),
+       ARCH_DESC_DEFINE(arm,           arm,            eabi    ),
+       ARCH_DESC_DEFINE(aarch64,       aarch64,        64bit   ),
+       ARCH_DESC_DEFINE(aarch64,       aarch64,        32bit   ),
+       ARCH_DESC_DEFINE(avr32,         avr32,          32bit   ),
+       ARCH_DESC_DEFINE(arc,           arc,            32bit   ),
+       ARCH_DESC_DEFINE(s390,          s390,           32bit   ),
+       ARCH_DESC_DEFINE(s390x,         s390x,          64bit   ),
+       ARCH_DESC_DEFINE(hppa,          hppa,           32bit   ),
+       ARCH_DESC_DEFINE(parisc,        hppa,           32bit   ),
+       ARCH_DESC_DEFINE(sh,            sh,             32bit   ),
+       ARCH_DESC_DEFINE(sh64,          sh64,           64bit   ),
+       ARCH_DESC_DEFINE(x86,           x86,            32bit   ),
+       ARCH_DESC_DEFINE(i386,          x86,            32bit   ),
+       ARCH_DESC_DEFINE(i486,          x86,            32bit   ),
+       ARCH_DESC_DEFINE(i586,          x86,            32bit   ),
+       ARCH_DESC_DEFINE(i686,          x86,            32bit   ),
+       ARCH_DESC_DEFINE(x86_64,        x86_64,         64bit   ),
+       ARCH_DESC_DEFINE(x86_64,        x86_64,         32bit   ),
+       ARCH_DESC_DEFINE(x86_64,        x86_64,         x32     ),
+       ARCH_DESC_DEFINE(amd64,         x86_64,         64bit   ),
+       ARCH_DESC_DEFINE(cris,          cris,           32bit   ),
+       ARCH_DESC_DEFINE(crisv10,       cris,           32bit   ),
+       ARCH_DESC_DEFINE(crisv32,       crisv32,        32bit   ),
+       ARCH_DESC_DEFINE(tile,          tile,           64bit   ),
+       ARCH_DESC_DEFINE(tile,          tile,           32bit   ),
+       ARCH_DESC_DEFINE(microblaze,    microblaze,     32bit   ),
+       ARCH_DESC_DEFINE(nios2,         nios2,          32bit   ),
+       ARCH_DESC_DEFINE(openrisc,      openrisc,       32bit   ),
+       ARCH_DESC_DEFINE(xtensa,        xtensa,         32bit   ),
+       ARCH_DESC_DEFINE(riscv,         riscv,          64bit   ),
+       ARCH_DESC_DEFINE(riscv,         riscv,          32bit   )
+};
+
+/* 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) {
+       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);
+}
+
+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))
+                       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;
+}
+
+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[] = {
+               "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[] = {
+               "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\
+  --list-arch      print out all ABIs for specified architecture\n\
+\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);
+}
+
+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[] = {
+               [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 */
+       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;
+}
+
+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[];
+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 */
+       for (i = 0; i < al_size_full; i++) {
+               match_pointer = strstr(arch_str, al_arch_name(a_full_list, i));
+               if (match_pointer == NULL || match_pointer != arch_str)
+                       continue;
+               if (arch_match == -1 ||
+                   al_arch_name_len(a_full_list, i) >
+                   al_arch_name_len(a_full_list, arch_match))
+                       arch_match = i;
+       }
+       if (arch_match == -1)
+               goto fail;
+       /* Now we find all ABI modes related to the architecture and its other
+          names */
+       /* Firstly, find the base arch */
+       arch_match = al_find_base_arch(a_full_list, arch_match);
+       /* Secondly, it is necessary to calculate size of final arch_list */
+       al_size_ret = al_get_abi_modes(a_full_list, arch_match);
+       while ((i = al_next_arch_name(a_full_list, arch_match)) != -1)
+               al_size_ret++;
+       if (al_size_ret == 0)
+               goto fail;
+       /* Finally, Create arch_list and fill it */
+       *arch = al_create(al_size_ret);
+       for (i = arch_match; i < (arch_match + al_size_ret); i++)
+               al_push(*arch, &architectures[i]);
+
+       free(a_full_list);
+       return 0;
+fail:
+       free(a_full_list);
+       return -1;
+}
+
+struct arch_service *
+arch_dispatcher(unsigned request_type, char *arch)
+{
+       struct utsname info_uname;
+       int i;
+       ARCH_LIST_DEFINE(arch_list) = NULL;
+
+       /* If user don't type any option in ARCH_REQ group, it means
+          get current arch */
+       if ((request_type & 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 */
+       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);
+                       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;
+}
+
+
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"
+};
+
+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


------------------------------------------------------------------------------
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