perf probe: Show trace event definition
Add --definition/-D option for showing the trace-event definition in stdout. This can be useful in debugging or combined with a shell script. e.g. ---- # perf probe --definition 'do_sys_open $params' p:probe/do_sys_open _text+2261728 dfd=%di:s32 filename=%si:u64 flags=%dx:s32 mode=%cx:u16 ---- Suggested-and-Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/147214226712.23638.2240534040014013658.stgit@devbox Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
committed by
Arnaldo Carvalho de Melo
parent
893c5c798b
commit
1c20b1d154
@ -21,6 +21,8 @@ or
|
|||||||
'perf probe' [options] --vars='PROBEPOINT'
|
'perf probe' [options] --vars='PROBEPOINT'
|
||||||
or
|
or
|
||||||
'perf probe' [options] --funcs
|
'perf probe' [options] --funcs
|
||||||
|
or
|
||||||
|
'perf probe' [options] --definition='PROBE' [...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -96,6 +98,11 @@ OPTIONS
|
|||||||
can also list functions in a user space executable / shared library.
|
can also list functions in a user space executable / shared library.
|
||||||
This also can accept a FILTER rule argument.
|
This also can accept a FILTER rule argument.
|
||||||
|
|
||||||
|
-D::
|
||||||
|
--definition=::
|
||||||
|
Show trace-event definition converted from given probe-event instead
|
||||||
|
of write it into tracing/[k,u]probe_events.
|
||||||
|
|
||||||
--filter=FILTER::
|
--filter=FILTER::
|
||||||
(Only for --vars and --funcs) Set filter. FILTER is a combination of glob
|
(Only for --vars and --funcs) Set filter. FILTER is a combination of glob
|
||||||
pattern, see FILTER PATTERN for detail.
|
pattern, see FILTER PATTERN for detail.
|
||||||
|
@ -326,6 +326,11 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_cleanup;
|
goto out_cleanup;
|
||||||
|
|
||||||
|
if (params.command == 'D') { /* it shows definition */
|
||||||
|
ret = show_probe_trace_events(pevs, npevs);
|
||||||
|
goto out_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
ret = apply_perf_probe_events(pevs, npevs);
|
ret = apply_perf_probe_events(pevs, npevs);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_cleanup;
|
goto out_cleanup;
|
||||||
@ -454,6 +459,14 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DWARF_SUPPORT
|
||||||
|
#define PROBEDEF_STR \
|
||||||
|
"[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT [[NAME=]ARG ...]"
|
||||||
|
#else
|
||||||
|
#define PROBEDEF_STR "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
{
|
{
|
||||||
@ -479,13 +492,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
opt_set_filter_with_command, DEFAULT_LIST_FILTER),
|
opt_set_filter_with_command, DEFAULT_LIST_FILTER),
|
||||||
OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
|
OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
|
||||||
opt_set_filter_with_command),
|
opt_set_filter_with_command),
|
||||||
OPT_CALLBACK('a', "add", NULL,
|
OPT_CALLBACK('a', "add", NULL, PROBEDEF_STR,
|
||||||
#ifdef HAVE_DWARF_SUPPORT
|
|
||||||
"[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
|
|
||||||
" [[NAME=]ARG ...]",
|
|
||||||
#else
|
|
||||||
"[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
|
|
||||||
#endif
|
|
||||||
"probe point definition, where\n"
|
"probe point definition, where\n"
|
||||||
"\t\tGROUP:\tGroup name (optional)\n"
|
"\t\tGROUP:\tGroup name (optional)\n"
|
||||||
"\t\tEVENT:\tEvent name\n"
|
"\t\tEVENT:\tEvent name\n"
|
||||||
@ -503,6 +510,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
"\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
|
"\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
|
||||||
#endif
|
#endif
|
||||||
opt_add_probe_event),
|
opt_add_probe_event),
|
||||||
|
OPT_CALLBACK('D', "definition", NULL, PROBEDEF_STR,
|
||||||
|
"Show trace event definition of given traceevent for k/uprobe_events.",
|
||||||
|
opt_add_probe_event),
|
||||||
OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
|
OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
|
||||||
" with existing name"),
|
" with existing name"),
|
||||||
OPT_CALLBACK('L', "line", NULL,
|
OPT_CALLBACK('L', "line", NULL,
|
||||||
@ -548,6 +558,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
|
|
||||||
set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
|
set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
|
||||||
set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
|
set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
|
||||||
|
set_option_flag(options, 'D', "definition", PARSE_OPT_EXCLUSIVE);
|
||||||
set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
|
set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
|
||||||
#ifdef HAVE_DWARF_SUPPORT
|
#ifdef HAVE_DWARF_SUPPORT
|
||||||
set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
|
set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
|
||||||
@ -644,6 +655,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
|
case 'D':
|
||||||
/* Ensure the last given target is used */
|
/* Ensure the last given target is used */
|
||||||
if (params.target && !params.target_used) {
|
if (params.target && !params.target_used) {
|
||||||
pr_err(" Error: -x/-m must follow the probe definitions.\n");
|
pr_err(" Error: -x/-m must follow the probe definitions.\n");
|
||||||
|
@ -3207,6 +3207,52 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int show_probe_trace_event(struct probe_trace_event *tev)
|
||||||
|
{
|
||||||
|
char *buf = synthesize_probe_trace_command(tev);
|
||||||
|
|
||||||
|
if (!buf) {
|
||||||
|
pr_debug("Failed to synthesize probe trace event.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Showing definition always go stdout */
|
||||||
|
printf("%s\n", buf);
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int show_probe_trace_events(struct perf_probe_event *pevs, int npevs)
|
||||||
|
{
|
||||||
|
struct strlist *namelist = strlist__new(NULL, NULL);
|
||||||
|
struct probe_trace_event *tev;
|
||||||
|
struct perf_probe_event *pev;
|
||||||
|
int i, j, ret = 0;
|
||||||
|
|
||||||
|
if (!namelist)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (j = 0; j < npevs && !ret; j++) {
|
||||||
|
pev = &pevs[j];
|
||||||
|
for (i = 0; i < pev->ntevs && !ret; i++) {
|
||||||
|
tev = &pev->tevs[i];
|
||||||
|
/* Skip if the symbol is out of .text or blacklisted */
|
||||||
|
if (!tev->point.symbol && !pev->uprobes)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Set new name for tev (and update namelist) */
|
||||||
|
ret = probe_trace_event__set_name(tev, pev,
|
||||||
|
namelist, true);
|
||||||
|
if (!ret)
|
||||||
|
ret = show_probe_trace_event(tev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strlist__delete(namelist);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
|
int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
|
||||||
{
|
{
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
|
@ -147,6 +147,7 @@ int line_range__init(struct line_range *lr);
|
|||||||
int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
|
int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
|
||||||
int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs);
|
int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs);
|
||||||
int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs);
|
int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs);
|
||||||
|
int show_probe_trace_events(struct perf_probe_event *pevs, int npevs);
|
||||||
void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs);
|
void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs);
|
||||||
int del_perf_probe_events(struct strfilter *filter);
|
int del_perf_probe_events(struct strfilter *filter);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user