All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 0/3] perf tools: Support insn and insnlen in perf script
@ 2016-10-07 13:42 Adrian Hunter
  2016-10-07 13:42 ` [PATCH V3 1/3] perf intel-pt/bts: Tidy instruction buffer size usage Adrian Hunter
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Adrian Hunter @ 2016-10-07 13:42 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Andi Kleen; +Cc: linux-kernel

Hi

I tidied Intel PT / BTS instruction buffer size usage, and took the liberty
of re-basing Andi's changes on top.


Adrian Hunter (1):
      perf intel-pt/bts: Tidy instruction buffer size usage

Andi Kleen (2):
      perf intel-pt/bts: Report instruction bytes and length in sample
      perf tools: Support insn and insnlen in perf script

 tools/perf/Documentation/perf-script.txt           |  6 +++++-
 tools/perf/builtin-script.c                        | 24 ++++++++++++++++++++--
 tools/perf/util/event.h                            |  3 +++
 tools/perf/util/intel-bts.c                        |  9 ++++----
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  |  2 ++
 .../perf/util/intel-pt-decoder/intel-pt-decoder.h  |  1 +
 .../util/intel-pt-decoder/intel-pt-insn-decoder.c  | 13 ++++++------
 .../util/intel-pt-decoder/intel-pt-insn-decoder.h  |  6 ++----
 tools/perf/util/intel-pt-decoder/intel-pt-log.c    |  4 ++--
 tools/perf/util/intel-pt.c                         | 19 ++++++++++++-----
 10 files changed, 61 insertions(+), 26 deletions(-)


Regards
Adrian

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH V3 1/3] perf intel-pt/bts: Tidy instruction buffer size usage
  2016-10-07 13:42 [PATCH V3 0/3] perf tools: Support insn and insnlen in perf script Adrian Hunter
@ 2016-10-07 13:42 ` Adrian Hunter
  2016-10-24 18:49   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-10-07 13:42 ` [PATCH V3 2/3] perf intel-pt/bts: Report instruction bytes and length in sample Adrian Hunter
  2016-10-07 13:42 ` [PATCH V3 3/3] perf tools: Support insn and insnlen in perf script Adrian Hunter
  2 siblings, 1 reply; 7+ messages in thread
From: Adrian Hunter @ 2016-10-07 13:42 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Andi Kleen; +Cc: linux-kernel

Tidy instruction buffer size usage in preparation for copying the
instruction bytes onto samples.

The instruction buffer is presently used for debugging, so rename its size
macro from INTEL_PT_INSN_DBG_BUF_SZ to INTEL_PT_INSN_BUF_SZ, and use it
everywhere.

Note that the maximum instruction size is 15 which is a less efficient size
to copy than 16, which is why a separate buffer size is used.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-bts.c                              |  8 +++-----
 tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c | 13 ++++++-------
 tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h |  6 ++----
 tools/perf/util/intel-pt-decoder/intel-pt-log.c          |  4 ++--
 tools/perf/util/intel-pt.c                               |  8 +++-----
 5 files changed, 16 insertions(+), 23 deletions(-)

diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index f545ec1e758a..8bc7fec817d7 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -319,15 +319,12 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
 	struct machine *machine = btsq->bts->machine;
 	struct thread *thread;
 	struct addr_location al;
-	unsigned char buf[1024];
-	size_t bufsz;
+	unsigned char buf[INTEL_PT_INSN_BUF_SZ];
 	ssize_t len;
 	int x86_64;
 	uint8_t cpumode;
 	int err = -1;
 
-	bufsz = intel_pt_insn_max_size();
-
 	if (machine__kernel_ip(machine, ip))
 		cpumode = PERF_RECORD_MISC_KERNEL;
 	else
@@ -341,7 +338,8 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
 	if (!al.map || !al.map->dso)
 		goto out_put;
 
-	len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf, bufsz);
+	len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf,
+				  INTEL_PT_INSN_BUF_SZ);
 	if (len <= 0)
 		goto out_put;
 
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index d23138c06665..5f95cd442075 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -27,6 +27,10 @@
 
 #include "intel-pt-insn-decoder.h"
 
+#if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE
+#error Instruction buffer size too small
+#endif
+
 /* Based on branch_type() from perf_event_intel_lbr.c */
 static void intel_pt_insn_decoder(struct insn *insn,
 				  struct intel_pt_insn *intel_pt_insn)
@@ -166,10 +170,10 @@ int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
 	if (!insn_complete(&insn) || insn.length > len)
 		return -1;
 	intel_pt_insn_decoder(&insn, intel_pt_insn);
-	if (insn.length < INTEL_PT_INSN_DBG_BUF_SZ)
+	if (insn.length < INTEL_PT_INSN_BUF_SZ)
 		memcpy(intel_pt_insn->buf, buf, insn.length);
 	else
-		memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_DBG_BUF_SZ);
+		memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_BUF_SZ);
 	return 0;
 }
 
@@ -211,11 +215,6 @@ int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
 	return 0;
 }
 
-size_t intel_pt_insn_max_size(void)
-{
-	return MAX_INSN_SIZE;
-}
-
 int intel_pt_insn_type(enum intel_pt_insn_op op)
 {
 	switch (op) {
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
index b0adbf37323e..37ec5627ae9b 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
@@ -20,7 +20,7 @@
 #include <stdint.h>
 
 #define INTEL_PT_INSN_DESC_MAX		32
-#define INTEL_PT_INSN_DBG_BUF_SZ	16
+#define INTEL_PT_INSN_BUF_SZ		16
 
 enum intel_pt_insn_op {
 	INTEL_PT_OP_OTHER,
@@ -47,7 +47,7 @@ struct intel_pt_insn {
 	enum intel_pt_insn_branch	branch;
 	int				length;
 	int32_t				rel;
-	unsigned char			buf[INTEL_PT_INSN_DBG_BUF_SZ];
+	unsigned char			buf[INTEL_PT_INSN_BUF_SZ];
 };
 
 int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
@@ -58,8 +58,6 @@ const char *intel_pt_insn_name(enum intel_pt_insn_op op);
 int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
 		       size_t buf_len);
 
-size_t intel_pt_insn_max_size(void);
-
 int intel_pt_insn_type(enum intel_pt_insn_op op);
 
 #endif
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
index 319bef33a64b..e02bc7b166a0 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
@@ -119,8 +119,8 @@ void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
 	if (intel_pt_log_open())
 		return;
 
-	if (len > INTEL_PT_INSN_DBG_BUF_SZ)
-		len = INTEL_PT_INSN_DBG_BUF_SZ;
+	if (len > INTEL_PT_INSN_BUF_SZ)
+		len = INTEL_PT_INSN_BUF_SZ;
 	intel_pt_print_data(intel_pt_insn->buf, len, ip, 8);
 	if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0)
 		fprintf(f, "%s\n", desc);
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index dc041d4368c8..815a14d8904b 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -428,8 +428,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 	struct machine *machine = ptq->pt->machine;
 	struct thread *thread;
 	struct addr_location al;
-	unsigned char buf[1024];
-	size_t bufsz;
+	unsigned char buf[INTEL_PT_INSN_BUF_SZ];
 	ssize_t len;
 	int x86_64;
 	u8 cpumode;
@@ -440,8 +439,6 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 	if (to_ip && *ip == to_ip)
 		goto out_no_cache;
 
-	bufsz = intel_pt_insn_max_size();
-
 	if (*ip >= ptq->pt->kernel_start)
 		cpumode = PERF_RECORD_MISC_KERNEL;
 	else
@@ -493,7 +490,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 
 		while (1) {
 			len = dso__data_read_offset(al.map->dso, machine,
-						    offset, buf, bufsz);
+						    offset, buf,
+						    INTEL_PT_INSN_BUF_SZ);
 			if (len <= 0)
 				return -EINVAL;
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH V3 2/3] perf intel-pt/bts: Report instruction bytes and length in sample
  2016-10-07 13:42 [PATCH V3 0/3] perf tools: Support insn and insnlen in perf script Adrian Hunter
  2016-10-07 13:42 ` [PATCH V3 1/3] perf intel-pt/bts: Tidy instruction buffer size usage Adrian Hunter
@ 2016-10-07 13:42 ` Adrian Hunter
  2016-10-24 18:50   ` [tip:perf/core] " tip-bot for Andi Kleen
  2016-10-07 13:42 ` [PATCH V3 3/3] perf tools: Support insn and insnlen in perf script Adrian Hunter
  2 siblings, 1 reply; 7+ messages in thread
From: Adrian Hunter @ 2016-10-07 13:42 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Andi Kleen; +Cc: linux-kernel

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

Change Intel PT and BTS to pass up the length and the instruction
bytes of the decoded or sampled instruction in the perf sample.

The decoder already knows this information, we just need to pass it
up. Since it is only a couple of movs it is not very expensive.

Handle instruction cache too. Make sure ilen is always initialized.

Used in the next patch.

[Adrian: re-base on top (and adjust for) instruction buffer size tidy-up]
[Adrian: add BTS support and adjust commit message accordingly]

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/event.h                                  |  3 +++
 tools/perf/util/intel-bts.c                              |  1 +
 tools/perf/util/intel-pt-decoder/intel-pt-decoder.c      |  2 ++
 tools/perf/util/intel-pt-decoder/intel-pt-decoder.h      |  1 +
 tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c |  2 +-
 tools/perf/util/intel-pt.c                               | 11 +++++++++++
 6 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8d363d5e65a2..c735c53a26f8 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -177,6 +177,8 @@ enum {
 	PERF_IP_FLAG_TRACE_BEGIN	|\
 	PERF_IP_FLAG_TRACE_END)
 
+#define MAX_INSN 16
+
 struct perf_sample {
 	u64 ip;
 	u32 pid, tid;
@@ -193,6 +195,7 @@ struct perf_sample {
 	u32 flags;
 	u16 insn_len;
 	u8  cpumode;
+	char insn[MAX_INSN];
 	void *raw_data;
 	struct ip_callchain *callchain;
 	struct branch_stack *branch_stack;
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 8bc7fec817d7..6c2eb5da4afc 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -295,6 +295,7 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
 	sample.cpu = btsq->cpu;
 	sample.flags = btsq->sample_flags;
 	sample.insn_len = btsq->intel_pt_insn.length;
+	memcpy(sample.insn, btsq->intel_pt_insn.buf, INTEL_PT_INSN_BUF_SZ);
 
 	if (bts->synth_opts.inject) {
 		event.sample.header.size = bts->branches_event_size;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 16c06d3ae577..e4e7dc781d21 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -980,6 +980,8 @@ out:
 out_no_progress:
 	decoder->state.insn_op = intel_pt_insn->op;
 	decoder->state.insn_len = intel_pt_insn->length;
+	memcpy(decoder->state.insn, intel_pt_insn->buf,
+	       INTEL_PT_INSN_BUF_SZ);
 
 	if (decoder->tx_flags & INTEL_PT_IN_TX)
 		decoder->state.flags |= INTEL_PT_IN_TX;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 89399985fa4d..e90619a43c0c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -66,6 +66,7 @@ struct intel_pt_state {
 	uint32_t flags;
 	enum intel_pt_insn_op insn_op;
 	int insn_len;
+	char insn[INTEL_PT_INSN_BUF_SZ];
 };
 
 struct intel_pt_insn;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index 5f95cd442075..7913363bde5c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -27,7 +27,7 @@
 
 #include "intel-pt-insn-decoder.h"
 
-#if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE
+#if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE || INTEL_PT_INSN_BUF_SZ > MAX_INSN
 #error Instruction buffer size too small
 #endif
 
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 815a14d8904b..85d5eeb66c75 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -143,6 +143,7 @@ struct intel_pt_queue {
 	u32 flags;
 	u16 insn_len;
 	u64 last_insn_cnt;
+	char insn[INTEL_PT_INSN_BUF_SZ];
 };
 
 static void intel_pt_dump(struct intel_pt *pt __maybe_unused,
@@ -315,6 +316,7 @@ struct intel_pt_cache_entry {
 	enum intel_pt_insn_branch	branch;
 	int				length;
 	int32_t				rel;
+	char				insn[INTEL_PT_INSN_BUF_SZ];
 };
 
 static int intel_pt_config_div(const char *var, const char *value, void *data)
@@ -400,6 +402,7 @@ static int intel_pt_cache_add(struct dso *dso, struct machine *machine,
 	e->branch = intel_pt_insn->branch;
 	e->length = intel_pt_insn->length;
 	e->rel = intel_pt_insn->rel;
+	memcpy(e->insn, intel_pt_insn->buf, INTEL_PT_INSN_BUF_SZ);
 
 	err = auxtrace_cache__add(c, offset, &e->entry);
 	if (err)
@@ -436,6 +439,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 	u64 insn_cnt = 0;
 	bool one_map = true;
 
+	intel_pt_insn->length = 0;
+
 	if (to_ip && *ip == to_ip)
 		goto out_no_cache;
 
@@ -475,6 +480,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 				intel_pt_insn->branch = e->branch;
 				intel_pt_insn->length = e->length;
 				intel_pt_insn->rel = e->rel;
+				memcpy(intel_pt_insn->buf, e->insn,
+				       INTEL_PT_INSN_BUF_SZ);
 				intel_pt_log_insn_no_data(intel_pt_insn, *ip);
 				return 0;
 			}
@@ -898,6 +905,7 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq)
 		if (ptq->state->flags & INTEL_PT_IN_TX)
 			ptq->flags |= PERF_IP_FLAG_IN_TX;
 		ptq->insn_len = ptq->state->insn_len;
+		memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ);
 	}
 }
 
@@ -1078,6 +1086,7 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
 	sample.cpu = ptq->cpu;
 	sample.flags = ptq->flags;
 	sample.insn_len = ptq->insn_len;
+	memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
 
 	/*
 	 * perf report cannot handle events without a branch stack when using
@@ -1139,6 +1148,7 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
 	sample.cpu = ptq->cpu;
 	sample.flags = ptq->flags;
 	sample.insn_len = ptq->insn_len;
+	memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
 
 	ptq->last_insn_cnt = ptq->state->tot_insn_cnt;
 
@@ -1201,6 +1211,7 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
 	sample.cpu = ptq->cpu;
 	sample.flags = ptq->flags;
 	sample.insn_len = ptq->insn_len;
+	memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
 
 	if (pt->synth_opts.callchain) {
 		thread_stack__sample(ptq->thread, ptq->chain,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH V3 3/3] perf tools: Support insn and insnlen in perf script
  2016-10-07 13:42 [PATCH V3 0/3] perf tools: Support insn and insnlen in perf script Adrian Hunter
  2016-10-07 13:42 ` [PATCH V3 1/3] perf intel-pt/bts: Tidy instruction buffer size usage Adrian Hunter
  2016-10-07 13:42 ` [PATCH V3 2/3] perf intel-pt/bts: Report instruction bytes and length in sample Adrian Hunter
@ 2016-10-07 13:42 ` Adrian Hunter
  2016-10-24 18:50   ` [tip:perf/core] perf script: Support insn and insnlen tip-bot for Andi Kleen
  2 siblings, 1 reply; 7+ messages in thread
From: Adrian Hunter @ 2016-10-07 13:42 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Andi Kleen; +Cc: linux-kernel

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

When looking at Intel PT traces with perf script it is useful to have
some indication of the instruction. Dump the instruction bytes and
instruction length, which can be used for simple pattern analysis in
scripts.

% perf record -e intel_pt// foo
% perf script --itrace=i0ns -F ip,insn,insnlen
 ffffffff8101232f ilen: 5 insn: 0f 1f 44 00 00
 ffffffff81012334 ilen: 1 insn: 5b
 ffffffff81012335 ilen: 1 insn: 5d
 ffffffff81012336 ilen: 1 insn: c3
 ffffffff810123e3 ilen: 1 insn: 5b
 ffffffff810123e4 ilen: 2 insn: 41 5c
 ffffffff810123e6 ilen: 1 insn: 5d
 ffffffff810123e7 ilen: 1 insn: c3
 ffffffff810124a6 ilen: 2 insn: 31 c0
 ffffffff810124a8 ilen: 9 insn: 41 83 bc 24 a8 01 00 00 01
 ffffffff810124b1 ilen: 2 insn: 75 87
...

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/Documentation/perf-script.txt |  6 +++++-
 tools/perf/builtin-script.c              | 24 ++++++++++++++++++++++--
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 053bbbd84ece..c01904f388ce 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -117,7 +117,7 @@ OPTIONS
         Comma separated list of fields to print. Options are:
         comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
         srcline, period, iregs, brstack, brstacksym, flags, bpf-output,
-        callindent. Field list can be prepended with the type, trace, sw or hw,
+        callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw,
         to indicate to which event type the field list applies.
         e.g., -F sw:comm,tid,time,ip,sym  and -F trace:time,cpu,trace
 
@@ -181,6 +181,10 @@ OPTIONS
 	Instruction Trace decoding. For calls and returns, it will display the
 	name of the symbol indented with spaces to reflect the stack depth.
 
+	When doing instruction trace decoding insn and insnlen give the
+	instruction bytes and the instruction length of the current
+	instruction.
+
 	Finally, a user may not set fields to none for all event types.
 	i.e., -F "" is not allowed.
 
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 7228d141a789..412fb6e65ac0 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -66,6 +66,8 @@ enum perf_output_field {
 	PERF_OUTPUT_WEIGHT	    = 1U << 18,
 	PERF_OUTPUT_BPF_OUTPUT	    = 1U << 19,
 	PERF_OUTPUT_CALLINDENT	    = 1U << 20,
+	PERF_OUTPUT_INSN	    = 1U << 21,
+	PERF_OUTPUT_INSNLEN	    = 1U << 22,
 };
 
 struct output_option {
@@ -93,6 +95,8 @@ struct output_option {
 	{.str = "weight",   .field = PERF_OUTPUT_WEIGHT},
 	{.str = "bpf-output",   .field = PERF_OUTPUT_BPF_OUTPUT},
 	{.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
+	{.str = "insn", .field = PERF_OUTPUT_INSN},
+	{.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
 };
 
 /* default set to maintain compatibility with current format */
@@ -624,6 +628,20 @@ static void print_sample_callindent(struct perf_sample *sample,
 		printf("%*s", spacing - len, "");
 }
 
+static void print_insn(struct perf_sample *sample,
+		       struct perf_event_attr *attr)
+{
+	if (PRINT_FIELD(INSNLEN))
+		printf(" ilen: %d", sample->insn_len);
+	if (PRINT_FIELD(INSN)) {
+		int i;
+
+		printf(" insn:");
+		for (i = 0; i < sample->insn_len; i++)
+			printf(" %02x", (unsigned char)sample->insn[i]);
+	}
+}
+
 static void print_sample_bts(struct perf_sample *sample,
 			     struct perf_evsel *evsel,
 			     struct thread *thread,
@@ -668,6 +686,8 @@ static void print_sample_bts(struct perf_sample *sample,
 	if (print_srcline_last)
 		map__fprintf_srcline(al->map, al->addr, "\n  ", stdout);
 
+	print_insn(sample, attr);
+
 	printf("\n");
 }
 
@@ -911,7 +931,7 @@ static void process_event(struct perf_script *script,
 
 	if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
 		print_sample_bpf_output(sample);
-
+	print_insn(sample, attr);
 	printf("\n");
 }
 
@@ -2124,7 +2144,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 		     "Valid types: hw,sw,trace,raw. "
 		     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
 		     "addr,symoff,period,iregs,brstack,brstacksym,flags,"
-		     "bpf-output,callindent", parse_output_fields),
+		     "bpf-output,callindent,insn,insnlen", parse_output_fields),
 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
 		    "system-wide collection from all CPUs"),
 	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [tip:perf/core] perf intel-pt/bts: Tidy instruction buffer size usage
  2016-10-07 13:42 ` [PATCH V3 1/3] perf intel-pt/bts: Tidy instruction buffer size usage Adrian Hunter
@ 2016-10-24 18:49   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 7+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-10-24 18:49 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: hpa, linux-kernel, acme, ak, mingo, adrian.hunter, tglx

Commit-ID:  32f98aab75dd385e326c975717f8b730c6c57508
Gitweb:     http://git.kernel.org/tip/32f98aab75dd385e326c975717f8b730c6c57508
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 7 Oct 2016 16:42:25 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 24 Oct 2016 10:31:32 -0300

perf intel-pt/bts: Tidy instruction buffer size usage

Tidy instruction buffer size usage in preparation for copying the
instruction bytes onto samples.

The instruction buffer is presently used for debugging, so rename its
size macro from INTEL_PT_INSN_DBG_BUF_SZ to INTEL_PT_INSN_BUF_SZ, and
use it everywhere.

Note that the maximum instruction size is 15 which is a less efficient size
to copy than 16, which is why a separate buffer size is used.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Link: http://lkml.kernel.org/r/1475847747-30994-2-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-bts.c                              |  8 +++-----
 tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c | 13 ++++++-------
 tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h |  6 ++----
 tools/perf/util/intel-pt-decoder/intel-pt-log.c          |  4 ++--
 tools/perf/util/intel-pt.c                               |  8 +++-----
 5 files changed, 16 insertions(+), 23 deletions(-)

diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index f545ec1..8bc7fec 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -319,15 +319,12 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
 	struct machine *machine = btsq->bts->machine;
 	struct thread *thread;
 	struct addr_location al;
-	unsigned char buf[1024];
-	size_t bufsz;
+	unsigned char buf[INTEL_PT_INSN_BUF_SZ];
 	ssize_t len;
 	int x86_64;
 	uint8_t cpumode;
 	int err = -1;
 
-	bufsz = intel_pt_insn_max_size();
-
 	if (machine__kernel_ip(machine, ip))
 		cpumode = PERF_RECORD_MISC_KERNEL;
 	else
@@ -341,7 +338,8 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
 	if (!al.map || !al.map->dso)
 		goto out_put;
 
-	len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf, bufsz);
+	len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf,
+				  INTEL_PT_INSN_BUF_SZ);
 	if (len <= 0)
 		goto out_put;
 
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index d23138c..5f95cd44 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -27,6 +27,10 @@
 
 #include "intel-pt-insn-decoder.h"
 
+#if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE
+#error Instruction buffer size too small
+#endif
+
 /* Based on branch_type() from perf_event_intel_lbr.c */
 static void intel_pt_insn_decoder(struct insn *insn,
 				  struct intel_pt_insn *intel_pt_insn)
@@ -166,10 +170,10 @@ int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
 	if (!insn_complete(&insn) || insn.length > len)
 		return -1;
 	intel_pt_insn_decoder(&insn, intel_pt_insn);
-	if (insn.length < INTEL_PT_INSN_DBG_BUF_SZ)
+	if (insn.length < INTEL_PT_INSN_BUF_SZ)
 		memcpy(intel_pt_insn->buf, buf, insn.length);
 	else
-		memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_DBG_BUF_SZ);
+		memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_BUF_SZ);
 	return 0;
 }
 
@@ -211,11 +215,6 @@ int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
 	return 0;
 }
 
-size_t intel_pt_insn_max_size(void)
-{
-	return MAX_INSN_SIZE;
-}
-
 int intel_pt_insn_type(enum intel_pt_insn_op op)
 {
 	switch (op) {
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
index b0adbf3..37ec562 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
@@ -20,7 +20,7 @@
 #include <stdint.h>
 
 #define INTEL_PT_INSN_DESC_MAX		32
-#define INTEL_PT_INSN_DBG_BUF_SZ	16
+#define INTEL_PT_INSN_BUF_SZ		16
 
 enum intel_pt_insn_op {
 	INTEL_PT_OP_OTHER,
@@ -47,7 +47,7 @@ struct intel_pt_insn {
 	enum intel_pt_insn_branch	branch;
 	int				length;
 	int32_t				rel;
-	unsigned char			buf[INTEL_PT_INSN_DBG_BUF_SZ];
+	unsigned char			buf[INTEL_PT_INSN_BUF_SZ];
 };
 
 int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
@@ -58,8 +58,6 @@ const char *intel_pt_insn_name(enum intel_pt_insn_op op);
 int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
 		       size_t buf_len);
 
-size_t intel_pt_insn_max_size(void);
-
 int intel_pt_insn_type(enum intel_pt_insn_op op);
 
 #endif
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
index 319bef3..e02bc7b 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
@@ -119,8 +119,8 @@ void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
 	if (intel_pt_log_open())
 		return;
 
-	if (len > INTEL_PT_INSN_DBG_BUF_SZ)
-		len = INTEL_PT_INSN_DBG_BUF_SZ;
+	if (len > INTEL_PT_INSN_BUF_SZ)
+		len = INTEL_PT_INSN_BUF_SZ;
 	intel_pt_print_data(intel_pt_insn->buf, len, ip, 8);
 	if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0)
 		fprintf(f, "%s\n", desc);
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index dc041d4..815a14d 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -428,8 +428,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 	struct machine *machine = ptq->pt->machine;
 	struct thread *thread;
 	struct addr_location al;
-	unsigned char buf[1024];
-	size_t bufsz;
+	unsigned char buf[INTEL_PT_INSN_BUF_SZ];
 	ssize_t len;
 	int x86_64;
 	u8 cpumode;
@@ -440,8 +439,6 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 	if (to_ip && *ip == to_ip)
 		goto out_no_cache;
 
-	bufsz = intel_pt_insn_max_size();
-
 	if (*ip >= ptq->pt->kernel_start)
 		cpumode = PERF_RECORD_MISC_KERNEL;
 	else
@@ -493,7 +490,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 
 		while (1) {
 			len = dso__data_read_offset(al.map->dso, machine,
-						    offset, buf, bufsz);
+						    offset, buf,
+						    INTEL_PT_INSN_BUF_SZ);
 			if (len <= 0)
 				return -EINVAL;
 

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [tip:perf/core] perf intel-pt/bts: Report instruction bytes and length in sample
  2016-10-07 13:42 ` [PATCH V3 2/3] perf intel-pt/bts: Report instruction bytes and length in sample Adrian Hunter
@ 2016-10-24 18:50   ` tip-bot for Andi Kleen
  0 siblings, 0 replies; 7+ messages in thread
From: tip-bot for Andi Kleen @ 2016-10-24 18:50 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: tglx, adrian.hunter, hpa, linux-kernel, ak, mingo, acme

Commit-ID:  faaa87680b25d9ec91a308d4c957f5b9305c7b59
Gitweb:     http://git.kernel.org/tip/faaa87680b25d9ec91a308d4c957f5b9305c7b59
Author:     Andi Kleen <ak@linux.intel.com>
AuthorDate: Fri, 7 Oct 2016 16:42:26 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 24 Oct 2016 10:31:32 -0300

perf intel-pt/bts: Report instruction bytes and length in sample

Change Intel PT and BTS to pass up the length and the instruction
bytes of the decoded or sampled instruction in the perf sample.

The decoder already knows this information, we just need to pass it
up. Since it is only a couple of movs it is not very expensive.

Handle instruction cache too. Make sure ilen is always initialized.

Used in the next patch.

[Adrian: re-base on top (and adjust for) instruction buffer size tidy-up]
[Adrian: add BTS support and adjust commit message accordingly]

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Link: http://lkml.kernel.org/r/1475847747-30994-3-git-send-email-adrian.hunter@intel.com
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.h                                  |  3 +++
 tools/perf/util/intel-bts.c                              |  1 +
 tools/perf/util/intel-pt-decoder/intel-pt-decoder.c      |  2 ++
 tools/perf/util/intel-pt-decoder/intel-pt-decoder.h      |  1 +
 tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c |  2 +-
 tools/perf/util/intel-pt.c                               | 11 +++++++++++
 6 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8d363d5..c735c53 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -177,6 +177,8 @@ enum {
 	PERF_IP_FLAG_TRACE_BEGIN	|\
 	PERF_IP_FLAG_TRACE_END)
 
+#define MAX_INSN 16
+
 struct perf_sample {
 	u64 ip;
 	u32 pid, tid;
@@ -193,6 +195,7 @@ struct perf_sample {
 	u32 flags;
 	u16 insn_len;
 	u8  cpumode;
+	char insn[MAX_INSN];
 	void *raw_data;
 	struct ip_callchain *callchain;
 	struct branch_stack *branch_stack;
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 8bc7fec..6c2eb5d 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -295,6 +295,7 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
 	sample.cpu = btsq->cpu;
 	sample.flags = btsq->sample_flags;
 	sample.insn_len = btsq->intel_pt_insn.length;
+	memcpy(sample.insn, btsq->intel_pt_insn.buf, INTEL_PT_INSN_BUF_SZ);
 
 	if (bts->synth_opts.inject) {
 		event.sample.header.size = bts->branches_event_size;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 16c06d3..e4e7dc7 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -980,6 +980,8 @@ out:
 out_no_progress:
 	decoder->state.insn_op = intel_pt_insn->op;
 	decoder->state.insn_len = intel_pt_insn->length;
+	memcpy(decoder->state.insn, intel_pt_insn->buf,
+	       INTEL_PT_INSN_BUF_SZ);
 
 	if (decoder->tx_flags & INTEL_PT_IN_TX)
 		decoder->state.flags |= INTEL_PT_IN_TX;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 8939998..e90619a 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -66,6 +66,7 @@ struct intel_pt_state {
 	uint32_t flags;
 	enum intel_pt_insn_op insn_op;
 	int insn_len;
+	char insn[INTEL_PT_INSN_BUF_SZ];
 };
 
 struct intel_pt_insn;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index 5f95cd44..7913363 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -27,7 +27,7 @@
 
 #include "intel-pt-insn-decoder.h"
 
-#if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE
+#if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE || INTEL_PT_INSN_BUF_SZ > MAX_INSN
 #error Instruction buffer size too small
 #endif
 
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 815a14d..85d5eeb 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -143,6 +143,7 @@ struct intel_pt_queue {
 	u32 flags;
 	u16 insn_len;
 	u64 last_insn_cnt;
+	char insn[INTEL_PT_INSN_BUF_SZ];
 };
 
 static void intel_pt_dump(struct intel_pt *pt __maybe_unused,
@@ -315,6 +316,7 @@ struct intel_pt_cache_entry {
 	enum intel_pt_insn_branch	branch;
 	int				length;
 	int32_t				rel;
+	char				insn[INTEL_PT_INSN_BUF_SZ];
 };
 
 static int intel_pt_config_div(const char *var, const char *value, void *data)
@@ -400,6 +402,7 @@ static int intel_pt_cache_add(struct dso *dso, struct machine *machine,
 	e->branch = intel_pt_insn->branch;
 	e->length = intel_pt_insn->length;
 	e->rel = intel_pt_insn->rel;
+	memcpy(e->insn, intel_pt_insn->buf, INTEL_PT_INSN_BUF_SZ);
 
 	err = auxtrace_cache__add(c, offset, &e->entry);
 	if (err)
@@ -436,6 +439,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 	u64 insn_cnt = 0;
 	bool one_map = true;
 
+	intel_pt_insn->length = 0;
+
 	if (to_ip && *ip == to_ip)
 		goto out_no_cache;
 
@@ -475,6 +480,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 				intel_pt_insn->branch = e->branch;
 				intel_pt_insn->length = e->length;
 				intel_pt_insn->rel = e->rel;
+				memcpy(intel_pt_insn->buf, e->insn,
+				       INTEL_PT_INSN_BUF_SZ);
 				intel_pt_log_insn_no_data(intel_pt_insn, *ip);
 				return 0;
 			}
@@ -898,6 +905,7 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq)
 		if (ptq->state->flags & INTEL_PT_IN_TX)
 			ptq->flags |= PERF_IP_FLAG_IN_TX;
 		ptq->insn_len = ptq->state->insn_len;
+		memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ);
 	}
 }
 
@@ -1078,6 +1086,7 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
 	sample.cpu = ptq->cpu;
 	sample.flags = ptq->flags;
 	sample.insn_len = ptq->insn_len;
+	memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
 
 	/*
 	 * perf report cannot handle events without a branch stack when using
@@ -1139,6 +1148,7 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
 	sample.cpu = ptq->cpu;
 	sample.flags = ptq->flags;
 	sample.insn_len = ptq->insn_len;
+	memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
 
 	ptq->last_insn_cnt = ptq->state->tot_insn_cnt;
 
@@ -1201,6 +1211,7 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
 	sample.cpu = ptq->cpu;
 	sample.flags = ptq->flags;
 	sample.insn_len = ptq->insn_len;
+	memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
 
 	if (pt->synth_opts.callchain) {
 		thread_stack__sample(ptq->thread, ptq->chain,

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [tip:perf/core] perf script: Support insn and insnlen
  2016-10-07 13:42 ` [PATCH V3 3/3] perf tools: Support insn and insnlen in perf script Adrian Hunter
@ 2016-10-24 18:50   ` tip-bot for Andi Kleen
  0 siblings, 0 replies; 7+ messages in thread
From: tip-bot for Andi Kleen @ 2016-10-24 18:50 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: tglx, acme, adrian.hunter, hpa, ak, linux-kernel, mingo

Commit-ID:  224e2c977b647d1ae72bf1d8e3424cd3e5e83f0c
Gitweb:     http://git.kernel.org/tip/224e2c977b647d1ae72bf1d8e3424cd3e5e83f0c
Author:     Andi Kleen <ak@linux.intel.com>
AuthorDate: Fri, 7 Oct 2016 16:42:27 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 24 Oct 2016 11:07:30 -0300

perf script: Support insn and insnlen

When looking at Intel PT traces with perf script it is useful to have
some indication of the instruction. Dump the instruction bytes and
instruction length, which can be used for simple pattern analysis in
scripts.

% perf record -e intel_pt// foo
% perf script --itrace=i0ns -F ip,insn,insnlen
 ffffffff8101232f ilen: 5 insn: 0f 1f 44 00 00
 ffffffff81012334 ilen: 1 insn: 5b
 ffffffff81012335 ilen: 1 insn: 5d
 ffffffff81012336 ilen: 1 insn: c3
 ffffffff810123e3 ilen: 1 insn: 5b
 ffffffff810123e4 ilen: 2 insn: 41 5c
 ffffffff810123e6 ilen: 1 insn: 5d
 ffffffff810123e7 ilen: 1 insn: c3
 ffffffff810124a6 ilen: 2 insn: 31 c0
 ffffffff810124a8 ilen: 9 insn: 41 83 bc 24 a8 01 00 00 01
 ffffffff810124b1 ilen: 2 insn: 75 87
...

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Link: http://lkml.kernel.org/r/1475847747-30994-4-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-script.txt |  6 +++++-
 tools/perf/builtin-script.c              | 24 ++++++++++++++++++++++--
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 053bbbd..c01904f 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -117,7 +117,7 @@ OPTIONS
         Comma separated list of fields to print. Options are:
         comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
         srcline, period, iregs, brstack, brstacksym, flags, bpf-output,
-        callindent. Field list can be prepended with the type, trace, sw or hw,
+        callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw,
         to indicate to which event type the field list applies.
         e.g., -F sw:comm,tid,time,ip,sym  and -F trace:time,cpu,trace
 
@@ -181,6 +181,10 @@ OPTIONS
 	Instruction Trace decoding. For calls and returns, it will display the
 	name of the symbol indented with spaces to reflect the stack depth.
 
+	When doing instruction trace decoding insn and insnlen give the
+	instruction bytes and the instruction length of the current
+	instruction.
+
 	Finally, a user may not set fields to none for all event types.
 	i.e., -F "" is not allowed.
 
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 7228d14..412fb6e 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -66,6 +66,8 @@ enum perf_output_field {
 	PERF_OUTPUT_WEIGHT	    = 1U << 18,
 	PERF_OUTPUT_BPF_OUTPUT	    = 1U << 19,
 	PERF_OUTPUT_CALLINDENT	    = 1U << 20,
+	PERF_OUTPUT_INSN	    = 1U << 21,
+	PERF_OUTPUT_INSNLEN	    = 1U << 22,
 };
 
 struct output_option {
@@ -93,6 +95,8 @@ struct output_option {
 	{.str = "weight",   .field = PERF_OUTPUT_WEIGHT},
 	{.str = "bpf-output",   .field = PERF_OUTPUT_BPF_OUTPUT},
 	{.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
+	{.str = "insn", .field = PERF_OUTPUT_INSN},
+	{.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
 };
 
 /* default set to maintain compatibility with current format */
@@ -624,6 +628,20 @@ static void print_sample_callindent(struct perf_sample *sample,
 		printf("%*s", spacing - len, "");
 }
 
+static void print_insn(struct perf_sample *sample,
+		       struct perf_event_attr *attr)
+{
+	if (PRINT_FIELD(INSNLEN))
+		printf(" ilen: %d", sample->insn_len);
+	if (PRINT_FIELD(INSN)) {
+		int i;
+
+		printf(" insn:");
+		for (i = 0; i < sample->insn_len; i++)
+			printf(" %02x", (unsigned char)sample->insn[i]);
+	}
+}
+
 static void print_sample_bts(struct perf_sample *sample,
 			     struct perf_evsel *evsel,
 			     struct thread *thread,
@@ -668,6 +686,8 @@ static void print_sample_bts(struct perf_sample *sample,
 	if (print_srcline_last)
 		map__fprintf_srcline(al->map, al->addr, "\n  ", stdout);
 
+	print_insn(sample, attr);
+
 	printf("\n");
 }
 
@@ -911,7 +931,7 @@ static void process_event(struct perf_script *script,
 
 	if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
 		print_sample_bpf_output(sample);
-
+	print_insn(sample, attr);
 	printf("\n");
 }
 
@@ -2124,7 +2144,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 		     "Valid types: hw,sw,trace,raw. "
 		     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
 		     "addr,symoff,period,iregs,brstack,brstacksym,flags,"
-		     "bpf-output,callindent", parse_output_fields),
+		     "bpf-output,callindent,insn,insnlen", parse_output_fields),
 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
 		    "system-wide collection from all CPUs"),
 	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-10-24 19:43 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-07 13:42 [PATCH V3 0/3] perf tools: Support insn and insnlen in perf script Adrian Hunter
2016-10-07 13:42 ` [PATCH V3 1/3] perf intel-pt/bts: Tidy instruction buffer size usage Adrian Hunter
2016-10-24 18:49   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-10-07 13:42 ` [PATCH V3 2/3] perf intel-pt/bts: Report instruction bytes and length in sample Adrian Hunter
2016-10-24 18:50   ` [tip:perf/core] " tip-bot for Andi Kleen
2016-10-07 13:42 ` [PATCH V3 3/3] perf tools: Support insn and insnlen in perf script Adrian Hunter
2016-10-24 18:50   ` [tip:perf/core] perf script: Support insn and insnlen tip-bot for Andi Kleen

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.