diff options
| author | Ingo Molnar <mingo@kernel.org> | 2016-02-25 08:20:56 +0100 | 
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2016-02-25 08:20:56 +0100 | 
| commit | 06466212a69c0511c5dcff7363c207ffc8913731 (patch) | |
| tree | 0a29bc742ef0fe77a40289fe7f57f1ea078ecd52 /tools/perf/builtin-script.c | |
| parent | c2b8d8c55c0235e21c563283f634bcfd2ba7bc1e (diff) | |
| parent | c92fcfde3486fb4b9e476ee5ad5995a62e401cce (diff) | |
Merge tag 'perf-core-for-mingo-20160224' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements from Arnaldo Carvalho de Melo:
User visible changes:
  - Hierarchy histogram mode for 'perf top' and 'perf report', showing multiple
    levels, one per --sort entry: (Namhyung Kim)
    On a mostly idle system:
    # perf top --hierarchy -s comm,dso
    Then expand some levels and use 'P' to take a snapshot:
    # cat perf.hist.0
    -  92.32%         perf
          58.20%         perf
          22.29%         libc-2.22.so
           5.97%         [kernel]
           4.18%         libelf-0.165.so
           1.69%         [unknown]
    -   4.71%         qemu-system-x86
           3.10%         [kernel]
           1.60%         qemu-system-x86_64 (deleted)
    +   2.97%         swapper
    #
  - Check availability of memory events in 'perf mem': (Jiri Olsa)
    On a Intel Broadwell machine:
    # perf mem record -e list
    ldlat-loads : available
    ldlat-stores: available
    #
  - Decode data_src values (e.g. perf.data files generated by 'perf mem record')
    in 'perf script': (Jiri Olsa)
    # perf script
      perf 693 [1] 4.088652: 1 cpu/mem-loads,ldlat=30/P: ffff88007d0b0f40 68100142 L1 hit|SNP None|TLB L1 or L2 hit|LCK No <SNIP>
                                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  - Print bpf-output events in 'perf script': (Wang Nan).
    # perf record -e bpf-output/no-inherit,name=evt/ -e ./test_bpf_output_3.c/map:channel.event=evt/ usleep 1000
    # perf script
       usleep  4882 21384.532523:   evt:  ffffffff810e97d1 sys_nanosleep ([kernel.kallsyms])
        BPF output: 0000: 52 61 69 73 65 20 61 20  Raise a
                    0008: 42 50 46 20 65 76 65 6e  BPF even
                    0010: 74 21 00 00              t!..
        BPF string: "Raise a BPF event!"
    #
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/builtin-script.c')
| -rw-r--r-- | tools/perf/builtin-script.c | 113 | 
1 files changed, 107 insertions, 6 deletions
| diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index f4caf4898245..ec4fbd410a4b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -23,6 +23,7 @@  #include "util/stat.h"  #include <linux/bitmap.h>  #include "asm/bug.h" +#include "util/mem-events.h"  static char const		*script_name;  static char const		*generate_script_lang; @@ -60,6 +61,7 @@ enum perf_output_field {  	PERF_OUTPUT_BRSTACKSYM	    = 1U << 16,  	PERF_OUTPUT_DATA_SRC	    = 1U << 17,  	PERF_OUTPUT_WEIGHT	    = 1U << 18, +	PERF_OUTPUT_BPF_OUTPUT	    = 1U << 19,  };  struct output_option { @@ -85,6 +87,7 @@ struct output_option {  	{.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},  	{.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},  	{.str = "weight",   .field = PERF_OUTPUT_WEIGHT}, +	{.str = "bpf-output",   .field = PERF_OUTPUT_BPF_OUTPUT},  };  /* default set to maintain compatibility with current format */ @@ -105,7 +108,7 @@ static struct {  			      PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |  			      PERF_OUTPUT_PERIOD, -		.invalid_fields = PERF_OUTPUT_TRACE, +		.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,  	},  	[PERF_TYPE_SOFTWARE] = { @@ -115,7 +118,7 @@ static struct {  			      PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |  			      PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |  			      PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | -			      PERF_OUTPUT_PERIOD, +			      PERF_OUTPUT_PERIOD | PERF_OUTPUT_BPF_OUTPUT,  		.invalid_fields = PERF_OUTPUT_TRACE,  	}, @@ -125,7 +128,7 @@ static struct {  		.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |  				  PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | -				  PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE, +				  PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE  	},  	[PERF_TYPE_RAW] = { @@ -138,7 +141,7 @@ static struct {  			      PERF_OUTPUT_PERIOD |  PERF_OUTPUT_ADDR |  			      PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT, -		.invalid_fields = PERF_OUTPUT_TRACE, +		.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,  	},  	[PERF_TYPE_BREAKPOINT] = { @@ -150,7 +153,7 @@ static struct {  			      PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |  			      PERF_OUTPUT_PERIOD, -		.invalid_fields = PERF_OUTPUT_TRACE, +		.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,  	},  }; @@ -623,6 +626,84 @@ static void print_sample_flags(u32 flags)  	printf("  %-4s ", str);  } +struct printer_data { +	int line_no; +	bool hit_nul; +	bool is_printable; +}; + +static void +print_sample_bpf_output_printer(enum binary_printer_ops op, +				unsigned int val, +				void *extra) +{ +	unsigned char ch = (unsigned char)val; +	struct printer_data *printer_data = extra; + +	switch (op) { +	case BINARY_PRINT_DATA_BEGIN: +		printf("\n"); +		break; +	case BINARY_PRINT_LINE_BEGIN: +		printf("%17s", !printer_data->line_no ? "BPF output:" : +						        "           "); +		break; +	case BINARY_PRINT_ADDR: +		printf(" %04x:", val); +		break; +	case BINARY_PRINT_NUM_DATA: +		printf(" %02x", val); +		break; +	case BINARY_PRINT_NUM_PAD: +		printf("   "); +		break; +	case BINARY_PRINT_SEP: +		printf("  "); +		break; +	case BINARY_PRINT_CHAR_DATA: +		if (printer_data->hit_nul && ch) +			printer_data->is_printable = false; + +		if (!isprint(ch)) { +			printf("%c", '.'); + +			if (!printer_data->is_printable) +				break; + +			if (ch == '\0') +				printer_data->hit_nul = true; +			else +				printer_data->is_printable = false; +		} else { +			printf("%c", ch); +		} +		break; +	case BINARY_PRINT_CHAR_PAD: +		printf(" "); +		break; +	case BINARY_PRINT_LINE_END: +		printf("\n"); +		printer_data->line_no++; +		break; +	case BINARY_PRINT_DATA_END: +	default: +		break; +	} +} + +static void print_sample_bpf_output(struct perf_sample *sample) +{ +	unsigned int nr_bytes = sample->raw_size; +	struct printer_data printer_data = {0, false, true}; + +	print_binary(sample->raw_data, nr_bytes, 8, +		     print_sample_bpf_output_printer, &printer_data); + +	if (printer_data.is_printable && printer_data.hit_nul) +		printf("%17s \"%s\"\n", "BPF string:", +		       (char *)(sample->raw_data)); +} +  struct perf_script {  	struct perf_tool	tool;  	struct perf_session	*session; @@ -649,6 +730,23 @@ static int perf_evlist__max_name_len(struct perf_evlist *evlist)  	return max;  } +static size_t data_src__printf(u64 data_src) +{ +	struct mem_info mi = { .data_src.val = data_src }; +	char decode[100]; +	char out[100]; +	static int maxlen; +	int len; + +	perf_script__meminfo_scnprintf(decode, 100, &mi); + +	len = scnprintf(out, 100, "%16" PRIx64 " %s", data_src, decode); +	if (maxlen < len) +		maxlen = len; + +	return printf("%-*s", maxlen, out); +} +  static void process_event(struct perf_script *script, union perf_event *event,  			  struct perf_sample *sample, struct perf_evsel *evsel,  			  struct addr_location *al) @@ -689,7 +787,7 @@ static void process_event(struct perf_script *script, union perf_event *event,  		print_sample_addr(event, sample, thread, attr);  	if (PRINT_FIELD(DATA_SRC)) -		printf("%16" PRIx64, sample->data_src); +		data_src__printf(sample->data_src);  	if (PRINT_FIELD(WEIGHT))  		printf("%16" PRIu64, sample->weight); @@ -713,6 +811,9 @@ static void process_event(struct perf_script *script, union perf_event *event,  	else if (PRINT_FIELD(BRSTACKSYM))  		print_sample_brstacksym(event, sample, thread, attr); +	if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) +		print_sample_bpf_output(sample); +  	printf("\n");  } | 
