perf trace: Remove arg_fmt->is_enum, we can get that from the BTF type

This is to pave the way for other BTF types, i.e. we try to find BTF
type then use things like btf_is_enum(btf_type) that we cached to find
the right strtoul and scnprintf routines.

For now only enum is supported, all the other types simple return zero
for scnprintf which makes it have the same behaviour as when BTF isn't
available, i.e. fallback to no pretty printing. Ditto for strtoul.

  root@x1:~# perf test -v enum
  124: perf trace enum augmentation tests                              : Ok
  root@x1:~# perf test -v enum
  124: perf trace enum augmentation tests                              : Ok
  root@x1:~# perf test -v enum
  124: perf trace enum augmentation tests                              : Ok
  root@x1:~# perf test -v enum
  124: perf trace enum augmentation tests                              : Ok
  root@x1:~# perf test -v enum
  124: perf trace enum augmentation tests                              : Ok
  root@x1:~#
Signed-off-by: default avatarHoward Chu <howardchu95@gmail.com>
Tested-by: default avatarHoward Chu <howardchu95@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20240624181345.124764-9-howardchu95@gmail.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 62284329
...@@ -111,7 +111,6 @@ struct syscall_arg_fmt { ...@@ -111,7 +111,6 @@ struct syscall_arg_fmt {
const char *name; const char *name;
u16 nr_entries; // for arrays u16 nr_entries; // for arrays
bool show_zero; bool show_zero;
bool is_enum;
#ifdef HAVE_LIBBPF_SUPPORT #ifdef HAVE_LIBBPF_SUPPORT
const struct btf_type *type; const struct btf_type *type;
#endif #endif
...@@ -910,33 +909,46 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, ...@@ -910,33 +909,46 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags #define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
#ifdef HAVE_LIBBPF_SUPPORT #ifdef HAVE_LIBBPF_SUPPORT
static int syscall_arg_fmt__cache_btf_enum(struct syscall_arg_fmt *arg_fmt, struct btf *btf, char *type) static void syscall_arg_fmt__cache_btf_enum(struct syscall_arg_fmt *arg_fmt, struct btf *btf, char *type)
{ {
int id; int id;
// Already cached?
if (arg_fmt->type != NULL)
return 0;
type = strstr(type, "enum "); type = strstr(type, "enum ");
if (type == NULL) if (type == NULL)
return -1; return;
type += 5; // skip "enum " to get the enumeration name type += 5; // skip "enum " to get the enumeration name
id = btf__find_by_name(btf, type); id = btf__find_by_name(btf, type);
if (id < 0) if (id < 0)
return -1; return;
arg_fmt->type = btf__type_by_id(btf, id); arg_fmt->type = btf__type_by_id(btf, id);
return arg_fmt->type == NULL ? -1 : 0;
} }
static bool syscall_arg__strtoul_btf_enum(char *bf, size_t size, struct syscall_arg *arg, u64 *val) static bool syscall_arg__strtoul_btf_enum(char *bf, size_t size, struct syscall_arg *arg, u64 *val)
{
const struct btf_type *bt = arg->fmt->type;
struct btf *btf = arg->trace->btf;
struct btf_enum *be = btf_enum(bt);
for (int i = 0; i < btf_vlen(bt); ++i, ++be) {
const char *name = btf__name_by_offset(btf, be->name_off);
int max_len = max(size, strlen(name));
if (strncmp(name, bf, max_len) == 0) {
*val = be->val;
return true;
}
}
return false;
}
static bool syscall_arg__strtoul_btf_type(char *bf, size_t size, struct syscall_arg *arg, u64 *val)
{ {
const struct btf_type *bt; const struct btf_type *bt;
char *type = arg->parm; char *type = arg->type_name;
struct btf_enum *be;
struct btf *btf; struct btf *btf;
trace__load_vmlinux_btf(arg->trace); trace__load_vmlinux_btf(arg->trace);
...@@ -945,20 +957,19 @@ static bool syscall_arg__strtoul_btf_enum(char *bf, size_t size, struct syscall_ ...@@ -945,20 +957,19 @@ static bool syscall_arg__strtoul_btf_enum(char *bf, size_t size, struct syscall_
if (btf == NULL) if (btf == NULL)
return false; return false;
if (syscall_arg_fmt__cache_btf_enum(arg->fmt, btf, type) < 0) if (arg->fmt->type == NULL) {
return false; // See if this is an enum
syscall_arg_fmt__cache_btf_enum(arg->fmt, btf, type);
}
// Now let's see if we have a BTF type resolved
bt = arg->fmt->type; bt = arg->fmt->type;
be = btf_enum(bt); if (bt == NULL)
for (int i = 0; i < btf_vlen(bt); ++i, ++be) { return false;
const char *name = btf__name_by_offset(btf, be->name_off);
int max_len = max(size, strlen(name));
if (strncmp(name, bf, max_len) == 0) { // If it is an enum:
*val = be->val; if (btf_is_enum(arg->fmt->type))
return true; return syscall_arg__strtoul_btf_enum(bf, size, arg, val);
}
}
return false; return false;
} }
...@@ -978,23 +989,23 @@ static size_t btf_enum_scnprintf(const struct btf_type *type, struct btf *btf, c ...@@ -978,23 +989,23 @@ static size_t btf_enum_scnprintf(const struct btf_type *type, struct btf *btf, c
return 0; return 0;
} }
static size_t trace__btf_enum_scnprintf(struct trace *trace, struct syscall_arg_fmt *arg_fmt, char *bf, static size_t trace__btf_scnprintf(struct trace *trace, struct syscall_arg_fmt *arg_fmt, char *bf,
size_t size, int val, char *type) size_t size, int val, char *type)
{ {
if (syscall_arg_fmt__cache_btf_enum(arg_fmt, trace->btf, type) < 0) if (trace->btf == NULL)
return 0; return 0;
return btf_enum_scnprintf(arg_fmt->type, trace->btf, bf, size, val); if (arg_fmt->type == NULL) {
} // Check if this is an enum and if we have the BTF type for it.
syscall_arg_fmt__cache_btf_enum(arg_fmt, trace->btf, type);
}
static size_t trace__btf_scnprintf(struct trace *trace, struct syscall_arg_fmt *arg_fmt, char *bf, // Did we manage to find a BTF type for the syscall/tracepoint argument?
size_t size, int val, char *type) if (arg_fmt->type == NULL)
{
if (trace->btf == NULL)
return 0; return 0;
if (arg_fmt->is_enum) if (btf_is_enum(arg_fmt->type))
return trace__btf_enum_scnprintf(trace, arg_fmt, bf, size, val, type); return btf_enum_scnprintf(arg_fmt->type, trace->btf, bf, size, val);
return 0; return 0;
} }
...@@ -1007,14 +1018,14 @@ static size_t trace__btf_scnprintf(struct trace *trace __maybe_unused, struct sy ...@@ -1007,14 +1018,14 @@ static size_t trace__btf_scnprintf(struct trace *trace __maybe_unused, struct sy
return 0; return 0;
} }
static bool syscall_arg__strtoul_btf_enum(char *bf __maybe_unused, size_t size __maybe_unused, static bool syscall_arg__strtoul_btf_type(char *bf __maybe_unused, size_t size __maybe_unused,
struct syscall_arg *arg __maybe_unused, u64 *val __maybe_unused) struct syscall_arg *arg __maybe_unused, u64 *val __maybe_unused)
{ {
return false; return false;
} }
#endif // HAVE_LIBBPF_SUPPORT #endif // HAVE_LIBBPF_SUPPORT
#define STUL_BTF_ENUM syscall_arg__strtoul_btf_enum #define STUL_BTF_TYPE syscall_arg__strtoul_btf_type
#define STRARRAY(name, array) \ #define STRARRAY(name, array) \
{ .scnprintf = SCA_STRARRAY, \ { .scnprintf = SCA_STRARRAY, \
...@@ -1887,7 +1898,6 @@ syscall_arg_fmt__init_array(struct syscall_arg_fmt *arg, struct tep_format_field ...@@ -1887,7 +1898,6 @@ syscall_arg_fmt__init_array(struct syscall_arg_fmt *arg, struct tep_format_field
continue; continue;
len = strlen(field->name); len = strlen(field->name);
arg->is_enum = false;
if (strcmp(field->type, "const char *") == 0 && if (strcmp(field->type, "const char *") == 0 &&
((len >= 4 && strcmp(field->name + len - 4, "name") == 0) || ((len >= 4 && strcmp(field->name + len - 4, "name") == 0) ||
...@@ -1915,8 +1925,8 @@ syscall_arg_fmt__init_array(struct syscall_arg_fmt *arg, struct tep_format_field ...@@ -1915,8 +1925,8 @@ syscall_arg_fmt__init_array(struct syscall_arg_fmt *arg, struct tep_format_field
*/ */
arg->scnprintf = SCA_FD; arg->scnprintf = SCA_FD;
} else if (strstr(field->type, "enum") && use_btf != NULL) { } else if (strstr(field->type, "enum") && use_btf != NULL) {
*use_btf = arg->is_enum = true; *use_btf = true;
arg->strtoul = STUL_BTF_ENUM; arg->strtoul = STUL_BTF_TYPE;
} else { } else {
const struct syscall_arg_fmt *fmt = const struct syscall_arg_fmt *fmt =
syscall_arg_fmt__find_by_name(field->name); syscall_arg_fmt__find_by_name(field->name);
...@@ -2236,10 +2246,13 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, ...@@ -2236,10 +2246,13 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
/* /*
* Suppress this argument if its value is zero and show_zero * Suppress this argument if its value is zero and show_zero
* property isn't set. * property isn't set.
*
* If it has a BTF type, then override the zero suppression knob
* as the common case is for zero in an enum to have an associated entry.
*/ */
if (val == 0 && !trace->show_zeros && if (val == 0 && !trace->show_zeros &&
!(sc->arg_fmt && sc->arg_fmt[arg.idx].show_zero) && !(sc->arg_fmt && sc->arg_fmt[arg.idx].show_zero) &&
!(sc->arg_fmt && sc->arg_fmt[arg.idx].is_enum)) !(sc->arg_fmt && sc->arg_fmt[arg.idx].strtoul == STUL_BTF_TYPE))
continue; continue;
printed += scnprintf(bf + printed, size - printed, "%s", printed ? ", " : ""); printed += scnprintf(bf + printed, size - printed, "%s", printed ? ", " : "");
...@@ -2942,7 +2955,7 @@ static size_t trace__fprintf_tp_fields(struct trace *trace, struct evsel *evsel, ...@@ -2942,7 +2955,7 @@ static size_t trace__fprintf_tp_fields(struct trace *trace, struct evsel *evsel,
val = syscall_arg_fmt__mask_val(arg, &syscall_arg, val); val = syscall_arg_fmt__mask_val(arg, &syscall_arg, val);
/* Suppress this argument if its value is zero and show_zero property isn't set. */ /* Suppress this argument if its value is zero and show_zero property isn't set. */
if (val == 0 && !trace->show_zeros && !arg->show_zero && !arg->is_enum) if (val == 0 && !trace->show_zeros && !arg->show_zero && arg->strtoul != STUL_BTF_TYPE)
continue; continue;
printed += scnprintf(bf + printed, size - printed, "%s", printed ? ", " : ""); printed += scnprintf(bf + printed, size - printed, "%s", printed ? ", " : "");
...@@ -3910,14 +3923,10 @@ static int trace__expand_filter(struct trace *trace, struct evsel *evsel) ...@@ -3910,14 +3923,10 @@ static int trace__expand_filter(struct trace *trace, struct evsel *evsel)
struct syscall_arg syscall_arg = { struct syscall_arg syscall_arg = {
.trace = trace, .trace = trace,
.fmt = fmt, .fmt = fmt,
.type_name = type,
.parm = fmt->parm,
}; };
if (fmt->is_enum) {
syscall_arg.parm = type;
} else {
syscall_arg.parm = fmt->parm;
}
if (fmt->strtoul(right, right_size, &syscall_arg, &val)) { if (fmt->strtoul(right, right_size, &syscall_arg, &val)) {
char *n, expansion[19]; char *n, expansion[19];
int expansion_lenght = scnprintf(expansion, sizeof(expansion), "%#" PRIx64, val); int expansion_lenght = scnprintf(expansion, sizeof(expansion), "%#" PRIx64, val);
......
...@@ -113,6 +113,7 @@ struct syscall_arg { ...@@ -113,6 +113,7 @@ struct syscall_arg {
struct thread *thread; struct thread *thread;
struct trace *trace; struct trace *trace;
void *parm; void *parm;
char *type_name;
u16 len; u16 len;
u8 idx; u8 idx;
u8 mask; u8 mask;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment