Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c20b1d1 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Arnaldo Carvalho de Melo
Browse files

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarMasami 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 893c5c79
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ or
'perf probe' [options] --vars='PROBEPOINT'
or
'perf probe' [options] --funcs
or
'perf probe' [options] --definition='PROBE' [...]

DESCRIPTION
-----------
@@ -96,6 +98,11 @@ OPTIONS
	can also list functions in a user space executable / shared library.
	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::
	(Only for --vars and --funcs) Set filter. FILTER is a combination of glob
	pattern, see FILTER PATTERN for detail.
+19 −7
Original line number Diff line number Diff line
@@ -326,6 +326,11 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
	if (ret < 0)
		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);
	if (ret < 0)
		goto out_cleanup;
@@ -454,6 +459,14 @@ static int perf_del_probe_events(struct strfilter *filter)
	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
__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_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
		     opt_set_filter_with_command),
	OPT_CALLBACK('a', "add", NULL,
#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
	OPT_CALLBACK('a', "add", NULL, PROBEDEF_STR,
		"probe point definition, where\n"
		"\t\tGROUP:\tGroup name (optional)\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",
#endif
		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"
		    " with existing name"),
	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, 'd', "del", PARSE_OPT_EXCLUSIVE);
	set_option_flag(options, 'D', "definition", PARSE_OPT_EXCLUSIVE);
	set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
#ifdef HAVE_DWARF_SUPPORT
	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;
	case 'a':
	case 'D':
		/* Ensure the last given target is used */
		if (params.target && !params.target_used) {
			pr_err("  Error: -x/-m must follow the probe definitions.\n");
+46 −0
Original line number Diff line number Diff line
@@ -3207,6 +3207,52 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)
	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 i, ret = 0;
+1 −0
Original line number Diff line number Diff line
@@ -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 convert_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);
int del_perf_probe_events(struct strfilter *filter);