diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r-- | tools/perf/builtin-script.c | 127 |
1 files changed, 89 insertions, 38 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 9c333ff3dfeb..baf17989a216 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "util/evlist.h" | 15 | #include "util/evlist.h" |
16 | #include "util/evsel.h" | 16 | #include "util/evsel.h" |
17 | #include "util/sort.h" | 17 | #include "util/sort.h" |
18 | #include "util/data.h" | ||
18 | #include <linux/bitmap.h> | 19 | #include <linux/bitmap.h> |
19 | 20 | ||
20 | static char const *script_name; | 21 | static char const *script_name; |
@@ -228,6 +229,24 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, | |||
228 | return 0; | 229 | return 0; |
229 | } | 230 | } |
230 | 231 | ||
232 | static void set_print_ip_opts(struct perf_event_attr *attr) | ||
233 | { | ||
234 | unsigned int type = attr->type; | ||
235 | |||
236 | output[type].print_ip_opts = 0; | ||
237 | if (PRINT_FIELD(IP)) | ||
238 | output[type].print_ip_opts |= PRINT_IP_OPT_IP; | ||
239 | |||
240 | if (PRINT_FIELD(SYM)) | ||
241 | output[type].print_ip_opts |= PRINT_IP_OPT_SYM; | ||
242 | |||
243 | if (PRINT_FIELD(DSO)) | ||
244 | output[type].print_ip_opts |= PRINT_IP_OPT_DSO; | ||
245 | |||
246 | if (PRINT_FIELD(SYMOFFSET)) | ||
247 | output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; | ||
248 | } | ||
249 | |||
231 | /* | 250 | /* |
232 | * verify all user requested events exist and the samples | 251 | * verify all user requested events exist and the samples |
233 | * have the expected data | 252 | * have the expected data |
@@ -236,7 +255,6 @@ static int perf_session__check_output_opt(struct perf_session *session) | |||
236 | { | 255 | { |
237 | int j; | 256 | int j; |
238 | struct perf_evsel *evsel; | 257 | struct perf_evsel *evsel; |
239 | struct perf_event_attr *attr; | ||
240 | 258 | ||
241 | for (j = 0; j < PERF_TYPE_MAX; ++j) { | 259 | for (j = 0; j < PERF_TYPE_MAX; ++j) { |
242 | evsel = perf_session__find_first_evtype(session, j); | 260 | evsel = perf_session__find_first_evtype(session, j); |
@@ -259,20 +277,7 @@ static int perf_session__check_output_opt(struct perf_session *session) | |||
259 | if (evsel == NULL) | 277 | if (evsel == NULL) |
260 | continue; | 278 | continue; |
261 | 279 | ||
262 | attr = &evsel->attr; | 280 | set_print_ip_opts(&evsel->attr); |
263 | |||
264 | output[j].print_ip_opts = 0; | ||
265 | if (PRINT_FIELD(IP)) | ||
266 | output[j].print_ip_opts |= PRINT_IP_OPT_IP; | ||
267 | |||
268 | if (PRINT_FIELD(SYM)) | ||
269 | output[j].print_ip_opts |= PRINT_IP_OPT_SYM; | ||
270 | |||
271 | if (PRINT_FIELD(DSO)) | ||
272 | output[j].print_ip_opts |= PRINT_IP_OPT_DSO; | ||
273 | |||
274 | if (PRINT_FIELD(SYMOFFSET)) | ||
275 | output[j].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; | ||
276 | } | 281 | } |
277 | 282 | ||
278 | return 0; | 283 | return 0; |
@@ -290,11 +295,11 @@ static void print_sample_start(struct perf_sample *sample, | |||
290 | 295 | ||
291 | if (PRINT_FIELD(COMM)) { | 296 | if (PRINT_FIELD(COMM)) { |
292 | if (latency_format) | 297 | if (latency_format) |
293 | printf("%8.8s ", thread->comm); | 298 | printf("%8.8s ", thread__comm_str(thread)); |
294 | else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) | 299 | else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) |
295 | printf("%s ", thread->comm); | 300 | printf("%s ", thread__comm_str(thread)); |
296 | else | 301 | else |
297 | printf("%16s ", thread->comm); | 302 | printf("%16s ", thread__comm_str(thread)); |
298 | } | 303 | } |
299 | 304 | ||
300 | if (PRINT_FIELD(PID) && PRINT_FIELD(TID)) | 305 | if (PRINT_FIELD(PID) && PRINT_FIELD(TID)) |
@@ -409,7 +414,9 @@ static void print_sample_bts(union perf_event *event, | |||
409 | printf(" => "); | 414 | printf(" => "); |
410 | 415 | ||
411 | /* print branch_to information */ | 416 | /* print branch_to information */ |
412 | if (PRINT_FIELD(ADDR)) | 417 | if (PRINT_FIELD(ADDR) || |
418 | ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && | ||
419 | !output[attr->type].user_set)) | ||
413 | print_sample_addr(event, sample, machine, thread, attr); | 420 | print_sample_addr(event, sample, machine, thread, attr); |
414 | 421 | ||
415 | printf("\n"); | 422 | printf("\n"); |
@@ -539,32 +546,51 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, | |||
539 | return 0; | 546 | return 0; |
540 | } | 547 | } |
541 | 548 | ||
542 | static struct perf_tool perf_script = { | 549 | struct perf_script { |
543 | .sample = process_sample_event, | 550 | struct perf_tool tool; |
544 | .mmap = perf_event__process_mmap, | 551 | struct perf_session *session; |
545 | .mmap2 = perf_event__process_mmap2, | ||
546 | .comm = perf_event__process_comm, | ||
547 | .exit = perf_event__process_exit, | ||
548 | .fork = perf_event__process_fork, | ||
549 | .attr = perf_event__process_attr, | ||
550 | .tracing_data = perf_event__process_tracing_data, | ||
551 | .build_id = perf_event__process_build_id, | ||
552 | .ordered_samples = true, | ||
553 | .ordering_requires_timestamps = true, | ||
554 | }; | 552 | }; |
555 | 553 | ||
554 | static int process_attr(struct perf_tool *tool, union perf_event *event, | ||
555 | struct perf_evlist **pevlist) | ||
556 | { | ||
557 | struct perf_script *scr = container_of(tool, struct perf_script, tool); | ||
558 | struct perf_evlist *evlist; | ||
559 | struct perf_evsel *evsel, *pos; | ||
560 | int err; | ||
561 | |||
562 | err = perf_event__process_attr(tool, event, pevlist); | ||
563 | if (err) | ||
564 | return err; | ||
565 | |||
566 | evlist = *pevlist; | ||
567 | evsel = perf_evlist__last(*pevlist); | ||
568 | |||
569 | if (evsel->attr.type >= PERF_TYPE_MAX) | ||
570 | return 0; | ||
571 | |||
572 | list_for_each_entry(pos, &evlist->entries, node) { | ||
573 | if (pos->attr.type == evsel->attr.type && pos != evsel) | ||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | set_print_ip_opts(&evsel->attr); | ||
578 | |||
579 | return perf_evsel__check_attr(evsel, scr->session); | ||
580 | } | ||
581 | |||
556 | static void sig_handler(int sig __maybe_unused) | 582 | static void sig_handler(int sig __maybe_unused) |
557 | { | 583 | { |
558 | session_done = 1; | 584 | session_done = 1; |
559 | } | 585 | } |
560 | 586 | ||
561 | static int __cmd_script(struct perf_session *session) | 587 | static int __cmd_script(struct perf_script *script) |
562 | { | 588 | { |
563 | int ret; | 589 | int ret; |
564 | 590 | ||
565 | signal(SIGINT, sig_handler); | 591 | signal(SIGINT, sig_handler); |
566 | 592 | ||
567 | ret = perf_session__process_events(session, &perf_script); | 593 | ret = perf_session__process_events(script->session, &script->tool); |
568 | 594 | ||
569 | if (debug_mode) | 595 | if (debug_mode) |
570 | pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); | 596 | pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); |
@@ -1113,10 +1139,14 @@ int find_scripts(char **scripts_array, char **scripts_path_array) | |||
1113 | char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; | 1139 | char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; |
1114 | DIR *scripts_dir, *lang_dir; | 1140 | DIR *scripts_dir, *lang_dir; |
1115 | struct perf_session *session; | 1141 | struct perf_session *session; |
1142 | struct perf_data_file file = { | ||
1143 | .path = input_name, | ||
1144 | .mode = PERF_DATA_MODE_READ, | ||
1145 | }; | ||
1116 | char *temp; | 1146 | char *temp; |
1117 | int i = 0; | 1147 | int i = 0; |
1118 | 1148 | ||
1119 | session = perf_session__new(input_name, O_RDONLY, 0, false, NULL); | 1149 | session = perf_session__new(&file, false, NULL); |
1120 | if (!session) | 1150 | if (!session) |
1121 | return -1; | 1151 | return -1; |
1122 | 1152 | ||
@@ -1266,6 +1296,21 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1266 | char *script_path = NULL; | 1296 | char *script_path = NULL; |
1267 | const char **__argv; | 1297 | const char **__argv; |
1268 | int i, j, err; | 1298 | int i, j, err; |
1299 | struct perf_script script = { | ||
1300 | .tool = { | ||
1301 | .sample = process_sample_event, | ||
1302 | .mmap = perf_event__process_mmap, | ||
1303 | .mmap2 = perf_event__process_mmap2, | ||
1304 | .comm = perf_event__process_comm, | ||
1305 | .exit = perf_event__process_exit, | ||
1306 | .fork = perf_event__process_fork, | ||
1307 | .attr = process_attr, | ||
1308 | .tracing_data = perf_event__process_tracing_data, | ||
1309 | .build_id = perf_event__process_build_id, | ||
1310 | .ordered_samples = true, | ||
1311 | .ordering_requires_timestamps = true, | ||
1312 | }, | ||
1313 | }; | ||
1269 | const struct option options[] = { | 1314 | const struct option options[] = { |
1270 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, | 1315 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, |
1271 | "dump raw trace in ASCII"), | 1316 | "dump raw trace in ASCII"), |
@@ -1317,12 +1362,17 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1317 | "perf script [<options>] <top-script> [script-args]", | 1362 | "perf script [<options>] <top-script> [script-args]", |
1318 | NULL | 1363 | NULL |
1319 | }; | 1364 | }; |
1365 | struct perf_data_file file = { | ||
1366 | .mode = PERF_DATA_MODE_READ, | ||
1367 | }; | ||
1320 | 1368 | ||
1321 | setup_scripting(); | 1369 | setup_scripting(); |
1322 | 1370 | ||
1323 | argc = parse_options(argc, argv, options, script_usage, | 1371 | argc = parse_options(argc, argv, options, script_usage, |
1324 | PARSE_OPT_STOP_AT_NON_OPTION); | 1372 | PARSE_OPT_STOP_AT_NON_OPTION); |
1325 | 1373 | ||
1374 | file.path = input_name; | ||
1375 | |||
1326 | if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { | 1376 | if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { |
1327 | rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); | 1377 | rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); |
1328 | if (!rec_script_path) | 1378 | if (!rec_script_path) |
@@ -1486,11 +1536,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1486 | if (!script_name) | 1536 | if (!script_name) |
1487 | setup_pager(); | 1537 | setup_pager(); |
1488 | 1538 | ||
1489 | session = perf_session__new(input_name, O_RDONLY, 0, false, | 1539 | session = perf_session__new(&file, false, &script.tool); |
1490 | &perf_script); | ||
1491 | if (session == NULL) | 1540 | if (session == NULL) |
1492 | return -ENOMEM; | 1541 | return -ENOMEM; |
1493 | 1542 | ||
1543 | script.session = session; | ||
1544 | |||
1494 | if (cpu_list) { | 1545 | if (cpu_list) { |
1495 | if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) | 1546 | if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) |
1496 | return -1; | 1547 | return -1; |
@@ -1514,7 +1565,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1514 | return -1; | 1565 | return -1; |
1515 | } | 1566 | } |
1516 | 1567 | ||
1517 | input = open(session->filename, O_RDONLY); /* input_name */ | 1568 | input = open(file.path, O_RDONLY); /* input_name */ |
1518 | if (input < 0) { | 1569 | if (input < 0) { |
1519 | perror("failed to open file"); | 1570 | perror("failed to open file"); |
1520 | return -1; | 1571 | return -1; |
@@ -1554,7 +1605,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1554 | if (err < 0) | 1605 | if (err < 0) |
1555 | goto out; | 1606 | goto out; |
1556 | 1607 | ||
1557 | err = __cmd_script(session); | 1608 | err = __cmd_script(&script); |
1558 | 1609 | ||
1559 | perf_session__delete(session); | 1610 | perf_session__delete(session); |
1560 | cleanup_scripting(); | 1611 | cleanup_scripting(); |