[PATCH 2/2] asinfo: Introduce static query tool asinfo
Eugene Syromiatnikov
esyr at redhat.com
Mon Jul 31 04:19:23 UTC 2017
On Fri, Jul 28, 2017 at 06:43:25PM +0300, Edgar Kaziakhmedov wrote:
> From: Edgar Kaziakhmedov <edgar.kaziakhmedov at virtuzzo.com>
>
> The 1.2 version of asinfo tool. The asinfo tool has the
This version is not mentioned anywhere else.
> following architecture:
> commnand dispatcher->architecture dispatcher->abi dispatcher->
"command"
> system call dispatcher->filter dispatcher
>
> As for arch. dispatcher, the asinfo has get-arch, list-arch, set-arch
> %name_of_arch options, arch_dispatcher is purposed to process them.
> As for abi dispatcher, the asinfo has get-abi, list-abi, set-abi
> %name_of_abi options, abi_dispatcher is putposed to process it.
"purposed"
> As for command_dispatcher, for now it checks all options for
> correctness.
> Now, to find out the main principle of working, let’s consider next
> one case:
> $ asinfo get-arch
> 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 corresponding for the set
> arch value.
>
> NOTE: syscall_dispatcher for now is not supported
>
> It is worth mentioning that this tool supports almostly all
> architectures supporting by Linux kernel.
More precisely, it supports (or, at least, should support) all
architectures/ABIs supported by strace (AFAIR RISC-V is not yet supported
by the Linux mainline kernel, for example).
>
> * Makefile.am (SUBDIRS): Add tools directory.
> * configure.ac (AC_CONFIG_FILES): Add Makefile's.
> * tools/Makefile.am: New file.
> * tools/asinfo/Makefile.am: New file.
> * tools/asinfo/dispatchers.h: New file. Prototype abi_dispatcher,
> arch_dispatcher, and syscall_dispatcher.
> * tools/asinfo/dispatchers.c: New file. Implement it.
> * tools/asinfo/arch_interface.h: New file. Prototype methods to simplify
> work with the list of arch_descriptor. Introduce struct arch_descriptor.
> * tools/asinfo/arch_interface.c: New file. Implement it.
> * tools/asinfo/request_msgs.h: New file. Introduce main types of requests.
> Introduce structures for syscall_dispatcher.
> * tools/asinfo/asinfo.c: New file. Implement support of all options.
> * 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 | 56 +++
> tools/asinfo/arch_interface.c | 888 ++++++++++++++++++++++++++++++++++++++++++
> tools/asinfo/arch_interface.h | 184 +++++++++
> tools/asinfo/asinfo.1 | 0
> tools/asinfo/asinfo.c | 196 ++++++++++
> tools/asinfo/dispatchers.c | 242 ++++++++++++
> tools/asinfo/dispatchers.h | 60 +++
> tools/asinfo/request_msgs.h | 115 ++++++
> 11 files changed, 1772 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
>
> diff --git a/Makefile.am b/Makefile.am
> index da175a27..ac40a8f2 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 0d407aff..ea14e270 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -842,6 +842,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..c2d5d8b2
> --- /dev/null
> +++ b/tools/asinfo/Makefile.am
> @@ -0,0 +1,56 @@
> +# 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 = \
Tabs after spaces.
> + arch_interface.c \
> + arch_interface.h \
> + asinfo.c \
> + dispatchers.c \
> + dispatchers.h \
> + ../../error_prints.c \
> + ../../error_prints.h \
> + ../../macros.h \
> + requests_msgs.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..6de6b830
> --- /dev/null
> +++ b/tools/asinfo/arch_interface.c
> @@ -0,0 +1,888 @@
> +/*
> + * 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 TD TRACE_DESC
> +#define TF TRACE_FILE
> +#define TI TRACE_IPC
> +#define TN TRACE_NETWORK
> +#define TP TRACE_PROCESS
> +#define TS TRACE_SIGNAL
> +#define TM TRACE_MEMORY
> +#define TST TRACE_STAT
> +#define TLST TRACE_LSTAT
> +#define TFST TRACE_FSTAT
> +#define TSTA TRACE_STAT_LIKE
> +#define TSF TRACE_STATFS
> +#define TFSF TRACE_FSTATFS
> +#define TSFA TRACE_STATFS_LIKE
> +#define NF SYSCALL_NEVER_FAILS
> +#define MA MAX_ARGS
> +#define SI STACKTRACE_INVALIDATE_CACHE
> +#define SE STACKTRACE_CAPTURE_ON_ENTER
> +#define CST COMPAT_SYSCALL_TYPES
Ugh. Looks like these shorthand definitions should be put in a separate
header.
> +
> +/*
> + * For the current functionality there is no need
> + * to use sen and (*sys_func)() fields in sysent struct
> + */
> +#define SEN(syscall_name) 0, NULL
> +
> +/* dummy_sysent is purposed to set syscall_list field in
> + * inherited architectures */
> +struct_sysent dummy_sysent[] = {};
> +
> +/* ARCH_blackfin */
> +struct_sysent blackfin_32bit_sysent[] = {
> + #include "bfin/syscallent.h"
> +};
> +const int blackfin_32bit_usr1 = 0;
> +const int blackfin_32bit_usr2 = 0;
> +/* ARCH_ia64 */
> +struct_sysent ia64_64bit_sysent[] = {
> + #include "ia64/syscallent.h"
> +};
> +const int ia64_64bit_usr1 = SYS_socket_subcall;
> +const int ia64_64bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_m68k */
> +struct_sysent m68k_32bit_sysent[] = {
> + #include "m68k/syscallent.h"
> +};
> +const int m68k_32bit_usr1 = SYS_socket_subcall;
> +const int m68k_32bit_usr2 = 0;
> +/* ARCH_sparc64 64bit ABI */
> +struct_sysent sparc64_64bit_sysent[] = {
> + #include "sparc64/syscallent.h"
> +};
> +const int sparc64_64bit_usr1 = SYS_socket_subcall;
> +const int sparc64_64bit_usr2 = 0;
> +/* ARCH_sparc64 32bit ABI */
> +struct_sysent sparc64_32bit_sysent[] = {
> + #include "sparc64/syscallent1.h"
> +};
> +const int sparc64_32bit_usr1 = SYS_socket_subcall;
> +const int sparc64_32bit_usr2 = 0;
> +/* ARCH_sparc */
> +struct_sysent sparc_32bit_sysent[] = {
> + #include "sparc/syscallent.h"
> +};
> +const int sparc_32bit_usr1 = SYS_socket_subcall;
> +const int sparc_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_metag */
> +struct_sysent metag_32bit_sysent[] = {
> + #include "metag/syscallent.h"
> +};
> +const int metag_32bit_usr1 = 0;
> +const int metag_32bit_usr2 = 0;
> +/* ARCH_mips o32 ABI */
> +#ifndef LINUX_MIPSO32
> +# define LINUX_MIPSO32 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent mips_o32_sysent[] = {
> + #include "dummy.h"
> + #include "mips/syscallent-compat.h"
> + #include "mips/syscallent-o32.h"
> +};
> +#ifdef NOW_DEFINED
> +# undef LINUX_MIPSO32
> +# undef NOW_DEFINED
> +#endif
> +const int mips_o32_usr1 = SYS_socket_subcall;
> +const int mips_o32_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_mips n32 ABI */
> +#ifndef LINUX_MIPSN32
> +# define LINUX_MIPSN32 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent mips_n32_sysent[] = {
> + #include "dummy.h"
> + #include "mips/syscallent-compat.h"
> + #include "mips/syscallent-n32.h"
> +};
> +#ifdef NOW_DEFINED
> +# undef LINUX_MIPSN32
> +# undef NOW_DEFINED
> +#endif
> +const int mips_n32_usr1 = SYS_socket_subcall;
> +const int mips_n32_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_mips n64 ABI */
> +#ifndef LINUX_MIPSN64
> +# define LINUX_MIPSN64 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent mips_n64_sysent[] = {
> + #include "dummy.h"
> + #include "mips/syscallent-compat.h"
> + #include "mips/syscallent-n64.h"
> +};
> +#ifdef NOW_DEFINED
> +# undef LINUX_MIPSN32
> +# undef NOW_DEFINED
> +#endif
> +const int mips_n64_usr1 = SYS_socket_subcall;
> +const int mips_n64_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_alpha */
> +struct_sysent alpha_64bit_sysent[] = {
> + #include "alpha/syscallent.h"
> +};
> +const int alpha_64bit_usr1 = 0;
> +const int alpha_64bit_usr2 = 0;
> +/* ARCH_ppc */
> +struct_sysent ppc_32bit_sysent[] = {
> + #include "powerpc/syscallent.h"
> +};
> +const int ppc_32bit_usr1 = SYS_socket_subcall;
> +const int ppc_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_ppc64 64bit ABI */
> +struct_sysent ppc64_64bit_sysent[] = {
> + #include "powerpc64/syscallent.h"
> +};
> +const int ppc64_64bit_usr1 = SYS_socket_subcall;
> +const int ppc64_64bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_ppc64 32bit ABI */
> +struct_sysent ppc64_32bit_sysent[] = {
> + #include "powerpc64/syscallent1.h"
> +};
> +const int ppc64_32bit_usr1 = SYS_socket_subcall;
> +const int ppc64_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_arm OABI*/
> +#ifdef __ARM_EABI__
> +# undef __ARM_EABI__
> +# define NOW_UNDEFINED 1
> +#endif
> +struct_sysent arm_oabi_sysent[] = {
> + #include "arm/syscallent.h"
> +};
> +const int arm_oabi_usr1 = SYS_socket_subcall;
> +const int arm_oabi_usr2 = ARM_FIRST_SHUFFLED_SYSCALL;
> +#undef ARM_FIRST_SHUFFLED_SYSCALL
> +#undef SYS_socket_subcall
> +#ifdef NOW_UNDEFINED
> +# define __ARM_EABI__ 1
> +# undef NOW_UNDEFINED
> +#endif
> +/* ARCH_arm EABI*/
> +#ifndef __ARM_EABI__
> +# define __ARM_EABI__ 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent arm_eabi_sysent[] = {
> + #include "arm/syscallent.h"
> +};
> +const int arm_eabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
> +const int arm_eabi_usr2 = 0;
> +#undef ARM_FIRST_SHUFFLED_SYSCALL
> +#ifdef NOW_DEFINED
> +# undef __ARM_EABI__
> +# undef NOW_DEFINED
> +#endif
> +/* ARCH_aarch64 64bit ABI */
> +struct_sysent aarch64_64bit_sysent[] = {
> + #include "aarch64/syscallent.h"
> +};
> +const int aarch64_64bit_usr1 = 0;
> +const int aarch64_64bit_usr2 = 0;
> +/* ARCH_aarch64 32bit ABI */
> +#ifndef __ARM_EABI__
> +# define __ARM_EABI__ 1
> +# define NOW_DEFINED 1
> +#endif
> +struct_sysent aarch64_32bit_sysent[] = {
> + #include "aarch64/syscallent1.h"
> +};
> +const int aarch64_32bit_usr1 = ARM_FIRST_SHUFFLED_SYSCALL;
> +const int aarch64_32bit_usr2 = ARM_LAST_SPECIAL_SYSCALL;
> +#undef ARM_FIRST_SHUFFLED_SYSCALL
> +#undef ARM_LAST_SPECIAL_SYSCALL
> +#ifdef NOW_DEFINED
> +# undef __ARM_EABI__
> +# undef NOW_DEFINED
> +#endif
> +/* ARCH_avr32 */
> +struct_sysent avr32_32bit_sysent[] = {
> + #include "avr32/syscallent.h"
> +};
> +const int avr32_32bit_usr1 = 0;
> +const int avr32_32bit_usr2 = 0;
> +/* ARCH_arc */
> +struct_sysent arc_32bit_sysent[] = {
> + #include "arc/syscallent.h"
> +};
> +const int arc_32bit_usr1 = 0;
> +const int arc_32bit_usr2 = 0;
> +/* ARCH_s390 */
> +struct_sysent s390_32bit_sysent[] = {
> + #include "s390/syscallent.h"
> +};
> +const int s390_32bit_usr1 = SYS_socket_subcall;
> +const int s390_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_s390x */
> +struct_sysent s390x_64bit_sysent[] = {
> + #include "s390x/syscallent.h"
> +};
> +const int s390x_64bit_usr1 = SYS_socket_subcall;
> +const int s390x_64bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_hppa */
> +struct_sysent hppa_32bit_sysent[] = {
> + #include "hppa/syscallent.h"
> +};
> +const int hppa_32bit_usr1 = 0;
> +const int hppa_32bit_usr2 = 0;
> +/* ARCH_parisc */
> +#define parisc_32bit_sysent dummy_sysent
> +const int parisc_32bit_usr1 = 0;
> +const int parisc_32bit_usr2 = 0;
> +/* ARCH_sh */
> +struct_sysent sh_32bit_sysent[] = {
> + #include "sh/syscallent.h"
> +};
> +const int sh_32bit_usr1 = SYS_socket_subcall;
> +const int sh_32bit_usr2 = 0;
> +/* ARCH_sh64 */
> +struct_sysent sh64_64bit_sysent[] = {
> + #include "sh64/syscallent.h"
> +};
> +const int sh64_64bit_usr1 = SYS_socket_subcall;
> +const int sh64_64bit_usr2 = 0;
> +/* ARCH_x86 */
> +struct_sysent x86_32bit_sysent[] = {
> + #include "i386/syscallent.h"
> +};
> +const int x86_32bit_usr1 = SYS_socket_subcall;
> +const int x86_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_i386 */
> +#define i386_32bit_sysent dummy_sysent
> +const int i386_32bit_usr1 = 0;
> +const int i386_32bit_usr2 = 0;
> +/* ARCH_i486 */
> +#define i486_32bit_sysent dummy_sysent
> +const int i486_32bit_usr1 = 0;
> +const int i486_32bit_usr2 = 0;
> +/* ARCH_i586 */
> +#define i586_32bit_sysent dummy_sysent
> +const int i586_32bit_usr1 = 0;
> +const int i586_32bit_usr2 = 0;
> +/* ARCH_i686 */
> +#define i686_32bit_sysent dummy_sysent
> +const int i686_32bit_usr1 = 0;
> +const int i686_32bit_usr2 = 0;
> +/* ARCH_x86_64 64bit ABI mode */
> +struct_sysent x86_64_64bit_sysent[] = {
> + #include "x86_64/syscallent.h"
> +};
> +const int x86_64_64bit_usr1 = 0;
> +const int x86_64_64bit_usr2 = 0;
> +/* ARCH_x86_64 32bit ABI mode */
> +struct_sysent x86_64_32bit_sysent[] = {
> + #include "x86_64/syscallent1.h"
> +};
> +const int x86_64_32bit_usr1 = SYS_socket_subcall;
> +const int x86_64_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_x86_64 x32 ABI mode */
> +struct_sysent x86_64_x32_sysent[] = {
> + #include "x86_64/syscallent2.h"
> +};
> +const int x86_64_x32_usr1 = 0;
> +const int x86_64_x32_usr2 = 0;
> +/* ARCH_amd64 */
> +#define amd64_64bit_sysent dummy_sysent
> +const int amd64_64bit_usr1 = 0;
> +const int amd64_64bit_usr2 = 0;
> +/* ARCH_cris */
> +struct_sysent cris_32bit_sysent[] = {
> + #include "crisv10/syscallent.h"
> +};
> +const int cris_32bit_usr1 = SYS_socket_subcall;
> +const int cris_32bit_usr2 = 0;
> +/* ARCH_crisv10 */
> +#define crisv10_32bit_sysent dummy_sysent
> +const int crisv10_32bit_usr1 = 0;
> +const int crisv10_32bit_usr2 = 0;
> +/* ARCH_crisv32 */
> +struct_sysent crisv32_32bit_sysent[] = {
> + #include "crisv32/syscallent.h"
> +};
> +const int crisv32_32bit_usr1 = SYS_socket_subcall;
> +const int crisv32_32bit_usr2 = 0;
> +#undef SYS_socket_subcall
> +/* ARCH_tile 64bit ABI mode */
> +struct_sysent tile_64bit_sysent[] = {
> + #include "tile/syscallent.h"
> +};
> +const int tile_64bit_usr1 = 0;
> +const int tile_64bit_usr2 = 0;
> +/* ARCH_tile 32bit ABI mode */
> +struct_sysent tile_32bit_sysent[] = {
> + #include "tile/syscallent1.h"
> +};
> +const int tile_32bit_usr1 = 0;
> +const int tile_32bit_usr2 = 0;
> +/* ARCH_microblaze */
> +struct_sysent microblaze_32bit_sysent[] = {
> + #include "microblaze/syscallent.h"
> +};
> +const int microblaze_32bit_usr1 = 0;
> +const int microblaze_32bit_usr2 = 0;
> +/* ARCH_nios2 */
> +struct_sysent nios2_32bit_sysent[] = {
> + #include "nios2/syscallent.h"
> +};
> +const int nios2_32bit_usr1 = 0;
> +const int nios2_32bit_usr2 = 0;
> +/* ARCH_openrisc */
> +struct_sysent openrisc_32bit_sysent[] = {
> + #include "or1k/syscallent.h"
> +};
> +const int openrisc_32bit_usr1 = 0;
> +const int openrisc_32bit_usr2 = 0;
> +/* ARCH_xtensa */
> +struct_sysent xtensa_32bit_sysent[] = {
> + #include "xtensa/syscallent.h"
> +};
> +const int xtensa_32bit_usr1 = 0;
> +const int xtensa_32bit_usr2 = 0;
> +/* ARCH_riscv 64bit ABI mode */
> +struct_sysent riscv_64bit_sysent[] = {
> + #include "riscv/syscallent.h"
> +};
> +const int riscv_64bit_usr1 = 0;
> +const int riscv_64bit_usr2 = 0;
> +/* ARCH_riscv 32bit ABI mode */
> +struct_sysent riscv_32bit_sysent[] = {
> + #include "riscv/syscallent1.h"
> +};
> +const int riscv_32bit_usr1 = 0;
> +const int riscv_32bit_usr2 = 0;
I'd strongly prefer this code being generated. There's already too much
burden for adding a new architecture support.
> +
> +#undef DEFINE_SYSCALLENT
> +
> +#undef SEN
> +#undef TD
> +#undef TF
> +#undef TI
> +#undef TN
> +#undef TP
> +#undef TS
> +#undef TM
> +#undef TST
> +#undef TLST
> +#undef TFST
> +#undef TSTA
> +#undef TSF
> +#undef TFSF
> +#undef TSFA
> +#undef NF
> +#undef MA
> +#undef SI
> +#undef SE
> +#undef CST
> +
> +#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), \
> + .list_of_syscall = arch##_##mode##_sysent, \
"syscall_list" sounds more natural.
> + .user_num1 = &arch##_##mode##_usr1, \
> + .user_num2 = &arch##_##mode##_usr2, \
> + .flag = AD_FLAG_EMPTY \
> + }
> +
> +/* Generate array of arch_descriptors for each architecture and mode */
> +struct arch_descriptor architectures[] = {
> + ARCH_DESC_DEFINE(blackfin, blackfin, 32bit ),
> + ARCH_DESC_DEFINE(ia64, ia64, 64bit ),
> + ARCH_DESC_DEFINE(m68k, m68k, 32bit ),
> + ARCH_DESC_DEFINE(sparc64, sparc64, 64bit ),
> + ARCH_DESC_DEFINE(sparc64, sparc64, 32bit ),
> + ARCH_DESC_DEFINE(sparc, sparc, 32bit ),
> + ARCH_DESC_DEFINE(metag, metag, 32bit ),
> + ARCH_DESC_DEFINE(mips, mips, o32 ),
> + ARCH_DESC_DEFINE(mips, mips, n32 ),
> + ARCH_DESC_DEFINE(mips, mips, n64 ),
> + ARCH_DESC_DEFINE(alpha, alpha, 64bit ),
> + ARCH_DESC_DEFINE(ppc, ppc, 32bit ),
> + ARCH_DESC_DEFINE(ppc64, ppc64, 64bit ),
> + ARCH_DESC_DEFINE(ppc64, ppc64, 32bit ),
> + ARCH_DESC_DEFINE(arm, arm, oabi ),
> + ARCH_DESC_DEFINE(arm, arm, eabi ),
> + ARCH_DESC_DEFINE(aarch64, aarch64, 64bit ),
> + ARCH_DESC_DEFINE(aarch64, aarch64, 32bit ),
> + ARCH_DESC_DEFINE(avr32, avr32, 32bit ),
> + ARCH_DESC_DEFINE(arc, arc, 32bit ),
> + ARCH_DESC_DEFINE(s390, s390, 32bit ),
> + ARCH_DESC_DEFINE(s390x, s390x, 64bit ),
> + ARCH_DESC_DEFINE(hppa, hppa, 32bit ),
> + ARCH_DESC_DEFINE(parisc, hppa, 32bit ),
> + ARCH_DESC_DEFINE(sh, sh, 32bit ),
> + ARCH_DESC_DEFINE(sh64, sh64, 64bit ),
> + ARCH_DESC_DEFINE(x86, x86, 32bit ),
> + ARCH_DESC_DEFINE(i386, x86, 32bit ),
> + ARCH_DESC_DEFINE(i486, x86, 32bit ),
> + ARCH_DESC_DEFINE(i586, x86, 32bit ),
> + ARCH_DESC_DEFINE(i686, x86, 32bit ),
> + ARCH_DESC_DEFINE(x86_64, x86_64, 64bit ),
> + ARCH_DESC_DEFINE(x86_64, x86_64, 32bit ),
> + ARCH_DESC_DEFINE(x86_64, x86_64, x32 ),
> + ARCH_DESC_DEFINE(amd64, x86_64, 64bit ),
> + ARCH_DESC_DEFINE(cris, cris, 32bit ),
> + ARCH_DESC_DEFINE(crisv10, cris, 32bit ),
> + ARCH_DESC_DEFINE(crisv32, crisv32, 32bit ),
> + ARCH_DESC_DEFINE(tile, tile, 64bit ),
> + ARCH_DESC_DEFINE(tile, tile, 32bit ),
> + ARCH_DESC_DEFINE(microblaze, microblaze, 32bit ),
> + ARCH_DESC_DEFINE(nios2, nios2, 32bit ),
> + ARCH_DESC_DEFINE(openrisc, openrisc, 32bit ),
> + ARCH_DESC_DEFINE(xtensa, xtensa, 32bit ),
> + ARCH_DESC_DEFINE(riscv, riscv, 64bit ),
> + ARCH_DESC_DEFINE(riscv, riscv, 32bit )
Looks like we definitely need list of personality names for each
architecture.
> +};
> +
> +/* 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 = xcalloc(sizeof(*as), 1);
> +
> + if (capacity)
> + as->arch_list = xcalloc(sizeof(*(as->arch_list)), 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->arch_list[m->next_free]->flag = AD_FLAG_EMPTY;
I'd prefer having arch descriptors immutable and mutable flag being
outside them, as a part of arch_service container.
> + 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->arch_list[index]->flag = flag;
> + return 0;
> + }
> + return -1;
> +}
> +
> +struct arch_descriptor *
> +al_get(struct arch_service *m, unsigned index)
> +{
> + if (al_is_index_ok(m, index) != 0)
> + return NULL;
> + return m->arch_list[index];
> +}
> +
> +unsigned int
> +al_size(struct arch_service *m)
> +{
> + return m->next_free;
> +}
> +
> +unsigned int
> +al_base_size(struct arch_service *m)
> +{
> + int arch_size = al_size(m);
> + int i = 0;
> + unsigned count = 0;
> +
> + for (i = 0; i < arch_size; i++)
> + if (m->arch_list[i]->arch_num ==
> + m->arch_list[i]->arch_base_num)
> + count++;
> + return count;
> +}
> +
> +void
> +al_free(struct arch_service *m)
> +{
> + free(m->arch_list);
> + free(m);
> +}
> +
> +enum arch_type
> +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_type
> +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)
> +{
> + struct arch_descriptor *elem = al_get(m, index);
> +
> + return (elem ? elem->flag : -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->list_of_syscall[i].sys_name &&
> + !(elem->list_of_syscall[i].sys_flags &
> + TRACE_INDIRECT_SUBCALL))
> + count++;
> + }
> + return count;
> +}
> +
> +/* This method is purposed to find base arch
> + * NOTE: base arch is the arch, where arch_num is equal to arch_base_num
> + * with default ABI mode */
> +int
> +al_find_base_arch(struct arch_service *m, unsigned index)
> +{
> + enum arch_type base_arch = ARCH_no_arch;
> + int arch_size = al_size(m);
> + int i = 0;
> +
> + /* If given arch meets conditions above then return this index */
> + if (al_is_index_ok(m, index) != 0)
> + return -1;
> + /* Search base arch */
> + base_arch = al_arch_base_num(m, index);
> + for (i = 0; i < arch_size; i++)
> + if ((strcmp(al_arch_name(m, index), al_arch_name(m, i)) == 0)
> + || (al_arch_base_num(m, i) == base_arch))
> + return i;
> + return -1;
> +}
> +
> +/* This method is purposed to count the supported ABI modes for the given
> + arch
> + NOTE: Firstly, do not forget to find base 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;
> + for (i = 0; i < arch_size; i++)
> + if (strcmp(arch_name, al_arch_name(m, i)) == 0)
> + abi_count++;
> + return abi_count;
> +}
> +
> +/* This method is purposed to check on uniqueness, in sense of arch name,
> + without taking into account ABI modes */
> +int
> +al_is_arch_unique(struct arch_service *m, unsigned index)
> +{
> + enum arch_type base_arch = ARCH_no_arch;
> + int arch_size = al_size(m);
> + int i = 0;
> +
> + if (al_arch_num(m, index) != al_arch_base_num(m, index) ||
> + al_arch_num(m, index) == ARCH_no_arch)
> + return -1;
> + base_arch = al_arch_base_num(m, index);
> + for (i = 0; i < arch_size; i++)
> + if ((al_arch_num(m, i) == base_arch) &&
> + (i != (int)index))
> + return -1;
> + return 0;
> +}
> +
> +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->list_of_syscall[i].sys_name == NULL)
> + continue;
> + if (strcmp(elem->list_of_syscall[i].sys_name, "ipc") == 0)
> + impl_buf = IMPL_int;
> + /* It is enough to find just semop sybcall */
> + if ((strcmp(elem->list_of_syscall[i].sys_name, "semop") == 0)
> + && !((elem->list_of_syscall[i].sys_flags &
> + TRACE_INDIRECT_SUBCALL))) {
> + if (impl_buf == IMPL_int)
> + impl_buf = IMPL_int_ext;
> + else
> + impl_buf = IMPL_ext;
> + }
> + }
> + 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->list_of_syscall[i].sys_name == NULL)
> + continue;
> + if (strcmp(elem->list_of_syscall[i].sys_name,
> + "socketcall") == 0)
> + impl_buf = IMPL_int;
> + /* It is enough to find just socket sybcall */
> + if ((strcmp(elem->list_of_syscall[i].sys_name, "socket") == 0)
> + && (!(elem->list_of_syscall[i].sys_flags &
> + TRACE_INDIRECT_SUBCALL))) {
> + if (impl_buf == IMPL_int)
> + impl_buf = IMPL_int_ext;
> + else
> + impl_buf = IMPL_ext;
> + }
> + }
> + return impl_buf;
> +}
For this, I think some generator similar to ioctlsort could be used,
which allows generating list of ID's of syscalls on different
architectures. Or simple wrapper for generate_sen.h, which allows
accessing them vis SEN_<arch>_<syscall> constants.
> +
> +int al_find_arch(struct arch_service *m, enum arch_type 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;
> +}
> +
> +//len could optimized
> +//arch_list_size 11
> +void
> +al_dump(struct arch_service *m)
> +{
> + const char *title[] = {
> + "N",
> + "Architecture name",
> + "ABI mode",
> + /* Implemented syscalls */
> + "IMPL syscalls",
> + /* IPC implementation */
> + "IPC IMPL",
> + /* SOCKET implementation */
> + "SOCKET IMPL"
> + };
> + const char *impl_st[] = {
> + "external",
> + "internal",
> + "int/ext"
> + };
> + int i = 0;
> + int lbase_arch = 0;
> + int temp_len = 0;
> + int arch_number_col = 0;
> + int arch_name_col = strlen(title[1]);
> + int arch_abi_col = strlen(title[2]);
> + /* It is hard to imagine arch with more than 10^13 syscalls */
Actually, it's difficult to have more than 2^32 syscalls.
> + int arch_impl_sc_col = strlen(title[3]);
> + int arch_ipc_col = strlen(title[4]);
> + int arch_sck_col = strlen(title[5]);
> + 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)
> + arch_number_col++;
> + for (i = 0; i < arch_size; i++) {
> + /* Calculate length of the column with the
> + architectures name */
> + if (al_is_arch_unique(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 > arch_name_col) {
> + arch_name_col = temp_len;
> + }
Braces can be omitted here.
> + /* Calculate length of the column with the ABI mode */
> + if (al_abi_mode_len(m, i) > arch_abi_col)
> + arch_abi_col = al_abi_mode_len(m, i);
> +
Stay empty line.
> + }
The complexity of this loop frightens me. Is it n^3?
> + arch_name_buf = xcalloc(arch_name_col, sizeof(*arch_name_buf));
> + /* Output title */
> + printf("| %*s | %*s | %*s | %*s | %*s | %*s |\n",
> + arch_number_col, title[0], arch_name_col, title[1],
> + arch_abi_col, title[2], arch_impl_sc_col, title[3],
> + arch_ipc_col, title[4], arch_sck_col, title[5]);
> + /* Output architectures */
> + for (i = 0; i < arch_size; i++) {
> + if ((al_is_arch_unique(m, i) == -1) ||
> + !(al_flag(m, i) & AD_FLAG_PRINT))
> + continue;
> + printf("| %*u | ", arch_number_col, 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 | ", arch_name_col, arch_name_buf);
> + printf("%*s | ", arch_abi_col, al_abi_mode(m, i));
> + printf("%*d | ", arch_impl_sc_col, al_syscall_impl(m, i));
> + printf("%*s | ", arch_ipc_col, impl_st[al_ipc_syscall(m, i)]);
> + printf("%*s |\n", arch_sck_col, impl_st[al_sck_syscall(m, i)]);
> + N++;
> + memset(arch_name_buf, 0, arch_name_col);
> + }
> + free(arch_name_buf);
> +}
> diff --git a/tools/asinfo/arch_interface.h b/tools/asinfo/arch_interface.h
> new file mode 100644
> index 00000000..a7a6d320
> --- /dev/null
> +++ b/tools/asinfo/arch_interface.h
> @@ -0,0 +1,184 @@
> +/*
> + * 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_type format name_arch = ARCH_ + kernel_arch/others_name + abi_mode */
> +enum arch_type {
So, are these architecture types or architecture names?
> + 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
> +};
> +
> +#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
> +
> +struct arch_descriptor {
> + enum arch_type arch_num;
> + const char *arch_name;
> + const int arch_name_len;
> + enum arch_type arch_base_num;
> + //enum abi_type abi_mode;
> + const char *abi_mode;
> + const int abi_mode_len;
> + const int max_scn;
> + struct_sysent *list_of_syscall;
> + /* In the most cases these fields are purposed to store specific for
> + given arch constants, for instance, socket_subcall index etc */
This sounds scary, taking into account the fact that these fields are not used,
actually.
> + const int *user_num1;
> + const int *user_num2;
> + /* User flags */
> + int flag;
> +};
> +
> +/* To provide push-back interface with arch_list */
> +struct arch_service {
> + struct arch_descriptor **arch_list;
> + 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_type 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_type 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_unique(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_type 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..195c1d09
> --- /dev/null
> +++ b/tools/asinfo/asinfo.c
> @@ -0,0 +1,196 @@
> +/*
> + * 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 "xmalloc.h"
> +
> +#ifndef HAVE_PROGRAM_INVOCATION_NAME
> +char *program_invocation_name;
> +#endif
> +
> +void
> +die(void)
> +{
> + exit(1);
> +}
> +
> +static int
> +is_more1bit(unsigned int num)
> +{
> + return !(num & (num - 1));
> +}
Usually such function is called "is_power_of_two" or something like that.
In your case it's (or, more precisely, its inverse) probably should be named
"is_single_bit" or something like this.
Note that this function return true for num == 0.
> +
> +static unsigned
> +option_to_request(char *option)
> +{
> + /* Convertion table to store string with options */
> + const char *options[] = {
> + [SD_REQ_GET_NAME_BIT] = "get-name",
> + [SD_REQ_GET_NUMBER_BIT] = "get-num",
> + [SD_REQ_GET_NARGS_BIT] = "get-nargs",
> + [AD_REQ_SET_ARCH_BIT] = "set-arch",
> + [AD_REQ_GET_ARCH_BIT] = "get-arch",
> + [AD_REQ_LIST_ARCH_BIT] = "list-arch",
> + [ABD_REQ_SET_ABI] = "set-abi",
> + [ABD_REQ_GET_ABI] = "get-abi",
> + [ABD_REQ_LIST_ABI] = "list-abi",
Why last three do not have "_BIT" suffix?
> + };
> + unsigned i;
> +
> + for (i = 0; i < ARRAY_SIZE(options); i++) {
> + if (options[i] && strcmp(option, options[i]) == 0)
> + return i;
> + }
> + return UINT_MAX;
> +}
> +
> +static unsigned
> +command_dispatcher(int argc, char *argv[], char *args[])
> +{
> + int i;
> + unsigned final_req = 0;
> + unsigned temp_req = 0;
> + unsigned non_req_arg = (1 << AD_REQ_GET_ARCH_BIT) |
> + (1 << AD_REQ_LIST_ARCH_BIT) |
> + (1 << ABD_REQ_GET_ABI_BIT) |
> + (1 << ABD_REQ_LIST_ABI_BIT) |
> + (1 << SD_REQ_GET_LIST_BIT);
> +
> + if (!program_invocation_name || !*program_invocation_name) {
> + static char name[] = "asinfo";
> + program_invocation_name =
> + (argv[0] && *argv[0]) ? argv[0] : name;
> + }
> +
> + /* Firstly, is is necessary to convert and make basic check */
To convert what?
> + for (i = 1; i < argc; i++) {
> + if ((temp_req = option_to_request(argv[i])) == UINT_MAX)
> + error_msg_and_help("unrecognized option '%s'", argv[i]);
> + if (final_req & (1 << temp_req))
> + error_msg_and_help("option '%s' has been used more than "
> + "once", argv[i]);
> + if (!((1 << temp_req) & non_req_arg) &&
> + ((i + 1 >= argc) || strlen(argv[i + 1]) == 0))
> + error_msg_and_help("option '%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,
> + here the only error is 'mixed options' */
> + /* More than one option from the 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("mixed options");
This error message is quite uninformative.
> + /* Check on mutually exclusive options chain */
> + /* If at least one syscall option has been typed, therefore
> + arch_options could be only empty or set-arch and
> + abi_option could be only empty or set-abi */
> + if ((final_req & SD_REQ_MASK) &&
> + (((final_req & AD_REQ_MASK) &&
> + !(final_req & (1 << AD_REQ_SET_ARCH_BIT))) ||
> + ((final_req & ABD_REQ_MASK) &&
> + !(final_req & (1 << ABD_REQ_SET_ABI_BIT)))))
> + error_msg_and_help("mixed options");
This too.
> +
> + /* list-arch couldn't be used with any abi options */
> + if ((final_req & (1 << AD_REQ_LIST_ARCH_BIT) &&
> + (final_req & ABD_REQ_MASK)))
> + error_msg_and_help("mixed options");
And this.
> +
> + return final_req;
> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> + ARCH_LIST_DEFINE(arch_list);
> + /* This array is purposed to store arguments for options in the
> + most convinient way */
"convenient"
> + 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]);
> + if (arch_list == NULL)
> + error_msg_and_help("unrecognized architecture '%s'",
> + input_args[AD_REQ_SET_ARCH]);
> + /* abi_dispatcher turn */
> + ret = abi_dispatcher(arch_list, reqs, input_args[ABD_REQ_SET_ABI]);
> + if (ret != 0)
> + error_msg_and_help("unrecognized ABI mode '%s'",
> + input_args[ABD_REQ_SET_ABI]);
> + /* syscall_dispatcher work */
> +#if 0
> + SYSCALL_LIST_DEFINE(syscall_list);
> + syscall_list = syscall_dispatcher(arch_list, requests,
> + input_args[IS_OWNrequests & SD_REQ_MASK]);
> + if (syscall_list[0].sys_name != NULL) {
> + printf("%s\n", syscall_list[0].sys_name);
> + } else {
> + error_msg_and_help("unrecognized syscall number '%s'",
> + input_args[fsbit_num(requests & SD_REQ_MASK)]);
> + }
> +#endif
> + /* If we want to get info about just architectures thus we dump just
> + info about archs, otherwise only about syscalls */
> + if (!(reqs & SD_REQ_MASK))
> + al_dump(arch_list);
> + else
> + //sl_dump
> + error_msg_and_die("syscall dispatcher isn't supported for now");
> + return 0;
> +}
> diff --git a/tools/asinfo/dispatchers.c b/tools/asinfo/dispatchers.c
> new file mode 100644
> index 00000000..101f9f14
> --- /dev/null
> +++ b/tools/asinfo/dispatchers.c
> @@ -0,0 +1,242 @@
> +/*
> + * 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 "sysent.h"
> +#include "xmalloc.h"
> +
> +extern struct arch_descriptor architectures[];
> +extern const int architectures_size;
> +
> +struct sc_base_info *
> +syscall_dispatcher(struct arch_service *arch, int request_type,
> + const char *data)
> +{
> + SYSCALL_LIST_DEFINE(syscall_list);
> +
> + if (request_type & (1 << SD_REQ_GET_NAME_BIT)) {
> + long int nsys;
> + char *endptr;
> + nsys = strtol(data, &endptr, 10);
> + if (*endptr != '\0' || nsys < 0 ||
> + nsys >= arch->arch_list[0]->max_scn) {
> + goto fail;
> + }
> + SYSCALL_LIST_ALLOC(syscall_list, 1);
> + syscall_list[0].sys_name =
> + arch->arch_list[0]->list_of_syscall[nsys].sys_name;
> + goto done;
> + }
> +
> +fail:
> + SYSCALL_LIST_ALLOC(syscall_list, 0);
> +done:
> + return syscall_list;
> +}
> +
> +static int
> +form_arch_list(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 firther 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 in architecture list */
> + for (i = 0; i < al_size_full; i++) {
> + match_pointer = strstr(arch_str, al_arch_name(a_full_list, i));
> + if (match_pointer == NULL || match_pointer != arch_str)
> + continue;
> + if (arch_match == -1 ||
> + al_arch_name_len(a_full_list, i) >
> + al_arch_name_len(a_full_list, arch_match))
> + arch_match = i;
> + }
> + if (arch_match == -1)
> + goto fail;
> + /* Now we find all ABI modes related to the architecture and its other
> + names */
> + /* Firstly, find the base arch */
> + arch_match = al_find_base_arch(a_full_list, arch_match);
> + /* Secondly, it is necessary to calculate size of arch list */
> + al_size_ret = al_get_abi_modes(a_full_list, arch_match);
> + while ((i = al_next_arch_name(a_full_list, arch_match)) != -1)
> + al_size_ret++;
> + if (al_size_ret == 0)
> + goto fail;
> + /* Finally, Create arch_list and fill it */
> + *arch = al_create(al_size_ret);
> + for (i = arch_match; i < (arch_match + al_size_ret); i++)
> + al_push(*arch, &architectures[i]);
> +
> + free(a_full_list);
> + return 0;
> +fail:
> + free(a_full_list);
> + return -1;
> +}
> +
> +struct arch_service *
> +arch_dispatcher(unsigned request_type, char *arch)
> +{
> + struct utsname info_uname;
> + int i;
> + ARCH_LIST_DEFINE(arch_list) = NULL;
> +
> + /* If user don't type any option in ARCH_REQ group, it means
> + get current arch */
> + if ((request_type & (1 << AD_REQ_GET_ARCH_BIT)) ||
> + (!(request_type & AD_REQ_MASK))) {
> + uname(&info_uname);
> + if (form_arch_list(&arch_list, info_uname.machine) == -1)
> + goto fail;
> + goto done;
> + }
> +
> + if (request_type & (1 << AD_REQ_SET_ARCH_BIT)) {
> + if (form_arch_list(&arch_list, arch) == -1)
> + goto fail;
> + goto done;
> + }
> +
> + if ((request_type & (1 << AD_REQ_LIST_ARCH_BIT))) {
> + 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_type arch_num = ARCH_no_arch;
> + int abi_modes = 0;
> + int arch_size = 0;
> + int flag = 0;
> +
> + if (a_serv == NULL)
> + return -1;
> + arch_size = al_size(a_serv);
> + abi_modes = al_get_abi_modes(a_serv, 0);
> + /* The strace package could be compiled as 32bit app on 64bit
> + architecture, therefore asinfo has to detect it and print out
> + corresponding personality. Frankly speaking, it is necessary to
> + detect strace package personality */
> + if ((request_type & (1 << ABD_REQ_GET_ABI_BIT)) ||
> + (!(request_type & ABD_REQ_MASK))) {
> + arch_num = al_arch_num(a_serv, 0);
> + switch (arch_num) {
> + 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_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_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;
> + default:
> + /* Other cases should be printed using default rule:
> + print 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 & (1 << ABD_REQ_LIST_ABI_BIT)) {
> + for (i = 0; i < abi_modes; i++)
> + al_set_flag(a_serv, i, AD_FLAG_PRINT);
> + goto done;
> + }
> +
> + if (request_type & (1 << ABD_REQ_SET_ABI_BIT)) {
> + 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;
> +}
> diff --git a/tools/asinfo/dispatchers.h b/tools/asinfo/dispatchers.h
> new file mode 100644
> index 00000000..dc76feb8
> --- /dev/null
> +++ b/tools/asinfo/dispatchers.h
> @@ -0,0 +1,60 @@
> +/*
> + * 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 "request_msgs.h"
> +#include "sysent.h"
> +
> +#define SYSCALL_LIST_DEFINE(name) \
> + struct sc_base_info *(name)
> +
> +#define SYSCALL_LIST_ALLOC(name, size) \
> + (name) = xcalloc(sizeof(*(name)), (size + 1))
> +
> +/* The main interaction with low-level structures, such as for now,
> + * struct_sysent, is happening here, the remaining processing should
> + * be done on the other levels.
> + */
> +struct sc_base_info *syscall_dispatcher(struct arch_service *arch,
> + int request_type,
> + const char *arg);
> +
> +/* The function is purposed to provide correct list of architectures
> + */
> +struct arch_service *arch_dispatcher(unsigned request_type, char* arch);
> +
> +/* Final filtering based on personality */
> +int abi_dispatcher(struct arch_service *a_serv, unsigned request_type,
> + char *abi);
> +
> +#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..895b043c
> --- /dev/null
> +++ b/tools/asinfo/request_msgs.h
> @@ -0,0 +1,115 @@
> +/*
> + * 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_NAME_BIT,
> + SD_REQ_GET_NUMBER_BIT,
> + SD_REQ_GET_NARGS_BIT,
> + SD_REQ_GET_PROTO_BIT,
> + SD_REQ_GET_KERNEL_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
> +};
> +
> +#define ENUM_FLAG(name) name = name##_BIT
Looks like I've made a mistake when wrote a code snippet example, there
should be a bit shift by amount of bits from the bit enumeration:
#define ENUM_FLAG(name) name = 1 << name##_BIT
> +enum req_type {
> + ENUM_FLAG(SD_REQ_GET_NAME),
> + ENUM_FLAG(SD_REQ_GET_NUMBER),
> + ENUM_FLAG(SD_REQ_GET_NARGS),
> + ENUM_FLAG(SD_REQ_GET_PROTO),
> + ENUM_FLAG(SD_REQ_GET_KERNEL),
> + 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),
> +};
> +#undef ENUM_FLAG
> +
> +#define BITMASK(hi, lo) ((1 << (hi)) - (1 << (lo)))
> +#define REQ_LAST_BIT FD_REQ_BIT_LAST /* Can be used in input_args calloc*/
> +#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)
> +
> +/* SD_REQ_GET_NAME, SD_REQ_GET_NUMBER */
> +struct sc_base_info {
> + int sys_number;
> + const char *sys_name;
> + int sys_flags;
> +};
> +
> +/* SD_REQ_GET_NARGS */
> +struct sc_nargs {
> + struct sc_base_info sys_bi;
> + int nargs;
> +};
> +
> +/* FD_SET_BASE_FILTER */
> +struct sc_filter {
> + struct sc_base_info sys_bi;
> + int filter_options;
> +};
> +
> +#endif /* !STRACE_ASINFO_REQ_MSGS */
> --
> 2.11.0
% ./asinfo -h
./asinfo: unrecognized option '-h'
Try './asinfo -h' for more information.
The implementation of architecture name aliases looks pretty convoluted.
The same for arch dispatcher, especially in form_arch_list part. It's
quite difficult to evaluate tool's functionality without any user
manual.
More information about the Strace-devel
mailing list