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 */ -- 2.11.0 ------------------------------------------------------------------------------ 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