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:
One of the annotations, that start with # symbol and are listed below.
Preprocessor definitions, that start with # and are not part of annotations listed below.
Constants, that start either with one of A-Z characters, 1<< character sequence, or a number.
- Any other content.
xlat/gen.sh processes the xlat file in two passes:
- To generate constant check/definition rules.
- To generate xlat struct definition.
The following rules are applied during processing:
- Annotations are processed as following:
#conditional
#unconditional
#val_type TYPE
#sorted [COMMAND]`
#value_indexed
#enum
#include INCLUDE
- Preprocessor definitions are emitted verbatim during the both passes.
- Constants ...
- The rest is added verbatim at the second pass.
Notes regarding #sorted and #value_indexed annotations:
- These annotations are optional and affect only the way values in an xlat
array are searched (index-based access in cave of #value_indexed and binary search in case of #sorted).
- The correctness of the generated xlat files is not checked with respect
to sort order (in case of #sorted) and fill effectiveness is not checked as well (in case of #value_sorted), so it is important to realise the outcomes of providing these annotations.
As a result, #sorted annotation can be provided only for xlat fields where fallback values are supplied for each constants, so the possible variations in external definition would not affect the correctness and effectiveness of the resulting xlat array.
As a rule of thumb, #value_indexed annotation is to be considered if it increases the resulting array size no more than (1+1/log2(CURRENT_ARRAY_SIZE)) times.
API
The xlat-related API is split between two files:
xlat.h contains main type definitions, xlat style flags, and xlat constant definition macros.
defs.h contains functions and function-like macros for using xlats.
xlat arrays can be interpreted in one of two ways:
- "xlat": named constants
- "flags": bitwise-OR'ed combination of named constants
Types
The main type is struct xlat. It is defined as follows:
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);
Related Functions
/** * 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