diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 3a1c031aff9ad049..49d99c20b7f711ef 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -112,10 +112,9 @@ struct syscall_arg_fmt { u16 nr_entries; // for arrays bool show_zero; bool is_enum; - struct { - void *entry; - u16 nr_entries; - } btf_entry; +#ifdef HAVE_LIBBPF_SUPPORT + const struct btf_type *type; +#endif }; struct syscall_fmt { @@ -146,7 +145,9 @@ struct trace { #ifdef HAVE_BPF_SKEL struct augmented_raw_syscalls_bpf *skel; #endif +#ifdef HAVE_LIBBPF_SUPPORT struct btf *btf; +#endif struct record_opts opts; struct evlist *evlist; struct machine *host; @@ -894,47 +895,32 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, #define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags -static int btf_enum_find_entry(struct btf *btf, char *type, struct syscall_arg_fmt *arg_fmt) +#ifdef HAVE_LIBBPF_SUPPORT +static int syscall_arg_fmt__cache_btf_enum(struct syscall_arg_fmt *arg_fmt, struct btf *btf, char *type) { - const struct btf_type *bt; - char enum_prefix[][16] = { "enum", "const enum" }, *ep; int id; - size_t i; - for (i = 0; i < ARRAY_SIZE(enum_prefix); i++) { - ep = enum_prefix[i]; - if (strlen(type) > strlen(ep) + 1 && strstarts(type, ep)) - type += strlen(ep) + 1; - } + type = strstr(type, "enum "); + if (type == NULL) + return -1; + + type += 5; // skip "enum " to get the enumeration name id = btf__find_by_name(btf, type); if (id < 0) return -1; - bt = btf__type_by_id(btf, id); - if (bt == NULL) - return -1; - - arg_fmt->btf_entry.entry = btf_enum(bt); - arg_fmt->btf_entry.nr_entries = btf_vlen(bt); - - return 0; + arg_fmt->type = btf__type_by_id(btf, id); + return arg_fmt->type == NULL ? -1 : 0; } -static size_t btf_enum_scnprintf(char *bf, size_t size, int val, struct btf *btf, char *type, - struct syscall_arg_fmt *arg_fmt) -{ - struct btf_enum *be; - int i; - - /* if btf_entry is NULL, find and save it to arg_fmt */ - if (arg_fmt->btf_entry.entry == NULL) - if (btf_enum_find_entry(btf, type, arg_fmt)) - return 0; - be = (struct btf_enum *)arg_fmt->btf_entry.entry; +static size_t btf_enum_scnprintf(const struct btf_type *type, struct btf *btf, char *bf, size_t size, int val) +{ + struct btf_enum *be = btf_enum(type); + const int nr_entries = btf_vlen(type); - for (i = 0; i < arg_fmt->btf_entry.nr_entries; ++i, ++be) { + for (int i = 0; i < nr_entries; ++i, ++be) { if (be->val == val) { return scnprintf(bf, size, "%s", btf__name_by_offset(btf, be->name_off)); @@ -944,6 +930,27 @@ static size_t btf_enum_scnprintf(char *bf, size_t size, int val, struct btf *btf return 0; } +static size_t trace__btf_enum_scnprintf(struct trace *trace, struct syscall_arg_fmt *arg_fmt, char *bf, + size_t size, int val, char *type) +{ + if (trace->btf == NULL) + return 0; + /* if btf_entry is NULL, find and save it to arg_fmt */ + if (arg_fmt->type == NULL && + syscall_arg_fmt__cache_btf_enum(arg_fmt, trace->btf, type) < 0) + return 0; + + return btf_enum_scnprintf(arg_fmt->type, trace->btf, bf, size, val); +} +#else // HAVE_LIBBPF_SUPPORT +static size_t trace__btf_enum_scnprintf(struct trace *trace __maybe_unused, struct syscall_arg_fmt *arg_fmt __maybe_unused, + char *bf __maybe_unused, size_t size __maybe_unused, int val __maybe_unused, + char *type __maybe_unused) +{ + return 0; +} +#endif // HAVE_LIBBPF_SUPPORT + #define STRARRAY(name, array) \ { .scnprintf = SCA_STRARRAY, \ .strtoul = STUL_STRARRAY, \ @@ -1757,13 +1764,18 @@ static void trace__symbols__exit(struct trace *trace) symbol__exit(); } -static void trace__load_vmlinux_btf(struct trace *trace) +static void trace__load_vmlinux_btf(struct trace *trace __maybe_unused) { +#ifdef HAVE_LIBBPF_SUPPORT + if (trace->btf != NULL) + return; + trace->btf = btf__load_vmlinux_btf(); if (verbose > 0) { fprintf(trace->output, trace->btf ? "vmlinux BTF loaded\n" : "Failed to load vmlinux BTF\n"); } +#endif } static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args) @@ -1959,7 +1971,7 @@ static int trace__read_syscall_info(struct trace *trace, int id) err = syscall__set_arg_fmts(sc); /* after calling syscall__set_arg_fmts() we'll know whether use_btf is true */ - if (sc->use_btf && trace->btf == NULL) + if (sc->use_btf) trace__load_vmlinux_btf(trace); return err; @@ -2182,10 +2194,9 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, if (trace->show_arg_names) printed += scnprintf(bf + printed, size - printed, "%s: ", field->name); - if (sc->arg_fmt[arg.idx].is_enum && trace->btf) { - size_t p = btf_enum_scnprintf(bf + printed, size - printed, val, - trace->btf, field->type, - &sc->arg_fmt[arg.idx]); + if (sc->arg_fmt[arg.idx].is_enum) { + size_t p = trace__btf_enum_scnprintf(trace, &sc->arg_fmt[arg.idx], bf + printed, + size - printed, val, field->type); if (p) { printed += p; continue;