aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r--tools/perf/builtin-trace.c209
1 files changed, 150 insertions, 59 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 2f8df45c4dcb..86cfe3800e6b 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -10,6 +10,7 @@
10#include "util/symbol.h" 10#include "util/symbol.h"
11#include "util/thread.h" 11#include "util/thread.h"
12#include "util/trace-event.h" 12#include "util/trace-event.h"
13#include "util/parse-options.h"
13#include "util/util.h" 14#include "util/util.h"
14 15
15static char const *script_name; 16static char const *script_name;
@@ -17,6 +18,7 @@ static char const *generate_script_lang;
17static bool debug_mode; 18static bool debug_mode;
18static u64 last_timestamp; 19static u64 last_timestamp;
19static u64 nr_unordered; 20static u64 nr_unordered;
21extern const struct option record_options[];
20 22
21static int default_start_script(const char *script __unused, 23static int default_start_script(const char *script __unused,
22 int argc __unused, 24 int argc __unused,
@@ -328,7 +330,7 @@ static struct script_desc *script_desc__new(const char *name)
328{ 330{
329 struct script_desc *s = zalloc(sizeof(*s)); 331 struct script_desc *s = zalloc(sizeof(*s));
330 332
331 if (s != NULL) 333 if (s != NULL && name)
332 s->name = strdup(name); 334 s->name = strdup(name);
333 335
334 return s; 336 return s;
@@ -337,6 +339,8 @@ static struct script_desc *script_desc__new(const char *name)
337static void script_desc__delete(struct script_desc *s) 339static void script_desc__delete(struct script_desc *s)
338{ 340{
339 free(s->name); 341 free(s->name);
342 free(s->half_liner);
343 free(s->args);
340 free(s); 344 free(s);
341} 345}
342 346
@@ -537,8 +541,40 @@ static char *get_script_path(const char *script_root, const char *suffix)
537 return path; 541 return path;
538} 542}
539 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
540static const char * const trace_usage[] = { 572static const char * const trace_usage[] = {
541 "perf trace [<options>] <command>", 573 "perf trace [<options>]",
574 "perf trace [<options>] record <script> [<record-options>] <command>",
575 "perf trace [<options>] report <script> [script-args]",
576 "perf trace [<options>] <script> [<record-options>] <command>",
577 "perf trace [<options>] <top-script> [script-args]",
542 NULL 578 NULL
543}; 579};
544 580
@@ -564,50 +600,81 @@ static const struct option options[] = {
564 OPT_END() 600 OPT_END()
565}; 601};
566 602
603static bool have_cmd(int argc, const char **argv)
604{
605 char **__argv = malloc(sizeof(const char *) * argc);
606
607 if (!__argv)
608 die("malloc");
609 memcpy(__argv, argv, sizeof(const char *) * argc);
610 argc = parse_options(argc, (const char **)__argv, record_options,
611 NULL, PARSE_OPT_STOP_AT_NON_OPTION);
612 free(__argv);
613
614 return argc != 0;
615}
616
567int cmd_trace(int argc, const char **argv, const char *prefix __used) 617int cmd_trace(int argc, const char **argv, const char *prefix __used)
568{ 618{
619 char *rec_script_path = NULL;
620 char *rep_script_path = NULL;
569 struct perf_session *session; 621 struct perf_session *session;
570 const char *suffix = NULL; 622 char *script_path = NULL;
571 const char **__argv; 623 const char **__argv;
572 char *script_path; 624 bool system_wide;
573 int i, err; 625 int i, j, err;
574 626
575 if (argc >= 2 && strncmp(argv[1], "rec", strlen("rec")) == 0) { 627 setup_scripting();
576 if (argc < 3) { 628
577 fprintf(stderr, 629 argc = parse_options(argc, argv, options, trace_usage,
578 "Please specify a record script\n"); 630 PARSE_OPT_STOP_AT_NON_OPTION);
579 return -1; 631
580 } 632 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
581 suffix = RECORD_SUFFIX; 633 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
634 if (!rec_script_path)
635 return cmd_record(argc, argv, NULL);
582 } 636 }
583 637
584 if (argc >= 2 && strncmp(argv[1], "rep", strlen("rep")) == 0) { 638 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
585 if (argc < 3) { 639 rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
640 if (!rep_script_path) {
586 fprintf(stderr, 641 fprintf(stderr,
587 "Please specify a report script\n"); 642 "Please specify a valid report script"
643 "(see 'perf trace -l' for listing)\n");
588 return -1; 644 return -1;
589 } 645 }
590 suffix = REPORT_SUFFIX;
591 } 646 }
592 647
593 /* make sure PERF_EXEC_PATH is set for scripts */ 648 /* make sure PERF_EXEC_PATH is set for scripts */
594 perf_set_argv_exec_path(perf_exec_path()); 649 perf_set_argv_exec_path(perf_exec_path());
595 650
596 if (!suffix && argc >= 2 && strncmp(argv[1], "-", strlen("-")) != 0) { 651 if (argc && !script_name && !rec_script_path && !rep_script_path) {
597 char *record_script_path, *report_script_path;
598 int live_pipe[2]; 652 int live_pipe[2];
653 int rep_args;
599 pid_t pid; 654 pid_t pid;
600 655
601 record_script_path = get_script_path(argv[1], RECORD_SUFFIX); 656 rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
602 if (!record_script_path) { 657 rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
603 fprintf(stderr, "record script not found\n"); 658
604 return -1; 659 if (!rec_script_path && !rep_script_path) {
660 fprintf(stderr, " Couldn't find script %s\n\n See perf"
661 " trace -l for available scripts.\n", argv[0]);
662 usage_with_options(trace_usage, options);
605 } 663 }
606 664
607 report_script_path = get_script_path(argv[1], REPORT_SUFFIX); 665 if (is_top_script(argv[0])) {
608 if (!report_script_path) { 666 rep_args = argc - 1;
609 fprintf(stderr, "report script not found\n"); 667 } else {
610 return -1; 668 int rec_args;
669
670 rep_args = has_required_arg(rep_script_path);
671 rec_args = (argc - 1) - rep_args;
672 if (rec_args < 0) {
673 fprintf(stderr, " %s script requires options."
674 "\n\n See perf trace -l for available "
675 "scripts and options.\n", argv[0]);
676 usage_with_options(trace_usage, options);
677 }
611 } 678 }
612 679
613 if (pipe(live_pipe) < 0) { 680 if (pipe(live_pipe) < 0) {
@@ -622,60 +689,84 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
622 } 689 }
623 690
624 if (!pid) { 691 if (!pid) {
692 system_wide = true;
693 j = 0;
694
625 dup2(live_pipe[1], 1); 695 dup2(live_pipe[1], 1);
626 close(live_pipe[0]); 696 close(live_pipe[0]);
627 697
628 __argv = malloc(6 * sizeof(const char *)); 698 if (!is_top_script(argv[0]))
629 __argv[0] = "/bin/sh"; 699 system_wide = !have_cmd(argc - rep_args,
630 __argv[1] = record_script_path; 700 &argv[rep_args]);
631 __argv[2] = "-q"; 701
632 __argv[3] = "-o"; 702 __argv = malloc((argc + 6) * sizeof(const char *));
633 __argv[4] = "-"; 703 if (!__argv)
634 __argv[5] = NULL; 704 die("malloc");
705
706 __argv[j++] = "/bin/sh";
707 __argv[j++] = rec_script_path;
708 if (system_wide)
709 __argv[j++] = "-a";
710 __argv[j++] = "-q";
711 __argv[j++] = "-o";
712 __argv[j++] = "-";
713 for (i = rep_args + 1; i < argc; i++)
714 __argv[j++] = argv[i];
715 __argv[j++] = NULL;
635 716
636 execvp("/bin/sh", (char **)__argv); 717 execvp("/bin/sh", (char **)__argv);
718 free(__argv);
637 exit(-1); 719 exit(-1);
638 } 720 }
639 721
640 dup2(live_pipe[0], 0); 722 dup2(live_pipe[0], 0);
641 close(live_pipe[1]); 723 close(live_pipe[1]);
642 724
643 __argv = malloc((argc + 3) * sizeof(const char *)); 725 __argv = malloc((argc + 4) * sizeof(const char *));
644 __argv[0] = "/bin/sh"; 726 if (!__argv)
645 __argv[1] = report_script_path; 727 die("malloc");
646 for (i = 2; i < argc; i++) 728 j = 0;
647 __argv[i] = argv[i]; 729 __argv[j++] = "/bin/sh";
648 __argv[i++] = "-i"; 730 __argv[j++] = rep_script_path;
649 __argv[i++] = "-"; 731 for (i = 1; i < rep_args + 1; i++)
650 __argv[i++] = NULL; 732 __argv[j++] = argv[i];
733 __argv[j++] = "-i";
734 __argv[j++] = "-";
735 __argv[j++] = NULL;
651 736
652 execvp("/bin/sh", (char **)__argv); 737 execvp("/bin/sh", (char **)__argv);
738 free(__argv);
653 exit(-1); 739 exit(-1);
654 } 740 }
655 741
656 if (suffix) { 742 if (rec_script_path)
657 script_path = get_script_path(argv[2], suffix); 743 script_path = rec_script_path;
658 if (!script_path) { 744 if (rep_script_path)
659 fprintf(stderr, "script not found\n"); 745 script_path = rep_script_path;
660 return -1; 746
661 } 747 if (script_path) {
662 748 system_wide = false;
663 __argv = malloc((argc + 1) * sizeof(const char *)); 749 j = 0;
664 __argv[0] = "/bin/sh"; 750
665 __argv[1] = script_path; 751 if (rec_script_path)
666 for (i = 3; i < argc; i++) 752 system_wide = !have_cmd(argc - 1, &argv[1]);
667 __argv[i - 1] = argv[i]; 753
668 __argv[argc - 1] = NULL; 754 __argv = malloc((argc + 2) * sizeof(const char *));
755 if (!__argv)
756 die("malloc");
757 __argv[j++] = "/bin/sh";
758 __argv[j++] = script_path;
759 if (system_wide)
760 __argv[j++] = "-a";
761 for (i = 2; i < argc; i++)
762 __argv[j++] = argv[i];
763 __argv[j++] = NULL;
669 764
670 execvp("/bin/sh", (char **)__argv); 765 execvp("/bin/sh", (char **)__argv);
766 free(__argv);
671 exit(-1); 767 exit(-1);
672 } 768 }
673 769
674 setup_scripting();
675
676 argc = parse_options(argc, argv, options, trace_usage,
677 PARSE_OPT_STOP_AT_NON_OPTION);
678
679 if (symbol__init() < 0) 770 if (symbol__init() < 0)
680 return -1; 771 return -1;
681 if (!script_name) 772 if (!script_name)