mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
perf evsel: Add lazy-initialized probe type detection helpers
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>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user