[PATCH 3/3] asinfo: Introduce static query tool asinfo
Edgar Kaziakhmedov
edgar.kaziakhmedov at virtuozzo.com
Wed Aug 9 10:15:07 UTC 2017
On Mon, 7 Aug 2017 20:18:23 +0200
Eugene Syromiatnikov <esyr at redhat.com> wrote:
> On Sat, Aug 05, 2017 at 04:57:36AM +0300, Edgar Kaziakhmedov wrote:
> > From: Edgar Kaziakhmedov <edgar.kaziakhmedov at virtuzzo.com>
> "virtuozzo"
>
> >
> > The main purpose of this program is to present all information
> > concluded at sysent.h files as a query tool.
> > The asinfo tool has the following architecture:
> > command dispatcher->architecture dispatcher->abi dispatcher->
> > system call dispatcher->filter dispatcher.
> > Each dispatcher accepts proccesed data from previous one.
> >
> > This point is illustrated by the following example:
> > $ asinfo --get-arch --get-sysc write
> > Firstly, arch_dispatcher will return the current architecture,
> > based on uname return value, after that in case of no options for
> > abi_dispatcher, AD perceives it as get-abi option and returns ABI
> > mode set at compile
> Does AD stand for "architecture dispatcher" or "ABI dispatcher"?
>
> > time of strace package. Therefore, syscall_dispatcher accepts this
> > architecture/ABI and works with specific set of system calls. It is
> > worth mentioning that it supports all architectures/ABIs supported
> > by strace.
> >
> > * Makefile.am (SUBDIRS): Add tools directory.
> > * configure.ac (AC_CONFIG_FILES): Add Makefile's.
> "Makefiles"
>
> > * tools/Makefile.am: New file.
> > * tools/asinfo/Makefile.am: New file.
> > * tools/asinfo/dispatchers.h: New file. Prototype abi_dispatcher,
> > arch_dispatcher, and syscall_dispatcher.
> > * tools/asinfo/dispatchers.c: New file. Implement it.
> > * tools/asinfo/arch_interface.h: New file. Introduce struct
> > arch_descriptor. Introduce arch_service. Prototype methods to
> > simplify work with the arch_service.
> > * tools/asinfo/arch_interface.c: New file. Implement it.
> > * tools/asinfo/syscall_interface.h: New file. Introduce
> > syscall_service. Prototype methods to simplify work with
> > syscall_service.
> > * tools/asinfo/syscall_interface.c: New file. Implement it.
> > * tools/asinfo/request_msgs.h: New file. Introduce main requests.
> > * tools/asinfo/asinfo.c: New file. Implement support of all options.
> > Implement usage.
> > * tools/asinfo/asinfo.1: New file. Empty man.
> >
> > Signed-off-by: Edgar Kaziakhmedov <edgar.kaziakhmedov at virtuozzo.com>
> > ---
> > Makefile.am | 2 +-
> > configure.ac | 2 +
> > tools/Makefile.am | 28 ++
> > tools/asinfo/Makefile.am | 59 +++
> > tools/asinfo/arch_interface.c | 865
> > +++++++++++++++++++++++++++++++++++++++
> > tools/asinfo/arch_interface.h | 185 +++++++++
> > tools/asinfo/asinfo.1 | 0
> > tools/asinfo/asinfo.c | 245 +++++++++++
> > tools/asinfo/dispatchers.c | 253 ++++++++++++
> > tools/asinfo/dispatchers.h | 48 +++
> > tools/asinfo/request_msgs.h | 100 +++++
> > tools/asinfo/syscall_interface.c | 339 +++++++++++++++
> > tools/asinfo/syscall_interface.h | 114 ++++++ 13 files changed,
> > 2239 insertions(+), 1 deletion(-) create mode 100644
> > tools/Makefile.am create mode 100644 tools/asinfo/Makefile.am
> > create mode 100644 tools/asinfo/arch_interface.c
> > create mode 100644 tools/asinfo/arch_interface.h
> > create mode 100644 tools/asinfo/asinfo.1
> > create mode 100644 tools/asinfo/asinfo.c
> > create mode 100644 tools/asinfo/dispatchers.c
> > create mode 100644 tools/asinfo/dispatchers.h
> > create mode 100644 tools/asinfo/request_msgs.h
> > create mode 100644 tools/asinfo/syscall_interface.c
> > create mode 100644 tools/asinfo/syscall_interface.h
> >
> > diff --git a/Makefile.am b/Makefile.am
> > index ae119a75..ff89f3c5 100644
> > --- a/Makefile.am
> > +++ b/Makefile.am
> > @@ -35,7 +35,7 @@ endif
> > if HAVE_MX32_RUNTIME
> > TESTS_MX32 = tests-mx32
> > endif
> > -SUBDIRS = tests $(TESTS_M32) $(TESTS_MX32)
> > +SUBDIRS = tests $(TESTS_M32) $(TESTS_MX32) tools
> >
> > bin_PROGRAMS = strace
> > man_MANS = strace.1
> > diff --git a/configure.ac b/configure.ac
> > index 7a9abf8f..ee5f651c 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -814,6 +814,8 @@ AC_CONFIG_FILES([Makefile
> > tests/Makefile
> > tests-m32/Makefile
> > tests-mx32/Makefile
> > + tools/Makefile
> > + tools/asinfo/Makefile
> > strace.spec
> > debian/changelog])
> > AC_OUTPUT
> > diff --git a/tools/Makefile.am b/tools/Makefile.am
> > new file mode 100644
> > index 00000000..f1c75cfb
> > --- /dev/null
> > +++ b/tools/Makefile.am
> > @@ -0,0 +1,28 @@
> > +# Automake input for strace tools.
> > +#
> > +# Copyright (c) 2017 Edgar A. Kaziakhmedov
> > <edgar.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..924e3585
> > --- /dev/null
> > +++ b/tools/asinfo/Makefile.am
> > @@ -0,0 +1,59 @@
> > +# 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_interface.c \
> > + arch_interface.h \
> > + asinfo.c \
> > + dispatchers.c \
> > + dispatchers.h \
> > + ../../error_prints.c \
> > + ../../error_prints.h \
> > + ../../macros.h \
> > + requests_msgs.h \
> "request_msgs.h"
>
> > + ../../shorthand-def.h \
> "../../shorthand_def.h"
>
> > + syscall_interface.c \
> > + syscall_interface.h \
> > + ../../xmalloc.c \
> > + ../../xmalloc.h \
> > + #end of asinfo_SOURCES
> > diff --git a/tools/asinfo/arch_interface.c
> > b/tools/asinfo/arch_interface.c new file mode 100644
> > index 00000000..efd2def4
> > --- /dev/null
> > +++ b/tools/asinfo/arch_interface.c
> > @@ -0,0 +1,865 @@
> > +/*
> > + * Copyright (c) 2017 Edgar A. Kaziakhmedov
> > <edgar.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. */ +/* These flags could be useful to print group of
> > syscalls */ +#define DEFINE_SHORTHAND
> > +#include "shorthand_def.h"
> > +
> > +/*
> > + * For the current functionality there is no need
> > + * to use sen and (*sys_func)() fields in sysent struct
> > + */
> > +#define SEN(syscall_name) 0, NULL
> > +
> > +/* dummy_sysent is purposed to set syscall_list field in
> > + * inherited architectures */
> > +struct_sysent dummy_sysent[] = {};
> static const
>
> > +
> > +/* ARCH_blackfin */
> > +struct_sysent blackfin_32bit_sysent[] = {
> static const
>
> > + #include "bfin/syscallent.h"
> > +};
> > +const int blackfin_32bit_usr1 = 0;
> static
>
> > +const int blackfin_32bit_usr2 = 0;
> static
>
> > +/* ARCH_ia64 */
> > +struct_sysent ia64_64bit_sysent[] = {
> static const
>
> > + #include "ia64/syscallent.h"
> > +};
> > +const int ia64_64bit_usr1 = 0;
> static
>
> > +const int ia64_64bit_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_m68k */
> > +struct_sysent m68k_32bit_sysent[] = {
> static const
>
> > + #include "m68k/syscallent.h"
> > +};
> > +const int m68k_32bit_usr1 = 0;
> static
>
> > +const int m68k_32bit_usr2 = 0;
> static
>
> > +/* ARCH_sparc64 64bit ABI */
> > +struct_sysent sparc64_64bit_sysent[] = {
> static const
>
> > + #include "sparc64/syscallent.h"
> > +};
> > +const int sparc64_64bit_usr1 = 0;
> static
>
> > +const int sparc64_64bit_usr2 = 0;
> static
>
> > +/* ARCH_sparc64 32bit ABI */
> > +struct_sysent sparc64_32bit_sysent[] = {
> static const
>
> > + #include "sparc64/syscallent1.h"
> > +};
> > +const int sparc64_32bit_usr1 = 0;
> static
>
> > +const int sparc64_32bit_usr2 = 0;
> static
>
> > +/* ARCH_sparc */
> > +struct_sysent sparc_32bit_sysent[] = {
> static const
>
> > + #include "sparc/syscallent.h"
> > +};
> > +const int sparc_32bit_usr1 = 0;
> static
>
> > +const int sparc_32bit_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_metag */
> > +struct_sysent metag_32bit_sysent[] = {
> static const
>
> > + #include "metag/syscallent.h"
> > +};
> > +const int metag_32bit_usr1 = 0;
> static
>
> > +const int metag_32bit_usr2 = 0;
> static
>
> > +/* ARCH_mips o32 ABI */
> > +#ifndef LINUX_MIPSO32
> > +# define LINUX_MIPSO32 1
> > +# define NOW_DEFINED 1
> > +#endif
> > +struct_sysent mips_o32_sysent[] = {
> static const
>
> > + #include "dummy.h"
> > + #include "mips/syscallent-compat.h"
> > + #include "mips/syscallent-o32.h"
> > +};
> > +#ifdef NOW_DEFINED
> > +# undef LINUX_MIPSO32
> > +# undef NOW_DEFINED
> > +#endif
> > +const int mips_o32_usr1 = 0;
> static
>
> > +const int mips_o32_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_mips n32 ABI */
> > +#ifndef LINUX_MIPSN32
> > +# define LINUX_MIPSN32 1
> > +# define NOW_DEFINED 1
> > +#endif
> > +struct_sysent mips_n32_sysent[] = {
> static const
>
> > + #include "dummy.h"
> > + #include "mips/syscallent-compat.h"
> > + #include "mips/syscallent-n32.h"
> > +};
> > +#ifdef NOW_DEFINED
> > +# undef LINUX_MIPSN32
> > +# undef NOW_DEFINED
> > +#endif
> > +const int mips_n32_usr1 = 0;
> static
>
> > +const int mips_n32_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_mips n64 ABI */
> > +#ifndef LINUX_MIPSN64
> > +# define LINUX_MIPSN64 1
> > +# define NOW_DEFINED 1
> > +#endif
> > +struct_sysent mips_n64_sysent[] = {
> static const
>
> > + #include "dummy.h"
> > + #include "mips/syscallent-compat.h"
> > + #include "mips/syscallent-n64.h"
> > +};
> > +#ifdef NOW_DEFINED
> > +# undef LINUX_MIPSN32
> > +# undef NOW_DEFINED
> > +#endif
> > +const int mips_n64_usr1 = 0;
> static
>
> > +const int mips_n64_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_alpha */
> > +struct_sysent alpha_64bit_sysent[] = {
> static const
>
> > + #include "alpha/syscallent.h"
> > +};
> > +const int alpha_64bit_usr1 = 0;
> static
>
> > +const int alpha_64bit_usr2 = 0;
> static
>
> > +/* ARCH_ppc */
> > +struct_sysent ppc_32bit_sysent[] = {
> static const
>
> > + #include "powerpc/syscallent.h"
> > +};
> > +const int ppc_32bit_usr1 = 0;
> static
>
> > +const int ppc_32bit_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_ppc64 64bit ABI */
> > +struct_sysent ppc64_64bit_sysent[] = {
> static const
>
> > + #include "powerpc64/syscallent.h"
> > +};
> > +const int ppc64_64bit_usr1 = 0;
> static
>
> > +const int ppc64_64bit_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_ppc64 32bit ABI */
> > +struct_sysent ppc64_32bit_sysent[] = {
> static const
>
> > + #include "powerpc64/syscallent1.h"
> > +};
> > +const int ppc64_32bit_usr1 = 0;
> static
>
> > +const int ppc64_32bit_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_arm OABI*/
> > +#ifdef __ARM_EABI__
> > +# undef __ARM_EABI__
> > +# define NOW_UNDEFINED 1
> > +#endif
> > +struct_sysent arm_oabi_sysent[] = {
> static const
>
> > + #include "arm/syscallent.h"
> > +};
> > +const int arm_oabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
> static
>
> > +const int arm_oabi_usr2 = ARM_LAST_SPECIAL_SYSCALL;
> static
>
> > +#undef ARM_FIRST_SHUFFLED_SYSCALL
> > +#undef ARM_LAST_SPECIAL_SYSCALL
> > +#undef SYS_socket_subcall
> > +#ifdef NOW_UNDEFINED
> > +# define __ARM_EABI__ 1
> > +# undef NOW_UNDEFINED
> > +#endif
> > +/* ARCH_arm EABI*/
> > +#ifndef __ARM_EABI__
> > +# define __ARM_EABI__ 1
> > +# define NOW_DEFINED 1
> > +#endif
> > +struct_sysent arm_eabi_sysent[] = {
> static const
>
> > + #include "arm/syscallent.h"
> > +};
> > +const int arm_eabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
> static
>
> > +const int arm_eabi_usr2 = ARM_LAST_SPECIAL_SYSCALL;
> static
>
> > +#undef ARM_FIRST_SHUFFLED_SYSCALL
> > +#undef ARM_LAST_SPECIAL_SYSCALL
> > +#ifdef NOW_DEFINED
> > +# undef __ARM_EABI__
> > +# undef NOW_DEFINED
> > +#endif
> > +/* ARCH_aarch64 64bit ABI */
> > +struct_sysent aarch64_64bit_sysent[] = {
> static const
>
> > + #include "aarch64/syscallent.h"
> > +};
> > +const int aarch64_64bit_usr1 = 0;
> static
>
> > +const int aarch64_64bit_usr2 = 0;
> static
>
> > +/* ARCH_aarch64 32bit ABI */
> > +#ifndef __ARM_EABI__
> > +# define __ARM_EABI__ 1
> > +# define NOW_DEFINED 1
> > +#endif
> > +struct_sysent aarch64_32bit_sysent[] = {
> static const
>
> > + #include "aarch64/syscallent1.h"
> > +};
> > +const int aarch64_32bit_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
> static
>
> > +const int aarch64_32bit_usr2 = ARM_LAST_SPECIAL_SYSCALL;
> static
>
> > +#undef ARM_FIRST_SHUFFLED_SYSCALL
> > +#undef ARM_LAST_SPECIAL_SYSCALL
> > +#ifdef NOW_DEFINED
> > +# undef __ARM_EABI__
> > +# undef NOW_DEFINED
> > +#endif
> > +/* ARCH_avr32 */
> > +struct_sysent avr32_32bit_sysent[] = {
> static const
>
> > + #include "avr32/syscallent.h"
> > +};
> > +const int avr32_32bit_usr1 = 0;
> static
>
> > +const int avr32_32bit_usr2 = 0;
> static
>
> > +/* ARCH_arc */
> > +struct_sysent arc_32bit_sysent[] = {
> static const
>
> > + #include "arc/syscallent.h"
> > +};
> > +const int arc_32bit_usr1 = 0;
> static
>
> > +const int arc_32bit_usr2 = 0;
> static
>
> > +/* ARCH_s390 */
> > +struct_sysent s390_32bit_sysent[] = {
> static const
>
> > + #include "s390/syscallent.h"
> > +};
> > +const int s390_32bit_usr1 = 0;
> static
>
> > +const int s390_32bit_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_s390x */
> > +struct_sysent s390x_64bit_sysent[] = {
> static const
>
> > + #include "s390x/syscallent.h"
> > +};
> > +const int s390x_64bit_usr1 = 0;
> static
>
> > +const int s390x_64bit_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_hppa */
> > +struct_sysent hppa_32bit_sysent[] = {
> static const
>
> > + #include "hppa/syscallent.h"
> > +};
> > +const int hppa_32bit_usr1 = 0;
> static
>
> > +const int hppa_32bit_usr2 = 0;
> static
>
> > +/* ARCH_parisc */
> > +#define parisc_32bit_sysent dummy_sysent
> > +const int parisc_32bit_usr1 = 0;
> static
>
> > +const int parisc_32bit_usr2 = 0;
> static
>
> > +/* ARCH_sh */
> > +struct_sysent sh_32bit_sysent[] = {
> static const
>
> > + #include "sh/syscallent.h"
> > +};
> > +const int sh_32bit_usr1 = 0;
> static
>
> > +const int sh_32bit_usr2 = 0;
> static
>
> > +/* ARCH_sh64 */
> > +struct_sysent sh64_64bit_sysent[] = {
> static const
>
> > + #include "sh64/syscallent.h"
> > +};
> > +const int sh64_64bit_usr1 = 0;
> static
>
> > +const int sh64_64bit_usr2 = 0;
> static
>
> > +/* ARCH_x86 */
> > +struct_sysent x86_32bit_sysent[] = {
> static const
>
> > + #include "i386/syscallent.h"
> > +};
> > +const int x86_32bit_usr1 = 0;
> static
>
> > +const int x86_32bit_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_i386 */
> > +#define i386_32bit_sysent dummy_sysent
> > +const int i386_32bit_usr1 = 0;
> static
>
> > +const int i386_32bit_usr2 = 0;
> static
>
> > +/* ARCH_i486 */
> > +#define i486_32bit_sysent dummy_sysent
> > +const int i486_32bit_usr1 = 0;
> static
>
> > +const int i486_32bit_usr2 = 0;
> static
>
> > +/* ARCH_i586 */
> > +#define i586_32bit_sysent dummy_sysent
> > +const int i586_32bit_usr1 = 0;
> static
>
> > +const int i586_32bit_usr2 = 0;
> static
>
> > +/* ARCH_i686 */
> > +#define i686_32bit_sysent dummy_sysent
> > +const int i686_32bit_usr1 = 0;
> static
>
> > +const int i686_32bit_usr2 = 0;
> static
>
> I don't quite understand why these definitions are per-alias and not
> per-ABI.
>
> > +/* ARCH_x86_64 64bit ABI mode */
> > +struct_sysent x86_64_64bit_sysent[] = {
> static const
>
> > + #include "x86_64/syscallent.h"
> > +};
> > +const int x86_64_64bit_usr1 = 0;
> static
>
> > +const int x86_64_64bit_usr2 = 0;
> static
>
> > +/* ARCH_x86_64 32bit ABI mode */
> > +struct_sysent x86_64_32bit_sysent[] = {
> static const
>
> > + #include "x86_64/syscallent1.h"
> > +};
> > +const int x86_64_32bit_usr1 = 0;
> static
>
> > +const int x86_64_32bit_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_x86_64 x32 ABI mode */
> > +struct_sysent x86_64_x32_sysent[] = {
> static const
>
> > + #include "x86_64/syscallent2.h"
> > +};
> > +const int x86_64_x32_usr1 = 0;
> static
>
> > +const int x86_64_x32_usr2 = 0;
> static
>
> > +/* ARCH_amd64 */
> > +#define amd64_64bit_sysent dummy_sysent
> > +const int amd64_64bit_usr1 = 0;
> static
>
> > +const int amd64_64bit_usr2 = 0;
> static
>
> > +/* ARCH_cris */
> > +struct_sysent cris_32bit_sysent[] = {
> static const
>
> > + #include "crisv10/syscallent.h"
> > +};
> > +const int cris_32bit_usr1 = 0;
> static
>
> > +const int cris_32bit_usr2 = 0;
> static
>
> > +/* ARCH_crisv10 */
> > +#define crisv10_32bit_sysent dummy_sysent
> > +const int crisv10_32bit_usr1 = 0;
> static
>
> > +const int crisv10_32bit_usr2 = 0;
> static
>
> > +/* ARCH_crisv32 */
> > +struct_sysent crisv32_32bit_sysent[] = {
> static const
>
> > + #include "crisv32/syscallent.h"
> > +};
> > +const int crisv32_32bit_usr1 = 0;
> static
>
> > +const int crisv32_32bit_usr2 = 0;
> static
>
> > +#undef SYS_socket_subcall
> > +/* ARCH_tile 64bit ABI mode */
> > +struct_sysent tile_64bit_sysent[] = {
> static const
>
> > + #include "tile/syscallent.h"
> > +};
> > +const int tile_64bit_usr1 = 0;
> static
>
> > +const int tile_64bit_usr2 = 0;
> static
>
> > +/* ARCH_tile 32bit ABI mode */
> > +struct_sysent tile_32bit_sysent[] = {
> static const
>
> > + #include "tile/syscallent1.h"
> > +};
> > +const int tile_32bit_usr1 = 0;
> static
>
> > +const int tile_32bit_usr2 = 0;
> static
>
> > +/* ARCH_microblaze */
> > +struct_sysent microblaze_32bit_sysent[] = {
> static const
>
> > + #include "microblaze/syscallent.h"
> > +};
> > +const int microblaze_32bit_usr1 = 0;
> static
>
> > +const int microblaze_32bit_usr2 = 0;
> static
>
> > +/* ARCH_nios2 */
> > +struct_sysent nios2_32bit_sysent[] = {
> static const
>
> > + #include "nios2/syscallent.h"
> > +};
> > +const int nios2_32bit_usr1 = 0;
> static
>
> > +const int nios2_32bit_usr2 = 0;
> static
>
> > +/* ARCH_openrisc */
> > +struct_sysent openrisc_32bit_sysent[] = {
> static const
>
> > + #include "or1k/syscallent.h"
> > +};
> > +const int openrisc_32bit_usr1 = 0;
> static
>
> > +const int openrisc_32bit_usr2 = 0;
> static
>
> > +/* ARCH_xtensa */
> > +struct_sysent xtensa_32bit_sysent[] = {
> static const
>
> > + #include "xtensa/syscallent.h"
> > +};
> > +const int xtensa_32bit_usr1 = 0;
> static
>
> > +const int xtensa_32bit_usr2 = 0;
> static
>
> > +/* ARCH_riscv 64bit ABI mode */
> > +struct_sysent riscv_64bit_sysent[] = {
> static const
>
> > + #include "riscv/syscallent.h"
> > +};
> > +const int riscv_64bit_usr1 = 0;
> static
>
> > +const int riscv_64bit_usr2 = 0;
> static
>
> > +/* ARCH_riscv 32bit ABI mode */
> > +struct_sysent riscv_32bit_sysent[] = {
> static const
>
> > + #include "riscv/syscallent1.h"
> > +};
> > +const int riscv_32bit_usr1 = 0;
> static
>
> > +const int riscv_32bit_usr2 = 0;
> static
>
> > +
> > +#undef DEFINE_SYSCALLENT
> > +
> > +#define DEFINE_SHORTHAND
> > +#include "shorthand_def.h"
> > +
> > +#define ARCH_DESC_DEFINE(arch, base_arch, mode) \
> > + [ARCH_##arch##_##mode] = { \
> > + .arch_num = ARCH_##arch##_##mode, \
> > + .arch_name = #arch, \
> > + .arch_name_len = ARRAY_SIZE(#arch)
> > - 1, \
> > + .arch_base_num =
> > ARCH_##base_arch##_##mode, \
> > + .abi_mode = #mode, \
> > + .abi_mode_len = ARRAY_SIZE(#arch) -
> > 1, \
> > + .max_scn =
> > ARRAY_SIZE(arch##_##mode##_sysent), \
> > + .syscall_list =
> > arch##_##mode##_sysent, \
> > + .user_num1 = &arch##_##mode##_usr1,
> > \
> > + .user_num2 = &arch##_##mode##_usr2,
> > \
> > + }
> I think that having list of aliases defined as a list of strings
> inside of ABI descriptor would significantly ease many things.
>
> The other thing I think superfluous is things like x86_64_32bit. I
> think, we can provide the information about compatible ABIs (other
> than native one) in yet another field.
>
> So something like this should be fine:
>
> #define MAX_ALIASES 6
> #define MAX_ALT_PERS 4
>
> struct arch_descriptor {
> /* enum arch_name_abi arch_num; */
> /* This should be equivalent to array index,
> but if
> * you want to pass the pointer to
> arch_descriptor
> * outside array, it probably makes sense to
> leave
> * it here as is */
>
> const char *arch_names[MAX_ALIASES];
> const char *abi_mode;
> int abi_mode_len;
> const int max_scn;
> struct_sysent *syscall_list;
> uint64_t compatible_pers;
> const int *user_num1;
> const int *user_num2;
> }
>
> And the definition macro like this:
>
> #define ARCH_DESC_DEFINE(arch, mode, compat_pers, ...) \
> [ARCH_##arch##_##mode] = { \
> /* .arch_num =
> ARCH_##arch##_##mode, */ \ .arch_names =
> { __VA_ARGS__ }, \ .abi_mode = #mode, \
> .abi_mode_len =
> ARRAY_SIZE(#arch) - 1, \ .max_scn =
> ARRAY_SIZE(arch##_##mode##_sysent), \ .syscall_list =
> arch##_##mode##_sysent, \ .user_num1 =
> &arch##_##mode##_usr1, \ .user_num2 =
> &arch##_##mode##_usr2, \ }
>
> And definitions like this:
>
> ARCH_DESC_DEFINE(x86, 32bit, 0, "x86", "i386", "i486",
> "i586", "i686"), ARCH_DESC_DEFINE(x86_64, 64bit, 1 << ARCH_x86_32bit
> | 1 << ARCH_x86_64_x32, "x86_64", "amd64", "EM64T"),
> ARCH_DESC_DEFINE(x86_64, x32, 1 << ARCH_x86_32bit, "x32"), ...
>
> This way, you're getting rid of "base_arch" concept, needless
> duplication of variables, leaving other places essentially the same
> (the search is still linear, just over jagged two-dimensional array
> containing the same amount of element, output alignment code, however,
> is going to be a little worse, as I dropped arch_name_len, since I
> don't see an easy way to derive it with this setup)
>
>
>
>
> > +/* Generate array of arch_descriptors for each architecture and
> > mode */ +struct arch_descriptor architectures[] = {
> const
>
> > + ARCH_DESC_DEFINE(blackfin, blackfin,
> > 32bit ),
> > + ARCH_DESC_DEFINE(ia64, ia64,
> > 64bit ),
> > + ARCH_DESC_DEFINE(m68k, m68k,
> > 32bit ),
> > + ARCH_DESC_DEFINE(sparc64, sparc64,
> > 64bit ),
> > + ARCH_DESC_DEFINE(sparc64, sparc64,
> > 32bit ),
> > + ARCH_DESC_DEFINE(sparc,
> > sparc, 32bit ),
> > + ARCH_DESC_DEFINE(metag,
> > metag, 32bit ),
> > + ARCH_DESC_DEFINE(mips, mips,
> > o32 ),
> > + ARCH_DESC_DEFINE(mips, mips,
> > n32 ),
> > + ARCH_DESC_DEFINE(mips, mips,
> > n64 ),
> > + ARCH_DESC_DEFINE(alpha,
> > alpha, 64bit ),
> > + ARCH_DESC_DEFINE(ppc, ppc,
> > 32bit ),
> > + ARCH_DESC_DEFINE(ppc64,
> > ppc64, 64bit ),
> > + ARCH_DESC_DEFINE(ppc64,
> > ppc64, 32bit ),
> > + ARCH_DESC_DEFINE(arm, arm,
> > oabi ),
> > + ARCH_DESC_DEFINE(arm, arm,
> > eabi ),
> > + ARCH_DESC_DEFINE(aarch64, aarch64,
> > 64bit ),
> > + ARCH_DESC_DEFINE(aarch64, aarch64,
> > 32bit ),
> > + ARCH_DESC_DEFINE(avr32,
> > avr32, 32bit ),
> > + ARCH_DESC_DEFINE(arc, arc,
> > 32bit ),
> > + ARCH_DESC_DEFINE(s390, s390,
> > 32bit ),
> > + ARCH_DESC_DEFINE(s390x,
> > s390x, 64bit ),
> > + ARCH_DESC_DEFINE(hppa, hppa,
> > 32bit ),
> > + ARCH_DESC_DEFINE(parisc, hppa,
> > 32bit ),
> > + ARCH_DESC_DEFINE(sh, sh,
> > 32bit ),
> > + ARCH_DESC_DEFINE(sh64, sh64,
> > 64bit ),
> > + ARCH_DESC_DEFINE(x86, x86,
> > 32bit ),
> > + ARCH_DESC_DEFINE(i386, x86,
> > 32bit ),
> > + ARCH_DESC_DEFINE(i486, x86,
> > 32bit ),
> > + ARCH_DESC_DEFINE(i586, x86,
> > 32bit ),
> > + ARCH_DESC_DEFINE(i686, x86,
> > 32bit ),
> > + ARCH_DESC_DEFINE(x86_64, x86_64,
> > 64bit ),
> > + ARCH_DESC_DEFINE(x86_64, x86_64,
> > 32bit ),
> > + ARCH_DESC_DEFINE(x86_64, x86_64,
> > x32 ),
> > + ARCH_DESC_DEFINE(amd64,
> > x86_64, 64bit ),
> > + ARCH_DESC_DEFINE(cris, cris,
> > 32bit ),
> > + ARCH_DESC_DEFINE(crisv10, cris,
> > 32bit ),
> > + ARCH_DESC_DEFINE(crisv32, crisv32,
> > 32bit ),
> > + ARCH_DESC_DEFINE(tile, tile,
> > 64bit ),
> > + ARCH_DESC_DEFINE(tile, tile,
> > 32bit ),
> > + ARCH_DESC_DEFINE(microblaze, microblaze,
> > 32bit ),
> > + ARCH_DESC_DEFINE(nios2,
> > nios2, 32bit ),
> > + ARCH_DESC_DEFINE(openrisc, openrisc,
> > 32bit ),
> > + ARCH_DESC_DEFINE(xtensa, xtensa,
> > 32bit ),
> > + ARCH_DESC_DEFINE(riscv,
> > riscv, 64bit ),
> > + ARCH_DESC_DEFINE(riscv,
> > riscv, 32bit ) +};
> > +
> > +/* To make architectures array usable for dispatchers.c */
> > +const int architectures_size = ARRAY_SIZE(architectures);
> > +
> > +#undef ARCH_DESC_DEFINE
> > +
> > +struct arch_service *
> > +al_create(unsigned int capacity)
> > +{
> > + struct arch_service *as = NULL;
> > +
> > + if (!capacity)
> > + return NULL;
> > + as = xcalloc(sizeof(*as), 1);
> > + as->arch_list = xcalloc(sizeof(*(as->arch_list)),
> > capacity);
> > + as->flag = xcalloc(sizeof(*(as->flag)), capacity);
> > + as->capacity = capacity;
> > + as->next_free = 0;
> > + return as;
> > +}
> > +
> > +int
> > +al_push(struct arch_service *m, struct arch_descriptor *element)
> > +{
> > + if (m->next_free >= m->capacity)
> > + return -1;
> > + m->arch_list[m->next_free] = element;
> > + m->flag[m->next_free] = AD_FLAG_EMPTY;
> > + m->next_free++;
> > + return 0;
> > +}
> > +
> > +static inline int
> > +al_is_index_ok(struct arch_service *m, unsigned index) {
> Opening brace should be on a separate line.
>
> > + if (index >= m->next_free)
> > + return -1;
> > + return 0;
> > +}
> > +
> > +int
> > +al_set_flag(struct arch_service *m, unsigned index, int flag)
> > +{
> > + if (al_is_index_ok(m, index) == 0) {
> > + m->flag[index] = flag;
> > + return 0;
> > + }
> > + return -1;
> > +}
> > +
> > +struct arch_descriptor *
> > +al_get(struct arch_service *m, unsigned index)
> > +{
> > + if (al_is_index_ok(m, index) != 0)
> > + return NULL;
> > + return m->arch_list[index];
> > +}
> > +
> > +unsigned int
> > +al_size(struct arch_service *m)
> > +{
> > + return m->next_free;
> > +}
> > +
> > +unsigned int
> > +al_base_size(struct arch_service *m)
> > +{
> > + int arch_size = al_size(m);
> > + int i = 0;
> > + unsigned count = 0;
> > +
> > + for (i = 0; i < arch_size; i++)
> > + if (m->arch_list[i]->arch_num ==
> > + m->arch_list[i]->arch_base_num)
> > + count++;
> > + return count;
> > +}
> > +
> > +void
> > +al_free(struct arch_service *m)
> > +{
> > + free(m->arch_list);
> free(m->flag)?
>
> > + free(m);
> > +}
> > +
> > +enum arch_name_abi
> > +al_arch_num(struct arch_service *m, unsigned index)
> > +{
> > + struct arch_descriptor *elem = al_get(m, index);
> > +
> > + return (elem ? elem->arch_num : ARCH_no_arch);
> > +}
> > +
> > +const char *
> > +al_arch_name(struct arch_service *m, unsigned index)
> > +{
> > + struct arch_descriptor *elem = al_get(m, index);
> > +
> > + return (elem ? elem->arch_name : NULL);
> > +}
> > +
> > +int
> > +al_arch_name_len(struct arch_service *m, unsigned index)
> > +{
> > + struct arch_descriptor *elem = al_get(m, index);
> > +
> > + return (elem ? elem->arch_name_len : -1);
> > +}
> > +
> > +enum arch_name_abi
> > +al_arch_base_num(struct arch_service *m, unsigned index)
> > +{
> > + struct arch_descriptor *elem = al_get(m, index);
> > +
> > + return (elem ? elem->arch_base_num : ARCH_no_arch);
> > +}
> > +
> > +const char *
> > +al_abi_mode(struct arch_service *m, unsigned index)
> > +{
> > + struct arch_descriptor *elem = al_get(m, index);
> > +
> > + return (elem ? elem->abi_mode : NULL);
> > +}
> > +
> > +int
> > +al_abi_mode_len(struct arch_service *m, unsigned index)
> > +{
> > + struct arch_descriptor *elem = al_get(m, index);
> > +
> > + return (elem ? elem->abi_mode_len : -1);
> > +}
> > +
> > +int
> > +al_flag(struct arch_service *m, unsigned index)
> > +{
> > + int status = al_is_index_ok(m, index);
> > +
> > + return (!status ? m->flag[index] : -1);
> > +}
> > +
> > +int
> > +al_syscall_impl(struct arch_service *m, unsigned index)
> > +{
> > + struct arch_descriptor *elem = al_get(m, index);
> > + int i = 0;
> > + int count = 0;
> > +
> > + if (elem == NULL)
> > + return -1;
> > + for (i = 0; i < elem->max_scn; i++) {
> > + if (elem->syscall_list[i].sys_name &&
> > + !(elem->syscall_list[i].sys_flags &
> > + TRACE_INDIRECT_SUBCALL))
> Condition continuation should be indented with 4 spaces.
>
> > + count++;
> > + }
> > + return count;
> > +}
> > +
>
> > +/* This method is purposed to find base arch
> > + NOTE: base arch is the arch, where arch_num is equal to
> > arch_base_num
> > + with default ABI mode */
> > +int
> > +al_find_base_arch(struct arch_service *m, unsigned index)
> > +{
> > + enum arch_name_abi base_arch = ARCH_no_arch;
> > + const char *arch_name = NULL;
> > + int mode = 0;
> > + int i = 0;
> > +
> > + if (al_is_index_ok(m, index) != 0)
> > + return -1;
> > + /* Is input arch ABI mode? */
> > + if (al_arch_base_num(m, index) == al_arch_num(m, index))
> > + mode = 1;
> > + /* Search base arch */
> > + base_arch = al_arch_base_num(m, index);
> > + arch_name = al_arch_name(m, index);
> > + for (i = index; i >= 0; i--) {
> > + if (!mode && (al_arch_num(m, i) != base_arch))
> > + continue;
> > + else {
> > + if (!mode)
> > + arch_name = al_arch_name(m, i);
> > + mode = 1;
> > + }
> > + if (mode && !strcmp(arch_name, al_arch_name(m, i)))
> > + continue;
> > + break;
> > + }
> > + return i + 1;
> > +}
> > +
> > +/* This method is purposed to count the supported ABI modes for
> > the given
> > + arch */
> > +int
> > +al_get_abi_modes(struct arch_service *m, unsigned index)
> > +{
> > + const char *arch_name = al_arch_name(m, index);
> > + int arch_size = al_size(m);
> > + int i = 0;
> > + int abi_count = 0;
> > +
> > + if (!arch_name)
> > + return -1;
> > + index = al_find_base_arch(m, index);
> > + for (i = index; i < arch_size; i++) {
> > + if (strcmp(arch_name, al_arch_name(m, i)) == 0) {
> > + abi_count++;
> > + continue;
> > + }
> > + break;
> > + }
> > + return abi_count;
> > +}
> > +
> > +/* If index is related to the first definition of arch in
> > arch_list -> 0 */ +int
> > +al_is_arch_source(struct arch_service *m, unsigned index)
> > +{
> > + int abi_modes = 0;
> > + unsigned base_index = 0;
> > +
> > + if (al_arch_num(m, index) != al_arch_base_num(m, index) ||
> > + al_arch_num(m, index) == ARCH_no_arch)
> > + return -1;
> > + base_index = al_find_base_arch(m, index);
> > + abi_modes = al_get_abi_modes(m, index);
> > + if ((index >= base_index) && (index < base_index +
> > abi_modes))
> > + return 0;
> > + return -1;
> > +}
> > +
> > +enum impl_type
> > +al_ipc_syscall(struct arch_service *m, unsigned index)
> > +{
> > + struct arch_descriptor *elem = al_get(m, index);
> > + int i;
> > + enum impl_type impl_buf = IMPL_int;
> > +
> > + for (i = 0; i < elem->max_scn; i++) {
> > + if (elem->syscall_list[i].sys_name == NULL)
> > + continue;
> > + /* It is enough to find just semop sybcall */
> > + if (!strcmp(elem->syscall_list[i].sys_name,
> > "semop")) {
> > + if (!(elem->syscall_list[i].sys_flags &
> > + TRACE_INDIRECT_SUBCALL))
> > + impl_buf = IMPL_ext;
> > + else if (impl_buf == IMPL_ext)
> > + impl_buf = IMPL_int_ext;
> > + else
> > + impl_buf = IMPL_int;
> > + }
> > + }
> > + return impl_buf;
> > +}
> > +
> > +enum impl_type
> > +al_sck_syscall(struct arch_service *m, unsigned index)
> > +{
> > + struct arch_descriptor *elem = al_get(m, index);
> > + int i;
> > + enum impl_type impl_buf = IMPL_int;
> > +
> > + for (i = 0; i < elem->max_scn; i++) {
> > + if (elem->syscall_list[i].sys_name == NULL)
> > + continue;
> > + /* It is enough to find just socket sybcall */
> > + if (!strcmp(elem->syscall_list[i].sys_name,
> > "socket")) {
> > + if (!(elem->syscall_list[i].sys_flags &
> > + TRACE_INDIRECT_SUBCALL))
> > + impl_buf = IMPL_ext;
> > + else if (impl_buf == IMPL_ext)
> > + impl_buf = IMPL_int_ext;
> > + else
> > + impl_buf = IMPL_int;
> > + }
> > + }
> > + return impl_buf;
> > +}
> All this information can be generated statically by some build-time
> script.
>
> > +
> > +int al_find_arch(struct arch_service *m, enum arch_name_abi a_type)
> > +{
> > + int arch_size = al_size(m);
> > + int i;
> > +
> > + for (i = 0; i < arch_size; i++)
> > + if (al_arch_num(m, i) == a_type)
> > + return i;
> > + return -1;
> > +}
> > +
> > +/* This method is purposed to find next one name of the same
> > architecture.
> > + For instance, x86_64 = amd64 */
> > +int
> > +al_next_arch_name(struct arch_service *m, unsigned index)
> > +{
> > + static int next_arch = -1;
> > + int i = 0;
> > + int arch_size = al_size(m);
> > +
> > + if (next_arch == -1)
> > + next_arch = index;
> > + else
> > + next_arch++;
> > + if (al_arch_num(m, index) != al_arch_base_num(m, index) ||
> > + al_arch_num(m, index) == ARCH_no_arch)
> > + return -1;
> > + for (i = next_arch; i < arch_size; i++) {
> > + next_arch = -1;
> > + if (strcmp(al_arch_name(m, index), al_arch_name(m,
> > i)) == 0)
> > + continue;
> > + if (al_arch_base_num(m, index) ==
> > al_arch_base_num(m, i)) {
> > + next_arch = i;
> > + break;
> > + }
> > + break;
> > + }
> > + if (next_arch >= arch_size)
> > + next_arch = -1;
> > + return next_arch;
> > +}
> > +
> > +void
> > +al_dump(struct arch_service *m)
> > +{
> > + const char *title[] = {
> static
>
> > + "N",
> > + "Architecture name",
> > + "ABI mode",
> > + /* Implemented syscalls */
> > + "IMPL syscalls",
> > + /* IPC implementation */
> > + "IPC IMPL",
> > + /* SOCKET implementation */
> > + "SOCKET IMPL"
> > + };
> > + int title_len[] = {
> > + 0,
> > + strlen(title[1]),
> > + strlen(title[2]),
> > + strlen(title[3]),
> > + strlen(title[4]),
> > + strlen(title[5]),
> > + };
> > + const char *impl_st[] = {
> static
>
> > + "external",
> > + "internal",
> > + "int/ext"
> > + };
> > + int i = 0;
> > + int lbase_arch = 0;
> > + int temp_len = 0;
> > + int arch_size = al_size(m);
> > + int arch_base_size = al_base_size(m);
> > + int N = 0;
> > + int next_name = 0;
> > + char *arch_name_buf;
> > +
> > + /* Calculate length of the column with the number of
> > architectures */
> > + for (i = 1; arch_base_size/i != 0; i *= 10)
> > + title_len[0]++;
> > + for (i = 0; i < arch_size; i++) {
> > + /* Calculate length of the column with the
> > + architectures name */
> > + if (al_is_arch_source(m, i) == -1)
> > + continue;
> > + lbase_arch = al_find_base_arch(m, i);
> > + temp_len = al_arch_name_len(m, lbase_arch);
> > + while ((next_name = al_next_arch_name(m,
> > lbase_arch)) != -1) {
> > + temp_len += al_arch_name_len(m, next_name);
> > + /* To take into account delim symbol */
> > + temp_len++;
> > + }
> > + if (temp_len > title_len[1])
> > + title_len[1] = temp_len;
> > + /* Calculate length of the column with the ABI
> > mode */
> > + if (al_abi_mode_len(m, i) > title_len[2])
> > + title_len[2] = al_abi_mode_len(m, i);
> > + }
> > +
> > + arch_name_buf = xcalloc(title_len[1],
> > sizeof(*arch_name_buf));
> > + /* Output title */
> > + printf("| %*s | %*s | %*s | %*s | %*s | %*s |\n",
> > + title_len[0], title[0], title_len[1], title[1],
> > + title_len[2], title[2], title_len[3], title[3],
> > + title_len[4], title[4], title_len[5], title[5]);
> > + /* Output architectures */
> > + for (i = 0; i < arch_size; i++) {
> > + if ((al_is_arch_source(m, i) == -1) ||
> > + !(al_flag(m, i) & AD_FLAG_PRINT))
> > + continue;
> > + printf("| %*u | ", title_len[0], N + 1);
> > + /* Put all the same arch back together */
> > + strcat(arch_name_buf, al_arch_name(m, i));
> > + lbase_arch = al_find_base_arch(m, i);
> > + while ((next_name = al_next_arch_name(m,
> > lbase_arch)) != -1) {
> > + strcat(arch_name_buf, "/");
> > + strcat(arch_name_buf, al_arch_name(m,
> > next_name));
> > + }
> > + printf("%*s | ", title_len[1], arch_name_buf);
> > + printf("%*s | ", title_len[2], al_abi_mode(m, i));
> > + printf("%*d | ", title_len[3], al_syscall_impl(m,
> > i));
> > + printf("%*s | ", title_len[4],
> > impl_st[al_ipc_syscall(m, i)]);
> > + printf("%*s |\n", title_len[5],
> > impl_st[al_sck_syscall(m, i)]);
> > + N++;
> > + memset(arch_name_buf, 0, title_len[1]);
> > + }
> > + free(arch_name_buf);
> > +}
> > diff --git a/tools/asinfo/arch_interface.h
> > b/tools/asinfo/arch_interface.h new file mode 100644
> > index 00000000..052e4716
> > --- /dev/null
> > +++ b/tools/asinfo/arch_interface.h
> > @@ -0,0 +1,185 @@
> > +/*
> > + * The arch_interface.h is purposed to interact with the basic
> > data structure
> > + * based on arch_descriptor struct. Mainly this set of methods are
> > used by
> > + * arch_dispatcher.
> > + *
> > + * Copyright (c) 2017 Edgar A. Kaziakhmedov
> > <edgar.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 "sysent.h"
> > +
> > +/* Type implementaion of syscall, internal means as a subcall,
> > + external means a separate syscall, this enum is purposed for
> > + well-known ipc and socket subcall group */
> > +enum impl_type {
> > + IMPL_ext,
> > + IMPL_int,
> > + IMPL_int_ext
> > +};
> > +
> > +/* Names of architectures
> > + * arch_name_abi format name_arch = ARCH_ +
> > kernel_kernel/other_name +
> > + abi_mode */
> > +enum arch_name_abi {
> > + ARCH_blackfin_32bit,
> > + ARCH_ia64_64bit,
> > + ARCH_m68k_32bit,
> > + ARCH_sparc64_64bit,
> > + ARCH_sparc64_32bit,
> > + ARCH_sparc_32bit,
> > + ARCH_metag_32bit,
> > + ARCH_mips_o32,
> > + ARCH_mips_n32,
> > + ARCH_mips_n64,
> > + ARCH_alpha_64bit,
> > + ARCH_ppc_32bit,
> > + ARCH_ppc64_64bit,
> > + ARCH_ppc64_32bit,
> > + ARCH_arm_oabi,
> > + ARCH_arm_eabi,
> > + ARCH_aarch64_64bit,
> > + ARCH_aarch64_32bit,
> > + ARCH_avr32_32bit,
> > + ARCH_arc_32bit,
> > + ARCH_s390_32bit,
> > + ARCH_s390x_64bit,
> > + ARCH_hppa_32bit,
> > + ARCH_parisc_32bit,
> > + ARCH_sh_32bit,
> > + ARCH_sh64_64bit,
> > + ARCH_x86_32bit,
> > + ARCH_i386_32bit,
> > + ARCH_i486_32bit,
> > + ARCH_i586_32bit,
> > + ARCH_i686_32bit,
> > + ARCH_x86_64_64bit,
> > + ARCH_x86_64_32bit,
> > + ARCH_x86_64_x32,
> > + ARCH_amd64_64bit,
> > + ARCH_cris_32bit,
> > + ARCH_crisv10_32bit,
> > + ARCH_crisv32_32bit,
> > + ARCH_tile_64bit,
> > + ARCH_tile_32bit,
> > + ARCH_microblaze_32bit,
> > + ARCH_nios2_32bit,
> > + ARCH_openrisc_32bit,
> > + ARCH_xtensa_32bit,
> > + ARCH_riscv_64bit,
> > + ARCH_riscv_32bit,
> > + ARCH_no_arch
> > +};
> > +
> > +struct arch_descriptor {
> > + enum arch_name_abi arch_num;
> > + const char *arch_name;
> > + const int arch_name_len;
> > + enum arch_name_abi arch_base_num;
> > + const char *abi_mode;
> > + const int abi_mode_len;
> > + const int max_scn;
> > + struct_sysent *syscall_list;
> > + /* In the most cases these fields are purposed to store
> > specific for
> > + given arch constants, for instance,
> > ARM_FIRST_SHUFFLED_SYSCALL */
> > + const int *user_num1;
> > + const int *user_num2;
> > +};
> > +
> > +#define AD_FLAG_EMPTY 0
> > +/* Actually, this flag is purposed to hide some abi modes while
> > printing in
> > + one arch group
> > + NOTE: arch group means base arch name + others */
> > +#define AD_FLAG_PRINT 1
> > +
> > +/* To provide push-back interface with arch_list */
> > +struct arch_service {
> > + /* immutable field */
> > + struct arch_descriptor **arch_list;
> > + /* User flags for each arch_descriptor */
> > + int *flag;
> > + unsigned capacity;
> > + unsigned next_free;
> > +};
> > +
> > +#define ARCH_LIST_DEFINE(name) \
> > + struct arch_service *(name)
> > +
> > +/* Push-back interface is purposed to simplify interaction with
> > + arch_service struct
> > + NOTE: al - architecture list */
> > +
> > +/* base methods */
> > +struct arch_service *al_create(unsigned int capacity);
> > +
> > +int al_push(struct arch_service *m, struct arch_descriptor
> > *element); +
> > +int al_set_flag(struct arch_service *m, unsigned index, int flag);
> > +
> > +struct arch_descriptor *al_get(struct arch_service *m, unsigned
> > index); +
> > +unsigned int al_size(struct arch_service *m);
> > +
> > +unsigned int al_base_size(struct arch_service *m);
> > +
> > +void al_free(struct arch_service *m);
> > +
> > +/* methods returning fields with error check */
> > +enum arch_name_abi al_arch_num(struct arch_service *m, unsigned
> > index); +
> > +const char *al_arch_name(struct arch_service *m, unsigned index);
> > +
> > +int al_arch_name_len(struct arch_service *m, unsigned index);
> > +
> > +enum arch_name_abi al_arch_base_num(struct arch_service *m,
> > unsigned index); +
> > +const char *al_abi_mode(struct arch_service *m, unsigned index);
> > +
> > +int al_abi_mode_len(struct arch_service *m, unsigned index);
> > +
> > +int al_flag(struct arch_service *m, unsigned index);
> > +
> > +/* calculating methods */
> > +int al_syscall_impl(struct arch_service *m, unsigned index);
> > +
> > +int al_find_base_arch(struct arch_service *m, unsigned index);
> > +
> > +int al_get_abi_modes(struct arch_service *m, unsigned index);
> > +
> > +int al_is_arch_source(struct arch_service *m, unsigned index);
> > +
> > +enum impl_type al_ipc_syscall(struct arch_service *m, unsigned
> > index); +
> > +enum impl_type al_sck_syscall(struct arch_service *m, unsigned
> > index); +
> > +int al_find_arch(struct arch_service *m, enum arch_name_abi
> > a_type); +
> > +int al_next_arch_name(struct arch_service *m, unsigned index);
> > +
> > +void al_dump(struct arch_service *m);
> > +
> > +#endif /* !ASINFO_ARCH_INTERFACE */
> > diff --git a/tools/asinfo/asinfo.1 b/tools/asinfo/asinfo.1
> > new file mode 100644
> > index 00000000..e69de29b
> > diff --git a/tools/asinfo/asinfo.c b/tools/asinfo/asinfo.c
> > new file mode 100644
> > index 00000000..a3ad9933
> > --- /dev/null
> > +++ b/tools/asinfo/asinfo.c
> > @@ -0,0 +1,245 @@
> > +/*
> > + * The asinfo main source. The asinfo tool is purposed to operate
> > + * with system calls and provide information about it.
> > + *
> > + * Copyright (c) 2017 Edgar A. Kaziakhmedov
> > <edgar.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 <limits.h>
> > +#include <stdarg.h>
> > +#include <stdbool.h>
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +
> > +#include "arch_interface.h"
> > +#include "dispatchers.h"
> > +#include "error_prints.h"
> > +#include "macros.h"
> > +#include "request_msgs.h"
> > +#include "syscall_interface.h"
> > +#include "xmalloc.h"
> > +
> > +#ifndef HAVE_PROGRAM_INVOCATION_NAME
> > +char *program_invocation_name;
> > +#endif
> > +
> > +static void
> > +usage(void)
> > +{
> > + printf("\
> > +usage: asinfo (--set-arch arch | --get-arch | --list-arch)\n\
> > + [--set-abi abi | --get-abi | --list-abi]\n\
> > + or: asinfo [(--set-arch arch | --get-arch) [--set-abi abi |
> > --get-abi]]\n\
> > + (--get-sysc num | name) | (--get-nargs num | name)\n\
> > +\n\
> > +Architecture:\n\
> > + --set-arch arch use architecture ARCH for further operations\n\
> > + --get-arch use architecture returned by uname for further
> > operations\n\
> > + --list-arch print out all architectures supported by
> > strace\n\
> > + (combined use list-arch and any ABI option is
> > permitted)\n\ +\n\
> > +ABI:\n\
> > + --set-abi abi use application binary interface ABI for
> > further operations\n\
> > + --get-arch use ABI mode used at compile time for further
> > operations\n\
> --get-abi?
>
> > + --list-arch print out all ABIs for specified
> > architecture\n\
> --list-abi?
>
> > +\n\
> > +System call:\n\
> > + --get-sysc num print name of system call with the NUM number\n\
> > + --get-sysc name print number of all system calls with NAME
> > substring\n\
> > + --get-nargs num get number of arguments of system call with the
> > NUM number\n\
> > + --get-nargs name get number of arguments of system calls with
> > NAME substring\n\ +\n\
> > +Miscellaneous:\n\
> > + -h print help message\n");
> > + exit(0);
> You can also format it as
>
> printf(
> "usage: asinfo (--set-arch arch | --get-arch |
> --list-arch)\n" " [--set-abi abi | --get-abi |
> --list-abi]\n" " or: asinfo [(--set-arch arch | --get-arch)
> [--set-abi abi | --get-abi]]\n" " (--get-sysc num |
> name) | (--get-nargs num | name)\n" ...
>
> without breaking indentation. Also, since you have no arguments to
> format, you can use puts() instead.
>
> > +}
> > +
> > +void
> > +die(void)
> > +{
> > + exit(1);
> > +}
> > +
> > +static int
> > +is_more1bit(unsigned int num)
> > +{
> > + return !(num & (num - 1));
> > +}
> > +
> > +static unsigned
> > +strpar2req(char *option)
> > +{
> > + /* Convertion table to store string with options */
> > + const char *options[] = {
> static
>
> > + [SD_REQ_GET_SYSC_BIT] = "--get-sysc",
> > + [SD_REQ_GET_NARGS_BIT] = "--get-nargs",
> > + [SD_REQ_GET_LIST_BIT] = "--list-sysc",
> > + [AD_REQ_SET_ARCH_BIT] = "--set-arch",
> > + [AD_REQ_GET_ARCH_BIT] = "--get-arch",
> > + [AD_REQ_LIST_ARCH_BIT] = "--list-arch",
> > + [ABD_REQ_SET_ABI_BIT] = "--set-abi",
> > + [ABD_REQ_GET_ABI_BIT] = "--get-abi",
> > + [ABD_REQ_LIST_ABI_BIT] = "--list-abi",
> > + [SERV_REQ_HELP_BIT] = "-h",
> > + };
> > + unsigned i;
> > +
> > + for (i = 0; i < ARRAY_SIZE(options); i++) {
> > + if (options[i] && strcmp(option, options[i]) == 0)
> > + return i;
> > + }
> > + return SERV_REQ_ERROR_BIT;
> > +}
> > +
> > +static unsigned
> > +command_dispatcher(int argc, char *argv[], char *args[])
> > +{
> > + int i;
> > + unsigned final_req = 0;
> > + unsigned temp_req = 0;
> > + unsigned non_req_arg = AD_REQ_GET_ARCH |
> > AD_REQ_LIST_ARCH |
> > + ABD_REQ_GET_ABI |
> > ABD_REQ_LIST_ABI |
> > + SD_REQ_GET_LIST;
> > +
> > + if (!program_invocation_name || !*program_invocation_name)
> > {
> > + static char name[] = "asinfo";
> > + program_invocation_name =
> > + (argv[0] && *argv[0]) ? argv[0] : name;
> > + }
> > +
> > + /* Try to find help option firstly */
> "first"
>
> > + for (i = 1; i < argc; i++) {
> > + if (strpar2req(argv[i]) == SERV_REQ_HELP_BIT)
> > + usage();
> > + }
> > + /* For now, is is necessary to convert string parameter to
> > number of
> > + request and make basic check */
> > + for (i = 1; i < argc; i++) {
> > + if ((temp_req = strpar2req(argv[i])) ==
> > SERV_REQ_ERROR_BIT)
> > + error_msg_and_help("unrecognized option
> > '%s'",
> > + argv[i]);
> > + if (final_req & 1 << temp_req)
> > + error_msg_and_help("parameter '%s' has
> > been used "
> > + "more than once",
> > argv[i]);
> > + if (!((1 << temp_req) & non_req_arg) &&
> > + (i + 1 >= argc || strlen(argv[i + 1]) == 0 ||
> > + strpar2req(argv[i + 1]) !=
> > SERV_REQ_ERROR_BIT))
> > + error_msg_and_help("parameter '%s'
> > requires "
> > + "argument", argv[i]);
> > + final_req |= 1 << temp_req;
> > + if (!((1 << temp_req) & non_req_arg)) {
> > + args[temp_req] = argv[i + 1];
> > + i++;
> > + }
> > + }
> > + /* Secondly, final_req should be logically checked */
> > + /* More than one option from one request group couldn't be
> > set */
> > + if ((is_more1bit(final_req & SD_REQ_MASK) == 0) ||
> > + (is_more1bit(final_req & AD_REQ_MASK) == 0) ||
> > + (is_more1bit(final_req & ABD_REQ_MASK) == 0) ||
> > + (is_more1bit(final_req & FD_REQ_MASK) == 0))
> > + error_msg_and_help("exclusive parameters");
> > + /* Check on mutually exclusive options chain */
> > + /* If at least one syscall option has been typed, therefore
> > + arch_options couldn't be list-arch and
> > + abi_option couldn't be list-abi */
> > + if ((final_req & SD_REQ_MASK) &&
> > + (((final_req & AD_REQ_MASK) && (final_req &
> > AD_REQ_LIST_ARCH)) ||
> > + ((final_req & ABD_REQ_MASK) && (final_req &
> > ABD_REQ_LIST_ABI))))
> > + error_msg_and_help("wrong parameters");
> > +
> > + /* list-arch couldn't be used with any abi options */
> > + if ((final_req & AD_REQ_LIST_ARCH) &&
> > + (final_req & ABD_REQ_MASK))
> > + error_msg_and_help("--list-arch cannot be used
> > with any "
> > + "ABI parameters");
> > +
> > + /* ABI requests could be used just in a combination with
> > arch
> > + requests */
> > + if ((final_req & ABD_REQ_MASK) &&
> > + !(final_req & AD_REQ_MASK))
> > + error_msg_and_help("ABI parameters could be used
> > only with "
> > + "architecture parameter");
> > + return final_req;
> > +}
> This function is very opaque.
>
> > +
> > +static char *
> > +seek_sc_arg(char **input_args)
> > +{
> > + int i;
> > +
> > + for (i = SD_REQ_GET_SYSC_BIT; i < SYSCALL_REQ_BIT_LAST;
> > i++)
> > + if (input_args[i] != NULL)
> > + return input_args[i];
> > + return NULL;
> > +}
> > +
> > +int
> > +main(int argc, char *argv[])
> > +{
> > + ARCH_LIST_DEFINE(arch_list);
> > + SYSCALL_LIST_DEFINE(sc_list);
> > + /* This array is purposed to store arguments for options
> > in the
> > + most convenient way */
> > + char **input_args = xcalloc(sizeof(*input_args),
> > REQ_LAST_BIT);
> > + unsigned reqs;
> > + int ret = 0;
> > +
> > + /* command_dispatcher turn */
> > + reqs = command_dispatcher(argc, argv, input_args);
> > + if (reqs == 0)
> > + error_msg_and_help("must have OPTIONS");
> > +
> > + /* arch_dispatcher turn */
> > + arch_list = arch_dispatcher(reqs,
> > input_args[AD_REQ_SET_ARCH_BIT]);
> > + if (arch_list == NULL)
> > + perror_msg_and_die("unrecognized architecture
> > '%s'",
> > +
> > input_args[AD_REQ_SET_ARCH_BIT]);
> > + /* abi_dispatcher turn */
> > + ret = abi_dispatcher(arch_list, reqs,
> > input_args[ABD_REQ_SET_ABI_BIT]);
> > + if (ret != 0)
> > + perror_msg_and_die("unrecognized ABI mode '%s' for
> > a given "
> > + "architecture",
> > +
> > input_args[ABD_REQ_SET_ABI_BIT]);
> > + if (ret != 0 && !input_args[ABD_REQ_SET_ABI_BIT])
> > + perror_msg_and_die("current architecture isn't
> > supported");
> > + /* syscall_dispatcher turn */
> > + sc_list = syscall_dispatcher(arch_list, reqs,
> > seek_sc_arg(input_args));
> > + if (ss_error(sc_list))
> > + perror_msg_and_die("%s", ss_get_serror(sc_list));
> > + /* If we want to get info about only architectures thus we
> > print out
> > + architectures, otherwise system calls */
> > + if (!(reqs & SD_REQ_MASK))
> > + al_dump(arch_list);
> > + else
> > + ss_dump(sc_list);
> > + return 0;
> > +}
> > diff --git a/tools/asinfo/dispatchers.c b/tools/asinfo/dispatchers.c
> > new file mode 100644
> > index 00000000..11122f09
> > --- /dev/null
> > +++ b/tools/asinfo/dispatchers.c
> > @@ -0,0 +1,253 @@
> > +/*
> > + * Copyright (c) 2017 Edgar A. Kaziakhmedov
> > <edgar.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"
> > +
> > +extern struct arch_descriptor architectures[];
> const
>
> > +extern const int architectures_size;
> > +
> > +static int
> > +lookup_arch(struct arch_service **arch, char *arch_str)
> > +{
> > + ARCH_LIST_DEFINE(a_full_list) =
> > al_create(architectures_size);
> > + int arch_match = -1;
> > + char *match_pointer = NULL;
> > + int al_size_ret = 0;
> > + int al_size_full = 0;
> > + int i;
> > +
> > + if (arch_str == NULL)
> > + return -1;
> > + /* Firstly, generate full list of arch to simplify further
> > work */
> > + for (i = 0; i < architectures_size; i++)
> > + al_push(a_full_list, &architectures[i]);
> > + al_size_full = al_size(a_full_list);
> > + /* Here we find the best match for arch_str in
> > architecture list.
> > + Best match means here that we have to find the longest
> > name of
> > + architecture in a_full_list with arch_str substring,
> > beginning
> > + from the first letter */
> sh63/sh64
>
> > + for (i = 0; i < al_size_full; i++) {
> > + match_pointer = strstr(arch_str,
> > al_arch_name(a_full_list, i));
> > + if (match_pointer == NULL || match_pointer !=
> > arch_str)
> > + continue;
> > + if (arch_match == -1 ||
> > + al_arch_name_len(a_full_list, i) >
> > + al_arch_name_len(a_full_list, arch_match))
> > + arch_match = i;
> > + }
> > + if (arch_match == -1)
> > + goto fail;
> > + /* Now we find all ABI modes related to the architecture
> > and its other
> > + names */
> > + /* Firstly, find the base arch */
> "First"
>
> > + arch_match = al_find_base_arch(a_full_list, arch_match);
> > + /* Secondly, it is necessary to calculate size of final
> > arch_list */
> "Second"
>
> > + al_size_ret = al_get_abi_modes(a_full_list, arch_match);
> > + while ((i = al_next_arch_name(a_full_list, arch_match)) !=
> > -1)
> > + al_size_ret++;
> > + if (al_size_ret == 0)
> > + goto fail;
> > + /* Finally, Create arch_list and fill it */
> > + *arch = al_create(al_size_ret);
> > + for (i = arch_match; i < (arch_match + al_size_ret); i++)
> > + al_push(*arch, &architectures[i]);
> > +
> > + free(a_full_list);
> > + return 0;
> > +fail:
> > + free(a_full_list);
> > + return -1;
> > +}
> > +
> > +struct arch_service *
> > +arch_dispatcher(unsigned request_type, char *arch)
> > +{
> > + struct utsname info_uname;
> > + int i;
> > + ARCH_LIST_DEFINE(arch_list) = NULL;
> > +
> > + /* If user don't type any option in ARCH_REQ group, it
> > means
> > + get current arch */
> > + if ((request_type & AD_REQ_GET_ARCH) ||
> > + (!(request_type & AD_REQ_MASK))) {
> > + uname(&info_uname);
> > + if (lookup_arch(&arch_list, info_uname.machine) ==
> > -1)
> > + goto fail;
> > + goto done;
> > + }
> > +
> > + if (request_type & AD_REQ_SET_ARCH) {
> > + if (lookup_arch(&arch_list, arch) == -1)
> > + goto fail;
> > + goto done;
> > + }
> > +
> > + if ((request_type & AD_REQ_LIST_ARCH)) {
> > + arch_list = al_create(architectures_size);
> > + for (i = 0; i < architectures_size; i++) {
> > + al_push(arch_list, &(architectures[i]));
> > + al_set_flag(arch_list, i, AD_FLAG_PRINT);
> > + }
> > + goto done;
> > + }
> > +fail:
> > + arch_list = NULL;
> > +done:
> > + return arch_list;
> > +}
> > +
> > +int
> > +abi_dispatcher(struct arch_service *a_serv, unsigned request_type,
> > char *abi) +{
> > + int i = 0;
> > + enum arch_name_abi arch_num = ARCH_no_arch;
> > + int abi_modes = 0;
> > + int arch_size = 0;
> > + int flag = 0;
> > +
> > + if (a_serv == NULL)
> > + return -1;
> > + arch_size = al_size(a_serv);
> > + abi_modes = al_get_abi_modes(a_serv, 0);
> > + /* The strace package could be compiled as 32bit app on
> > 64bit
> > + architecture, therefore asinfo has to detect it and
> > print out
> > + corresponding personality. Frankly speaking, it is
> > necessary to
> > + detect strace package personality */
> I assume you can obtain this information from config.h.
Yes, what I'm doing, all these definitions are coming from
config.h(__ARM_EABI__ doesn't count)
>
> > + if ((request_type & ABD_REQ_GET_ABI) ||
> > + (!(request_type & ABD_REQ_MASK))) {
> > + arch_num = al_arch_num(a_serv, 0);
> > + switch (arch_num) {
> > + case ARCH_mips_o32:
> > + al_set_flag(a_serv, al_find_arch(a_serv,
> > +#if defined(LINUX_MIPSO32)
> > + ARCH_mips_o32
> > +#elif defined(LINUX_MIPSN32)
> > + ARCH_mips_n32
> > +#else
> > + ARCH_mips_n64
> > +#endif
> > + ), AD_FLAG_PRINT);
> > + break;
> > + case ARCH_arm_oabi:
> > + al_set_flag(a_serv, al_find_arch(a_serv,
> > +#if defined(__ARM_EABI__)
> > + ARCH_arm_eabi
> > +#else
> > + ARCH_arm_oabi
> > +#endif
> > + ), AD_FLAG_PRINT);
> > + break;
> > + case ARCH_aarch64_64bit:
> > + al_set_flag(a_serv, al_find_arch(a_serv,
> > +#if defined(__ARM_EABI__)
> > + ARCH_aarch64_32bit
> > +#else
> > + ARCH_aarch64_64bit
> > +#endif
> > + ), AD_FLAG_PRINT);
> > + break;
> > + case ARCH_x86_64_64bit:
> > + al_set_flag(a_serv, al_find_arch(a_serv,
> > +#if defined(X86_64)
> > + ARCH_x86_64_64bit
> > +#elif defined(X32)
> > + ARCH_x86_64_x32
> > +#else
> > + ARCH_x86_64_32bit
> > +#endif
> > + ), AD_FLAG_PRINT);
> > + break;
> > + case ARCH_tile_64bit:
> > + al_set_flag(a_serv, al_find_arch(a_serv,
> > +#if defined(__tilepro__)
> > + ARCH_tile_32bit
> > +#else
> > + ARCH_tile_64bit
> > +#endif
> > + ), AD_FLAG_PRINT);
> Yet another reason for storing mask of compativle ABIs in arch
> descriptor.
Why? I didn't quite understand. I suppose that it is impossible to
store all info about one arch(with all ABIs) in one arch_descriptor,
because the macros ARCH_DEFINE is not able to include variable number
of sysents as I understand, thus I have to define each ABI mode
separately, don't I?
>
> > + break;
> > + default:
> > + /* Other cases should be printed using
> > default rule:
> > + print main(first) ABI mode + other arch
> > names */
> > + al_set_flag(a_serv, 0, AD_FLAG_PRINT);
> > + for (i = abi_modes; i < arch_size; i++)
> > + al_set_flag(a_serv, i,
> > AD_FLAG_PRINT);
> > + }
> > + goto done;
> > + }
> > +
> > + if (request_type & ABD_REQ_LIST_ABI) {
> > + for (i = 0; i < abi_modes; i++)
> > + al_set_flag(a_serv, i, AD_FLAG_PRINT);
> > + goto done;
> > + }
> > +
> > + if (request_type & ABD_REQ_SET_ABI) {
> > + if (abi == NULL)
> > + goto fail;
> > + for (i = 0; i < abi_modes; i++)
> > + if (strcmp(abi, al_abi_mode(a_serv, i)) ==
> > 0) {
> > + al_set_flag(a_serv, i,
> > AD_FLAG_PRINT);
> > + flag = 1;
> > + }
> > + if (!flag)
> > + goto fail;
> > + }
> > +done:
> > + return 0;
> > +fail:
> > + return -1;
> > +}
> > +
> > +struct syscall_service *
> > +syscall_dispatcher(struct arch_service *arch, int request_type,
> > char *arg) +{
> > + SYSCALL_LIST_DEFINE(syscall_list) = ss_create(arch,
> > request_type); +
> > + if (request_type & SD_REQ_MASK) {
> > + ss_update_sc_num(syscall_list);
> > + ss_mark_matches(syscall_list, arg);
> > + }
> > +
> > + return syscall_list;
> > +}
> > +
> > +
> Applying: asinfo: Introduce static query tool asinfo
> /home/esyr/dev/strace/.git/rebase-apply/patch:1726: new blank line at
> EOF.
> +
> warning: 1 line adds whitespace errors.
>
> > diff --git a/tools/asinfo/dispatchers.h b/tools/asinfo/dispatchers.h
> > new file mode 100644
> > index 00000000..2a62cff0
> > --- /dev/null
> > +++ b/tools/asinfo/dispatchers.h
> > @@ -0,0 +1,48 @@
> > +/*
> > + * The dispatchers.h contains all necessary functions to perform
> > main
> > + * work in the asinfo tool.
> > + *
> > + * Copyright (c) 2017 Edgar A. Kaziakhmedov
> > <edgar.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 *abi);
> > +
> > +/* The last stage of main filtering */
> > +struct syscall_service *syscall_dispatcher(struct arch_service
> > *arch,
> > + int request_type, char
> > *arg); +
> > +#endif /* !STRACE_ASINFO_COM_SCALLENT */
> > diff --git a/tools/asinfo/request_msgs.h
> > b/tools/asinfo/request_msgs.h new file mode 100644
> > index 00000000..ea9c1337
> > --- /dev/null
> > +++ b/tools/asinfo/request_msgs.h
> > @@ -0,0 +1,100 @@
> > +/*
> > + * The request_msgs are messages used by dispatchers in asinfo
> > tool to
> > + * operate with static data base.
> > + *
> > + * Copyright (c) 2017 Edgar A. Kaziakhmedov
> > <edgar.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, and filter_dispatcher,
> > + * which, in turn, could be combined
> > + */
> > +enum syscall_req_bit {
> > + SD_REQ_GET_SYSC_BIT,
> > + SD_REQ_GET_NARGS_BIT,
> > + SD_REQ_GET_LIST_BIT,
> > +
> > + SYSCALL_REQ_BIT_LAST
> > +};
> > +
> > +enum arch_req_bit {
> > + AD_REQ_SET_ARCH_BIT = SYSCALL_REQ_BIT_LAST,
> > + AD_REQ_GET_ARCH_BIT,
> > + AD_REQ_LIST_ARCH_BIT,
> > +
> > + ARCH_REQ_BIT_LAST
> > +};
> > +
> > +enum abi_req_bit {
> > + ABD_REQ_SET_ABI_BIT = ARCH_REQ_BIT_LAST,
> > + ABD_REQ_GET_ABI_BIT,
> > + ABD_REQ_LIST_ABI_BIT,
> > +
> > + ABD_REQ_BIT_LAST
> > +};
> > +
> > +enum fd_req_bit {
> > + FD_REQ_SET_BASE_FILTER_BIT = ABD_REQ_BIT_LAST,
> > +
> > + FD_REQ_BIT_LAST
> > +};
> > +
> > +enum serv_req_bit {
> > + SERV_REQ_HELP_BIT = FD_REQ_BIT_LAST,
> > + SERV_REQ_ERROR_BIT,
> > +
> > + SERV_REQ_BIT_LAST
> > +};
> > +
> > +#define ENUM_FLAG(name) name = 1 << name##_BIT
> > +enum req_type {
> > + ENUM_FLAG(SD_REQ_GET_SYSC),
> > + ENUM_FLAG(SD_REQ_GET_NARGS),
> > + ENUM_FLAG(SD_REQ_GET_LIST),
> > + ENUM_FLAG(AD_REQ_SET_ARCH),
> > + ENUM_FLAG(AD_REQ_GET_ARCH),
> > + ENUM_FLAG(AD_REQ_LIST_ARCH),
> > + ENUM_FLAG(ABD_REQ_SET_ABI),
> > + ENUM_FLAG(ABD_REQ_GET_ABI),
> > + ENUM_FLAG(ABD_REQ_LIST_ABI),
> > + ENUM_FLAG(FD_REQ_SET_BASE_FILTER),
> > + ENUM_FLAG(SERV_REQ_HELP),
> > + ENUM_FLAG(SERV_REQ_ERROR)
> > +};
> > +#undef ENUM_FLAG
> > +
> > +#define BITMASK(hi, lo) ((1 << (hi)) - (1 << (lo)))
> > +#define REQ_LAST_BIT SERV_REQ_BIT_LAST
> > +#define SD_REQ_MASK BITMASK(SYSCALL_REQ_BIT_LAST, 0)
> > +#define AD_REQ_MASK BITMASK(ARCH_REQ_BIT_LAST,
> > SYSCALL_REQ_BIT_LAST) +#define ABD_REQ_MASK
> > BITMASK(ABD_REQ_BIT_LAST, ARCH_REQ_BIT_LAST) +#define FD_REQ_MASK
> > BITMASK(FD_REQ_BIT_LAST, ABD_REQ_BIT_LAST) +#define SERV_REQ_MASK
> > BITMASK(SERV_REQ_BIT_LAST, FD_REQ_BIT_LAST) +
> > +#endif /* !STRACE_ASINFO_REQ_MSGS */
> > diff --git a/tools/asinfo/syscall_interface.c
> > b/tools/asinfo/syscall_interface.c new file mode 100644
> > index 00000000..a43ba9e7
> > --- /dev/null
> > +++ b/tools/asinfo/syscall_interface.c
> > @@ -0,0 +1,339 @@
> > +/*
> > + * Copyright (c) 2017 Edgar A. Kaziakhmedov
> > <edgar.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 "syscall_interface.h"
> > +#include "request_msgs.h"
> > +#include "xmalloc.h"
> > +
> > +struct syscall_service *
> > +ss_create(struct arch_service *m, int request_type)
> > +{
> > + int i;
> > + int arch_list_size = al_size(m);
> > + struct arch_descriptor *ad = NULL;
> > + struct syscall_service *ss = NULL;
> > +
> > + /* Function calling syscall_service should make sure,
> > + that there is just one arch with AD_FLAG_PRINT flag */
> > + for (i = 0; i < arch_list_size; i++)
> > + if (al_flag(m, i) & AD_FLAG_PRINT)
> > + ad = al_get(m, i);
> > + ss = xcalloc(sizeof(*ss), 1);
> > + ss->flag = xcalloc(sizeof(*(ss->flag)), ad->max_scn);
> > + ss->real_sys_num = xcalloc(sizeof(*(ss->real_sys_num)),
> > ad->max_scn);
> > + ss->arch = ad;
> > + ss->request_type = request_type;
> > + return ss;
> > +}
> > +
> > +int
> > +ss_flag(struct syscall_service *s, int num)
> > +{
> > + if (num >= s->arch->max_scn)
> > + return -1;
> > + return s->flag[num];
> > +}
> > +
> > +int
> > +ss_set_flag(struct syscall_service *s, int num, int flag)
> > +{
> > + if (num >= s->arch->max_scn)
> > + return -1;
> > + s->flag[num] = flag;
> > + return 0;
> > +}
> > +
> > +enum input_type
> > +ss_it(struct syscall_service *s)
> > +{
> > + return s->it;
> > +}
> > +
> > +void
> > +ss_set_input(struct syscall_service *s, enum input_type it)
> > +{
> > + s->it = it;
> > +}
> > +
> > +int
> > +ss_max_scn(struct syscall_service *s)
> > +{
> > + return s->arch->max_scn;
> > +}
> > +
> > +int
> > +ss_real_num(struct syscall_service *s, int num)
> > +{
> > + if (num >= s->arch->max_scn)
> > + return -1;
> > + return s->real_sys_num[num];
> > +}
> > +
> > +int
> > +ss_set_real_num(struct syscall_service *s, int num, int real_num)
> > +{
> > + if (num >= s->arch->max_scn)
> > + return -1;
> > + s->real_sys_num[num] = real_num;
> > + return 0;
> > +}
> > +
> > +const char *
> > +ss_syscall_name(struct syscall_service *s, int num)
> > +{
> > + return s->arch->syscall_list[num].sys_name;
> > +}
> > +
> > +int
> > +ss_syscall_flag(struct syscall_service *s, int num)
> > +{
> > + return s->arch->syscall_list[num].sys_flags;
> > +}
> > +
> > +unsigned
> > +ss_syscall_nargs(struct syscall_service *s, int num)
> > +{
> > + return s->arch->syscall_list[num].nargs;
> > +}
> > +
> > +int
> > +ss_user_num1(struct syscall_service *s)
> > +{
> > + return *(s->arch->user_num1);
> > +}
> > +
> > +int
> > +ss_user_num2(struct syscall_service *s)
> > +{
> > + return *(s->arch->user_num2);
> > +}
> > +
> > +void
> > +ss_free(struct syscall_service *s)
> > +{
> > + free(s->flag);
> > + free(s);
> > +}
> > +
> > +enum sc_error
> > +ss_error(struct syscall_service *s)
> > +{
> > + return s->last_error;
> > +}
> > +
> > +void
> > +ss_set_error(struct syscall_service *s, enum sc_error se)
> > +{
> > + s->last_error = se;
> > +}
> > +
> > +static const char *serrors[] = {
>
> > +[SE_WRONG_NUMBER] = "wrong syscall number",
> > +[SE_NUMBER_NON_EXIST] = "syscall with that number was not
> > implemented", +[SE_NAME_NON_EXIST] = "syscall with that name
> > doesn't exist"
> Items should be indented.
>
> > +};
> > +
> > +const char *
> > +ss_get_serror(struct syscall_service *s)
> > +{
> > + return serrors[s->last_error];
> > +}
> > +
> > +int
> > +ss_find_num(struct syscall_service *s, int real_num)
> > +{
> > + int i;
> > + int max_scn = ss_max_scn(s);
> > +
> > + for (i = 0; i < max_scn; i++)
> > + if (ss_real_num(s, i) == real_num)
> > + return i;
> > + return -1;
> > +}
> > +
> > +bool
> > +ss_is_syscall_valid(struct syscall_service *s, int num)
> > +{
> > + if ((num >= s->arch->max_scn) || (num < 0))
> > + return 0;
> > + return ss_syscall_name(s, num) &&
> > + !(ss_syscall_flag(s, num) & TRACE_INDIRECT_SUBCALL);
> > +}
> > +
> > +int
> > +ss_mark_matches(struct syscall_service *s, char *arg)
> > +{
> > + int sc_real_number;
> > + int sc_num;
> > + char sym = 0;
> > + char *sc_name = NULL;
> > + int sc_count = 0;
> > + int i = 0;
> > + int max_scn = ss_max_scn(s);
> > +
> > + /* In case of --list-sysc */
> > + if (arg == NULL) {
> > + for (i = 0; i < max_scn; i++)
> > + if (ss_is_syscall_valid(s, i))
> > + ss_set_flag(s, i, SS_FLAG_PRINT);
> > + return 0;
> > + }
> > +
> > + /* Is it a number? */
> > + if ((sscanf(arg, "%d%c", &sc_real_number, &sym) == 0) ||
> > sym != '\0')
> > + sc_name = arg;
> > + else if (sc_real_number < 0) {
> > + ss_set_error(s, SE_WRONG_NUMBER);
> > + return -1;
> > + }
> > +
> > + /* In case of name -> find arg as a substring and mark */
> > + if (sc_name != NULL) {
> > + for (i = 0; i < max_scn; i++)
> > + if (ss_is_syscall_valid(s, i) &&
> > + strstr(ss_syscall_name(s, i),
> > sc_name) != NULL) {
> > + ss_set_flag(s, i, SS_FLAG_PRINT);
> > + sc_count++;
> > + }
> > + if (sc_count == 0) {
> > + ss_set_error(s, SE_NAME_NON_EXIST);
> > + return -1;
> > + }
> > + ss_set_input(s, IT_STRING);
> > + return 0;
> > + }
> > + /* In case of number -> check and mark */
> > + sc_num = ss_find_num(s, sc_real_number);
> > + if (ss_is_syscall_valid(s, sc_num)) {
> > + ss_set_flag(s, sc_num, SS_FLAG_PRINT);
> > + ss_set_input(s, IT_NUMBER);
> > + return 0;
> > + }
> > + ss_set_error(s, SE_NUMBER_NON_EXIST);
> > + return -1;
> > +}
> > +
> > +#ifndef __X32_SYSCALL_BIT
> > +# define __X32_SYSCALL_BIT 0x40000000
> > +#endif
> > +
> > +int
> > +ss_update_sc_num(struct syscall_service *s)
> > +{
> > + int i = 0;
> > + int max_scn = ss_max_scn(s);
> > + for (i = 0; i < max_scn; i++) {
> > + if (!ss_is_syscall_valid(s, i)) {
> > + ss_set_real_num(s, i, -1);
> > + continue;
> > + }
> > + switch (s->arch->arch_num) {
> > + case ARCH_x86_64_x32:
> > + ss_set_real_num(s, i, i +
> > __X32_SYSCALL_BIT);
> > + break;
> > + case ARCH_arm_oabi:
> > + case ARCH_arm_eabi:
> > + case ARCH_aarch64_32bit:
> > + if (i == ss_user_num1(s))
> > + ss_set_real_num(s, i, 0x000ffff0);
> > + if ((i >= ss_user_num1(s) + 1) &&
> > + (i <= ss_user_num1(s) +
> > ss_user_num2(s) + 1))
> > + ss_set_real_num(s, i, i +
> > 0x000f0000 -
> > +
> > ss_user_num1(s) - 1);
> > + if (i < ss_user_num1(s))
> > + ss_set_real_num(s, i, i);
> > + break;
> > + case ARCH_sh64_64bit:
> > + ss_set_real_num(s, i, i & 0xffff);
> > + default:
> > + ss_set_real_num(s, i, i);
> > + }
> > + }
> > + return 0;
> > +}
> > +
> > +void
> > +ss_dump(struct syscall_service *s)
> > +{
> > + const char *title[] = {
> > + "System call name",
> > + "Syscall num",
> > + "Nargs",
> > + };
> > + int title_len[] = {
> > + strlen(title[0]),
> > + strlen(title[1]),
> > + strlen(title[2]),
> > + };
> > + int i;
> > + int max_scn = ss_max_scn(s);
> > + int temp_len = 0;
> > +
> > + /* Update title_len[0] */
> > + for (i = 0; i < max_scn; i++) {
> > + if (!(ss_flag(s, i) & SS_FLAG_PRINT))
> > + continue;
> > + temp_len = strlen(ss_syscall_name(s, i));
> > + if (temp_len > title_len[0])
> > + title_len[0] = temp_len;
> > + }
> > + /* Print title */
> > + if (s->request_type & SD_REQ_GET_LIST)
> > + printf("| %*s | %*s | %*s |\n", title_len[0],
> > title[0],
> > + title_len[1],
> > title[1],
> > + title_len[2],
> > title[2]);
> > + if (s->request_type & SD_REQ_GET_SYSC)
> > + printf("| %*s | %*s |\n", title_len[0], title[0],
> > + title_len[1], title[1]);
> > + if (s->request_type & SD_REQ_GET_NARGS)
> > + printf("| %*s | %*s |\n", title_len[0], title[0],
> > + title_len[2], title[2]);
> > + /* Print out syscall or list of syscalls */
> > + for (i = 0; i < max_scn; i++) {
> > + if (!(ss_flag(s, i) & SS_FLAG_PRINT))
> > + continue;
> > + if (s->request_type & SD_REQ_GET_LIST)
> > + printf("| %*s | %*d | %*u |\n",
> > + title_len[0], ss_syscall_name(s,
> > i),
> > + title_len[1], ss_real_num(s, i),
> > + title_len[2], ss_syscall_nargs(s,
> > i));
> > + if (s->request_type & SD_REQ_GET_SYSC)
> > + printf("| %*s | %*d |\n",
> > + title_len[0], ss_syscall_name(s,
> > i),
> > + title_len[1], ss_real_num(s, i));
> > + if (s->request_type & SD_REQ_GET_NARGS)
> > + printf("| %*s | %*u |\n",
> > + title_len[0], ss_syscall_name(s,
> > i),
> > + title_len[2], ss_syscall_nargs(s,
> > i));
> > + }
> > +}
> > diff --git a/tools/asinfo/syscall_interface.h
> > b/tools/asinfo/syscall_interface.h new file mode 100644
> > index 00000000..a8adf247
> > --- /dev/null
> > +++ b/tools/asinfo/syscall_interface.h
> > @@ -0,0 +1,114 @@
> > +/*
> > + * The syscall_interface.h is purposed to interact with the basic
> > data
> > + * structure based on arch_descriptor struct. Mainly this set of
> > methods are
> > + * used by syscall_dispatcher.
> > + *
> > + * Copyright (c) 2017 Edgar A. Kaziakhmedov
> > <edgar.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"
> > +
> > +#define SS_FLAG_EMPTY 0
> > +#define SS_FLAG_PRINT 1
> > +
> > +enum input_type {
> > + IT_STRING = 1,
> > + IT_NUMBER
> > +};
> > +
> > +enum sc_error {
> > + SE_WRONG_NUMBER = 1,
> > + SE_NUMBER_NON_EXIST,
> > + SE_NAME_NON_EXIST,
> > +};
> > +
> > +struct syscall_service {
> > + struct arch_descriptor *arch;
> > + /* Mutable user flags for each syscall */
> > + int *flag;
> > + int *real_sys_num;
> > + /* To choose the format while dumping */
> > + int request_type;
> > + /* To detect input type */
> > + enum input_type it;
> > + enum sc_error last_error;
> > +};
> > +
> > +#define SYSCALL_LIST_DEFINE(name) \
> > + struct syscall_service *(name)
> > +
> > +/* base methods */
> > +struct syscall_service *ss_create(struct arch_service *m, int
> > request_type); +
> > +int ss_flag(struct syscall_service *s, int num);
> > +
> > +int ss_set_flag(struct syscall_service *s, int num, int flag);
> > +
> > +enum input_type ss_it(struct syscall_service *s);
> > +
> > +void ss_set_input(struct syscall_service *s, enum input_type it);
> > +
> > +int ss_max_scn(struct syscall_service *s);
> > +
> > +int ss_real_num(struct syscall_service *s, int num);
> > +
> > +int ss_set_real_num(struct syscall_service *s, int num, int
> > real_num); +
> > +const char *ss_syscall_name(struct syscall_service *s, int num);
> > +
> > +int ss_syscall_flag(struct syscall_service *s, int num);
> > +
> > +unsigned ss_syscall_nargs(struct syscall_service *s, int num);
> > +
> > +int ss_user_num1(struct syscall_service *s);
> > +
> > +int ss_user_num2(struct syscall_service *s);
> > +
> > +void ss_free(struct syscall_service *s);
> > +
> > +/* error group methods */
> > +enum sc_error ss_error(struct syscall_service *s);
> > +
> > +void ss_set_error(struct syscall_service *s, enum sc_error se);
> > +
> > +const char *ss_get_serror(struct syscall_service *s);
> > +
> > +/* calculating methods */
> > +int ss_find_num(struct syscall_service *s, int real_num);
> > +
> > +bool ss_is_syscall_valid(struct syscall_service *s, int num);
> > +
> > +int ss_mark_matches(struct syscall_service *s, char *arg);
> > +
> > +int ss_update_sc_num(struct syscall_service *s);
> > +
> > +void ss_dump(struct syscall_service *s);
> > +
> > +#endif /* !ASINFO_SYSCALL_INTERFACE */
> > --
> > 2.11.0
>
> So, after playing with tool a little:
> * I miss "bfin" alias for blackfin
> * For some reason, mips assumes o32/n32/n64
> * There's not be/le differentiation (I'm not sure it's needed,
> however, but I think aliases, at least, may be useful, like
> mipsle/mips64le for mips/mips64, respectively)
>
> The features I am missing:
> * How can I select multiple architectures/ABIs? In order to see what
> are the discrepancies in numbering of specific syscall or its
> presence on specific architecture.
> * How can I select syscall classes?
> * (Looking at x32 syscall numbers) some option for hexadecimal output
> could be also useful.
> * Syscall count can be more useful, if it is calculated for the
> generated list of syscalls.
> * Matching different from substring match - what if I want to request
> open syscall specifically? Regex matching for syscall names could
> probably solve any desire in this regard. You can even employ the
> same convention as strace itself uses — no prefix means strict
> match, "%" prefix for syscall groups, "/" prefix for regex match.
> * Information about classes specific syscall belongs to may be also
> fo use.
>
> The features this patch also lacking:
> * NEWS entry
> * man page
> * Installation rules in spec/debian directory.
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Strace-devel mailing list
> Strace-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/strace-devel
-------------- 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/20170809/769fb426/attachment.bin>
More information about the Strace-devel
mailing list