All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers
  2026-06-16  1:31 [PATCHES 0/2] perf tools: Add cached probe type detection for evsel Arnaldo Carvalho de Melo
@ 2026-06-16  1:31 ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-06-16  1:31 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
	Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users,
	Arnaldo Carvalho de Melo, Claude Opus 4.6

From: Arnaldo Carvalho de Melo <acme@redhat.com>

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 2-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.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evsel.c | 44 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/evsel.h |  5 +++++
 2 files changed, 49 insertions(+)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 05fa0010c858a51e..223571091f09f9ee 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -254,6 +254,49 @@ 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,
+};
+
+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
+		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 +456,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)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 8009be22cc3f1055..bf75381526147f92 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -126,6 +126,7 @@ struct evsel {
 	bool			needs_uniquify;
 	bool			fallenback_eacces;
 	bool			fallenback_eopnotsupp;
+	u8			probe_type:2;
 	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)
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers
  2026-06-16 15:44 [PATCHES v2 0/2] perf tools: Add cached probe type detection for evsel Arnaldo Carvalho de Melo
@ 2026-06-16 15:44 ` Arnaldo Carvalho de Melo
  2026-06-16 16:03   ` sashiko-bot
  0 siblings, 1 reply; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-06-16 15:44 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
	Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users,
	Arnaldo Carvalho de Melo, Claude Opus 4.6

From: Arnaldo Carvalho de Melo <acme@redhat.com>

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.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evsel.c | 53 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/evsel.h |  5 ++++
 2 files changed, 58 insertions(+)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 05fa0010c858a51e..ea9fa04429f08a9e 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -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)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 8009be22cc3f1055..300c64d1e0c15e7d 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -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)
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers
  2026-06-16 15:44 ` [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers Arnaldo Carvalho de Melo
@ 2026-06-16 16:03   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-06-16 16:03 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Calling `evsel__field()` unconditionally without a `HAVE_LIBTRACEEVENT` feature guard or fallback stub causes linker errors when libtraceevent is omitted.
--

commit 1f0d622399b5f71c138cdc45ef059e320a38fea7
Author: Arnaldo Carvalho de Melo <acme@redhat.com>

perf evsel: Add lazy-initialized probe type detection helpers

This commit adds helpers to lazily detect and cache whether an evsel is a
kprobe, uprobe, or ftrace-based dynamic probe. It introduces a 3-bit
probe_type field in struct evsel to avoid repeated PMU lookups.

> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> --- a/tools/perf/util/evsel.c
> +++ b/tools/perf/util/evsel.c
[ ... ]
> +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"))

[Severity: High]
Will this cause a linker error when compiling without libtraceevent?

This unconditionally calls evsel__field. The actual implementation of
evsel__field is strictly wrapped in HAVE_LIBTRACEEVENT guards. Without a
fallback stub in tools/perf/util/evsel.h that returns NULL for the
!HAVE_LIBTRACEEVENT case, omitting libtraceevent could cause an undefined
reference error during linking since evsel__is_probe prevents dead-code
elimination of this function.

> +		evsel->probe_type = PROBE__FTRACE;
> +	else
> +		evsel->probe_type = PROBE__NOPE;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260616154446.7206-1-acme@kernel.org?part=1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCHES v3 0/2] perf tools: Add cached probe type detection for evsel
@ 2026-06-16 18:25 Arnaldo Carvalho de Melo
  2026-06-16 18:25 ` [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers Arnaldo Carvalho de Melo
  2026-06-16 18:25 ` [PATCH 2/2] perf trace: Guard __probe_ip suppression with evsel__is_probe() Arnaldo Carvalho de Melo
  0 siblings, 2 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-06-16 18:25 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
	Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users,
	Arnaldo Carvalho de Melo, Aaron Tomlin

Hi,

Checking whether an evsel is a kprobe or uprobe currently requires
walking the PMU list via evsel__find_pmu() on every call.  This is
wasteful when the same evsel is checked repeatedly in hot paths like
trace__fprintf_tp_fields().

Patch 1 adds evsel__is_kprobe(), evsel__is_uprobe(), and
evsel__is_probe() helpers that resolve the probe type on first call
and cache the result in a 3-bit field that fits in existing struct
padding.

Detection covers both PMU-based probes (kprobe/uprobe PMU, detected
by PMU name) and ftrace-based dynamic probes (kprobes/uprobes/fprobes
created via tracefs, which report as PMU "tracepoint").  Ftrace probes
are detected by the __probe_ip field that the kernel adds to all
dynamic probe formats — this is authoritative regardless of the
group/system name the user chose.

Patch 2 is the first user: it guards the __probe_ip field name
comparison in perf trace with evsel__is_probe(), so the strcmp is
skipped entirely for the common case of non-probe tracepoint events.

Patch 3 adds inline stubs for evsel__field() and evsel__common_field()
when libtraceevent is absent.  These were previously declared
unconditionally but defined only inside #ifdef HAVE_LIBTRACEEVENT,
which was harmless until patch 1 added a call from always-compiled
code in evsel.c.

Build-tested with gcc and clang.

Changes in v3:
  - Add patch 3: no-libtraceevent stubs for evsel__field() and
    evsel__common_field().  Without this, NO_LIBTRACEEVENT=1 builds
    fail to link because evsel__resolve_probe_type() calls
    evsel__field() unconditionally (sashiko-bot).

Changes in v2 (patch 1 only):
  - Detect ftrace-based dynamic probes (kprobes/uprobes/fprobes created
    via tracefs) that report PMU "tracepoint" instead of "kprobe"/
    "uprobe".  Check for the __probe_ip field presence in the tracepoint
    format.  Without this, evsel__is_probe() returned false for ftrace
    probes, breaking __probe_ip suppression in perf trace for probes
    created via 'perf probe' (sashiko-bot).
  - Widen probe_type bitfield from 2 to 3 bits for PROBE__FTRACE.

Arnaldo Carvalho de Melo (3):
  perf evsel: Add lazy-initialized probe type detection helpers
  perf trace: Guard __probe_ip suppression with evsel__is_probe()
  perf evsel: Add no-libtraceevent stubs for evsel__field() and evsel__common_field()

 tools/perf/builtin-trace.c |  2 +-
 tools/perf/util/evsel.c    | 53 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/evsel.h    | 19 +++++++++++++++++
 3 files changed, 73 insertions(+), 1 deletion(-)

Cc: Aaron Tomlin <atomlin@atomlin.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Namhyung Kim <namhyung@kernel.org>

Developed with AI assistance (Claude/sashiko), tagged in commits.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers
  2026-06-16 18:25 [PATCHES v3 0/2] perf tools: Add cached probe type detection for evsel Arnaldo Carvalho de Melo
@ 2026-06-16 18:25 ` Arnaldo Carvalho de Melo
  2026-06-16 18:40   ` sashiko-bot
  2026-06-16 18:25 ` [PATCH 2/2] perf trace: Guard __probe_ip suppression with evsel__is_probe() Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-06-16 18:25 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
	Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users,
	Arnaldo Carvalho de Melo, Claude Opus 4.6

From: Arnaldo Carvalho de Melo <acme@redhat.com>

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.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evsel.c | 53 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/evsel.h | 19 +++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 05fa0010c858a51e..ea9fa04429f08a9e 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -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)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 8009be22cc3f1055..163fc2b6a7eacca4 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -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)
@@ -397,8 +402,22 @@ struct tep_format_field;
 
 u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, bool needs_swap);
 
+#ifdef HAVE_LIBTRACEEVENT
 struct tep_format_field *evsel__field(struct evsel *evsel, const char *name);
 struct tep_format_field *evsel__common_field(struct evsel *evsel, const char *name);
+#else
+static inline struct tep_format_field *
+evsel__field(struct evsel *evsel __maybe_unused, const char *name __maybe_unused)
+{
+	return NULL;
+}
+
+static inline struct tep_format_field *
+evsel__common_field(struct evsel *evsel __maybe_unused, const char *name __maybe_unused)
+{
+	return NULL;
+}
+#endif
 
 bool __evsel__match(const struct evsel *evsel, u32 type, u64 config);
 
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] perf trace: Guard __probe_ip suppression with evsel__is_probe()
  2026-06-16 18:25 [PATCHES v3 0/2] perf tools: Add cached probe type detection for evsel Arnaldo Carvalho de Melo
  2026-06-16 18:25 ` [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers Arnaldo Carvalho de Melo
@ 2026-06-16 18:25 ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-06-16 18:25 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
	Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users,
	Arnaldo Carvalho de Melo, Aaron Tomlin, Claude

From: Arnaldo Carvalho de Melo <acme@redhat.com>

trace__fprintf_tp_fields() compares every field name against
"__probe_ip" for all tracepoint events, but this field is only
implicitly added by the Ftrace subsystem to bare dynamic probes.

Add an evsel__is_probe() check before the strcmp so the string
comparison is skipped entirely for non-probe events.

Reviewed-by: Aaron Tomlin <atomlin@atomlin.com>
Assisted-by: Claude <noreply@anthropic.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-trace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index a8492da23a9cc178..57f3f14c5d435805 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -3267,7 +3267,7 @@ static size_t trace__fprintf_tp_fields(struct trace *trace, struct perf_sample *
 		 * If verbose mode is enabled, ensure it is formatted as a
 		 * hexadecimal memory address rather than a signed integer.
 		 */
-		if (!strcmp(field->name, "__probe_ip")) {
+		if (evsel__is_probe(evsel) && !strcmp(field->name, "__probe_ip")) {
 			if (!verbose)
 				continue;
 
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers
  2026-06-16 18:25 ` [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers Arnaldo Carvalho de Melo
@ 2026-06-16 18:40   ` sashiko-bot
  2026-06-16 18:47     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 8+ messages in thread
From: sashiko-bot @ 2026-06-16 18:40 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Ftrace-based return probes (kretprobe, uretprobe, fexit) are incorrectly classified as PROBE__NOPE because they lack the __probe_ip field.
--

commit fc58c48524e7c99a712f8fb111c94abfbbeb4b6d
Author: Arnaldo Carvalho de Melo <acme@redhat.com>

perf evsel: Add lazy-initialized probe type detection helpers

This commit introduces lazy-initialized probe type detection helpers for
perf evsel. It caches the probe type lookup in a 3-bit field within struct
evsel to avoid repeated PMU list walks via evsel__find_pmu().

> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> index 05fa0010c858a..ea9fa04429f08 100644
> --- a/tools/perf/util/evsel.c
> +++ b/tools/perf/util/evsel.c

[ ... ]

> @@ -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"))

[Severity: Medium]
The commit message mentions this covers kprobes, uprobes, and fprobes
regardless of their group or system name by checking the __probe_ip field.
Will this successfully detect ftrace-based return probes?

It looks like return probes like kretprobe, uretprobe, and fexit do not
contain a __probe_ip field, but instead define __probe_func and
__probe_ret_ip.

If evsel__field() returns NULL for return probes, won't they incorrectly
fall through to the else branch and be classified as PROBE__NOPE?

> +		evsel->probe_type = PROBE__FTRACE;
> +	else
> +		evsel->probe_type = PROBE__NOPE;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260616182546.8892-1-acme@kernel.org?part=1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers
  2026-06-16 18:40   ` sashiko-bot
@ 2026-06-16 18:47     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 8+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-06-16 18:47 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: linux-perf-users

On Tue, Jun 16, 2026 at 06:40:05PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] Ftrace-based return probes (kretprobe, uretprobe, fexit) are incorrectly classified as PROBE__NOPE because they lack the __probe_ip field.
> --
> 
> commit fc58c48524e7c99a712f8fb111c94abfbbeb4b6d
> Author: Arnaldo Carvalho de Melo <acme@redhat.com>
> 
> perf evsel: Add lazy-initialized probe type detection helpers
> 
> This commit introduces lazy-initialized probe type detection helpers for
> perf evsel. It caches the probe type lookup in a 3-bit field within struct
> evsel to avoid repeated PMU list walks via evsel__find_pmu().
> 
> > diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> > index 05fa0010c858a..ea9fa04429f08 100644
> > --- a/tools/perf/util/evsel.c
> > +++ b/tools/perf/util/evsel.c
> 
> [ ... ]
> 
> > @@ -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"))
> 
> [Severity: Medium]
> The commit message mentions this covers kprobes, uprobes, and fprobes
> regardless of their group or system name by checking the __probe_ip field.
> Will this successfully detect ftrace-based return probes?
> 
> It looks like return probes like kretprobe, uretprobe, and fexit do not
> contain a __probe_ip field, but instead define __probe_func and
> __probe_ret_ip.
> 
> If evsel__field() returns NULL for return probes, won't they incorrectly
> fall through to the else branch and be classified as PROBE__NOPE?

Sure, and this is an interesting observation, we need to cover
__probe_ret_ip in the same fashion as __probe_ip, probably __probe_func
as well, but this should be done in an upcoming patch series.

I'll make sure to save this in a TODO file for later work.

- Arnaldo
 
> > +		evsel->probe_type = PROBE__FTRACE;
> > +	else
> > +		evsel->probe_type = PROBE__NOPE;
> > +}
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/20260616182546.8892-1-acme@kernel.org?part=1

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-06-16 18:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-16 18:25 [PATCHES v3 0/2] perf tools: Add cached probe type detection for evsel Arnaldo Carvalho de Melo
2026-06-16 18:25 ` [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers Arnaldo Carvalho de Melo
2026-06-16 18:40   ` sashiko-bot
2026-06-16 18:47     ` Arnaldo Carvalho de Melo
2026-06-16 18:25 ` [PATCH 2/2] perf trace: Guard __probe_ip suppression with evsel__is_probe() Arnaldo Carvalho de Melo
  -- strict thread matches above, loose matches on Subject: below --
2026-06-16 15:44 [PATCHES v2 0/2] perf tools: Add cached probe type detection for evsel Arnaldo Carvalho de Melo
2026-06-16 15:44 ` [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers Arnaldo Carvalho de Melo
2026-06-16 16:03   ` sashiko-bot
2026-06-16  1:31 [PATCHES 0/2] perf tools: Add cached probe type detection for evsel Arnaldo Carvalho de Melo
2026-06-16  1:31 ` [PATCH 1/2] perf evsel: Add lazy-initialized probe type detection helpers Arnaldo Carvalho de Melo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.