diff options
-rw-r--r-- | tools/perf/builtin-record.c | 10 | ||||
-rw-r--r-- | tools/perf/util/bpf-event.c | 46 | ||||
-rw-r--r-- | tools/perf/util/bpf-event.h | 1 | ||||
-rw-r--r-- | tools/perf/util/env.c | 19 | ||||
-rw-r--r-- | tools/perf/util/env.h | 6 | ||||
-rw-r--r-- | tools/perf/util/header.c | 1 | ||||
-rw-r--r-- | tools/perf/util/synthetic-events.h | 2 |
7 files changed, 84 insertions, 1 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 0b566f300569..53971b9de3ba 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -2162,6 +2162,14 @@ out: return err; } +static void record__synthesize_final_bpf_metadata(struct record *rec __maybe_unused) +{ +#ifdef HAVE_LIBBPF_SUPPORT + perf_event__synthesize_final_bpf_metadata(rec->session, + process_synthesized_event); +#endif +} + static int record__process_signal_event(union perf_event *event __maybe_unused, void *data) { struct record *rec = data; @@ -2807,6 +2815,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) trigger_off(&auxtrace_snapshot_trigger); trigger_off(&switch_output_trigger); + record__synthesize_final_bpf_metadata(rec); + if (opts->auxtrace_snapshot_on_exit) record__auxtrace_snapshot_exit(rec); diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index 1f6e76ee6024..dc09a4730c50 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -472,6 +472,49 @@ void bpf_metadata_free(struct bpf_metadata *metadata __maybe_unused) #endif /* HAVE_LIBBPF_STRINGS_SUPPORT */ +struct bpf_metadata_final_ctx { + const struct perf_tool *tool; + perf_event__handler_t process; + struct machine *machine; +}; + +static void synthesize_final_bpf_metadata_cb(struct bpf_prog_info_node *node, + void *data) +{ + struct bpf_metadata_final_ctx *ctx = (struct bpf_metadata_final_ctx *)data; + struct bpf_metadata *metadata = node->metadata; + int err; + + if (metadata == NULL) + return; + err = synthesize_perf_record_bpf_metadata(metadata, ctx->tool, + ctx->process, ctx->machine); + if (err != 0) { + const char *prog_name = metadata->prog_names[0]; + + if (prog_name != NULL) + pr_warning("Couldn't synthesize final BPF metadata for %s.\n", prog_name); + else + pr_warning("Couldn't synthesize final BPF metadata.\n"); + } + bpf_metadata_free(metadata); + node->metadata = NULL; +} + +void perf_event__synthesize_final_bpf_metadata(struct perf_session *session, + perf_event__handler_t process) +{ + struct perf_env *env = &session->header.env; + struct bpf_metadata_final_ctx ctx = { + .tool = session->tool, + .process = process, + .machine = &session->machines.host, + }; + + perf_env__iterate_bpf_prog_info(env, synthesize_final_bpf_metadata_cb, + &ctx); +} + /* * Synthesize PERF_RECORD_KSYMBOL and PERF_RECORD_BPF_EVENT for one bpf * program. One PERF_RECORD_BPF_EVENT is generated for the program. And @@ -612,6 +655,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, } info_node->info_linear = info_linear; + info_node->metadata = NULL; if (!perf_env__insert_bpf_prog_info(env, info_node)) { free(info_linear); free(info_node); @@ -803,6 +847,7 @@ static void perf_env__add_bpf_info(struct perf_env *env, u32 id) arrays |= 1UL << PERF_BPIL_JITED_INSNS; arrays |= 1UL << PERF_BPIL_LINE_INFO; arrays |= 1UL << PERF_BPIL_JITED_LINE_INFO; + arrays |= 1UL << PERF_BPIL_MAP_IDS; info_linear = get_bpf_prog_info_linear(fd, arrays); if (IS_ERR_OR_NULL(info_linear)) { @@ -815,6 +860,7 @@ static void perf_env__add_bpf_info(struct perf_env *env, u32 id) info_node = malloc(sizeof(struct bpf_prog_info_node)); if (info_node) { info_node->info_linear = info_linear; + info_node->metadata = bpf_metadata_create(&info_linear->info); if (!perf_env__insert_bpf_prog_info(env, info_node)) { free(info_linear); free(info_node); diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h index ef2dd3f1619e..60d2c6637af5 100644 --- a/tools/perf/util/bpf-event.h +++ b/tools/perf/util/bpf-event.h @@ -25,6 +25,7 @@ struct bpf_metadata { struct bpf_prog_info_node { struct perf_bpil *info_linear; + struct bpf_metadata *metadata; struct rb_node rb_node; }; diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 36411749e007..05a4f2657d72 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -3,8 +3,10 @@ #include "debug.h" #include "env.h" #include "util/header.h" -#include "linux/compiler.h" +#include "util/rwsem.h" +#include <linux/compiler.h> #include <linux/ctype.h> +#include <linux/rbtree.h> #include <linux/string.h> #include <linux/zalloc.h> #include "cgroup.h" @@ -89,6 +91,20 @@ out: return node; } +void perf_env__iterate_bpf_prog_info(struct perf_env *env, + void (*cb)(struct bpf_prog_info_node *node, + void *data), + void *data) +{ + struct rb_node *first; + + down_read(&env->bpf_progs.lock); + first = rb_first(&env->bpf_progs.infos); + for (struct rb_node *node = first; node != NULL; node = rb_next(node)) + (*cb)(rb_entry(node, struct bpf_prog_info_node, rb_node), data); + up_read(&env->bpf_progs.lock); +} + bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) { bool ret; @@ -174,6 +190,7 @@ static void perf_env__purge_bpf(struct perf_env *env) next = rb_next(&node->rb_node); rb_erase(&node->rb_node, root); zfree(&node->info_linear); + bpf_metadata_free(node->metadata); free(node); } diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index d90e343cf1fa..c90c1d717e73 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -174,16 +174,22 @@ const char *perf_env__raw_arch(struct perf_env *env); int perf_env__nr_cpus_avail(struct perf_env *env); void perf_env__init(struct perf_env *env); +#ifdef HAVE_LIBBPF_SUPPORT bool __perf_env__insert_bpf_prog_info(struct perf_env *env, struct bpf_prog_info_node *info_node); bool perf_env__insert_bpf_prog_info(struct perf_env *env, struct bpf_prog_info_node *info_node); struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, __u32 prog_id); +void perf_env__iterate_bpf_prog_info(struct perf_env *env, + void (*cb)(struct bpf_prog_info_node *node, + void *data), + void *data); bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); bool __perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id); struct btf_node *__perf_env__find_btf(struct perf_env *env, __u32 btf_id); +#endif // HAVE_LIBBPF_SUPPORT int perf_env__numa_node(struct perf_env *env, struct perf_cpu cpu); char *perf_env__find_pmu_cap(struct perf_env *env, const char *pmu_name, diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index d7f6ff6974aa..2dea35237e81 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3145,6 +3145,7 @@ static int process_bpf_prog_info(struct feat_fd *ff, void *data __maybe_unused) /* after reading from file, translate offset to address */ bpil_offs_to_addr(info_linear); info_node->info_linear = info_linear; + info_node->metadata = NULL; if (!__perf_env__insert_bpf_prog_info(env, info_node)) { free(info_linear); free(info_node); diff --git a/tools/perf/util/synthetic-events.h b/tools/perf/util/synthetic-events.h index b9c936b5cfeb..ee29615d68e5 100644 --- a/tools/perf/util/synthetic-events.h +++ b/tools/perf/util/synthetic-events.h @@ -92,6 +92,8 @@ int perf_event__synthesize_threads(const struct perf_tool *tool, perf_event__han int perf_event__synthesize_tracing_data(const struct perf_tool *tool, int fd, struct evlist *evlist, perf_event__handler_t process); int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc, const struct perf_tool *tool, perf_event__handler_t process, struct machine *machine); pid_t perf_event__synthesize_comm(const struct perf_tool *tool, union perf_event *event, pid_t pid, perf_event__handler_t process, struct machine *machine); +void perf_event__synthesize_final_bpf_metadata(struct perf_session *session, + perf_event__handler_t process); int perf_tool__process_synth_event(const struct perf_tool *tool, union perf_event *event, struct machine *machine, perf_event__handler_t process); |