Browse Source

Introduce asinfo tool

The main purpose of this query tool is to present all information concluded
at sysent.h files in a convenient way.
The asinfo tool has the following staged architecture:
(command dispatcher)->(architecture dispatcher)->
(abi dispatcher)->(system call dispatcher).
Each dispatcher accepts proccesed data from previous one.

This point can be illustrated by the following example:
$ asinfo --get-arch --get-sname 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 parameter 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
--get-snum 100,8,%ipc
For more info, use asinfo -h.

* 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/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/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. Implement version.
* tools/asinfo/arch_definitions.h: New file. Introduce useful storage
for architectures.

* tools/asinfo/gen_asinfo_files.sh: New file.
* bootstrap: Add it.
* tools/asinfo/Makefile.am: Include Makemodule.am.
(asinfo_SOURCES): Add $(ARCH_AUX_FILES).
* tools/asinfo/README-arch: New README explaining how to add new
architecture/ABI to asinfo tool.

* configure.ac (AC_CONFIG_FILES): Add asinfo.1.
(asinfo_manpage_date): New m4 define.
(ASINFO_MANPAGE_DATE): New define/subst.
* tools/asinfo/asinfo.1.in: New file.
* tools/asinfo/gen_asinfo_files.sh: Add asinfo.1 to .gitignore
generation.

* debian/control (strace): Add asinfo description.
* debian/strace.install: Add path to asinfo binary.
* debian/strace.manpages: Add path to asinfo manual page.
* strace.spec.in (%files): Add asinfo binary.

Update NEWS

This set of tests cover all possible cases in asinfo tool. However,
as asinfo uses some libraries provided by strace (such as basic_filters)
there is no need to test them again in asinfo context.
Also, the set of syscalls for specific architecture (hence, its number) might
be expanded in the future, so to overcome this obstacle and avoid duplication
of the same strings reference output ptintings are stored in
ref_asinfo_output.h file.
As for syscall-related checks, tests use old syscalls as samples, so their
numbers and names can't be changed.

* configure.ac (AC_CONFIG_FILES): Add tests Makefile to be generated.
* tools/asinfo/Makefile.am (SUBDIRS): Add tests dir.
* tools/asinfo/tests/Makefile.m: New file.
* tools/asinfo/tests/init.sh: New file. Main subroutines for tests.
* tools/asinfo/tests/ref_asinfo_output.h: New file.
* tools/asinfo/tests/com_disp_wrong_keys.c: Likewise.
* tools/asinfo/tests/com_disp_wrong_keys.test: Likewise.
* tools/asinfo/tests/format_output.c: Likewise.
* tools/asinfo/tests/format_output.test: Likewise.
* tools/asinfo/tests/get_arch_abi.c: Likewise.
* tools/asinfo/tests/get_arch_abi.test: Likewise.
* tools/asinfo/tests/get_sname.c: Likewise.
* tools/asinfo/tests/get_sname.test: Likewise.
* tools/asinfo/tests/get_snum.c: Likewise.
* tools/asinfo/tests/get_snum.test: Likewise.
* tools/asinfo/tests/list_arch.c: Likewise.
* tools/asinfo/tests/list_arch.test: Likewise.
* tools/asinfo/tests/multiarch_get_sname.c: Likewise.
* tools/asinfo/tests/multiarch_get_sname.test: Likewise.
* tools/asinfo/tests/multiarch_get_snum.c: Likewise.
* tools/asinfo/tests/multiarch_get_snum.test: Likewise.
* tools/asinfo/tests/set_abi.c: Likewise.
* tools/asinfo/tests/set_abi.test: Likewise.
* tools/asinfo/tests/set_arch.c: Likewise.
* tools/asinfo/tests/set_arch.test: Likewise.
* tools/asinfo/tests/set_mult_abi.c: Likewise.
* tools/asinfo/tests/set_mult_abi.test: Likewise.
* tools/asinfo/tests/set_mult_arch.c: Likewise.
* tools/asinfo/tests/set_mult_arch.test: Likewise.

Signed-off-by: Edgar Kaziakhmedov <edos.edgar@gmail.com>
Adjusted-and-rebased-by: Dmitry V. Levin <ldv@altlinux.org>
Edgar Kaziakhmedov 2 years ago
parent
commit
0c944e831e
51 changed files with 3690 additions and 2 deletions
  1. 1
    1
      Makefile.am
  2. 4
    0
      NEWS
  3. 1
    0
      bootstrap
  4. 8
    0
      configure.ac
  5. 3
    0
      debian/control
  6. 1
    0
      debian/strace.install
  7. 1
    0
      debian/strace.manpages
  8. 4
    1
      strace.spec.in
  9. 9
    0
      tools/Makefile.am
  10. 56
    0
      tools/asinfo/Makefile.am
  11. 37
    0
      tools/asinfo/README-arch
  12. 64
    0
      tools/asinfo/arch_definitions.h
  13. 607
    0
      tools/asinfo/arch_interface.c
  14. 144
    0
      tools/asinfo/arch_interface.h
  15. 264
    0
      tools/asinfo/asinfo.1.in
  16. 312
    0
      tools/asinfo/asinfo.c
  17. 225
    0
      tools/asinfo/dispatchers.c
  18. 29
    0
      tools/asinfo/dispatchers.h
  19. 91
    0
      tools/asinfo/error_interface.c
  20. 76
    0
      tools/asinfo/error_interface.h
  21. 153
    0
      tools/asinfo/gen_asinfo_files.sh
  22. 74
    0
      tools/asinfo/request_msgs.h
  23. 672
    0
      tools/asinfo/syscall_interface.c
  24. 123
    0
      tools/asinfo/syscall_interface.h
  25. 45
    0
      tools/asinfo/tests/Makefile.am
  26. 42
    0
      tools/asinfo/tests/com_disp_wrong_keys.c
  27. 32
    0
      tools/asinfo/tests/com_disp_wrong_keys.test
  28. 17
    0
      tools/asinfo/tests/format_output.c
  29. 8
    0
      tools/asinfo/tests/format_output.test
  30. 172
    0
      tools/asinfo/tests/get_arch_abi.c
  31. 7
    0
      tools/asinfo/tests/get_arch_abi.test
  32. 26
    0
      tools/asinfo/tests/get_sname.c
  33. 12
    0
      tools/asinfo/tests/get_sname.test
  34. 26
    0
      tools/asinfo/tests/get_snum.c
  35. 12
    0
      tools/asinfo/tests/get_snum.test
  36. 75
    0
      tools/asinfo/tests/init.sh
  37. 46
    0
      tools/asinfo/tests/list_arch.c
  38. 7
    0
      tools/asinfo/tests/list_arch.test
  39. 31
    0
      tools/asinfo/tests/multiarch_get_sname.c
  40. 12
    0
      tools/asinfo/tests/multiarch_get_sname.test
  41. 39
    0
      tools/asinfo/tests/multiarch_get_snum.c
  42. 12
    0
      tools/asinfo/tests/multiarch_get_snum.test
  43. 39
    0
      tools/asinfo/tests/ref_asinfo_output.h
  44. 9
    0
      tools/asinfo/tests/set_abi.c
  45. 7
    0
      tools/asinfo/tests/set_abi.test
  46. 11
    0
      tools/asinfo/tests/set_arch.c
  47. 7
    0
      tools/asinfo/tests/set_arch.test
  48. 11
    0
      tools/asinfo/tests/set_mult_abi.c
  49. 7
    0
      tools/asinfo/tests/set_mult_abi.test
  50. 12
    0
      tools/asinfo/tests/set_mult_arch.c
  51. 7
    0
      tools/asinfo/tests/set_mult_arch.test

+ 1
- 1
Makefile.am View File

@@ -15,7 +15,7 @@ endif
15 15
 if HAVE_MX32_RUNTIME
16 16
 TESTS_MX32 = tests-mx32
17 17
 endif
18
-SUBDIRS = . tests $(TESTS_M32) $(TESTS_MX32)
18
+SUBDIRS = . tests $(TESTS_M32) $(TESTS_MX32) tools
19 19
 
20 20
 bin_PROGRAMS = strace
21 21
 man_MANS = strace.1 strace-log-merge.1

+ 4
- 0
NEWS View File

@@ -1,6 +1,10 @@
1 1
 Noteworthy changes in release ?.? (????-??-??)
2 2
 ==============================================
3 3
 
4
+* New tools
5
+  * Added asinfo tool that is purposed to provide information about
6
+    system calls and architectures.
7
+
4 8
 * Improvements
5 9
   * Implemented -DD and -DDD options that move strace into a separate
6 10
     process group and session, respectively.

+ 1
- 0
bootstrap View File

@@ -10,6 +10,7 @@
10 10
 ./xlat/gen.sh
11 11
 ./tests/gen_pure_executables.sh
12 12
 ./tests/gen_tests.sh
13
+./tools/asinfo/gen_asinfo_files.sh
13 14
 
14 15
 for m in m32 mx32; do
15 16
 	tests=tests-$m

+ 8
- 0
configure.ac View File

@@ -18,6 +18,7 @@ AC_INIT([strace],
18 18
 	[https://strace.io])
19 19
 m4_define([copyright_year], st_esyscmd_s([./copyright-year-gen .year]))
20 20
 m4_define([manpage_date], st_esyscmd_s([./file-date-gen strace.1.in]))
21
+m4_define([asinfo_manpage_date], st_esyscmd_s([./file-date-gen tools/asinfo/asinfo.1.in]))
21 22
 AC_COPYRIGHT([Copyright (c) 1999-]copyright_year[ The strace developers.])
22 23
 AC_CONFIG_SRCDIR([strace.c])
23 24
 AC_CONFIG_AUX_DIR([.])
@@ -48,6 +49,9 @@ AC_SUBST([COPYRIGHT_YEAR], [copyright_year])
48 49
 AC_DEFINE([MANPAGE_DATE], "[manpage_date]", [Date])
49 50
 AC_SUBST([MANPAGE_DATE], [manpage_date])
50 51
 
52
+AC_DEFINE([ASINFO_MANPAGE_DATE], "[asinfo_manpage_date]", [Date])
53
+AC_SUBST([ASINFO_MANPAGE_DATE], [asinfo_manpage_date])
54
+
51 55
 AC_C_BIGENDIAN
52 56
 
53 57
 AC_MSG_CHECKING([for supported architecture])
@@ -971,6 +975,10 @@ AC_CONFIG_FILES([Makefile
971 975
 		 tests-mx32/Makefile
972 976
 		 strace.1
973 977
 		 strace-log-merge.1
978
+		 tools/asinfo/asinfo.1
979
+		 tools/Makefile
980
+		 tools/asinfo/Makefile
981
+		 tools/asinfo/tests/Makefile
974 982
 		 strace.spec
975 983
 		 debian/changelog])
976 984
 AC_OUTPUT

+ 3
- 0
debian/control View File

@@ -20,6 +20,9 @@ Description: System call tracer
20 20
  System calls and signals are events that happen at the user/kernel
21 21
  interface. A close examination of this boundary is very useful for bug
22 22
  isolation, sanity checking and attempting to capture race conditions.
23
+ .
24
+ This package also contains an advanced system call information tool
25
+ (asinfo) which provides information about system calls and architectures.
23 26
 
24 27
 Package: strace64
25 28
 Architecture: i386 powerpc s390 sparc

+ 1
- 0
debian/strace.install View File

@@ -1,2 +1,3 @@
1 1
 build/strace usr/bin
2 2
 strace-log-merge usr/bin
3
+build/tools/asinfo/asinfo usr/bin

+ 1
- 0
debian/strace.manpages View File

@@ -1,2 +1,3 @@
1 1
 build/strace.1
2 2
 build/strace-log-merge.1
3
+build/tools/asinfo/asinfo.1

+ 4
- 1
strace.spec.in View File

@@ -44,7 +44,9 @@ The strace program intercepts and records the system calls called and
44 44
 received by a running process.  Strace can print a record of each
45 45
 system call, its arguments and its return value.  Strace is useful for
46 46
 diagnosing problems and debugging, as well as for instructional
47
-purposes.
47
+purposes.  Also this package contains an advanced system call
48
+information tool (asinfo) which provides information about system calls
49
+and architectures.
48 50
 
49 51
 Install strace if you need a tool to track the system calls made and
50 52
 received by a process.
@@ -97,6 +99,7 @@ echo 'END OF TEST SUITE INFORMATION'
97 99
 %doc CREDITS ChangeLog.gz ChangeLog-CVS.gz COPYING NEWS README
98 100
 %{_bindir}/strace
99 101
 %{_bindir}/strace-log-merge
102
+%{_bindir}/asinfo
100 103
 %{_mandir}/man1/*
101 104
 
102 105
 %changelog

+ 9
- 0
tools/Makefile.am View File

@@ -0,0 +1,9 @@
1
+# Automake input for strace tools.
2
+#
3
+# Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
4
+# Copyright (c) 2017-2018 The strace developers.
5
+# All rights reserved.
6
+#
7
+# SPDX-License-Identifier: GPL-2.0-or-later
8
+
9
+SUBDIRS = asinfo

+ 56
- 0
tools/asinfo/Makefile.am View File

@@ -0,0 +1,56 @@
1
+# Automake input for asinfo.
2
+#
3
+# Copyright (c) 2017 Edgar Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
4
+# Copyright (c) 2017-2018 The strace developers.
5
+# All rights reserved.
6
+#
7
+# SPDX-License-Identifier: GPL-2.0-or-later
8
+
9
+SUBDIRS = . tests
10
+
11
+bin_PROGRAMS = asinfo
12
+man_MANS = asinfo.1
13
+
14
+OS = linux
15
+
16
+AUTOMAKE_OPTIONS = subdir-objects
17
+
18
+AM_CFLAGS = $(WARN_CFLAGS)
19
+AM_CPPFLAGS = -I$(builddir) \
20
+	      -I$(top_builddir)/$(OS) \
21
+	      -I$(top_srcdir)/$(OS) \
22
+	      -I$(top_builddir) \
23
+	      -I$(top_srcdir)
24
+
25
+include Makemodule.am
26
+
27
+asinfo_CPPFLAGS = $(AM_CPPFLAGS)
28
+asinfo_CFLAGS = $(AM_CFLAGS)
29
+
30
+asinfo_SOURCES =		\
31
+	arch_definitions.h	\
32
+	arch_interface.c	\
33
+	$(ARCH_AUX_FILES)	\
34
+	arch_interface.h	\
35
+	asinfo.c		\
36
+	../../basic_filters.c	\
37
+	dispatchers.c		\
38
+	dispatchers.h		\
39
+	error_interface.c	\
40
+	error_interface.h	\
41
+	../../error_prints.c	\
42
+	../../error_prints.h	\
43
+	../../filter.h		\
44
+	../../macros.h		\
45
+	../../number_set.c	\
46
+	../../number_set.h	\
47
+	request_msgs.h		\
48
+	../../string_to_uint.h	\
49
+	../../string_to_uint.c	\
50
+	syscall_interface.c	\
51
+	syscall_interface.h	\
52
+	../../sysent_shorthand_defs.h \
53
+	../../sysent_shorthand_undefs.h \
54
+	../../xmalloc.c		\
55
+	../../xmalloc.h		\
56
+	#end of asinfo_SOURCES

+ 37
- 0
tools/asinfo/README-arch View File

@@ -0,0 +1,37 @@
1
+This file describes the storage format of arch_definitions.h
2
+
3
+Storage format:
4
+/* [ARCH_SPECIFIC_DEFINE],[ACONST1,ACONST2] */
5
+ARCH_DESC_DEFINE(ARCH_NAME,ARCH_ABI,PASS({COMPAT_PERS1,COMPAT_PERS2,...}),\
6
+PASS({ALIAS1,ALIAS2,...}))
7
+
8
+ARCH_SPECIFIC_DEFINE:
9
+One syscallent.h header can contain several set of system calls for each
10
+compatible mode. And specific set can be switched by passing particular
11
+definition.
12
+So ARCH_SPECIFIC_DEFINE allows to forward a given definition, where
13
+!ARCH_SPECIFIC_DEFINE forwards undefined.
14
+If it is not required, left empty.
15
+
16
+ACONST1,ACONST2:
17
+It could be used to store architecture specific constants and pass them to code.
18
+If is is not required each one must be set to zero.
19
+
20
+ARCH_NAME:
21
+The main name of architecture will be used to generate the personality
22
+constants.
23
+The personality constant is equal to ARCH_+\$ARCH_ABI+_+\$ARCH_NAME.
24
+
25
+ARCH_ABI:
26
+Application binary interface for a given architecture, i.e. 32bit, 64bit, oabi,
27
+eabi, o32 etc.
28
+
29
+COMPAT_PERS1,COMPAT_PERS2,...:
30
+Compatible mode for a given architecture. It should be one of personality
31
+constants.
32
+If is is not required, left empty.
33
+
34
+ALIAS1,ALIAS2,...:
35
+Other name of the same architecture, like x86 and i386. At least one alias
36
+must to be set as it shows the name of architecture while printing.
37
+If current ARCH_NAME is just the compatible ABI mode, left empty.

+ 64
- 0
tools/asinfo/arch_definitions.h View File

@@ -0,0 +1,64 @@
1
+/* [],[aarch64/syscallent.h],[0,0] */
2
+ARCH_DESC_DEFINE(aarch64,	64bit,		PASS({ARCH_arm_eabi}),				PASS({"aarch64", "arm64"})			),
3
+/* [],[alpha/syscallent.h],[0,0] */
4
+ARCH_DESC_DEFINE(alpha,		64bit,		PASS({}),					PASS({"alpha"})					),
5
+/* [],[arc/syscallent.h],[0,0] */
6
+ARCH_DESC_DEFINE(arc,		32bit,		PASS({}),					PASS({"arc"})					),
7
+/* [!__ARM_EABI__],[arm/syscallent.h],[ARM_FIRST_SHUFFLED_SYSCALL,ARM_LAST_SPECIAL_SYSCALL] */
8
+ARCH_DESC_DEFINE(arm,		oabi,		PASS({ARCH_arm_eabi}),				PASS({"arm"})					),
9
+/* [__ARM_EABI__],[arm/syscallent.h],[ARM_FIRST_SHUFFLED_SYSCALL,ARM_LAST_SPECIAL_SYSCALL] */
10
+ARCH_DESC_DEFINE(arm,		eabi,		PASS({}),					PASS({})					),
11
+/* [],[avr32/syscallent.h],[0,0] */
12
+ARCH_DESC_DEFINE(avr32,		32bit,		PASS({}),					PASS({"avr32"})					),
13
+/* [],[bfin/syscallent.h],[0,0] */
14
+ARCH_DESC_DEFINE(blackfin,	32bit,		PASS({}),					PASS({"blackfin", "bfin"})			),
15
+/* [],[ia64/syscallent.h],[0,0] */
16
+ARCH_DESC_DEFINE(ia64,		64bit,		PASS({}),					PASS({"ia64"})					),
17
+/* [],[m68k/syscallent.h],[0,0] */
18
+ARCH_DESC_DEFINE(m68k,		32bit,		PASS({}),					PASS({"m68k"})					),
19
+/* [],[metag/syscallent.h],[0,0] */
20
+ARCH_DESC_DEFINE(metag,		32bit,		PASS({}),					PASS({"metag"})					),
21
+/* [],[microblaze/syscallent.h],[0,0] */
22
+ARCH_DESC_DEFINE(microblaze,	32bit,		PASS({}),					PASS({"microblaze"})				),
23
+/* [LINUX_MIPSN64],[dummy.h,mips/syscallent-compat.h,mips/syscallent-n64.h],[0,0] */
24
+ARCH_DESC_DEFINE(mips64,	n64,		PASS({ARCH_mips64_n32, ARCH_mips_o32}),		PASS({"mips64", "mips64le"})			),
25
+/* [LINUX_MIPSN32],[dummy.h,mips/syscallent-compat.h,mips/syscallent-n32.h],[0,0] */
26
+ARCH_DESC_DEFINE(mips64,	n32,		PASS({ARCH_mips_o32}),				PASS({})					),
27
+/* [LINUX_MIPSO32],[dummy.h,mips/syscallent-compat.h,mips/syscallent-o32.h],[0,0] */
28
+ARCH_DESC_DEFINE(mips,		o32,		PASS({}),					PASS({"mips", "mipsle"})			),
29
+/* [],[nios2/syscallent.h],[0,0] */
30
+ARCH_DESC_DEFINE(nios2,		32bit,		PASS({}),					PASS({"nios2"})					),
31
+/* [],[or1k/syscallent.h],[0,0] */
32
+ARCH_DESC_DEFINE(openrisc,	32bit,		PASS({}),					PASS({"openrisc", "or1k"})			),
33
+/* [],[hppa/syscallent.h],[0,0] */
34
+ARCH_DESC_DEFINE(hppa,		32bit,		PASS({}),					PASS({"parisc", "hppa"})			),
35
+/* [],[powerpc/syscallent.h],[0,0] */
36
+ARCH_DESC_DEFINE(ppc,		32bit,		PASS({}),					PASS({"ppc", "ppcle", "powerpc"})		),
37
+/* [],[powerpc64/syscallent.h],[0,0] */
38
+ARCH_DESC_DEFINE(ppc64,		64bit,		PASS({ARCH_ppc_32bit}),				PASS({"ppc64", "ppc64le", "powerpc64"})		),
39
+/* [],[riscv64/syscallent.h],[0,0] */
40
+ARCH_DESC_DEFINE(riscv64,	64bit,		PASS({}),					PASS({"riscv64"})					),
41
+/* [],[s390/syscallent.h],[0,0] */
42
+ARCH_DESC_DEFINE(s390,		32bit,		PASS({}),					PASS({"s390"})					),
43
+/* [],[s390x/syscallent.h],[0,0] */
44
+ARCH_DESC_DEFINE(s390x,		64bit,		PASS({}),					PASS({"s390x"})					),
45
+/* [],[sh/syscallent.h],[0,0] */
46
+ARCH_DESC_DEFINE(sh,		32bit,		PASS({}),					PASS({"sh"})					),
47
+/* [],[sh64/syscallent.h],[0,0] */
48
+ARCH_DESC_DEFINE(sh64,		64bit,		PASS({}),					PASS({"sh64"})					),
49
+/* [],[sparc/syscallent.h],[0,0] */
50
+ARCH_DESC_DEFINE(sparc,		32bit,		PASS({}),					PASS({"sparc"})					),
51
+/* [],[sparc64/syscallent.h],[0,0] */
52
+ARCH_DESC_DEFINE(sparc64,	64bit,		PASS({ARCH_sparc_32bit}),			PASS({"sparc64"})				),
53
+/* [],[tile/syscallent.h],[0,0] */
54
+ARCH_DESC_DEFINE(tile,		64bit,		PASS({ARCH_tile_32bit}),			PASS({"tile", "tilegx"})			),
55
+/* [],[tile/syscallent1.h],[0,0] */
56
+ARCH_DESC_DEFINE(tile,		32bit,		PASS({}),					PASS({"tilepro"})				),
57
+/* [],[x86_64/syscallent.h],[0,0] */
58
+ARCH_DESC_DEFINE(x86_64,	64bit,		PASS({ARCH_x86_64_x32, ARCH_x86_32bit}),	PASS({"x86_64", "amd64", "EM64T"})		),
59
+/* [],[x86_64/syscallent2.h],[0,0] */
60
+ARCH_DESC_DEFINE(x86_64,	x32,		PASS({ARCH_x86_32bit}),				PASS({})					),
61
+/* [],[i386/syscallent.h],[0,0] */
62
+ARCH_DESC_DEFINE(x86,		32bit,		PASS({}),					PASS({"x86", "i386", "i486", "i586", "i686"})	),
63
+/* [],[xtensa/syscallent.h],[0,0] */
64
+ARCH_DESC_DEFINE(xtensa,	32bit,		PASS({}),					PASS({"xtensa"})				)

+ 607
- 0
tools/asinfo/arch_interface.c View File

@@ -0,0 +1,607 @@
1
+/*
2
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
3
+ * Copyright (c) 2017-2018 The strace developers.
4
+ * All rights reserved.
5
+ *
6
+ * SPDX-License-Identifier: GPL-2.0-or-later
7
+ */
8
+
9
+#ifdef HAVE_CONFIG_H
10
+# include "config.h"
11
+#endif
12
+
13
+#include <stdio.h>
14
+#include <stdlib.h>
15
+#include <string.h>
16
+
17
+#include "arch_interface.h"
18
+#include "defs.h"
19
+#include "macros.h"
20
+#include "xmalloc.h"
21
+
22
+/* Define these shorthand notations to simplify the syscallent files. */
23
+#include "sysent_shorthand_defs.h"
24
+
25
+/* For the current functionality there is no need
26
+   to use sen and (*sys_func)() fields in sysent struct */
27
+#define SEN(syscall_name) 0, NULL
28
+
29
+/* Generated file based on arch_definitions.h */
30
+#include "arch_includes.h"
31
+
32
+/* Now undef them since short defines cause wicked namespace pollution. */
33
+#include "sysent_shorthand_undefs.h"
34
+
35
+#define PASS(...) __VA_ARGS__
36
+#define ARCH_DESC_DEFINE(arch, mode, comp_pers, arch_aliases) \
37
+	[ARCH_##arch##_##mode] = { \
38
+		.pers			= ARCH_##arch##_##mode, \
39
+		.arch_name		= arch_aliases, \
40
+		.abi_mode		= #mode, \
41
+		.abi_mode_len		= ARRAY_SIZE(#arch) - 1, \
42
+		.compat_pers		= comp_pers, \
43
+		.max_scn		= ARRAY_SIZE(arch##_##mode##_sysent), \
44
+		.syscall_list		= arch##_##mode##_sysent, \
45
+		.user_num1		= &arch##_##mode##_usr1, \
46
+		.user_num2		= &arch##_##mode##_usr2, \
47
+	}
48
+
49
+/* Generate array of arch_descriptors for each personality */
50
+const struct arch_descriptor architectures[] = {
51
+	#include "arch_definitions.h"
52
+};
53
+
54
+#undef ARCH_DESC_DEFINE
55
+#undef PASS
56
+
57
+struct arch_service *
58
+al_create(unsigned capacity)
59
+{
60
+	ARCH_LIST_DEFINE(as) = NULL;
61
+
62
+	if (!capacity)
63
+		return NULL;
64
+	as = xcalloc(sizeof(*as), 1);
65
+	as->arch_list = xcalloc(sizeof(*(as->arch_list)), capacity);
66
+	as->flag = xcalloc(sizeof(*(as->flag)), capacity);
67
+	as->in_aname = xcalloc(sizeof(*(as->in_aname)), capacity);
68
+	as->err = es_create();
69
+	as->capacity = capacity;
70
+	as->next_free = 0;
71
+	return as;
72
+}
73
+
74
+int
75
+al_push(struct arch_service *m, const struct arch_descriptor *element)
76
+{
77
+	if (m->next_free >= m->capacity)
78
+		return -1;
79
+	m->arch_list[m->next_free] = element;
80
+	m->flag[m->next_free] = AD_FLAG_EMPTY;
81
+	m->next_free++;
82
+	return 0;
83
+}
84
+
85
+static inline int
86
+al_is_index_ok(struct arch_service *m, unsigned index)
87
+{
88
+	if (index >= m->next_free)
89
+		return -1;
90
+	return 0;
91
+}
92
+
93
+int
94
+al_set_flag(struct arch_service *m, unsigned index, int flag)
95
+{
96
+	if (al_is_index_ok(m, index) == 0) {
97
+		m->flag[index] = flag;
98
+		return 0;
99
+	}
100
+	return -1;
101
+}
102
+
103
+int
104
+al_add_flag(struct arch_service *m, unsigned index, int flag)
105
+{
106
+	if (al_is_index_ok(m, index) == 0) {
107
+		m->flag[index] = m->flag[index] | flag;
108
+		return 0;
109
+	}
110
+	return -1;
111
+}
112
+
113
+int
114
+al_sub_flag(struct arch_service *m, unsigned index, int flag)
115
+{
116
+	if (al_is_index_ok(m, index) == 0) {
117
+		m->flag[index] = m->flag[index] & ~flag;
118
+		return 0;
119
+	}
120
+	return -1;
121
+}
122
+
123
+const struct arch_descriptor *
124
+al_get(struct arch_service *m, unsigned index)
125
+{
126
+	if (al_is_index_ok(m, index) != 0)
127
+		return NULL;
128
+	return m->arch_list[index];
129
+}
130
+
131
+unsigned int
132
+al_size(struct arch_service *m)
133
+{
134
+	return m->next_free;
135
+}
136
+
137
+void
138
+al_free(struct arch_service *m)
139
+{
140
+	int i;
141
+	int size = al_size(m);
142
+
143
+	for (i = 0; i < size; i++)
144
+		if (al_in_aname(m, i) != NULL)
145
+			free(al_in_aname(m, i));
146
+	free(m->arch_list);
147
+	free(m->flag);
148
+	free(m->in_aname);
149
+	es_free(m->err);
150
+	free(m);
151
+}
152
+
153
+struct error_service *al_err(struct arch_service *m)
154
+{
155
+	return m->err;
156
+}
157
+
158
+enum arch_pers
159
+al_pers(struct arch_service *m, unsigned index)
160
+{
161
+	const struct arch_descriptor *elem = al_get(m, index);
162
+
163
+	return (elem ? elem->pers : ARCH_no_pers);
164
+}
165
+
166
+const char **
167
+al_arch_name(struct arch_service *m, unsigned index)
168
+{
169
+	const struct arch_descriptor *elem = al_get(m, index);
170
+
171
+	return (elem ? (const char **)elem->arch_name : NULL);
172
+}
173
+
174
+enum arch_pers *
175
+al_cpers(struct arch_service *m, unsigned index)
176
+{
177
+	const struct arch_descriptor *elem = al_get(m, index);
178
+
179
+	return (elem ? (enum arch_pers *)elem->compat_pers : NULL);
180
+}
181
+
182
+const char *
183
+al_abi_mode(struct arch_service *m, unsigned index)
184
+{
185
+	const struct arch_descriptor *elem = al_get(m, index);
186
+
187
+	return (elem ? elem->abi_mode : NULL);
188
+}
189
+
190
+int
191
+al_abi_mode_len(struct arch_service *m, unsigned index)
192
+{
193
+	const struct arch_descriptor *elem = al_get(m, index);
194
+
195
+	return (elem ? elem->abi_mode_len : -1);
196
+}
197
+
198
+int
199
+al_flag(struct arch_service *m, unsigned index)
200
+{
201
+	int status = al_is_index_ok(m, index);
202
+
203
+	return (!status ? m->flag[index] : -1);
204
+}
205
+
206
+int
207
+al_set_in_aname(struct arch_service *m, unsigned index, char *aname)
208
+{
209
+	int status = al_is_index_ok(m, index);
210
+
211
+	if (status)
212
+		return -1;
213
+	m->in_aname[index] = aname;
214
+	return 0;
215
+}
216
+
217
+char *
218
+al_in_aname(struct arch_service *m, unsigned index)
219
+{
220
+	int status = al_is_index_ok(m, index);
221
+
222
+	return (!status ? m->in_aname[index] : NULL);
223
+}
224
+
225
+int
226
+al_psize(struct arch_service *m)
227
+{
228
+	int i;
229
+	int a_size = al_size(m);
230
+	int psize = 0;
231
+
232
+	for (i = 0; i < a_size; i++)
233
+		if (al_flag(m, i) & AD_FLAG_PRINT)
234
+			psize++;
235
+	return psize;
236
+}
237
+
238
+int
239
+al_arch_name_len(struct arch_service *m, unsigned index, int delim_len)
240
+{
241
+	const char **arch_name = NULL;
242
+	int i;
243
+	int final_len = 0;
244
+
245
+	while (!(al_flag(m, index) & AD_FLAG_MPERS))
246
+		index--;
247
+	arch_name = al_arch_name(m, index);
248
+	for (i = 0; (arch_name[i] != NULL) && (i < MAX_ALIASES); i++) {
249
+		final_len += strlen(arch_name[i]);
250
+		final_len += delim_len;
251
+	}
252
+	final_len -= delim_len;
253
+	return final_len;
254
+}
255
+
256
+int
257
+al_syscall_impl(struct arch_service *m, unsigned index)
258
+{
259
+	const struct arch_descriptor *elem = al_get(m, index);
260
+	int count = 0;
261
+
262
+	if (!elem)
263
+		return -1;
264
+	for (unsigned int i = 0; i < elem->max_scn; ++i) {
265
+		if (elem->syscall_list[i].sys_name &&
266
+		    !(elem->syscall_list[i].sys_flags &
267
+		    TRACE_INDIRECT_SUBCALL))
268
+			count++;
269
+	}
270
+	return count;
271
+}
272
+
273
+/* This method is purposed to count the supported ABI modes for the given
274
+   arch */
275
+int
276
+al_get_abi_modes(struct arch_service *m, unsigned index)
277
+{
278
+	const struct arch_descriptor *elem = al_get(m, index);
279
+	int i = 0;
280
+	int abi_count = 1;
281
+
282
+	if (!elem)
283
+		return -1;
284
+	for (i = 0; i < MAX_ALT_ABIS; i++)
285
+		if (elem->compat_pers[i] != ARCH_no_pers)
286
+			abi_count++;
287
+	return abi_count;
288
+}
289
+
290
+/* This method is purposed to find next one name of the same architecture.
291
+   For instance, x86_64 = amd64 */
292
+const char *
293
+al_next_alias(struct arch_service *m, unsigned index)
294
+{
295
+	static int next_alias = -1;
296
+	static const char **arch_name = NULL;
297
+	static unsigned lindex = 0;
298
+
299
+	if (lindex != index) {
300
+		lindex = index;
301
+		next_alias = -1;
302
+	}
303
+	if (al_pers(m, index) == ARCH_no_pers)
304
+		return NULL;
305
+	if (next_alias == -1) {
306
+		next_alias = 0;
307
+		while (!(al_flag(m, index) & AD_FLAG_MPERS))
308
+			index--;
309
+		arch_name = al_arch_name(m, index);
310
+	} else
311
+		next_alias++;
312
+	if (next_alias >= MAX_ALIASES || arch_name[next_alias] == NULL) {
313
+		next_alias = -1;
314
+		return NULL;
315
+	}
316
+	return arch_name[next_alias];
317
+}
318
+
319
+/* This method is purposed to return next one compat personality of the
320
+   same architecture */
321
+enum arch_pers
322
+al_next_cpers(struct arch_service *m, unsigned index)
323
+{
324
+	static int next_pers = -1;
325
+	enum arch_pers *a_pers = al_cpers(m, index);
326
+	static unsigned lindex = 0;
327
+
328
+	if (al_pers(m, index) == ARCH_no_pers)
329
+		return ARCH_no_pers;
330
+	if (lindex != index) {
331
+		lindex = index;
332
+		next_pers = -1;
333
+	}
334
+	if (next_pers == -1)
335
+		next_pers = 0;
336
+	else
337
+		next_pers++;
338
+	if (next_pers >= MAX_ALT_ABIS ||
339
+	    a_pers[next_pers] == ARCH_no_pers) {
340
+		next_pers = -1;
341
+		return ARCH_no_pers;
342
+	}
343
+	return a_pers[next_pers];
344
+}
345
+
346
+static enum impl_type
347
+al_indirect_subcall(struct arch_service *m, unsigned index, const char *name)
348
+{
349
+	const struct arch_descriptor *elem = al_get(m, index);
350
+	unsigned int impl = IMPL_none;
351
+
352
+	for (unsigned int i = 0; i < elem->max_scn; ++i) {
353
+		if (!elem->syscall_list[i].sys_name)
354
+			continue;
355
+		if (!strcmp(elem->syscall_list[i].sys_name, name)) {
356
+			if (!(elem->syscall_list[i].sys_flags &
357
+			     TRACE_INDIRECT_SUBCALL))
358
+				impl |= IMPL_ext;
359
+			else
360
+				impl |= IMPL_int;
361
+		}
362
+	}
363
+	return impl;
364
+}
365
+
366
+/* This method is purposed to create extended list of architectures */
367
+struct arch_service *
368
+al_create_filled(void)
369
+{
370
+	static const int architectures_size = ARRAY_SIZE(architectures) - 1;
371
+	ARCH_LIST_DEFINE(as) = al_create(architectures_size);
372
+	ARCH_LIST_DEFINE(f_as);
373
+	enum arch_pers cpers;
374
+	int esize = 0;
375
+	const char **arch_name = NULL;
376
+	int i;
377
+
378
+	/* Push and calculate size of extended table */
379
+	for (i = 0; i < architectures_size; i++) {
380
+		al_push(as, &(architectures[i + 1]));
381
+		arch_name = al_arch_name(as, i);
382
+		if (arch_name[0] != NULL)
383
+			esize += al_get_abi_modes(as, i);
384
+	}
385
+	f_as = al_create(esize);
386
+	/* Fill extended teble */
387
+	for (i = 0; i < architectures_size; i++) {
388
+		arch_name = al_arch_name(as, i);
389
+		if (arch_name[0] == NULL)
390
+			continue;
391
+		al_push(f_as, al_get(as, i));
392
+		al_add_flag(f_as, al_size(f_as) - 1, AD_FLAG_MPERS);
393
+		while ((cpers = al_next_cpers(as, i)) != ARCH_no_pers)
394
+			al_push(f_as, &(architectures[cpers]));
395
+	}
396
+	free(as);
397
+	return f_as;
398
+}
399
+
400
+/* To look up arch in arch_descriptor array */
401
+int
402
+al_mark_matches(struct arch_service *m, char *arch_str)
403
+{
404
+	int arch_match = -1;
405
+	char *match_pointer = NULL;
406
+	const char *a_name = NULL;
407
+	int al_size_full = al_size(m);
408
+	unsigned prev_arch_len = 0;
409
+	int i;
410
+	int a_abi;
411
+	char *in_aname;
412
+
413
+	if (arch_str == NULL)
414
+		return -1;
415
+	/* Here we find the best match for arch_str in architecture list.
416
+	   Best match means here that we have to find the longest name of
417
+	   architecture in a_full_list with arch_str substring, beginning
418
+	   from the first letter */
419
+	for (i = 0; i < al_size_full; i++) {
420
+		if (!(al_flag(m, i) & AD_FLAG_MPERS))
421
+			continue;
422
+		while ((a_name = al_next_alias(m, i)) != NULL) {
423
+			match_pointer = strstr(arch_str, a_name);
424
+			if (match_pointer == NULL || match_pointer != arch_str)
425
+				continue;
426
+			if (arch_match == -1 ||
427
+			    strlen(a_name) > prev_arch_len) {
428
+				prev_arch_len = strlen(a_name);
429
+				arch_match = i;
430
+			}
431
+		}
432
+	}
433
+	if (arch_match == -1)
434
+		return -1;
435
+	/* Now we find all ABI modes related to the architecture */
436
+	if ((a_abi = al_get_abi_modes(m, arch_match)) == -1)
437
+		return -1;
438
+	for (i = arch_match; i < (arch_match + a_abi); i++) {
439
+		al_add_flag(m, i, AD_FLAG_PRINT);
440
+		in_aname = xcalloc(sizeof(*in_aname), strlen(arch_str) + 1);
441
+		strcpy(in_aname, arch_str);
442
+		al_set_in_aname(m, i, in_aname);
443
+	}
444
+	return 0;
445
+}
446
+
447
+/* Join all architectures from 'f' and architectures with AD_FLAG_PRINT
448
+   from 's' arch_service structures */
449
+struct arch_service *
450
+al_join_print(struct arch_service *f, struct arch_service *s)
451
+{
452
+	int size1 = (f ? al_size(f) : 0);
453
+	int psize2 = al_psize(s);
454
+	int size2 = al_size(s);
455
+	int i;
456
+	int start_point = 0;
457
+	ARCH_LIST_DEFINE(final) = al_create(size1 + psize2);
458
+
459
+	for (i = 0; i < size2; i++)
460
+		if (al_flag(s, i) & AD_FLAG_PRINT) {
461
+			start_point = i;
462
+			break;
463
+		}
464
+	for (i = 0; i < size1; i++) {
465
+		al_push(final, al_get(f, i));
466
+		al_set_flag(final, i, al_flag(f, i));
467
+		al_set_in_aname(final, i, al_in_aname(f, i));
468
+		al_set_in_aname(f, i, NULL);
469
+	}
470
+	for (i = 0; i < psize2; i++) {
471
+		al_push(final, al_get(s, start_point + i));
472
+		al_set_flag(final, size1 + i , al_flag(s, start_point + i));
473
+		al_set_in_aname(final, size1 + i,
474
+				al_in_aname(s, start_point + i));
475
+		al_set_in_aname(s, start_point + i, NULL);
476
+		al_sub_flag(s, start_point + i, AD_FLAG_PRINT);
477
+	}
478
+	if (f)
479
+		al_free(f);
480
+	return final;
481
+}
482
+
483
+/* To avoid duplication of for(;;) construction */
484
+void
485
+al_unmark_all(struct arch_service *m, int flag)
486
+{
487
+	int a_size = al_size(m);
488
+	int i;
489
+
490
+	for (i = 0; i < a_size; i++)
491
+		al_sub_flag(m, i, flag);
492
+}
493
+
494
+/* Select one compatible personality in range of one architecture */
495
+int
496
+al_mark_pers4arch(struct arch_service *m, unsigned index, const char *abi_mode)
497
+{
498
+	unsigned i = index;
499
+
500
+	while (!(al_flag(m, i) & AD_FLAG_MPERS) || (i == index)) {
501
+		if (strcmp(abi_mode, "all") == 0) {
502
+			al_add_flag(m, i, AD_FLAG_PRINT);
503
+			i++;
504
+			if ((al_is_index_ok(m, i)) ||
505
+			    (al_flag(m, i) & AD_FLAG_MPERS))
506
+				return 0;
507
+			else
508
+				continue;
509
+		}
510
+		if (strcmp(al_abi_mode(m, i), abi_mode) == 0) {
511
+			al_add_flag(m, i, AD_FLAG_PRINT);
512
+			return 0;
513
+		}
514
+		i++;
515
+	}
516
+	return -1;
517
+}
518
+
519
+void
520
+al_dump(struct arch_service *m, int is_raw)
521
+{
522
+	static const char *title[] = {
523
+		"N",
524
+		"Architecture name",
525
+		"ABI mode",
526
+		/* Implemented syscalls */
527
+		"IMPL syscalls",
528
+		/* IPC implementation */
529
+		"IPC IMPL",
530
+		/* SOCKET implementation */
531
+		"SOCKET IMPL"
532
+	};
533
+	int title_len[] = {
534
+		0,
535
+		strlen(title[1]),
536
+		strlen(title[2]),
537
+		strlen(title[3]),
538
+		strlen(title[4]),
539
+		strlen(title[5]),
540
+	};
541
+	static const char *impl_st[] = {
542
+		"none",
543
+		"external",
544
+		"internal",
545
+		"int/ext"
546
+	};
547
+	static const char *delim = "/";
548
+	int i = 0;
549
+	int N = 0;
550
+	int temp_len = 0;
551
+	int arch_size = al_size(m);
552
+	int arch_psize = al_psize(m);
553
+	const char *next_alias = NULL;
554
+	char *whole_arch_name;
555
+
556
+	/* Calculate length of the column with the number of architectures */
557
+	for (i = 1; arch_psize/i != 0; i *= 10)
558
+		title_len[0]++;
559
+	for (i = 0; i < arch_size; i++) {
560
+		if (!(al_flag(m, i) & AD_FLAG_PRINT))
561
+			continue;
562
+		/* Calculate length of the column with the
563
+		   architectures name */
564
+		temp_len = al_arch_name_len(m, i, strlen(delim));
565
+		if (temp_len > title_len[1])
566
+			title_len[1] = temp_len;
567
+		/* Calculate length of the column with the ABI mode */
568
+		if (al_abi_mode_len(m, i) > title_len[2])
569
+			title_len[2] = al_abi_mode_len(m, i);
570
+	}
571
+
572
+	whole_arch_name = xcalloc(title_len[1] + 1, sizeof(*whole_arch_name));
573
+	/* Output title */
574
+	if (!is_raw)
575
+		printf("| %*s | %*s | %*s | %*s | %*s | %*s |\n",
576
+			title_len[0], title[0], title_len[1], title[1],
577
+			title_len[2], title[2], title_len[3], title[3],
578
+			title_len[4], title[4], title_len[5], title[5]);
579
+	/* Output architectures */
580
+	for (i = 0; i < arch_size; i++) {
581
+		if (!(al_flag(m, i) & AD_FLAG_PRINT))
582
+			continue;
583
+		N++;
584
+		memset(whole_arch_name, 0, title_len[1]);
585
+		/* Put all the same arch back together */
586
+		next_alias = al_next_alias(m, i);
587
+		strcat(whole_arch_name, next_alias);
588
+		while ((next_alias = al_next_alias(m, i)) != NULL) {
589
+			strcat(whole_arch_name, delim);
590
+			strcat(whole_arch_name, next_alias);
591
+		}
592
+		if (is_raw) {
593
+			printf("%u;%s;%s;%d;%s;%s;\n", N, whole_arch_name,
594
+			       al_abi_mode(m, i), al_syscall_impl(m, i),
595
+			       impl_st[al_indirect_subcall(m, i, "semctl")],
596
+			       impl_st[al_indirect_subcall(m, i, "socket")]);
597
+			continue;
598
+		}
599
+		printf("| %*u | ", title_len[0], N);
600
+		printf("%*s | ", title_len[1], whole_arch_name);
601
+		printf("%*s | ", title_len[2], al_abi_mode(m, i));
602
+		printf("%*d | ", title_len[3], al_syscall_impl(m, i));
603
+		printf("%*s | ", title_len[4], impl_st[al_indirect_subcall(m, i, "semctl")]);
604
+		printf("%*s |\n", title_len[5], impl_st[al_indirect_subcall(m, i, "socket")]);
605
+	}
606
+	free(whole_arch_name);
607
+}

+ 144
- 0
tools/asinfo/arch_interface.h View File

@@ -0,0 +1,144 @@
1
+/*
2
+ * The arch_interface.h is purposed to interact with the basic data structure
3
+ * based on arch_descriptor struct. Mainly this set of methods are used by
4
+ * arch_dispatcher.
5
+ *
6
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedv@virtuozzo.com>
7
+ * Copyright (c) 2017-2018 The strace developers.
8
+ * All rights reserved.
9
+ *
10
+ * SPDX-License-Identifier: GPL-2.0-or-later
11
+ */
12
+#ifndef ASINFO_ARCH_INTERFACE_H
13
+#define ASINFO_ARCH_INTERFACE_H
14
+
15
+#include "error_interface.h"
16
+#include "sysent.h"
17
+
18
+/* Type implementaion of syscall, internal means as a subcall,
19
+   external means a separate syscall, this enum is purposed for
20
+   well-known ipc and socket subcall group */
21
+enum impl_type {
22
+	IMPL_none = 0,
23
+	IMPL_ext = 1,
24
+	IMPL_int = 2,
25
+	IMPL_int_ext = IMPL_ext | IMPL_int
26
+};
27
+
28
+/* Names of personalities
29
+ * arch_pers = ARCH_ + kernel_kernel/other_name + abi_mode */
30
+enum arch_pers {
31
+	#include "arch_personalities.h"
32
+};
33
+
34
+#define MAX_ALIASES 6
35
+#define MAX_ALT_ABIS 3
36
+
37
+struct arch_descriptor {
38
+	enum arch_pers pers;
39
+	const char *arch_name[MAX_ALIASES];
40
+	const char *abi_mode;
41
+	const int abi_mode_len;
42
+	enum arch_pers compat_pers[MAX_ALT_ABIS];
43
+	const unsigned int max_scn;
44
+	const struct_sysent *syscall_list;
45
+	/* In the most cases these fields are purposed to store specific for
46
+	   given arch constants, for instance, ARM_FIRST_SHUFFLED_SYSCALL */
47
+	const int *user_num1;
48
+	const int *user_num2;
49
+};
50
+
51
+#define AD_FLAG_EMPTY 0
52
+/* to hide some abi modes belonging to one architecture */
53
+#define AD_FLAG_PRINT	(1 << 0)
54
+/* main personality, like x86_64 64bit */
55
+#define AD_FLAG_MPERS	(1 << 1)
56
+
57
+/* To provide push-back interface with arch_list */
58
+struct arch_service {
59
+	/* immutable field */
60
+	const struct arch_descriptor **arch_list;
61
+	/* User flags for each arch_descriptor */
62
+	int *flag;
63
+	/* To support conformity between ABI and ARCH */
64
+	char **in_aname;
65
+	struct error_service *err;
66
+	unsigned capacity;
67
+	unsigned next_free;
68
+};
69
+
70
+#define ARCH_LIST_DEFINE(name) \
71
+	struct arch_service *(name)
72
+
73
+/* Push-back interface is purposed to simplify interaction with
74
+   arch_service struct
75
+   NOTE: al - architecture list */
76
+
77
+/* base methods */
78
+struct arch_service *al_create(unsigned capacity);
79
+
80
+int al_push(struct arch_service *m, const struct arch_descriptor *element);
81
+
82
+int al_set_flag(struct arch_service *m, unsigned index, int flag);
83
+
84
+int al_add_flag(struct arch_service *m, unsigned index, int flag);
85
+
86
+int al_sub_flag(struct arch_service *m, unsigned index, int flag);
87
+
88
+const struct arch_descriptor *al_get(struct arch_service *m, unsigned index);
89
+
90
+unsigned int al_size(struct arch_service *m);
91
+
92
+void al_free(struct arch_service *m);
93
+
94
+struct error_service *al_err(struct arch_service *m);
95
+
96
+/* methods returning fields with error check */
97
+enum arch_pers al_pers(struct arch_service *m, unsigned index);
98
+
99
+const char **al_arch_name(struct arch_service *m, unsigned index);
100
+
101
+enum arch_pers *al_cpers(struct arch_service *m, unsigned index);
102
+
103
+const char *al_abi_mode(struct arch_service *m, unsigned index);
104
+
105
+int al_abi_mode_len(struct arch_service *m, unsigned index);
106
+
107
+int al_flag(struct arch_service *m, unsigned index);
108
+
109
+int al_set_in_aname(struct arch_service *m, unsigned index, char *aname);
110
+
111
+char *al_in_aname(struct arch_service *m, unsigned index);
112
+
113
+/* calculating methods */
114
+int al_psize(struct arch_service *m);
115
+
116
+int al_arch_name_len(struct arch_service *m, unsigned index, int delim_len);
117
+
118
+int al_syscall_impl(struct arch_service *m, unsigned index);
119
+
120
+int al_get_abi_modes(struct arch_service *m, unsigned index);
121
+
122
+const char *al_next_alias(struct arch_service *m, unsigned index);
123
+
124
+enum arch_pers al_next_cpers(struct arch_service *m, unsigned index);
125
+
126
+enum impl_type al_ipc_syscall(struct arch_service *m, unsigned index);
127
+
128
+enum impl_type al_sck_syscall(struct arch_service *m, unsigned index);
129
+
130
+struct arch_service *al_create_filled(void);
131
+
132
+int al_mark_matches(struct arch_service *m, char *arch_str);
133
+
134
+struct arch_service *al_join_print(struct arch_service *f,
135
+				   struct arch_service *s);
136
+
137
+void al_unmark_all(struct arch_service *m, int flag);
138
+
139
+int al_mark_pers4arch(struct arch_service *m, unsigned index,
140
+		      const char *abi_mode);
141
+
142
+void al_dump(struct arch_service *m, int is_raw);
143
+
144
+#endif /* !ASINFO_ARCH_INTERFACE_H */

+ 264
- 0
tools/asinfo/asinfo.1.in View File

@@ -0,0 +1,264 @@
1
+.\" Copyright (c) 2017 Edgar Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
2
+.\" Copyright (c) 1996-2018 The strace developers.
3
+.\" All rights reserved.
4
+.\"
5
+.\" SPDX-License-Identifier: GPL-2.0-or-later
6
+
7
+.\" Required option.
8
+.de OR
9
+.  ie \\n(.$-1 \
10
+.    RI "\fB\\$1\fP" "\ \\$2"
11
+.  el \
12
+.    BR "\\$1"
13
+..
14
+.TH ASINFO 1 "@ASINFO_MANPAGE_DATE@" "strace package @VERSION@"
15
+.SH NAME
16
+asinfo \- Advanced System call INFOrmation tool
17
+.SH SYNOPSIS
18
+.SY asinfo
19
+.BR "" \fR[{
20
+.OR \-\-set\-arch arch
21
+.BR "" |
22
+.OR \-\-get\-arch
23
+.BR "" }
24
+.OR \fR[\fP\-\-set\-abi abi
25
+.BR "" |
26
+.OR \-\-list\-abi\fR]\fR]
27
+.BR "" {
28
+.BR "" {
29
+.OR \-\-get\-sname expr
30
+.BR "" |
31
+.OR \-\-get\-snum expr
32
+.BR "" }
33
+.OP \-\-nargs
34
+.BR "" }
35
+.OP "\-\-raw"
36
+.YS
37
+.SY asinfo
38
+.BR "" {
39
+.OR \-\-set\-arch arch
40
+.BR "" |
41
+.OR \-\-get\-arch
42
+.BR "" |
43
+.OR \-\-list\-arch
44
+.BR "" }
45
+.BD "" [
46
+.OR \fR[\fP\-\-set\-abi abi
47
+.BR "" |
48
+.OR \-\-list\-abi\fR]
49
+.OP "\-\-raw"
50
+
51
+.SH DESCRIPTION
52
+.B asinfo
53
+provides information about various aspects of system calls across architectures
54
+using
55
+.B strace
56
+knowledge base.
57
+
58
+In the simplest
59
+case it provides mapping from system call name to number and reverse.
60
+The main advantage of tool is it can work in single/multi arch modes with
61
+the opportunity to show discrepancies in system call characteristics.
62
+Also, the single arch mode allows program to take a guess about the
63
+current architecture and ABI, if they are not specified. Furthermore,
64
+.B asinfo
65
+provides convenient filtering for selecting system calls.
66
+
67
+.SH OPTIONS
68
+.SS "Architecture parameters"
69
+.TP 7
70
+.BI "\-\-set\-arch " arch
71
+Specify architecture/architectures manually. The format of the
72
+.I arch
73
+expression is:
74
+.RS 9
75
+.IP
76
+\fIarch1\/\fR[\fB,\fIarch2\/\fR]...
77
+.RE
78
+.IP
79
+.TP
80
+.B \-\-get\-arch
81
+Select achitecture based on the current machine.
82
+.TP
83
+.B \-\-list-arch
84
+Print out all supported architectures.
85
+Combined use with any ABI option is permitted.
86
+.SS "ABI parameters"
87
+.TP 7
88
+.BI "\-\-set\-abi " abi
89
+Specify ABI/ABIs manually. The format of the experession is:
90
+.RS 9
91
+.IP
92
+\fIabi1\/\fR[\fB,\fIabi2\/\fR]...
93
+.RE
94
+.IP
95
+.IP
96
+Note that ABI should be selected for each corresponding architecture.
97
+In addition, the special value
98
+.B all
99
+allows to choose all ABIs for the respective architecture.
100
+.TP
101
+.B "\-\-list\-abi "
102
+Select all ABIs for the chosen architecture/architectures.
103
+.IP
104
+If ABI parameters are not used and only single architecture is selected, tool
105
+will take a guess about ABI based on the strace package build.
106
+.SS "System call parameters"
107
+.TP 7
108
+.BI "\-\-get\-sname " expr
109
+Select system calls that satisfy a filtering expression
110
+.I
111
+expr
112
+and print out name of system calls and numbers for each architecture/ABI.
113
+.TP
114
+.BI "\-\-get\-snum " expr
115
+Select system calls that satisfy a filtering expression
116
+.I
117
+expr
118
+and print out number of system calls and names for each architecture/ABI.
119
+.TP
120
+.B \-\-nargs
121
+Switch the second output system call characteristic to number of arguments.
122
+.SS Output formatting
123
+.TP 7
124
+.B "\-\-raw"
125
+Reset alignment and remove titles, use ';' as a delimiter.
126
+.SS Miscellaneous
127
+.TP 7
128
+.B \-h
129
+Print the help summary.
130
+.TP
131
+.B \-v
132
+Print the version number.
133
+
134
+.SH "FILTERING EXPRESSION"
135
+A filtering expression is a pattern that describes a set of syscall names,
136
+syscall numbers, and syscall group. The format of the expression is:
137
+.RS 2
138
+.IP
139
+[\fB!\fR][\fB?\fR]\,\fIvalue1\/\fR[\fB,\fR[\fB?\fR]\,\fIvalue2\/\fR]...
140
+.RE
141
+.LP
142
+where
143
+.I value
144
+is a symbol or number. Using an exclamation mark negates the set of values.
145
+For example,
146
+.BR \fIvalue\fR = write
147
+means print strictly the write system call.  By contrast,
148
+.BR \fIvalue\fR = !write
149
+means to dump every system call except write. Question mark before the
150
+syscall qualification allows suppression of error in case no syscalls matched
151
+the qualification provided, that can be particularly useful in multiarch mode,
152
+when system call is not presented in all selected architectures. In addition,
153
+the special values
154
+.B all
155
+and
156
+.B none
157
+have the obvious meanings.
158
+.LP
159
+Note that some shells use the exclamation point for history
160
+expansion even inside quoted arguments.  If so, you must escape
161
+the exclamation point with a backslash.
162
+.SS "Strict match"
163
+.TP 7
164
+.B \fIvalue\fR=\,\fIset\fR
165
+Print out only the specified set of system calls. For example,
166
+.BR \fIvalue\fR = open,close,read,write
167
+means to only show those four system calls.
168
+.SS "Regex match"
169
+.TP 7
170
+.B \fIvalue\fR=/\,\fIregex\fR
171
+Show only those system calls that match the
172
+.IR regex .
173
+You can use
174
+.B POSIX
175
+Extended Regular Expression syntax (see
176
+.BR regex (7)).
177
+.SS "Class match"
178
+.TP 7
179
+.BR \fIvalue\fR = %file
180
+.TQ
181
+.BR \fIvalue\fR  = file " (deprecated)"
182
+Show all system calls which take a file name as an argument.  You
183
+can think of this as an abbreviation for
184
+.BR \fIvalue\fR = open,stat,chmod,unlink,...
185
+Furthermore, using the abbreviation will ensure that you don't
186
+accidentally forget to include a call like
187
+.B lstat
188
+in the list.
189
+.PP
190
+.BR \fIvalue\fR = %process
191
+.TQ
192
+.BR \fIvalue\fR = process " (deprecated)"
193
+Show all system calls which involve process management.
194
+.PP
195
+.BR \fIvalue\fR = %network
196
+.TQ
197
+.BR \fIvalue\fR = network " (deprecated)"
198
+Show all the network related system calls.
199
+.PP
200
+.BR \fIvalue\fR = %signal
201
+.TQ
202
+.BR \fIvalue\fR = signal " (deprecated)"
203
+Show all signal related system calls.
204
+.PP
205
+.BR \fIvalue\fR = %ipc
206
+.TQ
207
+.BR \fIvalue\fR = ipc " (deprecated)"
208
+Show all IPC related system calls.
209
+.PP
210
+.BR \fIvalue\fR = %desc
211
+.TQ
212
+.BR \fIvalue\fR = desc " (deprecated)"
213
+Show all file descriptor related system calls.
214
+.PP
215
+.BR \fIvalue\fR = %memory
216
+.TQ
217
+.BR \fIvalue\fR = memory " (deprecated)"
218
+Show all memory mapping related system calls.
219
+.TP
220
+.BR \fIvalue\fR = %stat
221
+Show stat syscall variants.
222
+.TP
223
+.BR \fIvalue\fR = %lstat
224
+Show lstat syscall variants.
225
+.TP
226
+.BR \fIvalue\fR = %fstat
227
+Show fstat and fstatat syscall variants.
228
+.TP
229
+.BR \fIvalue\fR = %%stat
230
+Show syscalls used for requesting file status (stat, lstat, fstat, fstatat,
231
+statx, and their variants).
232
+.TP
233
+.BR \fIvalue\fR = %statfs
234
+Show statfs, statfs64, statvfs, osf_statfs, and osf_statfs64 system calls.
235
+The same effect can be achieved with
236
+.BR \fIvalue\fR = /^(.*_)?statv?fs
237
+regular expression.
238
+.TP
239
+.BR \fIvalue\fR = %fstatfs
240
+Show fstatfs, fstatfs64, fstatvfs, osf_fstatfs, and osf_fstatfs64 system calls.
241
+The same effect can be achieved with
242
+.BR \fIvalue\fR = /fstatv?fs
243
+regular expression.
244
+.TP
245
+.BR \fIvalue\fR = %%statfs
246
+Show syscalls related to file system statistics (statfs-like, fstatfs-like,
247
+and ustat).  The same effect can be achieved with
248
+.BR \fIvalue\fR = /statv?fs|fsstat|ustat
249
+regular expression.
250
+
251
+.SH "EXIT STATUS"
252
+On success,
253
+.B asinfo
254
+returns 0. Otherwise, in case of wrong input or no matches found, 1.
255
+
256
+.SH "REPORTING BUGS"
257
+Problems with
258
+.B asinfo
259
+should be reported to the
260
+.B strace
261
+mailing list at <strace-devel@lists.sourceforge.net>.
262
+
263
+.SH "SEE ALSO"
264
+.BR strace (1)

+ 312
- 0
tools/asinfo/asinfo.c View File

@@ -0,0 +1,312 @@
1
+/*
2
+ * The asinfo main source. The asinfo tool is purposed to operate
3
+ * with system calls and provide information about it.
4
+ *
5
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
6
+ * Copyright (c) 2017-2018 The strace developers.
7
+ * All rights reserved.
8
+ *
9
+ * SPDX-License-Identifier: GPL-2.0-or-later
10
+ */
11
+
12
+#ifdef HAVE_CONFIG_H
13
+# include "config.h"
14
+#endif
15
+#include <errno.h>
16
+#include <ctype.h>
17
+#include <limits.h>
18
+#include <stdarg.h>
19
+#include <stdbool.h>
20
+#include <stdio.h>
21
+#include <stdlib.h>
22
+#include <string.h>
23
+
24
+#include "arch_interface.h"
25
+#include "dispatchers.h"
26
+#include "error_interface.h"
27
+#include "error_prints.h"
28
+#include "macros.h"
29
+#include "request_msgs.h"
30
+#include "syscall_interface.h"
31
+#include "xmalloc.h"
32
+
33
+#ifndef HAVE_PROGRAM_INVOCATION_NAME
34
+char *program_invocation_name;
35
+#endif
36
+
37
+static void
38
+usage(void)
39
+{
40
+	puts(
41
+		"usage: asinfo (--set-arch arch | --get-arch | --list-arch)\n"
42
+		"              [--set-abi abi | --list-abi] [--raw]\n"
43
+		"   or: asinfo [(--set-arch arch | --get-arch) [--set-abi abi | --list-abi]]\n"
44
+		"              ((--get-sname expr | --get-snum expr) [--nargs]) [--raw]\n"
45
+		"\n"
46
+		"Architecture:\n"
47
+		"  --set-arch arch  use architecture ARCH for further work\n"
48
+		"                   argument format: arch1,arch2,...\n"
49
+		"  --get-arch       use architecture returned by uname for further work\n"
50
+		"  --list-arch      print out all architectures supported by strace\n"
51
+		"                   (combined use list-arch and any ABI option is permitted)\n"
52
+		"\n"
53
+		"ABI:\n"
54
+		"  --set-abi abi    use application binary interface ABI for further work\n"
55
+		"                   ('all' can be used as ABI to use all compatible personalities\n"
56
+		"                   for corresponding architecture)\n"
57
+		"                   argument format: abi1,abi2,...\n"
58
+		"  --list-abi       use all ABIs for specified architecture\n"
59
+		"\n"
60
+		"System call:\n"
61
+		"  --get-sname expr print all system calls that satisfy a filtering expression:\n"
62
+		"                   [!]all or [!][?]val1[,[?]val2]...\n"
63
+		"                   with the following format:\n"
64
+		"                   | N | syscall name | snum1 | snum2 | ...\n"
65
+		"  --get-snum expr  print all system calls that satisfy a filtering expression:\n"
66
+		"                   [!]all or [!][?]val1[,[?]val2]...\n"
67
+		"                   with the following format:\n"
68
+		"                   | N | syscall number | sname1 | sname2 | ...\n"
69
+		"  --nargs          change output format as follows:\n"
70
+		"                   | N | syscall name or number | nargs1 | sname2 | ...\n"
71
+		"\n"
72
+		"Output formatting:\n"
73
+		"  --raw            reset alignment and remove titles, use ';' as a delimiter\n"
74
+		"\n"
75
+		"Miscellaneous:\n"
76
+		"  -h               print help message\n"
77
+		"  -v               print version");
78
+	exit(0);
79
+}
80
+
81
+static void
82
+print_version(void)
83
+{
84
+	printf("asinfo (%s package) -- version %s\n"
85
+	       "Copyright (c) 1991-%s The strace developers <%s>.\n"
86
+	       "This is free software; see the source for copying conditions.  There is NO\n"
87
+	       "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
88
+	       PACKAGE_NAME, PACKAGE_VERSION, COPYRIGHT_YEAR, PACKAGE_URL);
89
+	exit(0);
90
+}
91
+
92
+void
93
+die(void)
94
+{
95
+	exit(1);
96
+}
97
+
98
+static int
99
+is_more1bit(unsigned int num)
100
+{
101
+	return !(num & (num - 1));
102
+}
103
+
104
+static unsigned
105
+strpar2req(char *option)
106
+{
107
+	/* Convertion table to store string with options */
108
+	static const char *options[] = {
109
+		[SD_REQ_GET_SNAME_BIT]	= "--get-sname",
110
+		[SD_REQ_GET_SNUM_BIT]	= "--get-snum",
111
+		[SD_REQ_NARGS_BIT]	= "--nargs",
112
+		[AD_REQ_SET_ARCH_BIT]	= "--set-arch",
113
+		[AD_REQ_GET_ARCH_BIT]	= "--get-arch",
114
+		[AD_REQ_LIST_ARCH_BIT]	= "--list-arch",
115
+		[ABD_REQ_SET_ABI_BIT]	= "--set-abi",
116
+		[ABD_REQ_LIST_ABI_BIT]	= "--list-abi",
117
+		[SERV_REQ_RAW_BIT]	= "--raw",
118
+		[SERV_REQ_HELP_BIT]	= "-h",
119
+		[SERV_REQ_VERSION_BIT]	= "-v"
120
+	};
121
+	unsigned i;
122
+
123
+	for (i = 0; i < ARRAY_SIZE(options); i++) {
124
+		if (options[i] && strcmp(option, options[i]) == 0)
125
+			return i;
126
+	}
127
+	return SERV_REQ_ERROR_BIT;
128
+}
129
+
130
+static char **
131
+arg2list(char *argument)
132
+{
133
+	int i;
134
+	int len = strlen(argument);
135
+	int occur = 1;
136
+	char **arg_list;
137
+
138
+	for (i = 0; i < len; i++) {
139
+		if (argument[i] == ',') {
140
+			if (i == 0 || i == len - 1 || argument[i + 1] == ',')
141
+				return NULL;
142
+			occur++;
143
+		}
144
+	}
145
+	arg_list = xcalloc(sizeof(*arg_list), occur + 1);
146
+	for (i = 0; i < occur; i++) {
147
+		arg_list[i] = argument;
148
+		argument = strchr(argument, ',');
149
+		if (argument) {
150
+			*argument = '\0';
151
+			argument++;
152
+		}
153
+	}
154
+	return arg_list;
155
+}
156
+
157
+/* The purpose of this function is to convert input parameters to number with
158
+   set bits, where each bit means specific work mode. Moreover, it checks input
159
+   for correctness and outputs error messages in case of wrong input */
160
+static unsigned
161
+command_dispatcher(int argc, char *argv[], char **args[])
162
+{
163
+	int i;
164
+	unsigned final_req = 0;
165
+	unsigned temp_req = 0;
166
+	int mult_arch = 0;
167
+	int mult_abi = 0;
168
+	unsigned non_req_arg = AD_REQ_GET_ARCH	| AD_REQ_LIST_ARCH	|
169
+			       ABD_REQ_LIST_ABI	| SD_REQ_NARGS		|
170
+			       SERV_REQ_RAW;
171
+
172
+	if (!program_invocation_name || !*program_invocation_name) {
173
+		static char name[] = "asinfo";
174
+		program_invocation_name =
175
+			(argv[0] && *argv[0]) ? argv[0] : name;
176
+	}
177
+
178
+	/* Try to find help or version parameter first */
179
+	for (i = 1; i < argc; i++) {
180
+		if (strpar2req(argv[i]) == SERV_REQ_HELP_BIT)
181
+			usage();
182
+		if (strpar2req(argv[i]) == SERV_REQ_VERSION_BIT)
183
+			print_version();
184
+	}
185
+	/* For now, is is necessary to convert string parameter to number of
186
+	   request and make basic check */
187
+	for (i = 1; i < argc; i++) {
188
+		if ((temp_req = strpar2req(argv[i])) == SERV_REQ_ERROR_BIT)
189
+			error_msg_and_help("unrecognized option '%s'",
190
+					   argv[i]);
191
+		if (final_req & 1 << temp_req)
192
+			error_msg_and_help("parameter '%s' has been used "
193
+					   "more than once", argv[i]);
194
+		if (!((1 << temp_req) & non_req_arg) &&
195
+		     (i + 1 >= argc || strlen(argv[i + 1]) == 0 ||
196
+		      strpar2req(argv[i + 1]) != SERV_REQ_ERROR_BIT))
197
+			error_msg_and_help("parameter '%s' requires "
198
+					   "argument", argv[i]);
199
+		final_req |= 1 << temp_req;
200
+		if (!((1 << temp_req) & non_req_arg)) {
201
+			if ((1 << temp_req) & SD_REQ_MASK) {
202
+				args[temp_req] = &argv[i + 1];
203
+				i++;
204
+				continue;
205
+			}
206
+			if ((args[temp_req] = arg2list(argv[i + 1])) != NULL) {
207
+				i++;
208
+				continue;
209
+			}
210
+			error_msg_and_help("argument '%s' of '%s' parameter "
211
+					   "has a wrong format",
212
+					   argv[i + 1], argv[i]);
213
+		}
214
+	}
215
+	/* Count our multuarchness */
216
+	if (args[AD_REQ_SET_ARCH_BIT])
217
+		while (args[AD_REQ_SET_ARCH_BIT][mult_arch] != NULL)
218
+			mult_arch++;
219
+	if (args[ABD_REQ_SET_ABI_BIT])
220
+		while (args[ABD_REQ_SET_ABI_BIT][mult_abi] != NULL)
221
+			mult_abi++;
222
+	/* final_req should be logically checked */
223
+	/* More than one option from one request group couldn't be set */
224
+	if ((is_more1bit(final_req & SD_REQ_MASK & ~SD_REQ_NARGS) == 0) ||
225
+	    (is_more1bit(final_req & AD_REQ_MASK) == 0) ||
226
+	    (is_more1bit(final_req & ABD_REQ_MASK) == 0))
227
+		error_msg_and_help("exclusive parameters");
228
+	/* Check on mutually exclusive options chain */
229
+	/* If at least one syscall option has been typed, therefore
230
+	   arch_options couldn't be list-arch and
231
+	   abi_option couldn't be list-abi */
232
+	if ((final_req & SD_REQ_MASK) &&
233
+	    (((final_req & AD_REQ_MASK) && (final_req & AD_REQ_LIST_ARCH))))
234
+		error_msg_and_help("wrong parameters");
235
+	/* list-arch couldn't be used with any abi options */
236
+	if ((final_req & AD_REQ_LIST_ARCH) &&
237
+	    (final_req & ABD_REQ_MASK))
238
+		error_msg_and_help("'--list-arch' cannot be used with any "
239
+				   "ABI parameters");
240
+	/* ABI requests could be used just in a combination with arch
241
+	   requests */
242
+	if ((final_req & ABD_REQ_MASK) &&
243
+	    !(final_req & AD_REQ_MASK))
244
+		error_msg_and_help("ABI parameters could be used only with "
245
+				   "architecture parameter");
246
+	/* set-abi must be used in case of multiple arch */
247
+	if ((mult_arch > 1) && !(final_req & ABD_REQ_MASK))
248
+		error_msg_and_help("ABI modes cannot be automatically "
249
+				   "detected for multiple "
250
+				   "architectures");
251
+	/* set-abi and set-arch have to take the same number of args */
252
+	if ((final_req & AD_REQ_SET_ARCH) && (final_req & ABD_REQ_SET_ABI) &&
253
+	    (mult_arch != mult_abi))
254
+		error_msg_and_help("each architecture needs respective "
255
+				   "ABI mode, and vice versa");
256
+	/* --nargs cannot be used alone */
257
+	if ((final_req & SD_REQ_NARGS) &&
258
+	    !(final_req & SD_REQ_MASK & ~SD_REQ_NARGS))
259
+		error_msg_and_help("first set main output syscall "
260
+				   "characteristics");
261
+	/* raw should not be single */
262
+	if (final_req == SERV_REQ_RAW)
263
+		error_msg_and_help("raw data implies existing data");
264
+	return final_req;
265
+}
266
+
267
+static char *
268
+seek_sc_arg(char **input_args[])
269
+{
270
+	int i;
271
+
272
+	for (i = SD_REQ_GET_SNAME_BIT; i < SYSCALL_REQ_BIT_LAST; i++)
273
+		if (input_args[i] != NULL)
274
+			return input_args[i][0];
275
+	return NULL;
276
+}
277
+
278
+int
279
+main(int argc, char *argv[])
280
+{
281
+	ARCH_LIST_DEFINE(arch_list);
282
+	SYSCALL_LIST_DEFINE(sc_list);
283
+	/* This array is purposed to store arguments for options in the
284
+	   most convenient way */
285
+	char ***in_args = xcalloc(sizeof(*in_args), REQ_LAST_BIT);
286
+	unsigned reqs;
287
+
288
+	/* command_dispatcher turn */
289
+	reqs = command_dispatcher(argc, argv, in_args);
290
+	if (reqs == 0)
291
+		error_msg_and_help("must have OPTIONS");
292
+
293
+	/* arch_dispatcher turn */
294
+	arch_list = arch_dispatcher(reqs, in_args[AD_REQ_SET_ARCH_BIT]);
295
+	if (es_error(al_err(arch_list)))
296
+		perror_msg_and_die("%s", es_get_serror(al_err(arch_list)));
297
+	/* abi_dispatcher turn */
298
+	abi_dispatcher(arch_list, reqs, in_args[ABD_REQ_SET_ABI_BIT]);
299
+	if (es_error(al_err(arch_list)))
300
+		perror_msg_and_die("%s", es_get_serror(al_err(arch_list)));
301
+	/* syscall_dispatcher turn */
302
+	sc_list = syscall_dispatcher(arch_list, reqs, seek_sc_arg(in_args));
303
+	if (es_error(ss_err(sc_list)))
304
+		perror_msg_and_die("%s", es_get_serror(ss_err(sc_list)));
305
+	/* If we want to get info about only architectures thus we print out
306
+	   architectures, otherwise system calls */
307
+	if (!(reqs & SD_REQ_MASK))
308
+		al_dump(arch_list, reqs & SERV_REQ_RAW);
309
+	else
310
+		ss_dump(sc_list, reqs & SERV_REQ_RAW);
311
+	return 0;
312
+}

+ 225
- 0
tools/asinfo/dispatchers.c View File

@@ -0,0 +1,225 @@
1
+/*
2
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
3
+ * Copyright (c) 2017-2018 The strace developers.
4
+ * All rights reserved.
5
+ *
6
+ * SPDX-License-Identifier: GPL-2.0-or-later
7
+ */
8
+
9
+#ifdef HAVE_CONFIG_H
10
+# include "config.h"
11
+#endif
12
+#include <stdlib.h>
13
+#include <stdio.h>
14
+#include <string.h>
15
+#include <sys/utsname.h>
16
+
17
+#include "arch_interface.h"
18
+#include "dispatchers.h"
19
+#include "macros.h"
20
+#include "request_msgs.h"
21
+#include "syscall_interface.h"
22
+#include "sysent.h"
23
+#include "xmalloc.h"
24
+
25
+struct arch_service *
26
+arch_dispatcher(unsigned request_type, char *arch[])
27
+{
28
+	struct utsname info_uname;
29
+	int i;
30
+	ARCH_LIST_DEFINE(arch_list) = al_create_filled();
31
+	ARCH_LIST_DEFINE(arch_final) = NULL;
32
+
33
+	/* If user don't type any option in ARCH_REQ group, it means
34
+	   get current arch */
35
+	if ((request_type & AD_REQ_GET_ARCH) ||
36
+	    (!(request_type & AD_REQ_MASK))) {
37
+		uname(&info_uname);
38
+		if (al_mark_matches(arch_list, info_uname.machine) == -1) {
39
+			es_set_error(al_err(arch_list), AD_UNSUP_ARCH);
40
+			es_set_option(al_err(arch_list), info_uname.machine,
41
+				      NULL, NULL);
42
+			goto fail;
43
+		}
44
+		/* Cut off useless archs */
45
+		arch_final = al_join_print(arch_final, arch_list);
46
+		al_unmark_all(arch_final, AD_FLAG_PRINT);
47
+		free(arch_list);
48
+		goto done;
49
+	}
50
+
51
+	if (request_type & AD_REQ_SET_ARCH) {
52
+		for (i = 0; arch[i] != NULL; i++) {
53
+			if (al_mark_matches(arch_list, arch[i]) == -1) {
54
+				es_set_error(al_err(arch_list), AD_UNSUP_ARCH);
55
+				es_set_option(al_err(arch_list), arch[i],
56
+					      NULL, NULL);
57
+				goto fail;
58
+			}
59
+			arch_final = al_join_print(arch_final, arch_list);
60
+		}
61
+		al_unmark_all(arch_final, AD_FLAG_PRINT);
62
+		al_free(arch_list);
63
+		goto done;
64
+	}
65
+
66
+	if ((request_type & AD_REQ_LIST_ARCH)) {
67
+		int a_size = al_size(arch_list);
68
+		for (i = 0; i < a_size; i++) {
69
+			al_add_flag(arch_list, i, AD_FLAG_PRINT);
70
+		}
71
+		arch_final = arch_list;
72
+		goto done;
73
+	}
74
+fail:
75
+	return arch_list;
76
+done:
77
+	return arch_final;
78
+}
79
+
80
+int
81
+abi_dispatcher(struct arch_service *a_serv, unsigned request_type,
82
+	       char *abi[])
83
+{
84
+	int i = 0;
85
+	enum arch_pers pers;
86
+	int arch_size = 0;
87
+	int a_pos = 0;
88
+
89
+	arch_size = al_size(a_serv);
90
+	/* The strace package could be compiled as 32bit app on 64bit
91
+	   architecture, therefore asinfo has to detect it and print out
92
+	   corresponding personality. Frankly speaking, it is necessary to
93
+	   detect strace package personality when it is possible */
94
+	if (!(request_type & ABD_REQ_MASK) &&
95
+	    !(request_type & AD_REQ_LIST_ARCH)) {
96
+		pers = al_pers(a_serv, a_pos);
97
+		switch (pers) {
98
+#if defined(MIPS)
99
+		case ARCH_mips_o32:
100
+		case ARCH_mips64_n64:
101
+			al_mark_pers4arch(a_serv, a_pos,
102
+#if defined(LINUX_MIPSO32)
103
+					  "o32"
104
+#elif defined(LINUX_MIPSN32)
105
+					  "n32"
106
+#elif defined(LINUX_MIPSN64)
107
+					  "n64"
108
+#endif
109
+					 );
110
+			break;
111
+#endif
112
+#if defined(ARM)
113
+		case ARCH_arm_oabi:
114
+			al_mark_pers4arch(a_serv, a_pos,
115
+#if defined(__ARM_EABI__) || !defined(ENABLE_ARM_OABI)
116
+					  "eabi"
117
+#else
118
+					  "oabi"
119
+#endif
120
+					 );
121
+			break;
122
+#endif
123
+#if defined(AARCH64)
124
+		case ARCH_aarch64_64bit:
125
+			al_mark_pers4arch(a_serv, a_pos,
126
+#if defined(__ARM_EABI__)
127
+					  "eabi"
128
+#else
129
+					  "64bit"
130
+#endif
131
+					 );
132
+			break;
133
+#endif
134
+#if defined(X86_64) || defined(X32)
135
+		case ARCH_x86_64_64bit:
136
+			al_mark_pers4arch(a_serv, a_pos,
137
+#if defined(X86_64)
138
+					  "64bit"
139
+#elif defined(X32)
140
+					  "x32"
141
+#endif
142
+				    );
143
+			break;
144
+#endif
145
+/* Especially for x86_64 32bit ABI, because configure.ac defines it
146
+   as I386 arch */
147
+#if defined(I386)
148
+		case ARCH_x86_64_64bit:
149
+			al_mark_pers4arch(a_serv, a_pos, "32bit");
150
+			break;
151
+#endif
152
+#if defined(TILE)
153
+		case ARCH_tile_64bit:
154
+			al_mark_pers4arch(a_serv, a_pos,
155
+#if defined(__tilepro__)
156
+					  "32bit"
157
+#else
158
+					  "64bit"
159
+#endif
160
+				    );
161
+			break;
162
+#endif
163
+		default:
164
+			if (arch_size == 1) {
165
+				al_add_flag(a_serv, a_pos, AD_FLAG_PRINT);
166
+				goto done;
167
+			}
168
+			es_set_error(al_err(a_serv), ABI_CANNOT_DETECT);
169
+			es_set_option(al_err(a_serv),
170
+				      al_in_aname(a_serv, a_pos), NULL, NULL);
171
+		}
172
+		goto done;
173
+	}
174
+
175
+	if (request_type & ABD_REQ_LIST_ABI) {
176
+		while (a_pos != arch_size) {
177
+			if (!al_mark_pers4arch(a_serv, a_pos, "all")) {
178
+				a_pos += al_get_abi_modes(a_serv, a_pos);
179
+				continue;
180
+			}
181
+			break;
182
+		}
183
+		goto done;
184
+	}
185
+
186
+	if (request_type & ABD_REQ_SET_ABI) {
187
+		for (i = 0; abi[i] != NULL; i++) {
188
+			if (!al_mark_pers4arch(a_serv, a_pos, abi[i])) {
189
+				a_pos += al_get_abi_modes(a_serv, a_pos);
190
+				continue;
191
+			}
192
+			es_set_error(al_err(a_serv), ABI_WRONG4ARCH);
193
+			es_set_option(al_err(a_serv),
194
+				      al_in_aname(a_serv, a_pos),
195
+				      abi[i], NULL);
196
+			break;
197
+		}
198
+	}
199
+done:
200
+	return 0;
201
+}
202
+
203
+struct syscall_service *
204
+syscall_dispatcher(struct arch_service *arch, int request_type, char *sysc)
205
+{
206
+	SYSCALL_LIST_DEFINE(sysc_serv) = ss_create(arch, request_type);
207
+	int narch = ss_size(sysc_serv);
208
+	int i = 0;
209
+	int ret = 0;
210
+	int count = 0;
211
+
212
+	if (request_type & SD_REQ_MASK) {
213
+		for (i = 0; i < narch; i++) {
214
+			ss_update_sc_num(sysc_serv, i);
215
+			ret = ss_mark_matches(sysc_serv, i, sysc);
216
+			if (ret == SD_NO_MATCHES_FND)
217
+				count++;
218
+		}
219
+	}
220
+	/* Clear error if we are in multiarch mode */
221
+	if (count != narch && narch != 1)
222
+		es_set_error(ss_err(sysc_serv), NO_ERROR);
223
+
224
+	return sysc_serv;
225
+}

+ 29
- 0
tools/asinfo/dispatchers.h View File

@@ -0,0 +1,29 @@
1
+/*
2
+ * The dispatchers.h contains all necessary functions to perform main
3
+ * work in the asinfo tool.
4
+ *
5
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
6
+ * Copyright (c) 2017-2018 The strace developers.
7
+ * All rights reserved.
8
+ *
9
+ * SPDX-License-Identifier: GPL-2.0-or-later
10
+ */
11
+
12
+#ifndef ASINFO_DISPATCHERS_H
13
+#define ASINFO_DISPATCHERS_H
14
+
15
+#include "arch_interface.h"
16
+#include "syscall_interface.h"
17
+
18
+/* The function is purposed to provide correct list of architectures */
19
+struct arch_service *arch_dispatcher(unsigned request_type, char *arch[]);
20
+
21
+/* Final arch filtering based on personality */
22
+int abi_dispatcher(struct arch_service *a_serv, unsigned request_type,
23
+		   char *abi[]);
24
+
25
+/* The last stage of main filtering */
26
+struct syscall_service *syscall_dispatcher(struct arch_service *arch,
27
+					   int request_type, char *sysc);
28
+
29
+#endif /* !ASINFO_DISPATCHERS_H */

+ 91
- 0
tools/asinfo/error_interface.c View File

@@ -0,0 +1,91 @@
1
+/*
2
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
3
+ * Copyright (c) 2017-2018 The strace developers.
4
+ * All rights reserved.
5
+ *
6
+ * SPDX-License-Identifier: GPL-2.0-or-later
7
+ */
8
+
9
+#ifdef HAVE_CONFIG_H
10
+# include "config.h"
11
+#endif
12
+
13
+#include <stdlib.h>
14
+#include <string.h>
15
+#include <stdio.h>
16
+
17
+#include "error_interface.h"
18
+#include "xmalloc.h"
19
+
20
+static const char *errors[] = {
21
+	[AD_UNSUP_ARCH_BIT]	= "architecture '%s' is unsupported",
22
+	[ABI_CANNOT_DETECT_BIT]	= "ABI mode cannot be automatically "
23
+				  "detected for non-target architecture '%s'",
24
+	[ABI_WRONG4ARCH_BIT]	= "architecture '%s' does not have ABI mode "
25
+				  "'%s'",
26
+	[SD_NO_MATCHES_FND_BIT]	= "no matches found",
27
+};
28
+
29
+struct error_service *
30
+es_create(void)
31
+{
32
+	struct error_service *err = xcalloc(sizeof(*err), 1);
33
+
34
+	return err;
35
+}
36
+
37
+enum common_error
38
+es_error(struct error_service *e)
39
+{
40
+	return e->last_error;
41
+}
42
+
43
+void
44
+es_set_error(struct error_service *e, enum common_error error)
45
+{
46
+	e->last_error = error;
47
+}
48
+
49
+void
50
+es_set_option(struct error_service *e, char *arch, char *abi, char *sc)
51
+{
52
+	if (arch) {
53
+		if (e->last_arch)
54
+			free(e->last_arch);
55
+		e->last_arch = xcalloc(sizeof(*(e->last_arch)),
56
+				       strlen(arch) + 1);
57
+		strcpy(e->last_arch, arch);
58
+	}
59
+	if (abi) {
60
+		if (e->last_abi)
61
+			free(e->last_abi);
62
+		e->last_abi = xcalloc(sizeof(*(e->last_abi)), strlen(abi) + 1);
63
+		strcpy(e->last_abi, abi);
64
+	}
65
+	if (sc) {
66
+		if (e->last_sc)
67
+			free(e->last_sc);
68
+		e->last_sc = xcalloc(sizeof(*(e->last_sc)), strlen(sc) + 1);
69
+		strcpy(e->last_sc, sc);
70
+	}
71
+}
72
+
73
+const char *
74
+es_get_serror(struct error_service *e)
75
+{
76
+	int err = 1 << e->last_error;
77
+	if (err & ERROR_ARCH_MASK)
78
+		sprintf(e->string, errors[e->last_error], e->last_arch);
79
+	else if (err & ERROR_NO_ARG_MASK)
80
+		sprintf(e->string, "%s", errors[e->last_error]);
81
+	else if (err & ERROR_ARCH_ABI_MASK)
82
+		sprintf(e->string, errors[e->last_error], e->last_arch,
83
+			e->last_abi);
84
+	return (const char *)(e->string);
85
+}
86
+
87
+void
88
+es_free(struct error_service *e)
89
+{
90
+	free(e);
91
+}

+ 76
- 0
tools/asinfo/error_interface.h View File

@@ -0,0 +1,76 @@
1
+/*
2
+ * As each dispatcher has a wide range of possible errors, there is need
3
+ * use separate and basic error interface.
4
+ *
5
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
6
+ * Copyright (c) 2017-2018 The strace developers.
7
+ * All rights reserved.
8
+ *
9
+ * SPDX-License-Identifier: GPL-2.0-or-later
10
+ */
11
+
12
+#ifndef ASINFO_ERROR_INTERFACE_H
13
+#define ASINFO_ERROR_INTERFACE_H
14
+
15
+/* errors which using last_arch */
16
+enum error_arch {
17
+	NO_ERROR_BIT,
18
+	AD_UNSUP_ARCH_BIT = 1,
19
+	ABI_CANNOT_DETECT_BIT,
20
+
21
+	ERROR_ARCH_LAST
22
+};
23
+
24
+enum error_no_arg {
25
+	SD_NO_MATCHES_FND_BIT = ERROR_ARCH_LAST,
26
+
27
+	ERROR_NO_ARG_LAST
28
+};
29
+
30
+enum error_arch_abi {
31
+	ABI_WRONG4ARCH_BIT = ERROR_NO_ARG_LAST,
32
+
33
+	ERROR_ARCH_ABI_LAST
34
+};
35
+
36
+#define ENUM_FLAG(name) name = name##_BIT
37
+enum common_error {
38
+	ENUM_FLAG(NO_ERROR),
39
+	/* arch dispatcher range */
40
+	ENUM_FLAG(AD_UNSUP_ARCH),
41
+	/* abi dipatcher range */
42
+	ENUM_FLAG(ABI_CANNOT_DETECT),
43
+	ENUM_FLAG(ABI_WRONG4ARCH),
44
+	/* syscall dispatcher range */
45
+	ENUM_FLAG(SD_NO_MATCHES_FND)
46
+};
47
+#undef ENUM_FLAG
48
+
49
+#define BITMASK(hi, lo) ((1 << (hi)) - (1 << (lo)))
50
+#define ERROR_ARCH_MASK  BITMASK(ERROR_ARCH_LAST, 0)
51
+#define ERROR_NO_ARG_MASK BITMASK(ERROR_NO_ARG_LAST, ERROR_ARCH_LAST)
52
+#define ERROR_ARCH_ABI_MASK BITMASK(ERROR_ARCH_ABI_LAST, ERROR_NO_ARG_LAST)
53
+
54
+#define ERROR_MSG_MAX_LEN 255
55
+
56
+struct error_service {
57
+	char string[ERROR_MSG_MAX_LEN];
58
+	enum common_error last_error;
59
+	char *last_arch;
60
+	char *last_abi;
61
+	char *last_sc;
62
+};
63
+
64
+struct error_service *es_create(void);
65
+
66
+enum common_error es_error(struct error_service *s);
67
+
68
+void es_set_error(struct error_service *s, enum common_error se);
69
+
70
+void es_set_option(struct error_service *e, char *arch, char *abi, char *sc);
71
+
72
+const char *es_get_serror(struct error_service *e);
73
+
74
+void es_free(struct error_service *e);
75
+
76
+#endif /* !ASINFO_ERROR_INTERFACE_H */

+ 153
- 0
tools/asinfo/gen_asinfo_files.sh View File

@@ -0,0 +1,153 @@
1
+#!/bin/sh
2
+#
3
+# Code generator simplifies addition of new architecture to asinfo tool
4
+#
5
+# Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
6
+# Copyright (c) 2017-2018 The strace developers.
7
+# All rights reserved.
8
+#
9
+# SPDX-License-Identifier: GPL-2.0-or-later
10
+
11
+cur_pers=""
12
+
13
+gen_pers_line()
14
+{
15
+	local out_file="$1"
16
+	local line="$2"
17
+	local arch_abi=""
18
+
19
+	LC_COLLATE=C
20
+	arch_abi="$(printf %s "${line}" |
21
+		    sed 's/ARCH_DESC_DEFINE(//' | cut -d, -f 1,2 |
22
+		    sed 's/,/_/g')"
23
+	cur_pers="${arch_abi}"
24
+	echo "ARCH_${arch_abi}," >> "${out_file}"
25
+}
26
+
27
+gen_includes_block()
28
+{
29
+	local out_file="$1"
30
+	local line="$2"
31
+	local def is_def includes include nums num count
32
+
33
+	(
34
+	LC_COLLATE=C
35
+	echo "/* ${cur_pers} */"
36
+	def="$(printf %s "${line#*\*}" | cut -d] -f 1 | sed 's/.*[][]//g')"
37
+	#Generate define construction
38
+	if [ "${def#!}" != "" ] && [ $(printf %.1s "${def}") = "!" ]; then
39
+		cat <<-EOF
40
+		#ifdef ${def#!}
41
+		# undef ${def#!}
42
+		# define ${def#!}_DUMMY_UNDEFINE
43
+		#endif
44
+		EOF
45
+		is_def="def"
46
+	else if [ "${def#!}" != "" ]; then
47
+		cat <<-EOF
48
+		#ifndef ${def}
49
+		# define ${def}
50
+		# define ${def}_DUMMY_DEFINE
51
+		#endif
52
+		EOF
53
+		is_def="undef"
54
+	fi
55
+	fi
56
+	#Generate includes
57
+	includes="$(printf %s "${line#*\*}" | cut -d] -f 2 | sed 's/.*[][]//g')"
58
+	echo "static const struct_sysent ${cur_pers}_sysent[] = {"
59
+	for include in $(echo "${includes}" | sed "s/,/ /g")
60
+	do
61
+		echo "	#include \"${include}\""
62
+	done
63
+	echo "};"
64
+	#Undefine definitions, if it is required
65
+	if [ "${is_def}" = "def" ]; then
66
+		cat <<-EOF
67
+		#ifdef ${def#!}_DUMMY_UNDEFINE
68
+		# define ${def#!} 1
69
+		# undef ${def#!}_DUMMY_UNDEFINE
70
+		#endif
71
+		EOF
72
+	else if [ "${is_def}" = "undef" ]; then
73
+		cat <<-EOF
74
+		#ifdef ${def#!}_DUMMY_DEFINE
75
+		# undef ${def#!}
76
+		# undef ${def#!}_DUMMY_DEFINE
77
+		#endif
78
+		EOF
79
+	fi
80
+	fi
81
+	#Generate arch specific numbers
82
+	nums="$(printf %s "${line#*\*}" | cut -d] -f 3 | sed 's/.*[][]//g')"
83
+	count=1
84
+	for num in $(echo "${nums}" | sed "s/,/ /g")
85
+	do
86
+		echo "static const int ${cur_pers}_usr${count} = ${num};"
87
+		count=$((count+1))
88
+		case "${num}" in
89
+		*[A-Za-z_]*) echo "#undef ${num}" ;;
90
+		*) ;;
91
+		esac
92
+	done
93
+	if [ $count -eq 1 ]; then
94
+		echo "static const int ${cur_pers}_usr${count} = 0;"
95
+	fi
96
+	echo "#undef SYS_socket_subcall"
97
+	echo "#undef BASE_NR"
98
+	) >> "${out_file}"
99
+	echo "${def}" >> "${out_file}"
100
+}
101
+
102
+main()
103
+{
104
+	set -- "${0%/*}" "${0%/*}"
105
+
106
+	local input="$1"
107
+	local output="$2"
108
+	local defs_file="arch_definitions.h"
109
+	local pers_file="arch_personalities.h"
110
+	local includes_file="arch_includes.h"
111
+	local pline=""
112
+
113
+	echo "ARCH_no_pers," > "${output}/${pers_file}"
114
+	echo -n > "${output}/${includes_file}"
115
+
116
+	#Main work
117
+	while read line; do
118
+		line="$(printf %s "${line}" | sed 's/[[:space:]]//g')"
119
+		if $(printf %s "${line}" |
120
+		     grep -F "ARCH_DESC_DEFINE" > /dev/null); then
121
+			gen_pers_line "${output}/${pers_file}" "${line}"
122
+		fi
123
+		if $(printf %s "${pline}" | grep -F "/*" > /dev/null); then
124
+			gen_includes_block "${output}/${includes_file}"\
125
+					   "${pline}"
126
+		fi
127
+		pline="${line}"
128
+	done < "${input}/${defs_file}"
129
+	#Makemodule.am
130
+	(
131
+	printf \
132
+"ARCH_AUX_FILES = ${includes_file} ${pers_file}\n\
133
+\$(top_srcdir)/tools/asinfo/${includes_file}: \
134
+\$(top_srcdir)/tools/asinfo/${defs_file} \
135
+\$(top_srcdir)/tools/asinfo/gen_asinfo_files.sh\n\
136
+	\$(AM_V_GEN)\$(top_srcdir)/tools/asinfo/gen_asinfo_files.sh\n\
137
+\$(top_srcdir)/tools/asinfo/${pers_file}: \
138
+\$(top_srcdir)/tools/asinfo/${defs_file} \
139
+\$(top_srcdir)/tools/asinfo/gen_asinfo_files.sh\n\
140
+	\$(AM_V_GEN)\$(top_srcdir)/tools/asinfo/gen_asinfo_files.sh"
141
+	) > "${output}/Makemodule.am"
142
+	#.gitignore
143
+	(
144
+	printf \
145
+"/${includes_file}\n\
146
+/${pers_file}\n\
147
+/Makemodule.am\n\
148
+/.gitignore\n\
149
+/asinfo.1"
150
+	) > "${output}/.gitignore"
151
+}
152
+
153
+main "$@"

+ 74
- 0
tools/asinfo/request_msgs.h View File

@@ -0,0 +1,74 @@
1
+/*
2
+ * The request_msgs are purposed to set the general mode of work, in
3
+ * particular, the work of main dispatchers.
4
+ *
5
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
6
+ * Copyright (c) 2017-2018 The strace developers.
7
+ * All rights reserved.
8
+ *
9
+ * SPDX-License-Identifier: GPL-2.0-or-later
10
+ */
11
+
12
+#ifndef ASINFO_REQUEST_MSGS_H
13
+#define ASINFO_REQUEST_MSGS_H
14
+
15
+/* Request types for syscall_dispatcher,
16
+ * arch_dispatcher, which, in turn, could be combined
17
+ */
18
+enum syscall_req_bit {
19
+	SD_REQ_GET_SNAME_BIT,
20
+	SD_REQ_GET_SNUM_BIT,
21
+	SD_REQ_NARGS_BIT,
22
+
23
+	SYSCALL_REQ_BIT_LAST
24
+};
25
+
26
+enum arch_req_bit {
27
+	AD_REQ_SET_ARCH_BIT = SYSCALL_REQ_BIT_LAST,
28
+	AD_REQ_GET_ARCH_BIT,
29
+	AD_REQ_LIST_ARCH_BIT,
30
+
31
+	ARCH_REQ_BIT_LAST
32
+};
33
+
34
+enum abi_req_bit {
35
+	ABD_REQ_SET_ABI_BIT = ARCH_REQ_BIT_LAST,
36
+	ABD_REQ_LIST_ABI_BIT,
37
+
38
+	ABD_REQ_BIT_LAST
39
+};
40
+
41
+enum serv_req_bit {
42
+	SERV_REQ_HELP_BIT = ABD_REQ_BIT_LAST,
43
+	SERV_REQ_VERSION_BIT,
44
+	SERV_REQ_ERROR_BIT,
45
+	SERV_REQ_RAW_BIT,
46
+
47
+	SERV_REQ_BIT_LAST
48
+};
49
+
50
+#define ENUM_FLAG(name) name = 1 << name##_BIT
51
+enum req_type {
52
+	ENUM_FLAG(SD_REQ_GET_SNAME),
53
+	ENUM_FLAG(SD_REQ_GET_SNUM),
54
+	ENUM_FLAG(SD_REQ_NARGS),
55
+	ENUM_FLAG(AD_REQ_SET_ARCH),
56
+	ENUM_FLAG(AD_REQ_GET_ARCH),
57
+	ENUM_FLAG(AD_REQ_LIST_ARCH),
58
+	ENUM_FLAG(ABD_REQ_SET_ABI),
59
+	ENUM_FLAG(ABD_REQ_LIST_ABI),
60
+	ENUM_FLAG(SERV_REQ_HELP),
61
+	ENUM_FLAG(SERV_REQ_VERSION),
62
+	ENUM_FLAG(SERV_REQ_ERROR),
63
+	ENUM_FLAG(SERV_REQ_RAW)
64
+};
65
+#undef ENUM_FLAG
66
+
67
+#define BITMASK(hi, lo) ((1 << (hi)) - (1 << (lo)))
68
+#define REQ_LAST_BIT SERV_REQ_BIT_LAST
69
+#define SD_REQ_MASK BITMASK(SYSCALL_REQ_BIT_LAST, 0)
70
+#define AD_REQ_MASK BITMASK(ARCH_REQ_BIT_LAST, SYSCALL_REQ_BIT_LAST)
71
+#define ABD_REQ_MASK BITMASK(ABD_REQ_BIT_LAST, ARCH_REQ_BIT_LAST)
72
+#define SERV_REQ_MASK BITMASK(SERV_REQ_BIT_LAST, ABD_REQ_BIT_LAST)
73
+
74
+#endif /* !ASINFO_REQUEST_MSGS_H */

+ 672
- 0
tools/asinfo/syscall_interface.c View File

@@ -0,0 +1,672 @@
1
+/*
2
+ * Copyright (c) 2017 Edgar A. Kaziakhmedov <edgar.kaziakhmedv@virtuozzo.com>
3
+ * Copyright (c) 2017-2018 The strace developers.
4
+ * All rights reserved.
5
+ *
6
+ * SPDX-License-Identifier: GPL-2.0-or-later
7
+ */
8
+
9
+#ifdef HAVE_CONFIG_H
10
+# include "config.h"
11
+#endif
12
+#include <stdbool.h>
13
+#include <stdio.h>
14
+#include <stdlib.h>
15
+#include <string.h>
16
+
17
+#include "macros.h"
18
+#include "arch_interface.h"
19
+#include "error_interface.h"
20
+#include "filter.h"
21
+#include "number_set.h"
22
+#include "arch_defs.h"
23
+#include "syscall_interface.h"
24
+#include "sysent.h"
25
+#include "request_msgs.h"
26
+#include "xmalloc.h"
27
+
28
+/* We shouldn't include defs.h here, because the following definitions
29
+   cannot be with const qualifier */
30
+const struct_sysent *sysent_vec[SUPPORTED_PERSONALITIES] = {NULL};
31
+unsigned int nsyscall_vec[SUPPORTED_PERSONALITIES] = {0};
32
+
33
+const char *const personality_designators[] =
34
+# if defined X86_64
35
+	{ "64", "32", "x32" }
36
+# elif defined X32
37
+	{ "x32", "32" }
38
+# elif SUPPORTED_PERSONALITIES == 2
39
+	{ "64", "32" }
40
+# else
41
+	{ STRINGIFY_VAL(__WORDSIZE) }
42
+# endif
43
+	;
44
+
45
+struct syscall_service *
46
+ss_create(struct arch_service *m, int request_type)
47
+{
48
+	int i;
49
+	int ss_count = 0;
50
+	int ssize = al_psize(m);
51
+	int asize = al_size(m);
52
+	struct syscall_service *ss = NULL;
53
+	int scn = 0;
54
+
55
+	ss = xcalloc(sizeof(*ss), 1);
56
+	ss->err = al_err(m);
57
+	/* If we are in arch/abi mode, but we need syscall_service to pass
58
+	   check for errors */
59
+	if (!(request_type & SD_REQ_MASK) || ssize == 0)
60
+		return ss;
61
+	ss->aws = xcalloc(sizeof(*(ss->aws)), ssize);
62
+	ss->narch = ssize;
63
+	for (i = 0; i < asize; i++)
64
+		if (al_flag(m, i) & AD_FLAG_PRINT) {
65
+			ss->aws[ss_count].arch = al_get(m, i);
66
+			scn = ss->aws[ss_count].arch->max_scn;
67
+			ss->aws[ss_count].flag = xcalloc(sizeof(int), scn);
68
+			ss->aws[ss_count].real_snum = xcalloc(sizeof(int), scn);
69
+			ss->aws[ss_count].a_name = al_in_aname(m, i);
70
+			al_set_in_aname(m, i, NULL);
71
+			ss_count++;
72
+		}
73
+	ss->request_type = request_type;
74
+	return ss;
75
+}
76
+
77
+int
78
+ssa_is_ok(struct syscall_service *s, int arch, int num)
79
+{
80
+	if (s == NULL || arch > s->narch || arch < 0 || num < 0 ||
81
+	    (unsigned int) num >= s->aws[arch].arch->max_scn)
82
+		return 0;
83
+	return 1;
84
+}
85
+
86
+struct error_service *
87
+ss_err(struct syscall_service *s)
88
+{
89
+	return s->err;
90
+}
91
+
92
+int
93
+ss_size(struct syscall_service *s)
94
+{
95
+	return s->narch;
96
+}
97
+
98
+int
99
+ssa_max_scn(struct syscall_service *s, int arch)
100
+{
101
+	if (!ssa_is_ok(s, arch, 0))
102
+		return -1;
103
+	return s->aws[arch].arch->max_scn;
104
+}
105
+
106
+const struct_sysent *
107
+ssa_sysc_list(struct syscall_service *s, int arch)
108
+{
109
+	if (!ssa_is_ok(s, arch, 0))
110
+		return NULL;
111
+	return s->aws[arch].arch->syscall_list;
112
+}
113
+
114
+int
115
+ssa_flag(struct syscall_service *s, int arch, int num)
116
+{
117
+	if (!ssa_is_ok(s, arch, num))
118
+		return -1;
119
+	return s->aws[arch].flag[num];
120
+}
121
+
122
+int
123
+ssa_set_flag(struct syscall_service *s, int arch, int num, int flag)
124
+{
125
+	if (!ssa_is_ok(s, arch, num))
126
+		return -1;
127
+	s->aws[arch].flag[num] = flag;
128
+	return 0;
129
+}
130
+
131
+int
132
+ssa_real_num(struct syscall_service *s, int arch, int num)
133
+{
134
+	if (!ssa_is_ok(s, arch, num))
135
+		return -1;
136
+	return s->aws[arch].real_snum[num];
137
+}
138
+
139
+int
140
+ssa_set_real_num(struct syscall_service *s, int arch, int num, int real_num)
141
+{
142
+	if (!ssa_is_ok(s, arch, num))
143
+		return -1;
144
+	s->aws[arch].real_snum[num] = real_num;
145
+	return 0;
146
+}
147
+
148
+const char *
149
+ssa_syscall_name(struct syscall_service *s, int arch, int num)
150
+{
151
+	if (!ssa_is_ok(s, arch, num))
152
+		return NULL;
153
+	return s->aws[arch].arch->syscall_list[num].sys_name;
154
+}
155
+
156
+int
157
+ssa_syscall_flag(struct syscall_service *s, int arch, int num)
158
+{
159
+	if (!ssa_is_ok(s, arch, num))
160
+		return -1;
161
+	return s->aws[arch].arch->syscall_list[num].sys_flags;
162
+}
163
+
164
+int
165
+ssa_syscall_nargs(struct syscall_service *s, int arch, int num)
166
+{
167
+	if (!ssa_is_ok(s, arch, num))
168
+		return -1;
169
+	return (int)s->aws[arch].arch->syscall_list[num].nargs;
170
+}
171
+
172
+int
173
+ssa_user_num1(struct syscall_service *s, int arch)
174
+{
175
+	if (!ssa_is_ok(s, arch, 0))
176
+		return -1;
177
+	return *(s->aws[arch].arch->user_num1);
178
+}
179
+
180
+int
181
+ssa_user_num2(struct syscall_service *s, int arch)
182
+{
183
+	if (!ssa_is_ok(s, arch, 0))
184
+		return -1;
185
+	return *(s->aws[arch].arch->user_num2);
186
+}
187
+
188
+void
189
+ss_free(struct syscall_service *s)
190
+{
191
+	int i;
192
+
193
+	es_free(ss_err(s));
194
+	for (i = 0; i < s->narch; i++ ) {
195
+		free(s->aws[i].flag);
196
+		free(s->aws[i].real_snum);
197
+		if (s->aws[i].a_name)
198
+			free(s->aws[i].a_name);
199
+	}
200
+	free(s);
201
+}
202
+
203
+int
204
+ssa_print_size(struct syscall_service *s, int arch)
205
+{
206
+	int i;
207
+	int max_scn = ssa_max_scn(s, arch);
208
+	int psize = 0;
209
+
210
+	for (i = 0; i < max_scn; i++)
211
+		if (ssa_flag(s, arch, i) & SS_FLAG_PRINT)
212
+			psize++;
213
+	return psize;
214
+}
215
+
216
+int
217
+ssa_is_syscall_valid(struct syscall_service *s, int arch, int num)
218
+{
219
+	if (!ssa_is_ok(s, arch, num))
220
+		return 0;
221
+	return ssa_syscall_name(s, arch, num) &&
222
+	       !(ssa_syscall_flag(s, arch, num) & TRACE_INDIRECT_SUBCALL);
223
+}
224
+
225
+int
226
+ss_mark_matches(struct syscall_service *s, int arch, char *arg)
227
+{
228
+	int i = 0;
229
+	int scount = 0;
230
+	int max_scn = ssa_max_scn(s, arch);
231
+	struct number_set *trace_set;
232
+
233
+	/* Init global variables */
234
+	nsyscall_vec[0] = ssa_max_scn(s, arch);
235
+	sysent_vec[0] =  ssa_sysc_list(s, arch);
236
+
237
+	trace_set = alloc_number_set_array(SUPPORTED_PERSONALITIES);
238
+	qualify_syscall_tokens(arg, trace_set);
239
+	for (i = 0; i < max_scn; i++)
240
+		if (ssa_is_syscall_valid(s, arch, i) &&
241
+		    ssa_real_num(s, arch, i) != HIDDEN_SYSC &&
242
+		    is_number_in_set_array(i, trace_set, 0)) {
243
+			ssa_set_flag(s, arch, i, SS_FLAG_PRINT);
244
+			scount++;
245
+		}
246
+	if (scount == 0) {
247
+		es_set_error(ss_err(s), SD_NO_MATCHES_FND);
248
+		return SD_NO_MATCHES_FND;
249
+	}
250
+	return 0;
251
+}
252
+
253
+int
254
+ss_update_sc_num(struct syscall_service *s, int arch)
255
+{
256
+	int i = 0;
257
+	int max_scn = ssa_max_scn(s, arch);
258
+	int usr1n = ssa_user_num1(s, arch);
259
+	int usr2n = ssa_user_num2(s, arch);
260
+
261
+	for (i = 0; i < max_scn; i++) {
262
+		if (!ssa_is_syscall_valid(s, arch, i)) {
263
+			ssa_set_real_num(s, arch, i, HIDDEN_SYSC);
264
+			continue;
265
+		}
266
+		switch (s->aws[arch].arch->pers) {
267
+		case ARCH_x86_64_x32:
268
+			/* Pure x32 specific syscalls without X32_SYSCALL_BIT */
269
+			if (strstr(ssa_syscall_name(s, arch, i), "64:"))
270
+				ssa_set_real_num(s, arch, i, HIDDEN_SYSC);
271
+			else
272
+				ssa_set_real_num(s, arch, i, i);
273
+			break;
274
+		case ARCH_arm_oabi:
275
+		case ARCH_arm_eabi:
276
+			/* Do not deal with private ARM syscalls */
277
+			if (i == usr1n)
278
+				ssa_set_real_num(s, arch, i, HIDDEN_SYSC);
279
+			if ((i >= usr1n + 1) && (i <= usr1n + usr2n + 1))
280
+				ssa_set_real_num(s, arch, i, HIDDEN_SYSC);
281
+			if (i < usr1n)
282
+				ssa_set_real_num(s, arch, i, i);
283
+			break;
284
+		case ARCH_sh64_64bit:
285
+			ssa_set_real_num(s, arch, i, i & 0xffff);
286
+			break;
287
+		default:
288
+			ssa_set_real_num(s, arch, i, i);
289
+		}
290
+	}
291
+	return 0;
292
+}
293
+
294
+static int
295
+sysccmp(const void *arg1, const void *arg2)
296
+{
297
+	const char *str1 = ((struct in_sysc *)arg1)->sys_name;
298
+	const char *str2 = ((struct in_sysc *)arg2)->sys_name;
299
+
300
+	return strcmp(str1, str2);
301
+}
302
+
303
+static struct sysc_meta *
304
+ss_make_union(struct syscall_service *s,
305
+	      void* (save)(struct syscall_service *, int, int))
306
+{
307
+	struct in_sysc **sysc;
308
+	struct out_sysc *sysc_l, *sysc_r, *sysc_to, *sysc_fr;
309
+	struct sysc_meta *sm = xcalloc(sizeof(*sm), 1);
310
+	int size = ss_size(s);
311
+	int max_scn;
312
+	int psize;
313
+	int out_size = 0;
314
+	int i, j, k, l;
315
+	int c = 0;
316
+	int res = 0;
317
+	int eff_size = 1;
318
+	/* Preparation */
319
+	sysc = xcalloc(sizeof(*sysc), size);
320
+	for (i = 0; i < size; i++) {
321
+		max_scn = ssa_max_scn(s, i);
322
+		psize = ssa_print_size(s, i);
323
+		sysc[i] = xcalloc(sizeof(**sysc), psize + 1);
324
+		c = 0;
325
+		for (j = 0; j < max_scn; j++) {
326
+			if (!(ssa_flag(s, i, j) & SS_FLAG_PRINT))
327
+				continue;
328
+			sysc[i][c].sys_name = ssa_syscall_name(s, i, j);
329
+			sysc[i][c].data = save(s, i, j);
330
+			c++;
331
+		}
332
+		qsort(sysc[i], psize, sizeof(struct in_sysc), &sysccmp);
333
+		out_size += psize;
334
+	}
335
+	/* Allocation */
336
+	sysc_l = xcalloc(sizeof(*sysc_l), out_size);
337
+	sysc_r = xcalloc(sizeof(*sysc_r), out_size);