Commit 45237f98 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Arnaldo Carvalho de Melo
Browse files

perf probe: Add --bootconfig to output definition in bootconfig format



Now the boot-time tracing supports kprobes events and that must be
written in bootconfig file in the following format.

  ftrace.event.kprobes.<EVENT_NAME>.probes = <PROBE-DEF>

'perf probe' already supports --definition (-D) action to show probe
definitions, but the format is for tracefs:

  [p|r][:EVENT_NAME] <PROBE-DEF>

This patch adds the --bootconfig option for -D action so that it outputs
the probe definitions in bootconfig format. E.g.

  $ perf probe --bootconfig -D "path_lookupat:7 err:s32 s:string"
  ftrace.event.kprobes.path_lookupat_L7.probe = 'path_lookupat.isra.0+309 err_s32=%ax:s32 s_string=+0(%r13):string'

Signed-off-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/162282412351.452340.14871995440005640114.stgit@devnote2


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent d26ea481
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -347,6 +347,9 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
		goto out_cleanup;

	if (params.command == 'D') {	/* it shows definition */
		if (probe_conf.bootconfig)
			ret = show_bootconfig_events(pevs, npevs);
		else
			ret = show_probe_trace_events(pevs, npevs);
		goto out_cleanup;
	}
@@ -581,6 +584,8 @@ __cmd_probe(int argc, const char **argv)
		   "Look for files with symbols relative to this directory"),
	OPT_CALLBACK(0, "target-ns", NULL, "pid",
		     "target pid for namespace contexts", opt_set_target_ns),
	OPT_BOOLEAN(0, "bootconfig", &probe_conf.bootconfig,
		    "Output probe definition with bootconfig format"),
	OPT_END()
	};
	int ret;
@@ -692,6 +697,11 @@ __cmd_probe(int argc, const char **argv)
		}
		break;
	case 'D':
		if (probe_conf.bootconfig && params.uprobes) {
			pr_err("  Error: --bootconfig doesn't support uprobes.\n");
			return -EINVAL;
		}
		__fallthrough;
	case 'a':

		/* Ensure the last given target is used */
+72 −0
Original line number Diff line number Diff line
@@ -3564,6 +3564,78 @@ int show_probe_trace_events(struct perf_probe_event *pevs, int npevs)
	return ret;
}

static int show_bootconfig_event(struct probe_trace_event *tev)
{
	struct probe_trace_point *tp = &tev->point;
	struct strbuf buf;
	char *ret = NULL;
	int err;

	if (strbuf_init(&buf, 32) < 0)
		return -ENOMEM;

	err = synthesize_kprobe_trace_def(tp, &buf);
	if (err >= 0)
		err = synthesize_probe_trace_args(tev, &buf);
	if (err >= 0)
		ret = strbuf_detach(&buf, NULL);
	strbuf_release(&buf);

	if (ret) {
		printf("'%s'", ret);
		free(ret);
	}

	return err;
}

int show_bootconfig_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;
	char *cur_name = NULL;
	int i, j, ret = 0;

	if (!namelist)
		return -ENOMEM;

	for (j = 0; j < npevs && !ret; j++) {
		pev = &pevs[j];
		if (pev->group && strcmp(pev->group, "probe"))
			pr_warning("WARN: Group name %s is ignored\n", pev->group);
		if (pev->uprobes) {
			pr_warning("ERROR: Bootconfig doesn't support uprobes\n");
			ret = -EINVAL;
			break;
		}
		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)
				break;

			if (!cur_name || strcmp(cur_name, tev->event)) {
				printf("%sftrace.event.kprobes.%s.probe = ",
					cur_name ? "\n" : "", tev->event);
				cur_name = tev->event;
			} else
				printf(", ");
			ret = show_bootconfig_event(tev);
		}
	}
	printf("\n");
	strlist__delete(namelist);

	return ret;
}

int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
{
	int i, ret = 0;
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ struct probe_conf {
	bool	force_add;
	bool	no_inlines;
	bool	cache;
	bool	bootconfig;
	int	max_probes;
	unsigned long	magic_num;
};
@@ -163,6 +164,7 @@ 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);
int show_bootconfig_events(struct perf_probe_event *pevs, int npevs);
void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs);

struct strfilter;