summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Turner <mattst88@gmail.com>2026-09-08 22:50:35 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2026-09-09 17:00:36 -0300
commit0b568c865fac195e90f4669bde5af0e236830af2 (patch)
tree3aa9e61e87607ecaf3c7156ba55674066d440ee5
parentb245a18823027c372b4aebb866129368c2ecd3f5 (diff)
downloadlinux-next-0b568c865fac195e90f4669bde5af0e236830af2.tar.gz
linux-next-0b568c865fac195e90f4669bde5af0e236830af2.zip
perf tools: make the GTK4 report browser actually loadable at runtime
perf report --gtk dlopen()s libperf-gtk.so, which expects to resolve symbols back against the running perf binary (callchain_param, symbol_conf, evsel__name, and friends live in perf, not the plugin). Two things broke that after the GTK 4 port: perf never passed -rdynamic, so none of its symbols were in its dynamic symbol table for a dlopen()ed plugin to find. Add -rdynamic to LDFLAGS when GTK4 support is enabled. annotated_source__hist_entry() was a static inline in annotate.h, so ui/gtk/annotate.c calling it pulled hashmap__find()'s expansion, hashmap_find(), into libperf-gtk.so as an undefined symbol. The only hashmap_find perf links against normally is libbpf's internal one (tools/lib/bpf/hashmap.c), built with -fvisibility=hidden, so it can never be exported to a dlopen()ed plugin regardless of LDFLAGS. Move annotated_source__hist_entry() into annotate.c as an ordinary exported function, so the plugin depends on it the same way it already depends on evsel__group_desc() and friends. With both fixes, a default 'make GTK4=1' build (libbpf statically linked) can dlopen() libperf-gtk.so and open the report browser without NO_LIBBPF=1 or manual LDFLAGS. Verified with perf report --gtk against real perf.data on a GTK4 desktop. Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Matt Turner <mattst88@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Makefile.config5
-rw-r--r--tools/perf/util/annotate.c11
-rw-r--r--tools/perf/util/annotate.h12
3 files changed, 18 insertions, 10 deletions
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 3e59e2b7eaec..4ee7393a39f9 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -785,6 +785,11 @@ ifdef GTK4
GTK_CFLAGS += $(shell $(PKG_CONFIG) --cflags gtk4 2>/dev/null)
GTK_LIBS := $(shell $(PKG_CONFIG) --libs gtk4 2>/dev/null)
EXTLIBS += -ldl
+ # libperf-gtk.so is dlopen()ed at runtime and calls back into
+ # symbols defined in the perf binary itself (callchain_param,
+ # symbol_conf, evsel__name, ...): perf needs to export those
+ # dynamically for the plugin to resolve them.
+ LDFLAGS += -rdynamic
endif
endif
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 9304c21c686a..fd789eb53e74 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -145,6 +145,17 @@ static int annotated_source__alloc_histograms(struct annotated_source *src,
return src->histograms ? 0 : -1;
}
+struct sym_hist_entry *
+annotated_source__hist_entry(struct annotated_source *src, const struct evsel *evsel, u64 offset)
+{
+ struct sym_hist_entry *entry;
+ long key = offset << 16 | evsel->core.idx;
+
+ if (!hashmap__find(src->samples, key, &entry))
+ return NULL;
+ return entry;
+}
+
void symbol__annotate_zero_histograms(struct symbol *sym)
{
struct annotation *notes = symbol__annotation(sym);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index d7807df6667f..4c49d41e73a4 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -446,16 +446,8 @@ static inline struct sym_hist *annotation__histogram(struct annotation *notes,
return annotated_source__histogram(notes->src, evsel);
}
-static inline struct sym_hist_entry *
-annotated_source__hist_entry(struct annotated_source *src, const struct evsel *evsel, u64 offset)
-{
- struct sym_hist_entry *entry;
- long key = offset << 16 | evsel->core.idx;
-
- if (!hashmap__find(src->samples, key, &entry))
- return NULL;
- return entry;
-}
+struct sym_hist_entry *
+annotated_source__hist_entry(struct annotated_source *src, const struct evsel *evsel, u64 offset);
static inline struct annotation *symbol__annotation(struct symbol *sym)
{