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