]> granicus.if.org Git - strace/commitdiff
Add support for personality designation in syscall qualifications
authorEugene Syromyatnikov <evgsyr@gmail.com>
Sun, 11 Feb 2018 04:04:05 +0000 (05:04 +0100)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 13 Jun 2018 15:05:09 +0000 (15:05 +0000)
* 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 <ldv@altlinux.org>
Closes: https://github.com/strace/strace/issues/35
NEWS
basic_filters.c
defs.h
strace.1.in
syscall.c

diff --git a/NEWS b/NEWS
index 9510e51b75ce9f7943ae339cc22c268493d59cae..26c7b144bf85ca149e9eb46517c575417036da02 100644 (file)
--- 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).
index 4ea23b54044227dcfaa2cb8dd0814fd42459cf7c..12c67c0320b59d130a5cb656875b1ca01d499d58 100644 (file)
  */
 
 #include "defs.h"
-#include "number_set.h"
-#include "filter.h"
+
 #include <regex.h>
 
+#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 7980529ba3c0618f067f9bdbc7f3dd6024bcfd41..4437d6fbc0ff6ad71f541367d3c809d181c4e6c7 100644 (file)
--- 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;
index 558c863492aa59f045ae73b7ddf0f4d3f4da9904..d5b83c5a2b64424ad625ea00f15e58f1b9af5d3f 100644 (file)
@@ -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
index 82eed5eb70b6a19e81a0d4c84706a87597100c81..fe85b8bfa5104e01b3611f5b44a3c0a4b588a303 100644 (file)
--- 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;