diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
| -rw-r--r-- | tools/perf/builtin-script.c | 66 | 
1 files changed, 53 insertions, 13 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index b1f57401ff23..37088cc0ff1b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -34,6 +34,7 @@  #include "util/event.h"  #include "ui/ui.h"  #include "print_binary.h" +#include "print_insn.h"  #include "archinsn.h"  #include <linux/bitmap.h>  #include <linux/kernel.h> @@ -134,6 +135,7 @@ enum perf_output_field {  	PERF_OUTPUT_CGROUP          = 1ULL << 39,  	PERF_OUTPUT_RETIRE_LAT      = 1ULL << 40,  	PERF_OUTPUT_DSOFF           = 1ULL << 41, +	PERF_OUTPUT_DISASM          = 1ULL << 42,  };  struct perf_script { @@ -189,6 +191,7 @@ struct output_option {  	{.str = "bpf-output",   .field = PERF_OUTPUT_BPF_OUTPUT},  	{.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},  	{.str = "insn", .field = PERF_OUTPUT_INSN}, +	{.str = "disasm", .field = PERF_OUTPUT_DISASM},  	{.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},  	{.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},  	{.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, @@ -1162,7 +1165,8 @@ out:  static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,  			    struct perf_insn *x, u8 *inbuf, int len,  			    int insn, FILE *fp, int *total_cycles, -			    struct perf_event_attr *attr) +			    struct perf_event_attr *attr, +			    struct thread *thread)  {  	int ilen = 0;  	int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t", ip, @@ -1171,6 +1175,16 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,  	if (PRINT_FIELD(BRSTACKINSNLEN))  		printed += fprintf(fp, "ilen: %d\t", ilen); +	if (PRINT_FIELD(SRCLINE)) { +		struct addr_location al; + +		addr_location__init(&al); +		thread__find_map(thread, x->cpumode, ip, &al); +		printed += map__fprintf_srcline(al.map, al.addr, " srcline: ", fp); +		printed += fprintf(fp, "\t"); +		addr_location__exit(&al); +	} +  	printed += fprintf(fp, "#%s%s%s%s",  			      en->flags.predicted ? " PRED" : "",  			      en->flags.mispred ? " MISPRED" : "", @@ -1182,6 +1196,7 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,  		if (insn)  			printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles);  	} +  	return printed + fprintf(fp, "\n");  } @@ -1260,7 +1275,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,  					   x.cpumode, x.cpu, &lastsym, attr, fp);  		printed += ip__fprintf_jump(entries[nr - 1].from, &entries[nr - 1],  					    &x, buffer, len, 0, fp, &total_cycles, -					    attr); +					    attr, thread);  		if (PRINT_FIELD(SRCCODE))  			printed += print_srccode(thread, x.cpumode, entries[nr - 1].from);  	} @@ -1291,7 +1306,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,  			printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);  			if (ip == end) {  				printed += ip__fprintf_jump(ip, &entries[i], &x, buffer + off, len - off, ++insn, fp, -							    &total_cycles, attr); +							    &total_cycles, attr, thread);  				if (PRINT_FIELD(SRCCODE))  					printed += print_srccode(thread, x.cpumode, ip);  				break; @@ -1511,11 +1526,12 @@ static int perf_sample__fprintf_insn(struct perf_sample *sample,  	if (PRINT_FIELD(INSNLEN))  		printed += fprintf(fp, " ilen: %d", sample->insn_len);  	if (PRINT_FIELD(INSN) && sample->insn_len) { -		int i; - -		printed += fprintf(fp, " insn:"); -		for (i = 0; i < sample->insn_len; i++) -			printed += fprintf(fp, " %02x", (unsigned char)sample->insn[i]); +		printed += fprintf(fp, " insn: "); +		printed += sample__fprintf_insn_raw(sample, fp); +	} +	if (PRINT_FIELD(DISASM) && sample->insn_len) { +		printed += fprintf(fp, "\t\t"); +		printed += sample__fprintf_insn_asm(sample, thread, machine, fp);  	}  	if (PRINT_FIELD(BRSTACKINSN) || PRINT_FIELD(BRSTACKINSNLEN))  		printed += perf_sample__fprintf_brstackinsn(sample, thread, attr, machine, fp); @@ -3108,6 +3124,13 @@ parse:  			rc = -EINVAL;  			goto out;  		} +#ifndef HAVE_LIBCAPSTONE_SUPPORT +		if (change != REMOVE && strcmp(tok, "disasm") == 0) { +			fprintf(stderr, "Field \"disasm\" requires perf to be built with libcapstone support.\n"); +			rc = -EINVAL; +			goto out; +		} +#endif  		if (type == -1) {  			/* add user option to all events types for @@ -3765,10 +3788,24 @@ static int perf_script__process_auxtrace_info(struct perf_session *session,  #endif  static int parse_insn_trace(const struct option *opt __maybe_unused, -			    const char *str __maybe_unused, -			    int unset __maybe_unused) +			    const char *str, int unset __maybe_unused)  { -	parse_output_fields(NULL, "+insn,-event,-period", 0); +	const char *fields = "+insn,-event,-period"; +	int ret; + +	if (str) { +		if (strcmp(str, "disasm") == 0) +			fields = "+disasm,-event,-period"; +		else if (strlen(str) != 0 && strcmp(str, "raw") != 0) { +			fprintf(stderr, "Only accept raw|disasm\n"); +			return -EINVAL; +		} +	} + +	ret = parse_output_fields(NULL, fields, 0); +	if (ret < 0) +		return ret; +  	itrace_parse_synth_opts(opt, "i0ns", 0);  	symbol_conf.nanosecs = true;  	return 0; @@ -3902,7 +3939,7 @@ int cmd_script(int argc, const char **argv)  		     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,dsoff,"  		     "addr,symoff,srcline,period,iregs,uregs,brstack,"  		     "brstacksym,flags,data_src,weight,bpf-output,brstackinsn," -		     "brstackinsnlen,brstackoff,callindent,insn,insnlen,synth," +		     "brstackinsnlen,brstackoff,callindent,insn,disasm,insnlen,synth,"  		     "phys_addr,metric,misc,srccode,ipc,tod,data_page_size,"  		     "code_page_size,ins_lat,machine_pid,vcpu,cgroup,retire_lat",  		     parse_output_fields), @@ -3914,7 +3951,7 @@ int cmd_script(int argc, const char **argv)  		   "only consider these symbols"),  	OPT_INTEGER(0, "addr-range", &symbol_conf.addr_range,  		    "Use with -S to list traced records within address range"), -	OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, NULL, +	OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, "raw|disasm",  			"Decode instructions from itrace", parse_insn_trace),  	OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL,  			"Run xed disassembler on output", parse_xed), @@ -4366,6 +4403,9 @@ script_found:  	flush_scripting(); +	if (verbose > 2 || debug_kmaps) +		perf_session__dump_kmaps(session); +  out_delete:  	if (script.ptime_range) {  		itrace_synth_opts__clear_time_range(&itrace_synth_opts);  | 
