]> granicus.if.org Git - strace/commitdiff
Introduce xlat verbosity styles
authorEugene Syromyatnikov <evgsyr@gmail.com>
Sat, 10 Mar 2018 03:48:33 +0000 (04:48 +0100)
committerEugene Syromyatnikov <evgsyr@gmail.com>
Thu, 12 Apr 2018 22:25:13 +0000 (00:25 +0200)
* defs.h (printxvals_ex): Rename from printxvals, add style argument.
(enum xlat_style): New enumeration.
(printxvals): New macro, a wrapper for printxvals_ex.
(printxval_searchn_ex): Rename from printxval_searchn, add style
argument.
(printxval_searchn): New macro, a wrapper for printxval_searchn_ex.
(printxval_search_ex): New macro, a wrapper for printxval_searchn_ex.
(sprintxval_ex): Rename from sprintxval, add style argument.
(sprintxval): New macro, a wrapper for sprintxval_ex.
(printflags_ex): Add style argument.
(sprintflags_ex): Rename from sprintflags, add style argument.
(sprintflags): New macro, a wrapper for sprintflags_ex.
(printflags64): Pass XLAT_STYLE_ABBREV as a style in printflags_ex call.
* netlink.c (decode_nlmsg_flags): Pass XLAT_STYLE_ABBREV as a style in
printflags_ex call.
* xlat.c (printxvals_ex): Rename from printxvals, add style argument,
handle it.
(sprintxval_ex): Rename from sprintxval, add style argument, handle it.
(printxval_searchn_ex): Rename from printxval_searchn, add style
argument, handle it.
(sprintflags_ex): Rename from sprintflags, add style argument,
handle it.
(printflags_ex): Add style argument, handle it.

Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
References: https://github.com/strace/strace/issues/27

defs.h
netlink.c
xlat.c

diff --git a/defs.h b/defs.h
index 12c76f38e2bc1cb255f9855e4c96e83b08983f1c..569825ffd3f404a87c2f9ccc1c25a48bf7968ad9 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -583,10 +583,31 @@ extern int printllval(struct tcb *, const char *, int)
 
 extern void printaddr64(uint64_t addr);
 extern void printaddr(kernel_ulong_t addr);
-extern int printxvals(const uint64_t, const char *, const struct xlat *, ...)
+
+enum xlat_style {
+       /** Print xlat value as is without xlat processing */
+       XLAT_STYLE_RAW     = 1 << 0,
+       /**
+        * Historic strace style, process xlat and print the result (xlat
+        * constant name/combination of flags), raw number only if nothing is
+        * found.
+        */
+       XLAT_STYLE_ABBREV  = 1 << 1,
+       /** Always print both raw number and xlat processing result. */
+       XLAT_STYLE_VERBOSE = XLAT_STYLE_RAW | XLAT_STYLE_ABBREV,
+};
+
+extern int printxvals_ex(uint64_t val, const char *dflt,
+                        enum xlat_style style, const struct xlat *, ...)
        ATTRIBUTE_SENTINEL;
-extern int printxval_searchn(const struct xlat *xlat, size_t xlat_size,
-       uint64_t val, const char *dflt);
+#define printxvals(val_, dflt_, ...) \
+       printxvals_ex((val_), (dflt_), XLAT_STYLE_ABBREV, __VA_ARGS__)
+extern int printxval_searchn_ex(const struct xlat *xlat, size_t xlat_size,
+                               uint64_t val, const char *dflt,
+                               enum xlat_style style);
+#define printxval_searchn(xlat_, xlat_size_, val_, dflt_) \
+       printxval_searchn_ex((xlat_), (xlat_size_), (val_), (dflt_), \
+                            XLAT_STYLE_ABBREV)
 /**
  * Wrapper around printxval_searchn that passes ARRAY_SIZE - 1
  * as the array size, as all arrays are XLAT_END-terminated and
@@ -594,15 +615,27 @@ extern int printxval_searchn(const struct xlat *xlat, size_t xlat_size,
  */
 #define printxval_search(xlat__, val__, dflt__) \
        printxval_searchn(xlat__, ARRAY_SIZE(xlat__) - 1, val__, dflt__)
-extern int sprintxval(char *buf, size_t size, const struct xlat *,
-       unsigned int val, const char *dflt);
+#define printxval_search_ex(xlat__, val__, dflt__) \
+       printxval_searchn_ex((xlat__), ARRAY_SIZE(xlat__) - 1, (val__), \
+                            (dflt__), XLAT_STYLE_ABBREV)
+extern int sprintxval_ex(char *buf, size_t size, const struct xlat *xlat,
+                        unsigned int val, const char *dflt,
+                        enum xlat_style style);
+#define sprintxval(buf_, size_, xlat_, val_, dflt_) \
+       sprintxval_ex((buf_), (size_), (xlat_), (val_), (dflt_), \
+                     XLAT_STYLE_ABBREV)
+
 extern int printargs(struct tcb *);
 extern int printargs_u(struct tcb *);
 extern int printargs_d(struct tcb *);
 
-extern int printflags_ex(uint64_t, const char *, const struct xlat *, ...)
+extern int printflags_ex(uint64_t flags, const char *dflt,
+                        enum xlat_style style, const struct xlat *, ...)
        ATTRIBUTE_SENTINEL;
-extern const char *sprintflags(const char *, const struct xlat *, uint64_t);
+extern const char *sprintflags_ex(const char *prefix, const struct xlat *xlat,
+                                 uint64_t flags, enum xlat_style style);
+#define sprintflags(prefix_, xlat_, flags_) \
+       sprintflags_ex((prefix_), (xlat_), (flags_), XLAT_STYLE_ABBREV)
 extern const char *sprinttime(long long sec);
 extern const char *sprinttime_nsec(long long sec, unsigned long long nsec);
 extern const char *sprinttime_usec(long long sec, unsigned long long usec);
@@ -779,7 +812,7 @@ printstr(struct tcb *tcp, kernel_ulong_t addr)
 static inline int
 printflags64(const struct xlat *x, uint64_t flags, const char *dflt)
 {
-       return printflags_ex(flags, dflt, x, NULL);
+       return printflags_ex(flags, dflt, XLAT_STYLE_ABBREV, x, NULL);
 }
 
 static inline int
index c9abb4c8eb1da7af2f7a4459387c27b7b7197648..46a394c67f436b943a3cfbff0e9ec142c5724c5c 100644 (file)
--- a/netlink.c
+++ b/netlink.c
@@ -430,7 +430,8 @@ decode_nlmsg_flags(const uint16_t flags, const uint16_t type,
        } else if (family < ARRAY_SIZE(nlmsg_flags) && nlmsg_flags[family])
                table = nlmsg_flags[family](type);
 
-       printflags_ex(flags, "NLM_F_???", netlink_flags, table, NULL);
+       printflags_ex(flags, "NLM_F_???", XLAT_STYLE_ABBREV,
+                     netlink_flags, table, NULL);
 }
 
 static void
diff --git a/xlat.c b/xlat.c
index be58f72eca1fcbb2e959b9496c6cdf70d8abc37c..647786b6a48a4872c211c1e6a5733753e68e7f1d 100644 (file)
--- a/xlat.c
+++ b/xlat.c
@@ -63,16 +63,23 @@ xlat_search(const struct xlat *xlat, const size_t nmemb, const uint64_t val)
 /**
  * Print entry in struct xlat table, if there.
  *
- * @param val  Value to search a literal representation for.
- * @param dflt String (abbreviated in comment syntax) which should be emitted
- *             if no appropriate xlat value has been found.
- * @param xlat (And the following arguments) Pointers to arrays of xlat values.
- *             The last argument should be NULL.
- * @return     1 if appropriate xlat value has been found, 0 otherwise.
+ * @param val   Value to search a literal representation for.
+ * @param dflt  String (abbreviated in comment syntax) which should be emitted
+ *              if no appropriate xlat value has been found.
+ * @param style Style in which xlat value should be printed.
+ * @param xlat  (And the following arguments) Pointers to arrays of xlat values.
+ *              The last argument should be NULL.
+ * @return      1 if appropriate xlat value has been found, 0 otherwise.
  */
 int
-printxvals(const uint64_t val, const char *dflt, const struct xlat *xlat, ...)
+printxvals_ex(const uint64_t val, const char *dflt, enum xlat_style style,
+             const struct xlat *xlat, ...)
 {
+       if (style == XLAT_STYLE_RAW) {
+               tprintf("%#" PRIx64, val);
+               return 0;
+       }
+
        va_list args;
 
        va_start(args, xlat);
@@ -80,7 +87,13 @@ printxvals(const uint64_t val, const char *dflt, const struct xlat *xlat, ...)
                const char *str = xlookup(xlat, val);
 
                if (str) {
-                       tprints(str);
+                       if (style == XLAT_STYLE_VERBOSE) {
+                               tprintf("%#" PRIx64, val);
+                               tprints_comment(str);
+                       } else {
+                               tprints(str);
+                       }
+
                        va_end(args);
                        return 1;
                }
@@ -95,13 +108,21 @@ printxvals(const uint64_t val, const char *dflt, const struct xlat *xlat, ...)
 }
 
 int
-sprintxval(char *const buf, const size_t size, const struct xlat *const x,
-          const unsigned int val, const char *const dflt)
+sprintxval_ex(char *const buf, const size_t size, const struct xlat *const x,
+             const unsigned int val, const char *const dflt,
+             enum xlat_style style)
 {
+       if (style == XLAT_STYLE_RAW)
+               return xsnprintf(buf, size, "%#x", val);
+
        const char *const str = xlookup(x, val);
 
-       if (str)
-               return xsnprintf(buf, size, "%s", str);
+       if (str) {
+               if (style == XLAT_STYLE_VERBOSE)
+                       return xsnprintf(buf, size, "%#x /* %s */", val, str);
+               else
+                       return xsnprintf(buf, size, "%s", str);
+       }
        if (dflt)
                return xsnprintf(buf, size, "%#x /* %s */", val, dflt);
 
@@ -119,17 +140,28 @@ sprintxval(char *const buf, const size_t size, const struct xlat *const x,
  * @param val       Value to search literal representation for.
  * @param dflt      String (abbreviated in comment syntax) which should be
  *                  emitted if no appropriate xlat value has been found.
+ * @param style     Style in which xlat value should be printed.
  * @return          1 if appropriate xlat value has been found, 0
  *                  otherwise.
  */
 int
-printxval_searchn(const struct xlat *xlat, size_t xlat_size, uint64_t val,
-       const char *dflt)
+printxval_searchn_ex(const struct xlat *xlat, size_t xlat_size, uint64_t val,
+                    const char *dflt, enum xlat_style style)
 {
+       if (style == XLAT_STYLE_RAW) {
+               tprintf("%#" PRIx64, val);
+               return 0;
+       }
+
        const char *s = xlat_search(xlat, xlat_size, val);
 
        if (s) {
-               tprints(s);
+               if (style == XLAT_STYLE_VERBOSE) {
+                       tprintf("%#" PRIx64, val);
+                       tprints_comment(s);
+               } else {
+                       tprints(s);
+               }
                return 1;
        }
 
@@ -144,9 +176,26 @@ printxval_searchn(const struct xlat *xlat, size_t xlat_size, uint64_t val,
  * Print to static string the entries whose bits are on in `flags'
  * Return static string.  If 0 is provided as flags, and there is no flag that
  * has the value of 0 (it should be the first in xlat table), return NULL.
+ *
+ * Expected output:
+ * +------------+------------+---------+------------+
+ * | flags != 0 | xlat found | style   | output     |
+ * +------------+------------+---------+------------+
+ * | false      | (any)      | raw     | <none>     |
+ * | true       | (any)      | raw     | VAL        |
+ * +------------+------------+---------+------------+
+ * | false      | false      | abbrev  | <none>     |
+ * | true       | false      | abbrev  | VAL        |
+ * | (any)      | true       | abbrev  | XLAT       |
+ * +------------+------------+---------+------------+
+ * | false      | false      | verbose | <none>     |
+ * | true       | false      | verbose | VAL        |
+ * | (any)      | true       | verbose | VAL (XLAT) |
+ * +------------+------------+---------+------------+
  */
 const char *
-sprintflags(const char *prefix, const struct xlat *xlat, uint64_t flags)
+sprintflags_ex(const char *prefix, const struct xlat *xlat, uint64_t flags,
+              enum xlat_style style)
 {
        static char outstr[1024];
        char *outptr;
@@ -154,47 +203,114 @@ sprintflags(const char *prefix, const struct xlat *xlat, uint64_t flags)
 
        outptr = stpcpy(outstr, prefix);
 
+       if (style == XLAT_STYLE_RAW) {
+               if (!flags)
+                       return NULL;
+
+               outptr = xappendstr(outstr, outptr, "%#" PRIx64, flags);
+
+               return outstr;
+       }
+
        if (flags == 0 && xlat->val == 0 && xlat->str) {
-               strcpy(outptr, xlat->str);
+               if (style == XLAT_STYLE_VERBOSE) {
+                       outptr = xappendstr(outstr, outptr, "0 /* %s */",
+                                           xlat->str);
+               } else {
+                       strcpy(outptr, xlat->str);
+               }
+
                return outstr;
        }
 
-       for (; xlat->str; xlat++) {
+       if (style == XLAT_STYLE_VERBOSE && flags)
+               outptr = xappendstr(outstr, outptr, "%#" PRIx64, flags);
+
+       for (; flags && xlat->str; xlat++) {
                if (xlat->val && (flags & xlat->val) == xlat->val) {
                        if (found)
                                *outptr++ = '|';
+                       else if (style == XLAT_STYLE_VERBOSE)
+                               outptr = stpcpy(outptr, " /* ");
+
                        outptr = stpcpy(outptr, xlat->str);
                        found = 1;
                        flags &= ~xlat->val;
-                       if (!flags)
-                               break;
                }
        }
 
        if (flags) {
                if (found)
                        *outptr++ = '|';
-               outptr = xappendstr(outstr, outptr, "%#" PRIx64, flags);
+               if (found || style != XLAT_STYLE_VERBOSE)
+                       outptr = xappendstr(outstr, outptr, "%#" PRIx64, flags);
        } else {
                if (!found)
                        return NULL;
        }
 
+       if (found && style == XLAT_STYLE_VERBOSE)
+               outptr = stpcpy(outptr, " */");
+
        return outstr;
 }
 
+/**
+ * Print flags from multiple xlat tables.
+ *
+ * Expected output:
+ * +------------+--------------+------------+---------+------------+
+ * | flags != 0 | dflt != NULL | xlat found | style   | output     |
+ * +------------+--------------+------------+---------+------------+
+ * | false      | false        | (any)      | raw     | <none>     |
+ * | false      | true         | (any)      | raw     | VAL        |
+ * | true       | (any)        | (any)      | raw     | VAL        |
+ * +------------+--------------+------------+---------+------------+
+ * | false      | false        | false      | abbrev  | <none>     |
+ * | false      | true         | false      | abbrev  | VAL        |
+ * | true       | false        | false      | abbrev  | VAL        |
+ * | true       | true         | false      | abbrev  | VAL (DFLT) |
+ * | (any)      | (any)        | true       | abbrev  | XLAT       |
+ * +------------+--------------+------------+---------+------------+
+ * | false      | false        | false      | verbose | <none>     |
+ * | false      | true         | false      | verbose | VAL        |
+ * | true       | false        | false      | verbose | VAL        |
+ * | true       | true         | false      | verbose | VAL (DFLT) |
+ * | (any)      | (any)        | true       | verbose | VAL (XLAT) |
+ * +------------+--------------+------------+---------+------------+
+ */
 int
-printflags_ex(uint64_t flags, const char *dflt, const struct xlat *xlat, ...)
+printflags_ex(uint64_t flags, const char *dflt, enum xlat_style style,
+             const struct xlat *xlat, ...)
 {
+       if (style == XLAT_STYLE_RAW) {
+               if (flags || dflt) {
+                       tprintf("%#" PRIx64, flags);
+                       return 1;
+               }
+
+               return 0;
+       }
+
+       const char *init_sep = "";
        unsigned int n = 0;
        va_list args;
 
+       if (style == XLAT_STYLE_VERBOSE) {
+               init_sep = " /* ";
+               if (flags)
+                       tprintf("%#" PRIx64, flags);
+       }
+
        va_start(args, xlat);
        for (; xlat; xlat = va_arg(args, const struct xlat *)) {
                for (; (flags || !n) && xlat->str; ++xlat) {
                        if ((flags == xlat->val) ||
                            (xlat->val && (flags & xlat->val) == xlat->val)) {
-                               tprintf("%s%s", (n++ ? "|" : ""), xlat->str);
+                               if (style == XLAT_STYLE_VERBOSE && !flags)
+                                       tprints("0");
+                               tprintf("%s%s",
+                                       (n++ ? "|" : init_sep), xlat->str);
                                flags &= ~xlat->val;
                        }
                        if (!flags)
@@ -208,9 +324,13 @@ printflags_ex(uint64_t flags, const char *dflt, const struct xlat *xlat, ...)
                        tprintf("|%#" PRIx64, flags);
                        n++;
                }
+
+               if (style == XLAT_STYLE_VERBOSE)
+                       tprints(" */");
        } else {
                if (flags) {
-                       tprintf("%#" PRIx64, flags);
+                       if (style != XLAT_STYLE_VERBOSE)
+                               tprintf("%#" PRIx64, flags);
                        tprints_comment(dflt);
                } else {
                        if (dflt)