Re: [PATCH 1/2] perf thread: Fix live-session detection in thread__e_machine()

From: Ian Rogers

Date: Tue Sep 08 2026 - 13:53:13 EST


On Sat, Sep 5, 2026 at 3:54 PM Matt Turner <mattst88@xxxxxxxxx> wrote:
>
> 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@xxxxxxxxx>

Reviewed-by: Ian Rogers <irogers@xxxxxxxxxx>

Thanks!
Ian

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