[PATCH] Split qualify/multipers-related stuff into separate files

Eugene Syromyatnikov evgsyr at gmail.com
Sun Aug 7 04:53:51 UTC 2016


This is an initial attempt ("proof of concept") of division of enormous
syscall.c into more local pieces. Originally it was intended to split
out qualify-related stuff, but in process it is revealed that there is
also significant part of multipers-related stuff which is also should be
isolated from syscall.c in order to successfully separate qualify stuff.
Notable tricks:
 * Reliance on SYS_socket_subcall/SYS_ipc_subcall defined in
   syscallent.h which is not a normal header. As a result,
   decode_socket_subcall/decode_ipc_subcall are provided and called
   disregarding of presence of these macros (they are defined as no-op
   in case macros are not defined)
 * MAX_NSYSCALLS is derived from nsyscalls, which, in turn, derived
   from size of array produced from inclusion of syscallent.h. As a
   result, all references to MAX_NSYSCALLS are replaced with
   get_nsyscalls().
 * Reliance on qual_vec in qual_flags. New function get_qual() is
   defined and gual_flags is converted to functional macro which calls
   it providing current personality.

This change passes tests on x86_64 and m32/x86_64, but surely needs
additional testing (especially on different architectures) in case split
of this sort proves itself useful.

* Makefile.am(strace_SOURCES): Add multipers.c, multipers.h, qualify.c,
  qualify.h.
* defs.h: Part of definitions moved to multipers.h.
* multipers.c: New file. Contains parts of syscall.c related to support
  of multiple personalities.
* multipers.h: New file. Contains parts of defs.h related to support of
  multiple personalities along with public interface of multipers.c
  (existing calls: set_personality, update_personality,
  decode_socket_subcall, decode_ipc_subcall; new calls: get_nsyscalls,
  *get_sysents).
* qualify.c: New file. Contains parts of syscall.c related to entity
  tracing qualification.
* qualify.h: New file. Contains public interface implemented in
  qualify.c (num_quals, qual_vec, get_qual, qualify).
* strace.c: Include multipers.h and qualify.h.
  (print_signalled, print_stopped) Replace qual_flags array subscription
  with call.
* syscall.c: Parts of definitions related to multiple personalities
  support and entity qualification moved to multipers.c and qualify.c,
  respectively.
  (decode_mips_subcall, dumpio, get_scno) Replace qual_flags array
  subscription with call.
  (trace_syscall_entering) Removing preprocessor checks around
  decode_socket_subcall/decode_ipc_subcall calls.

---
 Makefile.am |    4 +
 defs.h      |  196 +-------------------
 multipers.c |  380 +++++++++++++++++++++++++++++++++++++++
 multipers.h |  215 ++++++++++++++++++++++
 qualify.c   |  231 ++++++++++++++++++++++++
 qualify.h   |   19 ++
 strace.c    |    6 +-
 syscall.c   |  580 +----------------------------------------------------------
 8 files changed, 860 insertions(+), 771 deletions(-)
 create mode 100644 multipers.c
 create mode 100644 multipers.h
 create mode 100644 qualify.c
 create mode 100644 qualify.h

diff --git a/Makefile.am b/Makefile.am
index cb0bd92..4e94dce 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -161,6 +161,8 @@ strace_SOURCES =	\
 	msghdr.c	\
 	msghdr.h	\
 	mtd.c		\
+	multipers.c     \
+	multipers.h     \
 	native_defs.h	\
 	net.c		\
 	netlink.c       \
@@ -187,6 +189,8 @@ strace_SOURCES =	\
 	process_vm.c	\
 	ptp.c		\
 	ptrace.h	\
+	qualify.c       \
+	qualify.h       \
 	quota.c		\
 	readahead.c	\
 	readlink.c	\
diff --git a/defs.h b/defs.h
index eabce52..85c8e14 100644
--- a/defs.h
+++ b/defs.h
@@ -58,6 +58,7 @@
 #include <sys/syscall.h>
 
 #include "mpers_type.h"
+#include "multipers.h"
 #include "gcc_compat.h"
 
 #ifndef HAVE_STRERROR
@@ -151,146 +152,6 @@ extern char *stpcpy(char *dst, const char *src);
 # define ERESTART_RESTARTBLOCK 516
 #endif
 
-#if defined(SPARC) || defined(SPARC64)
-# define PERSONALITY0_WORDSIZE 4
-# if defined(SPARC64)
-#  define SUPPORTED_PERSONALITIES 2
-#  define PERSONALITY1_WORDSIZE 8
-#  ifdef HAVE_M32_MPERS
-#   define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
-#   define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
-#   define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
-#   define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
-#  endif
-# endif
-#endif
-
-#ifdef X86_64
-# define SUPPORTED_PERSONALITIES 3
-# define PERSONALITY0_WORDSIZE 8
-# define PERSONALITY1_WORDSIZE 4
-# define PERSONALITY2_WORDSIZE 4
-# ifdef HAVE_M32_MPERS
-#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
-#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
-#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
-#  define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
-# endif
-# ifdef HAVE_MX32_MPERS
-#  define PERSONALITY2_INCLUDE_FUNCS "mx32_funcs.h"
-#  define PERSONALITY2_INCLUDE_PRINTERS_DECLS "mx32_printer_decls.h"
-#  define PERSONALITY2_INCLUDE_PRINTERS_DEFS "mx32_printer_defs.h"
-#  define MPERS_mx32_IOCTL_MACROS "ioctl_redefs2.h"
-# endif
-#endif
-
-#ifdef X32
-# define SUPPORTED_PERSONALITIES 2
-# define PERSONALITY0_WORDSIZE 4
-# define PERSONALITY1_WORDSIZE 4
-# ifdef HAVE_M32_MPERS
-#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
-#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
-#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
-#  define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
-# endif
-#endif
-
-#ifdef ARM
-/* one personality */
-#endif
-
-#ifdef AARCH64
-/* The existing ARM personality, then AArch64 */
-# define SUPPORTED_PERSONALITIES 2
-# define PERSONALITY0_WORDSIZE 8
-# define PERSONALITY1_WORDSIZE 4
-# ifdef HAVE_M32_MPERS
-#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
-#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
-#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
-#  define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
-# endif
-#endif
-
-#ifdef POWERPC64
-# define SUPPORTED_PERSONALITIES 2
-# define PERSONALITY0_WORDSIZE 8
-# define PERSONALITY1_WORDSIZE 4
-# ifdef HAVE_M32_MPERS
-#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
-#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
-#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
-#  define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
-# endif
-#endif
-
-#ifdef TILE
-# define SUPPORTED_PERSONALITIES 2
-# define PERSONALITY0_WORDSIZE 8
-# define PERSONALITY1_WORDSIZE 4
-# ifdef __tilepro__
-#  define DEFAULT_PERSONALITY 1
-# endif
-# ifdef HAVE_M32_MPERS
-#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
-#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
-#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
-#  define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
-# endif
-#endif
-
-#ifndef SUPPORTED_PERSONALITIES
-# define SUPPORTED_PERSONALITIES 1
-#endif
-#ifndef DEFAULT_PERSONALITY
-# define DEFAULT_PERSONALITY 0
-#endif
-#ifndef PERSONALITY0_WORDSIZE
-# define PERSONALITY0_WORDSIZE SIZEOF_LONG
-#endif
-
-#ifndef PERSONALITY0_INCLUDE_PRINTERS_DECLS
-# define PERSONALITY0_INCLUDE_PRINTERS_DECLS "native_printer_decls.h"
-#endif
-#ifndef PERSONALITY0_INCLUDE_PRINTERS_DEFS
-# define PERSONALITY0_INCLUDE_PRINTERS_DEFS "native_printer_defs.h"
-#endif
-
-#ifndef PERSONALITY1_INCLUDE_PRINTERS_DECLS
-# define PERSONALITY1_INCLUDE_PRINTERS_DECLS "native_printer_decls.h"
-#endif
-#ifndef PERSONALITY1_INCLUDE_PRINTERS_DEFS
-# define PERSONALITY1_INCLUDE_PRINTERS_DEFS "native_printer_defs.h"
-#endif
-
-#ifndef PERSONALITY2_INCLUDE_PRINTERS_DECLS
-# define PERSONALITY2_INCLUDE_PRINTERS_DECLS "native_printer_decls.h"
-#endif
-#ifndef PERSONALITY2_INCLUDE_PRINTERS_DEFS
-# define PERSONALITY2_INCLUDE_PRINTERS_DEFS "native_printer_defs.h"
-#endif
-
-#ifndef PERSONALITY1_INCLUDE_FUNCS
-# define PERSONALITY1_INCLUDE_FUNCS "empty.h"
-#endif
-#ifndef PERSONALITY2_INCLUDE_FUNCS
-# define PERSONALITY2_INCLUDE_FUNCS "empty.h"
-#endif
-
-typedef struct sysent {
-	unsigned nargs;
-	int	sys_flags;
-	int	sen;
-	int	(*sys_func)();
-	const char *sys_name;
-} struct_sysent;
-
-typedef struct ioctlent {
-	const char *symbol;
-	unsigned int code;
-} struct_ioctlent;
-
 #if defined LINUX_MIPSN32 || defined X32
 # define HAVE_STRUCT_TCB_EXT_ARG 1
 #else
@@ -366,7 +227,6 @@ struct tcb {
 #define QUAL_SIGNAL	0x010	/* report events with this signal */
 #define QUAL_READ	0x020	/* dump data read on this file descriptor */
 #define QUAL_WRITE	0x040	/* dump data written to this file descriptor */
-typedef uint8_t qualbits_t;
 
 #define DEFAULT_QUAL_FLAGS (QUAL_TRACE | QUAL_ABBREV | QUAL_VERBOSE)
 
@@ -794,24 +654,6 @@ extern void tabto(void);
 extern void tprintf(const char *fmt, ...) ATTRIBUTE_FORMAT((printf, 1, 2));
 extern void tprints(const char *str);
 
-#if SUPPORTED_PERSONALITIES > 1
-extern void set_personality(int personality);
-extern unsigned current_personality;
-#else
-# define set_personality(personality) ((void)0)
-# define current_personality 0
-#endif
-
-#if SUPPORTED_PERSONALITIES == 1
-# define current_wordsize PERSONALITY0_WORDSIZE
-#else
-# if SUPPORTED_PERSONALITIES == 2 && PERSONALITY0_WORDSIZE == PERSONALITY1_WORDSIZE
-#  define current_wordsize PERSONALITY0_WORDSIZE
-# else
-extern unsigned current_wordsize;
-# endif
-#endif
-
 /* In many, many places we play fast and loose and use
  * tprintf("%d", (int) tcp->u_arg[N]) to print fds, pids etc.
  * We probably need to use widen_to_long() instead:
@@ -830,42 +672,6 @@ extern unsigned current_wordsize;
 	 sizeof(v) == sizeof(long) ? (unsigned long long) (unsigned long) (v) : \
 	 (unsigned long long) (v))
 
-extern const struct_sysent sysent0[];
-extern const char *const errnoent0[];
-extern const char *const signalent0[];
-extern const struct_ioctlent ioctlent0[];
-extern qualbits_t *qual_vec[SUPPORTED_PERSONALITIES];
-#define qual_flags (qual_vec[current_personality])
-
-#if SUPPORTED_PERSONALITIES > 1
-extern const struct_sysent *sysent;
-extern const char *const *errnoent;
-extern const char *const *signalent;
-extern const struct_ioctlent *ioctlent;
-#else
-# define sysent     sysent0
-# define errnoent   errnoent0
-# define signalent  signalent0
-# define ioctlent   ioctlent0
-#endif
-
-extern unsigned nsyscalls;
-extern unsigned nerrnos;
-extern unsigned nsignals;
-extern unsigned nioctlents;
-extern unsigned num_quals;
-
-#ifdef IN_MPERS_BOOTSTRAP
-/* Transform multi-line MPERS_PRINTER_DECL statements to one-liners.  */
-# define MPERS_PRINTER_DECL(type, name, ...) MPERS_PRINTER_DECL(type, name, __VA_ARGS__)
-#else /* !IN_MPERS_BOOTSTRAP */
-# if SUPPORTED_PERSONALITIES > 1
-#  include "printers.h"
-# else
-#  include "native_printer_decls.h"
-# endif
-# define MPERS_PRINTER_DECL(type, name, ...) type MPERS_FUNC_NAME(name)(__VA_ARGS__)
-#endif /* !IN_MPERS_BOOTSTRAP */
 
 /*
  * If you need non-NULL sysent[scno].sys_func and sysent[scno].sys_name
diff --git a/multipers.c b/multipers.c
new file mode 100644
index 0000000..a297486
--- /dev/null
+++ b/multipers.c
@@ -0,0 +1,380 @@
+#include "defs.h"
+#include "native_defs.h"
+#include "qualify.h"
+#include "syscall.h"
+
+#include "multipers.h"
+
+/* Define these shorthand notations to simplify the syscallent files. */
+#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 NF SYSCALL_NEVER_FAILS
+#define MA MAX_ARGS
+#define SI STACKTRACE_INVALIDATE_CACHE
+#define SE STACKTRACE_CAPTURE_ON_ENTER
+
+#define SEN(syscall_name) SEN_ ## syscall_name, SYS_FUNC_NAME(sys_ ## syscall_name)
+
+const struct_sysent sysent0[] = {
+#include "syscallent.h"
+};
+
+#if SUPPORTED_PERSONALITIES > 1
+# include PERSONALITY1_INCLUDE_FUNCS
+static const struct_sysent sysent1[] = {
+# include "syscallent1.h"
+};
+#endif
+
+#if SUPPORTED_PERSONALITIES > 2
+# include PERSONALITY2_INCLUDE_FUNCS
+static const struct_sysent sysent2[] = {
+# include "syscallent2.h"
+};
+#endif
+
+/* Now undef them since short defines cause wicked namespace pollution. */
+#undef SEN
+#undef TD
+#undef TF
+#undef TI
+#undef TN
+#undef TP
+#undef TS
+#undef TM
+#undef NF
+#undef MA
+#undef SI
+#undef SE
+
+/*
+ * `ioctlent[012].h' files are automatically generated by the auxiliary
+ * program `ioctlsort', such that the list is sorted by the `code' field.
+ * This has the side-effect of resolving the _IO.. macros into
+ * plain integers, eliminating the need to include here everything
+ * in "/usr/include".
+ */
+
+const char *const errnoent0[] = {
+#include "errnoent.h"
+};
+const char *const signalent0[] = {
+#include "signalent.h"
+};
+const struct_ioctlent ioctlent0[] = {
+#include "ioctlent0.h"
+};
+
+#if SUPPORTED_PERSONALITIES > 1
+static const char *const errnoent1[] = {
+# include "errnoent1.h"
+};
+static const char *const signalent1[] = {
+# include "signalent1.h"
+};
+static const struct_ioctlent ioctlent1[] = {
+# include "ioctlent1.h"
+};
+# include PERSONALITY0_INCLUDE_PRINTERS_DECLS
+static const struct_printers printers0 = {
+# include PERSONALITY0_INCLUDE_PRINTERS_DEFS
+};
+# include PERSONALITY1_INCLUDE_PRINTERS_DECLS
+static const struct_printers printers1 = {
+# include PERSONALITY1_INCLUDE_PRINTERS_DEFS
+};
+#endif
+
+#if SUPPORTED_PERSONALITIES > 2
+static const char *const errnoent2[] = {
+# include "errnoent2.h"
+};
+static const char *const signalent2[] = {
+# include "signalent2.h"
+};
+static const struct_ioctlent ioctlent2[] = {
+# include "ioctlent2.h"
+};
+# include PERSONALITY2_INCLUDE_PRINTERS_DECLS
+static const struct_printers printers2 = {
+# include PERSONALITY2_INCLUDE_PRINTERS_DEFS
+};
+#endif
+
+enum {
+	nsyscalls0 = ARRAY_SIZE(sysent0)
+#if SUPPORTED_PERSONALITIES > 1
+	, nsyscalls1 = ARRAY_SIZE(sysent1)
+# if SUPPORTED_PERSONALITIES > 2
+	, nsyscalls2 = ARRAY_SIZE(sysent2)
+# endif
+#endif
+};
+
+enum {
+	nerrnos0 = ARRAY_SIZE(errnoent0)
+#if SUPPORTED_PERSONALITIES > 1
+	, nerrnos1 = ARRAY_SIZE(errnoent1)
+# if SUPPORTED_PERSONALITIES > 2
+	, nerrnos2 = ARRAY_SIZE(errnoent2)
+# endif
+#endif
+};
+
+enum {
+	nsignals0 = ARRAY_SIZE(signalent0)
+#if SUPPORTED_PERSONALITIES > 1
+	, nsignals1 = ARRAY_SIZE(signalent1)
+# if SUPPORTED_PERSONALITIES > 2
+	, nsignals2 = ARRAY_SIZE(signalent2)
+# endif
+#endif
+};
+
+enum {
+	nioctlents0 = ARRAY_SIZE(ioctlent0)
+#if SUPPORTED_PERSONALITIES > 1
+	, nioctlents1 = ARRAY_SIZE(ioctlent1)
+# if SUPPORTED_PERSONALITIES > 2
+	, nioctlents2 = ARRAY_SIZE(ioctlent2)
+# endif
+#endif
+};
+
+enum {
+	MAX_NSYSCALLS1 = (nsyscalls0
+#if SUPPORTED_PERSONALITIES > 1
+			> nsyscalls1 ? nsyscalls0 : nsyscalls1
+#endif
+			),
+	MAX_NSYSCALLS2 = (MAX_NSYSCALLS1
+#if SUPPORTED_PERSONALITIES > 2
+			> nsyscalls2 ? MAX_NSYSCALLS1 : nsyscalls2
+#endif
+			),
+	MAX_NSYSCALLS = MAX_NSYSCALLS2,
+	/* We are ready for arches with up to 255 signals,
+	 * even though the largest known signo is on MIPS and it is 128.
+	 * The number of existing syscalls on all arches is
+	 * larger that 255 anyway, so it is just a pedantic matter.
+	 */
+	MIN_QUALS = MAX_NSYSCALLS > 255 ? MAX_NSYSCALLS : 255
+};
+
+#if SUPPORTED_PERSONALITIES > 1
+const struct_sysent *sysent = sysent0;
+const char *const *errnoent = errnoent0;
+const char *const *signalent = signalent0;
+const struct_ioctlent *ioctlent = ioctlent0;
+const struct_printers *printers = &printers0;
+#endif
+
+unsigned nsyscalls = nsyscalls0;
+unsigned nerrnos = nerrnos0;
+unsigned nsignals = nsignals0;
+unsigned nioctlents = nioctlents0;
+
+const unsigned nsyscall_vec[SUPPORTED_PERSONALITIES] = {
+	nsyscalls0,
+#if SUPPORTED_PERSONALITIES > 1
+	nsyscalls1,
+#endif
+#if SUPPORTED_PERSONALITIES > 2
+	nsyscalls2,
+#endif
+};
+static const struct_sysent *const sysent_vec[SUPPORTED_PERSONALITIES] = {
+	sysent0,
+#if SUPPORTED_PERSONALITIES > 1
+	sysent1,
+#endif
+#if SUPPORTED_PERSONALITIES > 2
+	sysent2,
+#endif
+};
+
+#if SUPPORTED_PERSONALITIES > 1
+unsigned current_personality;
+
+# ifndef current_wordsize
+unsigned current_wordsize;
+static const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
+	PERSONALITY0_WORDSIZE,
+	PERSONALITY1_WORDSIZE,
+# if SUPPORTED_PERSONALITIES > 2
+	PERSONALITY2_WORDSIZE,
+# endif
+};
+# endif
+
+unsigned int get_nsyscalls(int personality)
+{
+	if (personality == -1)
+		return MAX_NSYSCALLS;
+
+	return ((personality >= 0) && (personality < SUPPORTED_PERSONALITIES)) ?
+		nsyscall_vec[personality] : 0;
+}
+
+const struct_sysent *get_sysents(int personality)
+{
+	return ((personality >= 0) && (personality < SUPPORTED_PERSONALITIES)) ?
+	    sysent_vec[personality] : NULL;
+}
+
+void
+set_personality(int personality)
+{
+	nsyscalls = nsyscall_vec[personality];
+	sysent = sysent_vec[personality];
+
+	switch (personality) {
+	case 0:
+		errnoent = errnoent0;
+		nerrnos = nerrnos0;
+		ioctlent = ioctlent0;
+		nioctlents = nioctlents0;
+		signalent = signalent0;
+		nsignals = nsignals0;
+		printers = &printers0;
+		break;
+
+	case 1:
+		errnoent = errnoent1;
+		nerrnos = nerrnos1;
+		ioctlent = ioctlent1;
+		nioctlents = nioctlents1;
+		signalent = signalent1;
+		nsignals = nsignals1;
+		printers = &printers1;
+		break;
+
+# if SUPPORTED_PERSONALITIES > 2
+	case 2:
+		errnoent = errnoent2;
+		nerrnos = nerrnos2;
+		ioctlent = ioctlent2;
+		nioctlents = nioctlents2;
+		signalent = signalent2;
+		nsignals = nsignals2;
+		printers = &printers2;
+		break;
+# endif
+	}
+
+	current_personality = personality;
+# ifndef current_wordsize
+	current_wordsize = personality_wordsize[personality];
+# endif
+}
+
+void
+update_personality(struct tcb *tcp, unsigned int personality)
+{
+	if (personality == current_personality)
+		return;
+	set_personality(personality);
+
+	if (personality == tcp->currpers)
+		return;
+	tcp->currpers = personality;
+
+# undef PERSONALITY_NAMES
+# if defined POWERPC64
+#  define PERSONALITY_NAMES {"64 bit", "32 bit"}
+# elif defined X86_64
+#  define PERSONALITY_NAMES {"64 bit", "32 bit", "x32"}
+# elif defined X32
+#  define PERSONALITY_NAMES {"x32", "32 bit"}
+# elif defined AARCH64
+#  define PERSONALITY_NAMES {"64 bit", "32 bit"}
+# elif defined TILE
+#  define PERSONALITY_NAMES {"64-bit", "32-bit"}
+# endif
+# ifdef PERSONALITY_NAMES
+	if (!qflag) {
+		static const char *const names[] = PERSONALITY_NAMES;
+		error_msg("[ Process PID=%d runs in %s mode. ]",
+			  tcp->pid, names[personality]);
+	}
+# endif
+}
+#endif
+
+
+#ifdef SYS_socket_subcall
+void
+decode_socket_subcall(struct tcb *tcp)
+{
+	const int call = tcp->u_arg[0];
+
+	if (call < 1 || call >= SYS_socket_nsubcalls)
+		return;
+
+	const unsigned long scno = SYS_socket_subcall + call;
+	const unsigned int nargs = sysent[scno].nargs;
+	uint64_t buf[nargs];
+
+	if (umoven(tcp, tcp->u_arg[1], nargs * current_wordsize, buf) < 0)
+		return;
+
+	tcp->scno = scno;
+	tcp->qual_flg = qual_flags(scno);
+	tcp->s_ent = &sysent[scno];
+
+	unsigned int i;
+	for (i = 0; i < nargs; ++i)
+		tcp->u_arg[i] = (sizeof(uint32_t) == current_wordsize)
+				? ((uint32_t *) (void *) buf)[i] : buf[i];
+}
+#else /* #ifdef SYS_socket_subcall */
+void decode_socket_subcall(struct tcb *tcp) {}
+#endif /* #ifdef SYS_socket_subcall */
+
+
+#ifdef SYS_ipc_subcall
+void
+decode_ipc_subcall(struct tcb *tcp)
+{
+	unsigned int call = tcp->u_arg[0];
+	const unsigned int version = call >> 16;
+
+	if (version) {
+# if defined S390 || defined S390X
+		return;
+# else
+#  ifdef SPARC64
+		if (current_wordsize == 8)
+			return;
+#  endif
+		set_tcb_priv_ulong(tcp, version);
+		call &= 0xffff;
+# endif
+	}
+
+	switch (call) {
+		case  1: case  2: case  3: case  4:
+		case 11: case 12: case 13: case 14:
+		case 21: case 22: case 23: case 24:
+			break;
+		default:
+			return;
+	}
+
+	tcp->scno = SYS_ipc_subcall + call;
+	tcp->qual_flg = qual_flags(tcp->scno);
+	tcp->s_ent = &sysent[tcp->scno];
+
+	const unsigned int n = tcp->s_ent->nargs;
+	unsigned int i;
+	for (i = 0; i < n; i++)
+		tcp->u_arg[i] = tcp->u_arg[i + 1];
+}
+#else /* #ifdef SYS_ipc_subcall */
+void decode_ipc_subcall(struct tcb *tcp) {}
+#endif /* #ifdef SYS_ipc_subcall */
diff --git a/multipers.h b/multipers.h
new file mode 100644
index 0000000..7f02e4c
--- /dev/null
+++ b/multipers.h
@@ -0,0 +1,215 @@
+#ifndef STRACE_MULTIPERS_H
+#define STRACE_MULTIPERS_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <features.h>
+
+#if defined(SPARC) || defined(SPARC64)
+# define PERSONALITY0_WORDSIZE 4
+# if defined(SPARC64)
+#  define SUPPORTED_PERSONALITIES 2
+#  define PERSONALITY1_WORDSIZE 8
+#  ifdef HAVE_M32_MPERS
+#   define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
+#   define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
+#   define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
+#   define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
+#  endif
+# endif
+#endif
+
+#ifdef X86_64
+# define SUPPORTED_PERSONALITIES 3
+# define PERSONALITY0_WORDSIZE 8
+# define PERSONALITY1_WORDSIZE 4
+# define PERSONALITY2_WORDSIZE 4
+# ifdef HAVE_M32_MPERS
+#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
+#  define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
+# endif
+# ifdef HAVE_MX32_MPERS
+#  define PERSONALITY2_INCLUDE_FUNCS "mx32_funcs.h"
+#  define PERSONALITY2_INCLUDE_PRINTERS_DECLS "mx32_printer_decls.h"
+#  define PERSONALITY2_INCLUDE_PRINTERS_DEFS "mx32_printer_defs.h"
+#  define MPERS_mx32_IOCTL_MACROS "ioctl_redefs2.h"
+# endif
+#endif
+
+#ifdef X32
+# define SUPPORTED_PERSONALITIES 2
+# define PERSONALITY0_WORDSIZE 4
+# define PERSONALITY1_WORDSIZE 4
+# ifdef HAVE_M32_MPERS
+#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
+#  define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
+# endif
+#endif
+
+#ifdef ARM
+/* one personality */
+#endif
+
+#ifdef AARCH64
+/* The existing ARM personality, then AArch64 */
+# define SUPPORTED_PERSONALITIES 2
+# define PERSONALITY0_WORDSIZE 8
+# define PERSONALITY1_WORDSIZE 4
+# ifdef HAVE_M32_MPERS
+#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
+#  define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
+# endif
+#endif
+
+#ifdef POWERPC64
+# define SUPPORTED_PERSONALITIES 2
+# define PERSONALITY0_WORDSIZE 8
+# define PERSONALITY1_WORDSIZE 4
+# ifdef HAVE_M32_MPERS
+#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
+#  define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
+# endif
+#endif
+
+#ifdef TILE
+# define SUPPORTED_PERSONALITIES 2
+# define PERSONALITY0_WORDSIZE 8
+# define PERSONALITY1_WORDSIZE 4
+# ifdef __tilepro__
+#  define DEFAULT_PERSONALITY 1
+# endif
+# ifdef HAVE_M32_MPERS
+#  define PERSONALITY1_INCLUDE_FUNCS "m32_funcs.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DECLS "m32_printer_decls.h"
+#  define PERSONALITY1_INCLUDE_PRINTERS_DEFS "m32_printer_defs.h"
+#  define MPERS_m32_IOCTL_MACROS "ioctl_redefs1.h"
+# endif
+#endif
+
+#ifndef SUPPORTED_PERSONALITIES
+# define SUPPORTED_PERSONALITIES 1
+#endif
+#ifndef DEFAULT_PERSONALITY
+# define DEFAULT_PERSONALITY 0
+#endif
+#ifndef PERSONALITY0_WORDSIZE
+# define PERSONALITY0_WORDSIZE SIZEOF_LONG
+#endif
+
+#ifndef PERSONALITY0_INCLUDE_PRINTERS_DECLS
+# define PERSONALITY0_INCLUDE_PRINTERS_DECLS "native_printer_decls.h"
+#endif
+#ifndef PERSONALITY0_INCLUDE_PRINTERS_DEFS
+# define PERSONALITY0_INCLUDE_PRINTERS_DEFS "native_printer_defs.h"
+#endif
+
+#ifndef PERSONALITY1_INCLUDE_PRINTERS_DECLS
+# define PERSONALITY1_INCLUDE_PRINTERS_DECLS "native_printer_decls.h"
+#endif
+#ifndef PERSONALITY1_INCLUDE_PRINTERS_DEFS
+# define PERSONALITY1_INCLUDE_PRINTERS_DEFS "native_printer_defs.h"
+#endif
+
+#ifndef PERSONALITY2_INCLUDE_PRINTERS_DECLS
+# define PERSONALITY2_INCLUDE_PRINTERS_DECLS "native_printer_decls.h"
+#endif
+#ifndef PERSONALITY2_INCLUDE_PRINTERS_DEFS
+# define PERSONALITY2_INCLUDE_PRINTERS_DEFS "native_printer_defs.h"
+#endif
+
+#ifndef PERSONALITY1_INCLUDE_FUNCS
+# define PERSONALITY1_INCLUDE_FUNCS "empty.h"
+#endif
+#ifndef PERSONALITY2_INCLUDE_FUNCS
+# define PERSONALITY2_INCLUDE_FUNCS "empty.h"
+#endif
+
+typedef struct sysent {
+	unsigned nargs;
+	int	sys_flags;
+	int	sen;
+	int	(*sys_func)();
+	const char *sys_name;
+} struct_sysent;
+
+typedef struct ioctlent {
+	const char *symbol;
+	unsigned int code;
+} struct_ioctlent;
+
+extern const struct_sysent sysent0[];
+extern const char *const errnoent0[];
+extern const char *const signalent0[];
+extern const struct_ioctlent ioctlent0[];
+
+#if SUPPORTED_PERSONALITIES > 1
+extern const struct_sysent *sysent;
+extern const char *const *errnoent;
+extern const char *const *signalent;
+extern const struct_ioctlent *ioctlent;
+#else
+# define sysent     sysent0
+# define errnoent   errnoent0
+# define signalent  signalent0
+# define ioctlent   ioctlent0
+#endif
+
+extern unsigned nsyscalls;
+extern unsigned nerrnos;
+extern unsigned nsignals;
+extern unsigned nioctlents;
+extern unsigned num_quals;
+
+struct strace_statfs;
+struct tcb;
+
+#ifdef IN_MPERS_BOOTSTRAP
+/* Transform multi-line MPERS_PRINTER_DECL statements to one-liners.  */
+# define MPERS_PRINTER_DECL(type, name, ...) MPERS_PRINTER_DECL(type, name, __VA_ARGS__)
+#else /* !IN_MPERS_BOOTSTRAP */
+# if SUPPORTED_PERSONALITIES > 1
+#  include "printers.h"
+# else
+#  include "native_printer_decls.h"
+# endif
+# define MPERS_PRINTER_DECL(type, name, ...) type MPERS_FUNC_NAME(name)(__VA_ARGS__)
+#endif /* !IN_MPERS_BOOTSTRAP */
+
+extern const unsigned nsyscall_vec[SUPPORTED_PERSONALITIES];
+
+unsigned int get_nsyscalls(int personality);
+const struct_sysent *get_sysents(int personality);
+
+#if SUPPORTED_PERSONALITIES > 1
+extern void set_personality(int personality);
+void update_personality(struct tcb *tcp, unsigned int personality);
+extern unsigned current_personality;
+#else
+# define set_personality(personality) ((void)0)
+# define current_personality 0
+#endif
+
+#if SUPPORTED_PERSONALITIES == 1
+# define current_wordsize PERSONALITY0_WORDSIZE
+#else
+# if SUPPORTED_PERSONALITIES == 2 && PERSONALITY0_WORDSIZE == PERSONALITY1_WORDSIZE
+#  define current_wordsize PERSONALITY0_WORDSIZE
+# else
+extern unsigned current_wordsize;
+# endif
+#endif
+
+void decode_socket_subcall(struct tcb *tcp);
+void decode_ipc_subcall(struct tcb *tcp);
+
+#endif /* #ifndef STRACE_MULTIPERS_H */
diff --git a/qualify.c b/qualify.c
new file mode 100644
index 0000000..3307dcf
--- /dev/null
+++ b/qualify.c
@@ -0,0 +1,231 @@
+#include <signal.h>
+
+#include "multipers.h"
+
+#include "qualify.h"
+
+#ifndef NSIG
+# warning: NSIG is not defined, using 32
+# define NSIG 32
+#endif
+
+static int qual_syscall(), qual_signal(), qual_desc();
+
+static const struct qual_options {
+	unsigned int bitflag;
+	const char *option_name;
+	int (*qualify)(const char *, int, int);
+	const char *argument_name;
+} qual_options[] = {
+	{ QUAL_TRACE,	"trace",	qual_syscall,	"system call"	},
+	{ QUAL_TRACE,	"t",		qual_syscall,	"system call"	},
+	{ QUAL_ABBREV,	"abbrev",	qual_syscall,	"system call"	},
+	{ QUAL_ABBREV,	"a",		qual_syscall,	"system call"	},
+	{ QUAL_VERBOSE,	"verbose",	qual_syscall,	"system call"	},
+	{ QUAL_VERBOSE,	"v",		qual_syscall,	"system call"	},
+	{ QUAL_RAW,	"raw",		qual_syscall,	"system call"	},
+	{ QUAL_RAW,	"x",		qual_syscall,	"system call"	},
+	{ QUAL_SIGNAL,	"signal",	qual_signal,	"signal"	},
+	{ QUAL_SIGNAL,	"signals",	qual_signal,	"signal"	},
+	{ QUAL_SIGNAL,	"s",		qual_signal,	"signal"	},
+	{ QUAL_READ,	"read",		qual_desc,	"descriptor"	},
+	{ QUAL_READ,	"reads",	qual_desc,	"descriptor"	},
+	{ QUAL_READ,	"r",		qual_desc,	"descriptor"	},
+	{ QUAL_WRITE,	"write",	qual_desc,	"descriptor"	},
+	{ QUAL_WRITE,	"writes",	qual_desc,	"descriptor"	},
+	{ QUAL_WRITE,	"w",		qual_desc,	"descriptor"	},
+	{ 0,		NULL,		NULL,		NULL		},
+};
+
+unsigned num_quals = 0;
+qualbits_t *qual_vec[SUPPORTED_PERSONALITIES];
+
+
+static void
+reallocate_qual(const unsigned int n)
+{
+	unsigned p;
+	qualbits_t *qp;
+	for (p = 0; p < SUPPORTED_PERSONALITIES; p++) {
+		qp = qual_vec[p] = xreallocarray(qual_vec[p], n,
+						 sizeof(qualbits_t));
+		memset(&qp[num_quals], 0, (n - num_quals) * sizeof(qualbits_t));
+	}
+	num_quals = n;
+}
+
+static void
+qualify_one(const unsigned int n, unsigned int bitflag, const int not, const int pers)
+{
+	int p;
+
+	if (num_quals <= n)
+		reallocate_qual(n + 1);
+
+	for (p = 0; p < SUPPORTED_PERSONALITIES; p++) {
+		if (pers == p || pers < 0) {
+			if (not)
+				qual_vec[p][n] &= ~bitflag;
+			else
+				qual_vec[p][n] |= bitflag;
+		}
+	}
+}
+
+static int
+qual_syscall(const char *s, const unsigned int bitflag, const int not)
+{
+	int p;
+	unsigned int i;
+	int rc = -1;
+
+	if (*s >= '0' && *s <= '9') {
+		i = string_to_uint(s);
+		if (i >= get_nsyscalls(-1))
+			return -1;
+		qualify_one(i, bitflag, not, -1);
+		return 0;
+	}
+
+	for (p = 0; p < SUPPORTED_PERSONALITIES; p++) {
+		unsigned int nsyscalls = get_nsyscalls(p);
+
+		for (i = 0; i < nsyscalls; i++) {
+			if (get_sysents(p)[i].sys_name
+			 && strcmp(s, get_sysents(p)[i].sys_name) == 0
+			) {
+				qualify_one(i, bitflag, not, p);
+				rc = 0;
+			}
+		}
+	}
+
+	return rc;
+}
+
+static int
+qual_signal(const char *s, const unsigned int bitflag, const int not)
+{
+	unsigned int i;
+
+	if (*s >= '0' && *s <= '9') {
+		int signo = string_to_uint(s);
+		if (signo < 0 || signo > 255)
+			return -1;
+		qualify_one(signo, bitflag, not, -1);
+		return 0;
+	}
+	if (strncasecmp(s, "SIG", 3) == 0)
+		s += 3;
+	for (i = 0; i <= NSIG; i++) {
+		if (strcasecmp(s, signame(i) + 3) == 0) {
+			qualify_one(i, bitflag, not, -1);
+			return 0;
+		}
+	}
+	return -1;
+}
+
+static int
+qual_desc(const char *s, const unsigned int bitflag, const int not)
+{
+	if (*s >= '0' && *s <= '9') {
+		int desc = string_to_uint(s);
+		if (desc < 0 || desc > 0x7fff) /* paranoia */
+			return -1;
+		qualify_one(desc, bitflag, not, -1);
+		return 0;
+	}
+	return -1;
+}
+
+static int
+lookup_class(const char *s)
+{
+	if (strcmp(s, "file") == 0)
+		return TRACE_FILE;
+	if (strcmp(s, "ipc") == 0)
+		return TRACE_IPC;
+	if (strcmp(s, "network") == 0)
+		return TRACE_NETWORK;
+	if (strcmp(s, "process") == 0)
+		return TRACE_PROCESS;
+	if (strcmp(s, "signal") == 0)
+		return TRACE_SIGNAL;
+	if (strcmp(s, "desc") == 0)
+		return TRACE_DESC;
+	if (strcmp(s, "memory") == 0)
+		return TRACE_MEMORY;
+	return -1;
+}
+
+void
+qualify(const char *s)
+{
+	const struct qual_options *opt;
+	char *copy;
+	const char *p;
+	int not;
+	unsigned int i;
+
+	if (num_quals == 0)
+		reallocate_qual(get_nsyscalls(-1));
+
+	opt = &qual_options[0];
+	for (i = 0; (p = qual_options[i].option_name); i++) {
+		unsigned int len = strlen(p);
+		if (strncmp(s, p, len) == 0 && s[len] == '=') {
+			opt = &qual_options[i];
+			s += len + 1;
+			break;
+		}
+	}
+	not = 0;
+	if (*s == '!') {
+		not = 1;
+		s++;
+	}
+	if (strcmp(s, "none") == 0) {
+		not = 1 - not;
+		s = "all";
+	}
+	if (strcmp(s, "all") == 0) {
+		for (i = 0; i < num_quals; i++) {
+			qualify_one(i, opt->bitflag, not, -1);
+		}
+		return;
+	}
+	for (i = 0; i < num_quals; i++) {
+		qualify_one(i, opt->bitflag, !not, -1);
+	}
+	copy = xstrdup(s);
+	for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
+		int n;
+		if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
+			unsigned pers;
+			for (pers = 0; pers < SUPPORTED_PERSONALITIES; pers++) {
+				unsigned int nsyscalls = get_nsyscalls(pers);
+
+				for (i = 0; i < nsyscalls; i++)
+					if (get_sysents(pers)[i].sys_flags & n)
+						qualify_one(i, opt->bitflag, not, pers);
+			}
+			continue;
+		}
+		if (opt->qualify(p, opt->bitflag, not)) {
+			error_msg_and_die("invalid %s '%s'",
+				opt->argument_name, p);
+		}
+	}
+	free(copy);
+	return;
+}
+
+qualbits_t get_qual(int personality, int id)
+{
+	if ((id >= 0) && (id < num_quals) && (personality >= 0) &&
+	    (personality < SUPPORTED_PERSONALITIES))
+		return qual_vec[personality][id];
+
+	return 0;
+}
diff --git a/qualify.h b/qualify.h
new file mode 100644
index 0000000..e71df09
--- /dev/null
+++ b/qualify.h
@@ -0,0 +1,19 @@
+#ifndef STRACE_QUALIY_H
+#define STRACE_QUALIY_H
+
+#include <stdint.h>
+
+#include "defs.h"
+
+
+typedef uint8_t qualbits_t;
+
+extern unsigned num_quals;
+extern qualbits_t *qual_vec[SUPPORTED_PERSONALITIES];
+
+#define qual_flags(_id) get_qual(current_personality, _id)
+
+void qualify(const char *s);
+qualbits_t get_qual(int personality, int id);
+
+#endif /* #ifndef STRACE_QUALIY_H */
diff --git a/strace.c b/strace.c
index 680456b..b785ac8 100644
--- a/strace.c
+++ b/strace.c
@@ -44,8 +44,10 @@
 # include <sys/prctl.h>
 #endif
 
+#include "multipers.h"
 #include "ptrace.h"
 #include "printsiginfo.h"
+#include "qualify.h"
 
 /* In some libc, these aren't declared. Do it ourself: */
 extern char **environ;
@@ -2057,7 +2059,7 @@ print_signalled(struct tcb *tcp, const int pid, int status)
 	}
 
 	if (cflag != CFLAG_ONLY_STATS
-	 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)
+	 && (qual_flags(WTERMSIG(status)) & QUAL_SIGNAL)
 	) {
 		printleader(tcp);
 #ifdef WCOREDUMP
@@ -2093,7 +2095,7 @@ print_stopped(struct tcb *tcp, const siginfo_t *si, const unsigned int sig)
 {
 	if (cflag != CFLAG_ONLY_STATS
 	    && !hide_log_until_execve
-	    && (qual_flags[sig] & QUAL_SIGNAL)
+	    && (qual_flags(sig) & QUAL_SIGNAL)
 	   ) {
 		printleader(tcp);
 		if (si) {
diff --git a/syscall.c b/syscall.c
index e5ac7db..b9a9cce 100644
--- a/syscall.c
+++ b/syscall.c
@@ -63,572 +63,10 @@
 # define NT_PRSTATUS 1
 #endif
 
-#ifndef NSIG
-# warning: NSIG is not defined, using 32
-# define NSIG 32
-#endif
-
+#include "multipers.h"
+#include "qualify.h"
 #include "syscall.h"
 
-/* Define these shorthand notations to simplify the syscallent files. */
-#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 NF SYSCALL_NEVER_FAILS
-#define MA MAX_ARGS
-#define SI STACKTRACE_INVALIDATE_CACHE
-#define SE STACKTRACE_CAPTURE_ON_ENTER
-
-#define SEN(syscall_name) SEN_ ## syscall_name, SYS_FUNC_NAME(sys_ ## syscall_name)
-
-const struct_sysent sysent0[] = {
-#include "syscallent.h"
-};
-
-#if SUPPORTED_PERSONALITIES > 1
-# include PERSONALITY1_INCLUDE_FUNCS
-static const struct_sysent sysent1[] = {
-# include "syscallent1.h"
-};
-#endif
-
-#if SUPPORTED_PERSONALITIES > 2
-# include PERSONALITY2_INCLUDE_FUNCS
-static const struct_sysent sysent2[] = {
-# include "syscallent2.h"
-};
-#endif
-
-/* Now undef them since short defines cause wicked namespace pollution. */
-#undef SEN
-#undef TD
-#undef TF
-#undef TI
-#undef TN
-#undef TP
-#undef TS
-#undef TM
-#undef NF
-#undef MA
-#undef SI
-#undef SE
-
-/*
- * `ioctlent[012].h' files are automatically generated by the auxiliary
- * program `ioctlsort', such that the list is sorted by the `code' field.
- * This has the side-effect of resolving the _IO.. macros into
- * plain integers, eliminating the need to include here everything
- * in "/usr/include".
- */
-
-const char *const errnoent0[] = {
-#include "errnoent.h"
-};
-const char *const signalent0[] = {
-#include "signalent.h"
-};
-const struct_ioctlent ioctlent0[] = {
-#include "ioctlent0.h"
-};
-
-#if SUPPORTED_PERSONALITIES > 1
-static const char *const errnoent1[] = {
-# include "errnoent1.h"
-};
-static const char *const signalent1[] = {
-# include "signalent1.h"
-};
-static const struct_ioctlent ioctlent1[] = {
-# include "ioctlent1.h"
-};
-# include PERSONALITY0_INCLUDE_PRINTERS_DECLS
-static const struct_printers printers0 = {
-# include PERSONALITY0_INCLUDE_PRINTERS_DEFS
-};
-# include PERSONALITY1_INCLUDE_PRINTERS_DECLS
-static const struct_printers printers1 = {
-# include PERSONALITY1_INCLUDE_PRINTERS_DEFS
-};
-#endif
-
-#if SUPPORTED_PERSONALITIES > 2
-static const char *const errnoent2[] = {
-# include "errnoent2.h"
-};
-static const char *const signalent2[] = {
-# include "signalent2.h"
-};
-static const struct_ioctlent ioctlent2[] = {
-# include "ioctlent2.h"
-};
-# include PERSONALITY2_INCLUDE_PRINTERS_DECLS
-static const struct_printers printers2 = {
-# include PERSONALITY2_INCLUDE_PRINTERS_DEFS
-};
-#endif
-
-enum {
-	nsyscalls0 = ARRAY_SIZE(sysent0)
-#if SUPPORTED_PERSONALITIES > 1
-	, nsyscalls1 = ARRAY_SIZE(sysent1)
-# if SUPPORTED_PERSONALITIES > 2
-	, nsyscalls2 = ARRAY_SIZE(sysent2)
-# endif
-#endif
-};
-
-enum {
-	nerrnos0 = ARRAY_SIZE(errnoent0)
-#if SUPPORTED_PERSONALITIES > 1
-	, nerrnos1 = ARRAY_SIZE(errnoent1)
-# if SUPPORTED_PERSONALITIES > 2
-	, nerrnos2 = ARRAY_SIZE(errnoent2)
-# endif
-#endif
-};
-
-enum {
-	nsignals0 = ARRAY_SIZE(signalent0)
-#if SUPPORTED_PERSONALITIES > 1
-	, nsignals1 = ARRAY_SIZE(signalent1)
-# if SUPPORTED_PERSONALITIES > 2
-	, nsignals2 = ARRAY_SIZE(signalent2)
-# endif
-#endif
-};
-
-enum {
-	nioctlents0 = ARRAY_SIZE(ioctlent0)
-#if SUPPORTED_PERSONALITIES > 1
-	, nioctlents1 = ARRAY_SIZE(ioctlent1)
-# if SUPPORTED_PERSONALITIES > 2
-	, nioctlents2 = ARRAY_SIZE(ioctlent2)
-# endif
-#endif
-};
-
-#if SUPPORTED_PERSONALITIES > 1
-const struct_sysent *sysent = sysent0;
-const char *const *errnoent = errnoent0;
-const char *const *signalent = signalent0;
-const struct_ioctlent *ioctlent = ioctlent0;
-const struct_printers *printers = &printers0;
-#endif
-
-unsigned nsyscalls = nsyscalls0;
-unsigned nerrnos = nerrnos0;
-unsigned nsignals = nsignals0;
-unsigned nioctlents = nioctlents0;
-
-unsigned num_quals;
-qualbits_t *qual_vec[SUPPORTED_PERSONALITIES];
-
-static const unsigned nsyscall_vec[SUPPORTED_PERSONALITIES] = {
-	nsyscalls0,
-#if SUPPORTED_PERSONALITIES > 1
-	nsyscalls1,
-#endif
-#if SUPPORTED_PERSONALITIES > 2
-	nsyscalls2,
-#endif
-};
-static const struct_sysent *const sysent_vec[SUPPORTED_PERSONALITIES] = {
-	sysent0,
-#if SUPPORTED_PERSONALITIES > 1
-	sysent1,
-#endif
-#if SUPPORTED_PERSONALITIES > 2
-	sysent2,
-#endif
-};
-
-enum {
-	MAX_NSYSCALLS1 = (nsyscalls0
-#if SUPPORTED_PERSONALITIES > 1
-			> nsyscalls1 ? nsyscalls0 : nsyscalls1
-#endif
-			),
-	MAX_NSYSCALLS2 = (MAX_NSYSCALLS1
-#if SUPPORTED_PERSONALITIES > 2
-			> nsyscalls2 ? MAX_NSYSCALLS1 : nsyscalls2
-#endif
-			),
-	MAX_NSYSCALLS = MAX_NSYSCALLS2,
-	/* We are ready for arches with up to 255 signals,
-	 * even though the largest known signo is on MIPS and it is 128.
-	 * The number of existing syscalls on all arches is
-	 * larger that 255 anyway, so it is just a pedantic matter.
-	 */
-	MIN_QUALS = MAX_NSYSCALLS > 255 ? MAX_NSYSCALLS : 255
-};
-
-#if SUPPORTED_PERSONALITIES > 1
-unsigned current_personality;
-
-# ifndef current_wordsize
-unsigned current_wordsize;
-static const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
-	PERSONALITY0_WORDSIZE,
-	PERSONALITY1_WORDSIZE,
-# if SUPPORTED_PERSONALITIES > 2
-	PERSONALITY2_WORDSIZE,
-# endif
-};
-# endif
-
-void
-set_personality(int personality)
-{
-	nsyscalls = nsyscall_vec[personality];
-	sysent = sysent_vec[personality];
-
-	switch (personality) {
-	case 0:
-		errnoent = errnoent0;
-		nerrnos = nerrnos0;
-		ioctlent = ioctlent0;
-		nioctlents = nioctlents0;
-		signalent = signalent0;
-		nsignals = nsignals0;
-		printers = &printers0;
-		break;
-
-	case 1:
-		errnoent = errnoent1;
-		nerrnos = nerrnos1;
-		ioctlent = ioctlent1;
-		nioctlents = nioctlents1;
-		signalent = signalent1;
-		nsignals = nsignals1;
-		printers = &printers1;
-		break;
-
-# if SUPPORTED_PERSONALITIES > 2
-	case 2:
-		errnoent = errnoent2;
-		nerrnos = nerrnos2;
-		ioctlent = ioctlent2;
-		nioctlents = nioctlents2;
-		signalent = signalent2;
-		nsignals = nsignals2;
-		printers = &printers2;
-		break;
-# endif
-	}
-
-	current_personality = personality;
-# ifndef current_wordsize
-	current_wordsize = personality_wordsize[personality];
-# endif
-}
-
-static void
-update_personality(struct tcb *tcp, unsigned int personality)
-{
-	if (personality == current_personality)
-		return;
-	set_personality(personality);
-
-	if (personality == tcp->currpers)
-		return;
-	tcp->currpers = personality;
-
-# undef PERSONALITY_NAMES
-# if defined POWERPC64
-#  define PERSONALITY_NAMES {"64 bit", "32 bit"}
-# elif defined X86_64
-#  define PERSONALITY_NAMES {"64 bit", "32 bit", "x32"}
-# elif defined X32
-#  define PERSONALITY_NAMES {"x32", "32 bit"}
-# elif defined AARCH64
-#  define PERSONALITY_NAMES {"64 bit", "32 bit"}
-# elif defined TILE
-#  define PERSONALITY_NAMES {"64-bit", "32-bit"}
-# endif
-# ifdef PERSONALITY_NAMES
-	if (!qflag) {
-		static const char *const names[] = PERSONALITY_NAMES;
-		error_msg("[ Process PID=%d runs in %s mode. ]",
-			  tcp->pid, names[personality]);
-	}
-# endif
-}
-#endif
-
-static int qual_syscall(), qual_signal(), qual_desc();
-
-static const struct qual_options {
-	unsigned int bitflag;
-	const char *option_name;
-	int (*qualify)(const char *, int, int);
-	const char *argument_name;
-} qual_options[] = {
-	{ QUAL_TRACE,	"trace",	qual_syscall,	"system call"	},
-	{ QUAL_TRACE,	"t",		qual_syscall,	"system call"	},
-	{ QUAL_ABBREV,	"abbrev",	qual_syscall,	"system call"	},
-	{ QUAL_ABBREV,	"a",		qual_syscall,	"system call"	},
-	{ QUAL_VERBOSE,	"verbose",	qual_syscall,	"system call"	},
-	{ QUAL_VERBOSE,	"v",		qual_syscall,	"system call"	},
-	{ QUAL_RAW,	"raw",		qual_syscall,	"system call"	},
-	{ QUAL_RAW,	"x",		qual_syscall,	"system call"	},
-	{ QUAL_SIGNAL,	"signal",	qual_signal,	"signal"	},
-	{ QUAL_SIGNAL,	"signals",	qual_signal,	"signal"	},
-	{ QUAL_SIGNAL,	"s",		qual_signal,	"signal"	},
-	{ QUAL_READ,	"read",		qual_desc,	"descriptor"	},
-	{ QUAL_READ,	"reads",	qual_desc,	"descriptor"	},
-	{ QUAL_READ,	"r",		qual_desc,	"descriptor"	},
-	{ QUAL_WRITE,	"write",	qual_desc,	"descriptor"	},
-	{ QUAL_WRITE,	"writes",	qual_desc,	"descriptor"	},
-	{ QUAL_WRITE,	"w",		qual_desc,	"descriptor"	},
-	{ 0,		NULL,		NULL,		NULL		},
-};
-
-static void
-reallocate_qual(const unsigned int n)
-{
-	unsigned p;
-	qualbits_t *qp;
-	for (p = 0; p < SUPPORTED_PERSONALITIES; p++) {
-		qp = qual_vec[p] = xreallocarray(qual_vec[p], n,
-						 sizeof(qualbits_t));
-		memset(&qp[num_quals], 0, (n - num_quals) * sizeof(qualbits_t));
-	}
-	num_quals = n;
-}
-
-static void
-qualify_one(const unsigned int n, unsigned int bitflag, const int not, const int pers)
-{
-	int p;
-
-	if (num_quals <= n)
-		reallocate_qual(n + 1);
-
-	for (p = 0; p < SUPPORTED_PERSONALITIES; p++) {
-		if (pers == p || pers < 0) {
-			if (not)
-				qual_vec[p][n] &= ~bitflag;
-			else
-				qual_vec[p][n] |= bitflag;
-		}
-	}
-}
-
-static int
-qual_syscall(const char *s, const unsigned int bitflag, const int not)
-{
-	int p;
-	unsigned int i;
-	int rc = -1;
-
-	if (*s >= '0' && *s <= '9') {
-		i = string_to_uint(s);
-		if (i >= MAX_NSYSCALLS)
-			return -1;
-		qualify_one(i, bitflag, not, -1);
-		return 0;
-	}
-
-	for (p = 0; p < SUPPORTED_PERSONALITIES; p++) {
-		for (i = 0; i < nsyscall_vec[p]; i++) {
-			if (sysent_vec[p][i].sys_name
-			 && strcmp(s, sysent_vec[p][i].sys_name) == 0
-			) {
-				qualify_one(i, bitflag, not, p);
-				rc = 0;
-			}
-		}
-	}
-
-	return rc;
-}
-
-static int
-qual_signal(const char *s, const unsigned int bitflag, const int not)
-{
-	unsigned int i;
-
-	if (*s >= '0' && *s <= '9') {
-		int signo = string_to_uint(s);
-		if (signo < 0 || signo > 255)
-			return -1;
-		qualify_one(signo, bitflag, not, -1);
-		return 0;
-	}
-	if (strncasecmp(s, "SIG", 3) == 0)
-		s += 3;
-	for (i = 0; i <= NSIG; i++) {
-		if (strcasecmp(s, signame(i) + 3) == 0) {
-			qualify_one(i, bitflag, not, -1);
-			return 0;
-		}
-	}
-	return -1;
-}
-
-static int
-qual_desc(const char *s, const unsigned int bitflag, const int not)
-{
-	if (*s >= '0' && *s <= '9') {
-		int desc = string_to_uint(s);
-		if (desc < 0 || desc > 0x7fff) /* paranoia */
-			return -1;
-		qualify_one(desc, bitflag, not, -1);
-		return 0;
-	}
-	return -1;
-}
-
-static int
-lookup_class(const char *s)
-{
-	if (strcmp(s, "file") == 0)
-		return TRACE_FILE;
-	if (strcmp(s, "ipc") == 0)
-		return TRACE_IPC;
-	if (strcmp(s, "network") == 0)
-		return TRACE_NETWORK;
-	if (strcmp(s, "process") == 0)
-		return TRACE_PROCESS;
-	if (strcmp(s, "signal") == 0)
-		return TRACE_SIGNAL;
-	if (strcmp(s, "desc") == 0)
-		return TRACE_DESC;
-	if (strcmp(s, "memory") == 0)
-		return TRACE_MEMORY;
-	return -1;
-}
-
-void
-qualify(const char *s)
-{
-	const struct qual_options *opt;
-	char *copy;
-	const char *p;
-	int not;
-	unsigned int i;
-
-	if (num_quals == 0)
-		reallocate_qual(MIN_QUALS);
-
-	opt = &qual_options[0];
-	for (i = 0; (p = qual_options[i].option_name); i++) {
-		unsigned int len = strlen(p);
-		if (strncmp(s, p, len) == 0 && s[len] == '=') {
-			opt = &qual_options[i];
-			s += len + 1;
-			break;
-		}
-	}
-	not = 0;
-	if (*s == '!') {
-		not = 1;
-		s++;
-	}
-	if (strcmp(s, "none") == 0) {
-		not = 1 - not;
-		s = "all";
-	}
-	if (strcmp(s, "all") == 0) {
-		for (i = 0; i < num_quals; i++) {
-			qualify_one(i, opt->bitflag, not, -1);
-		}
-		return;
-	}
-	for (i = 0; i < num_quals; i++) {
-		qualify_one(i, opt->bitflag, !not, -1);
-	}
-	copy = xstrdup(s);
-	for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
-		int n;
-		if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
-			unsigned pers;
-			for (pers = 0; pers < SUPPORTED_PERSONALITIES; pers++) {
-				for (i = 0; i < nsyscall_vec[pers]; i++)
-					if (sysent_vec[pers][i].sys_flags & n)
-						qualify_one(i, opt->bitflag, not, pers);
-			}
-			continue;
-		}
-		if (opt->qualify(p, opt->bitflag, not)) {
-			error_msg_and_die("invalid %s '%s'",
-				opt->argument_name, p);
-		}
-	}
-	free(copy);
-	return;
-}
-
-#ifdef SYS_socket_subcall
-static void
-decode_socket_subcall(struct tcb *tcp)
-{
-	const int call = tcp->u_arg[0];
-
-	if (call < 1 || call >= SYS_socket_nsubcalls)
-		return;
-
-	const unsigned long scno = SYS_socket_subcall + call;
-	const unsigned int nargs = sysent[scno].nargs;
-	uint64_t buf[nargs];
-
-	if (umoven(tcp, tcp->u_arg[1], nargs * current_wordsize, buf) < 0)
-		return;
-
-	tcp->scno = scno;
-	tcp->qual_flg = qual_flags[scno];
-	tcp->s_ent = &sysent[scno];
-
-	unsigned int i;
-	for (i = 0; i < nargs; ++i)
-		tcp->u_arg[i] = (sizeof(uint32_t) == current_wordsize)
-				? ((uint32_t *) (void *) buf)[i] : buf[i];
-}
-#endif
-
-#ifdef SYS_ipc_subcall
-static void
-decode_ipc_subcall(struct tcb *tcp)
-{
-	unsigned int call = tcp->u_arg[0];
-	const unsigned int version = call >> 16;
-
-	if (version) {
-# if defined S390 || defined S390X
-		return;
-# else
-#  ifdef SPARC64
-		if (current_wordsize == 8)
-			return;
-#  endif
-		set_tcb_priv_ulong(tcp, version);
-		call &= 0xffff;
-# endif
-	}
-
-	switch (call) {
-		case  1: case  2: case  3: case  4:
-		case 11: case 12: case 13: case 14:
-		case 21: case 22: case 23: case 24:
-			break;
-		default:
-			return;
-	}
-
-	tcp->scno = SYS_ipc_subcall + call;
-	tcp->qual_flg = qual_flags[tcp->scno];
-	tcp->s_ent = &sysent[tcp->scno];
-
-	const unsigned int n = tcp->s_ent->nargs;
-	unsigned int i;
-	for (i = 0; i < n; i++)
-		tcp->u_arg[i] = tcp->u_arg[i + 1];
-}
-#endif
 
 #ifdef LINUX_MIPSO32
 static void
@@ -637,7 +75,7 @@ decode_mips_subcall(struct tcb *tcp)
 	if (!SCNO_IS_VALID(tcp->u_arg[0]))
 		return;
 	tcp->scno = tcp->u_arg[0];
-	tcp->qual_flg = qual_flags[tcp->scno];
+	tcp->qual_flg = qual_flags(tcp->scno);
 	tcp->s_ent = &sysent[tcp->scno];
 	memmove(&tcp->u_arg[0], &tcp->u_arg[1],
 		sizeof(tcp->u_arg) - sizeof(tcp->u_arg[0]));
@@ -661,7 +99,7 @@ dumpio(struct tcb *tcp)
 	sen = tcp->s_ent->sen;
 	if (SEN_printargs == sen)
 		return;
-	if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
+	if (qual_flags(tcp->u_arg[0]) & QUAL_READ) {
 		switch (sen) {
 		case SEN_read:
 		case SEN_pread:
@@ -683,7 +121,7 @@ dumpio(struct tcb *tcp)
 			return;
 		}
 	}
-	if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
+	if (qual_flags(tcp->u_arg[0]) & QUAL_WRITE) {
 		switch (sen) {
 		case SEN_write:
 		case SEN_pwrite:
@@ -811,20 +249,14 @@ trace_syscall_entering(struct tcb *tcp)
 		hide_log_until_execve = 0;
 	}
 
-#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
 	switch (tcp->s_ent->sen) {
-# ifdef SYS_socket_subcall
 		case SEN_socketcall:
 			decode_socket_subcall(tcp);
 			break;
-# endif
-# ifdef SYS_ipc_subcall
 		case SEN_ipc:
 			decode_ipc_subcall(tcp);
 			break;
-# endif
 	}
-#endif
 
 	if (!(tcp->qual_flg & QUAL_TRACE)
 	 || (tracing_paths && !pathtrace_match(tcp))
@@ -1297,7 +729,7 @@ get_scno(struct tcb *tcp)
 
 	if (SCNO_IS_VALID(tcp->scno)) {
 		tcp->s_ent = &sysent[tcp->scno];
-		tcp->qual_flg = qual_flags[tcp->scno];
+		tcp->qual_flg = qual_flags(tcp->scno);
 	} else {
 		static const struct_sysent unknown = {
 			.nargs = MAX_ARGS,
-- 
1.7.10.4





More information about the Strace-devel mailing list