lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAP-5=fWZG-N8ZzRh6h1qRuEgFbxTCyEwGu1sZZy+YmnSeGgSSw@mail.gmail.com>
Date: Thu, 29 May 2025 11:12:28 -0700
From: Ian Rogers <irogers@...gle.com>
To: Blake Jones <blakejones@...gle.com>
Cc: Alexei Starovoitov <ast@...nel.org>, Daniel Borkmann <daniel@...earbox.net>, 
	Andrii Nakryiko <andrii@...nel.org>, Martin KaFai Lau <martin.lau@...ux.dev>, 
	Eduard Zingerman <eddyz87@...il.com>, Song Liu <song@...nel.org>, 
	Yonghong Song <yonghong.song@...ux.dev>, John Fastabend <john.fastabend@...il.com>, 
	KP Singh <kpsingh@...nel.org>, Stanislav Fomichev <sdf@...ichev.me>, Hao Luo <haoluo@...gle.com>, 
	Jiri Olsa <jolsa@...nel.org>, Peter Zijlstra <peterz@...radead.org>, Ingo Molnar <mingo@...hat.com>, 
	Arnaldo Carvalho de Melo <acme@...nel.org>, Namhyung Kim <namhyung@...nel.org>, 
	Mark Rutland <mark.rutland@....com>, 
	Alexander Shishkin <alexander.shishkin@...ux.intel.com>, 
	Adrian Hunter <adrian.hunter@...el.com>, Kan Liang <kan.liang@...ux.intel.com>, 
	Chun-Tse Shao <ctshao@...gle.com>, Zhongqiu Han <quic_zhonhan@...cinc.com>, 
	James Clark <james.clark@...aro.org>, Charlie Jenkins <charlie@...osinc.com>, 
	Andi Kleen <ak@...ux.intel.com>, Dmitry Vyukov <dvyukov@...gle.com>, Leo Yan <leo.yan@....com>, 
	Yujie Liu <yujie.liu@...el.com>, Graham Woodward <graham.woodward@....com>, 
	Yicong Yang <yangyicong@...ilicon.com>, Ben Gainey <ben.gainey@....com>, 
	linux-kernel@...r.kernel.org, bpf@...r.kernel.org, 
	linux-perf-users@...r.kernel.org
Subject: Re: [PATCH 3/3] perf: collect BPF metadata from new programs, and
 display the new event

On Wed, May 21, 2025 at 3:27 PM Blake Jones <blakejones@...gle.com> wrote:
>
> This collects metadata for any BPF programs that were loaded during a
> "perf record" run, and emits it at the end of the run. It also adds support
> for displaying the new PERF_RECORD_BPF_METADATA type.
>
> Here's some example "perf script -D" output for the new event type. The
> ": unhandled!" message is from tool.c, analogous to other behavior there.
> I've elided some rows with all NUL characters for brevity, and I wrapped
> one of the >75-column lines to fit in the commit guidelines.
>
> 0x50fc8@...f.data [0x260]: event: 84
> .
> . ... raw event: size 608 bytes
> .  0000:  54 00 00 00 00 00 60 02 62 70 66 5f 70 72 6f 67  T.....`.bpf_prog
> .  0010:  5f 31 65 30 61 32 65 33 36 36 65 35 36 66 31 61  _1e0a2e366e56f1a
> .  0020:  32 5f 70 65 72 66 5f 73 61 6d 70 6c 65 5f 66 69  2_perf_sample_fi
> .  0030:  6c 74 65 72 00 00 00 00 00 00 00 00 00 00 00 00  lter............
> .  0040:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
> [...]
> .  0110:  74 65 73 74 5f 76 61 6c 75 65 00 00 00 00 00 00  test_value......
> .  0120:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
> [...]
> .  0150:  34 32 00 00 00 00 00 00 00 00 00 00 00 00 00 00  42..............
> .  0160:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
> [...]
>
> 0 0x50fc8 [0x260]: PERF_RECORD_BPF_METADATA \
>       prog bpf_prog_1e0a2e366e56f1a2_perf_sample_filter
>   entry 0:           test_value = 42
> : unhandled!
>
> Signed-off-by: Blake Jones <blakejones@...gle.com>
> ---
>  tools/perf/builtin-inject.c                  |  1 +
>  tools/perf/builtin-record.c                  |  8 +++
>  tools/perf/builtin-script.c                  | 15 ++++-
>  tools/perf/tests/shell/test_bpf_metadata.sh  | 67 ++++++++++++++++++++
>  tools/perf/util/bpf-event.c                  | 46 ++++++++++++++
>  tools/perf/util/bpf-event.h                  |  1 +
>  tools/perf/util/bpf_skel/sample_filter.bpf.c |  4 ++
>  tools/perf/util/env.c                        | 19 +++++-
>  tools/perf/util/env.h                        |  4 ++
>  tools/perf/util/event.c                      | 21 ++++++
>  tools/perf/util/event.h                      |  1 +
>  tools/perf/util/header.c                     |  1 +
>  tools/perf/util/session.c                    |  4 ++
>  tools/perf/util/synthetic-events.h           |  2 +
>  tools/perf/util/tool.c                       | 14 ++++
>  tools/perf/util/tool.h                       |  3 +-
>  16 files changed, 207 insertions(+), 4 deletions(-)
>  create mode 100644 tools/perf/tests/shell/test_bpf_metadata.sh
>
> diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
> index 11e49cafa3af..b15eac0716f7 100644
> --- a/tools/perf/builtin-inject.c
> +++ b/tools/perf/builtin-inject.c
> @@ -2530,6 +2530,7 @@ int cmd_inject(int argc, const char **argv)
>         inject.tool.finished_init       = perf_event__repipe_op2_synth;
>         inject.tool.compressed          = perf_event__repipe_op4_synth;
>         inject.tool.auxtrace            = perf_event__repipe_auxtrace;
> +       inject.tool.bpf_metadata        = perf_event__repipe_op2_synth;
>         inject.tool.dont_split_sample_group = true;
>         inject.session = __perf_session__new(&data, &inject.tool,
>                                              /*trace_event_repipe=*/inject.output.is_pipe);
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 136c0172799a..067e203f57c2 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -2161,6 +2161,12 @@ static int record__synthesize(struct record *rec, bool tail)
>         return err;
>  }
>
> +static void record__synthesize_final_bpf_metadata(struct record *rec)
> +{
> +       perf_event__synthesize_final_bpf_metadata(rec->session,
> +                                                 process_synthesized_event);
> +}
> +
>  static int record__process_signal_event(union perf_event *event __maybe_unused, void *data)
>  {
>         struct record *rec = data;
> @@ -2806,6 +2812,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/builtin-script.c b/tools/perf/builtin-script.c
> index 6c3bf74dd78c..4001e621b6cb 100644
> --- a/tools/perf/builtin-script.c
> +++ b/tools/perf/builtin-script.c
> @@ -38,6 +38,7 @@
>  #include "print_insn.h"
>  #include "archinsn.h"
>  #include <linux/bitmap.h>
> +#include <linux/compiler.h>
>  #include <linux/kernel.h>
>  #include <linux/stringify.h>
>  #include <linux/time64.h>
> @@ -50,6 +51,7 @@
>  #include <errno.h>
>  #include <inttypes.h>
>  #include <signal.h>
> +#include <stdio.h>
>  #include <sys/param.h>
>  #include <sys/types.h>
>  #include <sys/stat.h>
> @@ -2755,6 +2757,14 @@ process_bpf_events(const struct perf_tool *tool __maybe_unused,
>                            sample->tid);
>  }
>
> +static int
> +process_bpf_metadata_event(struct perf_session *session __maybe_unused,
> +                          union perf_event *event)
> +{
> +       perf_event__fprintf(event, NULL, stdout);
> +       return 0;
> +}
> +
>  static int process_text_poke_events(const struct perf_tool *tool,
>                                     union perf_event *event,
>                                     struct perf_sample *sample,
> @@ -2877,8 +2887,9 @@ static int __cmd_script(struct perf_script *script)
>                 script->tool.finished_round = process_finished_round_event;
>         }
>         if (script->show_bpf_events) {
> -               script->tool.ksymbol = process_bpf_events;
> -               script->tool.bpf     = process_bpf_events;
> +               script->tool.ksymbol      = process_bpf_events;
> +               script->tool.bpf          = process_bpf_events;
> +               script->tool.bpf_metadata = process_bpf_metadata_event;
>         }
>         if (script->show_text_poke_events) {
>                 script->tool.ksymbol   = process_bpf_events;
> diff --git a/tools/perf/tests/shell/test_bpf_metadata.sh b/tools/perf/tests/shell/test_bpf_metadata.sh
> new file mode 100644
> index 000000000000..ede31d5a3c36
> --- /dev/null
> +++ b/tools/perf/tests/shell/test_bpf_metadata.sh
> @@ -0,0 +1,67 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# BPF metadata collection test.
> +
> +set -e
> +
> +err=0
> +perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX)
> +
> +cleanup() {
> +       rm -f "${perfdata}"
> +       rm -f "${perfdata}".old
> +       trap - EXIT TERM INT
> +}
> +
> +trap_cleanup() {
> +       cleanup
> +       exit 1
> +}
> +trap trap_cleanup EXIT TERM INT
> +
> +test_bpf_metadata() {
> +       echo "Checking BPF metadata collection"
> +
> +       # This is a basic invocation of perf record
> +       # that invokes the perf_sample_filter BPF program.
> +       if ! perf record -e task-clock --filter 'ip > 0' \
> +                        -o "${perfdata}" sleep 1 2> /dev/null
> +       then
> +               echo "Basic BPF metadata test [Failed record]"
> +               err=1
> +               return
> +       fi
> +
> +       # The perf_sample_filter BPF program has the following variable in it:
> +       #
> +       #   volatile const int bpf_metadata_test_value SEC(".rodata") = 42;
> +       #
> +       # This invocation looks for a PERF_RECORD_BPF_METADATA event,
> +       # and checks that its content includes something for the above variable.
> +       if ! perf script --show-bpf-events -i "${perfdata}" | awk '
> +               /PERF_RECORD_BPF_METADATA.*perf_sample_filter/ {
> +                       header = 1;
> +               }
> +               /^ *entry/ {
> +                       if (header) { header = 0; entry = 1; }
> +               }
> +               $0 !~ /^ *entry/ {
> +                       entry = 0;
> +               }
> +               /test_value/ {
> +                       if (entry) print $NF;
> +               }
> +       ' | grep 42 > /dev/null
> +       then
> +               echo "Basic BPF metadata test [Failed invalid output]"
> +               err=1
> +               return
> +       fi
> +       echo "Basic BPF metadata test [Success]"
> +}
> +
> +test_bpf_metadata
> +
> +cleanup
> +exit $err
> diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c
> index 36d5676f025e..019832ec4802 100644
> --- a/tools/perf/util/bpf-event.c
> +++ b/tools/perf/util/bpf-event.c
> @@ -450,6 +450,49 @@ static int synthesize_perf_record_bpf_metadata(const struct bpf_metadata *metada
>         return err;
>  }
>
> +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
> @@ -590,6 +633,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);
> @@ -781,6 +825,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)) {
> @@ -793,6 +838,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 007f0b4d21cb..49a42c15bcc6 100644
> --- a/tools/perf/util/bpf-event.h
> +++ b/tools/perf/util/bpf-event.h
> @@ -26,6 +26,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/bpf_skel/sample_filter.bpf.c b/tools/perf/util/bpf_skel/sample_filter.bpf.c
> index b195e6efeb8b..b0265f000325 100644
> --- a/tools/perf/util/bpf_skel/sample_filter.bpf.c
> +++ b/tools/perf/util/bpf_skel/sample_filter.bpf.c
> @@ -43,6 +43,10 @@ struct lost_count {
>         __uint(max_entries, 1);
>  } dropped SEC(".maps");
>
> +// This is used by tests/shell/record_bpf_metadata.sh
> +// to verify that BPF metadata generation works.
> +const int bpf_metadata_test_value SEC(".rodata") = 42;

This is a bit random. For the non-BPF C code we have a build generated
PERF-VERSION-FILE that contains something like `#define PERF_VERSION
"6.15.rc7.ge450e74276d2"`. I wonder having something like (the section
is almost certainly wrong):
```
volatile const char * const bpf_metadata_perf_version
__attribute__((section(\".rodata\"), used, weak)) = PERF_VERSION;
```
with a build change something like:
```
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d4c7031b01a7..f825d9195d77 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -1250,9 +1250,9 @@ else
       $(Q)cp "$(VMLINUX_H)" $@
endif

-$(SKEL_TMP_OUT)/%.bpf.o: util/bpf_skel/%.bpf.c $(LIBBPF)
$(SKEL_OUT)/vmlinux.h | $(SKEL_TMP_OUT)
+$(SKEL_TMP_OUT)/%.bpf.o: util/bpf_skel/%.bpf.c $(LIBBPF)
$(OUTPUT)PERF-VERSION-FILE $(SKEL_OUT)/vml
inux.h | $(SKEL_TMP_OUT)
       $(QUIET_CLANG)$(CLANG) -g -O2 --target=bpf $(CLANG_OPTIONS)
$(BPF_INCLUDE) $(TOOLS_UAPI_INCL
UDE) \
-         -c $(filter util/bpf_skel/%.bpf.c,$^) -o $@
+         -include $(OUTPUT)PERF-VERSION-FILE -c $(filter
util/bpf_skel/%.bpf.c,$^) -o $@

$(SKEL_OUT)/%.skel.h: $(SKEL_TMP_OUT)/%.bpf.o | $(BPFTOOL)
       $(QUIET_GENSKEL)$(BPFTOOL) gen skeleton $< > $@

```
would be more useful/meaningful. Perhaps the build could inject the
variable to avoid duplicating it all the BPF skeletons.

nit: I wonder for testing it would be interesting to have 0 and >1
metadata values tested too. We may want to have test programs
explicitly for that, in tools/perf/tests.

Thanks,
Ian


> +
>  volatile const int use_idx_hash;
>
>  void *bpf_cast_to_kern_ctx(void *) __ksym;
> 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 @@ struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
>         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..6819cb9b99ff 100644
> --- a/tools/perf/util/env.h
> +++ b/tools/perf/util/env.h
> @@ -180,6 +180,10 @@ 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);
> diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
> index 80c9ea682413..e81c2d87d76a 100644
> --- a/tools/perf/util/event.c
> +++ b/tools/perf/util/event.c
> @@ -1,9 +1,12 @@
>  #include <errno.h>
>  #include <fcntl.h>
>  #include <inttypes.h>
> +#include <linux/compiler.h>
>  #include <linux/kernel.h>
>  #include <linux/types.h>
>  #include <perf/cpumap.h>
> +#include <perf/event.h>
> +#include <stdio.h>
>  #include <sys/types.h>
>  #include <sys/stat.h>
>  #include <unistd.h>
> @@ -78,6 +81,7 @@ static const char *perf_event__names[] = {
>         [PERF_RECORD_COMPRESSED]                = "COMPRESSED",
>         [PERF_RECORD_FINISHED_INIT]             = "FINISHED_INIT",
>         [PERF_RECORD_COMPRESSED2]               = "COMPRESSED2",
> +       [PERF_RECORD_BPF_METADATA]              = "BPF_METADATA",
>  };
>
>  const char *perf_event__name(unsigned int id)
> @@ -504,6 +508,20 @@ size_t perf_event__fprintf_bpf(union perf_event *event, FILE *fp)
>                        event->bpf.type, event->bpf.flags, event->bpf.id);
>  }
>
> +size_t perf_event__fprintf_bpf_metadata(union perf_event *event, FILE *fp)
> +{
> +       struct perf_record_bpf_metadata *metadata = &event->bpf_metadata;
> +       size_t ret;
> +
> +       ret = fprintf(fp, " prog %s\n", metadata->prog_name);
> +       for (__u32 i = 0; i < metadata->nr_entries; i++) {
> +               ret += fprintf(fp, "  entry %d: %20s = %s\n", i,
> +                              metadata->entries[i].key,
> +                              metadata->entries[i].value);
> +       }
> +       return ret;
> +}
> +
>  static int text_poke_printer(enum binary_printer_ops op, unsigned int val,
>                              void *extra, FILE *fp)
>  {
> @@ -601,6 +619,9 @@ size_t perf_event__fprintf(union perf_event *event, struct machine *machine, FIL
>         case PERF_RECORD_AUX_OUTPUT_HW_ID:
>                 ret += perf_event__fprintf_aux_output_hw_id(event, fp);
>                 break;
> +       case PERF_RECORD_BPF_METADATA:
> +               ret += perf_event__fprintf_bpf_metadata(event, fp);
> +               break;
>         default:
>                 ret += fprintf(fp, "\n");
>         }
> diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
> index 664bf39567ce..67ad4a2014bc 100644
> --- a/tools/perf/util/event.h
> +++ b/tools/perf/util/event.h
> @@ -370,6 +370,7 @@ size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp);
>  size_t perf_event__fprintf_cgroup(union perf_event *event, FILE *fp);
>  size_t perf_event__fprintf_ksymbol(union perf_event *event, FILE *fp);
>  size_t perf_event__fprintf_bpf(union perf_event *event, FILE *fp);
> +size_t perf_event__fprintf_bpf_metadata(union perf_event *event, FILE *fp);
>  size_t perf_event__fprintf_text_poke(union perf_event *event, struct machine *machine,FILE *fp);
>  size_t perf_event__fprintf(union perf_event *event, struct machine *machine, FILE *fp);
>
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index e3cdc3b7b4ab..7c477e2a93b3 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -3161,6 +3161,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/session.c b/tools/perf/util/session.c
> index a320672c264e..38075059086c 100644
> --- a/tools/perf/util/session.c
> +++ b/tools/perf/util/session.c
> @@ -12,6 +12,7 @@
>  #include <sys/types.h>
>  #include <sys/mman.h>
>  #include <perf/cpumap.h>
> +#include <perf/event.h>
>
>  #include "map_symbol.h"
>  #include "branch.h"
> @@ -1491,6 +1492,9 @@ static s64 perf_session__process_user_event(struct perf_session *session,
>         case PERF_RECORD_FINISHED_INIT:
>                 err = tool->finished_init(session, event);
>                 break;
> +       case PERF_RECORD_BPF_METADATA:
> +               err = tool->bpf_metadata(session, event);
> +               break;
>         default:
>                 err = -EINVAL;
>                 break;
> 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);
>
> diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c
> index 37bd8ac63b01..204ec03071bc 100644
> --- a/tools/perf/util/tool.c
> +++ b/tools/perf/util/tool.c
> @@ -1,12 +1,15 @@
>  // SPDX-License-Identifier: GPL-2.0
>  #include "data.h"
>  #include "debug.h"
> +#include "event.h"
>  #include "header.h"
>  #include "session.h"
>  #include "stat.h"
>  #include "tool.h"
>  #include "tsc.h"
> +#include <linux/compiler.h>
>  #include <sys/mman.h>
> +#include <stddef.h>
>  #include <unistd.h>
>
>  #ifdef HAVE_ZSTD_SUPPORT
> @@ -237,6 +240,16 @@ static int perf_session__process_compressed_event_stub(struct perf_session *sess
>         return 0;
>  }
>
> +static int perf_event__process_bpf_metadata_stub(struct perf_session *perf_session __maybe_unused,
> +                                                union perf_event *event)
> +{
> +       if (dump_trace)
> +               perf_event__fprintf_bpf_metadata(event, stdout);
> +
> +       dump_printf(": unhandled!\n");
> +       return 0;
> +}
> +
>  void perf_tool__init(struct perf_tool *tool, bool ordered_events)
>  {
>         tool->ordered_events = ordered_events;
> @@ -293,6 +306,7 @@ void perf_tool__init(struct perf_tool *tool, bool ordered_events)
>         tool->compressed = perf_session__process_compressed_event_stub;
>  #endif
>         tool->finished_init = process_event_op2_stub;
> +       tool->bpf_metadata = perf_event__process_bpf_metadata_stub;
>  }
>
>  bool perf_tool__compressed_is_stub(const struct perf_tool *tool)
> diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
> index db1c7642b0d1..18b76ff0f26a 100644
> --- a/tools/perf/util/tool.h
> +++ b/tools/perf/util/tool.h
> @@ -77,7 +77,8 @@ struct perf_tool {
>                         stat,
>                         stat_round,
>                         feature,
> -                       finished_init;
> +                       finished_init,
> +                       bpf_metadata;
>         event_op4       compressed;
>         event_op3       auxtrace;
>         bool            ordered_events;
> --
> 2.49.0.1143.g0be31eac6b-goog
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ