diff options
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/builtin-trace.c | 165 |
1 files changed, 108 insertions, 57 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0de7fcb9096..0483e28fa60 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
| @@ -330,7 +330,7 @@ static struct script_desc *script_desc__new(const char *name) | |||
| 330 | { | 330 | { |
| 331 | struct script_desc *s = zalloc(sizeof(*s)); | 331 | struct script_desc *s = zalloc(sizeof(*s)); |
| 332 | 332 | ||
| 333 | if (s != NULL) | 333 | if (s != NULL && name) |
| 334 | s->name = strdup(name); | 334 | s->name = strdup(name); |
| 335 | 335 | ||
| 336 | return s; | 336 | return s; |
| @@ -541,6 +541,34 @@ static char *get_script_path(const char *script_root, const char *suffix) | |||
| 541 | return path; | 541 | return path; |
| 542 | } | 542 | } |
| 543 | 543 | ||
| 544 | static bool is_top_script(const char *script_path) | ||
| 545 | { | ||
| 546 | return ends_with((char *)script_path, "top") == NULL ? false : true; | ||
| 547 | } | ||
| 548 | |||
| 549 | static int has_required_arg(char *script_path) | ||
| 550 | { | ||
| 551 | struct script_desc *desc; | ||
| 552 | int n_args = 0; | ||
| 553 | char *p; | ||
| 554 | |||
| 555 | desc = script_desc__new(NULL); | ||
| 556 | |||
| 557 | if (read_script_info(desc, script_path)) | ||
| 558 | goto out; | ||
| 559 | |||
| 560 | if (!desc->args) | ||
| 561 | goto out; | ||
| 562 | |||
| 563 | for (p = desc->args; *p; p++) | ||
| 564 | if (*p == '<') | ||
| 565 | n_args++; | ||
| 566 | out: | ||
| 567 | script_desc__delete(desc); | ||
| 568 | |||
| 569 | return n_args; | ||
| 570 | } | ||
| 571 | |||
| 544 | static const char * const trace_usage[] = { | 572 | static const char * const trace_usage[] = { |
| 545 | "perf trace [<options>] <command>", | 573 | "perf trace [<options>] <command>", |
| 546 | NULL | 574 | NULL |
| @@ -584,48 +612,65 @@ static bool have_cmd(int argc, const char **argv) | |||
| 584 | 612 | ||
| 585 | int cmd_trace(int argc, const char **argv, const char *prefix __used) | 613 | int cmd_trace(int argc, const char **argv, const char *prefix __used) |
| 586 | { | 614 | { |
| 615 | char *rec_script_path = NULL; | ||
| 616 | char *rep_script_path = NULL; | ||
| 587 | struct perf_session *session; | 617 | struct perf_session *session; |
| 588 | const char *suffix = NULL; | 618 | char *script_path = NULL; |
| 589 | const char **__argv; | 619 | const char **__argv; |
| 590 | char *script_path; | 620 | bool system_wide; |
| 591 | int i, err; | 621 | int i, j, err; |
| 592 | 622 | ||
| 593 | if (argc >= 2 && strncmp(argv[1], "rec", strlen("rec")) == 0) { | 623 | setup_scripting(); |
| 594 | if (argc < 3) { | 624 | |
| 595 | fprintf(stderr, | 625 | argc = parse_options(argc, argv, options, trace_usage, |
| 596 | "Please specify a record script\n"); | 626 | PARSE_OPT_STOP_AT_NON_OPTION); |
| 597 | return -1; | 627 | |
| 598 | } | 628 | if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { |
| 599 | suffix = RECORD_SUFFIX; | 629 | rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); |
| 630 | if (!rec_script_path) | ||
| 631 | return cmd_record(argc, argv, NULL); | ||
| 600 | } | 632 | } |
| 601 | 633 | ||
| 602 | if (argc >= 2 && strncmp(argv[1], "rep", strlen("rep")) == 0) { | 634 | if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) { |
| 603 | if (argc < 3) { | 635 | rep_script_path = get_script_path(argv[1], REPORT_SUFFIX); |
| 636 | if (!rep_script_path) { | ||
| 604 | fprintf(stderr, | 637 | fprintf(stderr, |
| 605 | "Please specify a report script\n"); | 638 | "Please specify a valid report script" |
| 639 | "(see 'perf trace -l' for listing)\n"); | ||
| 606 | return -1; | 640 | return -1; |
| 607 | } | 641 | } |
| 608 | suffix = REPORT_SUFFIX; | ||
| 609 | } | 642 | } |
| 610 | 643 | ||
| 611 | /* make sure PERF_EXEC_PATH is set for scripts */ | 644 | /* make sure PERF_EXEC_PATH is set for scripts */ |
| 612 | perf_set_argv_exec_path(perf_exec_path()); | 645 | perf_set_argv_exec_path(perf_exec_path()); |
| 613 | 646 | ||
| 614 | if (!suffix && argc >= 2 && strncmp(argv[1], "-", strlen("-")) != 0) { | 647 | if (argc && !script_name && !rec_script_path && !rep_script_path) { |
| 615 | char *record_script_path, *report_script_path; | ||
| 616 | int live_pipe[2]; | 648 | int live_pipe[2]; |
| 649 | int rep_args; | ||
| 617 | pid_t pid; | 650 | pid_t pid; |
| 618 | 651 | ||
| 619 | record_script_path = get_script_path(argv[1], RECORD_SUFFIX); | 652 | rec_script_path = get_script_path(argv[0], RECORD_SUFFIX); |
| 620 | if (!record_script_path) { | 653 | rep_script_path = get_script_path(argv[0], REPORT_SUFFIX); |
| 621 | fprintf(stderr, "record script not found\n"); | 654 | |
| 622 | return -1; | 655 | if (!rec_script_path && !rep_script_path) { |
| 656 | fprintf(stderr, " Couldn't find script %s\n\n See perf" | ||
| 657 | " trace -l for available scripts.\n", argv[0]); | ||
| 658 | usage_with_options(trace_usage, options); | ||
| 623 | } | 659 | } |
| 624 | 660 | ||
| 625 | report_script_path = get_script_path(argv[1], REPORT_SUFFIX); | 661 | if (is_top_script(argv[0])) { |
| 626 | if (!report_script_path) { | 662 | rep_args = argc - 1; |
| 627 | fprintf(stderr, "report script not found\n"); | 663 | } else { |
| 628 | return -1; | 664 | int rec_args; |
| 665 | |||
| 666 | rep_args = has_required_arg(rep_script_path); | ||
| 667 | rec_args = (argc - 1) - rep_args; | ||
| 668 | if (rec_args < 0) { | ||
| 669 | fprintf(stderr, " %s script requires options." | ||
| 670 | "\n\n See perf trace -l for available " | ||
| 671 | "scripts and options.\n", argv[0]); | ||
| 672 | usage_with_options(trace_usage, options); | ||
| 673 | } | ||
| 629 | } | 674 | } |
| 630 | 675 | ||
| 631 | if (pipe(live_pipe) < 0) { | 676 | if (pipe(live_pipe) < 0) { |
| @@ -640,19 +685,30 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) | |||
| 640 | } | 685 | } |
| 641 | 686 | ||
| 642 | if (!pid) { | 687 | if (!pid) { |
| 688 | system_wide = true; | ||
| 689 | j = 0; | ||
| 690 | |||
| 643 | dup2(live_pipe[1], 1); | 691 | dup2(live_pipe[1], 1); |
| 644 | close(live_pipe[0]); | 692 | close(live_pipe[0]); |
| 645 | 693 | ||
| 646 | __argv = malloc(6 * sizeof(const char *)); | 694 | if (!is_top_script(argv[0])) |
| 695 | system_wide = !have_cmd(argc - rep_args, | ||
| 696 | &argv[rep_args]); | ||
| 697 | |||
| 698 | __argv = malloc((argc + 6) * sizeof(const char *)); | ||
| 647 | if (!__argv) | 699 | if (!__argv) |
| 648 | die("malloc"); | 700 | die("malloc"); |
| 649 | 701 | ||
| 650 | __argv[0] = "/bin/sh"; | 702 | __argv[j++] = "/bin/sh"; |
| 651 | __argv[1] = record_script_path; | 703 | __argv[j++] = rec_script_path; |
| 652 | __argv[2] = "-q"; | 704 | if (system_wide) |
| 653 | __argv[3] = "-o"; | 705 | __argv[j++] = "-a"; |
| 654 | __argv[4] = "-"; | 706 | __argv[j++] = "-q"; |
| 655 | __argv[5] = NULL; | 707 | __argv[j++] = "-o"; |
| 708 | __argv[j++] = "-"; | ||
| 709 | for (i = rep_args + 1; i < argc; i++) | ||
| 710 | __argv[j++] = argv[i]; | ||
| 711 | __argv[j++] = NULL; | ||
| 656 | 712 | ||
| 657 | execvp("/bin/sh", (char **)__argv); | 713 | execvp("/bin/sh", (char **)__argv); |
| 658 | free(__argv); | 714 | free(__argv); |
| @@ -662,43 +718,43 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) | |||
| 662 | dup2(live_pipe[0], 0); | 718 | dup2(live_pipe[0], 0); |
| 663 | close(live_pipe[1]); | 719 | close(live_pipe[1]); |
| 664 | 720 | ||
| 665 | __argv = malloc((argc + 3) * sizeof(const char *)); | 721 | __argv = malloc((argc + 4) * sizeof(const char *)); |
| 666 | if (!__argv) | 722 | if (!__argv) |
| 667 | die("malloc"); | 723 | die("malloc"); |
| 668 | __argv[0] = "/bin/sh"; | 724 | j = 0; |
| 669 | __argv[1] = report_script_path; | 725 | __argv[j++] = "/bin/sh"; |
| 670 | for (i = 2; i < argc; i++) | 726 | __argv[j++] = rep_script_path; |
| 671 | __argv[i] = argv[i]; | 727 | for (i = 1; i < rep_args + 1; i++) |
| 672 | __argv[i++] = "-i"; | 728 | __argv[j++] = argv[i]; |
| 673 | __argv[i++] = "-"; | 729 | __argv[j++] = "-i"; |
| 674 | __argv[i++] = NULL; | 730 | __argv[j++] = "-"; |
| 731 | __argv[j++] = NULL; | ||
| 675 | 732 | ||
| 676 | execvp("/bin/sh", (char **)__argv); | 733 | execvp("/bin/sh", (char **)__argv); |
| 677 | free(__argv); | 734 | free(__argv); |
| 678 | exit(-1); | 735 | exit(-1); |
| 679 | } | 736 | } |
| 680 | 737 | ||
| 681 | if (suffix) { | 738 | if (rec_script_path) |
| 682 | bool system_wide = false; | 739 | script_path = rec_script_path; |
| 683 | int j = 0; | 740 | if (rep_script_path) |
| 741 | script_path = rep_script_path; | ||
| 684 | 742 | ||
| 685 | script_path = get_script_path(argv[2], suffix); | 743 | if (script_path) { |
| 686 | if (!script_path) { | 744 | system_wide = false; |
| 687 | fprintf(stderr, "script not found\n"); | 745 | j = 0; |
| 688 | return -1; | ||
| 689 | } | ||
| 690 | 746 | ||
| 691 | if (!strcmp(suffix, RECORD_SUFFIX)) | 747 | if (rec_script_path) |
| 692 | system_wide = !have_cmd(argc - 2, &argv[2]); | 748 | system_wide = !have_cmd(argc - 1, &argv[1]); |
| 693 | 749 | ||
| 694 | __argv = malloc((argc + 1) * sizeof(const char *)); | 750 | __argv = malloc((argc + 2) * sizeof(const char *)); |
| 695 | if (!__argv) | 751 | if (!__argv) |
| 696 | die("malloc"); | 752 | die("malloc"); |
| 697 | __argv[j++] = "/bin/sh"; | 753 | __argv[j++] = "/bin/sh"; |
| 698 | __argv[j++] = script_path; | 754 | __argv[j++] = script_path; |
| 699 | if (system_wide) | 755 | if (system_wide) |
| 700 | __argv[j++] = "-a"; | 756 | __argv[j++] = "-a"; |
| 701 | for (i = 3; i < argc; i++) | 757 | for (i = 2; i < argc; i++) |
| 702 | __argv[j++] = argv[i]; | 758 | __argv[j++] = argv[i]; |
| 703 | __argv[j++] = NULL; | 759 | __argv[j++] = NULL; |
| 704 | 760 | ||
| @@ -707,11 +763,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) | |||
| 707 | exit(-1); | 763 | exit(-1); |
| 708 | } | 764 | } |
| 709 | 765 | ||
| 710 | setup_scripting(); | ||
| 711 | |||
| 712 | argc = parse_options(argc, argv, options, trace_usage, | ||
| 713 | PARSE_OPT_STOP_AT_NON_OPTION); | ||
| 714 | |||
| 715 | if (symbol__init() < 0) | 766 | if (symbol__init() < 0) |
| 716 | return -1; | 767 | return -1; |
| 717 | if (!script_name) | 768 | if (!script_name) |
