From: Edgar Kaziakhmedov <edgar.kaziakhme...@virtuzzo.com> The 1.2 version of asinfo tool. The asinfo tool has the following architecture: commnand dispatcher->architecture dispatcher->abi dispatcher-> system call dispatcher->filter dispatcher
As for arch. dispatcher, the asinfo has get-arch, list-arch, set-arch %name_of_arch options, arch_dispatcher is purposed to process them. As for abi dispatcher, the asinfo has get-abi, list-abi, set-abi %name_of_abi options, abi_dispatcher is putposed to process it. As for command_dispatcher, for now it checks all options for correctness. Now, to find out the main principle of working, let’s consider next one case: $ asinfo get-arch Firstly, arch_dispatcher will return the current architecture, based on uname return value, after that in case of no options for abi_dispatcher, AD perceives it as get-abi option and returns corresponding for the set arch value. NOTE: syscall_dispatcher for now is not supported It is worth mentioning that this tool supports almostly all architectures supporting by Linux kernel. * Makefile.am (SUBDIRS): Add tools directory. * configure.ac (AC_CONFIG_FILES): Add Makefile's. * tools/Makefile.am: New file. * tools/asinfo/Makefile.am: New file. * tools/asinfo/dispatchers.h: New file. Prototype abi_dispatcher, arch_dispatcher, and syscall_dispatcher. * tools/asinfo/dispatchers.c: New file. Implement it. * tools/asinfo/arch_interface.h: New file. Prototype methods to simplify work with the list of arch_descriptor. Introduce struct arch_descriptor. * tools/asinfo/arch_interface.c: New file. Implement it. * tools/asinfo/request_msgs.h: New file. Introduce main types of requests. Introduce structures for syscall_dispatcher. * tools/asinfo/asinfo.c: New file. Implement support of all options. * tools/asinfo/asinfo.1: New file. Empty man. Signed-off-by: Edgar Kaziakhmedov <edgar.kaziakhme...@virtuozzo.com> --- Makefile.am | 2 +- configure.ac | 2 + tools/Makefile.am | 28 ++ tools/asinfo/Makefile.am | 56 +++ tools/asinfo/arch_interface.c | 888 ++++++++++++++++++++++++++++++++++++++++++ tools/asinfo/arch_interface.h | 184 +++++++++ tools/asinfo/asinfo.1 | 0 tools/asinfo/asinfo.c | 196 ++++++++++ tools/asinfo/dispatchers.c | 242 ++++++++++++ tools/asinfo/dispatchers.h | 60 +++ tools/asinfo/request_msgs.h | 115 ++++++ 11 files changed, 1772 insertions(+), 1 deletion(-) create mode 100644 tools/Makefile.am create mode 100644 tools/asinfo/Makefile.am create mode 100644 tools/asinfo/arch_interface.c create mode 100644 tools/asinfo/arch_interface.h create mode 100644 tools/asinfo/asinfo.1 create mode 100644 tools/asinfo/asinfo.c create mode 100644 tools/asinfo/dispatchers.c create mode 100644 tools/asinfo/dispatchers.h create mode 100644 tools/asinfo/request_msgs.h diff --git a/Makefile.am b/Makefile.am index da175a27..ac40a8f2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,7 +35,7 @@ endif if HAVE_MX32_RUNTIME TESTS_MX32 = tests-mx32 endif -SUBDIRS = tests $(TESTS_M32) $(TESTS_MX32) +SUBDIRS = tests $(TESTS_M32) $(TESTS_MX32) tools bin_PROGRAMS = strace man_MANS = strace.1 diff --git a/configure.ac b/configure.ac index 0d407aff..ea14e270 100644 --- a/configure.ac +++ b/configure.ac @@ -842,6 +842,8 @@ AC_CONFIG_FILES([Makefile tests/Makefile tests-m32/Makefile tests-mx32/Makefile + tools/Makefile + tools/asinfo/Makefile strace.spec debian/changelog]) AC_OUTPUT diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 00000000..6044e9ae --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,28 @@ +# Automake input for strace tools. +# +# Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.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..19451986 --- /dev/null +++ b/tools/asinfo/Makefile.am @@ -0,0 +1,56 @@ +# Automake input for asinfo. +# +# Copyright (c) 2017 Edgar Kaziakhmedov <e...@linux.com> +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +bin_PROGRAMS = asinfo +man_MANS = asinfo.1 + +OS = linux + +AUTOMAKE_OPTIONS = subdir-objects + +AM_CFLAGS = $(WARN_CFLAGS) +AM_CPPFLAGS = -I$(builddir) \ + -I$(top_builddir)/$(OS) \ + -I$(top_srcdir)/$(OS) \ + -I$(top_builddir) \ + -I$(top_srcdir) +asinfo_CPPFLAGS = $(AM_CPPFLAGS) +asinfo_CFLAGS = $(AM_CFLAGS) + +asinfo_SOURCES = \ + arch_interface.c \ + arch_interface.h \ + asinfo.c \ + dispatchers.c \ + dispatchers.h \ + ../../error_prints.c \ + ../../error_prints.h \ + ../../macros.h \ + requests_msgs.h \ + ../../xmalloc.c \ + ../../xmalloc.h \ + #end of asinfo_SOURCES diff --git a/tools/asinfo/arch_interface.c b/tools/asinfo/arch_interface.c new file mode 100644 index 00000000..6de6b830 --- /dev/null +++ b/tools/asinfo/arch_interface.c @@ -0,0 +1,888 @@ +/* + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhme...@virtuozzo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "arch_interface.h" +#include "defs.h" +#include "macros.h" +#include "xmalloc.h" + +/* Define these shorthand notations to simplify the syscallent files. */ +/* These flags could be useful to print group of syscalls */ +#define TD TRACE_DESC +#define TF TRACE_FILE +#define TI TRACE_IPC +#define TN TRACE_NETWORK +#define TP TRACE_PROCESS +#define TS TRACE_SIGNAL +#define TM TRACE_MEMORY +#define TST TRACE_STAT +#define TLST TRACE_LSTAT +#define TFST TRACE_FSTAT +#define TSTA TRACE_STAT_LIKE +#define TSF TRACE_STATFS +#define TFSF TRACE_FSTATFS +#define TSFA TRACE_STATFS_LIKE +#define NF SYSCALL_NEVER_FAILS +#define MA MAX_ARGS +#define SI STACKTRACE_INVALIDATE_CACHE +#define SE STACKTRACE_CAPTURE_ON_ENTER +#define CST COMPAT_SYSCALL_TYPES + +/* + * For the current functionality there is no need + * to use sen and (*sys_func)() fields in sysent struct + */ +#define SEN(syscall_name) 0, NULL + +/* dummy_sysent is purposed to set syscall_list field in + * inherited architectures */ +struct_sysent dummy_sysent[] = {}; + +/* ARCH_blackfin */ +struct_sysent blackfin_32bit_sysent[] = { + #include "bfin/syscallent.h" +}; +const int blackfin_32bit_usr1 = 0; +const int blackfin_32bit_usr2 = 0; +/* ARCH_ia64 */ +struct_sysent ia64_64bit_sysent[] = { + #include "ia64/syscallent.h" +}; +const int ia64_64bit_usr1 = SYS_socket_subcall; +const int ia64_64bit_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_m68k */ +struct_sysent m68k_32bit_sysent[] = { + #include "m68k/syscallent.h" +}; +const int m68k_32bit_usr1 = SYS_socket_subcall; +const int m68k_32bit_usr2 = 0; +/* ARCH_sparc64 64bit ABI */ +struct_sysent sparc64_64bit_sysent[] = { + #include "sparc64/syscallent.h" +}; +const int sparc64_64bit_usr1 = SYS_socket_subcall; +const int sparc64_64bit_usr2 = 0; +/* ARCH_sparc64 32bit ABI */ +struct_sysent sparc64_32bit_sysent[] = { + #include "sparc64/syscallent1.h" +}; +const int sparc64_32bit_usr1 = SYS_socket_subcall; +const int sparc64_32bit_usr2 = 0; +/* ARCH_sparc */ +struct_sysent sparc_32bit_sysent[] = { + #include "sparc/syscallent.h" +}; +const int sparc_32bit_usr1 = SYS_socket_subcall; +const int sparc_32bit_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_metag */ +struct_sysent metag_32bit_sysent[] = { + #include "metag/syscallent.h" +}; +const int metag_32bit_usr1 = 0; +const int metag_32bit_usr2 = 0; +/* ARCH_mips o32 ABI */ +#ifndef LINUX_MIPSO32 +# define LINUX_MIPSO32 1 +# define NOW_DEFINED 1 +#endif +struct_sysent mips_o32_sysent[] = { + #include "dummy.h" + #include "mips/syscallent-compat.h" + #include "mips/syscallent-o32.h" +}; +#ifdef NOW_DEFINED +# undef LINUX_MIPSO32 +# undef NOW_DEFINED +#endif +const int mips_o32_usr1 = SYS_socket_subcall; +const int mips_o32_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_mips n32 ABI */ +#ifndef LINUX_MIPSN32 +# define LINUX_MIPSN32 1 +# define NOW_DEFINED 1 +#endif +struct_sysent mips_n32_sysent[] = { + #include "dummy.h" + #include "mips/syscallent-compat.h" + #include "mips/syscallent-n32.h" +}; +#ifdef NOW_DEFINED +# undef LINUX_MIPSN32 +# undef NOW_DEFINED +#endif +const int mips_n32_usr1 = SYS_socket_subcall; +const int mips_n32_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_mips n64 ABI */ +#ifndef LINUX_MIPSN64 +# define LINUX_MIPSN64 1 +# define NOW_DEFINED 1 +#endif +struct_sysent mips_n64_sysent[] = { + #include "dummy.h" + #include "mips/syscallent-compat.h" + #include "mips/syscallent-n64.h" +}; +#ifdef NOW_DEFINED +# undef LINUX_MIPSN32 +# undef NOW_DEFINED +#endif +const int mips_n64_usr1 = SYS_socket_subcall; +const int mips_n64_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_alpha */ +struct_sysent alpha_64bit_sysent[] = { + #include "alpha/syscallent.h" +}; +const int alpha_64bit_usr1 = 0; +const int alpha_64bit_usr2 = 0; +/* ARCH_ppc */ +struct_sysent ppc_32bit_sysent[] = { + #include "powerpc/syscallent.h" +}; +const int ppc_32bit_usr1 = SYS_socket_subcall; +const int ppc_32bit_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_ppc64 64bit ABI */ +struct_sysent ppc64_64bit_sysent[] = { + #include "powerpc64/syscallent.h" +}; +const int ppc64_64bit_usr1 = SYS_socket_subcall; +const int ppc64_64bit_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_ppc64 32bit ABI */ +struct_sysent ppc64_32bit_sysent[] = { + #include "powerpc64/syscallent1.h" +}; +const int ppc64_32bit_usr1 = SYS_socket_subcall; +const int ppc64_32bit_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_arm OABI*/ +#ifdef __ARM_EABI__ +# undef __ARM_EABI__ +# define NOW_UNDEFINED 1 +#endif +struct_sysent arm_oabi_sysent[] = { + #include "arm/syscallent.h" +}; +const int arm_oabi_usr1 = SYS_socket_subcall; +const int arm_oabi_usr2 = ARM_FIRST_SHUFFLED_SYSCALL; +#undef ARM_FIRST_SHUFFLED_SYSCALL +#undef SYS_socket_subcall +#ifdef NOW_UNDEFINED +# define __ARM_EABI__ 1 +# undef NOW_UNDEFINED +#endif +/* ARCH_arm EABI*/ +#ifndef __ARM_EABI__ +# define __ARM_EABI__ 1 +# define NOW_DEFINED 1 +#endif +struct_sysent arm_eabi_sysent[] = { + #include "arm/syscallent.h" +}; +const int arm_eabi_usr1 = ARM_FIRST_SHUFFLED_SYSCALL; +const int arm_eabi_usr2 = 0; +#undef ARM_FIRST_SHUFFLED_SYSCALL +#ifdef NOW_DEFINED +# undef __ARM_EABI__ +# undef NOW_DEFINED +#endif +/* ARCH_aarch64 64bit ABI */ +struct_sysent aarch64_64bit_sysent[] = { + #include "aarch64/syscallent.h" +}; +const int aarch64_64bit_usr1 = 0; +const int aarch64_64bit_usr2 = 0; +/* ARCH_aarch64 32bit ABI */ +#ifndef __ARM_EABI__ +# define __ARM_EABI__ 1 +# define NOW_DEFINED 1 +#endif +struct_sysent aarch64_32bit_sysent[] = { + #include "aarch64/syscallent1.h" +}; +const int aarch64_32bit_usr1 = ARM_FIRST_SHUFFLED_SYSCALL; +const int aarch64_32bit_usr2 = ARM_LAST_SPECIAL_SYSCALL; +#undef ARM_FIRST_SHUFFLED_SYSCALL +#undef ARM_LAST_SPECIAL_SYSCALL +#ifdef NOW_DEFINED +# undef __ARM_EABI__ +# undef NOW_DEFINED +#endif +/* ARCH_avr32 */ +struct_sysent avr32_32bit_sysent[] = { + #include "avr32/syscallent.h" +}; +const int avr32_32bit_usr1 = 0; +const int avr32_32bit_usr2 = 0; +/* ARCH_arc */ +struct_sysent arc_32bit_sysent[] = { + #include "arc/syscallent.h" +}; +const int arc_32bit_usr1 = 0; +const int arc_32bit_usr2 = 0; +/* ARCH_s390 */ +struct_sysent s390_32bit_sysent[] = { + #include "s390/syscallent.h" +}; +const int s390_32bit_usr1 = SYS_socket_subcall; +const int s390_32bit_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_s390x */ +struct_sysent s390x_64bit_sysent[] = { + #include "s390x/syscallent.h" +}; +const int s390x_64bit_usr1 = SYS_socket_subcall; +const int s390x_64bit_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_hppa */ +struct_sysent hppa_32bit_sysent[] = { + #include "hppa/syscallent.h" +}; +const int hppa_32bit_usr1 = 0; +const int hppa_32bit_usr2 = 0; +/* ARCH_parisc */ +#define parisc_32bit_sysent dummy_sysent +const int parisc_32bit_usr1 = 0; +const int parisc_32bit_usr2 = 0; +/* ARCH_sh */ +struct_sysent sh_32bit_sysent[] = { + #include "sh/syscallent.h" +}; +const int sh_32bit_usr1 = SYS_socket_subcall; +const int sh_32bit_usr2 = 0; +/* ARCH_sh64 */ +struct_sysent sh64_64bit_sysent[] = { + #include "sh64/syscallent.h" +}; +const int sh64_64bit_usr1 = SYS_socket_subcall; +const int sh64_64bit_usr2 = 0; +/* ARCH_x86 */ +struct_sysent x86_32bit_sysent[] = { + #include "i386/syscallent.h" +}; +const int x86_32bit_usr1 = SYS_socket_subcall; +const int x86_32bit_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_i386 */ +#define i386_32bit_sysent dummy_sysent +const int i386_32bit_usr1 = 0; +const int i386_32bit_usr2 = 0; +/* ARCH_i486 */ +#define i486_32bit_sysent dummy_sysent +const int i486_32bit_usr1 = 0; +const int i486_32bit_usr2 = 0; +/* ARCH_i586 */ +#define i586_32bit_sysent dummy_sysent +const int i586_32bit_usr1 = 0; +const int i586_32bit_usr2 = 0; +/* ARCH_i686 */ +#define i686_32bit_sysent dummy_sysent +const int i686_32bit_usr1 = 0; +const int i686_32bit_usr2 = 0; +/* ARCH_x86_64 64bit ABI mode */ +struct_sysent x86_64_64bit_sysent[] = { + #include "x86_64/syscallent.h" +}; +const int x86_64_64bit_usr1 = 0; +const int x86_64_64bit_usr2 = 0; +/* ARCH_x86_64 32bit ABI mode */ +struct_sysent x86_64_32bit_sysent[] = { + #include "x86_64/syscallent1.h" +}; +const int x86_64_32bit_usr1 = SYS_socket_subcall; +const int x86_64_32bit_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_x86_64 x32 ABI mode */ +struct_sysent x86_64_x32_sysent[] = { + #include "x86_64/syscallent2.h" +}; +const int x86_64_x32_usr1 = 0; +const int x86_64_x32_usr2 = 0; +/* ARCH_amd64 */ +#define amd64_64bit_sysent dummy_sysent +const int amd64_64bit_usr1 = 0; +const int amd64_64bit_usr2 = 0; +/* ARCH_cris */ +struct_sysent cris_32bit_sysent[] = { + #include "crisv10/syscallent.h" +}; +const int cris_32bit_usr1 = SYS_socket_subcall; +const int cris_32bit_usr2 = 0; +/* ARCH_crisv10 */ +#define crisv10_32bit_sysent dummy_sysent +const int crisv10_32bit_usr1 = 0; +const int crisv10_32bit_usr2 = 0; +/* ARCH_crisv32 */ +struct_sysent crisv32_32bit_sysent[] = { + #include "crisv32/syscallent.h" +}; +const int crisv32_32bit_usr1 = SYS_socket_subcall; +const int crisv32_32bit_usr2 = 0; +#undef SYS_socket_subcall +/* ARCH_tile 64bit ABI mode */ +struct_sysent tile_64bit_sysent[] = { + #include "tile/syscallent.h" +}; +const int tile_64bit_usr1 = 0; +const int tile_64bit_usr2 = 0; +/* ARCH_tile 32bit ABI mode */ +struct_sysent tile_32bit_sysent[] = { + #include "tile/syscallent1.h" +}; +const int tile_32bit_usr1 = 0; +const int tile_32bit_usr2 = 0; +/* ARCH_microblaze */ +struct_sysent microblaze_32bit_sysent[] = { + #include "microblaze/syscallent.h" +}; +const int microblaze_32bit_usr1 = 0; +const int microblaze_32bit_usr2 = 0; +/* ARCH_nios2 */ +struct_sysent nios2_32bit_sysent[] = { + #include "nios2/syscallent.h" +}; +const int nios2_32bit_usr1 = 0; +const int nios2_32bit_usr2 = 0; +/* ARCH_openrisc */ +struct_sysent openrisc_32bit_sysent[] = { + #include "or1k/syscallent.h" +}; +const int openrisc_32bit_usr1 = 0; +const int openrisc_32bit_usr2 = 0; +/* ARCH_xtensa */ +struct_sysent xtensa_32bit_sysent[] = { + #include "xtensa/syscallent.h" +}; +const int xtensa_32bit_usr1 = 0; +const int xtensa_32bit_usr2 = 0; +/* ARCH_riscv 64bit ABI mode */ +struct_sysent riscv_64bit_sysent[] = { + #include "riscv/syscallent.h" +}; +const int riscv_64bit_usr1 = 0; +const int riscv_64bit_usr2 = 0; +/* ARCH_riscv 32bit ABI mode */ +struct_sysent riscv_32bit_sysent[] = { + #include "riscv/syscallent1.h" +}; +const int riscv_32bit_usr1 = 0; +const int riscv_32bit_usr2 = 0; + +#undef DEFINE_SYSCALLENT + +#undef SEN +#undef TD +#undef TF +#undef TI +#undef TN +#undef TP +#undef TS +#undef TM +#undef TST +#undef TLST +#undef TFST +#undef TSTA +#undef TSF +#undef TFSF +#undef TSFA +#undef NF +#undef MA +#undef SI +#undef SE +#undef CST + +#define ARCH_DESC_DEFINE(arch, base_arch, mode) \ + [ARCH_##arch##_##mode] = { \ + .arch_num = ARCH_##arch##_##mode, \ + .arch_name = #arch, \ + .arch_name_len = ARRAY_SIZE(#arch) - 1, \ + .arch_base_num = ARCH_##base_arch##_##mode, \ + .abi_mode = #mode, \ + .abi_mode_len = ARRAY_SIZE(#arch) - 1, \ + .max_scn = ARRAY_SIZE(arch##_##mode##_sysent), \ + .list_of_syscall = arch##_##mode##_sysent, \ + .user_num1 = &arch##_##mode##_usr1, \ + .user_num2 = &arch##_##mode##_usr2, \ + .flag = AD_FLAG_EMPTY \ + } + +/* Generate array of arch_descriptors for each architecture and mode */ +struct arch_descriptor architectures[] = { + ARCH_DESC_DEFINE(blackfin, blackfin, 32bit ), + ARCH_DESC_DEFINE(ia64, ia64, 64bit ), + ARCH_DESC_DEFINE(m68k, m68k, 32bit ), + ARCH_DESC_DEFINE(sparc64, sparc64, 64bit ), + ARCH_DESC_DEFINE(sparc64, sparc64, 32bit ), + ARCH_DESC_DEFINE(sparc, sparc, 32bit ), + ARCH_DESC_DEFINE(metag, metag, 32bit ), + ARCH_DESC_DEFINE(mips, mips, o32 ), + ARCH_DESC_DEFINE(mips, mips, n32 ), + ARCH_DESC_DEFINE(mips, mips, n64 ), + ARCH_DESC_DEFINE(alpha, alpha, 64bit ), + ARCH_DESC_DEFINE(ppc, ppc, 32bit ), + ARCH_DESC_DEFINE(ppc64, ppc64, 64bit ), + ARCH_DESC_DEFINE(ppc64, ppc64, 32bit ), + ARCH_DESC_DEFINE(arm, arm, oabi ), + ARCH_DESC_DEFINE(arm, arm, eabi ), + ARCH_DESC_DEFINE(aarch64, aarch64, 64bit ), + ARCH_DESC_DEFINE(aarch64, aarch64, 32bit ), + ARCH_DESC_DEFINE(avr32, avr32, 32bit ), + ARCH_DESC_DEFINE(arc, arc, 32bit ), + ARCH_DESC_DEFINE(s390, s390, 32bit ), + ARCH_DESC_DEFINE(s390x, s390x, 64bit ), + ARCH_DESC_DEFINE(hppa, hppa, 32bit ), + ARCH_DESC_DEFINE(parisc, hppa, 32bit ), + ARCH_DESC_DEFINE(sh, sh, 32bit ), + ARCH_DESC_DEFINE(sh64, sh64, 64bit ), + ARCH_DESC_DEFINE(x86, x86, 32bit ), + ARCH_DESC_DEFINE(i386, x86, 32bit ), + ARCH_DESC_DEFINE(i486, x86, 32bit ), + ARCH_DESC_DEFINE(i586, x86, 32bit ), + ARCH_DESC_DEFINE(i686, x86, 32bit ), + ARCH_DESC_DEFINE(x86_64, x86_64, 64bit ), + ARCH_DESC_DEFINE(x86_64, x86_64, 32bit ), + ARCH_DESC_DEFINE(x86_64, x86_64, x32 ), + ARCH_DESC_DEFINE(amd64, x86_64, 64bit ), + ARCH_DESC_DEFINE(cris, cris, 32bit ), + ARCH_DESC_DEFINE(crisv10, cris, 32bit ), + ARCH_DESC_DEFINE(crisv32, crisv32, 32bit ), + ARCH_DESC_DEFINE(tile, tile, 64bit ), + ARCH_DESC_DEFINE(tile, tile, 32bit ), + ARCH_DESC_DEFINE(microblaze, microblaze, 32bit ), + ARCH_DESC_DEFINE(nios2, nios2, 32bit ), + ARCH_DESC_DEFINE(openrisc, openrisc, 32bit ), + ARCH_DESC_DEFINE(xtensa, xtensa, 32bit ), + ARCH_DESC_DEFINE(riscv, riscv, 64bit ), + ARCH_DESC_DEFINE(riscv, riscv, 32bit ) +}; + +/* To make architectures array usable for dispatchers.c */ +const int architectures_size = ARRAY_SIZE(architectures); + +#undef ARCH_DESC_DEFINE + +struct arch_service * +al_create(unsigned int capacity) +{ + struct arch_service *as = xcalloc(sizeof(*as), 1); + + if (capacity) + as->arch_list = xcalloc(sizeof(*(as->arch_list)), capacity); + as->capacity = capacity; + as->next_free = 0; + return as; +} + +int +al_push(struct arch_service *m, struct arch_descriptor *element) +{ + if (m->next_free >= m->capacity) + return -1; + m->arch_list[m->next_free] = element; + m->arch_list[m->next_free]->flag = AD_FLAG_EMPTY; + m->next_free++; + return 0; +} + +static inline int +al_is_index_ok(struct arch_service *m, unsigned index) { + if (index >= m->next_free) + return -1; + return 0; +} + +int +al_set_flag(struct arch_service *m, unsigned index, int flag) +{ + if (al_is_index_ok(m, index) == 0) { + m->arch_list[index]->flag = flag; + return 0; + } + return -1; +} + +struct arch_descriptor * +al_get(struct arch_service *m, unsigned index) +{ + if (al_is_index_ok(m, index) != 0) + return NULL; + return m->arch_list[index]; +} + +unsigned int +al_size(struct arch_service *m) +{ + return m->next_free; +} + +unsigned int +al_base_size(struct arch_service *m) +{ + int arch_size = al_size(m); + int i = 0; + unsigned count = 0; + + for (i = 0; i < arch_size; i++) + if (m->arch_list[i]->arch_num == + m->arch_list[i]->arch_base_num) + count++; + return count; +} + +void +al_free(struct arch_service *m) +{ + free(m->arch_list); + free(m); +} + +enum arch_type +al_arch_num(struct arch_service *m, unsigned index) +{ + struct arch_descriptor *elem = al_get(m, index); + + return (elem ? elem->arch_num : ARCH_no_arch); +} + +const char * +al_arch_name(struct arch_service *m, unsigned index) +{ + struct arch_descriptor *elem = al_get(m, index); + + return (elem ? elem->arch_name : NULL); +} + +int +al_arch_name_len(struct arch_service *m, unsigned index) +{ + struct arch_descriptor *elem = al_get(m, index); + + return (elem ? elem->arch_name_len : -1); +} + +enum arch_type +al_arch_base_num(struct arch_service *m, unsigned index) +{ + struct arch_descriptor *elem = al_get(m, index); + + return (elem ? elem->arch_base_num : ARCH_no_arch); +} + +const char * +al_abi_mode(struct arch_service *m, unsigned index) +{ + struct arch_descriptor *elem = al_get(m, index); + + return (elem ? elem->abi_mode : NULL); +} + +int +al_abi_mode_len(struct arch_service *m, unsigned index) +{ + struct arch_descriptor *elem = al_get(m, index); + + return (elem ? elem->abi_mode_len : -1); +} + +int +al_flag(struct arch_service *m, unsigned index) +{ + struct arch_descriptor *elem = al_get(m, index); + + return (elem ? elem->flag : -1); +} + +int +al_syscall_impl(struct arch_service *m, unsigned index) +{ + struct arch_descriptor *elem = al_get(m, index); + int i = 0; + int count = 0; + + if (elem == NULL) + return -1; + for (i = 0; i < elem->max_scn; i++) { + if (elem->list_of_syscall[i].sys_name && + !(elem->list_of_syscall[i].sys_flags & + TRACE_INDIRECT_SUBCALL)) + count++; + } + return count; +} + +/* This method is purposed to find base arch + * NOTE: base arch is the arch, where arch_num is equal to arch_base_num + * with default ABI mode */ +int +al_find_base_arch(struct arch_service *m, unsigned index) +{ + enum arch_type base_arch = ARCH_no_arch; + int arch_size = al_size(m); + int i = 0; + + /* If given arch meets conditions above then return this index */ + if (al_is_index_ok(m, index) != 0) + return -1; + /* Search base arch */ + base_arch = al_arch_base_num(m, index); + for (i = 0; i < arch_size; i++) + if ((strcmp(al_arch_name(m, index), al_arch_name(m, i)) == 0) + || (al_arch_base_num(m, i) == base_arch)) + return i; + return -1; +} + +/* This method is purposed to count the supported ABI modes for the given + arch + NOTE: Firstly, do not forget to find base arch */ +int +al_get_abi_modes(struct arch_service *m, unsigned index) +{ + const char *arch_name = al_arch_name(m, index); + int arch_size = al_size(m); + int i = 0; + int abi_count = 0; + + if (!arch_name) + return -1; + for (i = 0; i < arch_size; i++) + if (strcmp(arch_name, al_arch_name(m, i)) == 0) + abi_count++; + return abi_count; +} + +/* This method is purposed to check on uniqueness, in sense of arch name, + without taking into account ABI modes */ +int +al_is_arch_unique(struct arch_service *m, unsigned index) +{ + enum arch_type base_arch = ARCH_no_arch; + int arch_size = al_size(m); + int i = 0; + + if (al_arch_num(m, index) != al_arch_base_num(m, index) || + al_arch_num(m, index) == ARCH_no_arch) + return -1; + base_arch = al_arch_base_num(m, index); + for (i = 0; i < arch_size; i++) + if ((al_arch_num(m, i) == base_arch) && + (i != (int)index)) + return -1; + return 0; +} + +enum impl_type +al_ipc_syscall(struct arch_service *m, unsigned index) +{ + struct arch_descriptor *elem = al_get(m, index); + int i; + enum impl_type impl_buf = IMPL_int; + + for (i = 0; i < elem->max_scn; i++) { + if (elem->list_of_syscall[i].sys_name == NULL) + continue; + if (strcmp(elem->list_of_syscall[i].sys_name, "ipc") == 0) + impl_buf = IMPL_int; + /* It is enough to find just semop sybcall */ + if ((strcmp(elem->list_of_syscall[i].sys_name, "semop") == 0) + && !((elem->list_of_syscall[i].sys_flags & + TRACE_INDIRECT_SUBCALL))) { + if (impl_buf == IMPL_int) + impl_buf = IMPL_int_ext; + else + impl_buf = IMPL_ext; + } + } + return impl_buf; +} + +enum impl_type +al_sck_syscall(struct arch_service *m, unsigned index) +{ + struct arch_descriptor *elem = al_get(m, index); + int i; + enum impl_type impl_buf = IMPL_int; + + for (i = 0; i < elem->max_scn; i++) { + if (elem->list_of_syscall[i].sys_name == NULL) + continue; + if (strcmp(elem->list_of_syscall[i].sys_name, + "socketcall") == 0) + impl_buf = IMPL_int; + /* It is enough to find just socket sybcall */ + if ((strcmp(elem->list_of_syscall[i].sys_name, "socket") == 0) + && (!(elem->list_of_syscall[i].sys_flags & + TRACE_INDIRECT_SUBCALL))) { + if (impl_buf == IMPL_int) + impl_buf = IMPL_int_ext; + else + impl_buf = IMPL_ext; + } + } + return impl_buf; +} + +int al_find_arch(struct arch_service *m, enum arch_type a_type) +{ + int arch_size = al_size(m); + int i; + + for (i = 0; i < arch_size; i++) + if (al_arch_num(m, i) == a_type) + return i; + return -1; +} + +/* This method is purposed to find next one name of the same architecture. + For instance, x86_64 = amd64 */ +int +al_next_arch_name(struct arch_service *m, unsigned index) +{ + static int next_arch = -1; + int i = 0; + int arch_size = al_size(m); + + if (next_arch == -1) + next_arch = index; + else + next_arch++; + if (al_arch_num(m, index) != al_arch_base_num(m, index) || + al_arch_num(m, index) == ARCH_no_arch) + return -1; + for (i = next_arch; i < arch_size; i++) { + next_arch = -1; + if (strcmp(al_arch_name(m, index), al_arch_name(m, i)) == 0) + continue; + if (al_arch_base_num(m, index) == al_arch_base_num(m, i)) { + next_arch = i; + break; + } + break; + } + if (next_arch >= arch_size) + next_arch = -1; + return next_arch; +} + +//len could optimized +//arch_list_size 11 +void +al_dump(struct arch_service *m) +{ + const char *title[] = { + "N", + "Architecture name", + "ABI mode", + /* Implemented syscalls */ + "IMPL syscalls", + /* IPC implementation */ + "IPC IMPL", + /* SOCKET implementation */ + "SOCKET IMPL" + }; + const char *impl_st[] = { + "external", + "internal", + "int/ext" + }; + int i = 0; + int lbase_arch = 0; + int temp_len = 0; + int arch_number_col = 0; + int arch_name_col = strlen(title[1]); + int arch_abi_col = strlen(title[2]); + /* It is hard to imagine arch with more than 10^13 syscalls */ + int arch_impl_sc_col = strlen(title[3]); + int arch_ipc_col = strlen(title[4]); + int arch_sck_col = strlen(title[5]); + int arch_size = al_size(m); + int arch_base_size = al_base_size(m); + int N = 0; + int next_name = 0; + char *arch_name_buf; + + /* Calculate length of the column with the number of architectures */ + for (i = 1; arch_base_size/i != 0; i *= 10) + arch_number_col++; + for (i = 0; i < arch_size; i++) { + /* Calculate length of the column with the + architectures name */ + if (al_is_arch_unique(m, i) == -1) + continue; + lbase_arch = al_find_base_arch(m, i); + temp_len = al_arch_name_len(m, lbase_arch); + while ((next_name = al_next_arch_name(m, lbase_arch)) != -1) { + temp_len += al_arch_name_len(m, next_name); + /* To take into account delim symbol */ + temp_len++; + } + if (temp_len > arch_name_col) { + arch_name_col = temp_len; + } + /* Calculate length of the column with the ABI mode */ + if (al_abi_mode_len(m, i) > arch_abi_col) + arch_abi_col = al_abi_mode_len(m, i); + + } + arch_name_buf = xcalloc(arch_name_col, sizeof(*arch_name_buf)); + /* Output title */ + printf("| %*s | %*s | %*s | %*s | %*s | %*s |\n", + arch_number_col, title[0], arch_name_col, title[1], + arch_abi_col, title[2], arch_impl_sc_col, title[3], + arch_ipc_col, title[4], arch_sck_col, title[5]); + /* Output architectures */ + for (i = 0; i < arch_size; i++) { + if ((al_is_arch_unique(m, i) == -1) || + !(al_flag(m, i) & AD_FLAG_PRINT)) + continue; + printf("| %*u | ", arch_number_col, N + 1); + /* Put all the same arch back together */ + strcat(arch_name_buf, al_arch_name(m, i)); + lbase_arch = al_find_base_arch(m, i); + while ((next_name = al_next_arch_name(m, lbase_arch)) != -1) { + strcat(arch_name_buf, "/"); + strcat(arch_name_buf, al_arch_name(m, next_name)); + } + printf("%*s | ", arch_name_col, arch_name_buf); + printf("%*s | ", arch_abi_col, al_abi_mode(m, i)); + printf("%*d | ", arch_impl_sc_col, al_syscall_impl(m, i)); + printf("%*s | ", arch_ipc_col, impl_st[al_ipc_syscall(m, i)]); + printf("%*s |\n", arch_sck_col, impl_st[al_sck_syscall(m, i)]); + N++; + memset(arch_name_buf, 0, arch_name_col); + } + free(arch_name_buf); +} diff --git a/tools/asinfo/arch_interface.h b/tools/asinfo/arch_interface.h new file mode 100644 index 00000000..a7a6d320 --- /dev/null +++ b/tools/asinfo/arch_interface.h @@ -0,0 +1,184 @@ +/* + * The arch_interface.h is purposed to interact with the basic data structure + * based on arch_descriptor struct. Mainly this set of methods are used by + * arch_dispatcher. + * + * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhm...@virtuozzo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ASINFO_ARCH_INTERFACE +#define ASINFO_ARCH_INTERFACE + +#include "sysent.h" + +/* Type implementaion of syscall, internal means as a subcall, + external means a separate syscall, this enum is purposed for + well-known ipc and socket subcall group */ +enum impl_type { + IMPL_ext, + IMPL_int, + IMPL_int_ext +}; + +/* Names of architectures + * arch_type format name_arch = ARCH_ + kernel_arch/others_name + abi_mode */ +enum arch_type { + ARCH_blackfin_32bit, + ARCH_ia64_64bit, + ARCH_m68k_32bit, + ARCH_sparc64_64bit, + ARCH_sparc64_32bit, + ARCH_sparc_32bit, + ARCH_metag_32bit, + ARCH_mips_o32, + ARCH_mips_n32, + ARCH_mips_n64, + ARCH_alpha_64bit, + ARCH_ppc_32bit, + ARCH_ppc64_64bit, + ARCH_ppc64_32bit, + ARCH_arm_oabi, + ARCH_arm_eabi, + ARCH_aarch64_64bit, + ARCH_aarch64_32bit, + ARCH_avr32_32bit, + ARCH_arc_32bit, + ARCH_s390_32bit, + ARCH_s390x_64bit, + ARCH_hppa_32bit, + ARCH_parisc_32bit, + ARCH_sh_32bit, + ARCH_sh64_64bit, + ARCH_x86_32bit, + ARCH_i386_32bit, + ARCH_i486_32bit, + ARCH_i586_32bit, + ARCH_i686_32bit, + ARCH_x86_64_64bit, + ARCH_x86_64_32bit, + ARCH_x86_64_x32, + ARCH_amd64_64bit, + ARCH_cris_32bit, + ARCH_crisv10_32bit, + ARCH_crisv32_32bit, + ARCH_tile_64bit, + ARCH_tile_32bit, + ARCH_microblaze_32bit, + ARCH_nios2_32bit, + ARCH_openrisc_32bit, + ARCH_xtensa_32bit, + ARCH_riscv_64bit, + ARCH_riscv_32bit, + ARCH_no_arch +}; + +#define AD_FLAG_EMPTY 0 +/* Actually, this flag is purposed to hide some abi modes while printing in + one arch group + NOTE: arch group means base arch name + others */ +#define AD_FLAG_PRINT 1 + +struct arch_descriptor { + enum arch_type arch_num; + const char *arch_name; + const int arch_name_len; + enum arch_type arch_base_num; + //enum abi_type abi_mode; + const char *abi_mode; + const int abi_mode_len; + const int max_scn; + struct_sysent *list_of_syscall; + /* In the most cases these fields are purposed to store specific for + given arch constants, for instance, socket_subcall index etc */ + const int *user_num1; + const int *user_num2; + /* User flags */ + int flag; +}; + +/* To provide push-back interface with arch_list */ +struct arch_service { + struct arch_descriptor **arch_list; + unsigned capacity; + unsigned next_free; +}; + +#define ARCH_LIST_DEFINE(name) \ + struct arch_service *(name) + +/* Push-back interface is purposed to simplify interaction with + arch_service struct + NOTE: al - architecture list */ + +/* base methods */ +struct arch_service *al_create(unsigned int capacity); + +int al_push(struct arch_service *m, struct arch_descriptor *element); + +int al_set_flag(struct arch_service *m, unsigned index, int flag); + +struct arch_descriptor *al_get(struct arch_service *m, unsigned index); + +unsigned int al_size(struct arch_service *m); + +unsigned int al_base_size(struct arch_service *m); + +void al_free(struct arch_service *m); + +/* methods returning fields with error check */ +enum arch_type al_arch_num(struct arch_service *m, unsigned index); + +const char *al_arch_name(struct arch_service *m, unsigned index); + +int al_arch_name_len(struct arch_service *m, unsigned index); + +enum arch_type al_arch_base_num(struct arch_service *m, unsigned index); + +const char *al_abi_mode(struct arch_service *m, unsigned index); + +int al_abi_mode_len(struct arch_service *m, unsigned index); + +int al_flag(struct arch_service *m, unsigned index); + +/* calculating methods */ +int al_syscall_impl(struct arch_service *m, unsigned index); + +int al_find_base_arch(struct arch_service *m, unsigned index); + +int al_get_abi_modes(struct arch_service *m, unsigned index); + +int al_is_arch_unique(struct arch_service *m, unsigned index); + +enum impl_type al_ipc_syscall(struct arch_service *m, unsigned index); + +enum impl_type al_sck_syscall(struct arch_service *m, unsigned index); + +int al_find_arch(struct arch_service *m, enum arch_type a_type); + +int al_next_arch_name(struct arch_service *m, unsigned index); + +void al_dump(struct arch_service *m); + +#endif /* !ASINFO_ARCH_INTERFACE */ diff --git a/tools/asinfo/asinfo.1 b/tools/asinfo/asinfo.1 new file mode 100644 index 00000000..e69de29b diff --git a/tools/asinfo/asinfo.c b/tools/asinfo/asinfo.c new file mode 100644 index 00000000..1b8089a4 --- /dev/null +++ b/tools/asinfo/asinfo.c @@ -0,0 +1,196 @@ +/* + * The asinfo main source. The asinfo tool is purposed to operate + * with system calls and provide information about it. + * + * Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include <errno.h> +#include <limits.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "arch_interface.h" +#include "dispatchers.h" +#include "error_prints.h" +#include "macros.h" +#include "request_msgs.h" +#include "xmalloc.h" + +#ifndef HAVE_PROGRAM_INVOCATION_NAME +char *program_invocation_name; +#endif + +void +die(void) +{ + exit(1); +} + +static int +is_more1bit(unsigned int num) +{ + return !(num & (num - 1)); +} + +static unsigned +option_to_request(char *option) +{ + /* Convertion table to store string with options */ + const char *options[] = { + [SD_REQ_GET_NAME_BIT] = "get-name", + [SD_REQ_GET_NUMBER_BIT] = "get-num", + [SD_REQ_GET_NARGS_BIT] = "get-nargs", + [AD_REQ_SET_ARCH_BIT] = "set-arch", + [AD_REQ_GET_ARCH_BIT] = "get-arch", + [AD_REQ_LIST_ARCH_BIT] = "list-arch", + [ABD_REQ_SET_ABI] = "set-abi", + [ABD_REQ_GET_ABI] = "get-abi", + [ABD_REQ_LIST_ABI] = "list-abi", + }; + unsigned i; + + for (i = 0; i < ARRAY_SIZE(options); i++) { + if (options[i] && strcmp(option, options[i]) == 0) + return i; + } + return UINT_MAX; +} + +static unsigned +command_dispatcher(int argc, char *argv[], char *args[]) +{ + int i; + unsigned final_req = 0; + unsigned temp_req = 0; + unsigned non_req_arg = (1 << AD_REQ_GET_ARCH_BIT) | + (1 << AD_REQ_LIST_ARCH_BIT) | + (1 << ABD_REQ_GET_ABI_BIT) | + (1 << ABD_REQ_LIST_ABI_BIT) | + (1 << SD_REQ_GET_LIST_BIT); + + if (!program_invocation_name || !*program_invocation_name) { + static char name[] = "asinfo"; + program_invocation_name = + (argv[0] && *argv[0]) ? argv[0] : name; + } + + /* Firstly, is is necessary to convert and make basic check */ + for (i = 1; i < argc; i++) { + if ((temp_req = option_to_request(argv[i])) == UINT_MAX) + error_msg_and_help("unrecognized option '%s'", argv[i]); + if (final_req & (1 << temp_req)) + error_msg_and_help("option '%s' has been used more than " + "once", argv[i]); + if (!((1 << temp_req) & non_req_arg) && + ((i + 1 >= argc) || strlen(argv[i + 1]) == 0)) + error_msg_and_help("option '%s' requires " + "argument", argv[i]); + final_req |= (1 << temp_req); + if (!((1 << temp_req) & non_req_arg)) { + args[temp_req] = argv[i + 1]; + i++; + } + } + /* Secondly, final_req should be logically checked, + here the only error is 'mixed options' */ + /* More than one option from the one request group couldn't be set*/ + if ((is_more1bit(final_req & SD_REQ_MASK) == 0) || + (is_more1bit(final_req & AD_REQ_MASK) == 0) || + (is_more1bit(final_req & ABD_REQ_MASK) == 0) || + (is_more1bit(final_req & FD_REQ_MASK) == 0)) + error_msg_and_help("mixed options"); + /* Check on mutually exclusive options chain */ + /* If at least one syscall option has been typed, therefore + arch_options could be only empty or set-arch and + abi_option could be only empty or set-abi */ + if ((final_req & SD_REQ_MASK) && + (((final_req & AD_REQ_MASK) && + !(final_req & (1 << AD_REQ_SET_ARCH_BIT))) || + ((final_req & ABD_REQ_MASK) && + !(final_req & (1 << ABD_REQ_SET_ABI_BIT))))) + error_msg_and_help("mixed options"); + + /* list-arch couldn't be used with any abi options */ + if ((final_req & (1 << AD_REQ_LIST_ARCH_BIT) && + (final_req & ABD_REQ_MASK))) + error_msg_and_help("mixed options"); + + return final_req; +} + +int +main(int argc, char *argv[]) +{ + ARCH_LIST_DEFINE(arch_list); + /* This array is purposed to store arguments for options in the + most convinient way */ + char **input_args = xcalloc(sizeof(*input_args), REQ_LAST_BIT); + unsigned reqs; + int ret = 0; + + /* command_dispatcher turn */ + reqs = command_dispatcher(argc, argv, input_args); + if (reqs == 0) + error_msg_and_help("must have OPTIONS"); + + /* arch_dispatcher turn */ + arch_list = arch_dispatcher(reqs, input_args[AD_REQ_SET_ARCH]); + if (arch_list == NULL) + error_msg_and_help("unrecognized architecture '%s'", + input_args[AD_REQ_SET_ARCH]); + /* abi_dispatcher turn */ + ret = abi_dispatcher(arch_list, reqs, input_args[ABD_REQ_SET_ABI]); + if (ret != 0) + error_msg_and_help("unrecognized ABI mode '%s'", + input_args[ABD_REQ_SET_ABI]); + /* syscall_dispatcher work */ +#if 0 + SYSCALL_LIST_DEFINE(syscall_list); + syscall_list = syscall_dispatcher(arch_list, requests, + input_args[IS_OWNrequests & SD_REQ_MASK]); + if (syscall_list[0].sys_name != NULL) { + printf("%s\n", syscall_list[0].sys_name); + } else { + error_msg_and_help("unrecognized syscall number '%s'", + input_args[fsbit_num(requests & SD_REQ_MASK)]); + } +#endif + /* If we want to get info about just architectures thus we dump just + info about archs, otherwise only about syscalls */ + if (!(reqs & SD_REQ_MASK)) + al_dump(arch_list); + else + //sl_dump + error_msg_and_die("syscall dispatcher isn't supported for now"); + return 0; +} diff --git a/tools/asinfo/dispatchers.c b/tools/asinfo/dispatchers.c new file mode 100644 index 00000000..753e9562 --- /dev/null +++ b/tools/asinfo/dispatchers.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/utsname.h> + +#include "arch_interface.h" +#include "dispatchers.h" +#include "macros.h" +#include "request_msgs.h" +#include "sysent.h" +#include "xmalloc.h" + +extern struct arch_descriptor architectures[]; +extern const int architectures_size; + +struct sc_base_info * +syscall_dispatcher(struct arch_service *arch, int request_type, + const char *data) +{ + SYSCALL_LIST_DEFINE(syscall_list); + + if (request_type & (1 << SD_REQ_GET_NAME_BIT)) { + long int nsys; + char *endptr; + nsys = strtol(data, &endptr, 10); + if (*endptr != '\0' || nsys < 0 || + nsys >= arch->arch_list[0]->max_scn) { + goto fail; + } + SYSCALL_LIST_ALLOC(syscall_list, 1); + syscall_list[0].sys_name = + arch->arch_list[0]->list_of_syscall[nsys].sys_name; + goto done; + } + +fail: + SYSCALL_LIST_ALLOC(syscall_list, 0); +done: + return syscall_list; +} + +static int +form_arch_list(struct arch_service **arch, char *arch_str) +{ + ARCH_LIST_DEFINE(a_full_list) = al_create(architectures_size); + int arch_match = -1; + char *match_pointer = NULL; + int al_size_ret = 0; + int al_size_full = 0; + int i; + + if (arch_str == NULL) + return -1; + /* Firstly, generate full list of arch to simplify firther work */ + for (i = 0; i < architectures_size; i++) + al_push(a_full_list, &architectures[i]); + al_size_full = al_size(a_full_list); + /* Here we find the best match in architecture list */ + for (i = 0; i < al_size_full; i++) { + match_pointer = strstr(arch_str, al_arch_name(a_full_list, i)); + if (match_pointer == NULL || match_pointer != arch_str) + continue; + if (arch_match == -1 || + al_arch_name_len(a_full_list, i) > + al_arch_name_len(a_full_list, arch_match)) + arch_match = i; + } + if (arch_match == -1) + goto fail; + /* Now we find all ABI modes related to the architecture and its other + names */ + /* Firstly, find the base arch */ + arch_match = al_find_base_arch(a_full_list, arch_match); + /* Secondly, it is necessary to calculate size of arch list */ + al_size_ret = al_get_abi_modes(a_full_list, arch_match); + while ((i = al_next_arch_name(a_full_list, arch_match)) != -1) + al_size_ret++; + if (al_size_ret == 0) + goto fail; + /* Finally, Create arch_list and fill it */ + *arch = al_create(al_size_ret); + for (i = arch_match; i < (arch_match + al_size_ret); i++) + al_push(*arch, &architectures[i]); + + free(a_full_list); + return 0; +fail: + free(a_full_list); + return -1; +} + +struct arch_service * +arch_dispatcher(unsigned request_type, char *arch) +{ + struct utsname info_uname; + int i; + ARCH_LIST_DEFINE(arch_list) = NULL; + + /* If user don't type any option in ARCH_REQ group, it means + get current arch */ + if ((request_type & (1 << AD_REQ_GET_ARCH_BIT)) || + (!(request_type & AD_REQ_MASK))) { + uname(&info_uname); + if (form_arch_list(&arch_list, info_uname.machine) == -1) + goto fail; + goto done; + } + + if (request_type & (1 << AD_REQ_SET_ARCH_BIT)) { + if (form_arch_list(&arch_list, arch) == -1) + goto fail; + goto done; + } + + if ((request_type & (1 << AD_REQ_LIST_ARCH_BIT))) { + arch_list = al_create(architectures_size); + for (i = 0; i < architectures_size; i++) { + al_push(arch_list, &(architectures[i])); + al_set_flag(arch_list, i, AD_FLAG_PRINT); + } + goto done; + } +fail: + arch_list = NULL; +done: + return arch_list; +} + +int +abi_dispatcher(struct arch_service *a_serv, unsigned request_type, char *abi) +{ + int i = 0; + enum arch_type arch_num = ARCH_no_arch; + int abi_modes = 0; + int arch_size = 0; + int flag = 0; + + if (a_serv == NULL) + return -1; + arch_size = al_size(a_serv); + abi_modes = al_get_abi_modes(a_serv, 0); + /* The strace package could be compiled as 32bit app on 64bit + architecture, therefore asinfo has to detect it and print out + corresponding personality. Frankly speaking, it is necessary to + detect strace package personality */ + if ((request_type & (1 << ABD_REQ_GET_ABI_BIT)) || + (!(request_type & ABD_REQ_MASK))) { + arch_num = al_arch_num(a_serv, 0); + switch (arch_num) { + case ARCH_x86_64_64bit: + al_set_flag(a_serv, al_find_arch(a_serv, +#if defined(X86_64) + ARCH_x86_64_64bit +#elif defined(X32) + ARCH_x86_64_x32 +#else + ARCH_x86_64_32bit +#endif + ), AD_FLAG_PRINT); + break; + case ARCH_arm_oabi: + al_set_flag(a_serv, al_find_arch(a_serv, +#if defined(__ARM_EABI__) + ARCH_arm_eabi +#else + ARCH_arm_oabi +#endif + ), AD_FLAG_PRINT); + break; + case ARCH_mips_o32: + al_set_flag(a_serv, al_find_arch(a_serv, +#if defined(LINUX_MIPSO32) + ARCH_mips_o32 +#elif defined(LINUX_MIPSN32) + ARCH_mips_n32 +#else + ARCH_mips_n64 +#endif + ), AD_FLAG_PRINT); + break; + default: + /* Other cases should be printed using default rule: + print first ABI mode + other arch names */ + al_set_flag(a_serv, 0, AD_FLAG_PRINT); + for (i = abi_modes; i < arch_size; i++) + al_set_flag(a_serv, i, AD_FLAG_PRINT); + } + goto done; + } + + if (request_type & (1 << ABD_REQ_LIST_ABI_BIT)) { + for (i = 0; i < abi_modes; i++) + al_set_flag(a_serv, i, AD_FLAG_PRINT); + goto done; + } + + if (request_type & (1 << ABD_REQ_SET_ABI_BIT)) { + if (abi == NULL) + goto fail; + for (i = 0; i < abi_modes; i++) + if (strcmp(abi, al_abi_mode(a_serv, i)) == 0) { + al_set_flag(a_serv, i, AD_FLAG_PRINT); + flag = 1; + } + if (!flag) + goto fail; + } +done: + return 0; +fail: + return -1; +} diff --git a/tools/asinfo/dispatchers.h b/tools/asinfo/dispatchers.h new file mode 100644 index 00000000..d3843f6e --- /dev/null +++ b/tools/asinfo/dispatchers.h @@ -0,0 +1,60 @@ +/* + * The dispatchers.h contains all necessary functions to perform main + * work in the asinfo tool. + * + * Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef STRACE_ASINFO_COM_SCALLENT +#define STRACE_ASINFO_COM_SCALLENT + +#include "arch_interface.h" +#include "request_msgs.h" +#include "sysent.h" + +#define SYSCALL_LIST_DEFINE(name) \ + struct sc_base_info *(name) + +#define SYSCALL_LIST_ALLOC(name, size) \ + (name) = xcalloc(sizeof(*(name)), (size + 1)) + +/* The main interaction with low-level structures, such as for now, + * struct_sysent, is happening here, the remaining processing should + * be done on the other levels. + */ +struct sc_base_info *syscall_dispatcher(struct arch_service *arch, + int request_type, + const char *arg); + +/* The function is purposed to provide correct list of architectures + */ +struct arch_service *arch_dispatcher(unsigned request_type, char* arch); + +/* Final filtering based on personality */ +int abi_dispatcher(struct arch_service *a_serv, unsigned request_type, + char *abi); + +#endif /* !STRACE_ASINFO_COM_SCALLENT */ diff --git a/tools/asinfo/request_msgs.h b/tools/asinfo/request_msgs.h new file mode 100644 index 00000000..8b87f0f2 --- /dev/null +++ b/tools/asinfo/request_msgs.h @@ -0,0 +1,115 @@ +/* + * The request_msgs are messages used by dispatchers in asinfo tool to + * operate with static data base. + * + * Copyright (c) 2017 Edgar A. Kaziakhmedov <e...@linux.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef STRACE_ASINFO_REQ_MSGS +#define STRACE_ASINFO_REQ_MSGS + +/* Request types for syscall_dispatcher, + * arch_dispatcher, and filter_dispatcher, + * which, in turn, could be combined + */ +enum syscall_req_bit { + SD_REQ_GET_NAME_BIT, + SD_REQ_GET_NUMBER_BIT, + SD_REQ_GET_NARGS_BIT, + SD_REQ_GET_PROTO_BIT, + SD_REQ_GET_KERNEL_BIT, + SD_REQ_GET_LIST_BIT, + + SYSCALL_REQ_BIT_LAST +}; + +enum arch_req_bit { + AD_REQ_SET_ARCH_BIT = SYSCALL_REQ_BIT_LAST, + AD_REQ_GET_ARCH_BIT, + AD_REQ_LIST_ARCH_BIT, + + ARCH_REQ_BIT_LAST +}; + +enum abi_req_bit { + ABD_REQ_SET_ABI_BIT = ARCH_REQ_BIT_LAST, + ABD_REQ_GET_ABI_BIT, + ABD_REQ_LIST_ABI_BIT, + + ABD_REQ_BIT_LAST +}; + +enum fd_req_bit { + FD_REQ_SET_BASE_FILTER_BIT = ABD_REQ_BIT_LAST, + + FD_REQ_BIT_LAST +}; + +#define ENUM_FLAG(name) name = name##_BIT +enum req_type { + ENUM_FLAG(SD_REQ_GET_NAME), + ENUM_FLAG(SD_REQ_GET_NUMBER), + ENUM_FLAG(SD_REQ_GET_NARGS), + ENUM_FLAG(SD_REQ_GET_PROTO), + ENUM_FLAG(SD_REQ_GET_KERNEL), + ENUM_FLAG(SD_REQ_GET_LIST), + ENUM_FLAG(AD_REQ_SET_ARCH), + ENUM_FLAG(AD_REQ_GET_ARCH), + ENUM_FLAG(AD_REQ_LIST_ARCH), + ENUM_FLAG(ABD_REQ_SET_ABI), + ENUM_FLAG(ABD_REQ_GET_ABI), + ENUM_FLAG(ABD_REQ_LIST_ABI), + ENUM_FLAG(FD_REQ_SET_BASE_FILTER), +}; +#undef ENUM_FLAG + +#define BITMASK(hi, lo) ((1 << (hi)) - (1 << (lo))) +#define REQ_LAST_BIT FD_REQ_BIT_LAST /* Can be used in input_args calloc*/ +#define SD_REQ_MASK BITMASK(SYSCALL_REQ_BIT_LAST, 0) +#define AD_REQ_MASK BITMASK(ARCH_REQ_BIT_LAST, SYSCALL_REQ_BIT_LAST) +#define ABD_REQ_MASK BITMASK(ABD_REQ_BIT_LAST, ARCH_REQ_BIT_LAST) +#define FD_REQ_MASK BITMASK(FD_REQ_BIT_LAST, ABD_REQ_BIT_LAST) + +/* SD_REQ_GET_NAME, SD_REQ_GET_NUMBER */ +struct sc_base_info { + int sys_number; + const char *sys_name; + int sys_flags; +}; + +/* SD_REQ_GET_NARGS */ +struct sc_nargs { + struct sc_base_info sys_bi; + int nargs; +}; + +/* FD_SET_BASE_FILTER */ +struct sc_filter { + struct sc_base_info sys_bi; + int filter_options; +}; + +#endif /* !STRACE_ASINFO_REQ_MSGS */ -- 2.11.0 ------------------------------------------------------------------------------ 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