[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