]> git.ipfire.org Git - thirdparty/kernel/linux.git/blobdiff - tools/perf/util/bpf-event.c
perf bpf: Save bpf_prog_info in a rbtree in perf_env
[thirdparty/kernel/linux.git] / tools / perf / util / bpf-event.c
index 5237e8f119974b19693f8442cb29c2682dc5d65e..37ee4e2a728a5263fdb2db67bda67990a150d4d6 100644 (file)
@@ -10,6 +10,7 @@
 #include "debug.h"
 #include "symbol.h"
 #include "machine.h"
+#include "env.h"
 #include "session.h"
 
 #define ptr_to_u64(ptr)    ((__u64)(unsigned long)(ptr))
@@ -54,17 +55,28 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
        struct bpf_event *bpf_event = &event->bpf_event;
        struct bpf_prog_info_linear *info_linear;
        struct perf_tool *tool = session->tool;
+       struct bpf_prog_info_node *info_node;
        struct bpf_prog_info *info;
        struct btf *btf = NULL;
        bool has_btf = false;
+       struct perf_env *env;
        u32 sub_prog_cnt, i;
        int err = 0;
        u64 arrays;
 
+       /*
+        * for perf-record and perf-report use header.env;
+        * otherwise, use global perf_env.
+        */
+       env = session->data ? &session->header.env : &perf_env;
+
        arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS;
        arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS;
        arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO;
        arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS;
+       arrays |= 1UL << BPF_PROG_INFO_JITED_INSNS;
+       arrays |= 1UL << BPF_PROG_INFO_LINE_INFO;
+       arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO;
 
        info_linear = bpf_program__get_prog_info_linear(fd, arrays);
        if (IS_ERR_OR_NULL(info_linear)) {
@@ -153,8 +165,8 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
                                                     machine, process);
        }
 
-       /* Synthesize PERF_RECORD_BPF_EVENT */
        if (!opts->no_bpf_event) {
+               /* Synthesize PERF_RECORD_BPF_EVENT */
                *bpf_event = (struct bpf_event){
                        .header = {
                                .type = PERF_RECORD_BPF_EVENT,
@@ -167,6 +179,22 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
                memcpy(bpf_event->tag, info->tag, BPF_TAG_SIZE);
                memset((void *)event + event->header.size, 0, machine->id_hdr_size);
                event->header.size += machine->id_hdr_size;
+
+               /* save bpf_prog_info to env */
+               info_node = malloc(sizeof(struct bpf_prog_info_node));
+               if (!info_node) {
+                       err = -1;
+                       goto out;
+               }
+
+               info_node->info_linear = info_linear;
+               perf_env__insert_bpf_prog_info(env, info_node);
+               info_linear = NULL;
+
+               /*
+                * process after saving bpf_prog_info to env, so that
+                * required information is ready for look up
+                */
                err = perf_tool__process_synth_event(tool, event,
                                                     machine, process);
        }