perf script: Find script file relative to exec path
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>
This commit is contained in:
committed by
Arnaldo Carvalho de Melo
parent
afe360a8c3
commit
6ea4b5dbe0
@@ -2665,6 +2665,37 @@ static void list_available_languages(void)
|
|||||||
fprintf(stderr, "\n");
|
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,
|
static int parse_scriptname(const struct option *opt __maybe_unused,
|
||||||
const char *str, int unset __maybe_unused)
|
const char *str, int unset __maybe_unused)
|
||||||
{
|
{
|
||||||
@@ -2706,6 +2737,8 @@ static int parse_scriptname(const struct option *opt __maybe_unused,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
script_name = find_script(script);
|
||||||
|
if (!script_name)
|
||||||
script_name = strdup(script);
|
script_name = strdup(script);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3718,6 +3751,12 @@ int cmd_script(int argc, const char **argv)
|
|||||||
rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
|
rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
|
||||||
|
|
||||||
if (!rec_script_path && !rep_script_path) {
|
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,
|
usage_with_options_msg(script_usage, options,
|
||||||
"Couldn't find script `%s'\n\n See perf"
|
"Couldn't find script `%s'\n\n See perf"
|
||||||
" script -l for available scripts.\n", argv[0]);
|
" script -l for available scripts.\n", argv[0]);
|
||||||
@@ -3810,7 +3849,7 @@ int cmd_script(int argc, const char **argv)
|
|||||||
free(__argv);
|
free(__argv);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
script_found:
|
||||||
if (rec_script_path)
|
if (rec_script_path)
|
||||||
script_path = rec_script_path;
|
script_path = rec_script_path;
|
||||||
if (rep_script_path)
|
if (rep_script_path)
|
||||||
|
|||||||
@@ -750,6 +750,7 @@ sub print_backtrace\n\
|
|||||||
|
|
||||||
struct scripting_ops perl_scripting_ops = {
|
struct scripting_ops perl_scripting_ops = {
|
||||||
.name = "Perl",
|
.name = "Perl",
|
||||||
|
.dirname = "perl",
|
||||||
.start_script = perl_start_script,
|
.start_script = perl_start_script,
|
||||||
.flush_script = perl_flush_script,
|
.flush_script = perl_flush_script,
|
||||||
.stop_script = perl_stop_script,
|
.stop_script = perl_stop_script,
|
||||||
|
|||||||
@@ -1876,6 +1876,7 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
|
|||||||
|
|
||||||
struct scripting_ops python_scripting_ops = {
|
struct scripting_ops python_scripting_ops = {
|
||||||
.name = "Python",
|
.name = "Python",
|
||||||
|
.dirname = "python",
|
||||||
.start_script = python_start_script,
|
.start_script = python_start_script,
|
||||||
.flush_script = python_flush_script,
|
.flush_script = python_flush_script,
|
||||||
.stop_script = python_stop_script,
|
.stop_script = python_stop_script,
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ static int python_generate_script_unsupported(struct tep_handle *pevent
|
|||||||
|
|
||||||
struct scripting_ops python_scripting_unsupported_ops = {
|
struct scripting_ops python_scripting_unsupported_ops = {
|
||||||
.name = "Python",
|
.name = "Python",
|
||||||
|
.dirname = "python",
|
||||||
.start_script = python_start_script_unsupported,
|
.start_script = python_start_script_unsupported,
|
||||||
.flush_script = flush_script_unsupported,
|
.flush_script = flush_script_unsupported,
|
||||||
.stop_script = stop_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 = {
|
struct scripting_ops perl_scripting_unsupported_ops = {
|
||||||
.name = "Perl",
|
.name = "Perl",
|
||||||
|
.dirname = "perl",
|
||||||
.start_script = perl_start_script_unsupported,
|
.start_script = perl_start_script_unsupported,
|
||||||
.flush_script = flush_script_unsupported,
|
.flush_script = flush_script_unsupported,
|
||||||
.stop_script = stop_script_unsupported,
|
.stop_script = stop_script_unsupported,
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ struct perf_stat_config;
|
|||||||
|
|
||||||
struct scripting_ops {
|
struct scripting_ops {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
const char *dirname; /* For script path .../scripts/<dirname>/... */
|
||||||
int (*start_script) (const char *script, int argc, const char **argv);
|
int (*start_script) (const char *script, int argc, const char **argv);
|
||||||
int (*flush_script) (void);
|
int (*flush_script) (void);
|
||||||
int (*stop_script) (void);
|
int (*stop_script) (void);
|
||||||
|
|||||||
Reference in New Issue
Block a user