Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1549623 > unrolled thread

[PATCH 2/4] perf, tools: Add disassembler for x86 using the XED library

Started byAndi Kleen <andi@firstfloor.org>
First post2017-01-03 10:10 +0100
Last post2017-01-08 15:30 +0100
Articles 2 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH 2/4] perf, tools: Add disassembler for x86 using the XED library Andi Kleen <andi@firstfloor.org> - 2017-01-03 10:10 +0100
    Re: [PATCH 2/4] perf, tools: Add disassembler for x86 using the XED  library Jiri Olsa <jolsa@redhat.com> - 2017-01-08 15:30 +0100

#1549623 — [PATCH 2/4] perf, tools: Add disassembler for x86 using the XED library

FromAndi Kleen <andi@firstfloor.org>
Date2017-01-03 10:10 +0100
Subject[PATCH 2/4] perf, tools: Add disassembler for x86 using the XED library
Message-ID<sVtgu-40T-13@gated-at.bofh.it>
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

Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 tools/perf/arch/x86/util/Build |  1 +
 tools/perf/arch/x86/util/dis.c | 89 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/Build          |  1 +
 tools/perf/util/dis.c          | 15 +++++++
 tools/perf/util/dis.h          | 20 ++++++++++
 5 files changed, 126 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..62920db9ade0
--- /dev/null
+++ b/tools/perf/arch/x86/util/dis.c
@@ -0,0 +1,89 @@
+/* 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);
+
+	/* Work around bogus errors in XED when inlen is large */
+	if (inlen > MAXINSN)
+		inlen = MAXINSN;
+	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 3840e3a87057..393000501579 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..a3929616dacd
--- /dev/null
+++ b/tools/perf/util/dis.c
@@ -0,0 +1,15 @@
+#include "perf.h"
+#include "util/dis.h"
+#include "util/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

[toc] | [next] | [standalone]


#1553881 — Re: [PATCH 2/4] perf, tools: Add disassembler for x86 using the XED library

FromJiri Olsa <jolsa@redhat.com>
Date2017-01-08 15:30 +0100
SubjectRe: [PATCH 2/4] perf, tools: Add disassembler for x86 using the XED library
Message-ID<sXmDT-7xs-23@gated-at.bofh.it>
In reply to#1549623
On Tue, Jan 03, 2017 at 01:00:27AM -0800, Andi Kleen wrote:

SNIP

> diff --git a/tools/perf/util/dis.c b/tools/perf/util/dis.c
> new file mode 100644
> index 000000000000..a3929616dacd
> --- /dev/null
> +++ b/tools/perf/util/dis.c
> @@ -0,0 +1,15 @@
> +#include "perf.h"
> +#include "util/dis.h"
> +#include "util/util.h"

no need for util/ prefix

jirka

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web