[PATCH] asinfo: Introduce static query tool asinfo
Edgar Kaziakhmedov
edgar.kaziakhmedov at virtuozzo.com
Tue Aug 15 04:55:47 UTC 2017
The main purpose of this program is to present all information concluded
at sysent.h files as a query tool.
The asinfo tool has the following architecture:
command dispatcher->architecture dispatcher->abi dispatcher->
system call dispatcher.
Each dispatcher accepts proccesed data from previous one.
This point is illustrated by the following example:
$ asinfo --get-arch --get-sysc write
Firstly, arch_dispatcher will return the current architecture, based on
uname return value, after that in case of no options for abi_dispatcher,
it perceives empty parameter as get-abi option and returns ABI mode set at
compile time of strace package. Therefore, syscall_dispatcher accepts this
architecture/ABI and works with specific set of system calls. It is worth
mentioning that it supports all architectures/ABIs supported by strace.
Also, tool can work in multi-arch mode. for instance:
$ ./tools/asinfo/asinfo --set-arch mips64,mips --set-abi n64,all
* 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/arch_interface.h: New file. Introduce struct
arch_descriptor. Introduce arch_service. Prototype methods to simplify
work with the arch_service.
* tools/asinfo/arch_interface.c: New file. Implement it.
* tools/asinfo/syscall_interface.h: New file. Introduce syscall_service.
Prototype methods to simplify work with syscall_service.
* tools/asinfo/syscall_interface.c: New file. Implement it.
* tools/asinfo/request_msgs.h: New file. Introduce main requests.
* tools/asinfo/asinfo.c: New file. Implement support of all options.
Implement usage.
* tools/asinfo/arch_definitions.h: New file. Introduce useful storage
way for architectures.
* tools/asinfo/arch_includes.h: New file.
* tools/asinfo/personalities.h: New file.
* 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/asinfo.1: New file. Empty man.
Signed-off-by: Edgar Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.com>
---
Makefile.am | 2 +-
configure.ac | 2 +
tools/Makefile.am | 28 ++
tools/asinfo/Makefile.am | 65 ++++
tools/asinfo/arch_definitions.h | 70 +++++
tools/asinfo/arch_includes.h | 272 +++++++++++++++++
tools/asinfo/arch_interface.c | 603 ++++++++++++++++++++++++++++++++++++++
tools/asinfo/arch_interface.h | 156 ++++++++++
tools/asinfo/arch_personalities.h | 36 +++
tools/asinfo/asinfo.1 | 0
tools/asinfo/asinfo.c | 295 +++++++++++++++++++
tools/asinfo/dispatchers.c | 219 ++++++++++++++
tools/asinfo/dispatchers.h | 48 +++
tools/asinfo/error_interface.c | 109 +++++++
tools/asinfo/error_interface.h | 95 ++++++
tools/asinfo/request_msgs.h | 97 ++++++
tools/asinfo/syscall_interface.c | 323 ++++++++++++++++++++
tools/asinfo/syscall_interface.h | 104 +++++++
18 files changed, 2523 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.1
create mode 100644 tools/asinfo/asinfo.c
create mode 100644 tools/asinfo/dispatchers.c
create mode 100644 tools/asinfo/dispatchers.h
create mode 100644 tools/asinfo/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 2a477f68..a4a287ae 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 f02b71a0..acd878d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -828,6 +828,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.kaziakhmedov at virtuozzo.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+SUBDIRS = asinfo
diff --git a/tools/asinfo/Makefile.am b/tools/asinfo/Makefile.am
new file mode 100644
index 00000000..19650aba
--- /dev/null
+++ b/tools/asinfo/Makefile.am
@@ -0,0 +1,65 @@
+# Automake input for asinfo.
+#
+# Copyright (c) 2017 Edgar Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+bin_PROGRAMS = asinfo
+man_MANS = asinfo.1
+
+OS = linux
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+AM_CFLAGS = $(WARN_CFLAGS)
+AM_CPPFLAGS = -I$(builddir) \
+ -I$(top_builddir)/$(OS) \
+ -I$(top_srcdir)/$(OS) \
+ -I$(top_builddir) \
+ -I$(top_srcdir)
+asinfo_CPPFLAGS = $(AM_CPPFLAGS)
+asinfo_CFLAGS = $(AM_CFLAGS)
+
+asinfo_SOURCES = \
+ arch_definitions.h \
+ arch_includes.h \
+ arch_interface.c \
+ arch_interface.h \
+ arch_personalities.h \
+ asinfo.c \
+ dispatchers.c \
+ dispatchers.h \
+ error_interface.c \
+ error_interface.h \
+ ../../error_prints.c \
+ ../../error_prints.h \
+ ../../macros.h \
+ request_msgs.h \
+ 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..3e1896fa
--- /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"}) ),
+/* [],[m86k/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/syscallent1.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..7aaca8a6
--- /dev/null
+++ b/tools/asinfo/arch_interface.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "arch_interface.h"
+#include "defs.h"
+#include "macros.h"
+#include "xmalloc.h"
+
+/* Define these shorthand notations to simplify the syscallent files. */
+#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->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)
+{
+ free(m->arch_list);
+ free(m->flag);
+ 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_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;
+
+ 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);
+ 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));
+ }
+ 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_sub_flag(s, start_point + i, AD_FLAG_PRINT);
+ }
+ 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)
+{
+ 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 */
+ 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;
+ printf("| %*u | ", title_len[0], N + 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);
+ }
+ 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)]);
+ memset(whole_arch_name, 0, title_len[1]);
+ N++;
+ }
+ free(whole_arch_name);
+}
diff --git a/tools/asinfo/arch_interface.h b/tools/asinfo/arch_interface.h
new file mode 100644
index 00000000..aedf9e04
--- /dev/null
+++ b/tools/asinfo/arch_interface.h
@@ -0,0 +1,156 @@
+/*
+ * The arch_interface.h is purposed to interact with the basic data structure
+ * based on arch_descriptor struct. Mainly this set of methods are used by
+ * arch_dispatcher.
+ *
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedv at virtuozzo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef ASINFO_ARCH_INTERFACE
+#define ASINFO_ARCH_INTERFACE
+
+#include "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;
+ 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);
+
+/* 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);
+
+#endif /* !ASINFO_ARCH_INTERFACE */
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.1 b/tools/asinfo/asinfo.1
new file mode 100644
index 00000000..e69de29b
diff --git a/tools/asinfo/asinfo.c b/tools/asinfo/asinfo.c
new file mode 100644
index 00000000..e71b672b
--- /dev/null
+++ b/tools/asinfo/asinfo.c
@@ -0,0 +1,295 @@
+/*
+ * The asinfo main source. The asinfo tool is purposed to operate
+ * with system calls and provide information about it.
+ *
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <errno.h>
+#include <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]\n"
+ " or: asinfo [(--set-arch arch | --get-arch) [--set-abi abi]]\n"
+ " (--get-sysc num | name) | (--get-nargs num | name)\n"
+ "\n"
+ "Architecture:\n"
+ " --set-arch arch use architecture ARCH for further operations\n"
+ " argument format: arch1,arch2,...\n"
+ " --get-arch use architecture returned by uname for further operations\n"
+ " --list-arch print out all architectures supported by strace\n"
+ " (combined use list-arch and any ABI option is permitted)\n"
+ "\n"
+ "ABI:\n"
+ " --set-abi abi use application binary interface ABI for further operations\n"
+ " ('all' can be used as ABI to use all compatible personalities\n"
+ " for corresponding architecture)\n"
+ " argument format: abi1,abi2,...\n"
+ " --list-abi print out all ABIs for specified architecture\n"
+ "\n"
+ "System call:\n"
+ " --get-sysc num print name of system call with the NUM number\n"
+ " --get-sysc name print number of all system calls with NAME substring\n"
+ " --get-nargs num get number of arguments of system call with the NUM number\n"
+ " --get-nargs name get number of arguments of system calls with NAME substring\n"
+ " --list-sysc print out all system calls for specified architecture and ABI\n"
+ "\n"
+ "Miscellaneous:\n"
+ " -h print help message\n");
+ exit(0);
+}
+
+void
+die(void)
+{
+ exit(1);
+}
+
+static int
+is_more1bit(unsigned int num)
+{
+ return !(num & (num - 1));
+}
+
+static unsigned
+strpar2req(char *option)
+{
+ /* Convertion table to store string with options */
+ static const char *options[] = {
+ [SD_REQ_GET_SYSC_BIT] = "--get-sysc",
+ [SD_REQ_GET_NARGS_BIT] = "--get-nargs",
+ [SD_REQ_GET_LIST_BIT] = "--list-sysc",
+ [AD_REQ_SET_ARCH_BIT] = "--set-arch",
+ [AD_REQ_GET_ARCH_BIT] = "--get-arch",
+ [AD_REQ_LIST_ARCH_BIT] = "--list-arch",
+ [ABD_REQ_SET_ABI_BIT] = "--set-abi",
+ [ABD_REQ_LIST_ABI_BIT] = "--list-abi",
+ [SERV_REQ_HELP_BIT] = "-h",
+ };
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(options); i++) {
+ if (options[i] && strcmp(option, options[i]) == 0)
+ return i;
+ }
+ return SERV_REQ_ERROR_BIT;
+}
+
+static 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_GET_LIST;
+
+ if (!program_invocation_name || !*program_invocation_name) {
+ static char name[] = "asinfo";
+ program_invocation_name =
+ (argv[0] && *argv[0]) ? argv[0] : name;
+ }
+
+ /* Try to find help option first */
+ for (i = 1; i < argc; i++) {
+ if (strpar2req(argv[i]) == SERV_REQ_HELP_BIT)
+ usage();
+ }
+ /* For now, is is necessary to convert string parameter to number of
+ request and make basic check */
+ for (i = 1; i < argc; i++) {
+ if ((temp_req = strpar2req(argv[i])) == SERV_REQ_ERROR_BIT)
+ error_msg_and_help("unrecognized option '%s'",
+ argv[i]);
+ if (final_req & 1 << temp_req)
+ error_msg_and_help("parameter '%s' has been used "
+ "more than once", argv[i]);
+ if (!((1 << temp_req) & non_req_arg) &&
+ (i + 1 >= argc || strlen(argv[i + 1]) == 0 ||
+ strpar2req(argv[i + 1]) != SERV_REQ_ERROR_BIT))
+ error_msg_and_help("parameter '%s' requires "
+ "argument", argv[i]);
+ final_req |= 1 << temp_req;
+ if (!((1 << temp_req) & non_req_arg)) {
+ 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]);
+ }
+ }
+ 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++;
+ /* Second, final_req should be logically checked */
+ /* More than one option from one request group couldn't be set */
+ if ((is_more1bit(final_req & SD_REQ_MASK) == 0) ||
+ (is_more1bit(final_req & AD_REQ_MASK) == 0) ||
+ (is_more1bit(final_req & ABD_REQ_MASK) == 0) ||
+ (is_more1bit(final_req & FD_REQ_MASK) == 0))
+ error_msg_and_help("exclusive parameters");
+ /* Check on mutually exclusive options chain */
+ /* If at least one syscall option has been typed, therefore
+ arch_options couldn't be list-arch and
+ abi_option couldn't be list-abi */
+ if ((final_req & SD_REQ_MASK) &&
+ (((final_req & AD_REQ_MASK) && (final_req & AD_REQ_LIST_ARCH)) ||
+ ((final_req & ABD_REQ_MASK) && (final_req & ABD_REQ_LIST_ABI))))
+ error_msg_and_help("wrong parameters");
+ /* list-arch couldn't be used with any abi options */
+ if ((final_req & AD_REQ_LIST_ARCH) &&
+ (final_req & ABD_REQ_MASK))
+ error_msg_and_help("'--list-arch' cannot be used with any "
+ "ABI parameters");
+ /* ABI requests could be used just in a combination with arch
+ requests */
+ if ((final_req & ABD_REQ_MASK) &&
+ !(final_req & AD_REQ_MASK))
+ error_msg_and_help("ABI parameters could be used only with "
+ "architecture parameter");
+ /* 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");
+ return final_req;
+}
+
+static char **
+seek_sc_arg(char **input_args[])
+{
+ int i;
+
+ for (i = SD_REQ_GET_SYSC_BIT; i < SYSCALL_REQ_BIT_LAST; i++)
+ if (input_args[i] != NULL)
+ return input_args[i];
+ return NULL;
+}
+
+int
+main(int argc, char *argv[])
+{
+ ARCH_LIST_DEFINE(arch_list);
+ SYSCALL_LIST_DEFINE(sc_list);
+ /* This array is purposed to store arguments for options in the
+ most convenient way */
+ char ***input_args = xcalloc(sizeof(*input_args), REQ_LAST_BIT);
+ unsigned reqs;
+
+ /* command_dispatcher turn */
+ reqs = command_dispatcher(argc, argv, input_args);
+ if (reqs == 0)
+ error_msg_and_help("must have OPTIONS");
+
+ /* arch_dispatcher turn */
+ arch_list = arch_dispatcher(reqs, input_args[AD_REQ_SET_ARCH_BIT]);
+ if (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, input_args[AD_REQ_SET_ARCH_BIT],
+ input_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(input_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);
+ else
+ ss_dump(sc_list);
+ return 0;
+}
diff --git a/tools/asinfo/dispatchers.c b/tools/asinfo/dispatchers.c
new file mode 100644
index 00000000..c01c8e04
--- /dev/null
+++ b/tools/asinfo/dispatchers.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/utsname.h>
+
+#include "arch_interface.h"
+#include "dispatchers.h"
+#include "macros.h"
+#include "request_msgs.h"
+#include "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;
+ }
+ 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 *arch[], 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__) || !defined(ENABLE_ARM_OABI)
+ "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"
+#elif defined(I686)
+ "32bit"
+#endif
+ );
+ 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), arch[0], NULL, NULL);
+ }
+ goto done;
+ }
+
+ if (request_type & ABD_REQ_LIST_ABI) {
+ for (i = 0; i < arch_size; i++)
+ al_add_flag(a_serv, i, AD_FLAG_PRINT);
+ 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), arch[i], abi[i], NULL);
+ break;
+ }
+ }
+done:
+ return 0;
+}
+
+struct syscall_service *
+syscall_dispatcher(struct arch_service *arch, int request_type, char *arg[])
+{
+ SYSCALL_LIST_DEFINE(syscall_list) = ss_create(arch, request_type);
+
+ if (request_type & SD_REQ_MASK) {
+ ss_update_sc_num(syscall_list);
+ ss_mark_matches(syscall_list, arg[0]);
+ }
+
+ return syscall_list;
+}
diff --git a/tools/asinfo/dispatchers.h b/tools/asinfo/dispatchers.h
new file mode 100644
index 00000000..2a566935
--- /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.kaziakhmedov at virtuozzo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef STRACE_ASINFO_COM_SCALLENT
+#define STRACE_ASINFO_COM_SCALLENT
+
+#include "arch_interface.h"
+#include "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 *arch[], char *abi[]);
+
+/* The last stage of main filtering */
+struct syscall_service *syscall_dispatcher(struct arch_service *arch,
+ int request_type, char *arg[]);
+
+#endif /* !STRACE_ASINFO_COM_SCALLENT */
diff --git a/tools/asinfo/error_interface.c b/tools/asinfo/error_interface.c
new file mode 100644
index 00000000..c3f68c67
--- /dev/null
+++ b/tools/asinfo/error_interface.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <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 for '%s' architecture cannot be "
+ "automatically detected",
+ [ABI_WRONG4ARCH_BIT] = "architecture '%s' does not have ABI mode "
+ "'%s'",
+ [SD_WRONG_NUMBER_BIT] = "wrong syscall number",
+ [SD_NUM_NO_EXIST_BIT] = "syscall with that number was not "
+ "implemented",
+ [SD_NAME_NO_EXIST_BIT] = "syscall with that name doesn't exist"
+};
+
+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..7bd509d3
--- /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.kaziakhmedov at virtuozzo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ASINFO_ERROR_INTERFACE
+#define ASINFO_ERROR_INTERFACE
+
+/* errors which using last_arch */
+enum error_arch {
+ AD_UNSUP_ARCH_BIT,
+ ABI_CANNOT_DETECT_BIT,
+
+ ERROR_ARCH_LAST
+};
+
+enum error_no_arg {
+ SD_WRONG_NUMBER_BIT = ERROR_ARCH_LAST,
+ SD_NUM_NO_EXIST_BIT,
+ SD_NAME_NO_EXIST_BIT,
+
+ 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 {
+ /* 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_WRONG_NUMBER),
+ ENUM_FLAG(SD_NUM_NO_EXIST),
+ ENUM_FLAG(SD_NAME_NO_EXIST)
+};
+#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)
+
+struct error_service {
+ char string[255];
+ 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 */
diff --git a/tools/asinfo/request_msgs.h b/tools/asinfo/request_msgs.h
new file mode 100644
index 00000000..fb5ef670
--- /dev/null
+++ b/tools/asinfo/request_msgs.h
@@ -0,0 +1,97 @@
+/*
+ * 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.kaziakhmedov at virtuozzo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef STRACE_ASINFO_REQ_MSGS
+#define STRACE_ASINFO_REQ_MSGS
+
+/* Request types for syscall_dispatcher,
+ * arch_dispatcher, which, in turn, could be combined
+ */
+enum syscall_req_bit {
+ SD_REQ_GET_SYSC_BIT,
+ SD_REQ_GET_NARGS_BIT,
+ SD_REQ_GET_LIST_BIT,
+
+ SYSCALL_REQ_BIT_LAST
+};
+
+enum arch_req_bit {
+ AD_REQ_SET_ARCH_BIT = SYSCALL_REQ_BIT_LAST,
+ AD_REQ_GET_ARCH_BIT,
+ AD_REQ_LIST_ARCH_BIT,
+
+ ARCH_REQ_BIT_LAST
+};
+
+enum abi_req_bit {
+ ABD_REQ_SET_ABI_BIT = ARCH_REQ_BIT_LAST,
+ ABD_REQ_LIST_ABI_BIT,
+
+ ABD_REQ_BIT_LAST
+};
+
+enum fd_req_bit {
+ FD_REQ_SET_BASE_FILTER_BIT = ABD_REQ_BIT_LAST,
+
+ FD_REQ_BIT_LAST
+};
+
+enum serv_req_bit {
+ SERV_REQ_HELP_BIT = FD_REQ_BIT_LAST,
+ SERV_REQ_ERROR_BIT,
+
+ SERV_REQ_BIT_LAST
+};
+
+#define ENUM_FLAG(name) name = 1 << name##_BIT
+enum req_type {
+ ENUM_FLAG(SD_REQ_GET_SYSC),
+ ENUM_FLAG(SD_REQ_GET_NARGS),
+ ENUM_FLAG(SD_REQ_GET_LIST),
+ ENUM_FLAG(AD_REQ_SET_ARCH),
+ ENUM_FLAG(AD_REQ_GET_ARCH),
+ ENUM_FLAG(AD_REQ_LIST_ARCH),
+ ENUM_FLAG(ABD_REQ_SET_ABI),
+ ENUM_FLAG(ABD_REQ_LIST_ABI),
+ ENUM_FLAG(FD_REQ_SET_BASE_FILTER),
+ ENUM_FLAG(SERV_REQ_HELP),
+ ENUM_FLAG(SERV_REQ_ERROR)
+};
+#undef ENUM_FLAG
+
+#define BITMASK(hi, lo) ((1 << (hi)) - (1 << (lo)))
+#define REQ_LAST_BIT SERV_REQ_BIT_LAST
+#define SD_REQ_MASK BITMASK(SYSCALL_REQ_BIT_LAST, 0)
+#define AD_REQ_MASK BITMASK(ARCH_REQ_BIT_LAST, SYSCALL_REQ_BIT_LAST)
+#define ABD_REQ_MASK BITMASK(ABD_REQ_BIT_LAST, ARCH_REQ_BIT_LAST)
+#define FD_REQ_MASK BITMASK(FD_REQ_BIT_LAST, ABD_REQ_BIT_LAST)
+#define SERV_REQ_MASK BITMASK(SERV_REQ_BIT_LAST, FD_REQ_BIT_LAST)
+
+#endif /* !STRACE_ASINFO_REQ_MSGS */
diff --git a/tools/asinfo/syscall_interface.c b/tools/asinfo/syscall_interface.c
new file mode 100644
index 00000000..3eb6b65d
--- /dev/null
+++ b/tools/asinfo/syscall_interface.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedv at virtuozzo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "arch_interface.h"
+#include "error_interface.h"
+#include "syscall_interface.h"
+#include "request_msgs.h"
+#include "xmalloc.h"
+
+struct syscall_service *
+ss_create(struct arch_service *m, int request_type)
+{
+ int i;
+ int arch_list_size = al_size(m);
+ const struct arch_descriptor *ad = NULL;
+ struct syscall_service *ss = NULL;
+
+ /* Function calling syscall_service should make sure,
+ that there is just one arch with AD_FLAG_PRINT flag */
+ for (i = 0; i < arch_list_size; i++)
+ if (al_flag(m, i) & AD_FLAG_PRINT)
+ ad = al_get(m, i);
+ ss = xcalloc(sizeof(*ss), 1);
+ ss->flag = xcalloc(sizeof(*(ss->flag)), ad->max_scn);
+ ss->real_sys_num = xcalloc(sizeof(*(ss->real_sys_num)), ad->max_scn);
+ ss->arch = ad;
+ ss->request_type = request_type;
+ ss->err = al_err(m);
+ return ss;
+}
+
+struct error_service *
+ss_err(struct syscall_service *m)
+{
+ return m->err;
+}
+
+int
+ss_flag(struct syscall_service *s, int num)
+{
+ if (num >= s->arch->max_scn)
+ return -1;
+ return s->flag[num];
+}
+
+int
+ss_set_flag(struct syscall_service *s, int num, int flag)
+{
+ if (num >= s->arch->max_scn)
+ return -1;
+ s->flag[num] = flag;
+ return 0;
+}
+
+enum input_type
+ss_it(struct syscall_service *s)
+{
+ return s->it;
+}
+
+void
+ss_set_input(struct syscall_service *s, enum input_type it)
+{
+ s->it = it;
+}
+
+int
+ss_max_scn(struct syscall_service *s)
+{
+ return s->arch->max_scn;
+}
+
+int
+ss_real_num(struct syscall_service *s, int num)
+{
+ if (num >= s->arch->max_scn)
+ return -1;
+ return s->real_sys_num[num];
+}
+
+int
+ss_set_real_num(struct syscall_service *s, int num, int real_num)
+{
+ if (num >= s->arch->max_scn)
+ return -1;
+ s->real_sys_num[num] = real_num;
+ return 0;
+}
+
+const char *
+ss_syscall_name(struct syscall_service *s, int num)
+{
+ return s->arch->syscall_list[num].sys_name;
+}
+
+int
+ss_syscall_flag(struct syscall_service *s, int num)
+{
+ return s->arch->syscall_list[num].sys_flags;
+}
+
+unsigned
+ss_syscall_nargs(struct syscall_service *s, int num)
+{
+ return s->arch->syscall_list[num].nargs;
+}
+
+int
+ss_user_num1(struct syscall_service *s)
+{
+ return *(s->arch->user_num1);
+}
+
+int
+ss_user_num2(struct syscall_service *s)
+{
+ return *(s->arch->user_num2);
+}
+
+void
+ss_free(struct syscall_service *s)
+{
+ free(s->flag);
+ free(s->real_sys_num);
+ free(s);
+}
+
+int
+ss_find_num(struct syscall_service *s, int real_num)
+{
+ int i;
+ int max_scn = ss_max_scn(s);
+
+ for (i = 0; i < max_scn; i++)
+ if (ss_real_num(s, i) == real_num)
+ return i;
+ return -1;
+}
+
+bool
+ss_is_syscall_valid(struct syscall_service *s, int num)
+{
+ if ((num >= s->arch->max_scn) || (num < 0))
+ return 0;
+ return ss_syscall_name(s, num) &&
+ !(ss_syscall_flag(s, num) & TRACE_INDIRECT_SUBCALL);
+}
+
+int
+ss_mark_matches(struct syscall_service *s, char *arg)
+{
+ int sc_real_number;
+ int sc_num;
+ char sym = 0;
+ char *sc_name = NULL;
+ int sc_count = 0;
+ int i = 0;
+ int max_scn = ss_max_scn(s);
+
+ /* In case of --list-sysc */
+ if (arg == NULL) {
+ for (i = 0; i < max_scn; i++)
+ if (ss_is_syscall_valid(s, i))
+ ss_set_flag(s, i, SS_FLAG_PRINT);
+ return 0;
+ }
+
+ /* Is it a number? */
+ if ((sscanf(arg, "%d%c", &sc_real_number, &sym) == 0) || sym != '\0')
+ sc_name = arg;
+ else if (sc_real_number < 0) {
+ es_set_error(ss_err(s), SD_WRONG_NUMBER);
+ return -1;
+ }
+
+ /* In case of name -> find arg as a substring and mark */
+ if (sc_name != NULL) {
+ for (i = 0; i < max_scn; i++)
+ if (ss_is_syscall_valid(s, i) &&
+ strstr(ss_syscall_name(s, i), sc_name) != NULL) {
+ ss_set_flag(s, i, SS_FLAG_PRINT);
+ sc_count++;
+ }
+ if (sc_count == 0) {
+ es_set_error(ss_err(s), SD_NAME_NO_EXIST);
+ return -1;
+ }
+ ss_set_input(s, IT_STRING);
+ return 0;
+ }
+ /* In case of number -> check and mark */
+ sc_num = ss_find_num(s, sc_real_number);
+ if (ss_is_syscall_valid(s, sc_num)) {
+ ss_set_flag(s, sc_num, SS_FLAG_PRINT);
+ ss_set_input(s, IT_NUMBER);
+ return 0;
+ }
+ es_set_error(ss_err(s), SD_NUM_NO_EXIST);
+ return -1;
+}
+
+#ifndef __X32_SYSCALL_BIT
+# define __X32_SYSCALL_BIT 0x40000000
+#endif
+
+int
+ss_update_sc_num(struct syscall_service *s)
+{
+ int i = 0;
+ int max_scn = ss_max_scn(s);
+ for (i = 0; i < max_scn; i++) {
+ if (!ss_is_syscall_valid(s, i)) {
+ ss_set_real_num(s, i, -1);
+ continue;
+ }
+ switch (s->arch->pers) {
+ case ARCH_x86_64_x32:
+ ss_set_real_num(s, i, i + __X32_SYSCALL_BIT);
+ break;
+ case ARCH_arm_oabi:
+ case ARCH_arm_eabi:
+ if (i == ss_user_num1(s))
+ ss_set_real_num(s, i, 0x000ffff0);
+ if ((i >= ss_user_num1(s) + 1) &&
+ (i <= ss_user_num1(s) + ss_user_num2(s) + 1))
+ ss_set_real_num(s, i, i + 0x000f0000 -
+ ss_user_num1(s) - 1);
+ if (i < ss_user_num1(s))
+ ss_set_real_num(s, i, i);
+ break;
+ case ARCH_sh64_64bit:
+ ss_set_real_num(s, i, i & 0xffff);
+ default:
+ ss_set_real_num(s, i, i);
+ }
+ }
+ return 0;
+}
+
+void
+ss_dump(struct syscall_service *s)
+{
+ static const char *title[] = {
+ "System call name",
+ "Syscall num",
+ "Nargs",
+ };
+ int title_len[] = {
+ strlen(title[0]),
+ strlen(title[1]),
+ strlen(title[2]),
+ };
+ int i;
+ int max_scn = ss_max_scn(s);
+ int temp_len = 0;
+
+ /* Update title_len[0] */
+ for (i = 0; i < max_scn; i++) {
+ if (!(ss_flag(s, i) & SS_FLAG_PRINT))
+ continue;
+ temp_len = strlen(ss_syscall_name(s, i));
+ if (temp_len > title_len[0])
+ title_len[0] = temp_len;
+ }
+ /* Print title */
+ if (s->request_type & SD_REQ_GET_LIST)
+ printf("| %*s | %*s | %*s |\n", title_len[0], title[0],
+ title_len[1], title[1],
+ title_len[2], title[2]);
+ if (s->request_type & SD_REQ_GET_SYSC)
+ printf("| %*s | %*s |\n", title_len[0], title[0],
+ title_len[1], title[1]);
+ if (s->request_type & SD_REQ_GET_NARGS)
+ printf("| %*s | %*s |\n", title_len[0], title[0],
+ title_len[2], title[2]);
+ /* Print out syscall or list of syscalls */
+ for (i = 0; i < max_scn; i++) {
+ if (!(ss_flag(s, i) & SS_FLAG_PRINT))
+ continue;
+ if (s->request_type & SD_REQ_GET_LIST)
+ printf("| %*s | %*d | %*u |\n",
+ title_len[0], ss_syscall_name(s, i),
+ title_len[1], ss_real_num(s, i),
+ title_len[2], ss_syscall_nargs(s, i));
+ if (s->request_type & SD_REQ_GET_SYSC)
+ printf("| %*s | %*d |\n",
+ title_len[0], ss_syscall_name(s, i),
+ title_len[1], ss_real_num(s, i));
+ if (s->request_type & SD_REQ_GET_NARGS)
+ printf("| %*s | %*u |\n",
+ title_len[0], ss_syscall_name(s, i),
+ title_len[2], ss_syscall_nargs(s, i));
+ }
+}
diff --git a/tools/asinfo/syscall_interface.h b/tools/asinfo/syscall_interface.h
new file mode 100644
index 00000000..ae8f2c1e
--- /dev/null
+++ b/tools/asinfo/syscall_interface.h
@@ -0,0 +1,104 @@
+/*
+ * 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.kaziakhmedv at virtuozzo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef ASINFO_SYSCALL_INTERFACE
+#define ASINFO_SYSCALL_INTERFACE
+
+#include <stdbool.h>
+
+#include "arch_interface.h"
+#include "error_interface.h"
+
+#define SS_FLAG_EMPTY 0
+#define SS_FLAG_PRINT 1
+
+enum input_type {
+ IT_STRING = 1,
+ IT_NUMBER
+};
+
+struct syscall_service {
+ const struct arch_descriptor *arch;
+ /* Mutable user flags for each syscall */
+ int *flag;
+ int *real_sys_num;
+ /* To choose the format while dumping */
+ int request_type;
+ /* To detect input type */
+ enum input_type it;
+ struct error_service *err;
+};
+
+#define SYSCALL_LIST_DEFINE(name) \
+ struct syscall_service *(name)
+
+/* base methods */
+struct syscall_service *ss_create(struct arch_service *m, int request_type);
+
+struct error_service *ss_err(struct syscall_service *m);
+
+int ss_flag(struct syscall_service *s, int num);
+
+int ss_set_flag(struct syscall_service *s, int num, int flag);
+
+enum input_type ss_it(struct syscall_service *s);
+
+void ss_set_input(struct syscall_service *s, enum input_type it);
+
+int ss_max_scn(struct syscall_service *s);
+
+int ss_real_num(struct syscall_service *s, int num);
+
+int ss_set_real_num(struct syscall_service *s, int num, int real_num);
+
+const char *ss_syscall_name(struct syscall_service *s, int num);
+
+int ss_syscall_flag(struct syscall_service *s, int num);
+
+unsigned ss_syscall_nargs(struct syscall_service *s, int num);
+
+int ss_user_num1(struct syscall_service *s);
+
+int ss_user_num2(struct syscall_service *s);
+
+void ss_free(struct syscall_service *s);
+
+/* calculating methods */
+int ss_find_num(struct syscall_service *s, int real_num);
+
+bool ss_is_syscall_valid(struct syscall_service *s, int num);
+
+int ss_mark_matches(struct syscall_service *s, char *arg);
+
+int ss_update_sc_num(struct syscall_service *s);
+
+void ss_dump(struct syscall_service *s);
+
+#endif /* !ASINFO_SYSCALL_INTERFACE */
--
2.11.0
More information about the Strace-devel
mailing list