The main purpose of this query tool is to present all information concluded
at sysent.h files in a convenient way.
The asinfo tool has the following staged architecture:
(command dispatcher)->(architecture dispatcher)->
(abi dispatcher)->(system call dispatcher).
Each dispatcher accepts proccesed data from previous one.

This point can be illustrated by the following example:
$ asinfo --get-arch --get-sname write
Firstly, arch_dispatcher will return the current architecture, based on
uname return value, after that in case of no options for abi_dispatcher,
it perceives empty parameter as get-abi parameter 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.
Also, tool can work in multi-arch mode. for instance:
$ ./tools/asinfo/asinfo --set-arch mips64,mips --set-abi n64,all
--get-snum 100,8,%ipc
For more info, use asinfo -h.

* Makefile.am (SUBDIRS): Add tools directory.
* configure.ac (AC_CONFIG_FILES): Add 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 them.
* tools/asinfo/error_interface.h: New file. Introduce error_service to
improve informativeness of output errors. Prototype methods to work with
error_service.
* tools/asinfo/error_interface.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. Implement version.
* tools/asinfo/arch_definitions.h: New file. Introduce useful storage
for architectures.
* tools/asinfo/arch_includes.h: New file.
* tools/asinfo/personalities.h: New file.

Signed-off-by: Edgar Kaziakhmedov <edgar.kaziakhme...@virtuozzo.com>
---
 Makefile.am                       |   2 +-
 configure.ac                      |   2 +
 tools/Makefile.am                 |  28 ++
 tools/asinfo/Makefile.am          |  71 ++++
 tools/asinfo/arch_definitions.h   |  70 ++++
 tools/asinfo/arch_includes.h      | 272 +++++++++++++++
 tools/asinfo/arch_interface.c     | 654 ++++++++++++++++++++++++++++++++++++
 tools/asinfo/arch_interface.h     | 162 +++++++++
 tools/asinfo/arch_personalities.h |  36 ++
 tools/asinfo/asinfo.c             | 331 ++++++++++++++++++
 tools/asinfo/dispatchers.c        | 244 ++++++++++++++
 tools/asinfo/dispatchers.h        |  48 +++
 tools/asinfo/error_interface.c    | 110 ++++++
 tools/asinfo/error_interface.h    |  95 ++++++
 tools/asinfo/request_msgs.h       |  93 ++++++
 tools/asinfo/syscall_interface.c  | 684 ++++++++++++++++++++++++++++++++++++++
 tools/asinfo/syscall_interface.h  | 142 ++++++++
 17 files changed, 3043 insertions(+), 1 deletion(-)
 create mode 100644 tools/Makefile.am
 create mode 100644 tools/asinfo/Makefile.am
 create mode 100644 tools/asinfo/arch_definitions.h
 create mode 100644 tools/asinfo/arch_includes.h
 create mode 100644 tools/asinfo/arch_interface.c
 create mode 100644 tools/asinfo/arch_interface.h
 create mode 100644 tools/asinfo/arch_personalities.h
 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/error_interface.c
 create mode 100644 tools/asinfo/error_interface.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 4aa9846c..73353484 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 29285dbf..d47bf3a5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -888,6 +888,8 @@ AC_CONFIG_FILES([Makefile
                 tests-m32/Makefile
                 tests-mx32/Makefile
                 strace.1
+                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..94175140
--- /dev/null
+++ b/tools/asinfo/Makefile.am
@@ -0,0 +1,71 @@
+# 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_definitions.h      \
+       arch_includes.h         \
+       arch_interface.c        \
+       arch_interface.h        \
+       arch_personalities.h    \
+       asinfo.c                \
+       ../../basic_filters.c   \
+       dispatchers.c           \
+       dispatchers.h           \
+       error_interface.c       \
+       error_interface.h       \
+       ../../error_prints.c    \
+       ../../error_prints.h    \
+       ../../filter.h          \
+       ../../macros.h          \
+       ../../number_set.c      \
+       ../../number_set.h      \
+       request_msgs.h          \
+       ../../string_to_uint.h  \
+       ../../string_to_uint.c  \
+       syscall_interface.c     \
+       syscall_interface.h     \
+       ../../sysent_shorthand_defs.h \
+       ../../sysent_shorthand_undefs.h \
+       ../../xmalloc.c         \
+       ../../xmalloc.h         \
+       #end of asinfo_SOURCES
diff --git a/tools/asinfo/arch_definitions.h b/tools/asinfo/arch_definitions.h
new file mode 100644
index 00000000..37103160
--- /dev/null
+++ b/tools/asinfo/arch_definitions.h
@@ -0,0 +1,70 @@
+/* [],[bfin/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(blackfin,     32bit,          PASS({}),                       
                PASS({"blackfin", "bfin"})                      ),
+/* [],[ia64/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(ia64,         64bit,          PASS({}),                       
                PASS({"ia64"})                                  ),
+/* [],[m68k/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(m68k,         32bit,          PASS({}),                       
                PASS({"m68k"})                                  ),
+/* [],[sparc64/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(sparc64,      64bit,          PASS({ARCH_sparc_32bit}),       
                PASS({"sparc64"})                               ),
+/* [],[sparc/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(sparc,                32bit,          PASS({}),               
                        PASS({"sparc"})                                 ),
+/* [],[metag/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(metag,                32bit,          PASS({}),               
                        PASS({"metag"})                                 ),
+/* 
[LINUX_MIPSN64],[dummy.h,mips/syscallent-compat.h,mips/syscallent-n64.h],[0,0] 
*/
+ARCH_DESC_DEFINE(mips64,       n64,            PASS({ARCH_mips64_n32, 
ARCH_mips_o32}),         PASS({"mips64", "mips64le"})                    ),
+/* 
[LINUX_MIPSN32],[dummy.h,mips/syscallent-compat.h,mips/syscallent-n32.h],[0,0] 
*/
+ARCH_DESC_DEFINE(mips64,       n32,            PASS({ARCH_mips_o32}),          
                PASS({})                                        ),
+/* 
[LINUX_MIPSO32],[dummy.h,mips/syscallent-compat.h,mips/syscallent-o32.h],[0,0] 
*/
+ARCH_DESC_DEFINE(mips,         o32,            PASS({}),                       
                PASS({"mips", "mipsle"})                        ),
+/* [],[alpha/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(alpha,                64bit,          PASS({}),               
                        PASS({"alpha"})                                 ),
+/* [],[powerpc64/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(ppc64,                64bit,          PASS({ARCH_ppc_32bit}), 
                        PASS({"ppc64", "ppc64le", "powerpc64"})         ),
+/* [],[powerpc/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(ppc,          32bit,          PASS({}),                       
                PASS({"ppc", "ppcle", "powerpc"})               ),
+/* [],[aarch64/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(aarch64,      64bit,          PASS({ARCH_arm_eabi}),          
                PASS({"aarch64", "arm64"})                      ),
+/* 
[!__ARM_EABI__],[arm/syscallent.h],[ARM_FIRST_SHUFFLED_SYSCALL,ARM_LAST_SPECIAL_SYSCALL]
 */
+ARCH_DESC_DEFINE(arm,          oabi,           PASS({ARCH_arm_eabi}),          
                PASS({"arm"})                                   ),
+/* 
[__ARM_EABI__],[arm/syscallent.h],[ARM_FIRST_SHUFFLED_SYSCALL,ARM_LAST_SPECIAL_SYSCALL]
 */
+ARCH_DESC_DEFINE(arm,          eabi,           PASS({}),                       
                PASS({})                                        ),
+/* [],[avr32/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(avr32,                32bit,          PASS({}),               
                        PASS({"avr32"})                                 ),
+/* [],[arc/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(arc,          32bit,          PASS({}),                       
                PASS({"arc"})                                   ),
+/* [],[s390x/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(s390x,                64bit,          PASS({}),               
                        PASS({"s390x"})                                 ),
+/* [],[s390/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(s390,         32bit,          PASS({}),                       
                PASS({"s390"})                                  ),
+/* [],[hppa/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(hppa,         32bit,          PASS({}),                       
                PASS({"parisc", "hppa"})                        ),
+/* [],[sh64/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(sh64,         64bit,          PASS({}),                       
                PASS({"sh64"})                                  ),
+/* [],[sh/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(sh,           32bit,          PASS({}),                       
                PASS({"sh"})                                    ),
+/* [],[x86_64/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(x86_64,       64bit,          PASS({ARCH_x86_64_x32, 
ARCH_x86_32bit}),        PASS({"x86_64", "amd64", "EM64T"})              ),
+/* [],[x86_64/syscallent2.h],[0,0] */
+ARCH_DESC_DEFINE(x86_64,       x32,            PASS({ARCH_x86_32bit}),         
                PASS({})                                        ),
+/* [],[i386/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(x86,          32bit,          PASS({}),                       
                PASS({"x86", "i386", "i486", "i586", "i686"})   ),
+/* [],[crisv10/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(cris,         32bit,          PASS({}),                       
                PASS({"cris", "crisv10"})                       ),
+/* [],[crisv32/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(crisv32,      32bit,          PASS({}),                       
                PASS({"crisv32"})                               ),
+/* [],[tile/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(tile,         64bit,          PASS({ARCH_tile_32bit}),        
                PASS({"tile", "tilegx"})                        ),
+/* [],[tile/syscallent1.h],[0,0] */
+ARCH_DESC_DEFINE(tile,         32bit,          PASS({}),                       
                PASS({"tilepro"})                               ),
+/* [],[microblaze/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(microblaze,   32bit,          PASS({}),                       
                PASS({"microblaze"})                            ),
+/* [],[nios2/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(nios2,                32bit,          PASS({}),               
                        PASS({"nios2"})                                 ),
+/* [],[or1k/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(openrisc,     32bit,          PASS({}),                       
                PASS({"openrisc", "or1k"})                      ),
+/* [],[xtensa/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(xtensa,       32bit,          PASS({}),                       
                PASS({"xtensa"})                                ),
+/* [],[riscv/syscallent.h],[0,0] */
+ARCH_DESC_DEFINE(riscv,                64bit,          
PASS({ARCH_riscv_32bit}),                       PASS({"riscv"})                 
                ),
+/* [],[riscv/syscallent1.h],[0,0] */
+ARCH_DESC_DEFINE(riscv,                32bit,          PASS({}),               
                        PASS({})                                        )
diff --git a/tools/asinfo/arch_includes.h b/tools/asinfo/arch_includes.h
new file mode 100644
index 00000000..e73a8328
--- /dev/null
+++ b/tools/asinfo/arch_includes.h
@@ -0,0 +1,272 @@
+/* ARCH_blackfin */
+static const struct_sysent blackfin_32bit_sysent[] = {
+       #include "bfin/syscallent.h"
+};
+static const int blackfin_32bit_usr1 = 0;
+const int blackfin_32bit_usr2 = 0;
+/* ARCH_ia64 */
+struct_sysent ia64_64bit_sysent[] = {
+       #include "ia64/syscallent.h"
+};
+static const int ia64_64bit_usr1 = 0;
+static const int ia64_64bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_m68k */
+static const struct_sysent m68k_32bit_sysent[] = {
+       #include "m68k/syscallent.h"
+};
+static const int m68k_32bit_usr1 = 0;
+static const int m68k_32bit_usr2 = 0;
+/* ARCH_sparc64 64bit ABI */
+static const struct_sysent sparc64_64bit_sysent[] = {
+       #include "sparc64/syscallent.h"
+};
+static const int sparc64_64bit_usr1 = 0;
+static const int sparc64_64bit_usr2 = 0;
+/* ARCH_sparc and 32bit ABI */
+static const struct_sysent sparc_32bit_sysent[] = {
+       #include "sparc/syscallent.h"
+};
+static const int sparc_32bit_usr1 = 0;
+static const int sparc_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_metag */
+static const struct_sysent metag_32bit_sysent[] = {
+       #include "metag/syscallent.h"
+};
+static const int metag_32bit_usr1 = 0;
+static const int metag_32bit_usr2 = 0;
+/* ARCH_mips n64 ABI */
+#ifndef LINUX_MIPSN64
+# define LINUX_MIPSN64 1
+# define NOW_DEFINED 1
+#endif
+static const struct_sysent mips64_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
+static const int mips64_n64_usr1 = 0;
+static const int mips64_n64_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_mips n32 ABI */
+#ifndef LINUX_MIPSN32
+# define LINUX_MIPSN32 1
+# define NOW_DEFINED 1
+#endif
+static const struct_sysent mips64_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
+static const int mips64_n32_usr1 = 0;
+static const int mips64_n32_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_mips o32 ABI */
+#ifndef LINUX_MIPSO32
+# define LINUX_MIPSO32 1
+# define NOW_DEFINED 1
+#endif
+static const 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
+static const int mips_o32_usr1 = 0;
+static const int mips_o32_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_alpha */
+static const struct_sysent alpha_64bit_sysent[] = {
+       #include "alpha/syscallent.h"
+};
+static const int alpha_64bit_usr1 = 0;
+static const int alpha_64bit_usr2 = 0;
+/* ARCH_ppc64 64bit ABI */
+static const struct_sysent ppc64_64bit_sysent[] = {
+       #include "powerpc64/syscallent.h"
+};
+static const int ppc64_64bit_usr1 = 0;
+static const int ppc64_64bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_ppc and 32bit */
+static const struct_sysent ppc_32bit_sysent[] = {
+       #include "powerpc/syscallent.h"
+};
+static const int ppc_32bit_usr1 = 0;
+static const int ppc_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_aarch64 64bit ABI */
+static const struct_sysent aarch64_64bit_sysent[] = {
+       #include "aarch64/syscallent.h"
+};
+static const int aarch64_64bit_usr1 = 0;
+static const int aarch64_64bit_usr2 = 0;
+/* ARCH_arm OABI*/
+#ifdef __ARM_EABI__
+# undef __ARM_EABI__
+# define NOW_UNDEFINED 1
+#endif
+static const struct_sysent arm_oabi_sysent[] = {
+       #include "arm/syscallent.h"
+};
+static const int arm_oabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
+static 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
+static const struct_sysent arm_eabi_sysent[] = {
+       #include "arm/syscallent.h"
+};
+static const int arm_eabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
+static 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_avr32 */
+static const struct_sysent avr32_32bit_sysent[] = {
+       #include "avr32/syscallent.h"
+};
+static const int avr32_32bit_usr1 = 0;
+static const int avr32_32bit_usr2 = 0;
+/* ARCH_arc */
+static const struct_sysent arc_32bit_sysent[] = {
+       #include "arc/syscallent.h"
+};
+static const int arc_32bit_usr1 = 0;
+static const int arc_32bit_usr2 = 0;
+/* ARCH_s390x */
+static const struct_sysent s390x_64bit_sysent[] = {
+       #include "s390x/syscallent.h"
+};
+static const int s390x_64bit_usr1 = 0;
+static const int s390x_64bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_s390 */
+static const struct_sysent s390_32bit_sysent[] = {
+       #include "s390/syscallent.h"
+};
+static const int s390_32bit_usr1 = 0;
+static const int s390_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_hppa */
+static const struct_sysent hppa_32bit_sysent[] = {
+       #include "hppa/syscallent.h"
+};
+static const int hppa_32bit_usr1 = 0;
+static const int hppa_32bit_usr2 = 0;
+/* ARCH_sh64 */
+static const struct_sysent sh64_64bit_sysent[] = {
+       #include "sh64/syscallent.h"
+};
+static const int sh64_64bit_usr1 = 0;
+static const int sh64_64bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_sh */
+static const struct_sysent sh_32bit_sysent[] = {
+       #include "sh/syscallent.h"
+};
+static const int sh_32bit_usr1 = 0;
+static const int sh_32bit_usr2 = 0;
+/* ARCH_x86_64 64bit ABI mode */
+static const struct_sysent x86_64_64bit_sysent[] = {
+       #include "x86_64/syscallent.h"
+};
+static const int x86_64_64bit_usr1 = 0;
+static const int x86_64_64bit_usr2 = 0;
+/* ARCH_x86_64 x32 ABI mode */
+static const struct_sysent x86_64_x32_sysent[] = {
+       #include "x86_64/syscallent2.h"
+};
+static const int x86_64_x32_usr1 = 0;
+static const int x86_64_x32_usr2 = 0;
+/* ARCH_x86 */
+static const struct_sysent x86_32bit_sysent[] = {
+       #include "i386/syscallent.h"
+};
+static const int x86_32bit_usr1 = 0;
+static const int x86_32bit_usr2 = 0;
+/* ARCH_cris */
+static struct_sysent cris_32bit_sysent[] = {
+       #include "crisv10/syscallent.h"
+};
+static const int cris_32bit_usr1 = 0;
+static const int cris_32bit_usr2 = 0;
+/* ARCH_crisv32 */
+static const struct_sysent crisv32_32bit_sysent[] = {
+       #include "crisv32/syscallent.h"
+};
+static const int crisv32_32bit_usr1 = 0;
+static const int crisv32_32bit_usr2 = 0;
+#undef SYS_socket_subcall
+/* ARCH_tile 64bit ABI mode */
+static const struct_sysent tile_64bit_sysent[] = {
+       #include "tile/syscallent.h"
+};
+static const int tile_64bit_usr1 = 0;
+static const int tile_64bit_usr2 = 0;
+/* ARCH_tile 32bit ABI mode */
+static const struct_sysent tile_32bit_sysent[] = {
+       #include "tile/syscallent1.h"
+};
+static const int tile_32bit_usr1 = 0;
+static const int tile_32bit_usr2 = 0;
+/* ARCH_microblaze */
+static const struct_sysent microblaze_32bit_sysent[] = {
+       #include "microblaze/syscallent.h"
+};
+static const int microblaze_32bit_usr1 = 0;
+static const int microblaze_32bit_usr2 = 0;
+/* ARCH_nios2 */
+static const struct_sysent nios2_32bit_sysent[] = {
+       #include "nios2/syscallent.h"
+};
+static const int nios2_32bit_usr1 = 0;
+static const int nios2_32bit_usr2 = 0;
+/* ARCH_openrisc */
+struct_sysent openrisc_32bit_sysent[] = {
+       #include "or1k/syscallent.h"
+};
+static const int openrisc_32bit_usr1 = 0;
+static const int openrisc_32bit_usr2 = 0;
+/* ARCH_xtensa */
+static const struct_sysent xtensa_32bit_sysent[] = {
+       #include "xtensa/syscallent.h"
+};
+static const int xtensa_32bit_usr1 = 0;
+static const int xtensa_32bit_usr2 = 0;
+/* ARCH_riscv 64bit ABI mode */
+static const struct_sysent riscv_64bit_sysent[] = {
+       #include "riscv/syscallent.h"
+};
+static const int riscv_64bit_usr1 = 0;
+static const int riscv_64bit_usr2 = 0;
+/* ARCH_riscv 32bit ABI mode */
+static const struct_sysent riscv_32bit_sysent[] = {
+       #include "riscv/syscallent1.h"
+};
+static const int riscv_32bit_usr1 = 0;
+static const int riscv_32bit_usr2 = 0;
diff --git a/tools/asinfo/arch_interface.c b/tools/asinfo/arch_interface.c
new file mode 100644
index 00000000..8e02ffd0
--- /dev/null
+++ b/tools/asinfo/arch_interface.c
@@ -0,0 +1,654 @@
+/*
+ * 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 <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. */
+#include "sysent_shorthand_defs.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
+
+/* Generated file based on arch_definitions.h */
+#include "arch_includes.h"
+
+/* Now undef them since short defines cause wicked namespace pollution. */
+#include "sysent_shorthand_undefs.h"
+
+#define PASS(...) __VA_ARGS__
+#define ARCH_DESC_DEFINE(arch, mode, comp_pers, arch_aliases) \
+       [ARCH_##arch##_##mode] = { \
+               .pers                   = ARCH_##arch##_##mode, \
+               .arch_name              = arch_aliases, \
+               .abi_mode               = #mode, \
+               .abi_mode_len           = ARRAY_SIZE(#arch) - 1, \
+               .compat_pers            = comp_pers, \
+               .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 personality */
+const struct arch_descriptor architectures[] = {
+       #include "arch_definitions.h"
+};
+
+#undef ARCH_DESC_DEFINE
+#undef PASS
+
+struct arch_service *
+al_create(unsigned capacity)
+{
+       ARCH_LIST_DEFINE(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->in_aname = xcalloc(sizeof(*(as->in_aname)), capacity);
+       as->err = es_create();
+       as->capacity = capacity;
+       as->next_free = 0;
+       return as;
+}
+
+int
+al_push(struct arch_service *m, const 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;
+}
+
+int
+al_add_flag(struct arch_service *m, unsigned index, int flag)
+{
+       if (al_is_index_ok(m, index) == 0) {
+               m->flag[index] = m->flag[index] | flag;
+               return 0;
+       }
+       return -1;
+}
+
+int
+al_sub_flag(struct arch_service *m, unsigned index, int flag)
+{
+       if (al_is_index_ok(m, index) == 0) {
+               m->flag[index] = m->flag[index] & ~flag;
+               return 0;
+       }
+       return -1;
+}
+
+const 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;
+}
+
+void
+al_free(struct arch_service *m)
+{
+       int i;
+       int size = al_size(m);
+
+       for (i = 0; i < size; i++)
+               if (al_in_aname(m, i) != NULL)
+                       free(al_in_aname(m, i));
+       free(m->arch_list);
+       free(m->flag);
+       free(m->in_aname);
+       es_free(m->err);
+       free(m);
+}
+
+struct error_service *al_err(struct arch_service *m)
+{
+       return m->err;
+}
+
+enum arch_pers
+al_pers(struct arch_service *m, unsigned index)
+{
+       const struct arch_descriptor *elem = al_get(m, index);
+
+       return (elem ? elem->pers : ARCH_no_pers);
+}
+
+const char **
+al_arch_name(struct arch_service *m, unsigned index)
+{
+       const struct arch_descriptor *elem = al_get(m, index);
+
+       return (elem ? (const char **)elem->arch_name : NULL);
+}
+
+enum arch_pers *
+al_cpers(struct arch_service *m, unsigned index)
+{
+       const struct arch_descriptor *elem = al_get(m, index);
+
+       return (elem ? (enum arch_pers *)elem->compat_pers : NULL);
+}
+
+const char *
+al_abi_mode(struct arch_service *m, unsigned index)
+{
+       const 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)
+{
+       const 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_set_in_aname(struct arch_service *m, unsigned index, char *aname)
+{
+       int status = al_is_index_ok(m, index);
+
+       if (status)
+               return -1;
+       m->in_aname[index] = aname;
+       return 0;
+}
+
+char *
+al_in_aname(struct arch_service *m, unsigned index)
+{
+       int status = al_is_index_ok(m, index);
+
+       return (!status ? m->in_aname[index] : NULL);
+}
+
+int
+al_psize(struct arch_service *m)
+{
+       int i;
+       int a_size = al_size(m);
+       int psize = 0;
+
+       for (i = 0; i < a_size; i++)
+               if (al_flag(m, i) & AD_FLAG_PRINT)
+                       psize++;
+       return psize;
+}
+
+int
+al_arch_name_len(struct arch_service *m, unsigned index, int delim_len)
+{
+       const char **arch_name = NULL;
+       int i;
+       int final_len = 0;
+
+       while (!(al_flag(m, index) & AD_FLAG_MPERS))
+               index--;
+       arch_name = al_arch_name(m, index);
+       for (i = 0; (arch_name[i] != NULL) && (i < MAX_ALIASES); i++) {
+               final_len += strlen(arch_name[i]);
+               final_len += delim_len;
+       }
+       final_len -= delim_len;
+       return final_len;
+}
+
+int
+al_syscall_impl(struct arch_service *m, unsigned index)
+{
+       const 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 count the supported ABI modes for the given
+   arch */
+int
+al_get_abi_modes(struct arch_service *m, unsigned index)
+{
+       const struct arch_descriptor *elem = al_get(m, index);
+       int i = 0;
+       int abi_count = 1;
+
+       if (!elem)
+               return -1;
+       for (i = 0; i < MAX_ALT_ABIS; i++)
+               if (elem->compat_pers[i] != ARCH_no_pers)
+                       abi_count++;
+       return abi_count;
+}
+
+/* This method is purposed to find next one name of the same architecture.
+   For instance, x86_64 = amd64 */
+const char *
+al_next_alias(struct arch_service *m, unsigned index)
+{
+       static int next_alias = -1;
+       static const char **arch_name = NULL;
+       static unsigned lindex = 0;
+
+       if (lindex != index) {
+               lindex = index;
+               next_alias = -1;
+       }
+       if (al_pers(m, index) == ARCH_no_pers)
+               return NULL;
+       if (next_alias == -1) {
+               next_alias = 0;
+               while (!(al_flag(m, index) & AD_FLAG_MPERS))
+                       index--;
+               arch_name = al_arch_name(m, index);
+       } else
+               next_alias++;
+       if (next_alias >= MAX_ALIASES || arch_name[next_alias] == NULL) {
+               next_alias = -1;
+               return NULL;
+       }
+       return arch_name[next_alias];
+}
+
+/* This method is purposed to return next one compat personality of the
+   same architecture */
+enum arch_pers
+al_next_cpers(struct arch_service *m, unsigned index)
+{
+       static int next_pers = -1;
+       enum arch_pers *a_pers = al_cpers(m, index);
+       static unsigned lindex = 0;
+
+       if (al_pers(m, index) == ARCH_no_pers)
+               return ARCH_no_pers;
+       if (lindex != index) {
+               lindex = index;
+               next_pers = -1;
+       }
+       if (next_pers == -1)
+               next_pers = 0;
+       else
+               next_pers++;
+       if (next_pers >= MAX_ALT_ABIS ||
+           a_pers[next_pers] == ARCH_no_pers) {
+               next_pers = -1;
+               return ARCH_no_pers;
+       }
+       return a_pers[next_pers];
+}
+
+enum impl_type
+al_ipc_syscall(struct arch_service *m, unsigned index)
+{
+       const 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)
+{
+       const 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;
+}
+
+/* This method is purposed to create extended list of architectures */
+struct arch_service *
+al_create_filled(void)
+{
+       static const int architectures_size = ARRAY_SIZE(architectures) - 1;
+       ARCH_LIST_DEFINE(as) = al_create(architectures_size);
+       ARCH_LIST_DEFINE(f_as);
+       enum arch_pers cpers;
+       int esize = 0;
+       const char **arch_name = NULL;
+       int i;
+
+       /* Push and calculate size of extended table */
+       for (i = 0; i < architectures_size; i++) {
+               al_push(as, &(architectures[i + 1]));
+               arch_name = al_arch_name(as, i);
+               if (arch_name[0] != NULL)
+                       esize += al_get_abi_modes(as, i);
+       }
+       f_as = al_create(esize);
+       /* Fill extended teble */
+       for (i = 0; i < architectures_size; i++) {
+               arch_name = al_arch_name(as, i);
+               if (arch_name[0] == NULL)
+                       continue;
+               al_push(f_as, al_get(as, i));
+               al_add_flag(f_as, al_size(f_as) - 1, AD_FLAG_MPERS);
+               while ((cpers = al_next_cpers(as, i)) != ARCH_no_pers)
+                       al_push(f_as, &(architectures[cpers]));
+       }
+       free(as);
+       return f_as;
+}
+
+/* To look up arch in arch_descriptor array */
+int
+al_mark_matches(struct arch_service *m, char *arch_str)
+{
+       int arch_match = -1;
+       char *match_pointer = NULL;
+       const char *a_name = NULL;
+       int al_size_full = al_size(m);
+       unsigned prev_arch_len = 0;
+       int i;
+       int a_abi;
+       char *in_aname;
+
+       if (arch_str == NULL)
+               return -1;
+       /* 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++) {
+               if (!(al_flag(m, i) & AD_FLAG_MPERS))
+                       continue;
+               while ((a_name = al_next_alias(m, i)) != NULL) {
+                       match_pointer = strstr(arch_str, a_name);
+                       if (match_pointer == NULL || match_pointer != arch_str)
+                               continue;
+                       if (arch_match == -1 ||
+                           strlen(a_name) > prev_arch_len) {
+                               prev_arch_len = strlen(a_name);
+                               arch_match = i;
+                       }
+               }
+       }
+       if (arch_match == -1)
+               return -1;
+       /* Now we find all ABI modes related to the architecture */
+       if ((a_abi = al_get_abi_modes(m, arch_match)) == -1)
+               return -1;
+       for (i = arch_match; i < (arch_match + a_abi); i++) {
+               al_add_flag(m, i, AD_FLAG_PRINT);
+               in_aname = xcalloc(sizeof(*in_aname), strlen(arch_str) + 1);
+               strcpy(in_aname, arch_str);
+               al_set_in_aname(m, i, in_aname);
+       }
+       return 0;
+}
+
+/* Join all architectures from 'f' and architectures with AD_FLAG_PRINT
+   from 's' arch_service structures */
+struct arch_service *
+al_join_print(struct arch_service *f, struct arch_service *s)
+{
+       int size1 = (f ? al_size(f) : 0);
+       int psize2 = al_psize(s);
+       int size2 = al_size(s);
+       int i;
+       int start_point = 0;
+       ARCH_LIST_DEFINE(final) = al_create(size1 + psize2);
+
+       for (i = 0; i < size2; i++)
+               if (al_flag(s, i) & AD_FLAG_PRINT) {
+                       start_point = i;
+                       break;
+               }
+       for (i = 0; i < size1; i++) {
+               al_push(final, al_get(f, i));
+               al_set_flag(final, i, al_flag(f, i));
+               al_set_in_aname(final, i, al_in_aname(f, i));
+               al_set_in_aname(f, i, NULL);
+       }
+       for (i = 0; i < psize2; i++) {
+               al_push(final, al_get(s, start_point + i));
+               al_set_flag(final, size1 + i , al_flag(s, start_point + i));
+               al_set_in_aname(final, size1 + i,
+                               al_in_aname(s, start_point + i));
+               al_set_in_aname(s, start_point + i, NULL);
+               al_sub_flag(s, start_point + i, AD_FLAG_PRINT);
+       }
+       if (f)
+               al_free(f);
+       return final;
+}
+
+/* To avoid duplication of for(;;) construction */
+void
+al_unmark_all(struct arch_service *m, int flag)
+{
+       int a_size = al_size(m);
+       int i;
+
+       for (i = 0; i < a_size; i++)
+               al_sub_flag(m, i, flag);
+}
+
+/* Select one compatible personality in range of one architecture */
+int
+al_mark_pers4arch(struct arch_service *m, unsigned index, const char *abi_mode)
+{
+       unsigned i = index;
+
+       while (!(al_flag(m, i) & AD_FLAG_MPERS) || (i == index)) {
+               if (strcmp(abi_mode, "all") == 0) {
+                       al_add_flag(m, i, AD_FLAG_PRINT);
+                       i++;
+                       if ((al_is_index_ok(m, i)) ||
+                           (al_flag(m, i) & AD_FLAG_MPERS))
+                               return 0;
+                       else
+                               continue;
+               }
+               if (strcmp(al_abi_mode(m, i), abi_mode) == 0) {
+                       al_add_flag(m, i, AD_FLAG_PRINT);
+                       return 0;
+               }
+               i++;
+       }
+       return -1;
+}
+
+void
+al_dump(struct arch_service *m, int is_raw)
+{
+       static 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]),
+       };
+       static const char *impl_st[] = {
+               "external",
+               "internal",
+               "int/ext"
+       };
+       static const char *delim = "/";
+       int i = 0;
+       int N = 0;
+       int temp_len = 0;
+       int arch_size = al_size(m);
+       int arch_psize = al_psize(m);
+       const char *next_alias = NULL;
+       char *whole_arch_name;
+
+       /* Calculate length of the column with the number of architectures */
+       for (i = 1; arch_psize/i != 0; i *= 10)
+               title_len[0]++;
+       for (i = 0; i < arch_size; i++) {
+               if (!(al_flag(m, i) & AD_FLAG_PRINT))
+                       continue;
+               /* Calculate length of the column with the
+                  architectures name */
+               temp_len = al_arch_name_len(m, i, strlen(delim));
+               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);
+       }
+
+       whole_arch_name = xcalloc(title_len[1], sizeof(*whole_arch_name));
+       /* Output title */
+       if (!is_raw)
+               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_flag(m, i) & AD_FLAG_PRINT))
+                       continue;
+               N++;
+               memset(whole_arch_name, 0, title_len[1]);
+               /* Put all the same arch back together */
+               next_alias = al_next_alias(m, i);
+               strcat(whole_arch_name, next_alias);
+               while ((next_alias = al_next_alias(m, i)) != NULL) {
+                       strcat(whole_arch_name, delim);
+                       strcat(whole_arch_name, next_alias);
+               }
+               if (is_raw) {
+                       printf("%u;%s;%s;%d;%s;%s;\n", N, whole_arch_name,
+                              al_abi_mode(m, i), al_syscall_impl(m, i),
+                              impl_st[al_ipc_syscall(m, i)],
+                              impl_st[al_ipc_syscall(m, i)]);
+                       continue;
+               }
+               printf("| %*u | ", title_len[0], N);
+               printf("%*s | ", title_len[1], whole_arch_name);
+               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)]);
+       }
+       free(whole_arch_name);
+}
diff --git a/tools/asinfo/arch_interface.h b/tools/asinfo/arch_interface.h
new file mode 100644
index 00000000..1e7123fc
--- /dev/null
+++ b/tools/asinfo/arch_interface.h
@@ -0,0 +1,162 @@
+/*
+ * 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_H
+#define ASINFO_ARCH_INTERFACE_H
+
+#include "error_interface.h"
+#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 personalities
+ * arch_pers = ARCH_ + kernel_kernel/other_name + abi_mode */
+enum arch_pers {
+       #include "arch_personalities.h"
+};
+
+#define MAX_ALIASES 6
+#define MAX_ALT_ABIS 3
+
+struct arch_descriptor {
+       enum arch_pers pers;
+       const char *arch_name[MAX_ALIASES];
+       const char *abi_mode;
+       const int abi_mode_len;
+       enum arch_pers compat_pers[MAX_ALT_ABIS];
+       const int max_scn;
+       const 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
+/* to hide some abi modes belonging to one architecture */
+#define AD_FLAG_PRINT  (1 << 0)
+/* main personality, like x86_64 64bit */
+#define AD_FLAG_MPERS  (1 << 1)
+
+/* To provide push-back interface with arch_list */
+struct arch_service {
+       /* immutable field */
+       const struct arch_descriptor **arch_list;
+       /* User flags for each arch_descriptor */
+       int *flag;
+       /* To support conformity between ABI and ARCH */
+       char **in_aname;
+       struct error_service *err;
+       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 capacity);
+
+int al_push(struct arch_service *m, const struct arch_descriptor *element);
+
+int al_set_flag(struct arch_service *m, unsigned index, int flag);
+
+int al_add_flag(struct arch_service *m, unsigned index, int flag);
+
+int al_sub_flag(struct arch_service *m, unsigned index, int flag);
+
+const struct arch_descriptor *al_get(struct arch_service *m, unsigned index);
+
+unsigned int al_size(struct arch_service *m);
+
+void al_free(struct arch_service *m);
+
+struct error_service *al_err(struct arch_service *m);
+
+/* methods returning fields with error check */
+enum arch_pers al_pers(struct arch_service *m, unsigned index);
+
+const char **al_arch_name(struct arch_service *m, unsigned index);
+
+enum arch_pers *al_cpers(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);
+
+int al_set_in_aname(struct arch_service *m, unsigned index, char *aname);
+
+char *al_in_aname(struct arch_service *m, unsigned index);
+
+/* calculating methods */
+int al_psize(struct arch_service *m);
+
+int al_arch_name_len(struct arch_service *m, unsigned index, int delim_len);
+
+int al_syscall_impl(struct arch_service *m, unsigned index);
+
+int al_get_abi_modes(struct arch_service *m, unsigned index);
+
+const char *al_next_alias(struct arch_service *m, unsigned index);
+
+enum arch_pers al_next_cpers(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);
+
+struct arch_service *al_create_filled(void);
+
+int al_mark_matches(struct arch_service *m, char *arch_str);
+
+struct arch_service *al_join_print(struct arch_service *f,
+                                  struct arch_service *s);
+
+void al_unmark_all(struct arch_service *m, int flag);
+
+int al_mark_pers4arch(struct arch_service *m, unsigned index,
+                     const char *abi_mode);
+
+void al_dump(struct arch_service *m, int is_raw);
+
+#endif /* !ASINFO_ARCH_INTERFACE_H */
diff --git a/tools/asinfo/arch_personalities.h 
b/tools/asinfo/arch_personalities.h
new file mode 100644
index 00000000..9499c5aa
--- /dev/null
+++ b/tools/asinfo/arch_personalities.h
@@ -0,0 +1,36 @@
+ARCH_no_pers,
+ARCH_blackfin_32bit,
+ARCH_ia64_64bit,
+ARCH_m68k_32bit,
+ARCH_sparc64_64bit,
+ARCH_sparc_32bit,
+ARCH_metag_32bit,
+ARCH_mips64_n64,
+ARCH_mips64_n32,
+ARCH_mips_o32,
+ARCH_alpha_64bit,
+ARCH_ppc64_64bit,
+ARCH_ppc_32bit,
+ARCH_aarch64_64bit,
+ARCH_arm_oabi,
+ARCH_arm_eabi,
+ARCH_avr32_32bit,
+ARCH_arc_32bit,
+ARCH_s390x_64bit,
+ARCH_s390_32bit,
+ARCH_hppa_32bit,
+ARCH_sh64_64bit,
+ARCH_sh_32bit,
+ARCH_x86_64_64bit,
+ARCH_x86_64_x32,
+ARCH_x86_32bit,
+ARCH_cris_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
diff --git a/tools/asinfo/asinfo.c b/tools/asinfo/asinfo.c
new file mode 100644
index 00000000..9b1ac9e5
--- /dev/null
+++ b/tools/asinfo/asinfo.c
@@ -0,0 +1,331 @@
+/*
+ * 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 <ctype.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_interface.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)
+{
+       puts(
+               "usage: asinfo (--set-arch arch | --get-arch | --list-arch)\n"
+               "              [--set-abi abi | --list-abi] [--raw]\n"
+               "   or: asinfo [(--set-arch arch | --get-arch) [--set-abi abi | 
--list-abi]]\n"
+               "              ((--get-sname expr | --get-snum expr) [--nargs]) 
[--raw]\n"
+               "\n"
+               "Architecture:\n"
+               "  --set-arch arch  use architecture ARCH for further work\n"
+               "                   argument format: arch1,arch2,...\n"
+               "  --get-arch       use architecture returned by uname for 
further work\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 work\n"
+               "                   ('all' can be used as ABI to use all 
compatible personalities\n"
+               "                   for corresponding architecture)\n"
+               "                   argument format: abi1,abi2,...\n"
+               "  --list-abi       use all ABIs for specified architecture\n"
+               "\n"
+               "System call:\n"
+               "  --get-sname expr print all system calls that satisfy a 
filtering expression:\n"
+               "                   [!]all or [!][?]val1[,[?]val2]...\n"
+               "                   with the following format:\n"
+               "                   | N | syscall name | snum1 | snum2 | ...\n"
+               "  --get-snum expr  print all system calls that satisfy a 
filtering expression:\n"
+               "                   [!]all or [!][?]val1[,[?]val2]...\n"
+               "                   with the following format:\n"
+               "                   | N | syscall number | sname1 | sname2 | 
...\n"
+               "  --nargs          change output format as follows:\n"
+               "                   | N | syscall name or number | nargs1 | 
sname2 | ...\n"
+               "\n"
+               "Output formatting:\n"
+               "  --raw            reset alignment and remove titles, use ';' 
as a delimiter\n"
+               "\n"
+               "Miscellaneous:\n"
+               "  -h               print help message\n"
+               "  -v               print version");
+       exit(0);
+}
+
+static void
+print_version(void)
+{
+       printf("asinfo (%s package) -- version %s\n"
+              "Copyright (c) 1991-%s The strace developers <%s>.\n"
+              "This is free software; see the source for copying conditions.  
There is NO\n"
+              "warranty; not even for MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE.\n",
+              PACKAGE_NAME, PACKAGE_VERSION, COPYRIGHT_YEAR, PACKAGE_URL);
+       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 */
+       static const char *options[] = {
+               [SD_REQ_GET_SNAME_BIT]  = "--get-sname",
+               [SD_REQ_GET_SNUM_BIT]   = "--get-snum",
+               [SD_REQ_NARGS_BIT]      = "--nargs",
+               [AD_REQ_SET_ARCH_BIT]   = "--set-arch",
+               [AD_REQ_GET_ARCH_BIT]   = "--get-arch",
+               [AD_REQ_LIST_ARCH_BIT]  = "--list-arch",
+               [ABD_REQ_SET_ABI_BIT]   = "--set-abi",
+               [ABD_REQ_LIST_ABI_BIT]  = "--list-abi",
+               [SERV_REQ_RAW_BIT]      = "--raw",
+               [SERV_REQ_HELP_BIT]     = "-h",
+               [SERV_REQ_VERSION_BIT]  = "-v"
+       };
+       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 char **
+arg2list(char *argument)
+{
+       int i;
+       int len = strlen(argument);
+       int occur = 1;
+       char **arg_list;
+
+       for (i = 0; i < len; i++) {
+               if (argument[i] == ',') {
+                       if (i == 0 || i == len - 1 || argument[i + 1] == ',')
+                               return NULL;
+                       occur++;
+               }
+       }
+       arg_list = xcalloc(sizeof(*arg_list), occur + 1);
+       for (i = 0; i < occur; i++) {
+               arg_list[i] = argument;
+               argument = strchr(argument, ',');
+               if (argument) {
+                       *argument = '\0';
+                       argument++;
+               }
+       }
+       return arg_list;
+}
+
+/* The purpose of this function is to convert input parameters to number with
+   set bits, where each bit means specific work mode. Moreover, it checks input
+   for correctness and outputs error messages in case of wrong input */
+static unsigned
+command_dispatcher(int argc, char *argv[], char **args[])
+{
+       int i;
+       unsigned final_req = 0;
+       unsigned temp_req = 0;
+       int mult_arch = 0;
+       int mult_abi = 0;
+       unsigned non_req_arg = AD_REQ_GET_ARCH  | AD_REQ_LIST_ARCH      |
+                              ABD_REQ_LIST_ABI | SD_REQ_NARGS          |
+                              SERV_REQ_RAW;
+
+       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 or version parameter first */
+       for (i = 1; i < argc; i++) {
+               if (strpar2req(argv[i]) == SERV_REQ_HELP_BIT)
+                       usage();
+               if (strpar2req(argv[i]) == SERV_REQ_VERSION_BIT)
+                       print_version();
+       }
+       /* 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)) {
+                       if ((1 << temp_req) & SD_REQ_MASK) {
+                               args[temp_req] = &argv[i + 1];
+                               i++;
+                               continue;
+                       }
+                       if ((args[temp_req] = arg2list(argv[i + 1])) != NULL) {
+                               i++;
+                               continue;
+                       }
+                       error_msg_and_help("argument '%s' of '%s' parameter "
+                                          "has a wrong format",
+                                          argv[i + 1], argv[i]);
+               }
+       }
+       /* Count our multuarchness */
+       if (args[AD_REQ_SET_ARCH_BIT])
+               while (args[AD_REQ_SET_ARCH_BIT][mult_arch] != NULL)
+                       mult_arch++;
+       if (args[ABD_REQ_SET_ABI_BIT])
+               while (args[ABD_REQ_SET_ABI_BIT][mult_abi] != NULL)
+                       mult_abi++;
+       /* 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 & ~SD_REQ_NARGS) == 0) ||
+           (is_more1bit(final_req & AD_REQ_MASK) == 0) ||
+           (is_more1bit(final_req & ABD_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))))
+               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");
+       /* set-abi must be used in case of multiple arch */
+       if ((mult_arch > 1) && !(final_req & ABD_REQ_MASK))
+               error_msg_and_help("ABI modes cannot be automatically "
+                                  "detected for multiple "
+                                  "architectures");
+       /* set-abi and set-arch have to take the same number of args */
+       if ((final_req & AD_REQ_SET_ARCH) && (final_req & ABD_REQ_SET_ABI) &&
+           (mult_arch != mult_abi))
+               error_msg_and_help("each architecture needs respective "
+                                  "ABI mode, and vice versa");
+       /* --nargs cannot be used alone */
+       if ((final_req & SD_REQ_NARGS) &&
+           !(final_req & SD_REQ_MASK & ~SD_REQ_NARGS))
+               error_msg_and_help("first set main output syscall "
+                                  "characteristics");
+       /* raw should not be single */
+       if (final_req == SERV_REQ_RAW)
+               error_msg_and_help("raw data implies existing data");
+       return final_req;
+}
+
+static char *
+seek_sc_arg(char **input_args[])
+{
+       int i;
+
+       for (i = SD_REQ_GET_SNAME_BIT; i < SYSCALL_REQ_BIT_LAST; i++)
+               if (input_args[i] != NULL)
+                       return input_args[i][0];
+       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 ***in_args = xcalloc(sizeof(*in_args), REQ_LAST_BIT);
+       unsigned reqs;
+
+       /* command_dispatcher turn */
+       reqs = command_dispatcher(argc, argv, in_args);
+       if (reqs == 0)
+               error_msg_and_help("must have OPTIONS");
+
+       /* arch_dispatcher turn */
+       arch_list = arch_dispatcher(reqs, in_args[AD_REQ_SET_ARCH_BIT]);
+       if (es_error(al_err(arch_list)))
+               perror_msg_and_die("%s", es_get_serror(al_err(arch_list)));
+       /* abi_dispatcher turn */
+       abi_dispatcher(arch_list, reqs, in_args[ABD_REQ_SET_ABI_BIT]);
+       if (es_error(al_err(arch_list)))
+               perror_msg_and_die("%s", es_get_serror(al_err(arch_list)));
+       /* syscall_dispatcher turn */
+       sc_list = syscall_dispatcher(arch_list, reqs, seek_sc_arg(in_args));
+       if (es_error(ss_err(sc_list)))
+               perror_msg_and_die("%s", es_get_serror(ss_err(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, reqs & SERV_REQ_RAW);
+       else
+               ss_dump(sc_list, reqs & SERV_REQ_RAW);
+       return 0;
+}
diff --git a/tools/asinfo/dispatchers.c b/tools/asinfo/dispatchers.c
new file mode 100644
index 00000000..ec0f20f9
--- /dev/null
+++ b/tools/asinfo/dispatchers.c
@@ -0,0 +1,244 @@
+/*
+ * 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"
+
+struct arch_service *
+arch_dispatcher(unsigned request_type, char *arch[])
+{
+       struct utsname info_uname;
+       int i;
+       ARCH_LIST_DEFINE(arch_list) = al_create_filled();
+       ARCH_LIST_DEFINE(arch_final) = 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 (al_mark_matches(arch_list, info_uname.machine) == -1) {
+                       es_set_error(al_err(arch_list), AD_UNSUP_ARCH);
+                       es_set_option(al_err(arch_list), info_uname.machine,
+                                     NULL, NULL);
+                       goto fail;
+               }
+               /* Cut off useless archs */
+               arch_final = al_join_print(arch_final, arch_list);
+               al_unmark_all(arch_final, AD_FLAG_PRINT);
+               free(arch_list);
+               goto done;
+       }
+
+       if (request_type & AD_REQ_SET_ARCH) {
+               for (i = 0; arch[i] != NULL; i++) {
+                       if (al_mark_matches(arch_list, arch[i]) == -1) {
+                               es_set_error(al_err(arch_list), AD_UNSUP_ARCH);
+                               es_set_option(al_err(arch_list), arch[i],
+                                             NULL, NULL);
+                               goto fail;
+                       }
+                       arch_final = al_join_print(arch_final, arch_list);
+               }
+               al_unmark_all(arch_final, AD_FLAG_PRINT);
+               al_free(arch_list);
+               goto done;
+       }
+
+       if ((request_type & AD_REQ_LIST_ARCH)) {
+               int a_size = al_size(arch_list);
+               for (i = 0; i < a_size; i++) {
+                       al_add_flag(arch_list, i, AD_FLAG_PRINT);
+               }
+               arch_final = arch_list;
+               goto done;
+       }
+fail:
+       return arch_list;
+done:
+       return arch_final;
+}
+
+int
+abi_dispatcher(struct arch_service *a_serv, unsigned request_type,
+              char *abi[])
+{
+       int i = 0;
+       enum arch_pers pers;
+       int arch_size = 0;
+       int a_pos = 0;
+
+       arch_size = al_size(a_serv);
+       /* 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 when it is possible */
+       if (!(request_type & ABD_REQ_MASK) &&
+           !(request_type & AD_REQ_LIST_ARCH)) {
+               pers = al_pers(a_serv, a_pos);
+               switch (pers) {
+#if defined(MIPS)
+               case ARCH_mips_o32:
+               case ARCH_mips64_n64:
+                       al_mark_pers4arch(a_serv, a_pos,
+#if defined(LINUX_MIPSO32)
+                                         "o32"
+#elif defined(LINUX_MIPSN32)
+                                         "n32"
+#elif defined(LINUX_MIPSN64)
+                                         "n64"
+#endif
+                                        );
+                       break;
+#endif
+#if defined(ARM)
+               case ARCH_arm_oabi:
+                       al_mark_pers4arch(a_serv, a_pos,
+#if defined(__ARM_EABI__) || !defined(ENABLE_ARM_OABI)
+                                         "eabi"
+#else
+                                         "oabi"
+#endif
+                                        );
+                       break;
+#endif
+#if defined(AARCH64)
+               case ARCH_aarch64_64bit:
+                       al_mark_pers4arch(a_serv, a_pos,
+#if defined(__ARM_EABI__)
+                                         "eabi"
+#else
+                                         "64bit"
+#endif
+                                        );
+                       break;
+#endif
+#if defined(X86_64) || defined(X32)
+               case ARCH_x86_64_64bit:
+                       al_mark_pers4arch(a_serv, a_pos,
+#if defined(X86_64)
+                                         "64bit"
+#elif defined(X32)
+                                         "x32"
+#endif
+                                   );
+                       break;
+#endif
+/* Especially for x86_64 32bit ABI, because configure.ac defines it
+   as I386 arch */
+#if defined(I386)
+               case ARCH_x86_64_64bit:
+                       al_mark_pers4arch(a_serv, a_pos, "32bit");
+                       break;
+#endif
+#if defined(TILE)
+               case ARCH_tile_64bit:
+                       al_mark_pers4arch(a_serv, a_pos,
+#if defined(__tilepro__)
+                                         "32bit"
+#else
+                                         "64bit"
+#endif
+                                   );
+                       break;
+#endif
+               default:
+                       if (arch_size == 1) {
+                               al_add_flag(a_serv, a_pos, AD_FLAG_PRINT);
+                               goto done;
+                       }
+                       es_set_error(al_err(a_serv), ABI_CANNOT_DETECT);
+                       es_set_option(al_err(a_serv),
+                                     al_in_aname(a_serv, a_pos), NULL, NULL);
+               }
+               goto done;
+       }
+
+       if (request_type & ABD_REQ_LIST_ABI) {
+               while (a_pos != arch_size) {
+                       if (!al_mark_pers4arch(a_serv, a_pos, "all")) {
+                               a_pos += al_get_abi_modes(a_serv, a_pos);
+                               continue;
+                       }
+                       break;
+               }
+               goto done;
+       }
+
+       if (request_type & ABD_REQ_SET_ABI) {
+               for (i = 0; abi[i] != NULL; i++) {
+                       if (!al_mark_pers4arch(a_serv, a_pos, abi[i])) {
+                               a_pos += al_get_abi_modes(a_serv, a_pos);
+                               continue;
+                       }
+                       es_set_error(al_err(a_serv), ABI_WRONG4ARCH);
+                       es_set_option(al_err(a_serv),
+                                     al_in_aname(a_serv, a_pos),
+                                     abi[i], NULL);
+                       break;
+               }
+       }
+done:
+       return 0;
+}
+
+struct syscall_service *
+syscall_dispatcher(struct arch_service *arch, int request_type, char *sysc)
+{
+       SYSCALL_LIST_DEFINE(sysc_serv) = ss_create(arch, request_type);
+       int narch = ss_size(sysc_serv);
+       int i = 0;
+       int ret = 0;
+       int count = 0;
+
+       if (request_type & SD_REQ_MASK) {
+               for (i = 0; i < narch; i++) {
+                       ss_update_sc_num(sysc_serv, i);
+                       ret = ss_mark_matches(sysc_serv, i, sysc);
+                       if (ret == SD_NO_MATCHES_FND)
+                               count++;
+               }
+       }
+       /* Clear error if we are in multiarch mode */
+       if (count != narch && narch != 1)
+               es_set_error(ss_err(sysc_serv), NO_ERROR);
+
+       return sysc_serv;
+}
diff --git a/tools/asinfo/dispatchers.h b/tools/asinfo/dispatchers.h
new file mode 100644
index 00000000..778b0344
--- /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 ASINFO_DISPATCHERS_H
+#define ASINFO_DISPATCHERS_H
+
+#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 *sysc);
+
+#endif /* !ASINFO_DISPATCHERS_H */
diff --git a/tools/asinfo/error_interface.c b/tools/asinfo/error_interface.c
new file mode 100644
index 00000000..2b519a90
--- /dev/null
+++ b/tools/asinfo/error_interface.c
@@ -0,0 +1,110 @@
+/*
+ * 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 <string.h>
+#include <stdio.h>
+
+#include "error_interface.h"
+#include "xmalloc.h"
+
+static const char *errors[] = {
+       [AD_UNSUP_ARCH_BIT]     = "architecture '%s' is unsupported",
+       [ABI_CANNOT_DETECT_BIT] = "ABI mode cannot be automatically "
+                                 "detected for non-target architecture '%s'",
+       [ABI_WRONG4ARCH_BIT]    = "architecture '%s' does not have ABI mode "
+                                 "'%s'",
+       [SD_NO_MATCHES_FND_BIT] = "no matches found",
+};
+
+struct error_service *
+es_create(void)
+{
+       struct error_service *err = xcalloc(sizeof(*err), 1);
+
+       return err;
+}
+
+enum common_error
+es_error(struct error_service *e)
+{
+       return e->last_error;
+}
+
+void
+es_set_error(struct error_service *e, enum common_error error)
+{
+       e->last_error = error;
+}
+
+void
+es_set_option(struct error_service *e, char *arch, char *abi, char *sc)
+{
+       if (arch) {
+               if (e->last_arch)
+                       free(e->last_arch);
+               e->last_arch = xcalloc(sizeof(*(e->last_arch)),
+                                      strlen(arch) + 1);
+               strcpy(e->last_arch, arch);
+       }
+       if (abi) {
+               if (e->last_abi)
+                       free(e->last_abi);
+               e->last_abi = xcalloc(sizeof(*(e->last_abi)), strlen(abi) + 1);
+               strcpy(e->last_abi, abi);
+       }
+       if (sc) {
+               if (e->last_sc)
+                       free(e->last_sc);
+               e->last_sc = xcalloc(sizeof(*(e->last_sc)), strlen(sc) + 1);
+               strcpy(e->last_sc, sc);
+       }
+}
+
+const char *
+es_get_serror(struct error_service *e)
+{
+       int err = 1 << e->last_error;
+       if (err & ERROR_ARCH_MASK)
+               sprintf(e->string, errors[e->last_error], e->last_arch);
+       else if (err & ERROR_NO_ARG_MASK)
+               sprintf(e->string, "%s", errors[e->last_error]);
+       else if (err & ERROR_ARCH_ABI_MASK)
+               sprintf(e->string, errors[e->last_error], e->last_arch,
+                       e->last_abi);
+       return (const char *)(e->string);
+}
+
+void
+es_free(struct error_service *e)
+{
+       free(e);
+}
diff --git a/tools/asinfo/error_interface.h b/tools/asinfo/error_interface.h
new file mode 100644
index 00000000..048d2778
--- /dev/null
+++ b/tools/asinfo/error_interface.h
@@ -0,0 +1,95 @@
+/*
+ * As each dispatcher has a wide range of possible errors, there is need
+ * use separate and basic error interface.
+ *
+ * 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 ASINFO_ERROR_INTERFACE_H
+#define ASINFO_ERROR_INTERFACE_H
+
+/* errors which using last_arch */
+enum error_arch {
+       NO_ERROR_BIT,
+       AD_UNSUP_ARCH_BIT = 1,
+       ABI_CANNOT_DETECT_BIT,
+
+       ERROR_ARCH_LAST
+};
+
+enum error_no_arg {
+       SD_NO_MATCHES_FND_BIT = ERROR_ARCH_LAST,
+
+       ERROR_NO_ARG_LAST
+};
+
+enum error_arch_abi {
+       ABI_WRONG4ARCH_BIT = ERROR_NO_ARG_LAST,
+
+       ERROR_ARCH_ABI_LAST
+};
+
+#define ENUM_FLAG(name) name = name##_BIT
+enum common_error {
+       ENUM_FLAG(NO_ERROR),
+       /* arch dispatcher range */
+       ENUM_FLAG(AD_UNSUP_ARCH),
+       /* abi dipatcher range */
+       ENUM_FLAG(ABI_CANNOT_DETECT),
+       ENUM_FLAG(ABI_WRONG4ARCH),
+       /* syscall dispatcher range */
+       ENUM_FLAG(SD_NO_MATCHES_FND)
+};
+#undef ENUM_FLAG
+
+#define BITMASK(hi, lo) ((1 << (hi)) - (1 << (lo)))
+#define ERROR_ARCH_MASK  BITMASK(ERROR_ARCH_LAST, 0)
+#define ERROR_NO_ARG_MASK BITMASK(ERROR_NO_ARG_LAST, ERROR_ARCH_LAST)
+#define ERROR_ARCH_ABI_MASK BITMASK(ERROR_ARCH_ABI_LAST, ERROR_NO_ARG_LAST)
+
+#define ERROR_MSG_MAX_LEN 255
+
+struct error_service {
+       char string[ERROR_MSG_MAX_LEN];
+       enum common_error last_error;
+       char *last_arch;
+       char *last_abi;
+       char *last_sc;
+};
+
+struct error_service *es_create(void);
+
+enum common_error es_error(struct error_service *s);
+
+void es_set_error(struct error_service *s, enum common_error se);
+
+void es_set_option(struct error_service *e, char *arch, char *abi, char *sc);
+
+const char *es_get_serror(struct error_service *e);
+
+void es_free(struct error_service *e);
+
+#endif /* !ASINFO_ERROR_INTERFACE_H */
diff --git a/tools/asinfo/request_msgs.h b/tools/asinfo/request_msgs.h
new file mode 100644
index 00000000..d358798e
--- /dev/null
+++ b/tools/asinfo/request_msgs.h
@@ -0,0 +1,93 @@
+/*
+ * The request_msgs are purposed to set the general mode of work, in
+ * particular, the work of main dispatchers.
+ *
+ * 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 ASINFO_REQUEST_MSGS_H
+#define ASINFO_REQUEST_MSGS_H
+
+/* Request types for syscall_dispatcher,
+ * arch_dispatcher, which, in turn, could be combined
+ */
+enum syscall_req_bit {
+       SD_REQ_GET_SNAME_BIT,
+       SD_REQ_GET_SNUM_BIT,
+       SD_REQ_NARGS_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_LIST_ABI_BIT,
+
+       ABD_REQ_BIT_LAST
+};
+
+enum serv_req_bit {
+       SERV_REQ_HELP_BIT = ABD_REQ_BIT_LAST,
+       SERV_REQ_VERSION_BIT,
+       SERV_REQ_ERROR_BIT,
+       SERV_REQ_RAW_BIT,
+
+       SERV_REQ_BIT_LAST
+};
+
+#define ENUM_FLAG(name) name = 1 << name##_BIT
+enum req_type {
+       ENUM_FLAG(SD_REQ_GET_SNAME),
+       ENUM_FLAG(SD_REQ_GET_SNUM),
+       ENUM_FLAG(SD_REQ_NARGS),
+       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_LIST_ABI),
+       ENUM_FLAG(SERV_REQ_HELP),
+       ENUM_FLAG(SERV_REQ_VERSION),
+       ENUM_FLAG(SERV_REQ_ERROR),
+       ENUM_FLAG(SERV_REQ_RAW)
+};
+#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 SERV_REQ_MASK BITMASK(SERV_REQ_BIT_LAST, ABD_REQ_BIT_LAST)
+
+#endif /* !ASINFO_REQUEST_MSGS_H */
diff --git a/tools/asinfo/syscall_interface.c b/tools/asinfo/syscall_interface.c
new file mode 100644
index 00000000..e41a8397
--- /dev/null
+++ b/tools/asinfo/syscall_interface.c
@@ -0,0 +1,684 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "arch_interface.h"
+#include "error_interface.h"
+#include "filter.h"
+#include "number_set.h"
+#include "supported_personalities.h"
+#include "syscall_interface.h"
+#include "sysent.h"
+#include "request_msgs.h"
+#include "xmalloc.h"
+
+/* We shouldn't include defs.h here, because the following definitions
+   cannot be with const qualifier */
+const struct_sysent *sysent_vec[SUPPORTED_PERSONALITIES] = {NULL};
+unsigned int nsyscall_vec[SUPPORTED_PERSONALITIES] = {0};
+
+struct syscall_service *
+ss_create(struct arch_service *m, int request_type)
+{
+       int i;
+       int ss_count = 0;
+       int ssize = al_psize(m);
+       int asize = al_size(m);
+       struct syscall_service *ss = NULL;
+       int scn = 0;
+
+       ss = xcalloc(sizeof(*ss), 1);
+       ss->err = al_err(m);
+       /* If we are in arch/abi mode, but we need syscall_service to pass
+          check for errors */
+       if (!(request_type & SD_REQ_MASK) || ssize == 0)
+               return ss;
+       ss->aws = xcalloc(sizeof(*(ss->aws)), ssize);
+       ss->narch = ssize;
+       for (i = 0; i < asize; i++)
+               if (al_flag(m, i) & AD_FLAG_PRINT) {
+                       ss->aws[ss_count].arch = al_get(m, i);
+                       scn = ss->aws[ss_count].arch->max_scn;
+                       ss->aws[ss_count].flag = xcalloc(sizeof(int), scn);
+                       ss->aws[ss_count].real_snum = xcalloc(sizeof(int), scn);
+                       ss->aws[ss_count].a_name = al_in_aname(m, i);
+                       al_set_in_aname(m, i, NULL);
+                       ss_count++;
+               }
+       ss->request_type = request_type;
+       return ss;
+}
+
+int
+ssa_is_ok(struct syscall_service *s, int arch, int num)
+{
+       if (s == NULL || arch > s->narch || arch < 0 || num < 0 ||
+           num >= s->aws[arch].arch->max_scn)
+               return 0;
+       return 1;
+}
+
+struct error_service *
+ss_err(struct syscall_service *s)
+{
+       return s->err;
+}
+
+int
+ss_size(struct syscall_service *s)
+{
+       return s->narch;
+}
+
+int
+ssa_max_scn(struct syscall_service *s, int arch)
+{
+       if (!ssa_is_ok(s, arch, 0))
+               return -1;
+       return s->aws[arch].arch->max_scn;
+}
+
+const struct_sysent *
+ssa_sysc_list(struct syscall_service *s, int arch)
+{
+       if (!ssa_is_ok(s, arch, 0))
+               return NULL;
+       return s->aws[arch].arch->syscall_list;
+}
+
+int
+ssa_flag(struct syscall_service *s, int arch, int num)
+{
+       if (!ssa_is_ok(s, arch, num))
+               return -1;
+       return s->aws[arch].flag[num];
+}
+
+int
+ssa_set_flag(struct syscall_service *s, int arch, int num, int flag)
+{
+       if (!ssa_is_ok(s, arch, num))
+               return -1;
+       s->aws[arch].flag[num] = flag;
+       return 0;
+}
+
+int
+ssa_real_num(struct syscall_service *s, int arch, int num)
+{
+       if (!ssa_is_ok(s, arch, num))
+               return -1;
+       return s->aws[arch].real_snum[num];
+}
+
+int
+ssa_set_real_num(struct syscall_service *s, int arch, int num, int real_num)
+{
+       if (!ssa_is_ok(s, arch, num))
+               return -1;
+       s->aws[arch].real_snum[num] = real_num;
+       return 0;
+}
+
+const char *
+ssa_syscall_name(struct syscall_service *s, int arch, int num)
+{
+       if (!ssa_is_ok(s, arch, num))
+               return NULL;
+       return s->aws[arch].arch->syscall_list[num].sys_name;
+}
+
+int
+ssa_syscall_flag(struct syscall_service *s, int arch, int num)
+{
+       if (!ssa_is_ok(s, arch, num))
+               return -1;
+       return s->aws[arch].arch->syscall_list[num].sys_flags;
+}
+
+int
+ssa_syscall_nargs(struct syscall_service *s, int arch, int num)
+{
+       if (!ssa_is_ok(s, arch, num))
+               return -1;
+       return (int)s->aws[arch].arch->syscall_list[num].nargs;
+}
+
+int
+ssa_user_num1(struct syscall_service *s, int arch)
+{
+       if (!ssa_is_ok(s, arch, 0))
+               return -1;
+       return *(s->aws[arch].arch->user_num1);
+}
+
+int
+ssa_user_num2(struct syscall_service *s, int arch)
+{
+       if (!ssa_is_ok(s, arch, 0))
+               return -1;
+       return *(s->aws[arch].arch->user_num2);
+}
+
+void
+ss_free(struct syscall_service *s)
+{
+       int i;
+
+       es_free(ss_err(s));
+       for (i = 0; i < s->narch; i++ ) {
+               free(s->aws[i].flag);
+               free(s->aws[i].real_snum);
+               if (s->aws[i].a_name)
+                       free(s->aws[i].a_name);
+       }
+       free(s);
+}
+
+int
+ssa_print_size(struct syscall_service *s, int arch)
+{
+       int i;
+       int max_scn = ssa_max_scn(s, arch);
+       int psize = 0;
+
+       for (i = 0; i < max_scn; i++)
+               if (ssa_flag(s, arch, i) & SS_FLAG_PRINT)
+                       psize++;
+       return psize;
+}
+
+int
+ssa_is_syscall_valid(struct syscall_service *s, int arch, int num)
+{
+       if (!ssa_is_ok(s, arch, num))
+               return 0;
+       return ssa_syscall_name(s, arch, num) &&
+              !(ssa_syscall_flag(s, arch, num) & TRACE_INDIRECT_SUBCALL);
+}
+
+int
+ss_mark_matches(struct syscall_service *s, int arch, char *arg)
+{
+       int i = 0;
+       int scount = 0;
+       int max_scn = ssa_max_scn(s, arch);
+       struct number_set *trace_set;
+       static const char *error_format = {"system call(%s/%s)"};
+       char *out_error = xcalloc(sizeof(char *), strlen(error_format) +
+                                 strlen(s->aws[arch].a_name) +
+                                 strlen(s->aws[arch].arch->abi_mode));
+
+       sprintf(out_error, error_format, s->aws[arch].a_name,
+               s->aws[arch].arch->abi_mode);
+       /* Init global variables */
+       nsyscall_vec[0] = ssa_max_scn(s, arch);
+       sysent_vec[0] =  ssa_sysc_list(s, arch);
+
+       trace_set = alloc_number_set_array(SUPPORTED_PERSONALITIES);
+       qualify_syscall_tokens(arg, trace_set, out_error);
+       for (i = 0; i < max_scn; i++)
+               if (ssa_is_syscall_valid(s, arch, i) &&
+                   ssa_real_num(s, arch, i) != HIDDEN_SYSC &&
+                   is_number_in_set_array(i, trace_set, 0)) {
+                       ssa_set_flag(s, arch, i, SS_FLAG_PRINT);
+                       scount++;
+               }
+       free(out_error);
+       if (scount == 0) {
+               es_set_error(ss_err(s), SD_NO_MATCHES_FND);
+               return SD_NO_MATCHES_FND;
+       }
+       return 0;
+}
+
+int
+ss_update_sc_num(struct syscall_service *s, int arch)
+{
+       int i = 0;
+       int max_scn = ssa_max_scn(s, arch);
+       int usr1n = ssa_user_num1(s, arch);
+       int usr2n = ssa_user_num2(s, arch);
+
+       for (i = 0; i < max_scn; i++) {
+               if (!ssa_is_syscall_valid(s, arch, i)) {
+                       ssa_set_real_num(s, arch, i, HIDDEN_SYSC);
+                       continue;
+               }
+               switch (s->aws[arch].arch->pers) {
+               case ARCH_x86_64_x32:
+                       /* Pure x32 specific syscalls without X32_SYSCALL_BIT */
+                       if (strstr(ssa_syscall_name(s, arch, i), "64:"))
+                               ssa_set_real_num(s, arch, i, HIDDEN_SYSC);
+                       else
+                               ssa_set_real_num(s, arch, i, i);
+                       break;
+               case ARCH_arm_oabi:
+               case ARCH_arm_eabi:
+                       /* Do not deal with private ARM syscalls */
+                       if (i == usr1n)
+                               ssa_set_real_num(s, arch, i, HIDDEN_SYSC);
+                       if ((i >= usr1n + 1) && (i <= usr1n + usr2n + 1))
+                               ssa_set_real_num(s, arch, i, HIDDEN_SYSC);
+                       if (i < usr1n)
+                               ssa_set_real_num(s, arch, i, i);
+                       break;
+               case ARCH_sh64_64bit:
+                       ssa_set_real_num(s, arch, i, i & 0xffff);
+               default:
+                       ssa_set_real_num(s, arch, i, i);
+               }
+       }
+       return 0;
+}
+
+static int
+sysccmp(const void *arg1, const void *arg2)
+{
+       const char *str1 = ((struct in_sysc *)arg1)->sys_name;
+       const char *str2 = ((struct in_sysc *)arg2)->sys_name;
+
+       return strcmp(str1, str2);
+}
+
+static struct sysc_meta *
+ss_make_union(struct syscall_service *s,
+             void* (save)(struct syscall_service *, int, int))
+{
+       struct in_sysc **sysc;
+       struct out_sysc *sysc_l, *sysc_r, *sysc_to, *sysc_fr;
+       struct sysc_meta *sm = xcalloc(sizeof(*sm), 1);
+       int size = ss_size(s);
+       int max_scn;
+       int psize;
+       int out_size = 0;
+       int i, j, k, l;
+       int c = 0;
+       int res = 0;
+       int eff_size = 1;
+       /* Preparation */
+       sysc = xcalloc(sizeof(*sysc), size);
+       for (i = 0; i < size; i++) {
+               max_scn = ssa_max_scn(s, i);
+               psize = ssa_print_size(s, i);
+               sysc[i] = xcalloc(sizeof(**sysc), psize + 1);
+               c = 0;
+               for (j = 0; j < max_scn; j++) {
+                       if (!(ssa_flag(s, i, j) & SS_FLAG_PRINT))
+                               continue;
+                       sysc[i][c].sys_name = ssa_syscall_name(s, i, j);
+                       sysc[i][c].data = save(s, i, j);
+                       c++;
+               }
+               qsort(sysc[i], psize, sizeof(struct in_sysc), &sysccmp);
+               out_size += psize;
+       }
+       /* Allocation */
+       sysc_l = xcalloc(sizeof(*sysc_l), out_size);
+       sysc_r = xcalloc(sizeof(*sysc_r), out_size);
+       for (i = 0; i < out_size; i++) {
+               sysc_r[i].data = xcalloc(sizeof(void *), size);
+               sysc_l[i].data = xcalloc(sizeof(void *), size);
+       }
+       /* Set with first arch in sysc */
+       for (i = 0; sysc[0][i].sys_name != NULL; i++) {
+               sysc_r[i].sys_name = sysc[0][i].sys_name;
+               sysc_r[i].data[0] = sysc[0][i].data;
+       }
+       /* Union
+          Main idea is simple:
+          [sysc_to]<->[sysc_fr]<------[sysc1][sysc2][sysc3]...
+          1) [sysc_fr] = [sysc1]
+          2) [sysc_to] = [sysc_fr] | [sysc2]
+          3) [sysc_to] <-> [sysc_fr]
+          4) [sysc_to] = [sysc_fr] | [sysc3]
+          etc. */
+       sysc_to = sysc_r;
+       sysc_fr = sysc_l;
+       for (i = 1; i < size; i++) {
+               l = 0; j = 0; k = 0;
+               if (sysc[i][j].sys_name != NULL || i == 1) {
+                       sysc_fr = (eff_size % 2) ? sysc_r : sysc_l;
+                       sysc_to = (eff_size % 2) ? sysc_l : sysc_r;
+                       eff_size++;
+               }
+               while (sysc[i][j].sys_name != NULL && k < out_size) {
+                       memset(sysc_to[l].data, 0, sizeof(void *) * size);
+                       if (!sysc_fr[k].sys_name)
+                               res = -1;
+                       else
+                               res = strcmp(sysc[i][j].sys_name,
+                                            sysc_fr[k].sys_name);
+                       if (res < 0) {
+                               sysc_to[l].sys_name = sysc[i][j].sys_name;
+                               sysc_to[l].data[i] = sysc[i][j].data;
+                               j++;
+                       } else if (res > 0) {
+                               sysc_to[l].sys_name = sysc_fr[k].sys_name;
+                               memcpy(sysc_to[l].data, sysc_fr[k].data,
+                                      sizeof(void *) * size);
+                               k++;
+                       } else {
+                               sysc_to[l].sys_name = sysc[i][j].sys_name;
+                               memcpy(sysc_to[l].data, sysc_fr[k].data,
+                                      sizeof(void *) * size);
+                               sysc_to[l].data[i] = sysc[i][j].data;
+                               k++;
+                               j++;
+                       }
+                       l++;
+               }
+               while (k < out_size && l < out_size) {
+                       sysc_to[l].sys_name = sysc_fr[k].sys_name;
+                       memcpy(sysc_to[l].data, sysc_fr[k].data,
+                              sizeof(void *) * size);
+                       k++;
+                       l++;
+               }
+       }
+       /* Free */
+       for (i = 0; i < out_size; i++)
+               free(sysc_fr[i].data);
+       free(sysc_fr);
+       for (i = 0; i < size; i++)
+               free(sysc[i]);
+       free(sysc);
+
+       sm->sysc_list = sysc_to;
+       sm->size = out_size;
+       return sm;
+}
+
+static struct sysc_meta *
+ss_make_enumeration(struct syscall_service *s,
+                   void* (save)(struct syscall_service *, int, int))
+{
+       struct out_sysc *sysc_out;
+       struct sysc_meta *sm = xcalloc(sizeof(*sm), 1);
+       int size = ss_size(s);
+       int max_scn = 0;
+       int i, j, k;
+       int flag;
+       bool clear = true;
+
+       for (i = 0; i < size; i++)
+               if (max_scn < ssa_max_scn(s, i))
+                       max_scn = ssa_max_scn(s, i);
+
+       sysc_out = xcalloc(sizeof(*sysc_out), max_scn);
+       for (i = 0; i < max_scn; i++)
+               sysc_out[i].data = xcalloc(sizeof(void *), size);
+       for (i = 0; i < size; i++)
+               for (j = 0; j < max_scn; j++) {
+                       clear = true;
+                       flag = ssa_flag(s, i, j);
+                       if ((flag != -1) && (flag & SS_FLAG_PRINT)) {
+                               sysc_out[j].sys_num = j;
+                               sysc_out[j].data[i] = save(s, i, j);
+                       }
+                       for (k = 0; k <= i; k++)
+                               if (sysc_out[j].data[k])
+                                       clear = 0;
+                       if (clear)
+                               sysc_out[j].sys_num = -1;
+               }
+       sm->sysc_list = sysc_out;
+       sm->size = max_scn;
+       return sm;
+}
+
+static void *
+ssa_save_snum(struct syscall_service *s, int arch, int snum)
+{
+       return (void *)&(s->aws[arch].real_snum[snum]);
+}
+
+static void *
+ssa_save_nargs(struct syscall_service *s, int arch, int snum)
+{
+       return (void *)&(s->aws[arch].arch->syscall_list[snum].nargs);
+}
+
+static void *
+ssa_save_sname(struct syscall_service *s, int arch, int snum)
+{
+       return (void *)(s->aws[arch].arch->syscall_list[snum].sys_name);
+}
+
+static unsigned
+fast_len(int num)
+{
+       int i;
+       unsigned count = 0;
+
+       for (i = 1; num/i != 0; i *= 10)
+               count++;
+       return count;
+}
+
+static unsigned *
+ss_get_width_sname(struct syscall_service *s, struct sysc_meta *sm, int narch)
+{
+       /* '2' hereinafter takes into account first two default columns */
+       unsigned *width = xcalloc(sizeof(*width), narch + 2);
+       int i, j;
+       unsigned len;
+       unsigned max;
+       int N = 1;
+       struct out_sysc *psysc = sm->sysc_list;
+
+       /* Calculate length of 'N' and sname columns */
+       for (i = 0; i < sm->size; i++) {
+               if (!psysc[i].sys_name)
+                       continue;
+               len = strlen(psysc[i].sys_name);
+               if (len > width[1])
+                       width[1] = len;
+               N++;
+       }
+       width[0] = fast_len(N);
+       for (i = 0; i < narch; i++) {
+               for (j = 0; j < sm->size; j++) {
+                       if (!psysc[j].data[i])
+                               continue;
+                       max = *((int *)(psysc[j].data[i]));
+                       if (max > width[i + 2])
+                               width[i + 2] = max;
+               }
+               width[i + 2] = fast_len(width[i + 2]);
+               max = 0;
+       }
+       return width;
+}
+
+static unsigned *
+ss_get_width_snum(struct syscall_service *s, struct sysc_meta *sm, int narch)
+{
+       unsigned *width = xcalloc(sizeof(*width), narch + 2);
+       int i, j;
+       unsigned len;
+       unsigned max;
+       int N = 1;
+       struct out_sysc *psysc = sm->sysc_list;
+
+
+       /* Calculate length of 'N' and snum columns */
+       for (i = 0; i < sm->size; i++) {
+               if (psysc[i].sys_num == -1)
+                       continue;
+               max = fast_len(psysc[i].sys_num);
+               if (max > width[1])
+                       width[1] = max;
+               N++;
+       }
+       width[1] = fast_len(width[1]);
+       width[0] = fast_len(N);
+       for (i = 0; i < narch; i++) {
+               for (j = 0; j < sm->size; j++) {
+                       if (!psysc[j].data[i])
+                               continue;
+                       if (s->request_type & SD_REQ_NARGS)
+                               len = *((int *)(psysc[j].data[i]));
+                       else
+                               len = strlen((char *)(psysc[j].data[i]));
+                       if (len > width[i + 2])
+                               width[i + 2] = len;
+               }
+               if (s->request_type & SD_REQ_NARGS)
+                       width[i + 2] = fast_len(width[i + 2]);
+               len = 0;
+       }
+       return width;
+}
+
+void
+ss_dump(struct syscall_service *s, int is_raw)
+{
+       static const char *title[] = {
+               "N",
+               "Syscall name",
+               "Snum",
+       };
+       struct sysc_meta *sm;
+       struct out_sysc *psysc;
+       int ncolumn = ss_size(s);
+       unsigned *title_len;
+       int N = 1;
+       int i, j;
+
+       /* Main work */
+       if (s->request_type & SD_REQ_GET_SNAME) {
+               if (s->request_type & SD_REQ_NARGS)
+                       sm = ss_make_union(s, ssa_save_nargs);
+               else
+                       sm = ss_make_union(s, ssa_save_snum);
+               title_len = ss_get_width_sname(s, sm, ncolumn);
+               if (strlen(title[1]) > title_len[1])
+                       title_len[1] = strlen(title[1]);
+       } else {
+               if (s->request_type & SD_REQ_NARGS)
+                       sm = ss_make_enumeration(s, ssa_save_nargs);
+               else
+                       sm = ss_make_enumeration(s, ssa_save_sname);
+               title_len = ss_get_width_snum(s, sm, ncolumn);
+               if (strlen(title[2]) > title_len[1])
+                       title_len[1] = strlen(title[2]);
+       }
+       psysc = sm->sysc_list;
+       if (is_raw)
+               goto skip_format;
+       /* Adjust width */
+       for (i = 0; i < ncolumn; i++) {
+               if (strlen(s->aws[i].a_name) > title_len[i + 2])
+                       title_len[i + 2] = strlen(s->aws[i].a_name);
+               if (strlen(s->aws[i].arch->abi_mode) > title_len[i + 2])
+                       title_len[i + 2] = strlen(s->aws[i].arch->abi_mode);
+       }
+       /* Print out title */
+       printf("| %*s | %*s |", title_len[0], "", title_len[1], "");
+       for (i = 0; i < ncolumn; i++)
+               printf(" %*s |", title_len[i + 2], s->aws[i].a_name);
+       puts("");
+       printf("| %*s |", title_len[0], title[0]);
+       if (s->request_type & SD_REQ_GET_SNAME)
+               printf(" %*s |", title_len[1], title[1]);
+       else
+               printf(" %*s |", title_len[1], title[2]);
+       for (i = 0; i < ncolumn; i++)
+               printf(" %*s |", title_len[i + 2], s->aws[i].arch->abi_mode);
+       puts("");
+       /* Syscalls */
+       for (i = 0; i < sm->size; i++) {
+               if (s->request_type & SD_REQ_GET_SNAME) {
+                       if (psysc[i].sys_name == NULL)
+                               continue;
+                       printf("| %*d |", title_len[0], N);
+                       printf(" %*s |", title_len[1], psysc[i].sys_name);
+               } else {
+                       if (psysc[i].sys_num == -1)
+                               continue;
+                       printf("| %*d |", title_len[0], N);
+                       printf(" %*d |", title_len[1], psysc[i].sys_num);
+               }
+               for (j = 0; j < ncolumn; j++) {
+                       if (!psysc[i].data[j]) {
+                               printf(" %*s |", title_len[j + 2], "-");
+                               continue;
+                       }
+                       if (s->request_type & SD_REQ_GET_SNAME ||
+                           s->request_type & SD_REQ_NARGS)
+                               printf(" %*d |", title_len[j + 2],
+                                      *((int *)(psysc[i].data[j])));
+                       else
+                               printf(" %*s |", title_len[j + 2],
+                                      (char *)(psysc[i].data[j]));
+               }
+               puts("");
+               N++;
+       }
+       goto out;
+skip_format:
+       for (i = 0; i < sm->size; i++) {
+               if (s->request_type & SD_REQ_GET_SNAME) {
+                       if (psysc[i].sys_name == NULL)
+                               continue;
+                       printf("%d;%s;", N, psysc[i].sys_name);
+               } else {
+                       if (psysc[i].sys_num == -1)
+                               continue;
+                       printf("%d;%d;", N, psysc[i].sys_num);
+               }
+               for (j = 0; j < ncolumn; j++) {
+                       if (!psysc[i].data[j]) {
+                               printf("%c;", '-');
+                               continue;
+                       }
+                       if (s->request_type & SD_REQ_GET_SNAME ||
+                           s->request_type & SD_REQ_NARGS)
+                               printf("%d;", *((int *)(psysc[i].data[j])));
+                       else
+                               printf("%s;", (char *)(psysc[i].data[j]));
+               }
+               puts("");
+               N++;
+       }
+out:
+       /* free, exit */
+       for (i = 0; i < sm->size; i++) {
+               free(psysc[i].data);
+       }
+       free(psysc);
+       free(sm);
+       free(title_len);
+}
diff --git a/tools/asinfo/syscall_interface.h b/tools/asinfo/syscall_interface.h
new file mode 100644
index 00000000..917330cd
--- /dev/null
+++ b/tools/asinfo/syscall_interface.h
@@ -0,0 +1,142 @@
+/*
+ * 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_H
+#define ASINFO_SYSCALL_INTERFACE_H
+
+#include <limits.h>
+#include <stdbool.h>
+
+#include "arch_interface.h"
+#include "error_interface.h"
+#include "sysent.h"
+
+#define SS_FLAG_EMPTY 0
+#define SS_FLAG_PRINT 1
+
+#define HIDDEN_SYSC INT_MIN
+
+/* Complete element type ‘struct number_set’ */
+typedef unsigned int number_slot_t;
+
+struct number_set {
+       number_slot_t *vec;
+       unsigned int nslots;
+       bool not;
+};
+
+/* To avoid include defs.h */
+extern bool is_number_in_set(unsigned int number, const struct number_set *);
+
+struct arch_wrapper {
+       const struct arch_descriptor *arch;
+       /* Mutable user flags for each syscall */
+       int *flag;
+       int *real_snum;
+       char *a_name;
+};
+
+struct syscall_service {
+       struct arch_wrapper *aws;
+       int narch;
+       /* To choose the format while dumping */
+       int request_type;
+       struct error_service *err;
+};
+
+/* These structures are purposed to make union and enumeration with
+   syscall list */
+struct out_sysc {
+       const char *sys_name;
+       int sys_num;
+       void **data;
+};
+
+struct sysc_meta {
+       struct out_sysc *sysc_list;
+       int size;
+};
+
+struct in_sysc {
+       const char *sys_name;
+       void *data;
+};
+
+#define SYSCALL_LIST_DEFINE(name) \
+       struct syscall_service *(name)
+
+/* base methods
+   ss is related to syscall_service
+   ssa is related to arch_wrapper */
+struct syscall_service *ss_create(struct arch_service *m, int request_type);
+
+int ssa_is_ok(struct syscall_service *s, int arch, int num);
+
+struct error_service *ss_err(struct syscall_service *s);
+
+int ss_size(struct syscall_service *m);
+
+int ssa_max_scn(struct syscall_service *s, int arch);
+
+const struct_sysent *ssa_sysc_list(struct syscall_service *s, int arch);
+
+int ssa_flag(struct syscall_service *s, int arch, int num);
+
+int ssa_set_flag(struct syscall_service *s, int arch, int num, int flag);
+
+int ssa_real_num(struct syscall_service *s, int arch, int num);
+
+int ssa_set_real_num(struct syscall_service *s, int arch, int num,
+                    int real_num);
+
+const char *ssa_syscall_name(struct syscall_service *s, int arch, int num);
+
+int ssa_syscall_flag(struct syscall_service *s, int arch, int num);
+
+int ssa_syscall_nargs(struct syscall_service *s, int arch, int num);
+
+int ssa_user_num1(struct syscall_service *s, int arch);
+
+int ssa_user_num2(struct syscall_service *s, int arch);
+
+void ss_free(struct syscall_service *s);
+
+/* calculating methods */
+int ssa_print_size(struct syscall_service *s, int arch);
+
+int ssa_find_snum(struct syscall_service *s, int arch, int real_num);
+
+int ss_mark_matches(struct syscall_service *s, int arch, char *arg);
+
+int ss_update_sc_num(struct syscall_service *s, int arch);
+
+void ss_dump(struct syscall_service *s, int is_raw);
+
+#endif /* !ASINFO_SYSCALL_INTERFACE_H */
-- 
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