From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753695AbdK1AZe (ORCPT ); Mon, 27 Nov 2017 19:25:34 -0500 Received: from mga07.intel.com ([134.134.136.100]:56310 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753246AbdK1AXb (ORCPT ); Mon, 27 Nov 2017 19:23:31 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,466,1505804400"; d="scan'208";a="6618586" From: Andi Kleen To: acme@kernel.org Cc: jolsa@kernel.org, mhiramat@kernel.org, adrian.hunter@intel.com, linux-kernel@vger.kernel.org, Andi Kleen Subject: [PATCH 02/12] perf, tools, script: Print insn/insnlen for non PT sample Date: Mon, 27 Nov 2017 16:23:11 -0800 Message-Id: <20171128002321.2878-3-andi@firstfloor.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20171128002321.2878-1-andi@firstfloor.org> References: <20171128002321.2878-1-andi@firstfloor.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Andi Kleen Dumping insn/insnlen only works for PT samples where the PT decoder fills in these fields. Add a fallback for other samples where we grab the instructions manually and then call an architecture specific function to determine the instruction length. The architecture specific function is currently only implemented for x86, and uses the standard Linux instruction decoder. Signed-off-by: Andi Kleen --- tools/perf/arch/x86/util/Build | 1 + tools/perf/arch/x86/util/insnlen.c | 12 ++++++++++++ tools/perf/builtin-script.c | 13 +++++++++++++ tools/perf/util/Build | 1 + tools/perf/util/insnlen.c | 10 ++++++++++ tools/perf/util/insnlen.h | 6 ++++++ 6 files changed, 43 insertions(+) create mode 100644 tools/perf/arch/x86/util/insnlen.c create mode 100644 tools/perf/util/insnlen.c create mode 100644 tools/perf/util/insnlen.h diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build index f95e6f46ef0d..139f9f1a56f9 100644 --- a/tools/perf/arch/x86/util/Build +++ b/tools/perf/arch/x86/util/Build @@ -1,6 +1,7 @@ libperf-y += header.o libperf-y += tsc.o libperf-y += pmu.o +libperf-y += insnlen.o libperf-y += kvm-stat.o libperf-y += perf_regs.o libperf-y += group.o diff --git a/tools/perf/arch/x86/util/insnlen.c b/tools/perf/arch/x86/util/insnlen.c new file mode 100644 index 000000000000..8e2e50bd5201 --- /dev/null +++ b/tools/perf/arch/x86/util/insnlen.c @@ -0,0 +1,12 @@ +#include "intel-pt-decoder/insn.h" +#include "intel-pt-decoder/inat.h" +#include "insnlen.h" + +int arch_insn_len(char *insnbytes, int insnlen, int is64bit) +{ + struct insn insn; + + insn_init(&insn, insnbytes, insnlen, is64bit); + insn_get_length(&insn); + return insn.length; +} diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index ee7c7aaaae72..cae4b13fc715 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -20,6 +20,7 @@ #include "util/data.h" #include "util/auxtrace.h" #include "util/cpumap.h" +#include "util/insnlen.h" #include "util/thread_map.h" #include "util/stat.h" #include "util/string2.h" @@ -1108,6 +1109,18 @@ static int perf_sample__fprintf_insn(struct perf_sample *sample, { int printed = 0; + if ((PRINT_FIELD(INSNLEN) || PRINT_FIELD(INSN)) && !sample->insn_len) { + u8 ibuf[64]; + bool is64bit; + u8 cpumode; + + if (grab_bb(ibuf, sample->ip, sample->ip + 16, + machine, thread, &is64bit, &cpumode, false) > 0) { + sample->insn_len = arch_insn_len((char *)ibuf, 16, is64bit); + memcpy(sample->insn, ibuf, sample->insn_len); + } + } + if (PRINT_FIELD(INSNLEN)) printed += fprintf(fp, " ilen: %d", sample->insn_len); if (PRINT_FIELD(INSN)) { diff --git a/tools/perf/util/Build b/tools/perf/util/Build index a3de7916fe63..80c05329835a 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -14,6 +14,7 @@ libperf-y += kallsyms.o libperf-y += levenshtein.o libperf-y += llvm-utils.o libperf-y += mmap.o +libperf-y += insnlen.o libperf-y += memswap.o libperf-y += parse-events.o libperf-y += perf_regs.o diff --git a/tools/perf/util/insnlen.c b/tools/perf/util/insnlen.c new file mode 100644 index 000000000000..6c126960a7e6 --- /dev/null +++ b/tools/perf/util/insnlen.c @@ -0,0 +1,10 @@ +#include "perf.h" +#include "insnlen.h" + +/* Fallback for architectures not supporting this */ +__weak int arch_insn_len(char *buf __maybe_unused, + int len __maybe_unused, + int is64bit __maybe_unused) +{ + return 0; +} diff --git a/tools/perf/util/insnlen.h b/tools/perf/util/insnlen.h new file mode 100644 index 000000000000..289877dff89d --- /dev/null +++ b/tools/perf/util/insnlen.h @@ -0,0 +1,6 @@ +#ifndef INSNLEN_H +#define INSNLEN_H 1 + +int arch_insn_len(char *buf, int len, int is64bit); + +#endif -- 2.13.6