perf script: Find script file relative to exec path
authorAdrian Hunter <adrian.hunter@intel.com>
Mon, 24 May 2021 06:57:18 +0000 (09:57 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 25 May 2021 12:51:44 +0000 (09:51 -0300)
Allow perf script to find a script in the exec path.

Example:

Before:

 $ perf record -a -e intel_pt/branch=0/ sleep 0.1
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.954 MB perf.data ]
 $ perf script intel-pt-events.py 2>&1 | head -3
   Error: Couldn't find script `intel-pt-events.py'
   See perf script -l for available scripts.
 $ perf script -s intel-pt-events.py 2>&1 | head -3
 Can't open python script "intel-pt-events.py": No such file or directory
 $ perf script ~/libexec/perf-core/scripts/python/intel-pt-events.py 2>&1 | head -3
   Error: Couldn't find script `/home/ahunter/libexec/perf-core/scripts/python/intel-pt-events.py'
   See perf script -l for available scripts.
 $

After:

 $ perf script intel-pt-events.py 2>&1 | head -3
 Intel PT Power Events and PTWRITE
            perf  8123/8123  [000]       551.230753986     cbr:  42  freq: 4219 MHz  (156%)                0 [unknown] ([unknown])
            perf  8123/8123  [001]       551.230808216     cbr:  42  freq: 4219 MHz  (156%)                0 [unknown] ([unknown])
 $ perf script -s intel-pt-events.py 2>&1 | head -3
 Intel PT Power Events and PTWRITE
            perf  8123/8123  [000]       551.230753986     cbr:  42  freq: 4219 MHz  (156%)                0 [unknown] ([unknown])
            perf  8123/8123  [001]       551.230808216     cbr:  42  freq: 4219 MHz  (156%)                0 [unknown] ([unknown])
 $ perf script ~/libexec/perf-core/scripts/python/intel-pt-events.py 2>&1 | head -3
 Intel PT Power Events and PTWRITE
            perf  8123/8123  [000]       551.230753986     cbr:  42  freq: 4219 MHz  (156%)                0 [unknown] ([unknown])
            perf  8123/8123  [001]       551.230808216     cbr:  42  freq: 4219 MHz  (156%)                0 [unknown] ([unknown])
 $

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Link: http://lore.kernel.org/lkml/20210524065718.11421-1-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-script.c
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/trace-event-scripting.c
tools/perf/util/trace-event.h

index 1280cbf..2a06246 100644 (file)
@@ -2665,6 +2665,37 @@ static void list_available_languages(void)
        fprintf(stderr, "\n");
 }
 
+/* Find script file relative to current directory or exec path */
+static char *find_script(const char *script)
+{
+       char path[PATH_MAX];
+
+       if (!scripting_ops) {
+               const char *ext = strrchr(script, '.');
+
+               if (!ext)
+                       return NULL;
+
+               scripting_ops = script_spec__lookup(++ext);
+               if (!scripting_ops)
+                       return NULL;
+       }
+
+       if (access(script, R_OK)) {
+               char *exec_path = get_argv_exec_path();
+
+               if (!exec_path)
+                       return NULL;
+               snprintf(path, sizeof(path), "%s/scripts/%s/%s",
+                        exec_path, scripting_ops->dirname, script);
+               free(exec_path);
+               script = path;
+               if (access(script, R_OK))
+                       return NULL;
+       }
+       return strdup(script);
+}
+
 static int parse_scriptname(const struct option *opt __maybe_unused,
                            const char *str, int unset __maybe_unused)
 {
@@ -2706,7 +2737,9 @@ static int parse_scriptname(const struct option *opt __maybe_unused,
                }
        }
 
-       script_name = strdup(script);
+       script_name = find_script(script);
+       if (!script_name)
+               script_name = strdup(script);
 
        return 0;
 }
@@ -3718,6 +3751,12 @@ int cmd_script(int argc, const char **argv)
                rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
 
                if (!rec_script_path && !rep_script_path) {
+                       script_name = find_script(argv[0]);
+                       if (script_name) {
+                               argc -= 1;
+                               argv += 1;
+                               goto script_found;
+                       }
                        usage_with_options_msg(script_usage, options,
                                "Couldn't find script `%s'\n\n See perf"
                                " script -l for available scripts.\n", argv[0]);
@@ -3810,7 +3849,7 @@ int cmd_script(int argc, const char **argv)
                free(__argv);
                exit(-1);
        }
-
+script_found:
        if (rec_script_path)
                script_path = rec_script_path;
        if (rep_script_path)
index 0e608a5..865d310 100644 (file)
@@ -750,6 +750,7 @@ sub print_backtrace\n\
 
 struct scripting_ops perl_scripting_ops = {
        .name = "Perl",
+       .dirname = "perl",
        .start_script = perl_start_script,
        .flush_script = perl_flush_script,
        .stop_script = perl_stop_script,
index 4e4aa4c..db8f243 100644 (file)
@@ -1876,6 +1876,7 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
 
 struct scripting_ops python_scripting_ops = {
        .name                   = "Python",
+       .dirname                = "python",
        .start_script           = python_start_script,
        .flush_script           = python_flush_script,
        .stop_script            = python_stop_script,
index 714581b..cf6ed8b 100644 (file)
@@ -63,6 +63,7 @@ static int python_generate_script_unsupported(struct tep_handle *pevent
 
 struct scripting_ops python_scripting_unsupported_ops = {
        .name = "Python",
+       .dirname = "python",
        .start_script = python_start_script_unsupported,
        .flush_script = flush_script_unsupported,
        .stop_script = stop_script_unsupported,
@@ -126,6 +127,7 @@ static int perl_generate_script_unsupported(struct tep_handle *pevent
 
 struct scripting_ops perl_scripting_unsupported_ops = {
        .name = "Perl",
+       .dirname = "perl",
        .start_script = perl_start_script_unsupported,
        .flush_script = flush_script_unsupported,
        .stop_script = stop_script_unsupported,
index 72fdf2a..39fb39e 100644 (file)
@@ -71,6 +71,7 @@ struct perf_stat_config;
 
 struct scripting_ops {
        const char *name;
+       const char *dirname; /* For script path .../scripts/<dirname>/... */
        int (*start_script) (const char *script, int argc, const char **argv);
        int (*flush_script) (void);
        int (*stop_script) (void);