From: Eugene Syromyatnikov Date: Sun, 11 Feb 2018 04:04:05 +0000 (+0100) Subject: Add support for personality designation in syscall qualifications X-Git-Tag: v4.23~14 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3fedf07869e605841a70b4387f0b5ba44c073cf1;p=strace Add support for personality designation in syscall qualifications * syscall.c (personality_designators): New array. * defs.h (personality_designators): New declaration. * basic_filters.c (qualify_syscall_separate_personality, qualify_syscall_number_personality): New functions. (qualify_syscall_number): Use qualify_syscall_separate_personality for checking for a personality specification, call qualify_syscall_number_personality for setting number set for specific personality. (qualify_syscall_name_personality): New function. (qualify_syscall_name): Use qualify_syscall_separate_personality for checking for a personality specification, call qualify_syscall_name_personality for setting number set for specific personality. * strace.1.in (.SS Filtering): Document it. * NEWS: Mention it. Co-Authored-by: Dmitry V. Levin Closes: https://github.com/strace/strace/issues/35 --- diff --git a/NEWS b/NEWS index 9510e51b..26c7b144 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,8 @@ Noteworthy changes in release ?.?? (????-??-??) using --enable-stacktrace option. * Added -X option for configuring xlat output formatting (addresses Debian bug #692915). + * Added support for personality designation ("64", "32", or "x32") to syscall + qualifications in -e trace expressions. * Implemented injection of syscalls with no side effects as an alternative to injection of an invalid syscall (-e inject=SET:syscall= expression). * Improved support for reproducible builds (addresses Debian bug #896016). diff --git a/basic_filters.c b/basic_filters.c index 4ea23b54..12c67c03 100644 --- a/basic_filters.c +++ b/basic_filters.c @@ -27,25 +27,82 @@ */ #include "defs.h" -#include "number_set.h" -#include "filter.h" + #include +#include "filter.h" +#include "number_set.h" +#include "xstring.h" + + +/** + * Checks whether a @-separated personality specification suffix is present. + * Personality suffix is a one of strings stored in personality_designators + * array. + * + * @param[in] s Specification string to check. + * @param[out] p Where to store personality number if it is found. + * @return If personality is found, the provided string is copied without + * suffix and returned as a result (callee should de-alllocate it + * with free() after use), and personality number is written to p. + * Otherwise, NULL is returned and p is untouched. + */ +static char * +qualify_syscall_separate_personality(const char *s, unsigned int *p) +{ + char *pos = strchr(s, '@'); + + if (!pos) + return NULL; + + for (unsigned int i = 0; i < SUPPORTED_PERSONALITIES; i++) { + if (!strcmp(pos + 1, personality_designators[i])) { + *p = i; + return xstrndup(s, pos - s); + } + } + + error_msg_and_help("incorrect personality designator '%s'" + " in qualification '%s'", pos + 1, s); +} + +static bool +qualify_syscall_number_personality(int n, unsigned int p, + struct number_set *set) +{ + if ((unsigned int) n >= nsyscall_vec[p]) + return false; + + add_number_to_set_array(n, set, p); + + return true; +} + static bool qualify_syscall_number(const char *s, struct number_set *set) { - int n = string_to_uint(s); + unsigned int p; + char *num_str = qualify_syscall_separate_personality(s, &p); + int n; + + if (num_str) { + n = string_to_uint(num_str); + free(num_str); + + if (n < 0) + return false; + + return qualify_syscall_number_personality(n, p, set); + } + + n = string_to_uint(s); if (n < 0) return false; bool done = false; - for (unsigned int p = 0; p < SUPPORTED_PERSONALITIES; ++p) { - if ((unsigned) n >= nsyscall_vec[p]) - continue; - add_number_to_set_array(n, set, p); - done = true; - } + for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) + done |= qualify_syscall_number_personality(n, p, set); return done; } @@ -163,20 +220,38 @@ scno_by_name(const char *s, unsigned int p, kernel_long_t start) return -1; } +static bool +qualify_syscall_name_personality(const char *s, unsigned int p, + struct number_set *set) +{ + bool found = false; + + for (kernel_long_t scno = 0; (scno = scno_by_name(s, p, scno)) >= 0; + ++scno) { + add_number_to_set_array(scno, set, p); + found = true; + } + + return found; +} + static bool qualify_syscall_name(const char *s, struct number_set *set) { + unsigned int p; + char *name_str = qualify_syscall_separate_personality(s, &p); bool found = false; - for (unsigned int p = 0; p < SUPPORTED_PERSONALITIES; ++p) { - for (kernel_long_t scno = 0; - (scno = scno_by_name(s, p, scno)) >= 0; - ++scno) { - add_number_to_set_array(scno, set, p); - found = true; - } + if (name_str) { + found = qualify_syscall_name_personality(name_str, p, set); + free(name_str); + + return found; } + for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) + found |= qualify_syscall_name_personality(s, p, set); + return found; } diff --git a/defs.h b/defs.h index 7980529b..4437d6fb 100644 --- a/defs.h +++ b/defs.h @@ -1370,6 +1370,8 @@ extern const struct_sysent sysent0[]; extern const struct_ioctlent ioctlent0[]; extern const char *const personality_names[]; +/* Personality designators to be used for specifying personality */ +extern const char *const personality_designators[]; #if SUPPORTED_PERSONALITIES > 1 extern const struct_sysent *sysent; diff --git a/strace.1.in b/strace.1.in index 558c8634..d5b83c5a 100644 --- a/strace.1.in +++ b/strace.1.in @@ -446,6 +446,9 @@ means to trace every system call except .BR open . Question mark before the syscall qualification allows suppression of error in case no syscalls matched the qualification provided. +Appending one of "@64", "@32", or "@x32" suffixes to the syscall qualification +allows specifying syscalls only for the 64-bit, 32-bit, or 32-on-64-bit +personality, respectively. In addition, the special values .B all and diff --git a/syscall.c b/syscall.c index 82eed5eb..fe85b8bf 100644 --- a/syscall.c +++ b/syscall.c @@ -191,6 +191,18 @@ const char *const personality_names[] = # endif ; +const char *const personality_designators[] = +# if defined X86_64 + { "64", "32", "x32" } +# elif defined X32 + { "x32", "32" } +# elif SUPPORTED_PERSONALITIES == 2 + { "64", "32" } +# else + { STRINGIFY_VAL(__WORDSIZE) } +# endif + ; + #if SUPPORTED_PERSONALITIES > 1 unsigned current_personality;