All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andi Kleen <andi@firstfloor.org>
To: acme@kernel.org
Cc: jolsa@kernel.org, linux-kernel@vger.kernel.org,
	Andi Kleen <ak@linux.intel.com>
Subject: [PATCH 3/5] perf, tools: Add disassembler for x86 using the XED library
Date: Wed, 18 Jan 2017 17:41:48 -0800	[thread overview]
Message-ID: <20170119014150.19218-4-andi@firstfloor.org> (raw)
In-Reply-To: <20170119014150.19218-1-andi@firstfloor.org>

From: Andi Kleen <ak@linux.intel.com>

Add a generic disassembler function for x86 using the XED library,
and a fallback function for architectures that don't implement one.
Other architectures can implement their own disassembler functions.

The previous version of this patch used udis86, but was
rejected because udis86 was unmaintained and a runtime dependency.
Using the recently released xed avoids both of these problems:
- XED is well maintained, uptodate, and used by many Intel tools
- XED is linked statically so there is no runtime dependency.

The XED library can be downloaded from http://github.com/intelxed/xed

v2: Clean up includes.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 tools/perf/arch/x86/util/Build |  1 +
 tools/perf/arch/x86/util/dis.c | 86 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/Build          |  1 +
 tools/perf/util/dis.c          | 15 ++++++++
 tools/perf/util/dis.h          | 20 ++++++++++
 5 files changed, 123 insertions(+)
 create mode 100644 tools/perf/arch/x86/util/dis.c
 create mode 100644 tools/perf/util/dis.c
 create mode 100644 tools/perf/util/dis.h

diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build
index f95e6f46ef0d..93490009ea6a 100644
--- a/tools/perf/arch/x86/util/Build
+++ b/tools/perf/arch/x86/util/Build
@@ -14,3 +14,4 @@ libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
 libperf-$(CONFIG_AUXTRACE) += auxtrace.o
 libperf-$(CONFIG_AUXTRACE) += intel-pt.o
 libperf-$(CONFIG_AUXTRACE) += intel-bts.o
+libperf-$(CONFIG_XED) += dis.o
diff --git a/tools/perf/arch/x86/util/dis.c b/tools/perf/arch/x86/util/dis.c
new file mode 100644
index 000000000000..39703512fe17
--- /dev/null
+++ b/tools/perf/arch/x86/util/dis.c
@@ -0,0 +1,86 @@
+/* Disassembler using the XED library */
+#include "perf.h"
+#include "util/session.h"
+#include "util/symbol.h"
+#include "util/thread.h"
+#include "util/dis.h"
+
+#include <xed/xed-interface.h>
+#include <xed/xed-decode.h>
+#include <xed/xed-decoded-inst-api.h>
+
+static int dis_resolve(xed_uint64_t addr, char *buf, xed_uint32_t buflen,
+		xed_uint64_t *off, void *data)
+{
+	struct perf_dis *x = data;
+	struct addr_location al;
+
+	memset(&al, 0, sizeof(struct addr_location));
+
+	thread__find_addr_map(x->thread, x->cpumode, MAP__FUNCTION, addr, &al);
+	if (!al.map)
+		thread__find_addr_map(x->thread, x->cpumode, MAP__VARIABLE,
+					addr, &al);
+	al.cpu = x->cpu;
+	al.sym = NULL;
+
+	if (al.map)
+		al.sym = map__find_symbol(al.map, al.addr);
+
+	if (!al.sym)
+		return 0;
+
+	if (al.addr < al.sym->end)
+		*off = al.addr - al.sym->start;
+	else
+		*off = al.addr - al.map->start - al.sym->start;
+	snprintf(buf, buflen, "%s", al.sym->name);
+	return 1;
+}
+
+/* x must be set up earlier */
+char *disas_inst(struct perf_dis *x, uint64_t ip, u8 *inbuf, int inlen,
+		 int *lenp)
+{
+	xed_decoded_inst_t inst;
+	xed_print_info_t info;
+	xed_error_enum_t err;
+	static bool init;
+
+	if (!init) {
+		xed_tables_init();
+		init = true;
+	}
+
+	if (lenp)
+		*lenp = 0;
+
+	xed_init_print_info(&info);
+	info.syntax = XED_SYNTAX_ATT;
+	info.disassembly_callback = dis_resolve;
+	info.context = x;
+
+	xed_decoded_inst_zero(&inst);
+	if (x->is64bit)
+		xed_decoded_inst_set_mode(&inst, XED_MACHINE_MODE_LONG_64,
+				XED_ADDRESS_WIDTH_64b);
+	else
+		xed_decoded_inst_set_mode(&inst, XED_MACHINE_MODE_LEGACY_32,
+				XED_ADDRESS_WIDTH_32b);
+
+	err = xed_decode(&inst, (uint8_t *)inbuf, inlen);
+	if (err != XED_ERROR_NONE) {
+		snprintf(x->out, sizeof(x->out), "err: %s for %d bytes",
+				xed_error_enum_t2str(err), inlen);
+		return x->out;
+	}
+	if (lenp)
+		*lenp = xed_decoded_inst_get_length(&inst);
+	info.p = &inst;
+	info.buf = x->out;
+	info.blen = sizeof(x->out);
+	info.runtime_address = ip;
+	if (!xed_format_generic(&info))
+		strcpy(x->out, "err: cannot format");
+	return x->out;
+}
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 5da376bc1afc..cdaeb4764fee 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -88,6 +88,7 @@ libperf-y += mem-events.o
 libperf-y += vsprintf.o
 libperf-y += drv_configs.o
 libperf-y += time-utils.o
+libperf-y += dis.o
 
 libperf-$(CONFIG_LIBBPF) += bpf-loader.o
 libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
diff --git a/tools/perf/util/dis.c b/tools/perf/util/dis.c
new file mode 100644
index 000000000000..89c9b84051b8
--- /dev/null
+++ b/tools/perf/util/dis.c
@@ -0,0 +1,15 @@
+#include "perf.h"
+#include "dis.h"
+#include "util.h"
+
+/* Fallback for architectures with no disassembler */
+
+__weak char *disas_inst(struct perf_dis *x, uint64_t ip __maybe_unused,
+		u8 *inbuf __maybe_unused, int inlen __maybe_unused,
+		int *lenp)
+{
+	if (lenp)
+		*lenp = 0;
+	strcpy(x->out, "?");
+	return x->out;
+}
diff --git a/tools/perf/util/dis.h b/tools/perf/util/dis.h
new file mode 100644
index 000000000000..ffda324cbc1a
--- /dev/null
+++ b/tools/perf/util/dis.h
@@ -0,0 +1,20 @@
+#ifndef DIS_H
+#define DIS_H 1
+
+#define MAXINSN 15
+
+struct perf_dis {
+	/* Initialized by callers: */
+	struct thread *thread;
+	u8 cpumode;
+	int cpu;
+	bool is64bit;
+	/* Temporary */
+	char out[256];
+};
+
+char *disas_inst(struct perf_dis *x, uint64_t ip, u8 *inbuf, int inlen,
+		 int *lenp);
+
+
+#endif
-- 
2.9.3

  parent reply	other threads:[~2017-01-19  1:42 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-19  1:41 New attempt at adding an disassembler to perf Andi Kleen
2017-01-19  1:41 ` [PATCH 1/5] perf, tools: Add probing for xed Andi Kleen
2017-01-19  1:41 ` [PATCH 2/5] perf, tools: Add one liner warning for disabled features Andi Kleen
2017-01-19  1:41 ` Andi Kleen [this message]
2017-01-19  1:41 ` [PATCH 4/5] perf, tools, script: Add support for printing assembler Andi Kleen
2017-01-23 19:49   ` Arnaldo Carvalho de Melo
2017-01-23 19:55     ` Andi Kleen
2017-01-23 20:06       ` Arnaldo Carvalho de Melo
2017-01-19  1:41 ` [PATCH 5/5] perf, tools, script: Add brstackasm output for branch stacks Andi Kleen
2017-01-24 18:54   ` Arnaldo Carvalho de Melo
2017-01-19 15:36 ` New attempt at adding an disassembler to perf Jiri Olsa
2017-01-19 16:54   ` Andi Kleen
2017-01-20 13:22 ` Jiri Olsa
  -- strict thread matches above, loose matches on Subject: below --
2017-01-10  1:02 New attempt at adding an disassembler to perf v2 Andi Kleen
2017-01-10  1:02 ` [PATCH 3/5] perf, tools: Add disassembler for x86 using the XED library Andi Kleen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170119014150.19218-4-andi@firstfloor.org \
    --to=andi@firstfloor.org \
    --cc=acme@kernel.org \
    --cc=ak@linux.intel.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.