On Tue, 15 Aug 2017 07:55:47 +0300 Edgar Kaziakhmedov <edgar.kaziakhme...@virtuozzo.com> wrote:
I suppose there is no more need to review this patch, because a lot's changed from that moment. Also, I thought that it'd be useful to add processing of some numerical expression(for syscall) besides regexp and syscall group. For example, option like --set-snum 1-10,3,0xf0000 seems convenient(output list of syscalls with this numbers) And I'd ask, is this format looks enough? I mean, set of numbers and ranges separated by comma(with hex-dec numbers). I came to this decision because regexp format doesn't look convenient here from my point of view. > The main purpose of this program is to present all information > concluded at sysent.h files as a query tool. > The asinfo tool has the following architecture: > command dispatcher->architecture dispatcher->abi dispatcher-> > system call dispatcher. > Each dispatcher accepts proccesed data from previous one. > > This point is illustrated by the following example: > $ asinfo --get-arch --get-sysc write > Firstly, arch_dispatcher will return the current architecture, based > on uname return value, after that in case of no options for > abi_dispatcher, it perceives empty parameter as get-abi option and > returns ABI mode set at compile time of strace package. Therefore, > syscall_dispatcher accepts this architecture/ABI and works with > specific set of system calls. It is worth mentioning that it supports > all architectures/ABIs supported by strace. Also, tool can work in > multi-arch mode. for instance: $ ./tools/asinfo/asinfo --set-arch > mips64,mips --set-abi n64,all > > * Makefile.am (SUBDIRS): Add tools directory. > * configure.ac (AC_CONFIG_FILES): Add Makefiles. > * tools/Makefile.am: New file. > * tools/asinfo/Makefile.am: New file. > * tools/asinfo/dispatchers.h: New file. Prototype abi_dispatcher, > arch_dispatcher, and syscall_dispatcher. > * tools/asinfo/dispatchers.c: New file. Implement them. > * tools/asinfo/arch_interface.h: New file. Introduce struct > arch_descriptor. Introduce arch_service. Prototype methods to simplify > work with the arch_service. > * tools/asinfo/arch_interface.c: New file. Implement it. > * tools/asinfo/syscall_interface.h: New file. Introduce > syscall_service. Prototype methods to simplify work with > syscall_service. > * tools/asinfo/syscall_interface.c: New file. Implement it. > * tools/asinfo/request_msgs.h: New file. Introduce main requests. > * tools/asinfo/asinfo.c: New file. Implement support of all options. > Implement usage. > * tools/asinfo/arch_definitions.h: New file. Introduce useful storage > way for architectures. > * tools/asinfo/arch_includes.h: New file. > * tools/asinfo/personalities.h: New file. > * tools/asinfo/error_interface.h: New file. Introduce error_service to > improve informativeness of output errors. Prototype methods to work > with error_service. > * tools/asinfo/error_interface.c: New file. Implement it. > * tools/asinfo/asinfo.1: New file. Empty man. > > Signed-off-by: Edgar Kaziakhmedov <edgar.kaziakhme...@virtuozzo.com> > --- > Makefile.am | 2 +- > configure.ac | 2 + > tools/Makefile.am | 28 ++ > tools/asinfo/Makefile.am | 65 ++++ > tools/asinfo/arch_definitions.h | 70 +++++ > tools/asinfo/arch_includes.h | 272 +++++++++++++++++ > tools/asinfo/arch_interface.c | 603 > ++++++++++++++++++++++++++++++++++++++ > tools/asinfo/arch_interface.h | 156 ++++++++++ > tools/asinfo/arch_personalities.h | 36 +++ > tools/asinfo/asinfo.1 | 0 > tools/asinfo/asinfo.c | 295 +++++++++++++++++++ > tools/asinfo/dispatchers.c | 219 ++++++++++++++ > tools/asinfo/dispatchers.h | 48 +++ > tools/asinfo/error_interface.c | 109 +++++++ > tools/asinfo/error_interface.h | 95 ++++++ > tools/asinfo/request_msgs.h | 97 ++++++ > tools/asinfo/syscall_interface.c | 323 ++++++++++++++++++++ > tools/asinfo/syscall_interface.h | 104 +++++++ 18 files changed, > 2523 insertions(+), 1 deletion(-) create mode 100644 tools/Makefile.am > create mode 100644 tools/asinfo/Makefile.am > create mode 100644 tools/asinfo/arch_definitions.h > create mode 100644 tools/asinfo/arch_includes.h > create mode 100644 tools/asinfo/arch_interface.c > create mode 100644 tools/asinfo/arch_interface.h > create mode 100644 tools/asinfo/arch_personalities.h > create mode 100644 tools/asinfo/asinfo.1 > create mode 100644 tools/asinfo/asinfo.c > create mode 100644 tools/asinfo/dispatchers.c > create mode 100644 tools/asinfo/dispatchers.h > create mode 100644 tools/asinfo/error_interface.c > create mode 100644 tools/asinfo/error_interface.h > create mode 100644 tools/asinfo/request_msgs.h > create mode 100644 tools/asinfo/syscall_interface.c > create mode 100644 tools/asinfo/syscall_interface.h > > diff --git a/Makefile.am b/Makefile.am > index 2a477f68..a4a287ae 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -35,7 +35,7 @@ endif > if HAVE_MX32_RUNTIME > TESTS_MX32 = tests-mx32 > endif > -SUBDIRS = . tests $(TESTS_M32) $(TESTS_MX32) > +SUBDIRS = . tests $(TESTS_M32) $(TESTS_MX32) tools > > bin_PROGRAMS = strace > man_MANS = strace.1 > diff --git a/configure.ac b/configure.ac > index f02b71a0..acd878d0 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -828,6 +828,8 @@ AC_CONFIG_FILES([Makefile > tests-m32/Makefile > tests-mx32/Makefile > strace.1 > + tools/Makefile > + tools/asinfo/Makefile > strace.spec > debian/changelog]) > AC_OUTPUT > diff --git a/tools/Makefile.am b/tools/Makefile.am > new file mode 100644 > index 00000000..f1c75cfb > --- /dev/null > +++ b/tools/Makefile.am > @@ -0,0 +1,28 @@ > +# Automake input for strace tools. > +# > +# Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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..19650aba > --- /dev/null > +++ b/tools/asinfo/Makefile.am > @@ -0,0 +1,65 @@ > +# 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 = \ > + arch_definitions.h \ > + arch_includes.h \ > + arch_interface.c \ > + arch_interface.h \ > + arch_personalities.h \ > + asinfo.c \ > + dispatchers.c \ > + dispatchers.h \ > + error_interface.c \ > + error_interface.h \ > + ../../error_prints.c \ > + ../../error_prints.h \ > + ../../macros.h \ > + request_msgs.h \ > + syscall_interface.c \ > + syscall_interface.h \ > + ../../sysent_shorthand_defs.h \ > + ../../sysent_shorthand_undefs.h \ > + ../../xmalloc.c \ > + ../../xmalloc.h \ > + #end of asinfo_SOURCES > diff --git a/tools/asinfo/arch_definitions.h > b/tools/asinfo/arch_definitions.h new file mode 100644 > index 00000000..3e1896fa > --- /dev/null > +++ b/tools/asinfo/arch_definitions.h > @@ -0,0 +1,70 @@ > +/* [],[bfin/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(blackfin, 32bit, > PASS({}), PASS({"blackfin", > "bfin"}) ), +/* [],[ia64/syscallent.h],[0,0] > */ +ARCH_DESC_DEFINE(ia64, 64bit, > PASS({}), > PASS({"ia64"}) ), +/* > [],[m86k/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(m68k, 32bit, > PASS({}), > PASS({"m68k"}) ), +/* > [],[sparc64/syscallent.h],[0,0] */ +ARCH_DESC_DEFINE(sparc64, > 64bit, > PASS({ARCH_sparc_32bit}), > PASS({"sparc64"}) ), +/* > [],[sparc/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(sparc, 32bit, > PASS({}), > PASS({"sparc"}) ), +/* > [],[metag/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(metag, 32bit, > PASS({}), > PASS({"metag"}) ), +/* > [LINUX_MIPSN64],[dummy.h,mips/syscallent-compat.h,mips/syscallent-n64.h],[0,0] > */ +ARCH_DESC_DEFINE(mips64, n64, > PASS({ARCH_mips64_n32, ARCH_mips_o32}), > PASS({"mips64", "mips64le"}) ), +/* > [LINUX_MIPSN32],[dummy.h,mips/syscallent-compat.h,mips/syscallent-n32.h],[0,0] > */ +ARCH_DESC_DEFINE(mips64, n32, > PASS({ARCH_mips_o32}), > PASS({}) ), +/* > [LINUX_MIPSO32],[dummy.h,mips/syscallent-compat.h,mips/syscallent-o32.h],[0,0] > */ +ARCH_DESC_DEFINE(mips, o32, > PASS({}), PASS({"mips", > "mipsle"}) ), +/* > [],[alpha/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(alpha, 64bit, > PASS({}), > PASS({"alpha"}) ), +/* > [],[powerpc64/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(ppc64, 64bit, > PASS({ARCH_ppc_32bit}), PASS({"ppc64", > "ppc64le", "powerpc64"}) ), +/* > [],[powerpc/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(ppc, 32bit, > PASS({}), PASS({"ppc", > "ppcle", "powerpc"}) ), +/* > [],[aarch64/syscallent.h],[0,0] */ +ARCH_DESC_DEFINE(aarch64, > 64bit, > PASS({ARCH_arm_eabi}), > PASS({"aarch64", "arm64"}) ), +/* > [!__ARM_EABI__],[arm/syscallent.h],[ARM_FIRST_SHUFFLED_SYSCALL,ARM_LAST_SPECIAL_SYSCALL] > */ +ARCH_DESC_DEFINE(arm, oabi, > PASS({ARCH_arm_eabi}), > PASS({"arm"}) ), +/* > [__ARM_EABI__],[arm/syscallent.h],[ARM_FIRST_SHUFFLED_SYSCALL,ARM_LAST_SPECIAL_SYSCALL] > */ +ARCH_DESC_DEFINE(arm, eabi, > PASS({}), > PASS({}) ), +/* > [],[avr32/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(avr32, 32bit, > PASS({}), > PASS({"avr32"}) ), +/* > [],[arc/syscallent.h],[0,0] */ +ARCH_DESC_DEFINE(arc, > 32bit, > PASS({}), > PASS({"arc"}) ), +/* > [],[s390x/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(s390x, 64bit, > PASS({}), > PASS({"s390x"}) ), +/* > [],[s390/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(s390, 32bit, > PASS({}), > PASS({"s390"}) ), +/* > [],[hppa/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(hppa, 32bit, > PASS({}), PASS({"parisc", > "hppa"}) ), +/* [],[sh64/syscallent.h],[0,0] > */ +ARCH_DESC_DEFINE(sh64, 64bit, > PASS({}), > PASS({"sh64"}) ), +/* > [],[sh/syscallent.h],[0,0] */ +ARCH_DESC_DEFINE(sh, > 32bit, > PASS({}), > PASS({"sh"}) ), +/* > [],[x86_64/syscallent.h],[0,0] */ +ARCH_DESC_DEFINE(x86_64, > 64bit, PASS({ARCH_x86_64_x32, ARCH_x86_32bit}), > PASS({"x86_64", "amd64", "EM64T"}) ), +/* > [],[x86_64/syscallent1.h],[0,0] */ +ARCH_DESC_DEFINE(x86_64, > x32, > PASS({ARCH_x86_32bit}), > PASS({}) ), +/* > [],[i386/syscallent.h],[0,0] */ +ARCH_DESC_DEFINE(x86, > 32bit, > PASS({}), PASS({"x86", "i386", > "i486", "i586", "i686"}) ), +/* > [],[crisv10/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(cris, 32bit, > PASS({}), PASS({"cris", > "crisv10"}) ), +/* > [],[crisv32/syscallent.h],[0,0] */ +ARCH_DESC_DEFINE(crisv32, > 32bit, > PASS({}), > PASS({"crisv32"}) ), +/* > [],[tile/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(tile, 64bit, > PASS({ARCH_tile_32bit}), PASS({"tile", > "tilegx"}) ), +/* > [],[tile/syscallent1.h],[0,0] */ > +ARCH_DESC_DEFINE(tile, 32bit, > PASS({}), > PASS({"tilepro"}) ), +/* > [],[microblaze/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(microblaze, 32bit, > PASS({}), > PASS({"microblaze"}) ), +/* > [],[nios2/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(nios2, 32bit, > PASS({}), > PASS({"nios2"}) ), +/* > [],[or1k/syscallent.h],[0,0] */ +ARCH_DESC_DEFINE(openrisc, > 32bit, > PASS({}), PASS({"openrisc", > "or1k"}) ), +/* [],[xtensa/syscallent.h],[0,0] > */ +ARCH_DESC_DEFINE(xtensa, 32bit, > PASS({}), > PASS({"xtensa"}) ), +/* > [],[riscv/syscallent.h],[0,0] */ > +ARCH_DESC_DEFINE(riscv, 64bit, > PASS({ARCH_riscv_32bit}), > PASS({"riscv"}) ), +/* > [],[riscv/syscallent1.h],[0,0] */ > +ARCH_DESC_DEFINE(riscv, 32bit, > PASS({}), > PASS({}) ) diff --git > a/tools/asinfo/arch_includes.h b/tools/asinfo/arch_includes.h new > file mode 100644 index 00000000..e73a8328 --- /dev/null +++ > b/tools/asinfo/arch_includes.h @@ -0,0 +1,272 @@ +/* ARCH_blackfin */ > +static const struct_sysent blackfin_32bit_sysent[] = { > + #include "bfin/syscallent.h" > +}; > +static const int blackfin_32bit_usr1 = 0; > +const int blackfin_32bit_usr2 = 0; > +/* ARCH_ia64 */ > +struct_sysent ia64_64bit_sysent[] = { > + #include "ia64/syscallent.h" > +}; > +static const int ia64_64bit_usr1 = 0; > +static const int ia64_64bit_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_m68k */ > +static const struct_sysent m68k_32bit_sysent[] = { > + #include "m68k/syscallent.h" > +}; > +static const int m68k_32bit_usr1 = 0; > +static const int m68k_32bit_usr2 = 0; > +/* ARCH_sparc64 64bit ABI */ > +static const struct_sysent sparc64_64bit_sysent[] = { > + #include "sparc64/syscallent.h" > +}; > +static const int sparc64_64bit_usr1 = 0; > +static const int sparc64_64bit_usr2 = 0; > +/* ARCH_sparc and 32bit ABI */ > +static const struct_sysent sparc_32bit_sysent[] = { > + #include "sparc/syscallent.h" > +}; > +static const int sparc_32bit_usr1 = 0; > +static const int sparc_32bit_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_metag */ > +static const struct_sysent metag_32bit_sysent[] = { > + #include "metag/syscallent.h" > +}; > +static const int metag_32bit_usr1 = 0; > +static const int metag_32bit_usr2 = 0; > +/* ARCH_mips n64 ABI */ > +#ifndef LINUX_MIPSN64 > +# define LINUX_MIPSN64 1 > +# define NOW_DEFINED 1 > +#endif > +static const struct_sysent mips64_n64_sysent[] = { > + #include "dummy.h" > + #include "mips/syscallent-compat.h" > + #include "mips/syscallent-n64.h" > +}; > +#ifdef NOW_DEFINED > +# undef LINUX_MIPSN32 > +# undef NOW_DEFINED > +#endif > +static const int mips64_n64_usr1 = 0; > +static const int mips64_n64_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_mips n32 ABI */ > +#ifndef LINUX_MIPSN32 > +# define LINUX_MIPSN32 1 > +# define NOW_DEFINED 1 > +#endif > +static const struct_sysent mips64_n32_sysent[] = { > + #include "dummy.h" > + #include "mips/syscallent-compat.h" > + #include "mips/syscallent-n32.h" > +}; > +#ifdef NOW_DEFINED > +# undef LINUX_MIPSN32 > +# undef NOW_DEFINED > +#endif > +static const int mips64_n32_usr1 = 0; > +static const int mips64_n32_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_mips o32 ABI */ > +#ifndef LINUX_MIPSO32 > +# define LINUX_MIPSO32 1 > +# define NOW_DEFINED 1 > +#endif > +static const struct_sysent mips_o32_sysent[] = { > + #include "dummy.h" > + #include "mips/syscallent-compat.h" > + #include "mips/syscallent-o32.h" > +}; > +#ifdef NOW_DEFINED > +# undef LINUX_MIPSO32 > +# undef NOW_DEFINED > +#endif > +static const int mips_o32_usr1 = 0; > +static const int mips_o32_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_alpha */ > +static const struct_sysent alpha_64bit_sysent[] = { > + #include "alpha/syscallent.h" > +}; > +static const int alpha_64bit_usr1 = 0; > +static const int alpha_64bit_usr2 = 0; > +/* ARCH_ppc64 64bit ABI */ > +static const struct_sysent ppc64_64bit_sysent[] = { > + #include "powerpc64/syscallent.h" > +}; > +static const int ppc64_64bit_usr1 = 0; > +static const int ppc64_64bit_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_ppc and 32bit */ > +static const struct_sysent ppc_32bit_sysent[] = { > + #include "powerpc/syscallent.h" > +}; > +static const int ppc_32bit_usr1 = 0; > +static const int ppc_32bit_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_aarch64 64bit ABI */ > +static const struct_sysent aarch64_64bit_sysent[] = { > + #include "aarch64/syscallent.h" > +}; > +static const int aarch64_64bit_usr1 = 0; > +static const int aarch64_64bit_usr2 = 0; > +/* ARCH_arm OABI*/ > +#ifdef __ARM_EABI__ > +# undef __ARM_EABI__ > +# define NOW_UNDEFINED 1 > +#endif > +static const struct_sysent arm_oabi_sysent[] = { > + #include "arm/syscallent.h" > +}; > +static const int arm_oabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL; > +static const int arm_oabi_usr2 = ARM_LAST_SPECIAL_SYSCALL; > +#undef ARM_FIRST_SHUFFLED_SYSCALL > +#undef ARM_LAST_SPECIAL_SYSCALL > +#undef SYS_socket_subcall > +#ifdef NOW_UNDEFINED > +# define __ARM_EABI__ 1 > +# undef NOW_UNDEFINED > +#endif > +/* ARCH_arm EABI*/ > +#ifndef __ARM_EABI__ > +# define __ARM_EABI__ 1 > +# define NOW_DEFINED 1 > +#endif > +static const struct_sysent arm_eabi_sysent[] = { > + #include "arm/syscallent.h" > +}; > +static const int arm_eabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL; > +static const int arm_eabi_usr2 = ARM_LAST_SPECIAL_SYSCALL; > +#undef ARM_FIRST_SHUFFLED_SYSCALL > +#undef ARM_LAST_SPECIAL_SYSCALL > +#ifdef NOW_DEFINED > +# undef __ARM_EABI__ > +# undef NOW_DEFINED > +#endif > +/* ARCH_avr32 */ > +static const struct_sysent avr32_32bit_sysent[] = { > + #include "avr32/syscallent.h" > +}; > +static const int avr32_32bit_usr1 = 0; > +static const int avr32_32bit_usr2 = 0; > +/* ARCH_arc */ > +static const struct_sysent arc_32bit_sysent[] = { > + #include "arc/syscallent.h" > +}; > +static const int arc_32bit_usr1 = 0; > +static const int arc_32bit_usr2 = 0; > +/* ARCH_s390x */ > +static const struct_sysent s390x_64bit_sysent[] = { > + #include "s390x/syscallent.h" > +}; > +static const int s390x_64bit_usr1 = 0; > +static const int s390x_64bit_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_s390 */ > +static const struct_sysent s390_32bit_sysent[] = { > + #include "s390/syscallent.h" > +}; > +static const int s390_32bit_usr1 = 0; > +static const int s390_32bit_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_hppa */ > +static const struct_sysent hppa_32bit_sysent[] = { > + #include "hppa/syscallent.h" > +}; > +static const int hppa_32bit_usr1 = 0; > +static const int hppa_32bit_usr2 = 0; > +/* ARCH_sh64 */ > +static const struct_sysent sh64_64bit_sysent[] = { > + #include "sh64/syscallent.h" > +}; > +static const int sh64_64bit_usr1 = 0; > +static const int sh64_64bit_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_sh */ > +static const struct_sysent sh_32bit_sysent[] = { > + #include "sh/syscallent.h" > +}; > +static const int sh_32bit_usr1 = 0; > +static const int sh_32bit_usr2 = 0; > +/* ARCH_x86_64 64bit ABI mode */ > +static const struct_sysent x86_64_64bit_sysent[] = { > + #include "x86_64/syscallent.h" > +}; > +static const int x86_64_64bit_usr1 = 0; > +static const int x86_64_64bit_usr2 = 0; > +/* ARCH_x86_64 x32 ABI mode */ > +static const struct_sysent x86_64_x32_sysent[] = { > + #include "x86_64/syscallent2.h" > +}; > +static const int x86_64_x32_usr1 = 0; > +static const int x86_64_x32_usr2 = 0; > +/* ARCH_x86 */ > +static const struct_sysent x86_32bit_sysent[] = { > + #include "i386/syscallent.h" > +}; > +static const int x86_32bit_usr1 = 0; > +static const int x86_32bit_usr2 = 0; > +/* ARCH_cris */ > +static struct_sysent cris_32bit_sysent[] = { > + #include "crisv10/syscallent.h" > +}; > +static const int cris_32bit_usr1 = 0; > +static const int cris_32bit_usr2 = 0; > +/* ARCH_crisv32 */ > +static const struct_sysent crisv32_32bit_sysent[] = { > + #include "crisv32/syscallent.h" > +}; > +static const int crisv32_32bit_usr1 = 0; > +static const int crisv32_32bit_usr2 = 0; > +#undef SYS_socket_subcall > +/* ARCH_tile 64bit ABI mode */ > +static const struct_sysent tile_64bit_sysent[] = { > + #include "tile/syscallent.h" > +}; > +static const int tile_64bit_usr1 = 0; > +static const int tile_64bit_usr2 = 0; > +/* ARCH_tile 32bit ABI mode */ > +static const struct_sysent tile_32bit_sysent[] = { > + #include "tile/syscallent1.h" > +}; > +static const int tile_32bit_usr1 = 0; > +static const int tile_32bit_usr2 = 0; > +/* ARCH_microblaze */ > +static const struct_sysent microblaze_32bit_sysent[] = { > + #include "microblaze/syscallent.h" > +}; > +static const int microblaze_32bit_usr1 = 0; > +static const int microblaze_32bit_usr2 = 0; > +/* ARCH_nios2 */ > +static const struct_sysent nios2_32bit_sysent[] = { > + #include "nios2/syscallent.h" > +}; > +static const int nios2_32bit_usr1 = 0; > +static const int nios2_32bit_usr2 = 0; > +/* ARCH_openrisc */ > +struct_sysent openrisc_32bit_sysent[] = { > + #include "or1k/syscallent.h" > +}; > +static const int openrisc_32bit_usr1 = 0; > +static const int openrisc_32bit_usr2 = 0; > +/* ARCH_xtensa */ > +static const struct_sysent xtensa_32bit_sysent[] = { > + #include "xtensa/syscallent.h" > +}; > +static const int xtensa_32bit_usr1 = 0; > +static const int xtensa_32bit_usr2 = 0; > +/* ARCH_riscv 64bit ABI mode */ > +static const struct_sysent riscv_64bit_sysent[] = { > + #include "riscv/syscallent.h" > +}; > +static const int riscv_64bit_usr1 = 0; > +static const int riscv_64bit_usr2 = 0; > +/* ARCH_riscv 32bit ABI mode */ > +static const struct_sysent riscv_32bit_sysent[] = { > + #include "riscv/syscallent1.h" > +}; > +static const int riscv_32bit_usr1 = 0; > +static const int riscv_32bit_usr2 = 0; > diff --git a/tools/asinfo/arch_interface.c > b/tools/asinfo/arch_interface.c new file mode 100644 > index 00000000..7aaca8a6 > --- /dev/null > +++ b/tools/asinfo/arch_interface.c > @@ -0,0 +1,603 @@ > +/* > + * Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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. */ +#include "sysent_shorthand_defs.h" > + > +/* For the current functionality there is no need > + to use sen and (*sys_func)() fields in sysent struct */ > +#define SEN(syscall_name) 0, NULL > + > +/* Generated file based on arch_definitions.h */ > +#include "arch_includes.h" > + > +/* Now undef them since short defines cause wicked namespace > pollution. */ +#include "sysent_shorthand_undefs.h" > + > +#define PASS(...) __VA_ARGS__ > +#define ARCH_DESC_DEFINE(arch, mode, comp_pers, arch_aliases) \ > + [ARCH_##arch##_##mode] = { \ > + .pers = ARCH_##arch##_##mode, > \ > + .arch_name = arch_aliases, \ > + .abi_mode = #mode, \ > + .abi_mode_len = ARRAY_SIZE(#arch) - > 1, \ > + .compat_pers = comp_pers, \ > + .max_scn = > ARRAY_SIZE(arch##_##mode##_sysent), \ > + .syscall_list = > arch##_##mode##_sysent, \ > + .user_num1 = &arch##_##mode##_usr1, \ > + .user_num2 = &arch##_##mode##_usr2, \ > + } > + > +/* Generate array of arch_descriptors for each personality */ > +const struct arch_descriptor architectures[] = { > + #include "arch_definitions.h" > +}; > + > +#undef ARCH_DESC_DEFINE > +#undef PASS > + > +struct arch_service * > +al_create(unsigned capacity) > +{ > + ARCH_LIST_DEFINE(as) = NULL; > + > + if (!capacity) > + return NULL; > + as = xcalloc(sizeof(*as), 1); > + as->arch_list = xcalloc(sizeof(*(as->arch_list)), capacity); > + as->flag = xcalloc(sizeof(*(as->flag)), capacity); > + as->err = es_create(); > + as->capacity = capacity; > + as->next_free = 0; > + return as; > +} > + > +int > +al_push(struct arch_service *m, const struct arch_descriptor > *element) +{ > + if (m->next_free >= m->capacity) > + return -1; > + m->arch_list[m->next_free] = element; > + m->flag[m->next_free] = AD_FLAG_EMPTY; > + m->next_free++; > + return 0; > +} > + > +static inline int > +al_is_index_ok(struct arch_service *m, unsigned index) > +{ > + if (index >= m->next_free) > + return -1; > + return 0; > +} > + > +int > +al_set_flag(struct arch_service *m, unsigned index, int flag) > +{ > + if (al_is_index_ok(m, index) == 0) { > + m->flag[index] = flag; > + return 0; > + } > + return -1; > +} > + > +int > +al_add_flag(struct arch_service *m, unsigned index, int flag) > +{ > + if (al_is_index_ok(m, index) == 0) { > + m->flag[index] = m->flag[index] | flag; > + return 0; > + } > + return -1; > +} > + > +int > +al_sub_flag(struct arch_service *m, unsigned index, int flag) > +{ > + if (al_is_index_ok(m, index) == 0) { > + m->flag[index] = m->flag[index] & ~flag; > + return 0; > + } > + return -1; > +} > + > +const struct arch_descriptor * > +al_get(struct arch_service *m, unsigned index) > +{ > + if (al_is_index_ok(m, index) != 0) > + return NULL; > + return m->arch_list[index]; > +} > + > +unsigned int > +al_size(struct arch_service *m) > +{ > + return m->next_free; > +} > + > +void > +al_free(struct arch_service *m) > +{ > + free(m->arch_list); > + free(m->flag); > + es_free(m->err); > + free(m); > +} > + > +struct error_service *al_err(struct arch_service *m) > +{ > + return m->err; > +} > + > +enum arch_pers > +al_pers(struct arch_service *m, unsigned index) > +{ > + const struct arch_descriptor *elem = al_get(m, index); > + > + return (elem ? elem->pers : ARCH_no_pers); > +} > + > +const char ** > +al_arch_name(struct arch_service *m, unsigned index) > +{ > + const struct arch_descriptor *elem = al_get(m, index); > + > + return (elem ? (const char **)elem->arch_name : NULL); > +} > + > +enum arch_pers * > +al_cpers(struct arch_service *m, unsigned index) > +{ > + const struct arch_descriptor *elem = al_get(m, index); > + > + return (elem ? (enum arch_pers *)elem->compat_pers : NULL); > +} > + > +const char * > +al_abi_mode(struct arch_service *m, unsigned index) > +{ > + const struct arch_descriptor *elem = al_get(m, index); > + > + return (elem ? elem->abi_mode : NULL); > +} > + > +int > +al_abi_mode_len(struct arch_service *m, unsigned index) > +{ > + const struct arch_descriptor *elem = al_get(m, index); > + > + return (elem ? elem->abi_mode_len : -1); > +} > + > +int > +al_flag(struct arch_service *m, unsigned index) > +{ > + int status = al_is_index_ok(m, index); > + > + return (!status ? m->flag[index] : -1); > +} > + > +int > +al_psize(struct arch_service *m) > +{ > + int i; > + int a_size = al_size(m); > + int psize = 0; > + > + for (i = 0; i < a_size; i++) > + if (al_flag(m, i) & AD_FLAG_PRINT) > + psize++; > + return psize; > +} > + > +int > +al_arch_name_len(struct arch_service *m, unsigned index, int > delim_len) +{ > + const char **arch_name = NULL; > + int i; > + int final_len = 0; > + > + while (!(al_flag(m, index) & AD_FLAG_MPERS)) > + index--; > + arch_name = al_arch_name(m, index); > + for (i = 0; (arch_name[i] != NULL) && (i < MAX_ALIASES); > i++) { > + final_len += strlen(arch_name[i]); > + final_len += delim_len; > + } > + final_len -= delim_len; > + return final_len; > +} > + > +int > +al_syscall_impl(struct arch_service *m, unsigned index) > +{ > + const struct arch_descriptor *elem = al_get(m, index); > + int i = 0; > + int count = 0; > + > + if (elem == NULL) > + return -1; > + for (i = 0; i < elem->max_scn; i++) { > + if (elem->syscall_list[i].sys_name && > + !(elem->syscall_list[i].sys_flags & > + TRACE_INDIRECT_SUBCALL)) > + count++; > + } > + return count; > +} > + > +/* This method is purposed to count the supported ABI modes for the > given > + arch */ > +int > +al_get_abi_modes(struct arch_service *m, unsigned index) > +{ > + const struct arch_descriptor *elem = al_get(m, index); > + int i = 0; > + int abi_count = 1; > + > + if (!elem) > + return -1; > + for (i = 0; i < MAX_ALT_ABIS; i++) > + if (elem->compat_pers[i] != ARCH_no_pers) > + abi_count++; > + return abi_count; > +} > + > +/* This method is purposed to find next one name of the same > architecture. > + For instance, x86_64 = amd64 */ > +const char * > +al_next_alias(struct arch_service *m, unsigned index) > +{ > + static int next_alias = -1; > + static const char **arch_name = NULL; > + static unsigned lindex = 0; > + > + if (lindex != index) { > + lindex = index; > + next_alias = -1; > + } > + if (al_pers(m, index) == ARCH_no_pers) > + return NULL; > + if (next_alias == -1) { > + next_alias = 0; > + while (!(al_flag(m, index) & AD_FLAG_MPERS)) > + index--; > + arch_name = al_arch_name(m, index); > + } else > + next_alias++; > + if (next_alias >= MAX_ALIASES || arch_name[next_alias] == > NULL) { > + next_alias = -1; > + return NULL; > + } > + return arch_name[next_alias]; > +} > + > +/* This method is purposed to return next one compat personality of > the > + same architecture */ > +enum arch_pers > +al_next_cpers(struct arch_service *m, unsigned index) > +{ > + static int next_pers = -1; > + enum arch_pers *a_pers = al_cpers(m, index); > + static unsigned lindex = 0; > + > + if (al_pers(m, index) == ARCH_no_pers) > + return ARCH_no_pers; > + if (lindex != index) { > + lindex = index; > + next_pers = -1; > + } > + if (next_pers == -1) > + next_pers = 0; > + else > + next_pers++; > + if (next_pers >= MAX_ALT_ABIS || > + a_pers[next_pers] == ARCH_no_pers) { > + next_pers = -1; > + return ARCH_no_pers; > + } > + return a_pers[next_pers]; > +} > + > +enum impl_type > +al_ipc_syscall(struct arch_service *m, unsigned index) > +{ > + const struct arch_descriptor *elem = al_get(m, index); > + int i; > + enum impl_type impl_buf = IMPL_int; > + > + for (i = 0; i < elem->max_scn; i++) { > + if (elem->syscall_list[i].sys_name == NULL) > + continue; > + /* It is enough to find just semop sybcall */ > + if (!strcmp(elem->syscall_list[i].sys_name, > "semop")) { > + if (!(elem->syscall_list[i].sys_flags & > + TRACE_INDIRECT_SUBCALL)) > + impl_buf = IMPL_ext; > + else if (impl_buf == IMPL_ext) > + impl_buf = IMPL_int_ext; > + else > + impl_buf = IMPL_int; > + } > + } > + return impl_buf; > +} > + > +enum impl_type > +al_sck_syscall(struct arch_service *m, unsigned index) > +{ > + const struct arch_descriptor *elem = al_get(m, index); > + int i; > + enum impl_type impl_buf = IMPL_int; > + > + for (i = 0; i < elem->max_scn; i++) { > + if (elem->syscall_list[i].sys_name == NULL) > + continue; > + /* It is enough to find just socket sybcall */ > + if (!strcmp(elem->syscall_list[i].sys_name, > "socket")) { > + if (!(elem->syscall_list[i].sys_flags & > + TRACE_INDIRECT_SUBCALL)) > + impl_buf = IMPL_ext; > + else if (impl_buf == IMPL_ext) > + impl_buf = IMPL_int_ext; > + else > + impl_buf = IMPL_int; > + } > + } > + return impl_buf; > +} > + > +/* This method is purposed to create extended list of architectures > */ +struct arch_service * > +al_create_filled(void) > +{ > + static const int architectures_size = > ARRAY_SIZE(architectures) - 1; > + ARCH_LIST_DEFINE(as) = al_create(architectures_size); > + ARCH_LIST_DEFINE(f_as); > + enum arch_pers cpers; > + int esize = 0; > + const char **arch_name = NULL; > + int i; > + > + /* Push and calculate size of extended table */ > + for (i = 0; i < architectures_size; i++) { > + al_push(as, &(architectures[i + 1])); > + arch_name = al_arch_name(as, i); > + if (arch_name[0] != NULL) > + esize += al_get_abi_modes(as, i); > + } > + f_as = al_create(esize); > + /* Fill extended teble */ > + for (i = 0; i < architectures_size; i++) { > + arch_name = al_arch_name(as, i); > + if (arch_name[0] == NULL) > + continue; > + al_push(f_as, al_get(as, i)); > + al_add_flag(f_as, al_size(f_as) - 1, AD_FLAG_MPERS); > + while ((cpers = al_next_cpers(as, i)) != > ARCH_no_pers) > + al_push(f_as, &(architectures[cpers])); > + } > + free(as); > + return f_as; > +} > + > +/* To look up arch in arch_descriptor array */ > +int > +al_mark_matches(struct arch_service *m, char *arch_str) > +{ > + int arch_match = -1; > + char *match_pointer = NULL; > + const char *a_name = NULL; > + int al_size_full = al_size(m); > + unsigned prev_arch_len = 0; > + int i; > + int a_abi; > + > + if (arch_str == NULL) > + return -1; > + /* Here we find the best match for arch_str in architecture > list. > + Best match means here that we have to find the longest > name of > + architecture in a_full_list with arch_str substring, > beginning > + from the first letter */ > + for (i = 0; i < al_size_full; i++) { > + if (!(al_flag(m, i) & AD_FLAG_MPERS)) > + continue; > + while ((a_name = al_next_alias(m, i)) != NULL) { > + match_pointer = strstr(arch_str, a_name); > + if (match_pointer == NULL || > match_pointer != arch_str) > + continue; > + if (arch_match == -1 || > + strlen(a_name) > prev_arch_len) { > + prev_arch_len = strlen(a_name); > + arch_match = i; > + } > + } > + } > + if (arch_match == -1) > + return -1; > + /* Now we find all ABI modes related to the architecture */ > + if ((a_abi = al_get_abi_modes(m, arch_match)) == -1) > + return -1; > + for (i = arch_match; i < (arch_match + a_abi); i++) > + al_add_flag(m, i, AD_FLAG_PRINT); > + return 0; > +} > + > +/* Join all architectures from 'f' and architectures with > AD_FLAG_PRINT > + from 's' arch_service structures */ > +struct arch_service * > +al_join_print(struct arch_service *f, struct arch_service *s) > +{ > + int size1 = (f ? al_size(f) : 0); > + int psize2 = al_psize(s); > + int size2 = al_size(s); > + int i; > + int start_point = 0; > + ARCH_LIST_DEFINE(final) = al_create(size1 + psize2); > + > + for (i = 0; i < size2; i++) > + if (al_flag(s, i) & AD_FLAG_PRINT) { > + start_point = i; > + break; > + } > + for (i = 0; i < size1; i++) { > + al_push(final, al_get(f, i)); > + al_set_flag(final, i, al_flag(f, i)); > + } > + for (i = 0; i < psize2; i++) { > + al_push(final, al_get(s, start_point + i)); > + al_set_flag(final, size1 + i , al_flag(s, > start_point + i)); > + al_sub_flag(s, start_point + i, AD_FLAG_PRINT); > + } > + return final; > +} > + > +/* To avoid duplication of for(;;) construction */ > +void > +al_unmark_all(struct arch_service *m, int flag) > +{ > + int a_size = al_size(m); > + int i; > + > + for (i = 0; i < a_size; i++) > + al_sub_flag(m, i, flag); > +} > + > +/* Select one compatible personality in range of one architecture */ > +int > +al_mark_pers4arch(struct arch_service *m, unsigned index, const char > *abi_mode) +{ > + unsigned i = index; > + > + while (!(al_flag(m, i) & AD_FLAG_MPERS) || (i == index)) { > + if (strcmp(abi_mode, "all") == 0) { > + al_add_flag(m, i, AD_FLAG_PRINT); > + i++; > + if ((al_is_index_ok(m, i)) || > + (al_flag(m, i) & AD_FLAG_MPERS)) > + return 0; > + else > + continue; > + } > + if (strcmp(al_abi_mode(m, i), abi_mode) == 0) { > + al_add_flag(m, i, AD_FLAG_PRINT); > + return 0; > + } > + i++; > + } > + return -1; > +} > + > +void > +al_dump(struct arch_service *m) > +{ > + static const char *title[] = { > + "N", > + "Architecture name", > + "ABI mode", > + /* Implemented syscalls */ > + "IMPL syscalls", > + /* IPC implementation */ > + "IPC IMPL", > + /* SOCKET implementation */ > + "SOCKET IMPL" > + }; > + int title_len[] = { > + 0, > + strlen(title[1]), > + strlen(title[2]), > + strlen(title[3]), > + strlen(title[4]), > + strlen(title[5]), > + }; > + static const char *impl_st[] = { > + "external", > + "internal", > + "int/ext" > + }; > + static const char *delim = "/"; > + int i = 0; > + int N = 0; > + int temp_len = 0; > + int arch_size = al_size(m); > + int arch_psize = al_psize(m); > + const char *next_alias = NULL; > + char *whole_arch_name; > + > + /* Calculate length of the column with the number of > architectures */ > + for (i = 1; arch_psize/i != 0; i *= 10) > + title_len[0]++; > + for (i = 0; i < arch_size; i++) { > + if (!(al_flag(m, i) & AD_FLAG_PRINT)) > + continue; > + /* Calculate length of the column with the > + architectures name */ > + temp_len = al_arch_name_len(m, i, strlen(delim)); > + if (temp_len > title_len[1]) > + title_len[1] = temp_len; > + /* Calculate length of the column with the ABI mode > */ > + if (al_abi_mode_len(m, i) > title_len[2]) > + title_len[2] = al_abi_mode_len(m, i); > + } > + > + whole_arch_name = xcalloc(title_len[1], > sizeof(*whole_arch_name)); > + /* Output title */ > + printf("| %*s | %*s | %*s | %*s | %*s | %*s |\n", > + title_len[0], title[0], title_len[1], title[1], > + title_len[2], title[2], title_len[3], title[3], > + title_len[4], title[4], title_len[5], title[5]); > + /* Output architectures */ > + for (i = 0; i < arch_size; i++) { > + if (!(al_flag(m, i) & AD_FLAG_PRINT)) > + continue; > + printf("| %*u | ", title_len[0], N + 1); > + /* Put all the same arch back together */ > + next_alias = al_next_alias(m, i); > + strcat(whole_arch_name, next_alias); > + while ((next_alias = al_next_alias(m, i)) != NULL) { > + strcat(whole_arch_name, delim); > + strcat(whole_arch_name, next_alias); > + } > + printf("%*s | ", title_len[1], whole_arch_name); > + printf("%*s | ", title_len[2], al_abi_mode(m, i)); > + printf("%*d | ", title_len[3], al_syscall_impl(m, > i)); > + printf("%*s | ", title_len[4], > impl_st[al_ipc_syscall(m, i)]); > + printf("%*s |\n", title_len[5], > impl_st[al_sck_syscall(m, i)]); > + memset(whole_arch_name, 0, title_len[1]); > + N++; > + } > + free(whole_arch_name); > +} > diff --git a/tools/asinfo/arch_interface.h > b/tools/asinfo/arch_interface.h new file mode 100644 > index 00000000..aedf9e04 > --- /dev/null > +++ b/tools/asinfo/arch_interface.h > @@ -0,0 +1,156 @@ > +/* > + * The arch_interface.h is purposed to interact with the basic data > structure > + * based on arch_descriptor struct. Mainly this set of methods are > used by > + * arch_dispatcher. > + * > + * Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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 "error_interface.h" > +#include "sysent.h" > + > +/* Type implementaion of syscall, internal means as a subcall, > + external means a separate syscall, this enum is purposed for > + well-known ipc and socket subcall group */ > +enum impl_type { > + IMPL_ext, > + IMPL_int, > + IMPL_int_ext > +}; > + > +/* Names of personalities > + * arch_pers = ARCH_ + kernel_kernel/other_name + abi_mode */ > +enum arch_pers { > + #include "arch_personalities.h" > +}; > + > +#define MAX_ALIASES 6 > +#define MAX_ALT_ABIS 3 > + > +struct arch_descriptor { > + enum arch_pers pers; > + const char *arch_name[MAX_ALIASES]; > + const char *abi_mode; > + const int abi_mode_len; > + enum arch_pers compat_pers[MAX_ALT_ABIS]; > + const int max_scn; > + const struct_sysent *syscall_list; > + /* In the most cases these fields are purposed to store > specific for > + given arch constants, for instance, > ARM_FIRST_SHUFFLED_SYSCALL */ > + const int *user_num1; > + const int *user_num2; > +}; > + > +#define AD_FLAG_EMPTY 0 > +/* to hide some abi modes belonging to one architecture */ > +#define AD_FLAG_PRINT (1 << 0) > +/* main personality, like x86_64 64bit */ > +#define AD_FLAG_MPERS (1 << 1) > + > +/* To provide push-back interface with arch_list */ > +struct arch_service { > + /* immutable field */ > + const struct arch_descriptor **arch_list; > + /* User flags for each arch_descriptor */ > + int *flag; > + struct error_service *err; > + unsigned capacity; > + unsigned next_free; > +}; > + > +#define ARCH_LIST_DEFINE(name) \ > + struct arch_service *(name) > + > +/* Push-back interface is purposed to simplify interaction with > + arch_service struct > + NOTE: al - architecture list */ > + > +/* base methods */ > +struct arch_service *al_create(unsigned capacity); > + > +int al_push(struct arch_service *m, const struct arch_descriptor > *element); + > +int al_set_flag(struct arch_service *m, unsigned index, int flag); > + > +int al_add_flag(struct arch_service *m, unsigned index, int flag); > + > +int al_sub_flag(struct arch_service *m, unsigned index, int flag); > + > +const struct arch_descriptor *al_get(struct arch_service *m, > unsigned index); + > +unsigned int al_size(struct arch_service *m); > + > +void al_free(struct arch_service *m); > + > +struct error_service *al_err(struct arch_service *m); > + > +/* methods returning fields with error check */ > +enum arch_pers al_pers(struct arch_service *m, unsigned index); > + > +const char **al_arch_name(struct arch_service *m, unsigned index); > + > +enum arch_pers *al_cpers(struct arch_service *m, unsigned index); > + > +const char *al_abi_mode(struct arch_service *m, unsigned index); > + > +int al_abi_mode_len(struct arch_service *m, unsigned index); > + > +int al_flag(struct arch_service *m, unsigned index); > + > +/* calculating methods */ > +int al_psize(struct arch_service *m); > + > +int al_arch_name_len(struct arch_service *m, unsigned index, int > delim_len); + > +int al_syscall_impl(struct arch_service *m, unsigned index); > + > +int al_get_abi_modes(struct arch_service *m, unsigned index); > + > +const char *al_next_alias(struct arch_service *m, unsigned index); > + > +enum arch_pers al_next_cpers(struct arch_service *m, unsigned index); > + > +enum impl_type al_ipc_syscall(struct arch_service *m, unsigned > index); + > +enum impl_type al_sck_syscall(struct arch_service *m, unsigned > index); + > +struct arch_service *al_create_filled(void); > + > +int al_mark_matches(struct arch_service *m, char *arch_str); > + > +struct arch_service *al_join_print(struct arch_service *f, > + struct arch_service *s); > + > +void al_unmark_all(struct arch_service *m, int flag); > + > +int al_mark_pers4arch(struct arch_service *m, unsigned index, > + const char *abi_mode); > + > +void al_dump(struct arch_service *m); > + > +#endif /* !ASINFO_ARCH_INTERFACE */ > diff --git a/tools/asinfo/arch_personalities.h > b/tools/asinfo/arch_personalities.h new file mode 100644 > index 00000000..9499c5aa > --- /dev/null > +++ b/tools/asinfo/arch_personalities.h > @@ -0,0 +1,36 @@ > +ARCH_no_pers, > +ARCH_blackfin_32bit, > +ARCH_ia64_64bit, > +ARCH_m68k_32bit, > +ARCH_sparc64_64bit, > +ARCH_sparc_32bit, > +ARCH_metag_32bit, > +ARCH_mips64_n64, > +ARCH_mips64_n32, > +ARCH_mips_o32, > +ARCH_alpha_64bit, > +ARCH_ppc64_64bit, > +ARCH_ppc_32bit, > +ARCH_aarch64_64bit, > +ARCH_arm_oabi, > +ARCH_arm_eabi, > +ARCH_avr32_32bit, > +ARCH_arc_32bit, > +ARCH_s390x_64bit, > +ARCH_s390_32bit, > +ARCH_hppa_32bit, > +ARCH_sh64_64bit, > +ARCH_sh_32bit, > +ARCH_x86_64_64bit, > +ARCH_x86_64_x32, > +ARCH_x86_32bit, > +ARCH_cris_32bit, > +ARCH_crisv32_32bit, > +ARCH_tile_64bit, > +ARCH_tile_32bit, > +ARCH_microblaze_32bit, > +ARCH_nios2_32bit, > +ARCH_openrisc_32bit, > +ARCH_xtensa_32bit, > +ARCH_riscv_64bit, > +ARCH_riscv_32bit > diff --git a/tools/asinfo/asinfo.1 b/tools/asinfo/asinfo.1 > new file mode 100644 > index 00000000..e69de29b > diff --git a/tools/asinfo/asinfo.c b/tools/asinfo/asinfo.c > new file mode 100644 > index 00000000..e71b672b > --- /dev/null > +++ b/tools/asinfo/asinfo.c > @@ -0,0 +1,295 @@ > +/* > + * The asinfo main source. The asinfo tool is purposed to operate > + * with system calls and provide information about it. > + * > + * Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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 <ctype.h> > +#include <limits.h> > +#include <stdarg.h> > +#include <stdbool.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include "arch_interface.h" > +#include "dispatchers.h" > +#include "error_interface.h" > +#include "error_prints.h" > +#include "macros.h" > +#include "request_msgs.h" > +#include "syscall_interface.h" > +#include "xmalloc.h" > + > +#ifndef HAVE_PROGRAM_INVOCATION_NAME > +char *program_invocation_name; > +#endif > + > +static void > +usage(void) > +{ > + puts( > + "usage: asinfo (--set-arch arch | --get-arch | > --list-arch)\n" > + " [--set-abi abi | --list-abi]\n" > + " or: asinfo [(--set-arch arch | --get-arch) > [--set-abi abi]]\n" > + " (--get-sysc num | name) | > (--get-nargs num | name)\n" > + "\n" > + "Architecture:\n" > + " --set-arch arch use architecture ARCH for > further operations\n" > + " argument format: > arch1,arch2,...\n" > + " --get-arch use architecture returned by > uname for further operations\n" > + " --list-arch print out all architectures > supported by strace\n" > + " (combined use list-arch and any > ABI option is permitted)\n" > + "\n" > + "ABI:\n" > + " --set-abi abi use application binary interface > ABI for further operations\n" > + " ('all' can be used as ABI to use > all compatible personalities\n" > + " for corresponding > architecture)\n" > + " argument format: abi1,abi2,...\n" > + " --list-abi print out all ABIs for specified > architecture\n" > + "\n" > + "System call:\n" > + " --get-sysc num print name of system call with > the NUM number\n" > + " --get-sysc name print number of all system calls > with NAME substring\n" > + " --get-nargs num get number of arguments of > system call with the NUM number\n" > + " --get-nargs name get number of arguments of > system calls with NAME substring\n" > + " --list-sysc print out all system calls for > specified architecture and ABI\n" > + "\n" > + "Miscellaneous:\n" > + " -h print help message\n"); > + exit(0); > +} > + > +void > +die(void) > +{ > + exit(1); > +} > + > +static int > +is_more1bit(unsigned int num) > +{ > + return !(num & (num - 1)); > +} > + > +static unsigned > +strpar2req(char *option) > +{ > + /* Convertion table to store string with options */ > + static const char *options[] = { > + [SD_REQ_GET_SYSC_BIT] = "--get-sysc", > + [SD_REQ_GET_NARGS_BIT] = "--get-nargs", > + [SD_REQ_GET_LIST_BIT] = "--list-sysc", > + [AD_REQ_SET_ARCH_BIT] = "--set-arch", > + [AD_REQ_GET_ARCH_BIT] = "--get-arch", > + [AD_REQ_LIST_ARCH_BIT] = "--list-arch", > + [ABD_REQ_SET_ABI_BIT] = "--set-abi", > + [ABD_REQ_LIST_ABI_BIT] = "--list-abi", > + [SERV_REQ_HELP_BIT] = "-h", > + }; > + unsigned i; > + > + for (i = 0; i < ARRAY_SIZE(options); i++) { > + if (options[i] && strcmp(option, options[i]) == 0) > + return i; > + } > + return SERV_REQ_ERROR_BIT; > +} > + > +static char ** > +arg2list(char *argument) > +{ > + int i; > + int len = strlen(argument); > + int occur = 1; > + char **arg_list; > + > + for (i = 0; i < len; i++) { > + if (argument[i] == ',') { > + if (i == 0 || i == len - 1 || argument[i + > 1] == ',') > + return NULL; > + occur++; > + } > + } > + arg_list = xcalloc(sizeof(*arg_list), occur + 1); > + for (i = 0; i < occur; i++) { > + arg_list[i] = argument; > + argument = strchr(argument, ','); > + if (argument) { > + *argument = '\0'; > + argument++; > + } > + } > + return arg_list; > +} > + > +/* The purpose of this function is to convert input parameters to > number with > + set bits, where each bit means specific work mode. Moreover, it > checks input > + for correctness and outputs error messages in case of wrong input > */ +static unsigned > +command_dispatcher(int argc, char *argv[], char **args[]) > +{ > + int i; > + unsigned final_req = 0; > + unsigned temp_req = 0; > + int mult_arch = 0; > + int mult_abi = 0; > + unsigned non_req_arg = AD_REQ_GET_ARCH | AD_REQ_LIST_ARCH | > + ABD_REQ_LIST_ABI | SD_REQ_GET_LIST; > + > + if (!program_invocation_name || !*program_invocation_name) { > + static char name[] = "asinfo"; > + program_invocation_name = > + (argv[0] && *argv[0]) ? argv[0] : name; > + } > + > + /* Try to find help option first */ > + for (i = 1; i < argc; i++) { > + if (strpar2req(argv[i]) == SERV_REQ_HELP_BIT) > + usage(); > + } > + /* For now, is is necessary to convert string parameter to > number of > + request and make basic check */ > + for (i = 1; i < argc; i++) { > + if ((temp_req = strpar2req(argv[i])) == > SERV_REQ_ERROR_BIT) > + error_msg_and_help("unrecognized option > '%s'", > + argv[i]); > + if (final_req & 1 << temp_req) > + error_msg_and_help("parameter '%s' has been > used " > + "more than once", > argv[i]); > + if (!((1 << temp_req) & non_req_arg) && > + (i + 1 >= argc || strlen(argv[i + 1]) == 0 || > + strpar2req(argv[i + 1]) != SERV_REQ_ERROR_BIT)) > + error_msg_and_help("parameter '%s' requires " > + "argument", argv[i]); > + final_req |= 1 << temp_req; > + if (!((1 << temp_req) & non_req_arg)) { > + if ((args[temp_req] = arg2list(argv[i + > 1])) != NULL) { > + i++; > + continue; > + } > + error_msg_and_help("argument '%s' of '%s' > parameter " > + "has a wrong format", > + argv[i + 1], argv[i]); > + } > + } > + if (args[AD_REQ_SET_ARCH_BIT]) > + while (args[AD_REQ_SET_ARCH_BIT][mult_arch] != NULL) > + mult_arch++; > + if (args[ABD_REQ_SET_ABI_BIT]) > + while (args[ABD_REQ_SET_ABI_BIT][mult_abi] != NULL) > + mult_abi++; > + /* Second, final_req should be logically checked */ > + /* More than one option from one request group couldn't be > set */ > + if ((is_more1bit(final_req & SD_REQ_MASK) == 0) || > + (is_more1bit(final_req & AD_REQ_MASK) == 0) || > + (is_more1bit(final_req & ABD_REQ_MASK) == 0) || > + (is_more1bit(final_req & FD_REQ_MASK) == 0)) > + error_msg_and_help("exclusive parameters"); > + /* Check on mutually exclusive options chain */ > + /* If at least one syscall option has been typed, therefore > + arch_options couldn't be list-arch and > + abi_option couldn't be list-abi */ > + if ((final_req & SD_REQ_MASK) && > + (((final_req & AD_REQ_MASK) && (final_req & > AD_REQ_LIST_ARCH)) || > + ((final_req & ABD_REQ_MASK) && (final_req & > ABD_REQ_LIST_ABI)))) > + error_msg_and_help("wrong parameters"); > + /* list-arch couldn't be used with any abi options */ > + if ((final_req & AD_REQ_LIST_ARCH) && > + (final_req & ABD_REQ_MASK)) > + error_msg_and_help("'--list-arch' cannot be used > with any " > + "ABI parameters"); > + /* ABI requests could be used just in a combination with arch > + requests */ > + if ((final_req & ABD_REQ_MASK) && > + !(final_req & AD_REQ_MASK)) > + error_msg_and_help("ABI parameters could be used > only with " > + "architecture parameter"); > + /* set-abi must be used in case of multiple arch */ > + if ((mult_arch > 1) && !(final_req & ABD_REQ_MASK)) > + error_msg_and_help("ABI modes cannot be > automatically " > + "detected for multiple " > + "architectures"); > + /* set-abi and set-arch have to take the same number of args > */ > + if ((final_req & AD_REQ_SET_ARCH) && (final_req & > ABD_REQ_SET_ABI) && > + (mult_arch != mult_abi)) > + error_msg_and_help("each architecture needs > respective " > + "ABI mode"); > + return final_req; > +} > + > +static char ** > +seek_sc_arg(char **input_args[]) > +{ > + int i; > + > + for (i = SD_REQ_GET_SYSC_BIT; i < SYSCALL_REQ_BIT_LAST; i++) > + if (input_args[i] != NULL) > + return input_args[i]; > + return NULL; > +} > + > +int > +main(int argc, char *argv[]) > +{ > + ARCH_LIST_DEFINE(arch_list); > + SYSCALL_LIST_DEFINE(sc_list); > + /* This array is purposed to store arguments for options in > the > + most convenient way */ > + char ***input_args = xcalloc(sizeof(*input_args), > REQ_LAST_BIT); > + unsigned reqs; > + > + /* command_dispatcher turn */ > + reqs = command_dispatcher(argc, argv, input_args); > + if (reqs == 0) > + error_msg_and_help("must have OPTIONS"); > + > + /* arch_dispatcher turn */ > + arch_list = arch_dispatcher(reqs, > input_args[AD_REQ_SET_ARCH_BIT]); > + if (es_error(al_err(arch_list))) > + perror_msg_and_die("%s", > es_get_serror(al_err(arch_list))); > + /* abi_dispatcher turn */ > + abi_dispatcher(arch_list, reqs, > input_args[AD_REQ_SET_ARCH_BIT], > + > input_args[ABD_REQ_SET_ABI_BIT]); > + if (es_error(al_err(arch_list))) > + perror_msg_and_die("%s", > es_get_serror(al_err(arch_list))); > + /* syscall_dispatcher turn */ > + sc_list = syscall_dispatcher(arch_list, reqs, > seek_sc_arg(input_args)); > + if (es_error(ss_err(sc_list))) > + perror_msg_and_die("%s", > es_get_serror(ss_err(sc_list))); > + /* If we want to get info about only architectures thus we > print out > + architectures, otherwise system calls */ > + if (!(reqs & SD_REQ_MASK)) > + al_dump(arch_list); > + else > + ss_dump(sc_list); > + return 0; > +} > diff --git a/tools/asinfo/dispatchers.c b/tools/asinfo/dispatchers.c > new file mode 100644 > index 00000000..c01c8e04 > --- /dev/null > +++ b/tools/asinfo/dispatchers.c > @@ -0,0 +1,219 @@ > +/* > + * Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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 "syscall_interface.h" > +#include "sysent.h" > +#include "xmalloc.h" > + > +struct arch_service * > +arch_dispatcher(unsigned request_type, char *arch[]) > +{ > + struct utsname info_uname; > + int i; > + ARCH_LIST_DEFINE(arch_list) = al_create_filled(); > + ARCH_LIST_DEFINE(arch_final) = NULL; > + > + /* If user don't type any option in ARCH_REQ group, it means > + get current arch */ > + if ((request_type & AD_REQ_GET_ARCH) || > + (!(request_type & AD_REQ_MASK))) { > + uname(&info_uname); > + if (al_mark_matches(arch_list, info_uname.machine) > == -1) { > + es_set_error(al_err(arch_list), > AD_UNSUP_ARCH); > + es_set_option(al_err(arch_list), > info_uname.machine, > + NULL, NULL); > + goto fail; > + } > + arch_final = al_join_print(arch_final, arch_list); > + al_unmark_all(arch_final, AD_FLAG_PRINT); > + free(arch_list); > + goto done; > + } > + > + if (request_type & AD_REQ_SET_ARCH) { > + for (i = 0; arch[i] != NULL; i++) { > + if (al_mark_matches(arch_list, arch[i]) == > -1) { > + es_set_error(al_err(arch_list), > AD_UNSUP_ARCH); > + es_set_option(al_err(arch_list), > arch[i], > + NULL, NULL); > + goto fail; > + } > + arch_final = al_join_print(arch_final, > arch_list); > + } > + al_unmark_all(arch_final, AD_FLAG_PRINT); > + al_free(arch_list); > + goto done; > + } > + > + if ((request_type & AD_REQ_LIST_ARCH)) { > + int a_size = al_size(arch_list); > + for (i = 0; i < a_size; i++) { > + al_add_flag(arch_list, i, AD_FLAG_PRINT); > + } > + arch_final = arch_list; > + goto done; > + } > +fail: > + return arch_list; > +done: > + return arch_final; > +} > + > +int > +abi_dispatcher(struct arch_service *a_serv, unsigned request_type, > + char *arch[], char *abi[]) > +{ > + int i = 0; > + enum arch_pers pers; > + int arch_size = 0; > + int a_pos = 0; > + > + arch_size = al_size(a_serv); > + /* The strace package could be compiled as 32bit app on 64bit > + architecture, therefore asinfo has to detect it and print > out > + corresponding personality. Frankly speaking, it is > necessary to > + detect strace package personality when it is possible */ > + if (!(request_type & ABD_REQ_MASK) && > + !(request_type & AD_REQ_LIST_ARCH)) { > + pers = al_pers(a_serv, a_pos); > + switch (pers) { > +#if defined(MIPS) > + case ARCH_mips_o32: > + case ARCH_mips64_n64: > + al_mark_pers4arch(a_serv, a_pos, > +#if defined(LINUX_MIPSO32) > + "o32" > +#elif defined(LINUX_MIPSN32) > + "n32" > +#elif defined(LINUX_MIPSN64) > + "n64" > +#endif > + ); > + break; > +#endif > +#if defined(ARM) > + case ARCH_arm_oabi: > + al_mark_pers4arch(a_serv, a_pos, > +#if defined(__ARM_EABI__) || !defined(ENABLE_ARM_OABI) > + "eabi" > +#else > + "oabi" > +#endif > + ); > + break; > +#endif > +#if defined(AARCH64) > + case ARCH_aarch64_64bit: > + al_mark_pers4arch(a_serv, a_pos, > +#if defined(__ARM_EABI__) || !defined(ENABLE_ARM_OABI) > + "eabi" > +#else > + "64bit" > +#endif > + ); > + break; > +#endif > +#if defined(X86_64) || defined(X32) > + case ARCH_x86_64_64bit: > + al_mark_pers4arch(a_serv, a_pos, > +#if defined(X86_64) > + "64bit" > +#elif defined(X32) > + "x32" > +#elif defined(I686) > + "32bit" > +#endif > + ); > + break; > +#endif > +#if defined(TILE) > + case ARCH_tile_64bit: > + al_mark_pers4arch(a_serv, a_pos, > +#if defined(__tilepro__) > + "32bit" > +#else > + "64bit" > +#endif > + ); > + break; > +#endif > + default: > + if (arch_size == 1) { > + al_add_flag(a_serv, a_pos, > AD_FLAG_PRINT); > + goto done; > + } > + es_set_error(al_err(a_serv), > ABI_CANNOT_DETECT); > + es_set_option(al_err(a_serv), arch[0], NULL, > NULL); > + } > + goto done; > + } > + > + if (request_type & ABD_REQ_LIST_ABI) { > + for (i = 0; i < arch_size; i++) > + al_add_flag(a_serv, i, AD_FLAG_PRINT); > + goto done; > + } > + > + if (request_type & ABD_REQ_SET_ABI) { > + for (i = 0; abi[i] != NULL; i++) { > + if (!al_mark_pers4arch(a_serv, a_pos, > abi[i])) { > + a_pos += al_get_abi_modes(a_serv, > a_pos); > + continue; > + } > + es_set_error(al_err(a_serv), ABI_WRONG4ARCH); > + es_set_option(al_err(a_serv), arch[i], > abi[i], NULL); > + break; > + } > + } > +done: > + return 0; > +} > + > +struct syscall_service * > +syscall_dispatcher(struct arch_service *arch, int request_type, char > *arg[]) +{ > + SYSCALL_LIST_DEFINE(syscall_list) = ss_create(arch, > request_type); + > + if (request_type & SD_REQ_MASK) { > + ss_update_sc_num(syscall_list); > + ss_mark_matches(syscall_list, arg[0]); > + } > + > + return syscall_list; > +} > diff --git a/tools/asinfo/dispatchers.h b/tools/asinfo/dispatchers.h > new file mode 100644 > index 00000000..2a566935 > --- /dev/null > +++ b/tools/asinfo/dispatchers.h > @@ -0,0 +1,48 @@ > +/* > + * The dispatchers.h contains all necessary functions to perform main > + * work in the asinfo tool. > + * > + * Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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 "syscall_interface.h" > + > +/* The function is purposed to provide correct list of architectures > */ +struct arch_service *arch_dispatcher(unsigned request_type, char > *arch[]); + > +/* Final arch filtering based on personality */ > +int abi_dispatcher(struct arch_service *a_serv, unsigned > request_type, > + char *arch[], char *abi[]); > + > +/* The last stage of main filtering */ > +struct syscall_service *syscall_dispatcher(struct arch_service *arch, > + int request_type, char > *arg[]); + > +#endif /* !STRACE_ASINFO_COM_SCALLENT */ > diff --git a/tools/asinfo/error_interface.c > b/tools/asinfo/error_interface.c new file mode 100644 > index 00000000..c3f68c67 > --- /dev/null > +++ b/tools/asinfo/error_interface.c > @@ -0,0 +1,109 @@ > +/* > + * Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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 <stdlib.h> > +#include <string.h> > +#include <stdio.h> > + > +#include "error_interface.h" > +#include "xmalloc.h" > + > +static const char *errors[] = { > + [AD_UNSUP_ARCH_BIT] = "architecture '%s' is > unsupported", > + [ABI_CANNOT_DETECT_BIT] = "ABI mode for '%s' > architecture cannot be " > + "automatically detected", > + [ABI_WRONG4ARCH_BIT] = "architecture '%s' does not > have ABI mode " > + "'%s'", > + [SD_WRONG_NUMBER_BIT] = "wrong syscall number", > + [SD_NUM_NO_EXIST_BIT] = "syscall with that number was > not " > + "implemented", > + [SD_NAME_NO_EXIST_BIT] = "syscall with that name > doesn't exist" +}; > + > +struct error_service * > +es_create(void) > +{ > + struct error_service *err = xcalloc(sizeof(*err), 1); > + > + return err; > +} > + > +enum common_error > +es_error(struct error_service *e) > +{ > + return e->last_error; > +} > + > +void > +es_set_error(struct error_service *e, enum common_error error) > +{ > + e->last_error = error; > +} > + > +void > +es_set_option(struct error_service *e, char *arch, char *abi, char > *sc) +{ > + if (arch) { > + if (e->last_arch) > + free(e->last_arch); > + e->last_arch = xcalloc(sizeof(*(e->last_arch)), > + strlen(arch) + 1); > + strcpy(e->last_arch, arch); > + } > + if (abi) { > + if (e->last_abi) > + free(e->last_abi); > + e->last_abi = xcalloc(sizeof(*(e->last_abi)), > strlen(abi) + 1); > + strcpy(e->last_abi, abi); > + } > + if (sc) { > + if (e->last_sc) > + free(e->last_sc); > + e->last_sc = xcalloc(sizeof(*(e->last_sc)), > strlen(sc) + 1); > + strcpy(e->last_sc, sc); > + } > +} > + > +const char * > +es_get_serror(struct error_service *e) > +{ > + int err = 1 << e->last_error; > + if (err & ERROR_ARCH_MASK) > + sprintf(e->string, errors[e->last_error], > e->last_arch); > + else if (err & ERROR_NO_ARG_MASK) > + sprintf(e->string, "%s", errors[e->last_error]); > + else if (err & ERROR_ARCH_ABI_MASK) > + sprintf(e->string, errors[e->last_error], > e->last_arch, > + e->last_abi); > + return (const char *)(e->string); > +} > + > +void > +es_free(struct error_service *e) > +{ > + free(e); > +} > diff --git a/tools/asinfo/error_interface.h > b/tools/asinfo/error_interface.h new file mode 100644 > index 00000000..7bd509d3 > --- /dev/null > +++ b/tools/asinfo/error_interface.h > @@ -0,0 +1,95 @@ > +/* > + * As each dispatcher has a wide range of possible errors, there is > need > + * use separate and basic error interface. > + * > + * Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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 ASINFO_ERROR_INTERFACE > +#define ASINFO_ERROR_INTERFACE > + > +/* errors which using last_arch */ > +enum error_arch { > + AD_UNSUP_ARCH_BIT, > + ABI_CANNOT_DETECT_BIT, > + > + ERROR_ARCH_LAST > +}; > + > +enum error_no_arg { > + SD_WRONG_NUMBER_BIT = ERROR_ARCH_LAST, > + SD_NUM_NO_EXIST_BIT, > + SD_NAME_NO_EXIST_BIT, > + > + ERROR_NO_ARG_LAST > +}; > + > +enum error_arch_abi { > + ABI_WRONG4ARCH_BIT = ERROR_NO_ARG_LAST, > + > + ERROR_ARCH_ABI_LAST > +}; > + > +#define ENUM_FLAG(name) name = name##_BIT > +enum common_error { > + /* arch dispatcher range */ > + ENUM_FLAG(AD_UNSUP_ARCH), > + /* abi dipatcher range */ > + ENUM_FLAG(ABI_CANNOT_DETECT), > + ENUM_FLAG(ABI_WRONG4ARCH), > + /* syscall dispatcher range */ > + ENUM_FLAG(SD_WRONG_NUMBER), > + ENUM_FLAG(SD_NUM_NO_EXIST), > + ENUM_FLAG(SD_NAME_NO_EXIST) > +}; > +#undef ENUM_FLAG > + > +#define BITMASK(hi, lo) ((1 << (hi)) - (1 << (lo))) > +#define ERROR_ARCH_MASK BITMASK(ERROR_ARCH_LAST, 0) > +#define ERROR_NO_ARG_MASK BITMASK(ERROR_NO_ARG_LAST, ERROR_ARCH_LAST) > +#define ERROR_ARCH_ABI_MASK BITMASK(ERROR_ARCH_ABI_LAST, > ERROR_NO_ARG_LAST) + > +struct error_service { > + char string[255]; > + enum common_error last_error; > + char *last_arch; > + char *last_abi; > + char *last_sc; > +}; > + > +struct error_service *es_create(void); > + > +enum common_error es_error(struct error_service *s); > + > +void es_set_error(struct error_service *s, enum common_error se); > + > +void es_set_option(struct error_service *e, char *arch, char *abi, > char *sc); + > +const char *es_get_serror(struct error_service *e); > + > +void es_free(struct error_service *e); > + > +#endif /* !ASINFO_ERROR_INTERFACE */ > diff --git a/tools/asinfo/request_msgs.h b/tools/asinfo/request_msgs.h > new file mode 100644 > index 00000000..fb5ef670 > --- /dev/null > +++ b/tools/asinfo/request_msgs.h > @@ -0,0 +1,97 @@ > +/* > + * The request_msgs are purposed to set the general mode of work, in > + * particular, the work of main dispatchers. > + * > + * Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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, which, in turn, could be combined > + */ > +enum syscall_req_bit { > + SD_REQ_GET_SYSC_BIT, > + SD_REQ_GET_NARGS_BIT, > + SD_REQ_GET_LIST_BIT, > + > + SYSCALL_REQ_BIT_LAST > +}; > + > +enum arch_req_bit { > + AD_REQ_SET_ARCH_BIT = SYSCALL_REQ_BIT_LAST, > + AD_REQ_GET_ARCH_BIT, > + AD_REQ_LIST_ARCH_BIT, > + > + ARCH_REQ_BIT_LAST > +}; > + > +enum abi_req_bit { > + ABD_REQ_SET_ABI_BIT = ARCH_REQ_BIT_LAST, > + ABD_REQ_LIST_ABI_BIT, > + > + ABD_REQ_BIT_LAST > +}; > + > +enum fd_req_bit { > + FD_REQ_SET_BASE_FILTER_BIT = ABD_REQ_BIT_LAST, > + > + FD_REQ_BIT_LAST > +}; > + > +enum serv_req_bit { > + SERV_REQ_HELP_BIT = FD_REQ_BIT_LAST, > + SERV_REQ_ERROR_BIT, > + > + SERV_REQ_BIT_LAST > +}; > + > +#define ENUM_FLAG(name) name = 1 << name##_BIT > +enum req_type { > + ENUM_FLAG(SD_REQ_GET_SYSC), > + ENUM_FLAG(SD_REQ_GET_NARGS), > + ENUM_FLAG(SD_REQ_GET_LIST), > + ENUM_FLAG(AD_REQ_SET_ARCH), > + ENUM_FLAG(AD_REQ_GET_ARCH), > + ENUM_FLAG(AD_REQ_LIST_ARCH), > + ENUM_FLAG(ABD_REQ_SET_ABI), > + ENUM_FLAG(ABD_REQ_LIST_ABI), > + ENUM_FLAG(FD_REQ_SET_BASE_FILTER), > + ENUM_FLAG(SERV_REQ_HELP), > + ENUM_FLAG(SERV_REQ_ERROR) > +}; > +#undef ENUM_FLAG > + > +#define BITMASK(hi, lo) ((1 << (hi)) - (1 << (lo))) > +#define REQ_LAST_BIT SERV_REQ_BIT_LAST > +#define SD_REQ_MASK BITMASK(SYSCALL_REQ_BIT_LAST, 0) > +#define AD_REQ_MASK BITMASK(ARCH_REQ_BIT_LAST, SYSCALL_REQ_BIT_LAST) > +#define ABD_REQ_MASK BITMASK(ABD_REQ_BIT_LAST, ARCH_REQ_BIT_LAST) > +#define FD_REQ_MASK BITMASK(FD_REQ_BIT_LAST, ABD_REQ_BIT_LAST) > +#define SERV_REQ_MASK BITMASK(SERV_REQ_BIT_LAST, FD_REQ_BIT_LAST) > + > +#endif /* !STRACE_ASINFO_REQ_MSGS */ > diff --git a/tools/asinfo/syscall_interface.c > b/tools/asinfo/syscall_interface.c new file mode 100644 > index 00000000..3eb6b65d > --- /dev/null > +++ b/tools/asinfo/syscall_interface.c > @@ -0,0 +1,323 @@ > +/* > + * Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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. > + */ > + > +#include <stdbool.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include "arch_interface.h" > +#include "error_interface.h" > +#include "syscall_interface.h" > +#include "request_msgs.h" > +#include "xmalloc.h" > + > +struct syscall_service * > +ss_create(struct arch_service *m, int request_type) > +{ > + int i; > + int arch_list_size = al_size(m); > + const struct arch_descriptor *ad = NULL; > + struct syscall_service *ss = NULL; > + > + /* Function calling syscall_service should make sure, > + that there is just one arch with AD_FLAG_PRINT flag */ > + for (i = 0; i < arch_list_size; i++) > + if (al_flag(m, i) & AD_FLAG_PRINT) > + ad = al_get(m, i); > + ss = xcalloc(sizeof(*ss), 1); > + ss->flag = xcalloc(sizeof(*(ss->flag)), ad->max_scn); > + ss->real_sys_num = xcalloc(sizeof(*(ss->real_sys_num)), > ad->max_scn); > + ss->arch = ad; > + ss->request_type = request_type; > + ss->err = al_err(m); > + return ss; > +} > + > +struct error_service * > +ss_err(struct syscall_service *m) > +{ > + return m->err; > +} > + > +int > +ss_flag(struct syscall_service *s, int num) > +{ > + if (num >= s->arch->max_scn) > + return -1; > + return s->flag[num]; > +} > + > +int > +ss_set_flag(struct syscall_service *s, int num, int flag) > +{ > + if (num >= s->arch->max_scn) > + return -1; > + s->flag[num] = flag; > + return 0; > +} > + > +enum input_type > +ss_it(struct syscall_service *s) > +{ > + return s->it; > +} > + > +void > +ss_set_input(struct syscall_service *s, enum input_type it) > +{ > + s->it = it; > +} > + > +int > +ss_max_scn(struct syscall_service *s) > +{ > + return s->arch->max_scn; > +} > + > +int > +ss_real_num(struct syscall_service *s, int num) > +{ > + if (num >= s->arch->max_scn) > + return -1; > + return s->real_sys_num[num]; > +} > + > +int > +ss_set_real_num(struct syscall_service *s, int num, int real_num) > +{ > + if (num >= s->arch->max_scn) > + return -1; > + s->real_sys_num[num] = real_num; > + return 0; > +} > + > +const char * > +ss_syscall_name(struct syscall_service *s, int num) > +{ > + return s->arch->syscall_list[num].sys_name; > +} > + > +int > +ss_syscall_flag(struct syscall_service *s, int num) > +{ > + return s->arch->syscall_list[num].sys_flags; > +} > + > +unsigned > +ss_syscall_nargs(struct syscall_service *s, int num) > +{ > + return s->arch->syscall_list[num].nargs; > +} > + > +int > +ss_user_num1(struct syscall_service *s) > +{ > + return *(s->arch->user_num1); > +} > + > +int > +ss_user_num2(struct syscall_service *s) > +{ > + return *(s->arch->user_num2); > +} > + > +void > +ss_free(struct syscall_service *s) > +{ > + free(s->flag); > + free(s->real_sys_num); > + free(s); > +} > + > +int > +ss_find_num(struct syscall_service *s, int real_num) > +{ > + int i; > + int max_scn = ss_max_scn(s); > + > + for (i = 0; i < max_scn; i++) > + if (ss_real_num(s, i) == real_num) > + return i; > + return -1; > +} > + > +bool > +ss_is_syscall_valid(struct syscall_service *s, int num) > +{ > + if ((num >= s->arch->max_scn) || (num < 0)) > + return 0; > + return ss_syscall_name(s, num) && > + !(ss_syscall_flag(s, num) & TRACE_INDIRECT_SUBCALL); > +} > + > +int > +ss_mark_matches(struct syscall_service *s, char *arg) > +{ > + int sc_real_number; > + int sc_num; > + char sym = 0; > + char *sc_name = NULL; > + int sc_count = 0; > + int i = 0; > + int max_scn = ss_max_scn(s); > + > + /* In case of --list-sysc */ > + if (arg == NULL) { > + for (i = 0; i < max_scn; i++) > + if (ss_is_syscall_valid(s, i)) > + ss_set_flag(s, i, SS_FLAG_PRINT); > + return 0; > + } > + > + /* Is it a number? */ > + if ((sscanf(arg, "%d%c", &sc_real_number, &sym) == 0) || > sym != '\0') > + sc_name = arg; > + else if (sc_real_number < 0) { > + es_set_error(ss_err(s), SD_WRONG_NUMBER); > + return -1; > + } > + > + /* In case of name -> find arg as a substring and mark */ > + if (sc_name != NULL) { > + for (i = 0; i < max_scn; i++) > + if (ss_is_syscall_valid(s, i) && > + strstr(ss_syscall_name(s, i), > sc_name) != NULL) { > + ss_set_flag(s, i, SS_FLAG_PRINT); > + sc_count++; > + } > + if (sc_count == 0) { > + es_set_error(ss_err(s), SD_NAME_NO_EXIST); > + return -1; > + } > + ss_set_input(s, IT_STRING); > + return 0; > + } > + /* In case of number -> check and mark */ > + sc_num = ss_find_num(s, sc_real_number); > + if (ss_is_syscall_valid(s, sc_num)) { > + ss_set_flag(s, sc_num, SS_FLAG_PRINT); > + ss_set_input(s, IT_NUMBER); > + return 0; > + } > + es_set_error(ss_err(s), SD_NUM_NO_EXIST); > + return -1; > +} > + > +#ifndef __X32_SYSCALL_BIT > +# define __X32_SYSCALL_BIT 0x40000000 > +#endif > + > +int > +ss_update_sc_num(struct syscall_service *s) > +{ > + int i = 0; > + int max_scn = ss_max_scn(s); > + for (i = 0; i < max_scn; i++) { > + if (!ss_is_syscall_valid(s, i)) { > + ss_set_real_num(s, i, -1); > + continue; > + } > + switch (s->arch->pers) { > + case ARCH_x86_64_x32: > + ss_set_real_num(s, i, i + __X32_SYSCALL_BIT); > + break; > + case ARCH_arm_oabi: > + case ARCH_arm_eabi: > + if (i == ss_user_num1(s)) > + ss_set_real_num(s, i, 0x000ffff0); > + if ((i >= ss_user_num1(s) + 1) && > + (i <= ss_user_num1(s) + ss_user_num2(s) > + 1)) > + ss_set_real_num(s, i, i + 0x000f0000 > - > + > ss_user_num1(s) - 1); > + if (i < ss_user_num1(s)) > + ss_set_real_num(s, i, i); > + break; > + case ARCH_sh64_64bit: > + ss_set_real_num(s, i, i & 0xffff); > + default: > + ss_set_real_num(s, i, i); > + } > + } > + return 0; > +} > + > +void > +ss_dump(struct syscall_service *s) > +{ > + static const char *title[] = { > + "System call name", > + "Syscall num", > + "Nargs", > + }; > + int title_len[] = { > + strlen(title[0]), > + strlen(title[1]), > + strlen(title[2]), > + }; > + int i; > + int max_scn = ss_max_scn(s); > + int temp_len = 0; > + > + /* Update title_len[0] */ > + for (i = 0; i < max_scn; i++) { > + if (!(ss_flag(s, i) & SS_FLAG_PRINT)) > + continue; > + temp_len = strlen(ss_syscall_name(s, i)); > + if (temp_len > title_len[0]) > + title_len[0] = temp_len; > + } > + /* Print title */ > + if (s->request_type & SD_REQ_GET_LIST) > + printf("| %*s | %*s | %*s |\n", title_len[0], > title[0], > + title_len[1], > title[1], > + title_len[2], > title[2]); > + if (s->request_type & SD_REQ_GET_SYSC) > + printf("| %*s | %*s |\n", title_len[0], title[0], > + title_len[1], title[1]); > + if (s->request_type & SD_REQ_GET_NARGS) > + printf("| %*s | %*s |\n", title_len[0], title[0], > + title_len[2], title[2]); > + /* Print out syscall or list of syscalls */ > + for (i = 0; i < max_scn; i++) { > + if (!(ss_flag(s, i) & SS_FLAG_PRINT)) > + continue; > + if (s->request_type & SD_REQ_GET_LIST) > + printf("| %*s | %*d | %*u |\n", > + title_len[0], ss_syscall_name(s, i), > + title_len[1], ss_real_num(s, i), > + title_len[2], ss_syscall_nargs(s, > i)); > + if (s->request_type & SD_REQ_GET_SYSC) > + printf("| %*s | %*d |\n", > + title_len[0], ss_syscall_name(s, i), > + title_len[1], ss_real_num(s, i)); > + if (s->request_type & SD_REQ_GET_NARGS) > + printf("| %*s | %*u |\n", > + title_len[0], ss_syscall_name(s, i), > + title_len[2], ss_syscall_nargs(s, > i)); > + } > +} > diff --git a/tools/asinfo/syscall_interface.h > b/tools/asinfo/syscall_interface.h new file mode 100644 > index 00000000..ae8f2c1e > --- /dev/null > +++ b/tools/asinfo/syscall_interface.h > @@ -0,0 +1,104 @@ > +/* > + * The syscall_interface.h is purposed to interact with the basic > data > + * structure based on arch_descriptor struct. Mainly this set of > methods are > + * used by syscall_dispatcher. > + * > + * Copyright (c) 2017 Edgar A. Kaziakhmedov > <edgar.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_SYSCALL_INTERFACE > +#define ASINFO_SYSCALL_INTERFACE > + > +#include <stdbool.h> > + > +#include "arch_interface.h" > +#include "error_interface.h" > + > +#define SS_FLAG_EMPTY 0 > +#define SS_FLAG_PRINT 1 > + > +enum input_type { > + IT_STRING = 1, > + IT_NUMBER > +}; > + > +struct syscall_service { > + const struct arch_descriptor *arch; > + /* Mutable user flags for each syscall */ > + int *flag; > + int *real_sys_num; > + /* To choose the format while dumping */ > + int request_type; > + /* To detect input type */ > + enum input_type it; > + struct error_service *err; > +}; > + > +#define SYSCALL_LIST_DEFINE(name) \ > + struct syscall_service *(name) > + > +/* base methods */ > +struct syscall_service *ss_create(struct arch_service *m, int > request_type); + > +struct error_service *ss_err(struct syscall_service *m); > + > +int ss_flag(struct syscall_service *s, int num); > + > +int ss_set_flag(struct syscall_service *s, int num, int flag); > + > +enum input_type ss_it(struct syscall_service *s); > + > +void ss_set_input(struct syscall_service *s, enum input_type it); > + > +int ss_max_scn(struct syscall_service *s); > + > +int ss_real_num(struct syscall_service *s, int num); > + > +int ss_set_real_num(struct syscall_service *s, int num, int > real_num); + > +const char *ss_syscall_name(struct syscall_service *s, int num); > + > +int ss_syscall_flag(struct syscall_service *s, int num); > + > +unsigned ss_syscall_nargs(struct syscall_service *s, int num); > + > +int ss_user_num1(struct syscall_service *s); > + > +int ss_user_num2(struct syscall_service *s); > + > +void ss_free(struct syscall_service *s); > + > +/* calculating methods */ > +int ss_find_num(struct syscall_service *s, int real_num); > + > +bool ss_is_syscall_valid(struct syscall_service *s, int num); > + > +int ss_mark_matches(struct syscall_service *s, char *arg); > + > +int ss_update_sc_num(struct syscall_service *s); > + > +void ss_dump(struct syscall_service *s); > + > +#endif /* !ASINFO_SYSCALL_INTERFACE */
pgpdXh5s6ocS5.pgp
Description: OpenPGP digital signature
------------------------------------------------------------------------------ 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