aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-trace.c165
1 files changed, 108 insertions, 57 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 0de7fcb90965..0483e28fa60d 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
544static bool is_top_script(const char *script_path)
545{
546 return ends_with((char *)script_path, "top") == NULL ? false : true;
547}
548
549static 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++;
566out:
567 script_desc__delete(desc);
568
569 return n_args;
570}
571
544static const char * const trace_usage[] = { 572static 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
585int cmd_trace(int argc, const char **argv, const char *prefix __used) 613int 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)