perf tools: Support insn and insnlen in perf script
Adrian Hunter
reviewerv3 cover perf tools: Support insn and insnlen in perf script
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
Adrian Hunter
reviewerPATCH v3 1/3 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.
--- 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(-)
tools/perf/util/intel-bts.c +3 -5
@@ -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;
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c +6 -7
@@ -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) {
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h +2 -4
@@ -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 16enum 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
tools/perf/util/intel-pt-decoder/intel-pt-log.c +2 -2
@@ -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);
tools/perf/util/intel-pt.c +3 -5
@@ -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 ;
Signature · 1 line
1.9.1
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf intel-pt/bts: Tidy instruction buffer size usage
perf intel-pt/bts: Tidy instruction buffer size usage
Commit-ID: 32f98aab75dd385e326c975717f8b730c6c57508 Gitweb: http://git.kernel.org/tip/32f98aab75dd385e326c975717f8b730c6c57508 Author: Adrian Hunter <[email protected]> AuthorDate: Fri, 7 Oct 2016 16:42:25 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> 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.
--- 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(-)
tools/perf/util/intel-bts.c +3 -5
@@ -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;
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c +6 -7
@@ -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) {
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h +2 -4
@@ -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 16enum 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
tools/perf/util/intel-pt-decoder/intel-pt-log.c +2 -2
@@ -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);
tools/perf/util/intel-pt.c +3 -5
@@ -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 ;
Adrian Hunter
reviewerPATCH v3 2/3 perf intel-pt/bts: Report instruction bytes and length in sample
In reply to Adrian HunterFrom: Andi Kleen <[email protected]>
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]
--- 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(-)
tools/perf/util/event.h +3 -0
@@ -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;
tools/perf/util/intel-bts.c +1 -0
@@ -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;
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +2 -0
@@ -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 ;
tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +1 -0
@@ -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 ;
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c +1 -1
@@ -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
tools/perf/util/intel-pt.c +11 -0
@@ -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,
Signature · 1 line
1.9.1
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf intel-pt/bts: Report instruction bytes and length in sample
perf intel-pt/bts: Report instruction bytes and length in sample
Commit-ID: faaa87680b25d9ec91a308d4c957f5b9305c7b59 Gitweb: http://git.kernel.org/tip/faaa87680b25d9ec91a308d4c957f5b9305c7b59 Author: Andi Kleen <[email protected]> AuthorDate: Fri, 7 Oct 2016 16:42:26 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> 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]
--- 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(-)
tools/perf/util/event.h +3 -0
@@ -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;
tools/perf/util/intel-bts.c +1 -0
@@ -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;
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +2 -0
@@ -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 ;
tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +1 -0
@@ -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 ;
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c +1 -1
@@ -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
tools/perf/util/intel-pt.c +11 -0
@@ -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,
Adrian Hunter
reviewerPATCH v3 3/3 perf tools: Support insn and insnlen in perf script
In reply to Adrian HunterFrom: Andi Kleen <[email protected]>
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
...
--- tools/perf/Documentation/perf-script.txt | 6 +++++- tools/perf/builtin-script.c | 24 ++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-script.txt +5 -1
@@ -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.
tools/perf/builtin-script.c +22 -2
@@ -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...]",
Signature · 1 line
1.9.1
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf script: Support insn and insnlen
perf script: Support insn and insnlen
Commit-ID: 224e2c977b647d1ae72bf1d8e3424cd3e5e83f0c Gitweb: http://git.kernel.org/tip/224e2c977b647d1ae72bf1d8e3424cd3e5e83f0c Author: Andi Kleen <[email protected]> AuthorDate: Fri, 7 Oct 2016 16:42:27 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> 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
...
--- tools/perf/Documentation/perf-script.txt | 6 +++++- tools/perf/builtin-script.c | 24 ++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-script.txt +5 -1
@@ -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.
tools/perf/builtin-script.c +22 -2
@@ -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...]",