summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Turner <mattst88@gmail.com>2026-09-05 18:54:11 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2026-09-08 18:08:37 -0300
commit15917a3a1ce0695f824892c8f9d0dc51408ee580 (patch)
treecb127cf171235495194dc6f2283235f026dbfbe1
parentee32ee73cc78a5068c571da2a71dd5f34b818058 (diff)
downloadlinux-next-15917a3a1ce0695f824892c8f9d0dc51408ee580.tar.gz
linux-next-15917a3a1ce0695f824892c8f9d0dc51408ee580.zip
perf thread: Fix live-session detection in thread__e_machine()
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: 70351029b55677eb ("perf thread: Add support for reading the e_machine type for a thread") Reviewed-by: Ian Rogers <irogers@google.com> Signed-off-by: Matt Turner <mattst88@gmail.com> Cc: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/machine.c1
-rw-r--r--tools/perf/util/thread.c2
2 files changed, 2 insertions, 1 deletions
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) {