aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r--tools/perf/builtin-script.c155
1 files changed, 131 insertions, 24 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index c691214d820f..57f9a7e7f7d3 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -23,6 +23,7 @@
23#include "util/stat.h" 23#include "util/stat.h"
24#include <linux/bitmap.h> 24#include <linux/bitmap.h>
25#include "asm/bug.h" 25#include "asm/bug.h"
26#include "util/mem-events.h"
26 27
27static char const *script_name; 28static char const *script_name;
28static char const *generate_script_lang; 29static char const *generate_script_lang;
@@ -58,6 +59,9 @@ enum perf_output_field {
58 PERF_OUTPUT_IREGS = 1U << 14, 59 PERF_OUTPUT_IREGS = 1U << 14,
59 PERF_OUTPUT_BRSTACK = 1U << 15, 60 PERF_OUTPUT_BRSTACK = 1U << 15,
60 PERF_OUTPUT_BRSTACKSYM = 1U << 16, 61 PERF_OUTPUT_BRSTACKSYM = 1U << 16,
62 PERF_OUTPUT_DATA_SRC = 1U << 17,
63 PERF_OUTPUT_WEIGHT = 1U << 18,
64 PERF_OUTPUT_BPF_OUTPUT = 1U << 19,
61}; 65};
62 66
63struct output_option { 67struct output_option {
@@ -81,6 +85,9 @@ struct output_option {
81 {.str = "iregs", .field = PERF_OUTPUT_IREGS}, 85 {.str = "iregs", .field = PERF_OUTPUT_IREGS},
82 {.str = "brstack", .field = PERF_OUTPUT_BRSTACK}, 86 {.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
83 {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM}, 87 {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
88 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
89 {.str = "weight", .field = PERF_OUTPUT_WEIGHT},
90 {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT},
84}; 91};
85 92
86/* default set to maintain compatibility with current format */ 93/* default set to maintain compatibility with current format */
@@ -101,7 +108,7 @@ static struct {
101 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 108 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
102 PERF_OUTPUT_PERIOD, 109 PERF_OUTPUT_PERIOD,
103 110
104 .invalid_fields = PERF_OUTPUT_TRACE, 111 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
105 }, 112 },
106 113
107 [PERF_TYPE_SOFTWARE] = { 114 [PERF_TYPE_SOFTWARE] = {
@@ -111,7 +118,7 @@ static struct {
111 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 118 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
112 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 119 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
113 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 120 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
114 PERF_OUTPUT_PERIOD, 121 PERF_OUTPUT_PERIOD | PERF_OUTPUT_BPF_OUTPUT,
115 122
116 .invalid_fields = PERF_OUTPUT_TRACE, 123 .invalid_fields = PERF_OUTPUT_TRACE,
117 }, 124 },
@@ -121,7 +128,7 @@ static struct {
121 128
122 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 129 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
123 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 130 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
124 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE, 131 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE
125 }, 132 },
126 133
127 [PERF_TYPE_RAW] = { 134 [PERF_TYPE_RAW] = {
@@ -131,9 +138,10 @@ static struct {
131 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 138 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
132 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 139 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
133 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 140 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
134 PERF_OUTPUT_PERIOD, 141 PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR |
142 PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT,
135 143
136 .invalid_fields = PERF_OUTPUT_TRACE, 144 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
137 }, 145 },
138 146
139 [PERF_TYPE_BREAKPOINT] = { 147 [PERF_TYPE_BREAKPOINT] = {
@@ -145,7 +153,7 @@ static struct {
145 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 153 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
146 PERF_OUTPUT_PERIOD, 154 PERF_OUTPUT_PERIOD,
147 155
148 .invalid_fields = PERF_OUTPUT_TRACE, 156 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
149 }, 157 },
150}; 158};
151 159
@@ -242,6 +250,16 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
242 PERF_OUTPUT_ADDR, allow_user_set)) 250 PERF_OUTPUT_ADDR, allow_user_set))
243 return -EINVAL; 251 return -EINVAL;
244 252
253 if (PRINT_FIELD(DATA_SRC) &&
254 perf_evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC",
255 PERF_OUTPUT_DATA_SRC))
256 return -EINVAL;
257
258 if (PRINT_FIELD(WEIGHT) &&
259 perf_evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT, "WEIGHT",
260 PERF_OUTPUT_WEIGHT))
261 return -EINVAL;
262
245 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { 263 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
246 pr_err("Display of symbols requested but neither sample IP nor " 264 pr_err("Display of symbols requested but neither sample IP nor "
247 "sample address\nis selected. Hence, no addresses to convert " 265 "sample address\nis selected. Hence, no addresses to convert "
@@ -608,6 +626,84 @@ static void print_sample_flags(u32 flags)
608 printf(" %-4s ", str); 626 printf(" %-4s ", str);
609} 627}
610 628
629struct printer_data {
630 int line_no;
631 bool hit_nul;
632 bool is_printable;
633};
634
635static void
636print_sample_bpf_output_printer(enum binary_printer_ops op,
637 unsigned int val,
638 void *extra)
639{
640 unsigned char ch = (unsigned char)val;
641 struct printer_data *printer_data = extra;
642
643 switch (op) {
644 case BINARY_PRINT_DATA_BEGIN:
645 printf("\n");
646 break;
647 case BINARY_PRINT_LINE_BEGIN:
648 printf("%17s", !printer_data->line_no ? "BPF output:" :
649 " ");
650 break;
651 case BINARY_PRINT_ADDR:
652 printf(" %04x:", val);
653 break;
654 case BINARY_PRINT_NUM_DATA:
655 printf(" %02x", val);
656 break;
657 case BINARY_PRINT_NUM_PAD:
658 printf(" ");
659 break;
660 case BINARY_PRINT_SEP:
661 printf(" ");
662 break;
663 case BINARY_PRINT_CHAR_DATA:
664 if (printer_data->hit_nul && ch)
665 printer_data->is_printable = false;
666
667 if (!isprint(ch)) {
668 printf("%c", '.');
669
670 if (!printer_data->is_printable)
671 break;
672
673 if (ch == '\0')
674 printer_data->hit_nul = true;
675 else
676 printer_data->is_printable = false;
677 } else {
678 printf("%c", ch);
679 }
680 break;
681 case BINARY_PRINT_CHAR_PAD:
682 printf(" ");
683 break;
684 case BINARY_PRINT_LINE_END:
685 printf("\n");
686 printer_data->line_no++;
687 break;
688 case BINARY_PRINT_DATA_END:
689 default:
690 break;
691 }
692}
693
694static void print_sample_bpf_output(struct perf_sample *sample)
695{
696 unsigned int nr_bytes = sample->raw_size;
697 struct printer_data printer_data = {0, false, true};
698
699 print_binary(sample->raw_data, nr_bytes, 8,
700 print_sample_bpf_output_printer, &printer_data);
701
702 if (printer_data.is_printable && printer_data.hit_nul)
703 printf("%17s \"%s\"\n", "BPF string:",
704 (char *)(sample->raw_data));
705}
706
611struct perf_script { 707struct perf_script {
612 struct perf_tool tool; 708 struct perf_tool tool;
613 struct perf_session *session; 709 struct perf_session *session;
@@ -634,6 +730,23 @@ static int perf_evlist__max_name_len(struct perf_evlist *evlist)
634 return max; 730 return max;
635} 731}
636 732
733static size_t data_src__printf(u64 data_src)
734{
735 struct mem_info mi = { .data_src.val = data_src };
736 char decode[100];
737 char out[100];
738 static int maxlen;
739 int len;
740
741 perf_script__meminfo_scnprintf(decode, 100, &mi);
742
743 len = scnprintf(out, 100, "%16" PRIx64 " %s", data_src, decode);
744 if (maxlen < len)
745 maxlen = len;
746
747 return printf("%-*s", maxlen, out);
748}
749
637static void process_event(struct perf_script *script, union perf_event *event, 750static void process_event(struct perf_script *script, union perf_event *event,
638 struct perf_sample *sample, struct perf_evsel *evsel, 751 struct perf_sample *sample, struct perf_evsel *evsel,
639 struct addr_location *al) 752 struct addr_location *al)
@@ -673,6 +786,12 @@ static void process_event(struct perf_script *script, union perf_event *event,
673 if (PRINT_FIELD(ADDR)) 786 if (PRINT_FIELD(ADDR))
674 print_sample_addr(event, sample, thread, attr); 787 print_sample_addr(event, sample, thread, attr);
675 788
789 if (PRINT_FIELD(DATA_SRC))
790 data_src__printf(sample->data_src);
791
792 if (PRINT_FIELD(WEIGHT))
793 printf("%16" PRIu64, sample->weight);
794
676 if (PRINT_FIELD(IP)) { 795 if (PRINT_FIELD(IP)) {
677 if (!symbol_conf.use_callchain) 796 if (!symbol_conf.use_callchain)
678 printf(" "); 797 printf(" ");
@@ -692,6 +811,9 @@ static void process_event(struct perf_script *script, union perf_event *event,
692 else if (PRINT_FIELD(BRSTACKSYM)) 811 else if (PRINT_FIELD(BRSTACKSYM))
693 print_sample_brstacksym(event, sample, thread, attr); 812 print_sample_brstacksym(event, sample, thread, attr);
694 813
814 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
815 print_sample_bpf_output(sample);
816
695 printf("\n"); 817 printf("\n");
696} 818}
697 819
@@ -1090,23 +1212,6 @@ static struct script_spec *script_spec__find(const char *spec)
1090 return NULL; 1212 return NULL;
1091} 1213}
1092 1214
1093static struct script_spec *script_spec__findnew(const char *spec,
1094 struct scripting_ops *ops)
1095{
1096 struct script_spec *s = script_spec__find(spec);
1097
1098 if (s)
1099 return s;
1100
1101 s = script_spec__new(spec, ops);
1102 if (!s)
1103 return NULL;
1104
1105 script_spec__add(s);
1106
1107 return s;
1108}
1109
1110int script_spec_register(const char *spec, struct scripting_ops *ops) 1215int script_spec_register(const char *spec, struct scripting_ops *ops)
1111{ 1216{
1112 struct script_spec *s; 1217 struct script_spec *s;
@@ -1115,9 +1220,11 @@ int script_spec_register(const char *spec, struct scripting_ops *ops)
1115 if (s) 1220 if (s)
1116 return -1; 1221 return -1;
1117 1222
1118 s = script_spec__findnew(spec, ops); 1223 s = script_spec__new(spec, ops);
1119 if (!s) 1224 if (!s)
1120 return -1; 1225 return -1;
1226 else
1227 script_spec__add(s);
1121 1228
1122 return 0; 1229 return 0;
1123} 1230}