From nobody Mon Feb 9 00:53:39 2026 Received: from mail-dl1-f73.google.com (mail-dl1-f73.google.com [74.125.82.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F48132AAD4 for ; Sat, 17 Jan 2026 05:29:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768627779; cv=none; b=tpqtP/dv+Mq/uHxuWdXgjRjFfyyOsxiGia4Vz933VNP8EqVowLGdan0noLVg0klIOebWv2IGVAPA8FwY0kmpCJn/gjnULckS0pRWSv7mMZlws3SWUic/5orRYcEj/D/T2M2jFE9b4eDYE4GFhOZhpyM1lZ13pQntiOptiuC7gCs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768627779; c=relaxed/simple; bh=KYMlIYaO4TFVGe4X8XgmkKM5kQetl6AIq2SNvs1o89Q=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=r+dZyq3dk4gngGa7UEhoBdu+hp6Ip3jF4YXclw44RrzDQ4HGZi6RJoQeKRnqh7PqZEnPw0y6KWkC2pld87AxSkXzUtjjkhHrKa2rIHRmlYwlCtXjOu7n3j/i2Za+HVXR1zHiODB1yCc/9zZxHvyAy1ZWz+VnI4w2xmR/4b49KOo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=etkslVtf; arc=none smtp.client-ip=74.125.82.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="etkslVtf" Received: by mail-dl1-f73.google.com with SMTP id a92af1059eb24-11b94abc09dso5088555c88.1 for ; Fri, 16 Jan 2026 21:29:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1768627774; x=1769232574; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=1S66FILKRfXMvRmBPDp7wjeWNFb1HGCJm/Z2kIzT3UE=; b=etkslVtf+WabkqxmYU0hOpR+zkX8Vw5nHTrbcPa6GQt4QbTbomCCLjlP3qnQW3y/Bw 03hvruFfEqtgcK/11st2jj78BKjUgYA1opueROPJJ4VSA8u2iD34gacXcRZK1dEMqBq7 TYYTyniY+TE0DG3mkNRLlmf3oS3R1rfNnSTq0vCSyjqGQBNpWDypgEld4x2HHNyty7A1 OWWoVLzexmaLE2p2+qh3Y68dTKHNK2w8SXtkFJPZcieKXzzUjdP0fqhmoN+Scp259t5l djbXzoURbu9+wPvEITjIetiU3njp5uwSuYZp9UuP4wnUGFzdZHQZjld9A68GQUEW64Px Zggw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768627774; x=1769232574; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=1S66FILKRfXMvRmBPDp7wjeWNFb1HGCJm/Z2kIzT3UE=; b=HnYNrH8frVz9zRxFvgmfiK60PUDRH0MTwSvwlesZnfP1Jlv/GX4yla2AKtWFQj5akN XZdkcqEntnjvIb5xbD2b6+8+kgFEn+D2Ee2HzbuzSo9OdDDx/XvywkYQIYrAEe7KD/6y aJZAUVRnYhiL6UsmsOPJ6FwSl8SrgRVHFiUd9KpYRvITtufvcVCFiEtjQ2SIR+l+XDMU lvr5GxUt16aHg00Hqkvbm8AegNYyyoMwyvUt4BQlGgOOeTJ55q2hVBjlQnbWJPgJPL9w 6lSmO19sx1GogVvnAIqkLEOl76I443DEf2BOxjYF998y/UONhRxWAkKk8sTpYireilAs qM0A== X-Forwarded-Encrypted: i=1; AJvYcCW408+k+U3wNeCq4As21C909g1rXGBdwawNWmkz/95jB/MtlZkhBgKtbR0UbAHXIQsLuk+ipdwoSfl35Ro=@vger.kernel.org X-Gm-Message-State: AOJu0YzAUG3BfSw9NNfMg7IiAAspJ/lFZeu6J8fwz/XTdI2h8HsPhY1X +c84Qcrbx/gy0FnwbNTu3pFeBYyZW5S40OF6Utr4In8BnloWsea2KmEzMWFwTcE7vsTbpxm3rOY Wto77+W6gNg== X-Received: from dlag7.prod.google.com ([2002:a05:701b:2507:b0:11f:3043:2c7f]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:b93:b0:123:3508:893f with SMTP id a92af1059eb24-1244a765c10mr3680068c88.31.1768627774218; Fri, 16 Jan 2026 21:29:34 -0800 (PST) Date: Fri, 16 Jan 2026 21:28:34 -0800 In-Reply-To: <20260117052849.2205545-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260117052849.2205545-1-irogers@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260117052849.2205545-9-irogers@google.com> Subject: [PATCH v1 08/23] perf perf_regs: Switch from arch string to int e_machine From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark , John Garry , Will Deacon , Leo Yan , Guo Ren , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Shimin Guo , Athira Rajeev , Stephen Brennan , Howard Chu , Thomas Falcon , Andi Kleen , "Dr. David Alan Gilbert" , Dmitry Vyukov , "=?UTF-8?q?Krzysztof=20=C5=81opatowski?=" , Chun-Tse Shao , Aditya Bodkhe , Haibo Xu , Sergei Trofimovich , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-csky@vger.kernel.org, linux-riscv@lists.infradead.org, Mark Wielaard Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The arch string requires multiple strcmp to identify things like the IP and SP. Switch to passing in an e_machine that in the bulk of cases is computed using a current thread load. The e_machine also allows identification of 32-bit vs 64-bit processes. Signed-off-by: Ian Rogers --- tools/perf/builtin-script.c | 17 ++- tools/perf/util/evsel.c | 14 ++- tools/perf/util/perf_regs.c | 105 +++++++++++------- tools/perf/util/perf_regs.h | 10 +- .../scripting-engines/trace-event-python.c | 21 ++-- tools/perf/util/session.c | 65 ++++++++--- tools/perf/util/session.h | 1 + tools/perf/util/unwind-libdw.c | 12 +- tools/perf/util/unwind-libunwind-local.c | 7 +- 9 files changed, 164 insertions(+), 88 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 62e43d3c5ad7..372bede30230 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -717,7 +717,7 @@ static int perf_session__check_output_opt(struct perf_s= ession *session) return 0; } =20 -static int perf_sample__fprintf_regs(struct regs_dump *regs, uint64_t mask= , const char *arch, +static int perf_sample__fprintf_regs(struct regs_dump *regs, uint64_t mask= , uint16_t e_machine, FILE *fp) { unsigned i =3D 0, r; @@ -730,7 +730,7 @@ static int perf_sample__fprintf_regs(struct regs_dump *= regs, uint64_t mask, cons =20 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) { u64 val =3D regs->regs[i++]; - printed +=3D fprintf(fp, "%5s:0x%"PRIx64" ", perf_reg_name(r, arch), val= ); + printed +=3D fprintf(fp, "%5s:0x%"PRIx64" ", perf_reg_name(r, e_machine)= , val); } =20 return printed; @@ -787,23 +787,23 @@ tod_scnprintf(struct perf_script *script, char *buf, = int buflen, } =20 static int perf_sample__fprintf_iregs(struct perf_sample *sample, - struct perf_event_attr *attr, const char *arch, FILE *fp) + struct perf_event_attr *attr, uint16_t e_machine, FILE *fp) { if (!sample->intr_regs) return 0; =20 return perf_sample__fprintf_regs(perf_sample__intr_regs(sample), - attr->sample_regs_intr, arch, fp); + attr->sample_regs_intr, e_machine, fp); } =20 static int perf_sample__fprintf_uregs(struct perf_sample *sample, - struct perf_event_attr *attr, const char *arch, FILE *fp) + struct perf_event_attr *attr, uint16_t e_machine, FILE *fp) { if (!sample->user_regs) return 0; =20 return perf_sample__fprintf_regs(perf_sample__user_regs(sample), - attr->sample_regs_user, arch, fp); + attr->sample_regs_user, e_machine, fp); } =20 static int perf_sample__fprintf_start(struct perf_script *script, @@ -2418,7 +2418,6 @@ static void process_event(struct perf_script *script, struct evsel_script *es =3D evsel->priv; FILE *fp =3D es->fp; char str[PAGE_SIZE_NAME_LEN]; - const char *arch =3D perf_env__arch(machine->env); =20 if (output[type].fields =3D=3D 0) return; @@ -2506,10 +2505,10 @@ static void process_event(struct perf_script *scrip= t, } =20 if (PRINT_FIELD(IREGS)) - perf_sample__fprintf_iregs(sample, attr, arch, fp); + perf_sample__fprintf_iregs(sample, attr, thread__e_machine(thread, machi= ne), fp); =20 if (PRINT_FIELD(UREGS)) - perf_sample__fprintf_uregs(sample, attr, arch, fp); + perf_sample__fprintf_uregs(sample, attr, thread__e_machine(thread, machi= ne), fp); =20 if (PRINT_FIELD(BRSTACK)) perf_sample__fprintf_brstack(sample, thread, evsel, fp); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 6d324141588c..5ac1a05601b1 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -34,6 +34,7 @@ #include "callchain.h" #include "cgroup.h" #include "counts.h" +#include "dwarf-regs.h" #include "event.h" #include "evsel.h" #include "time-utils.h" @@ -1007,6 +1008,13 @@ int evsel__group_desc(struct evsel *evsel, char *buf= , size_t size) return ret; } =20 +static uint16_t evsel__e_machine(struct evsel *evsel) +{ + struct perf_session *session =3D evsel__session(evsel); + + return session ? perf_session__e_machine(session) : EM_HOST; +} + static void __evsel__config_callchain(struct evsel *evsel, struct record_o= pts *opts, struct callchain_param *param) { @@ -1042,13 +1050,13 @@ static void __evsel__config_callchain(struct evsel = *evsel, struct record_opts *o =20 if (param->record_mode =3D=3D CALLCHAIN_DWARF) { if (!function) { - const char *arch =3D perf_env__arch(evsel__env(evsel)); + uint16_t e_machine =3D evsel__e_machine(evsel); =20 evsel__set_sample_bit(evsel, REGS_USER); evsel__set_sample_bit(evsel, STACK_USER); if (opts->sample_user_regs && - DWARF_MINIMAL_REGS(arch) !=3D arch__user_reg_mask()) { - attr->sample_regs_user |=3D DWARF_MINIMAL_REGS(arch); + DWARF_MINIMAL_REGS(e_machine) !=3D arch__user_reg_mask()) { + attr->sample_regs_user |=3D DWARF_MINIMAL_REGS(e_machine); pr_warning("WARNING: The use of --call-graph=3Ddwarf may require all t= he user registers, " "specifying a subset with --user-regs may render DWARF unwinding u= nreliable, " "so the minimal registers set (IP, SP) is explicitly forced.\n"); diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c index 44b90bbf2d07..b58d59b84fb1 100644 --- a/tools/perf/util/perf_regs.c +++ b/tools/perf/util/perf_regs.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include #include "perf_regs.h" @@ -30,30 +31,48 @@ const struct sample_reg * __weak arch__sample_reg_masks= (void) return sample_reg_masks; } =20 -const char *perf_reg_name(int id, const char *arch) +const char *perf_reg_name(int id, uint16_t e_machine) { const char *reg_name =3D NULL; =20 - if (!strcmp(arch, "csky")) + switch (e_machine) { + case EM_ARM: + reg_name =3D __perf_reg_name_arm(id); + break; + case EM_AARCH64: + reg_name =3D __perf_reg_name_arm64(id); + break; + case EM_CSKY: reg_name =3D __perf_reg_name_csky(id); - else if (!strcmp(arch, "loongarch")) + break; + case EM_LOONGARCH: reg_name =3D __perf_reg_name_loongarch(id); - else if (!strcmp(arch, "mips")) + break; + case EM_MIPS: reg_name =3D __perf_reg_name_mips(id); - else if (!strcmp(arch, "powerpc")) + break; + case EM_PPC: + case EM_PPC64: reg_name =3D __perf_reg_name_powerpc(id); - else if (!strcmp(arch, "riscv")) + break; + case EM_RISCV: reg_name =3D __perf_reg_name_riscv(id); - else if (!strcmp(arch, "s390")) + break; + case EM_S390: reg_name =3D __perf_reg_name_s390(id); - else if (!strcmp(arch, "x86")) + break; + case EM_386: + case EM_X86_64: reg_name =3D __perf_reg_name_x86(id); - else if (!strcmp(arch, "arm")) - reg_name =3D __perf_reg_name_arm(id); - else if (!strcmp(arch, "arm64")) - reg_name =3D __perf_reg_name_arm64(id); + break; + default: + break; + } + if (reg_name) + return reg_name; =20 - return reg_name ?: "unknown"; + pr_debug("Failed to find register %d for ELF machine type %u\n", id, e_ma= chine); + return "unknown"; } =20 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) @@ -83,52 +102,60 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, = int id) return 0; } =20 -uint64_t perf_arch_reg_ip(const char *arch) +uint64_t perf_arch_reg_ip(uint16_t e_machine) { - if (!strcmp(arch, "arm")) + switch (e_machine) { + case EM_ARM: return __perf_reg_ip_arm(); - else if (!strcmp(arch, "arm64")) + case EM_AARCH64: return __perf_reg_ip_arm64(); - else if (!strcmp(arch, "csky")) + case EM_CSKY: return __perf_reg_ip_csky(); - else if (!strcmp(arch, "loongarch")) + case EM_LOONGARCH: return __perf_reg_ip_loongarch(); - else if (!strcmp(arch, "mips")) + case EM_MIPS: return __perf_reg_ip_mips(); - else if (!strcmp(arch, "powerpc")) + case EM_PPC: + case EM_PPC64: return __perf_reg_ip_powerpc(); - else if (!strcmp(arch, "riscv")) + case EM_RISCV: return __perf_reg_ip_riscv(); - else if (!strcmp(arch, "s390")) + case EM_S390: return __perf_reg_ip_s390(); - else if (!strcmp(arch, "x86")) + case EM_386: + case EM_X86_64: return __perf_reg_ip_x86(); - - pr_err("Fail to find IP register for arch %s, returns 0\n", arch); - return 0; + default: + pr_err("Failed to find IP register for ELF machine type %u\n", e_machine= ); + return 0; + } } =20 -uint64_t perf_arch_reg_sp(const char *arch) +uint64_t perf_arch_reg_sp(uint16_t e_machine) { - if (!strcmp(arch, "arm")) + switch (e_machine) { + case EM_ARM: return __perf_reg_sp_arm(); - else if (!strcmp(arch, "arm64")) + case EM_AARCH64: return __perf_reg_sp_arm64(); - else if (!strcmp(arch, "csky")) + case EM_CSKY: return __perf_reg_sp_csky(); - else if (!strcmp(arch, "loongarch")) + case EM_LOONGARCH: return __perf_reg_sp_loongarch(); - else if (!strcmp(arch, "mips")) + case EM_MIPS: return __perf_reg_sp_mips(); - else if (!strcmp(arch, "powerpc")) + case EM_PPC: + case EM_PPC64: return __perf_reg_sp_powerpc(); - else if (!strcmp(arch, "riscv")) + case EM_RISCV: return __perf_reg_sp_riscv(); - else if (!strcmp(arch, "s390")) + case EM_S390: return __perf_reg_sp_s390(); - else if (!strcmp(arch, "x86")) + case EM_386: + case EM_X86_64: return __perf_reg_sp_x86(); - - pr_err("Fail to find SP register for arch %s, returns 0\n", arch); - return 0; + default: + pr_err("Failed to find SP register for ELF machine type %u\n", e_machine= ); + return 0; + } } diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index f2d0736d65cc..7bfc6a34c02b 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h @@ -28,10 +28,10 @@ uint64_t arch__intr_reg_mask(void); uint64_t arch__user_reg_mask(void); const struct sample_reg *arch__sample_reg_masks(void); =20 -const char *perf_reg_name(int id, const char *arch); +const char *perf_reg_name(int id, uint16_t e_machine); int perf_reg_value(u64 *valp, struct regs_dump *regs, int id); -uint64_t perf_arch_reg_ip(const char *arch); -uint64_t perf_arch_reg_sp(const char *arch); +uint64_t perf_arch_reg_ip(uint16_t e_machine); +uint64_t perf_arch_reg_sp(uint16_t e_machine); const char *__perf_reg_name_arm64(int id); uint64_t __perf_reg_ip_arm64(void); uint64_t __perf_reg_sp_arm64(void); @@ -60,9 +60,9 @@ const char *__perf_reg_name_x86(int id); uint64_t __perf_reg_ip_x86(void); uint64_t __perf_reg_sp_x86(void); =20 -static inline uint64_t DWARF_MINIMAL_REGS(const char *arch) +static inline uint64_t DWARF_MINIMAL_REGS(uint16_t e_machine) { - return (1ULL << perf_arch_reg_ip(arch)) | (1ULL << perf_arch_reg_sp(arch)= ); + return (1ULL << perf_arch_reg_ip(e_machine)) | (1ULL << perf_arch_reg_sp(= e_machine)); } =20 #endif /* __PERF_REGS_H */ diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools= /perf/util/scripting-engines/trace-event-python.c index 6655c0bbe0d8..b90edc147796 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -50,6 +50,7 @@ #include "../thread-stack.h" #include "../trace-event.h" #include "../call-path.h" +#include "dwarf-regs.h" #include "map.h" #include "symbol.h" #include "thread_map.h" @@ -713,7 +714,7 @@ static void set_sample_datasrc_in_dict(PyObject *dict, _PyUnicode_FromString(decode)); } =20 -static void regs_map(struct regs_dump *regs, uint64_t mask, const char *ar= ch, char *bf, int size) +static void regs_map(struct regs_dump *regs, uint64_t mask, uint16_t e_mac= hine, char *bf, int size) { unsigned int i =3D 0, r; int printed =3D 0; @@ -731,7 +732,7 @@ static void regs_map(struct regs_dump *regs, uint64_t m= ask, const char *arch, ch =20 printed +=3D scnprintf(bf + printed, size - printed, "%5s:0x%" PRIx64 " ", - perf_reg_name(r, arch), val); + perf_reg_name(r, e_machine), val); } } =20 @@ -739,10 +740,10 @@ static void regs_map(struct regs_dump *regs, uint64_t= mask, const char *arch, ch =20 static int set_regs_in_dict(PyObject *dict, struct perf_sample *sample, - struct evsel *evsel) + struct evsel *evsel, + uint16_t e_machine) { struct perf_event_attr *attr =3D &evsel->core.attr; - const char *arch =3D perf_env__arch(evsel__env(evsel)); =20 int size =3D (__sw_hweight64(attr->sample_regs_intr) * MAX_REG_SIZE) + 1; char *bf =3D NULL; @@ -752,7 +753,7 @@ static int set_regs_in_dict(PyObject *dict, if (!bf) return -1; =20 - regs_map(sample->intr_regs, attr->sample_regs_intr, arch, bf, size); + regs_map(sample->intr_regs, attr->sample_regs_intr, e_machine, bf, size); =20 pydict_set_item_string_decref(dict, "iregs", _PyUnicode_FromString(bf)); @@ -764,7 +765,7 @@ static int set_regs_in_dict(PyObject *dict, if (!bf) return -1; } - regs_map(sample->user_regs, attr->sample_regs_user, arch, bf, size); + regs_map(sample->user_regs, attr->sample_regs_user, e_machine, bf, size); =20 pydict_set_item_string_decref(dict, "uregs", _PyUnicode_FromString(bf)); @@ -834,6 +835,8 @@ static PyObject *get_perf_sample_dict(struct perf_sampl= e *sample, PyObject *callchain) { PyObject *dict, *dict_sample, *brstack, *brstacksym; + struct machine *machine; + uint16_t e_machine =3D EM_HOST; =20 dict =3D PyDict_New(); if (!dict) @@ -920,7 +923,11 @@ static PyObject *get_perf_sample_dict(struct perf_samp= le *sample, PyLong_FromUnsignedLongLong(sample->cyc_cnt)); } =20 - if (set_regs_in_dict(dict, sample, evsel)) + if (al->thread) { + machine =3D maps__machine(thread__maps(al->thread)); + e_machine =3D thread__e_machine(al->thread, machine); + } + if (set_regs_in_dict(dict, sample, evsel, e_machine)) Py_FatalError("Failed to setting regs in dict"); =20 return dict; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 922ef6577bbb..d7b28cb4e672 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -17,6 +17,7 @@ #include "map_symbol.h" #include "branch.h" #include "debug.h" +#include "dwarf-regs.h" #include "env.h" #include "evlist.h" #include "evsel.h" @@ -942,7 +943,7 @@ static void branch_stack__printf(struct perf_sample *sa= mple, } } =20 -static void regs_dump__printf(u64 mask, u64 *regs, const char *arch) +static void regs_dump__printf(u64 mask, u64 *regs, uint16_t e_machine) { unsigned rid, i =3D 0; =20 @@ -950,7 +951,7 @@ static void regs_dump__printf(u64 mask, u64 *regs, cons= t char *arch) u64 val =3D regs[i++]; =20 printf(".... %-5s 0x%016" PRIx64 "\n", - perf_reg_name(rid, arch), val); + perf_reg_name(rid, e_machine), val); } } =20 @@ -968,7 +969,7 @@ static inline const char *regs_dump_abi(struct regs_dum= p *d) return regs_abi[d->abi]; } =20 -static void regs__printf(const char *type, struct regs_dump *regs, const c= har *arch) +static void regs__printf(const char *type, struct regs_dump *regs, uint16_= t e_machine) { u64 mask =3D regs->mask; =20 @@ -977,10 +978,10 @@ static void regs__printf(const char *type, struct reg= s_dump *regs, const char *a mask, regs_dump_abi(regs)); =20 - regs_dump__printf(mask, regs->regs, arch); + regs_dump__printf(mask, regs->regs, e_machine); } =20 -static void regs_user__printf(struct perf_sample *sample, const char *arch) +static void regs_user__printf(struct perf_sample *sample, uint16_t e_machi= ne) { struct regs_dump *user_regs; =20 @@ -990,10 +991,10 @@ static void regs_user__printf(struct perf_sample *sam= ple, const char *arch) user_regs =3D perf_sample__user_regs(sample); =20 if (user_regs->regs) - regs__printf("user", user_regs, arch); + regs__printf("user", user_regs, e_machine); } =20 -static void regs_intr__printf(struct perf_sample *sample, const char *arch) +static void regs_intr__printf(struct perf_sample *sample, uint16_t e_machi= ne) { struct regs_dump *intr_regs; =20 @@ -1003,7 +1004,7 @@ static void regs_intr__printf(struct perf_sample *sam= ple, const char *arch) intr_regs =3D perf_sample__intr_regs(sample); =20 if (intr_regs->regs) - regs__printf("intr", intr_regs, arch); + regs__printf("intr", intr_regs, e_machine); } =20 static void stack_user__printf(struct stack_dump *dump) @@ -1092,21 +1093,28 @@ char *get_page_size_name(u64 size, char *str) return str; } =20 -static void dump_sample(struct evsel *evsel, union perf_event *event, - struct perf_sample *sample, const char *arch) +static void dump_sample(struct machine *machine, struct evsel *evsel, unio= n perf_event *event, + struct perf_sample *sample) { u64 sample_type; char str[PAGE_SIZE_NAME_LEN]; + uint16_t e_machine =3D EM_NONE; =20 if (!dump_trace) return; =20 + sample_type =3D evsel->core.attr.sample_type; + + if (sample_type & (PERF_SAMPLE_REGS_USER | PERF_SAMPLE_REGS_INTR)) { + struct thread *thread =3D machine__find_thread(machine, sample->pid, sam= ple->pid); + + e_machine =3D thread__e_machine(thread, machine); + } + printf("(IP, 0x%x): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRI= x64 "\n", event->header.misc, sample->pid, sample->tid, sample->ip, sample->period, sample->addr); =20 - sample_type =3D evsel->core.attr.sample_type; - if (evsel__has_callchain(evsel)) callchain__printf(evsel, sample); =20 @@ -1114,10 +1122,10 @@ static void dump_sample(struct evsel *evsel, union = perf_event *event, branch_stack__printf(sample, evsel); =20 if (sample_type & PERF_SAMPLE_REGS_USER) - regs_user__printf(sample, arch); + regs_user__printf(sample, e_machine); =20 if (sample_type & PERF_SAMPLE_REGS_INTR) - regs_intr__printf(sample, arch); + regs_intr__printf(sample, e_machine); =20 if (sample_type & PERF_SAMPLE_STACK_USER) stack_user__printf(&sample->user_stack); @@ -1432,10 +1440,10 @@ static int machines__deliver_event(struct machines = *machines, } if (machine =3D=3D NULL) { ++evlist->stats.nr_unprocessable_samples; - dump_sample(evsel, event, sample, perf_env__arch(NULL)); + dump_sample(machine, evsel, event, sample); return 0; } - dump_sample(evsel, event, sample, perf_env__arch(machine->env)); + dump_sample(machine, evsel, event, sample); if (sample->deferred_callchain && tool->merge_deferred_callchains) { struct deferred_event *de =3D malloc(sizeof(*de)); size_t sz =3D event->header.size; @@ -2928,3 +2936,28 @@ struct perf_env *perf_session__env(struct perf_sessi= on *session) { return &session->header.env; } + +static int perf_session__e_machine_cb(struct thread *thread, + void *arg __maybe_unused) +{ + uint16_t *result =3D arg; + struct machine *machine =3D maps__machine(thread__maps(thread)); + + *result =3D thread__e_machine(thread, machine); + return *result !=3D EM_NONE ? 1 : 0; +} + +/* + * Note, a machine may have mixed 32-bit and 64-bit processes and so mixed + * e_machines. Use thread__e_machine when this matters. + */ +uint16_t perf_session__e_machine(struct perf_session *session) +{ + uint16_t e_machine =3D EM_NONE; + + machines__for_each_thread(&session->machines, + perf_session__e_machine_cb, + &e_machine); + + return e_machine =3D=3D EM_NONE ? EM_HOST : e_machine; +} diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 22d3ff877e83..eddc4c630b33 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -211,5 +211,6 @@ int perf_event__process_finished_round(const struct per= f_tool *tool, struct ordered_events *oe); =20 struct perf_env *perf_session__env(struct perf_session *session); +uint16_t perf_session__e_machine(struct perf_session *session); =20 #endif /* __PERF_SESSION_H */ diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index dc882f17f52d..c25190cdceb4 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -187,7 +187,7 @@ static bool memory_read(Dwfl *dwfl __maybe_unused, Dwar= f_Addr addr, Dwarf_Word * void *arg) { struct unwind_info *ui =3D arg; - const char *arch =3D perf_env__arch(ui->machine->env); + uint16_t e_machine =3D thread__e_machine(ui->thread, ui->machine); struct stack_dump *stack =3D &ui->sample->user_stack; u64 start, end; int offset; @@ -197,7 +197,7 @@ static bool memory_read(Dwfl *dwfl __maybe_unused, Dwar= f_Addr addr, Dwarf_Word * return false; =20 ret =3D perf_reg_value(&start, ui->sample->user_regs, - perf_arch_reg_sp(arch)); + perf_arch_reg_sp(e_machine)); if (ret) return false; =20 @@ -300,16 +300,18 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *a= rg, int max_stack, bool best_effort) { + struct machine *machine =3D maps__machine(thread__maps(thread)); struct unwind_info *ui, ui_buf =3D { .sample =3D data, .thread =3D thread, - .machine =3D maps__machine((thread__maps(thread))), + .machine =3D machine, .cb =3D cb, .arg =3D arg, .max_stack =3D max_stack, .best_effort =3D best_effort }; - const char *arch =3D perf_env__arch(ui_buf.machine->env); + uint16_t e_machine =3D thread__e_machine(thread, machine); + const char *arch =3D perf_env__arch(machine->env); Dwarf_Word ip; int err =3D -EINVAL, i; const Dwfl_Thread_Callbacks *callbacks; @@ -327,7 +329,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, if (!ui->dwfl) goto out; =20 - err =3D perf_reg_value(&ip, data->user_regs, perf_arch_reg_ip(arch)); + err =3D perf_reg_value(&ip, data->user_regs, perf_arch_reg_ip(e_machine)); if (err) goto out; =20 diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unw= ind-libunwind-local.c index 0b037e7389a0..a24b45106acd 100644 --- a/tools/perf/util/unwind-libunwind-local.c +++ b/tools/perf/util/unwind-libunwind-local.c @@ -572,7 +572,6 @@ static int access_mem(unw_addr_space_t __maybe_unused a= s, int __write, void *arg) { struct unwind_info *ui =3D arg; - const char *arch =3D perf_env__arch(ui->machine->env); struct stack_dump *stack =3D &ui->sample->user_stack; u64 start, end; int offset; @@ -585,7 +584,7 @@ static int access_mem(unw_addr_space_t __maybe_unused a= s, } =20 ret =3D perf_reg_value(&start, perf_sample__user_regs(ui->sample), - perf_arch_reg_sp(arch)); + perf_arch_reg_sp(thread__e_machine(ui->thread, ui->machine))); if (ret) return ret; =20 @@ -734,7 +733,7 @@ static void _unwind__finish_access(struct maps *maps) static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, void *arg, int max_stack) { - const char *arch =3D perf_env__arch(ui->machine->env); + uint16_t e_machine =3D thread__e_machine(ui->thread, ui->machine); u64 val; unw_word_t ips[max_stack]; unw_addr_space_t addr_space; @@ -742,7 +741,7 @@ static int get_entries(struct unwind_info *ui, unwind_e= ntry_cb_t cb, int ret, i =3D 0; =20 ret =3D perf_reg_value(&val, perf_sample__user_regs(ui->sample), - perf_arch_reg_ip(arch)); + perf_arch_reg_ip(e_machine)); if (ret) return ret; =20 --=20 2.52.0.457.g6b5491de43-goog