On Fri, Jul 28, 2017 at 06:43:25PM +0300, Edgar Kaziakhmedov wrote: > From: Edgar Kaziakhmedov <edgar.kaziakhme...@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.kaziakhme...@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.kaziakhme...@virtuozzo.com> > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without > +# modification, are permitted provided that the following conditions > +# are met: > +# 1. Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# 2. Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in the > +# documentation and/or other materials provided with the distribution. > +# 3. The name of the author may not be used to endorse or promote products > +# derived from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + > +SUBDIRS = asinfo > diff --git a/tools/asinfo/Makefile.am b/tools/asinfo/Makefile.am > new file mode 100644 > index 00000000..c2d5d8b2 > --- /dev/null > +++ b/tools/asinfo/Makefile.am > @@ -0,0 +1,56 @@ > +# Automake input for asinfo. > +# > +# Copyright (c) 2017 Edgar Kaziakhmedov <edgar.kaziakhme...@virtuozzo.com> > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without > +# modification, are permitted provided that the following conditions > +# are met: > +# 1. Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# 2. Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in the > +# documentation and/or other materials provided with the distribution. > +# 3. The name of the author may not be used to endorse or promote products > +# derived from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + > +bin_PROGRAMS = asinfo > +man_MANS = asinfo.1 > + > +OS = linux > + > +AUTOMAKE_OPTIONS = subdir-objects > + > +AM_CFLAGS = $(WARN_CFLAGS) > +AM_CPPFLAGS = -I$(builddir) \ > + -I$(top_builddir)/$(OS) \ > + -I$(top_srcdir)/$(OS) \ > + -I$(top_builddir) \ > + -I$(top_srcdir) > +asinfo_CPPFLAGS = $(AM_CPPFLAGS) > +asinfo_CFLAGS = $(AM_CFLAGS) > + > +asinfo_SOURCES = \ 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.kaziakhme...@virtuozzo.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#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.kaziakhm...@virtuozzo.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > +#ifndef ASINFO_ARCH_INTERFACE > +#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.kaziakhme...@virtuozzo.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifdef HAVE_CONFIG_H > +# include "config.h" > +#endif > +#include <errno.h> > +#include <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.kaziakhme...@virtuozzo.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifdef HAVE_CONFIG_H > +# include "config.h" > +#endif > +#include <stdlib.h> > +#include <stdio.h> > +#include <string.h> > +#include <sys/utsname.h> > + > +#include "arch_interface.h" > +#include "dispatchers.h" > +#include "macros.h" > +#include "request_msgs.h" > +#include "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.kaziakhme...@virtuozzo.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifndef 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.kaziakhme...@virtuozzo.com> > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The name of the author may not be used to endorse or promote products > + * derived from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifndef 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. ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel