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(); |
