[PATCH 1/2] perf thread: Fix live-session detection in thread__e_machine()
From: Matt Turner <mattst88@gmail.com>
Date: 2026-09-05 22:54:16
Also in:
lkml
Subsystem:
performance events subsystem, the rest · Maintainers:
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Linus Torvalds
When the per-thread e_machine cannot be determined from the DSOs in the
thread's maps, thread__e_machine_endian() decides between reading
/proc/<pid>/exe and falling back to the recorded session environment:
bool is_live = machine->machines == NULL;
if (!is_live) {
/* Check if the session has a data file. */
struct perf_session *session = container_of(...);
is_live = !!session->data;
}
Neither half of that works.
The back pointer added by commit a088031c4998 ("perf tools: Add machine to
machines back pointer") is set by machines__add(), which only ever adds
guests; the host machine never gets one. Host-machine threads, which is to
say almost all of them, therefore see machine->machines == NULL and are
declared live before the session is consulted at all.
The session test is also inverted. A session with a perf_data attached is
one being read from a perf.data file, i.e. exactly the case that is not
live, while a live session such as 'perf top' passes data=NULL to
__perf_session__new().
So a file-based session takes the live path and reads /proc/<pid>/exe on
the analysing host, which at best describes an unrelated process that has
since been given the recorded pid, and normally just fails, leaving
e_machine as EM_NONE. The perf_env fallback that would have supplied the
recorded architecture is never reached, and thread__e_machine() returns
EM_HOST.
For a same-architecture recording this is invisible, since EM_HOST is the
right answer anyway. Cross-architecture it is not: annotating an Alpha
perf.data on an x86_64 host selects the x86 struct arch, so the Alpha
disassembly is matched against the x86 instruction table. Alpha's 'ret'
collides with x86's and gets ret_ops, while its calls and branches match
nothing and are left unparsed, so no call target is resolved and no jump
arrows are drawn.
Set the back pointer for the host machine and correct the session test.
The new back pointer does not disturb the other reader of the field,
machine__findnew_guest_code(), which machine__resolve() only calls when
!machine__is_host(machine).
Fixes: 70351029b556 ("perf thread: Add support for reading the e_machine type for a thread")
Signed-off-by: Matt Turner <mattst88@gmail.com>
---
tools/perf/util/machine.c | 1 +
tools/perf/util/thread.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index f86b3b7df742..a1288fbed833 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c@@ -237,6 +237,7 @@ int machines__init(struct machines *machines) { int err = machine__init(&machines->host, "", HOST_KERNEL_ID); + machines->host.machines = machines; machines->guests = RB_ROOT_CACHED; return err; }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index e483ffcb5d93..f0d3773d87db 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c@@ -536,7 +536,7 @@ uint16_t thread__e_machine_endian(struct thread *thread, struct machine *machine struct perf_session, machines); - is_live = !!session->data; + is_live = !session->data; } /* Read from /proc/pid/exe if live. */ if (is_live) {
--
2.54.0