Skip to content

Commit fdc3441

Browse files
blakej11namhyung
authored andcommitted
perf record: collect BPF metadata from new programs
This collects metadata for any BPF programs that were loaded during a "perf record" run, and emits it at the end of the run. Signed-off-by: Blake Jones <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Namhyung Kim <[email protected]>
1 parent ab38e84 commit fdc3441

File tree

7 files changed

+84
-1
lines changed

7 files changed

+84
-1
lines changed

tools/perf/builtin-record.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2162,6 +2162,14 @@ static int record__synthesize(struct record *rec, bool tail)
21622162
return err;
21632163
}
21642164

2165+
static void record__synthesize_final_bpf_metadata(struct record *rec __maybe_unused)
2166+
{
2167+
#ifdef HAVE_LIBBPF_SUPPORT
2168+
perf_event__synthesize_final_bpf_metadata(rec->session,
2169+
process_synthesized_event);
2170+
#endif
2171+
}
2172+
21652173
static int record__process_signal_event(union perf_event *event __maybe_unused, void *data)
21662174
{
21672175
struct record *rec = data;
@@ -2807,6 +2815,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
28072815
trigger_off(&auxtrace_snapshot_trigger);
28082816
trigger_off(&switch_output_trigger);
28092817

2818+
record__synthesize_final_bpf_metadata(rec);
2819+
28102820
if (opts->auxtrace_snapshot_on_exit)
28112821
record__auxtrace_snapshot_exit(rec);
28122822

tools/perf/util/bpf-event.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,49 @@ void bpf_metadata_free(struct bpf_metadata *metadata __maybe_unused)
472472

473473
#endif /* HAVE_LIBBPF_STRINGS_SUPPORT */
474474

475+
struct bpf_metadata_final_ctx {
476+
const struct perf_tool *tool;
477+
perf_event__handler_t process;
478+
struct machine *machine;
479+
};
480+
481+
static void synthesize_final_bpf_metadata_cb(struct bpf_prog_info_node *node,
482+
void *data)
483+
{
484+
struct bpf_metadata_final_ctx *ctx = (struct bpf_metadata_final_ctx *)data;
485+
struct bpf_metadata *metadata = node->metadata;
486+
int err;
487+
488+
if (metadata == NULL)
489+
return;
490+
err = synthesize_perf_record_bpf_metadata(metadata, ctx->tool,
491+
ctx->process, ctx->machine);
492+
if (err != 0) {
493+
const char *prog_name = metadata->prog_names[0];
494+
495+
if (prog_name != NULL)
496+
pr_warning("Couldn't synthesize final BPF metadata for %s.\n", prog_name);
497+
else
498+
pr_warning("Couldn't synthesize final BPF metadata.\n");
499+
}
500+
bpf_metadata_free(metadata);
501+
node->metadata = NULL;
502+
}
503+
504+
void perf_event__synthesize_final_bpf_metadata(struct perf_session *session,
505+
perf_event__handler_t process)
506+
{
507+
struct perf_env *env = &session->header.env;
508+
struct bpf_metadata_final_ctx ctx = {
509+
.tool = session->tool,
510+
.process = process,
511+
.machine = &session->machines.host,
512+
};
513+
514+
perf_env__iterate_bpf_prog_info(env, synthesize_final_bpf_metadata_cb,
515+
&ctx);
516+
}
517+
475518
/*
476519
* Synthesize PERF_RECORD_KSYMBOL and PERF_RECORD_BPF_EVENT for one bpf
477520
* 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,
612655
}
613656

614657
info_node->info_linear = info_linear;
658+
info_node->metadata = NULL;
615659
if (!perf_env__insert_bpf_prog_info(env, info_node)) {
616660
free(info_linear);
617661
free(info_node);
@@ -803,6 +847,7 @@ static void perf_env__add_bpf_info(struct perf_env *env, u32 id)
803847
arrays |= 1UL << PERF_BPIL_JITED_INSNS;
804848
arrays |= 1UL << PERF_BPIL_LINE_INFO;
805849
arrays |= 1UL << PERF_BPIL_JITED_LINE_INFO;
850+
arrays |= 1UL << PERF_BPIL_MAP_IDS;
806851

807852
info_linear = get_bpf_prog_info_linear(fd, arrays);
808853
if (IS_ERR_OR_NULL(info_linear)) {
@@ -815,6 +860,7 @@ static void perf_env__add_bpf_info(struct perf_env *env, u32 id)
815860
info_node = malloc(sizeof(struct bpf_prog_info_node));
816861
if (info_node) {
817862
info_node->info_linear = info_linear;
863+
info_node->metadata = bpf_metadata_create(&info_linear->info);
818864
if (!perf_env__insert_bpf_prog_info(env, info_node)) {
819865
free(info_linear);
820866
free(info_node);

tools/perf/util/bpf-event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct bpf_metadata {
2525

2626
struct bpf_prog_info_node {
2727
struct perf_bpil *info_linear;
28+
struct bpf_metadata *metadata;
2829
struct rb_node rb_node;
2930
};
3031

tools/perf/util/env.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
#include "debug.h"
44
#include "env.h"
55
#include "util/header.h"
6-
#include "linux/compiler.h"
6+
#include "util/rwsem.h"
7+
#include <linux/compiler.h>
78
#include <linux/ctype.h>
9+
#include <linux/rbtree.h>
810
#include <linux/string.h>
911
#include <linux/zalloc.h>
1012
#include "cgroup.h"
@@ -89,6 +91,20 @@ struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
8991
return node;
9092
}
9193

94+
void perf_env__iterate_bpf_prog_info(struct perf_env *env,
95+
void (*cb)(struct bpf_prog_info_node *node,
96+
void *data),
97+
void *data)
98+
{
99+
struct rb_node *first;
100+
101+
down_read(&env->bpf_progs.lock);
102+
first = rb_first(&env->bpf_progs.infos);
103+
for (struct rb_node *node = first; node != NULL; node = rb_next(node))
104+
(*cb)(rb_entry(node, struct bpf_prog_info_node, rb_node), data);
105+
up_read(&env->bpf_progs.lock);
106+
}
107+
92108
bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
93109
{
94110
bool ret;
@@ -174,6 +190,7 @@ static void perf_env__purge_bpf(struct perf_env *env)
174190
next = rb_next(&node->rb_node);
175191
rb_erase(&node->rb_node, root);
176192
zfree(&node->info_linear);
193+
bpf_metadata_free(node->metadata);
177194
free(node);
178195
}
179196

tools/perf/util/env.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,22 @@ const char *perf_env__raw_arch(struct perf_env *env);
174174
int perf_env__nr_cpus_avail(struct perf_env *env);
175175

176176
void perf_env__init(struct perf_env *env);
177+
#ifdef HAVE_LIBBPF_SUPPORT
177178
bool __perf_env__insert_bpf_prog_info(struct perf_env *env,
178179
struct bpf_prog_info_node *info_node);
179180
bool perf_env__insert_bpf_prog_info(struct perf_env *env,
180181
struct bpf_prog_info_node *info_node);
181182
struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
182183
__u32 prog_id);
184+
void perf_env__iterate_bpf_prog_info(struct perf_env *env,
185+
void (*cb)(struct bpf_prog_info_node *node,
186+
void *data),
187+
void *data);
183188
bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node);
184189
bool __perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node);
185190
struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id);
186191
struct btf_node *__perf_env__find_btf(struct perf_env *env, __u32 btf_id);
192+
#endif // HAVE_LIBBPF_SUPPORT
187193

188194
int perf_env__numa_node(struct perf_env *env, struct perf_cpu cpu);
189195
char *perf_env__find_pmu_cap(struct perf_env *env, const char *pmu_name,

tools/perf/util/header.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3145,6 +3145,7 @@ static int process_bpf_prog_info(struct feat_fd *ff, void *data __maybe_unused)
31453145
/* after reading from file, translate offset to address */
31463146
bpil_offs_to_addr(info_linear);
31473147
info_node->info_linear = info_linear;
3148+
info_node->metadata = NULL;
31483149
if (!__perf_env__insert_bpf_prog_info(env, info_node)) {
31493150
free(info_linear);
31503151
free(info_node);

tools/perf/util/synthetic-events.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ int perf_event__synthesize_threads(const struct perf_tool *tool, perf_event__han
9292
int perf_event__synthesize_tracing_data(const struct perf_tool *tool, int fd, struct evlist *evlist, perf_event__handler_t process);
9393
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);
9494
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);
95+
void perf_event__synthesize_final_bpf_metadata(struct perf_session *session,
96+
perf_event__handler_t process);
9597

9698
int perf_tool__process_synth_event(const struct perf_tool *tool, union perf_event *event, struct machine *machine, perf_event__handler_t process);
9799

0 commit comments

Comments
 (0)