All of lore.kernel.org
 help / color / mirror / Atom feed
From: Masami Hiramatsu <mhiramat@kernel.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>,
	linux-kernel@vger.kernel.org, Namhyung Kim <namhyung@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	Hemant Kumar <hemant@linux.vnet.ibm.com>,
	Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>,
	Brendan Gregg <brendan.d.gregg@gmail.com>
Subject: [PATCH perf/core v10 18/23] perf probe: Allow wildcard for cached events
Date: Wed,  8 Jun 2016 18:31:58 +0900	[thread overview]
Message-ID: <20160608093158.3116.35718.stgit@devbox> (raw)
In-Reply-To: <20160608092854.3116.29007.stgit@devbox>

Allo glob wildcard for reusing cached/SDT events. E.g.

  # perf probe -x /usr/lib64/libc-2.20.so -a %sdt_libc:\*

This example adds probes for all SDT in libc.
Note that the SDTs must have been scanned by perf buildid-cache.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v10:
  - Split off bugfix, adding interface, and target search patches.
  - Do not export clear_probe_trace_events().
 Changes in v7:
  - Continue to search caches if a build-id cache has no probe cache.
  - Make probe_cache__open() to accept DSO__NAME_KALLSYMS for kernel.
  - Fix to add probes correctly when a wildcard matchs both of
    uprobes and kprobes.
 Changes in v5.1:
  - Fix a SEGV bug when a group name is omitted. (Thanks Hemant!)
---
 tools/perf/util/probe-event.c |  107 +++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/probe-file.c  |   38 ++++++++++++---
 tools/perf/util/probe-file.h  |    3 +
 3 files changed, 138 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 443340f..f692fd5 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1206,7 +1206,7 @@ static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
 	ptr = strchr(*arg, ':');
 	if (ptr) {
 		*ptr = '\0';
-		if (!is_c_func_name(*arg))
+		if (!pev->sdt && !is_c_func_name(*arg))
 			goto ng_name;
 		pev->group = strdup(*arg);
 		if (!pev->group)
@@ -1214,7 +1214,7 @@ static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
 		*arg = ptr + 1;
 	} else
 		pev->group = NULL;
-	if (!is_c_func_name(*arg)) {
+	if (!pev->sdt && !is_c_func_name(*arg)) {
 ng_name:
 		semantic_error("%s is bad for event name -it must "
 			       "follow C symbol-naming rule.\n", *arg);
@@ -1644,6 +1644,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
 			ret = -ENOMEM;
 			goto out;
 		}
+		tev->uprobes = (tp->module[0] == '/');
 		p++;
 	} else
 		p = argv[1];
@@ -2518,7 +2519,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 	int ret;
 
 	/* If probe_event or trace_event already have the name, reuse it */
-	if (pev->event)
+	if (pev->event && !pev->sdt)
 		event = pev->event;
 	else if (tev->event)
 		event = tev->event;
@@ -2531,7 +2532,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 		else
 			event = tev->point.realname;
 	}
-	if (pev->group)
+	if (pev->group && !pev->sdt)
 		group = pev->group;
 	else if (tev->group)
 		group = tev->group;
@@ -2894,6 +2895,100 @@ errout:
 
 bool __weak arch__prefers_symtab(void) { return false; }
 
+/* Concatinate two arrays */
+static void *memcat(void *a, size_t sz_a, void *b, size_t sz_b)
+{
+	void *ret;
+
+	ret = malloc(sz_a + sz_b);
+	if (ret) {
+		memcpy(ret, a, sz_a);
+		memcpy(ret + sz_a, b, sz_b);
+	}
+	return ret;
+}
+
+static int
+concat_probe_trace_events(struct probe_trace_event **tevs, int *ntevs,
+			  struct probe_trace_event **tevs2, int ntevs2)
+{
+	struct probe_trace_event *new_tevs;
+	int ret = 0;
+
+	if (ntevs == 0) {
+		*tevs = *tevs2;
+		*ntevs = ntevs2;
+		*tevs2 = NULL;
+		return 0;
+	}
+
+	if (*ntevs + ntevs2 > probe_conf.max_probes)
+		ret = -E2BIG;
+	else {
+		/* Concatinate the array of probe_trace_event */
+		new_tevs = memcat(*tevs, (*ntevs) * sizeof(**tevs),
+				  *tevs2, ntevs2 * sizeof(**tevs2));
+		if (!new_tevs)
+			ret = -ENOMEM;
+		else {
+			free(*tevs);
+			*tevs = new_tevs;
+			*ntevs += ntevs2;
+		}
+	}
+	if (ret < 0)
+		clear_probe_trace_events(*tevs2, ntevs2);
+	zfree(tevs2);
+
+	return ret;
+}
+
+/*
+ * Try to find probe_trace_event from given probe caches. Return the number
+ * of cached events found, if an error occurs return the error.
+ */
+static int find_cached_events(struct perf_probe_event *pev,
+			      struct probe_trace_event **tevs,
+			      const char *target)
+{
+	struct probe_cache *cache;
+	struct probe_cache_entry *entry;
+	struct probe_trace_event *tmp_tevs = NULL;
+	int ntevs = 0;
+	int ret = 0;
+
+	cache = probe_cache__new(target);
+	/* Return 0 ("not found") if the target has no probe cache. */
+	if (!cache)
+		return 0;
+
+	for_each_probe_cache_entry(entry, cache) {
+		/* Skip the cache entry which has no name */
+		if (!entry->pev.event || !entry->pev.group)
+			continue;
+		if ((!pev->group || strglobmatch(entry->pev.group, pev->group)) &&
+		    strglobmatch(entry->pev.event, pev->event)) {
+			ret = probe_cache_entry__get_event(entry, &tmp_tevs);
+			if (ret > 0)
+				ret = concat_probe_trace_events(tevs, &ntevs,
+								&tmp_tevs, ret);
+			if (ret < 0)
+				break;
+		}
+	}
+	probe_cache__delete(cache);
+	if (ret < 0) {
+		clear_probe_trace_events(*tevs, ntevs);
+		zfree(tevs);
+	} else {
+		ret = ntevs;
+		if (ntevs > 0 && target && target[0] == '/')
+			pev->uprobes = true;
+	}
+
+	return ret;
+}
+
 static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 					      struct probe_trace_event **tevs)
 {
@@ -2903,6 +2998,10 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 	struct str_node *node;
 	int ret, i;
 
+	if (pev->sdt)
+		/* For SDT/cached events, we use special search functions */
+		return find_cached_events(pev, tevs, pev->target);
+
 	cache = probe_cache__new(pev->target);
 	if (!cache)
 		return 0;
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 7b60380..3a1d42a 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -360,13 +360,38 @@ probe_cache_entry__new(struct perf_probe_event *pev)
 	return ret;
 }
 
-/* For the kernel probe caches, pass target = NULL */
+int probe_cache_entry__get_event(struct probe_cache_entry *entry,
+				 struct probe_trace_event **tevs)
+{
+	struct probe_trace_event *tev;
+	struct str_node *node;
+	int ret, i;
+
+	ret = strlist__nr_entries(entry->tevlist);
+	if (ret > probe_conf.max_probes)
+		return -E2BIG;
+
+	*tevs = zalloc(ret * sizeof(*tev));
+	if (!*tevs)
+		return -ENOMEM;
+
+	i = 0;
+	strlist__for_each(node, entry->tevlist) {
+		tev = &(*tevs)[i++];
+		ret = parse_probe_trace_command(node->s, tev);
+		if (ret < 0)
+			break;
+	}
+	return i;
+}
+
+/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
 static int probe_cache__open(struct probe_cache *pcache, const char *target)
 {
 	char cpath[PATH_MAX];
 	char sbuildid[SBUILD_ID_SIZE];
 	char *dir_name = NULL;
-	bool is_kallsyms = !target;
+	bool is_kallsyms = false;
 	int ret, fd;
 
 	if (target && build_id_cache__cached(target)) {
@@ -376,12 +401,13 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
 		goto found;
 	}
 
-	if (target)
-		ret = filename__sprintf_build_id(target, sbuildid);
-	else {
+	if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) {
 		target = DSO__NAME_KALLSYMS;
+		is_kallsyms = true;
 		ret = sysfs__sprintf_build_id("/", sbuildid);
-	}
+	} else
+		ret = filename__sprintf_build_id(target, sbuildid);
+
 	if (ret < 0) {
 		pr_debug("Failed to get build-id from %s.\n", target);
 		return ret;
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 6271ec6..0faf083 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -36,6 +36,9 @@ int probe_file__get_events(int fd, struct strfilter *filter,
 				  struct strlist *plist);
 int probe_file__del_strlist(int fd, struct strlist *namelist);
 
+int probe_cache_entry__get_event(struct probe_cache_entry *entry,
+				 struct probe_trace_event **tevs);
+
 struct probe_cache *probe_cache__new(const char *target);
 int probe_cache__add_entry(struct probe_cache *pcache,
 			   struct perf_probe_event *pev,

  parent reply	other threads:[~2016-06-08  9:32 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-08  9:29 [PATCH perf/core v10 00/23] perf-probe --cache and SDT support Masami Hiramatsu
2016-06-08  9:29 ` [PATCH perf/core v10 01/23] perf: util: Fix rm_rf() to handle non-regular files correctly Masami Hiramatsu
2016-06-16  8:31   ` [tip:perf/core] perf tools: " tip-bot for Masami Hiramatsu
2016-06-08  9:29 ` [PATCH perf/core v10 02/23] perf-probe: Fix to add NULL check for strndup Masami Hiramatsu
2016-06-16  8:32   ` [tip:perf/core] perf probe: " tip-bot for Masami Hiramatsu
2016-06-08  9:29 ` [PATCH perf/core v10 03/23] perf-buildid: Rename and export build_id_cache__cachedir() Masami Hiramatsu
2016-06-16  8:32   ` [tip:perf/core] perf buildid: " tip-bot for Masami Hiramatsu
2016-06-08  9:29 ` [PATCH perf/core v10 04/23] perf probe: Add perf_probe_event__copy() Masami Hiramatsu
2016-06-16  8:33   ` [tip:perf/core] " tip-bot for Masami Hiramatsu
2016-06-08  9:29 ` [PATCH perf/core v10 05/23] perf probe: Recover and export synthesize_perf_probe_point() Masami Hiramatsu
2016-06-16  8:33   ` [tip:perf/core] perf probe: Uncomment " tip-bot for Masami Hiramatsu
2016-06-08  9:29 ` [PATCH perf/core v10 06/23] perf probe-file: Introduce perf_cache interfaces Masami Hiramatsu
2016-06-09 14:16   ` Arnaldo Carvalho de Melo
2016-06-10 22:18     ` Masami Hiramatsu
2016-06-08  9:30 ` [PATCH perf/core v10 07/23] perf probe: Add --cache option to cache the probe definitions Masami Hiramatsu
2016-06-09 14:18   ` Arnaldo Carvalho de Melo
2016-06-10 23:32     ` Masami Hiramatsu
2016-06-08  9:30 ` [PATCH perf/core v10 08/23] perf probe: Use cache entry if possible Masami Hiramatsu
2016-06-08  9:30 ` [PATCH perf/core v10 09/23] perf probe: Show all cached probes Masami Hiramatsu
2016-06-09 14:22   ` Arnaldo Carvalho de Melo
2016-06-11  0:28     ` Masami Hiramatsu
2016-06-12  3:20       ` Masami Hiramatsu
2016-06-08  9:30 ` [PATCH perf/core v10 10/23] perf probe: Remove caches when --cache is given Masami Hiramatsu
2016-06-09 14:28   ` Arnaldo Carvalho de Melo
2016-06-11  1:17     ` Masami Hiramatsu
2016-06-08  9:30 ` [PATCH perf/core v10 11/23] perf/sdt: ELF support for SDT Masami Hiramatsu
2016-06-08  9:31 ` [PATCH perf/core v10 12/23] perf probe: Add group name support Masami Hiramatsu
2016-06-08  9:31 ` [PATCH perf/core v10 13/23] perf buildid-cache: Scan and import user SDT events to probe cache Masami Hiramatsu
2016-06-08  9:31 ` [PATCH perf/core v10 14/23] perf probe: Accept %sdt and %cached event name Masami Hiramatsu
2016-06-08  9:31 ` [PATCH perf/core v10 15/23] perf-list: Show SDT and pre-cached events Masami Hiramatsu
2016-06-08  9:31 ` [PATCH perf/core v10 16/23] perf-list: Skip SDTs placed in invalid binaries Masami Hiramatsu
2016-06-08  9:31 ` [PATCH perf/core v10 17/23] perf: probe-cache: Add for_each_probe_cache_entry() wrapper Masami Hiramatsu
2016-06-08  9:31 ` Masami Hiramatsu [this message]
2016-06-08  9:32 ` [PATCH perf/core v10 19/23] perf probe: Search SDT/cached event from all probe caches Masami Hiramatsu
2016-06-08  9:32 ` [PATCH perf/core v10 20/23] perf probe: Support @BUILDID or @FILE suffix for SDT events Masami Hiramatsu
2016-06-08  9:32 ` [PATCH perf/core v10 21/23] perf probe: Support a special SDT probe format Masami Hiramatsu
2016-06-08  9:32 ` [PATCH perf/core v10 22/23] perf build: Add sdt feature detection Masami Hiramatsu
2016-06-08  9:32 ` [PATCH perf/core v10 23/23] perf-test: Add a test case for SDT event Masami Hiramatsu
2016-06-08 11:13 ` [PATCH perf/core v10 00/23] perf-probe --cache and SDT support Masami Hiramatsu
2016-06-08 11:15 ` [PATCH perf/core v10 22/23] perf build: Add sdt feature detection Masami Hiramatsu
2016-06-08 11:16 ` [PATCH perf/core v10 23/23] perf-test: Add a test case for SDT event Masami Hiramatsu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160608093158.3116.35718.stgit@devbox \
    --to=mhiramat@kernel.org \
    --cc=acme@kernel.org \
    --cc=ananth@linux.vnet.ibm.com \
    --cc=brendan.d.gregg@gmail.com \
    --cc=hemant@linux.vnet.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.