]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf evsel: Add lazy-initialized probe type detection helpers
authorArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 16 Jun 2026 19:35:43 +0000 (16:35 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 16 Jun 2026 19:35:43 +0000 (16:35 -0300)
Several places in perf need to check whether an evsel is a kprobe or
uprobe, which requires looking up the PMU by name via evsel__find_pmu().
This lookup walks the PMU list each time, which is wasteful when the
same evsel is checked repeatedly.

Add evsel__is_kprobe(), evsel__is_uprobe(), and evsel__is_probe() that
resolve the probe type on first call via evsel__pmu_name() and cache
the result in a 3-bit field (probe_type) in struct evsel.  The field
fits in existing padding after the bool fields, so struct size does not
grow.

The enum uses PROBE__UNKNOWN (0) as the uninitialized sentinel —
explicitly set in evsel__init() — so the lookup happens on first use.
PROBE__NOPE (1) caches "not a probe" to avoid repeated negative lookups.

PMU-based probes (kprobe/uprobe PMU) are detected by PMU name.
Ftrace-based dynamic probes (created via tracefs, reported as PMU
"tracepoint") are detected by the __probe_ip field that the kernel
adds to all dynamic probe formats.  This covers kprobes, uprobes, and
fprobes regardless of their group/system name.

Cc: Aaron Tomlin <atomlin@atomlin.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/evsel.c
tools/perf/util/evsel.h

index 05fa0010c858a51e809082b90a0e0531f61889cb..ea9fa04429f08a9e1a594d24d768d8cdb4fffc2e 100644 (file)
@@ -254,6 +254,58 @@ const char *evsel__pmu_name(const struct evsel *evsel)
        return event_type(evsel->core.attr.type);
 }
 
+enum evsel_probe_type {
+       PROBE__UNKNOWN  = 0,
+       PROBE__NOPE     = 1,
+       PROBE__KPROBE   = 2,
+       PROBE__UPROBE   = 3,
+       /*
+        * Ftrace-based dynamic probes (kprobes/uprobes/fprobes created via
+        * tracefs) report PMU "tracepoint", not "kprobe"/"uprobe".  Detect
+        * them by the __probe_ip field that the kernel adds to all dynamic
+        * probe formats.
+        */
+       PROBE__FTRACE   = 4,
+};
+
+static void evsel__resolve_probe_type(struct evsel *evsel)
+{
+       const char *name = evsel__pmu_name(evsel);
+
+       if (!strcmp(name, "kprobe"))
+               evsel->probe_type = PROBE__KPROBE;
+       else if (!strcmp(name, "uprobe"))
+               evsel->probe_type = PROBE__UPROBE;
+       else if (!strcmp(name, "tracepoint") && evsel__field(evsel, "__probe_ip"))
+               evsel->probe_type = PROBE__FTRACE;
+       else
+               evsel->probe_type = PROBE__NOPE;
+}
+
+bool evsel__is_probe(struct evsel *evsel)
+{
+       if (evsel->probe_type == PROBE__UNKNOWN)
+               evsel__resolve_probe_type(evsel);
+
+       return evsel->probe_type > PROBE__NOPE;
+}
+
+bool evsel__is_kprobe(struct evsel *evsel)
+{
+       if (evsel->probe_type == PROBE__UNKNOWN)
+               evsel__resolve_probe_type(evsel);
+
+       return evsel->probe_type == PROBE__KPROBE;
+}
+
+bool evsel__is_uprobe(struct evsel *evsel)
+{
+       if (evsel->probe_type == PROBE__UNKNOWN)
+               evsel__resolve_probe_type(evsel);
+
+       return evsel->probe_type == PROBE__UPROBE;
+}
+
 #define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y))
 
 int __evsel__sample_size(u64 sample_type)
@@ -413,6 +465,7 @@ void evsel__init(struct evsel *evsel,
        evsel->supported     = true;
        evsel->alternate_hw_config = PERF_COUNT_HW_MAX;
        evsel->script_output_type = -1; // FIXME: OUTPUT_TYPE_UNSET, see builtin-script.c
+       evsel->probe_type = PROBE__UNKNOWN;
 }
 
 struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx)
index b959d4797b14035d30f9f535810055894b75c5eb..163fc2b6a7eacca4775e66d6167176acd8ad6c3a 100644 (file)
@@ -126,6 +126,7 @@ struct evsel {
        bool                    needs_uniquify;
        bool                    fallenback_eacces;
        bool                    fallenback_eopnotsupp;
+       u8                      probe_type:3;
        struct hashmap          *per_pkg_mask;
        int                     err;
        int                     script_output_type;
@@ -259,6 +260,10 @@ struct perf_pmu *evsel__find_pmu(const struct evsel *evsel);
 const char *evsel__pmu_name(const struct evsel *evsel);
 bool evsel__is_aux_event(const struct evsel *evsel);
 
+bool evsel__is_probe(struct evsel *evsel);
+bool evsel__is_kprobe(struct evsel *evsel);
+bool evsel__is_uprobe(struct evsel *evsel);
+
 struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx);
 
 static inline struct evsel *evsel__new(struct perf_event_attr *attr)