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


------------------------------------------------------------------------------
_______________________________________________
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to