[PATCH] asinfo: Introduce static query tool asinfo
Edgar Kaziakhmedov
edgar.kaziakhmedov at virtuozzo.com
Thu Aug 17 23:39:28 UTC 2017
On Tue, 15 Aug 2017 07:55:47 +0300
Edgar Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.com> wrote:
I suppose there is no more need to review this patch, because a lot's
changed from that moment.
Also, I thought that it'd be useful to add processing of some numerical
expression(for syscall) besides regexp and syscall group.
For example, option like
--set-snum 1-10,3,0xf0000
seems convenient(output list of syscalls with this numbers)
And I'd ask, is this format looks enough? I mean, set of numbers and
ranges separated by comma(with hex-dec numbers).
I came to this decision because regexp format doesn't look convenient
here from my point of view.
> 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 */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20170818/d391280f/attachment.bin>
More information about the Strace-devel
mailing list