strace's Named Constant Support (xlat) Documentation

strace has extensive support for decoding various named constants that appear in various places of Linux API surface, that is handled by similarly extensive API and infrastructure. This document is an attempt to capture the current state of it and provide information related to its usage.

File Format

xlat file is a file in a text-like format with .in extension, placed in the xlat directory. It is the basis of a C header file generation

It is interpreted line-by-line (by xlat/gen.sh script). Each line can be one of the following:

xlat/gen.sh processes the xlat file in two passes:

  1. To generate constant check/definition rules.
  2. To generate xlat struct definition.

The following rules are applied during processing:

Notes regarding #sorted and #value_indexed annotations:

API

The xlat-related API is split between two files:

xlat arrays can be interpreted in one of two ways:

Types

The main type is struct xlat. It is defined as follows:

   1 enum xlat_type {
   2         XT_NORMAL,
   3         XT_SORTED,
   4         XT_INDEXED,
   5 };
   6 
   7 struct xlat_data {
   8         uint64_t val;
   9         const char *str;
  10 };
  11 
  12 struct xlat {
  13         const struct xlat_data *data;
  14         size_t flags_strsz;
  15         uint32_t size;
  16         enum xlat_type type;
  17         uint64_t flags_mask;
  18 };

xlat Styles

/* xlat.h */
enum xlat_style {
        /**
         * Special value that is used for passing to *print{xval,flags}*_ex
         * routines that indicates that no overriding of user-supplied xlat
         * verbosity/formatting configuration is intended.
         */
        XLAT_STYLE_DEFAULT = 0,

        /** 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,

# define XLAT_STYLE_FORMAT_SHIFT   2
# define XLAT_STYLE_VERBOSITY_MASK ((1 << XLAT_STYLE_FORMAT_SHIFT) - 1)

        XLAT_STYLE_FMT_X   = 0 << XLAT_STYLE_FORMAT_SHIFT,
        XLAT_STYLE_FMT_U   = 1 << XLAT_STYLE_FORMAT_SHIFT,
        XLAT_STYLE_FMT_D   = 2 << XLAT_STYLE_FORMAT_SHIFT,

# define XLAT_STYLE_FORMAT_MASK    (3 << XLAT_STYLE_FORMAT_SHIFT)

# define XLAT_STYLE_SPEC_BITS (XLAT_STYLE_FORMAT_SHIFT + 2)
# define XLAT_STYLE_MASK ((1 << XLAT_STYLE_SPEC_BITS) - 1)
};


/* defs.h */
# define xlat_verbose(style_) ((style_) & XLAT_STYLE_VERBOSITY_MASK)
# define xlat_format(style_)  ((style_) & XLAT_STYLE_FORMAT_MASK)

extern enum xlat_style xlat_verbosity;

enum xlat_style_private_flags {
        /* print_array */
        FLAG(PAF_PRINT_INDICES),
        FLAG(PAF_ARRAY_TRUNCATED),

        /* print_xlat */
        FLAG(PXF_DEFAULT_STR),
};

Functions and Macros

/**
 * Print a value in accordance with xlat formatting settings.
 *
 * @param val   Value itself.
 * @param str   String representation of the value.  Semantics may be affected
 *              by style argument;
 * @param style Combination of flags from enum xlat_style and PXF_* flags
 *              from enum xlat_style_private_flags:
 *               - PXF_DEFAULT_STR - interpret str argument as default
 *                 (fallback) string and not as string representation of val.
 */
extern void print_xlat_ex(uint64_t val, const char *str, uint32_t style);
# define print_xlat(val_) \
        print_xlat_ex((val_), #val_, XLAT_STYLE_DEFAULT)
# define print_xlat32(val_) \
        print_xlat_ex((uint32_t) (val_), #val_, XLAT_STYLE_DEFAULT)
# define print_xlat_u(val_) \
        print_xlat_ex((val_), #val_, XLAT_STYLE_FMT_U)
# define print_xlat_d(val_) \
        print_xlat_ex((val_), #val_, XLAT_STYLE_FMT_D)

extern int printflags_ex(uint64_t flags, const char *dflt,
                         enum xlat_style, const struct xlat *, ...)
        ATTRIBUTE_SENTINEL;
extern const char *sprintflags_ex(const char *prefix, const struct xlat *,
                                  uint64_t flags, char sep, enum xlat_style);

static inline const char *
sprintflags(const char *prefix, const struct xlat *xlat, uint64_t flags)
{
        return sprintflags_ex(prefix, xlat, flags, '\0', XLAT_STYLE_DEFAULT);
}

static inline int
printflags64(const struct xlat *x, uint64_t flags, const char *dflt)
{
        return printflags_ex(flags, dflt, XLAT_STYLE_DEFAULT, x, NULL);
}

static inline int
printflags(const struct xlat *x, unsigned int flags, const char *dflt)
{
        return printflags64(x, flags, dflt);
}

static inline int
printxval64(const struct xlat *x, const uint64_t val, const char *dflt)
{
        return printxvals(val, dflt, x, NULL);
}

static inline int
printxval(const struct xlat *x, const unsigned int val, const char *dflt)
{
        return printxvals(val, dflt, x, NULL);
}

static inline int
printxval64_u(const struct xlat *x, const uint64_t val, const char *dflt)
{
        return printxvals_ex(val, dflt, XLAT_STYLE_FMT_U, x, NULL);
}

static inline int
printxval_u(const struct xlat *x, const unsigned int val, const char *dflt)
{
        return printxvals_ex(val, dflt, XLAT_STYLE_FMT_U, x, NULL);
}

static inline int
printxval64_d(const struct xlat *x, const int64_t val, const char *dflt)
{
        return printxvals_ex(val, dflt, XLAT_STYLE_FMT_D, x, NULL);
}

static inline int
printxval_d(const struct xlat *x, const int val, const char *dflt)
{
        return printxvals_ex(val, dflt, XLAT_STYLE_FMT_D, x, NULL);
}

Complicated cases

dyxlat

struct dyxlat;
struct dyxlat *dyxlat_alloc(size_t nmemb);
void dyxlat_free(struct dyxlat *);
const struct xlat *dyxlat_get(const struct dyxlat *);
void dyxlat_add_pair(struct dyxlat *, uint64_t val, const char *str, size_t len);

/**
 * Array printing function with over-engineered interface.
 *
 * @param start_addr       If tfetch_mem_fn is non-NULL: address in tracee's
 *                         memory where the start of the array is located.
 *                         If tfetch_mem_fn is NULL: ignored.
 * @param nmemb            Number of elements in array.
 * @param elem_buf         If tfetch_mem_fn is non-NULL: a buffer where each
 *                         element fetched by tfetch_mem_fn is stored.
 *                         If tfetch_mem_fn is NULL: address of the start of
 *                         the array in local memory.
 * @param elem_size        Size (in bytes) of each element in the array.
 * @param tfetch_mem_fn    Fetching function. If NULL, then elem_buf is treated
 *                         as local array of nmemb members elem_size each;
 *                         start_addr is ignored.
 * @param print_func       Element printing callback.
 * @param opaque_data      A value that is unconditionally passed to print_func
 *                         in opaque_data argument.
 * @param flags            Combination of xlat style settings and additional
 *                         flags from enum print_array_flags.
 * @param index_xlat       Xlat array that is used for printing indices.
 * @param index_xlat_size  The size of xlat array.
 * @param index_dflt       Default string for the values not found
 *                         in index_xlat.
 */
extern bool
print_array_ex(struct tcb *,
               kernel_ulong_t start_addr,
               size_t nmemb,
               void *elem_buf,
               size_t elem_size,
               tfetch_mem_fn tfetch_mem_func,
               print_fn print_func,
               void *opaque_data,
               unsigned int flags,
               const struct xlat *index_xlat,
               const char *index_dflt);

/** Shorthand for printing local arrays. */
static inline bool
print_local_array_ex(struct tcb *tcp,
                     void *start_addr,
                     const size_t nmemb,
                     const size_t elem_size,
                     print_fn print_func,
                     void *const opaque_data,
                     unsigned int flags,
                     const struct xlat *index_xlat,
                     const char *index_dflt)
{
        return print_array_ex(tcp, (uintptr_t) start_addr, nmemb,
                              NULL, elem_size, NULL, print_func,
                              opaque_data, flags, index_xlat, index_dflt);
}

enum find_xlat_flag_bits {
        FXL_CASE_SENSITIVE_BIT,
};

enum find_xlat_flags {
        /** Whether to use strcmp instead of strcasecmp for comparison */
        FLAG(FXL_CASE_SENSITIVE),
};

/**
 * Searches for a string-value pair in the provided array of pairs.
 *
 * @param items     Array of string-value pairs to search in.
 * @param s         String to search for.
 * @param num_items Item count in items array.
 * @param flags     Bitwise-or'ed flags from enum find_xlat_flags.
 * @return          Pointer to the first matching string-value pair inside items
 *                  or NULL if nothing has been found.
 */
extern const struct xlat_data *find_xlat_val_ex(const struct xlat_data *items,
                                                const char *s, size_t num_items,
                                                unsigned int flags);
# define find_xlat_val(items_, s_) \
        find_xlat_val_ex((items_), (s_), ARRAY_SIZE(items_), 0)
# define find_xlat_val_case(items_, s_) \
        find_xlat_val_ex((items_), (s_), ARRAY_SIZE(items_), FXL_CASE_SENSITIVE)

/**
 * A find_xlat_val_ex wrapper for option arguments parsing.  Provides a value
 * from strs array that matched the supplied arg string.  If arg is NULL,
 * default_val is returned.  If nothing has matched, not_found value
 * is returned.
 *
 * find_arg_val provides a wrapper for the common case of statically-defined
 * strs arrays.
 *
 * @param arg         Argument string to parse
 * @param strs        Array of string-value pairs to match arg against.
 * @param strs_size   Element count in the strs array.
 * @param default_val Value to return if arg is NULL.
 * @param not_found   Value to return if arg hasn't found among strs.
 * @return            default_val is arg is NULL, value part of the matched
 *                    string-value pair, or not_found if nothing has matched.
 */
extern uint64_t find_arg_val_(const char *arg, const struct xlat_data *strs,
                              size_t strs_size, uint64_t default_val,
                              uint64_t not_found);
/** A find_arg_val_ wrapper that supplies strs_size to it using ARRAY_SIZE. */
# define find_arg_val(arg_, strs_, dflt_, not_found_) \
        find_arg_val_((arg_), (strs_), ARRAY_SIZE(strs_), (dflt_), (not_found_))

API in `tests/`

/* test/tests.h */
/* Print flags in symbolic form according to xlat table. */
int printflags(const struct xlat *, const unsigned long long, const char *);

/* Print flags in symbolic form according to xlat table. */
int printflags(const struct xlat *, const unsigned long long, const char *);

/* Print constant in symbolic form according to xlat table. */
int printxval_abbrev(const struct xlat *, const unsigned long long,
                     const char *);
int printxval_raw(const struct xlat *, const unsigned long long, const char *);
int printxval_verbose(const struct xlat *, const unsigned long long,
                      const char *);

/* Print constant in symbolic form according to xlat table. */
const char *sprintxlat_abbrev(const char *, const unsigned long long,
                           const char *);
const char *sprintxlat_raw(const char *, const unsigned long long,
                           const char *);
const char *sprintxlat_verbose(const char *, const unsigned long long,
                               const char *);

/* Print constant in symbolic form according to xlat table. */
const char *sprintxval_abbrev(const struct xlat *, const unsigned long long,
                              const char *);
const char *sprintxval_raw(const struct xlat *, const unsigned long long,
                           const char *);
const char *sprintxval_verbose(const struct xlat *, const unsigned long long,
                               const char *);

# if XLAT_RAW
#  define printxval  printxval_raw
#  define sprintxlat sprintxlat_raw
#  define sprintxval sprintxval_raw
# elif XLAT_VERBOSE
#  define printxval  printxval_verbose
#  define sprintxlat sprintxlat_verbose
#  define sprintxval sprintxval_verbose
# else
#  define printxval  printxval_abbrev
#  define sprintxlat sprintxlat_abbrev
#  define sprintxval sprintxval_abbrev
# endif

Things to Consider

xlat and mpers

Shared xlats

Testing xlat output

   1 /* xlat verbosity defaults */
   2 # ifndef XLAT_RAW
   3 #  define XLAT_RAW 0
   4 # endif
   5 # ifndef XLAT_VERBOSE
   6 #  define XLAT_VERBOSE 0
   7 # endif
   8 
   9 
  10 
  11 # if XLAT_RAW
  12 #  define XLAT_KNOWN(val_, str_) STRINGIFY_VAL(val_)
  13 #  define XLAT_UNKNOWN(val_, dflt_) STRINGIFY_VAL(val_)
  14 
  15 #  define XLAT_FMT "%#x"
  16 #  define XLAT_ARGS(a_) (a_)
  17 #  define XLAT_SEL(v_, s_) v_
  18 
  19 #  define ABBR(s_) ""
  20 #  define RAW(s_) s_
  21 #  define VERB(s_) ""
  22 #  define NABBR(s_) s_
  23 #  define NRAW(s_) ""
  24 #  define NVERB(s_) s_
  25 # elif XLAT_VERBOSE
  26 #  define XLAT_KNOWN(val_, str_) STRINGIFY_VAL(val_) " /* " str_ " */"
  27 #  define XLAT_UNKNOWN(val_, dflt_) STRINGIFY_VAL(val_) " /* " dflt_ " */"
  28 
  29 #  define XLAT_FMT "%#x /* %s */"
  30 #  define XLAT_ARGS(a_) a_, #a_
  31 #  define XLAT_SEL(v_, s_) v_, s_
  32 
  33 #  define ABBR(s_) ""
  34 #  define RAW(s_) ""
  35 #  define VERB(s_) s_
  36 #  define NABBR(s_) s_
  37 #  define NRAW(s_) s_
  38 #  define NVERB(s_) ""
  39 # else /* !XLAT_RAW && !XLAT_VERBOSE */
  40 #  define XLAT_KNOWN(val_, str_) str_
  41 #  define XLAT_UNKNOWN(val_, dflt_) STRINGIFY_VAL(val_) " /* " dflt_ " */"
  42 
  43 #  define XLAT_FMT "%s"
  44 #  define XLAT_ARGS(a_) #a_
  45 #  define XLAT_SEL(v_, s_) s_
  46 
  47 #  define ABBR(s_) s_
  48 #  define RAW(s_) ""
  49 #  define VERB(s_) ""
  50 #  define NABBR(s_) ""
  51 #  define NRAW(s_) s_
  52 #  define NVERB(s_) s_
  53 # endif /* XLAT_RAW, XLAT_VERBOSE */
  54 
  55 # define XLAT_STR(v_) sprintxlat(#v_, v_, NULL)
  56 
  57 # define ARG_XLAT_KNOWN(val_, str_) val_, XLAT_KNOWN(val_, str_)
  58 # define ARG_XLAT_UNKNOWN(val_, str_) val_, XLAT_UNKNOWN(val_, str_)
  59 

XlatDocumentation (last edited 2020-04-19 14:54:21 by eSyr)