Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1184459 > unrolled thread

[RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support

Started byMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
First post2015-07-15 11:20 +0200
Last post2015-07-20 20:50 +0200
Articles 20 on this page of 22 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-15 11:20 +0200
    [RFC PATCH perf/core v2 08/16] perf-buildid-cache: Use lsdir for  looking up buildid caches Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-15 11:20 +0200
    [RFC PATCH perf/core v2 11/16] perf probe: Show all cached probes Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-15 11:20 +0200
    [RFC PATCH perf/core v2 10/16] perf probe: Use cache entry if  possible Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-15 11:20 +0200
    [RFC PATCH perf/core v2 03/16] perf probe: Use strbuf for making  strings in probe-event.c Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-15 11:20 +0200
      Re: [RFC PATCH perf/core v2 03/16] perf probe: Use strbuf for making  strings in probe-event.c Namhyung Kim <namhyung@kernel.org> - 2015-07-17 10:00 +0200
        Re: Re: [RFC PATCH perf/core v2 03/16] perf probe: Use strbuf  for making strings in probe-event.c Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-17 12:20 +0200
    [RFC PATCH perf/core v2 07/16] perf: Add lsdir to read a directory Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-15 11:20 +0200
    [RFC PATCH perf/core v2 13/16] perf/sdt: ELF support for SDT Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-15 11:20 +0200
    [RFC PATCH perf/core v2 16/16] perf probe: Accept %sdt and %cached  event name Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-15 11:30 +0200
      Re: [RFC PATCH perf/core v2 16/16] perf probe: Accept %sdt and  %cached event name Namhyung Kim <namhyung@kernel.org> - 2015-07-19 13:00 +0200
    [RFC PATCH perf/core v2 15/16] perf buildid-cache: Scan and import  user SDT events to probe cache Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-15 11:30 +0200
      Re: [RFC PATCH perf/core v2 15/16] perf buildid-cache: Scan and  import user SDT events to probe cache Namhyung Kim <namhyung@kernel.org> - 2015-07-19 12:50 +0200
    Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support Hemant Kumar <hemant@linux.vnet.ibm.com> - 2015-07-16 05:20 +0200
      Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support Hemant Kumar <hemant@linux.vnet.ibm.com> - 2015-07-22 16:20 +0200
        Re: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and  SDT support Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-23 15:20 +0200
          Re: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT  support Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-07-23 16:10 +0200
            Re: Re: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and  SDT support Namhyung Kim <namhyung@kernel.org> - 2015-07-24 10:10 +0200
              Re: Re: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and  SDT support Namhyung Kim <namhyung@kernel.org> - 2015-07-27 16:10 +0200
                Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> - 2015-07-28 02:50 +0200
    Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-07-20 20:40 +0200
      Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-07-20 20:50 +0200

Page 1 of 2  [1] 2  Next page →


#1184459 — [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-15 11:20 +0200
Subject[RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support
Message-ID<pMr17-36Z-3@gated-at.bofh.it>
Hi,

Here is the 2nd version of the patchset for probe-cache and 
initial SDT support which are going to be perf-cache finally.

The perf-probe is useful for debugging, but it strongly depends
on the debuginfo. Without debuginfo, it is just a frontend of
ftrace's dynamic events. This can usually happen in server
farms or on cloud system, since no one wants to distribute
big debuginfo packages.

To solve this issue, I had tried to make a pre-analyzed probes
( https://lkml.org/lkml/2014/10/31/207 ) but it has a problm
that we can't ensure the probed binary is same as what we analyzed.
Arnaldo gave me an idea to reuse build-id cache for that perpose
and this series is the first prototype of that.

At the same time, Hemant has started to support SDT probes which
also use the cache file of SDT info. So I decided to merge this
into the same build-id cache.
In this version, SDT support is still very limited, it works
as a part of probe-cache.

In this version, perf probe supports --cache option which means
that perf probe manipulate probe caches, for example,

  # perf probe --cache --add "probe-desc"

does not only add probe events but also add "probe-desc" and
it's result on the cache. (Note that the cached entry is always
referred even without --cache)
The --list and --del commands also support --cache. Note that
both are only manipulate caches, not real events.

To use SDT, we have to scan the target binary at first by using
perf-buildid-cache, e.g.

  # perf buildid-cache --add /lib/libc-2.17.so 

And perf probe --cache --list shows what SDTs are scanned.

  # perf probe --cache --list
  /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
  libc:setjmp=setjmp
  libc:longjmp=longjmp
  libc:longjmp_target=longjmp_target
  libc:memory_heap_new=memory_heap_new
  libc:memory_sbrk_less=memory_sbrk_less
  libc:memory_arena_reuse_free_list=memory_arena_reuse_free_list
  libc:memory_arena_reuse=memory_arena_reuse
  ...

To use the SDT events, perf probe -x BIN %SDTEVENT allows you to
add a probe on SDTEVENT@BIN.

  # perf probe -x /lib/libc-2.17.so %memory_heap_new

If you define a cached probe with event name, you can also reuse
it as same as SDT events.

  # perf probe -x ./perf --cache -n 'myevent=dso__load $params'

(Note that "-n" option only updates caches)
To use the above "myevent", you just have to add "%myevent".

  # perf probe -x ./perf %myevent


TODOs:
 - Show available cached/SDT events by perf-list
 - Allow perf-record to use cached/SDT events directly

Thank you,

---

Hemant Kumar (1):
      perf/sdt: ELF support for SDT

Masami Hiramatsu (15):
      perf probe: Simplify __add_probe_trace_events code
      perf probe: Move ftrace probe-event operations to probe-file.c
      perf probe: Use strbuf for making strings in probe-event.c
      perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid
      perf buildid: Use SBUILD_ID_SIZE macro
      perf buildid: Introduce sysfs/filename__sprintf_build_id
      perf: Add lsdir to read a directory
      perf-buildid-cache: Use lsdir for looking up buildid caches
      perf probe: Add --cache option to cache the probe definitions
      perf probe: Use cache entry if possible
      perf probe: Show all cached probes
      perf probe: Remove caches when --cache is given
      perf probe: Add group name support
      perf buildid-cache: Scan and import user SDT events to probe cache
      perf probe: Accept %sdt and %cached event name


 tools/perf/Documentation/perf-probe.txt |   14 
 tools/perf/builtin-buildid-cache.c      |   22 -
 tools/perf/builtin-buildid-list.c       |   28 -
 tools/perf/builtin-probe.c              |    3 
 tools/perf/util/Build                   |    1 
 tools/perf/util/build-id.c              |  230 ++++++--
 tools/perf/util/build-id.h              |   11 
 tools/perf/util/dso.h                   |    5 
 tools/perf/util/probe-event.c           |  918 ++++++++++++++-----------------
 tools/perf/util/probe-event.h           |   16 -
 tools/perf/util/probe-file.c            |  763 ++++++++++++++++++++++++++
 tools/perf/util/probe-file.h            |   46 ++
 tools/perf/util/probe-finder.c          |   10 
 tools/perf/util/symbol-elf.c            |  252 +++++++++
 tools/perf/util/symbol.c                |    2 
 tools/perf/util/symbol.h                |   22 +
 tools/perf/util/util.c                  |   34 +
 tools/perf/util/util.h                  |    4 
 18 files changed, 1781 insertions(+), 600 deletions(-)
 create mode 100644 tools/perf/util/probe-file.c
 create mode 100644 tools/perf/util/probe-file.h


-- 
Masami HIRAMATSU
Linux Technology Research Center, System Productivity Research Dept.
Center for Technology Innovation - Systems Engineering 
Hitachi, Ltd., Research & Development Group
E-mail: masami.hiramatsu.pt@hitachi.com

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1184461 — [RFC PATCH perf/core v2 08/16] perf-buildid-cache: Use lsdir for looking up buildid caches

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-15 11:20 +0200
Subject[RFC PATCH perf/core v2 08/16] perf-buildid-cache: Use lsdir for looking up buildid caches
Message-ID<pMr19-36Z-65@gated-at.bofh.it>
In reply to#1184459
Use new lsdir() for looking up buildid caches. This changes
logic a bit to ignore all dot files, since the build-id
cache must not start with dot.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
---
 tools/perf/util/build-id.c |   30 +++++-------------------------
 1 file changed, 5 insertions(+), 25 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 8c40133..02a5e0d 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -342,38 +342,18 @@ int build_id_cache__list_build_ids(const char *pathname,
 {
 	struct strlist *list;
 	char *dir_name;
-	DIR *dir;
-	struct dirent *d;
 	int ret = 0;
 
-	list = strlist__new(true, NULL);
 	dir_name = build_id_cache__dirname_from_path(pathname, false, false,
 						     NULL);
-	if (!list || !dir_name) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!dir_name)
+		return -ENOMEM;
 
-	/* List up all dirents */
-	dir = opendir(dir_name);
-	if (!dir) {
+	list = lsdir(dir_name, lsdir_no_dot_filter);
+	if (!list)
 		ret = -errno;
-		goto out;
-	}
-
-	while ((d = readdir(dir)) != NULL) {
-		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
-			continue;
-		strlist__add(list, d->d_name);
-	}
-	closedir(dir);
-
-out:
+	*result = list;
 	free(dir_name);
-	if (ret)
-		strlist__delete(list);
-	else
-		*result = list;
 
 	return ret;
 }


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1184462 — [RFC PATCH perf/core v2 11/16] perf probe: Show all cached probes

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-15 11:20 +0200
Subject[RFC PATCH perf/core v2 11/16] perf probe: Show all cached probes
Message-ID<pMr19-36Z-67@gated-at.bofh.it>
In reply to#1184459
perf probe --list shows all cached probes when --cache
is given. Each caches are shown with on which binary that
probed. e.g.
  -----
  # perf probe --cache vfs_read \$params
  # perf probe --cache -x /lib64/libc-2.17.so getaddrinfo \$params
  # ./perf probe --cache --list
  /[kernel.kallsyms] (1466a0a250b5d0070c6d0f03c5fed30b237970a1):
  vfs_read $params
  /usr/lib64/libc-2.17.so (c31ffe7942bfd77b2fca8f9bd5709d387a86d3bc):
  getaddrinfo $params
  -----
Note that $params requires debuginfo.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

---
Changes in v2:
 - Fix to ignore if build-id list is failed to get with -ENOENT,
   since this can happen when ~/.debug is not initialized.
 - Do not show binary name if there is no cached entries.
 - Update perf-probe.txt too.
---
 tools/perf/Documentation/perf-probe.txt |    8 ++-
 tools/perf/builtin-probe.c              |    2 -
 tools/perf/util/build-id.c              |   79 ++++++++++++++++++++++++++++++-
 tools/perf/util/build-id.h              |    3 +
 tools/perf/util/probe-event.c           |    3 +
 tools/perf/util/probe-file.c            |   65 +++++++++++++++++++++++++-
 tools/perf/util/probe-file.h            |    1 
 7 files changed, 154 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 947db6f..5a70d45 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -67,7 +67,10 @@ OPTIONS
 
 -l::
 --list[=[GROUP:]EVENT]::
-	List up current probe events. This can also accept filtering patterns of event names.
+	List up current probe events. This can also accept filtering patterns of
+	event names.
+	When this is used with --cache, perf shows all cached probes instead of
+	the live probes.
 
 -L::
 --line=::
@@ -110,8 +113,9 @@ OPTIONS
 	adding and removal operations.
 
 --cache::
-	Cache the probes (with --add option). Any events which successfully added
+	(With --add) Cache the probes. Any events which successfully added
 	are also stored in the cache file.
+	(With --list) Show cached probes.
 
 --max-probes=NUM::
 	Set the maximum number of probe points for an event. Default is 128.
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 5ac8a79..5d0c246 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -44,7 +44,7 @@
 
 #define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
 #define DEFAULT_FUNC_FILTER "!_*"
-#define DEFAULT_LIST_FILTER "*:*"
+#define DEFAULT_LIST_FILTER "*"
 
 /* Session management structure */
 static struct {
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 169639e..63123c1 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -144,8 +144,7 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
 	return ret;
 }
 
-static char *build_id_cache__linkname(const char *sbuild_id, char *bf,
-				      size_t size)
+char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size)
 {
 	char *tmp = bf;
 	int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
@@ -155,6 +154,29 @@ static char *build_id_cache__linkname(const char *sbuild_id, char *bf,
 	return bf;
 }
 
+char *build_id_cache__origname(const char *sbuild_id)
+{
+	char *linkname;
+	char buf[PATH_MAX];
+	char *ret = NULL, *p;
+
+	linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
+	if (!linkname)
+		return NULL;
+
+	if (readlink(linkname, buf, PATH_MAX) < 0)
+		goto out;
+	/* The link should be "../..<origpath>/<sbuild_id>" */
+	p = strrchr(buf, '/');	/* Cut off the "/<sbuild_id>" */
+	if (p) {
+		*p = '\0';
+		ret = strdup(buf + 5);	/* Skip "../.." */
+	}
+out:
+	free(linkname);
+	return ret;
+}
+
 static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
 {
 	return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
@@ -313,6 +335,59 @@ void disable_buildid_cache(void)
 	no_buildid_cache = true;
 }
 
+int build_id_cache__list_all(struct strlist **result)
+{
+	struct strlist *toplist, *list, *bidlist;
+	struct str_node *nd, *nd2;
+	char *topdir, *linkdir;
+	char sbuild_id[SBUILD_ID_SIZE];
+	int ret = 0;
+
+	/* Open the top-level directory */
+	if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
+		return -errno;
+	toplist = lsdir(topdir, lsdir_no_dot_filter);
+	if (!toplist) {
+		pr_debug("Failed to opendir %s\n", topdir);
+		ret = -errno;
+		goto out;
+	}
+	bidlist = strlist__new(true, NULL);
+	strlist__for_each(nd, toplist) {
+		if (asprintf(&linkdir, "%s/%s", topdir, nd->s) < 0) {
+			ret = -errno;
+			goto out;
+		}
+		/* Open the lower-level directory */
+		list = lsdir(linkdir, lsdir_no_dot_filter);
+		if (!list) {
+			pr_debug("Failed to open %s: %d\n", linkdir, -errno);
+			goto next;
+		}
+		strlist__for_each(nd2, list) {
+			ret = snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s",
+					nd->s, nd2->s);
+			if (ret != SBUILD_ID_SIZE - 1) {
+				pr_debug("%s/%s is not buildid cache\n",
+					nd->s, nd2->s);
+				continue;
+			}
+			strlist__add(bidlist, sbuild_id);
+		}
+		strlist__delete(list);
+next:
+		free(linkdir);
+	}
+
+	*result = bidlist;
+out:
+	if (toplist)
+		strlist__delete(toplist);
+	free(topdir);
+
+	return ret;
+}
+
 char *build_id_cache__dirname_from_path(const char *sbuild_id, const char *name,
 					bool is_kallsyms, bool is_vdso)
 {
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index a1f428d..2d5c61c 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -27,8 +27,11 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
 int perf_session__write_buildid_table(struct perf_session *session, int fd);
 int perf_session__cache_build_ids(struct perf_session *session);
 
+char *build_id_cache__origname(const char *sbuild_id);
+char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
 char *build_id_cache__dirname_from_path(const char *sbuild_id, const char *name,
 					bool is_kallsyms, bool is_vdso);
+int build_id_cache__list_all(struct strlist **result);
 int build_id_cache__list_build_ids(const char *pathname,
 				   struct strlist **result);
 bool build_id_cache__cached(const char *sbuild_id);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index c71b16b..23b577b 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2210,6 +2210,9 @@ int show_perf_probe_events(struct strfilter *filter)
 
 	setup_pager();
 
+	if (probe_conf.cache)
+		return probe_cache__show_all_caches(filter);
+
 	ret = init_symbol_maps(false);
 	if (ret < 0)
 		return ret;
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 984f690..da69ff7 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -340,10 +340,17 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
 {
 	char cpath[PATH_MAX];
 	char sbuildid[SBUILD_ID_SIZE];
-	char *dir_name;
+	char *dir_name = NULL;
 	bool is_kallsyms = !target;
 	int ret, fd;
 
+	if (target && build_id_cache__cached(target)) {
+		/* This is a cached buildid */
+		strncpy(sbuildid, target, SBUILD_ID_SIZE);
+		dir_name = build_id_cache__linkname(sbuildid, NULL, 0);
+		goto found;
+	}
+
 	if (target)
 		ret = filename__sprintf_build_id(target, sbuildid);
 	else {
@@ -367,8 +374,11 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
 
 	dir_name = build_id_cache__dirname_from_path(sbuildid, target,
 						     is_kallsyms, false);
-	if (!dir_name)
+found:
+	if (!dir_name) {
+		pr_debug("Failed to get cache from %s\n", target);
 		return -ENOMEM;
+	}
 
 	snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
 	fd = open(cpath, O_CREAT | O_RDWR | O_APPEND, 0644);
@@ -616,3 +626,54 @@ int probe_cache__commit(struct probe_cache *pcache)
 out:
 	return ret;
 }
+
+static int probe_cache__show_entries(struct probe_cache *pcache,
+				     struct strfilter *filter)
+{
+	struct probe_cache_entry *entry;
+	char buf[128], *ptr;
+
+	list_for_each_entry(entry, &pcache->list, list) {
+		if (entry->pev.event) {
+			ptr = buf;
+			snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event);
+		} else
+			ptr = entry->spev;
+		if (strfilter__compare(filter, ptr))
+			printf("%s\n", entry->spev);
+	}
+	return 0;
+}
+
+/* Show all cached probes */
+int probe_cache__show_all_caches(struct strfilter *filter)
+{
+	struct probe_cache *pcache;
+	struct strlist *bidlist;
+	struct str_node *nd;
+	char *buf;
+	int ret;
+
+	buf = strfilter__string(filter);
+	pr_debug("list cache with filter: %s\n", buf);
+	free(buf);
+
+	ret = build_id_cache__list_all(&bidlist);
+	if (ret < 0) {
+		pr_debug("Failed to get buildids: %d\n", ret);
+		return ret == -ENOENT ? 0 : ret;
+	}
+	strlist__for_each(nd, bidlist) {
+		pcache = probe_cache__new(nd->s);
+		if (!pcache)
+			continue;
+		if (!list_empty(&pcache->list)) {
+			buf = build_id_cache__origname(nd->s);
+			printf("%s (%s):\n", buf, nd->s);
+			free(buf);
+			probe_cache__show_entries(pcache, filter);
+		}
+		probe_cache__delete(pcache);
+	}
+	return 0;
+}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 833e061..26dc4f7 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -38,4 +38,5 @@ struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
 					    struct perf_probe_event *pev);
 struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
 					const char *group, const char *event);
+int probe_cache__show_all_caches(struct strfilter *filter);
 #endif


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1184467 — [RFC PATCH perf/core v2 10/16] perf probe: Use cache entry if possible

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-15 11:20 +0200
Subject[RFC PATCH perf/core v2 10/16] perf probe: Use cache entry if possible
Message-ID<pMr1a-36Z-77@gated-at.bofh.it>
In reply to#1184459
Before analyzing debuginfo, try to find a corresponding entry
from probe cache always. This does not depend on --cache,
the --cache enables to store/update cache, but looking up
the cache is always enabled.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

---
Changes in v2:
 - Reuse tev->event and tev->group as base event name if possible,
   since when using the cache entry with wildcard, pev will not
   have its name/symbol.
 - Do not skip trace events whose tev->point.symbol == NULL if
   pev->uprobes is set, since cached uprobe event doesn't know
   the original symbols.
 - Fix to set tev->uprobes attribute flag from the pev->uprobes.
---
 tools/perf/util/probe-event.c |   70 ++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/probe-file.c  |   20 +++++++++++-
 tools/perf/util/probe-file.h  |    5 ++-
 3 files changed, 91 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index fc30c2d..c71b16b 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2310,13 +2310,18 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 
 	if (pev->event)
 		event = pev->event;
-	else
+	else if (tev->event)
+		event = tev->event;
+	else {
 		if (pev->point.function && !strisglob(pev->point.function))
 			event = pev->point.function;
 		else
 			event = tev->point.realname;
+	}
 	if (pev->group)
 		group = pev->group;
+	else if (tev->group)
+		group = tev->group;
 	else
 		group = PERFPROBE_GROUP;
 
@@ -2366,7 +2371,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 	for (i = 0; i < ntevs; i++) {
 		tev = &tevs[i];
 		/* Skip if the symbol is out of .text or blacklisted */
-		if (!tev->point.symbol)
+		if (!tev->point.symbol && !pev->uprobes)
 			continue;
 
 		/* Set new name for tev (and update namelist) */
@@ -2589,6 +2594,62 @@ err_out:
 
 bool __weak arch__prefers_symtab(void) { return false; }
 
+static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
+					      struct probe_trace_event **tevs)
+{
+	struct probe_cache *cache;
+	struct probe_cache_entry *entry;
+	struct probe_trace_event *tev;
+	struct str_node *node;
+	int ret, i;
+
+	cache = probe_cache__new(pev->target);
+	if (!cache)
+		return 0;
+
+	entry = probe_cache__find(cache, pev);
+
+	if (!entry && !pev->event &&
+	    (!pev->point.file && pev->point.function && !pev->point.retprobe &&
+	     !pev->point.line && !pev->point.offset && !pev->point.lazy_line)) {
+		entry = probe_cache__find_by_name(cache, pev->group,
+						  pev->point.function);
+	}
+	if (!entry) {
+		ret = 0;
+		goto out;
+	}
+
+	ret = strlist__nr_entries(entry->tevlist);
+	if (ret > probe_conf.max_probes) {
+		pr_debug("Too many entries matched in the cache of %s\n",
+			 pev->target ? : "kernel");
+		ret = -E2BIG;
+		goto out;
+	}
+
+	*tevs = zalloc(ret * sizeof(*tev));
+	if (!*tevs) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	i = 0;
+	strlist__for_each(node, entry->tevlist) {
+		tev = &(*tevs)[i++];
+		ret = parse_probe_trace_command(node->s, tev);
+		if (ret < 0)
+			goto out;
+		/* Set the uprobes attribute as same as original */
+		tev->uprobes = pev->uprobes;
+	}
+	ret = i;
+
+out:
+	probe_cache__delete(cache);
+	return ret;
+}
+
 static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 					 struct probe_trace_event **tevs)
 {
@@ -2603,6 +2664,11 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 		}
 	}
 
+	/* At first, we need to lookup cache entry */
+	ret = find_probe_trace_events_from_cache(pev, tevs);
+	if (ret > 0)
+		return ret;	/* Found in probe cache */
+
 	if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
 		ret = find_probe_trace_events_from_map(pev, tevs);
 		if (ret > 0)
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 572e8c2..984f690 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -481,7 +481,7 @@ static bool streql(const char *a, const char *b)
 	return !strcmp(a, b);
 }
 
-static struct probe_cache_entry *
+struct probe_cache_entry *
 probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
 {
 	struct probe_cache_entry *entry = NULL;
@@ -506,6 +506,24 @@ found:
 	return entry;
 }
 
+struct probe_cache_entry *
+probe_cache__find_by_name(struct probe_cache *pcache,
+			  const char *group, const char *event)
+{
+	struct probe_cache_entry *entry = NULL;
+
+	list_for_each_entry(entry, &pcache->list, list) {
+		/* Hit if same event name or same command-string */
+		if (streql(entry->pev.group, group) &&
+		    streql(entry->pev.event, event))
+			goto found;
+	}
+	entry = NULL;
+
+found:
+	return entry;
+}
+
 int probe_cache__add_entry(struct probe_cache *pcache,
 			   struct perf_probe_event *pev,
 			   struct probe_trace_event *tevs, int ntevs)
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 7b473b39..833e061 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -34,5 +34,8 @@ int probe_cache__add_entry(struct probe_cache *pcache,
 			   struct probe_trace_event *tevs, int ntevs);
 int probe_cache__commit(struct probe_cache *pcache);
 void probe_cache__delete(struct probe_cache *pcache);
-
+struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
+					    struct perf_probe_event *pev);
+struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
+					const char *group, const char *event);
 #endif


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1184468 — [RFC PATCH perf/core v2 03/16] perf probe: Use strbuf for making strings in probe-event.c

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-15 11:20 +0200
Subject[RFC PATCH perf/core v2 03/16] perf probe: Use strbuf for making strings in probe-event.c
Message-ID<pMr1a-36Z-79@gated-at.bofh.it>
In reply to#1184459
Replace many fixed-length char array with strbuf to
stringify perf_probe_event and probe_trace_event etc. in
util/probe-event.c.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
---
Changes in v2:
 - Make perf_probe_event__sprintf() simpler.
---
 tools/perf/util/probe-event.c  |  242 ++++++++++++++--------------------------
 tools/perf/util/probe-event.h  |    3 
 tools/perf/util/probe-finder.c |   10 +-
 3 files changed, 92 insertions(+), 163 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index fe4941a..b6ed15e 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1562,69 +1562,52 @@ out:
 }
 
 /* Compose only probe arg */
-int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
+char *synthesize_perf_probe_arg(struct perf_probe_arg *pa)
 {
 	struct perf_probe_arg_field *field = pa->field;
-	int ret;
-	char *tmp = buf;
+	struct strbuf buf;
+	char *ret;
 
+	strbuf_init(&buf, 64);
 	if (pa->name && pa->var)
-		ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
+		strbuf_addf(&buf, "%s=%s", pa->name, pa->var);
 	else
-		ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
-	if (ret <= 0)
-		goto error;
-	tmp += ret;
-	len -= ret;
+		strbuf_addstr(&buf, pa->name ?: pa->var);
 
 	while (field) {
 		if (field->name[0] == '[')
-			ret = e_snprintf(tmp, len, "%s", field->name);
+			strbuf_addstr(&buf, field->name);
 		else
-			ret = e_snprintf(tmp, len, "%s%s",
-					 field->ref ? "->" : ".", field->name);
-		if (ret <= 0)
-			goto error;
-		tmp += ret;
-		len -= ret;
+			strbuf_addf(&buf, "%s%s", field->ref ? "->" : ".",
+				    field->name);
 		field = field->next;
 	}
 
-	if (pa->type) {
-		ret = e_snprintf(tmp, len, ":%s", pa->type);
-		if (ret <= 0)
-			goto error;
-		tmp += ret;
-		len -= ret;
-	}
+	if (pa->type)
+		strbuf_addf(&buf, ":%s", pa->type);
+
+	ret = strbuf_detach(&buf, NULL);
+	strbuf_release(&buf);
 
-	return tmp - buf;
-error:
-	pr_debug("Failed to synthesize perf probe argument: %d\n", ret);
 	return ret;
 }
 
 /* Compose only probe point (not argument) */
 static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
 {
-	char *buf, *tmp;
-	char offs[32] = "", line[32] = "", file[32] = "";
-	int ret, len;
-
-	buf = zalloc(MAX_CMDLEN);
-	if (buf == NULL) {
-		ret = -ENOMEM;
-		goto error;
-	}
-	if (pp->offset) {
-		ret = e_snprintf(offs, 32, "+%lu", pp->offset);
-		if (ret <= 0)
-			goto error;
-	}
-	if (pp->line) {
-		ret = e_snprintf(line, 32, ":%d", pp->line);
-		if (ret <= 0)
-			goto error;
+	struct strbuf buf;
+	char *tmp;
+	int len;
+
+	strbuf_init(&buf, 64);
+	if (pp->function) {
+		strbuf_addstr(&buf, pp->function);
+		if (pp->offset)
+			strbuf_addf(&buf, "+%lu", pp->offset);
+		else if (pp->line)
+			strbuf_addf(&buf, ":%d", pp->line);
+		else if (pp->retprobe)
+			strbuf_addstr(&buf, "%return");
 	}
 	if (pp->file) {
 		tmp = pp->file;
@@ -1633,25 +1616,14 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
 			tmp = strchr(pp->file + len - 30, '/');
 			tmp = tmp ? tmp + 1 : pp->file + len - 30;
 		}
-		ret = e_snprintf(file, 32, "@%s", tmp);
-		if (ret <= 0)
-			goto error;
+		strbuf_addf(&buf, "@%s", tmp);
+		if (!pp->function && pp->line)
+			strbuf_addf(&buf, ":%d", pp->line);
 	}
 
-	if (pp->function)
-		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
-				 offs, pp->retprobe ? "%return" : "", line,
-				 file);
-	else
-		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
-	if (ret <= 0)
-		goto error;
-
-	return buf;
-error:
-	pr_debug("Failed to synthesize perf probe point: %d\n", ret);
-	free(buf);
-	return NULL;
+	tmp = strbuf_detach(&buf, NULL);
+	strbuf_release(&buf);
+	return tmp;
 }
 
 #if 0
@@ -1680,45 +1652,30 @@ char *synthesize_perf_probe_command(struct perf_probe_event *pev)
 #endif
 
 static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
-					     char **buf, size_t *buflen,
-					     int depth)
+					    struct strbuf *buf, int depth)
 {
-	int ret;
 	if (ref->next) {
 		depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
-							 buflen, depth + 1);
+							 depth + 1);
 		if (depth < 0)
 			goto out;
 	}
-
-	ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
-	if (ret < 0)
-		depth = ret;
-	else {
-		*buf += ret;
-		*buflen -= ret;
-	}
+	strbuf_addf(buf, "%+ld(", ref->offset);
 out:
 	return depth;
-
 }
 
 static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
-				       char *buf, size_t buflen)
+				      struct strbuf *buf)
 {
 	struct probe_trace_arg_ref *ref = arg->ref;
-	int ret, depth = 0;
-	char *tmp = buf;
+	int depth = 0;
 
 	/* Argument name or separator */
 	if (arg->name)
-		ret = e_snprintf(buf, buflen, " %s=", arg->name);
+		strbuf_addf(buf, " %s=", arg->name);
 	else
-		ret = e_snprintf(buf, buflen, " ");
-	if (ret < 0)
-		return ret;
-	buf += ret;
-	buflen -= ret;
+		strbuf_addch(buf, ' ');
 
 	/* Special case: @XXX */
 	if (arg->value[0] == '@' && arg->ref)
@@ -1726,86 +1683,58 @@ static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
 
 	/* Dereferencing arguments */
 	if (ref) {
-		depth = __synthesize_probe_trace_arg_ref(ref, &buf,
-							  &buflen, 1);
+		depth = __synthesize_probe_trace_arg_ref(ref, buf, 1);
 		if (depth < 0)
 			return depth;
 	}
 
 	/* Print argument value */
 	if (arg->value[0] == '@' && arg->ref)
-		ret = e_snprintf(buf, buflen, "%s%+ld", arg->value,
-				 arg->ref->offset);
+		strbuf_addf(buf, "%s%+ld", arg->value, arg->ref->offset);
 	else
-		ret = e_snprintf(buf, buflen, "%s", arg->value);
-	if (ret < 0)
-		return ret;
-	buf += ret;
-	buflen -= ret;
+		strbuf_addstr(buf, arg->value);
 
 	/* Closing */
-	while (depth--) {
-		ret = e_snprintf(buf, buflen, ")");
-		if (ret < 0)
-			return ret;
-		buf += ret;
-		buflen -= ret;
-	}
+	while (depth--)
+		strbuf_addch(buf, ')');
 	/* Print argument type */
-	if (arg->type) {
-		ret = e_snprintf(buf, buflen, ":%s", arg->type);
-		if (ret <= 0)
-			return ret;
-		buf += ret;
-	}
+	if (arg->type)
+		strbuf_addf(buf, ":%s", arg->type);
 
-	return buf - tmp;
+	return 0;
 }
 
 char *synthesize_probe_trace_command(struct probe_trace_event *tev)
 {
 	struct probe_trace_point *tp = &tev->point;
-	char *buf;
-	int i, len, ret;
-
-	buf = zalloc(MAX_CMDLEN);
-	if (buf == NULL)
-		return NULL;
-
-	len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
-			 tev->group, tev->event);
-	if (len <= 0)
-		goto error;
+	struct strbuf buf;
+	char *ret = NULL;
+	int i;
 
 	/* Uprobes must have tp->address and tp->module */
 	if (tev->uprobes && (!tp->address || !tp->module))
-		goto error;
+		return NULL;
+
+	strbuf_init(&buf, 32);
+	strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
+		    tev->group, tev->event);
 
 	/* Use the tp->address for uprobes */
 	if (tev->uprobes)
-		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
-				 tp->module, tp->address);
+		strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address);
 	else
-		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
-				 tp->module ?: "", tp->module ? ":" : "",
-				 tp->symbol, tp->offset);
-
-	if (ret <= 0)
-		goto error;
-	len += ret;
+		strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "",
+			    tp->module ? ":" : "", tp->symbol, tp->offset);
 
 	for (i = 0; i < tev->nargs; i++) {
-		ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
-						  MAX_CMDLEN - len);
-		if (ret <= 0)
+		if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0)
 			goto error;
-		len += ret;
 	}
 
-	return buf;
+	ret = strbuf_detach(&buf, NULL);
 error:
-	free(buf);
-	return NULL;
+	strbuf_release(&buf);
+	return ret;
 }
 
 static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
@@ -1883,7 +1812,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
 static int convert_to_perf_probe_event(struct probe_trace_event *tev,
 			       struct perf_probe_event *pev, bool is_kprobe)
 {
-	char buf[64] = "";
+	struct strbuf buf = STRBUF_INIT;
 	int i, ret;
 
 	/* Convert event/group name */
@@ -1906,9 +1835,10 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
 		if (tev->args[i].name)
 			pev->args[i].name = strdup(tev->args[i].name);
 		else {
-			ret = synthesize_probe_trace_arg(&tev->args[i],
-							  buf, 64);
-			pev->args[i].name = strdup(buf);
+			strbuf_init(&buf, 32);
+			ret = synthesize_probe_trace_arg(&tev->args[i], &buf);
+			pev->args[i].name = strbuf_detach(&buf, NULL);
+			strbuf_release(&buf);
 		}
 		if (pev->args[i].name == NULL && ret >= 0)
 			ret = -ENOMEM;
@@ -2086,37 +2016,37 @@ static int perf_probe_event__sprintf(const char *group, const char *event,
 				     const char *module,
 				     struct strbuf *result)
 {
-	int i, ret;
-	char buf[128];
-	char *place;
+	int i;
+	char *buf;
 
-	/* Synthesize only event probe point */
-	place = synthesize_perf_probe_point(&pev->point);
-	if (!place)
-		return -EINVAL;
+	if (asprintf(&buf, "%s:%s", group, event) < 0)
+		return -errno;
+	strbuf_addf(result, "  %-20s (on ", buf);
+	free(buf);
 
-	ret = e_snprintf(buf, 128, "%s:%s", group, event);
-	if (ret < 0)
-		goto out;
+	/* Synthesize only event probe point */
+	buf = synthesize_perf_probe_point(&pev->point);
+	if (!buf)
+		return -ENOMEM;
+	strbuf_addstr(result, buf);
+	free(buf);
 
-	strbuf_addf(result, "  %-20s (on %s", buf, place);
 	if (module)
 		strbuf_addf(result, " in %s", module);
 
 	if (pev->nargs > 0) {
 		strbuf_addstr(result, " with");
 		for (i = 0; i < pev->nargs; i++) {
-			ret = synthesize_perf_probe_arg(&pev->args[i],
-							buf, 128);
-			if (ret < 0)
-				goto out;
+			buf = synthesize_perf_probe_arg(&pev->args[i]);
+			if (!buf)
+				return -ENOMEM;
 			strbuf_addf(result, " %s", buf);
+			free(buf);
 		}
 	}
 	strbuf_addch(result, ')');
-out:
-	free(place);
-	return ret;
+
+	return 0;
 }
 
 /* Show an event */
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 20f555d..4cff6be 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -115,8 +115,7 @@ extern int parse_probe_trace_command(const char *cmd,
 /* Events to command string */
 extern char *synthesize_perf_probe_command(struct perf_probe_event *pev);
 extern char *synthesize_probe_trace_command(struct probe_trace_event *tev);
-extern int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf,
-				     size_t len);
+extern char *synthesize_perf_probe_arg(struct perf_probe_arg *pa);
 
 /* Check the perf_probe_event needs debuginfo */
 extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 2da65a7..f7beb3c 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -550,7 +550,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
 static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
 {
 	Dwarf_Die vr_die;
-	char buf[32], *ptr;
+	char *buf, *ptr;
 	int ret = 0;
 
 	if (!is_c_varname(pf->pvar->var)) {
@@ -575,13 +575,13 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
 	if (pf->pvar->name)
 		pf->tvar->name = strdup(pf->pvar->name);
 	else {
-		ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
-		if (ret < 0)
-			return ret;
+		buf = synthesize_perf_probe_arg(pf->pvar);
+		if (!buf)
+			return -ENOMEM;
 		ptr = strchr(buf, ':');	/* Change type separator to _ */
 		if (ptr)
 			*ptr = '_';
-		pf->tvar->name = strdup(buf);
+		pf->tvar->name = buf;
 	}
 	if (pf->tvar->name == NULL)
 		return -ENOMEM;


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1186542 — Re: [RFC PATCH perf/core v2 03/16] perf probe: Use strbuf for making strings in probe-event.c

FromNamhyung Kim <namhyung@kernel.org>
Date2015-07-17 10:00 +0200
SubjectRe: [RFC PATCH perf/core v2 03/16] perf probe: Use strbuf for making strings in probe-event.c
Message-ID<pN8IP-7Cv-9@gated-at.bofh.it>
In reply to#1184468
Hi Masami,

On Wed, Jul 15, 2015 at 06:14:14PM +0900, Masami Hiramatsu wrote:
> Replace many fixed-length char array with strbuf to
> stringify perf_probe_event and probe_trace_event etc. in
> util/probe-event.c.
> 
> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> ---

[SNIP]

> +	ret = strbuf_detach(&buf, NULL);
> +	strbuf_release(&buf);

It seems that strbuf_release() is meaningless after strbuf_detach().


>  
> -	return tmp - buf;
> -error:
> -	pr_debug("Failed to synthesize perf probe argument: %d\n", ret);
>  	return ret;
>  }
>  
>  /* Compose only probe point (not argument) */
>  static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
>  {
> -	char *buf, *tmp;
> -	char offs[32] = "", line[32] = "", file[32] = "";
> -	int ret, len;
> -
> -	buf = zalloc(MAX_CMDLEN);
> -	if (buf == NULL) {
> -		ret = -ENOMEM;
> -		goto error;
> -	}
> -	if (pp->offset) {
> -		ret = e_snprintf(offs, 32, "+%lu", pp->offset);
> -		if (ret <= 0)
> -			goto error;
> -	}
> -	if (pp->line) {
> -		ret = e_snprintf(line, 32, ":%d", pp->line);
> -		if (ret <= 0)
> -			goto error;
> +	struct strbuf buf;
> +	char *tmp;
> +	int len;
> +
> +	strbuf_init(&buf, 64);
> +	if (pp->function) {
> +		strbuf_addstr(&buf, pp->function);
> +		if (pp->offset)
> +			strbuf_addf(&buf, "+%lu", pp->offset);
> +		else if (pp->line)
> +			strbuf_addf(&buf, ":%d", pp->line);
> +		else if (pp->retprobe)
> +			strbuf_addstr(&buf, "%return");
>  	}
>  	if (pp->file) {
>  		tmp = pp->file;
> @@ -1633,25 +1616,14 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
>  			tmp = strchr(pp->file + len - 30, '/');
>  			tmp = tmp ? tmp + 1 : pp->file + len - 30;
>  		}
> -		ret = e_snprintf(file, 32, "@%s", tmp);
> -		if (ret <= 0)
> -			goto error;
> +		strbuf_addf(&buf, "@%s", tmp);
> +		if (!pp->function && pp->line)
> +			strbuf_addf(&buf, ":%d", pp->line);
>  	}
>  
> -	if (pp->function)
> -		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
> -				 offs, pp->retprobe ? "%return" : "", line,
> -				 file);
> -	else
> -		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
> -	if (ret <= 0)
> -		goto error;
> -
> -	return buf;
> -error:
> -	pr_debug("Failed to synthesize perf probe point: %d\n", ret);
> -	free(buf);
> -	return NULL;
> +	tmp = strbuf_detach(&buf, NULL);
> +	strbuf_release(&buf);

Ditto.


> +	return tmp;
>  }


[SNIP]
>  char *synthesize_probe_trace_command(struct probe_trace_event *tev)
>  {
>  	struct probe_trace_point *tp = &tev->point;
> -	char *buf;
> -	int i, len, ret;
> -
> -	buf = zalloc(MAX_CMDLEN);
> -	if (buf == NULL)
> -		return NULL;
> -
> -	len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
> -			 tev->group, tev->event);
> -	if (len <= 0)
> -		goto error;
> +	struct strbuf buf;
> +	char *ret = NULL;
> +	int i;
>  
>  	/* Uprobes must have tp->address and tp->module */
>  	if (tev->uprobes && (!tp->address || !tp->module))
> -		goto error;
> +		return NULL;
> +
> +	strbuf_init(&buf, 32);
> +	strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
> +		    tev->group, tev->event);
>  
>  	/* Use the tp->address for uprobes */
>  	if (tev->uprobes)
> -		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
> -				 tp->module, tp->address);
> +		strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address);
>  	else
> -		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
> -				 tp->module ?: "", tp->module ? ":" : "",
> -				 tp->symbol, tp->offset);
> -
> -	if (ret <= 0)
> -		goto error;
> -	len += ret;
> +		strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "",
> +			    tp->module ? ":" : "", tp->symbol, tp->offset);
>  
>  	for (i = 0; i < tev->nargs; i++) {
> -		ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
> -						  MAX_CMDLEN - len);
> -		if (ret <= 0)
> +		if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0)
>  			goto error;
> -		len += ret;
>  	}
>  
> -	return buf;
> +	ret = strbuf_detach(&buf, NULL);
>  error:
> -	free(buf);
> -	return NULL;
> +	strbuf_release(&buf);

This is necessary for the error path.


> +	return ret;
>  }
>  
>  static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
> @@ -1883,7 +1812,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
>  static int convert_to_perf_probe_event(struct probe_trace_event *tev,
>  			       struct perf_probe_event *pev, bool is_kprobe)
>  {
> -	char buf[64] = "";
> +	struct strbuf buf = STRBUF_INIT;
>  	int i, ret;
>  
>  	/* Convert event/group name */
> @@ -1906,9 +1835,10 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
>  		if (tev->args[i].name)
>  			pev->args[i].name = strdup(tev->args[i].name);
>  		else {
> -			ret = synthesize_probe_trace_arg(&tev->args[i],
> -							  buf, 64);
> -			pev->args[i].name = strdup(buf);
> +			strbuf_init(&buf, 32);
> +			ret = synthesize_probe_trace_arg(&tev->args[i], &buf);
> +			pev->args[i].name = strbuf_detach(&buf, NULL);
> +			strbuf_release(&buf);

Ditto.

Thanks,
Namhyung

>  		}
>  		if (pev->args[i].name == NULL && ret >= 0)
>  			ret = -ENOMEM;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1186672 — Re: Re: [RFC PATCH perf/core v2 03/16] perf probe: Use strbuf for making strings in probe-event.c

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-17 12:20 +0200
SubjectRe: Re: [RFC PATCH perf/core v2 03/16] perf probe: Use strbuf for making strings in probe-event.c
Message-ID<pNaUh-2ta-9@gated-at.bofh.it>
In reply to#1186542
On 2015/07/17 16:42, Namhyung Kim wrote:
> Hi Masami,
> 
> On Wed, Jul 15, 2015 at 06:14:14PM +0900, Masami Hiramatsu wrote:
>> Replace many fixed-length char array with strbuf to
>> stringify perf_probe_event and probe_trace_event etc. in
>> util/probe-event.c.
>>
>> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
>> ---
> 
> [SNIP]
> 
>> +	ret = strbuf_detach(&buf, NULL);
>> +	strbuf_release(&buf);
> 
> It seems that strbuf_release() is meaningless after strbuf_detach().

Ah, right! I'll remove those redundant strbuf_release.

Thanks!

> 
> 
>>  
>> -	return tmp - buf;
>> -error:
>> -	pr_debug("Failed to synthesize perf probe argument: %d\n", ret);
>>  	return ret;
>>  }
>>  
>>  /* Compose only probe point (not argument) */
>>  static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
>>  {
>> -	char *buf, *tmp;
>> -	char offs[32] = "", line[32] = "", file[32] = "";
>> -	int ret, len;
>> -
>> -	buf = zalloc(MAX_CMDLEN);
>> -	if (buf == NULL) {
>> -		ret = -ENOMEM;
>> -		goto error;
>> -	}
>> -	if (pp->offset) {
>> -		ret = e_snprintf(offs, 32, "+%lu", pp->offset);
>> -		if (ret <= 0)
>> -			goto error;
>> -	}
>> -	if (pp->line) {
>> -		ret = e_snprintf(line, 32, ":%d", pp->line);
>> -		if (ret <= 0)
>> -			goto error;
>> +	struct strbuf buf;
>> +	char *tmp;
>> +	int len;
>> +
>> +	strbuf_init(&buf, 64);
>> +	if (pp->function) {
>> +		strbuf_addstr(&buf, pp->function);
>> +		if (pp->offset)
>> +			strbuf_addf(&buf, "+%lu", pp->offset);
>> +		else if (pp->line)
>> +			strbuf_addf(&buf, ":%d", pp->line);
>> +		else if (pp->retprobe)
>> +			strbuf_addstr(&buf, "%return");
>>  	}
>>  	if (pp->file) {
>>  		tmp = pp->file;
>> @@ -1633,25 +1616,14 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
>>  			tmp = strchr(pp->file + len - 30, '/');
>>  			tmp = tmp ? tmp + 1 : pp->file + len - 30;
>>  		}
>> -		ret = e_snprintf(file, 32, "@%s", tmp);
>> -		if (ret <= 0)
>> -			goto error;
>> +		strbuf_addf(&buf, "@%s", tmp);
>> +		if (!pp->function && pp->line)
>> +			strbuf_addf(&buf, ":%d", pp->line);
>>  	}
>>  
>> -	if (pp->function)
>> -		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
>> -				 offs, pp->retprobe ? "%return" : "", line,
>> -				 file);
>> -	else
>> -		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
>> -	if (ret <= 0)
>> -		goto error;
>> -
>> -	return buf;
>> -error:
>> -	pr_debug("Failed to synthesize perf probe point: %d\n", ret);
>> -	free(buf);
>> -	return NULL;
>> +	tmp = strbuf_detach(&buf, NULL);
>> +	strbuf_release(&buf);
> 
> Ditto.
> 
> 
>> +	return tmp;
>>  }
> 
> 
> [SNIP]
>>  char *synthesize_probe_trace_command(struct probe_trace_event *tev)
>>  {
>>  	struct probe_trace_point *tp = &tev->point;
>> -	char *buf;
>> -	int i, len, ret;
>> -
>> -	buf = zalloc(MAX_CMDLEN);
>> -	if (buf == NULL)
>> -		return NULL;
>> -
>> -	len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
>> -			 tev->group, tev->event);
>> -	if (len <= 0)
>> -		goto error;
>> +	struct strbuf buf;
>> +	char *ret = NULL;
>> +	int i;
>>  
>>  	/* Uprobes must have tp->address and tp->module */
>>  	if (tev->uprobes && (!tp->address || !tp->module))
>> -		goto error;
>> +		return NULL;
>> +
>> +	strbuf_init(&buf, 32);
>> +	strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
>> +		    tev->group, tev->event);
>>  
>>  	/* Use the tp->address for uprobes */
>>  	if (tev->uprobes)
>> -		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
>> -				 tp->module, tp->address);
>> +		strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address);
>>  	else
>> -		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
>> -				 tp->module ?: "", tp->module ? ":" : "",
>> -				 tp->symbol, tp->offset);
>> -
>> -	if (ret <= 0)
>> -		goto error;
>> -	len += ret;
>> +		strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "",
>> +			    tp->module ? ":" : "", tp->symbol, tp->offset);
>>  
>>  	for (i = 0; i < tev->nargs; i++) {
>> -		ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
>> -						  MAX_CMDLEN - len);
>> -		if (ret <= 0)
>> +		if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0)
>>  			goto error;
>> -		len += ret;
>>  	}
>>  
>> -	return buf;
>> +	ret = strbuf_detach(&buf, NULL);
>>  error:
>> -	free(buf);
>> -	return NULL;
>> +	strbuf_release(&buf);
> 
> This is necessary for the error path.
> 
> 
>> +	return ret;
>>  }
>>  
>>  static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
>> @@ -1883,7 +1812,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
>>  static int convert_to_perf_probe_event(struct probe_trace_event *tev,
>>  			       struct perf_probe_event *pev, bool is_kprobe)
>>  {
>> -	char buf[64] = "";
>> +	struct strbuf buf = STRBUF_INIT;
>>  	int i, ret;
>>  
>>  	/* Convert event/group name */
>> @@ -1906,9 +1835,10 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
>>  		if (tev->args[i].name)
>>  			pev->args[i].name = strdup(tev->args[i].name);
>>  		else {
>> -			ret = synthesize_probe_trace_arg(&tev->args[i],
>> -							  buf, 64);
>> -			pev->args[i].name = strdup(buf);
>> +			strbuf_init(&buf, 32);
>> +			ret = synthesize_probe_trace_arg(&tev->args[i], &buf);
>> +			pev->args[i].name = strbuf_detach(&buf, NULL);
>> +			strbuf_release(&buf);
> 
> Ditto.
> 
> Thanks,
> Namhyung
> 
>>  		}
>>  		if (pev->args[i].name == NULL && ret >= 0)
>>  			ret = -ENOMEM;
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 


-- 
Masami HIRAMATSU
Linux Technology Research Center, System Productivity Research Dept.
Center for Technology Innovation - Systems Engineering
Hitachi, Ltd., Research & Development Group
E-mail: masami.hiramatsu.pt@hitachi.com
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1184469 — [RFC PATCH perf/core v2 07/16] perf: Add lsdir to read a directory

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-15 11:20 +0200
Subject[RFC PATCH perf/core v2 07/16] perf: Add lsdir to read a directory
Message-ID<pMr1b-36Z-81@gated-at.bofh.it>
In reply to#1184459
As a utility function, add lsdir() which reads given
directory and store entry name into a strlist.
lsdir accepts a filter function so that user can
filter out unneeded entries.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
---
 tools/perf/util/util.c |   34 ++++++++++++++++++++++++++++++++++
 tools/perf/util/util.h |    4 ++++
 2 files changed, 38 insertions(+)

diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index edc2d63..69694dd 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -115,6 +115,40 @@ int rm_rf(char *path)
 	return rmdir(path);
 }
 
+/* A filter which removes dot files */
+bool lsdir_no_dot_filter(const char *dirname __maybe_unused, struct dirent *d)
+{
+	return d->d_name[0] != '.';
+}
+
+/* lsdir reads a directory and store it in strlist */
+struct strlist *lsdir(const char *dirname,
+		      bool (*filter)(const char *, struct dirent *))
+{
+	struct strlist *list = NULL;
+	DIR *dir;
+	struct dirent *d;
+
+	dir = opendir(dirname);
+	if (!dir)
+		return NULL;
+
+	list = strlist__new(true, NULL);
+	if (!list) {
+		errno = -ENOMEM;
+		goto out;
+	}
+
+	while ((d = readdir(dir)) != NULL) {
+		if (!filter || filter(dirname, d))
+			strlist__add(list, d->d_name);
+	}
+
+out:
+	closedir(dir);
+	return list;
+}
+
 static int slow_copyfile(const char *from, const char *to)
 {
 	int err = -1;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 20d625a..fb5401b 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -79,6 +79,7 @@
 #include <termios.h>
 #include <linux/bitops.h>
 #include <termios.h>
+#include "strlist.h"
 
 extern const char *graph_line;
 extern const char *graph_dotted_line;
@@ -250,6 +251,9 @@ static inline int sane_case(int x, int high)
 
 int mkdir_p(char *path, mode_t mode);
 int rm_rf(char *path);
+struct strlist *lsdir(const char *dirname,
+		      bool (*filter)(const char *, struct dirent *));
+bool lsdir_no_dot_filter(const char *dirname __maybe_unused, struct dirent *d);
 int copyfile(const char *from, const char *to);
 int copyfile_mode(const char *from, const char *to, mode_t mode);
 int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1184470 — [RFC PATCH perf/core v2 13/16] perf/sdt: ELF support for SDT

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-15 11:20 +0200
Subject[RFC PATCH perf/core v2 13/16] perf/sdt: ELF support for SDT
Message-ID<pMr1b-36Z-83@gated-at.bofh.it>
In reply to#1184459
From: Hemant Kumar <hemant@linux.vnet.ibm.com>

This patch serves the initial support to identify and list SDT events in binaries.
When programs containing SDT markers are compiled, gcc with the help of assembler
directives identifies them and places them in the section ".note.stapsdt". To find
these markers from the binaries, one needs to traverse through this section and
parse the relevant details like the name, type and location of the marker. Also,
the original location could be skewed due to the effect of prelinking. If that is
the case, the locations need to be adjusted.

The functions in this patch open a given ELF, find out the SDT section, parse the
relevant details, adjust the location (if necessary) and populate them in a list.

A typical note entry in ".note.stapsdt" section is as follows :


                                 |--nhdr.n_namesz--|
                ------------------------------------
                |      nhdr      |     "stapsdt"   |
        -----   |----------------------------------|
         |      |  <location>       <base_address> |
         |      |  <semaphore>                     |
nhdr.n_descsize |  "provider_name"   "note_name"   |
         |      |   <args>                         |
        -----   |----------------------------------|
                |      nhdr      |     "stapsdt"   |
                |...

The above shows an excerpt from the section ".note.stapsdt".
'nhdr' is a structure which has the note name size (n_namesz), note
description size (n_desc_sz) and note type (n_type). So, in order to
parse the note note info, we need nhdr to tell us where to start from.
As can be seen from <sys/sdt.h>, the name of the SDT notes given is "stapsdt".
But this is not the identifier of the note.
After that, we go to description of the note to find out its location, the
address of the ".stapsdt.base" section and the semaphore address.
Then, we find the provider name and the SDT marker name and then follow the
arguments.

Signed-off-by: Hemant Kumar <hemant@linux.vnet.ibm.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/symbol-elf.c |  252 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/symbol.h     |   22 ++++
 2 files changed, 274 insertions(+)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 65f7e38..6bffa6a 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1775,6 +1775,258 @@ void kcore_extract__delete(struct kcore_extract *kce)
 	unlink(kce->extract_filename);
 }
 
+/**
+ * populate_sdt_note : Parse raw data and identify SDT note
+ * @elf: elf of the opened file
+ * @data: raw data of a section with description offset applied
+ * @len: note description size
+ * @type: type of the note
+ * @sdt_notes: List to add the SDT note
+ *
+ * Responsible for parsing the @data in section .note.stapsdt in @elf and
+ * if its an SDT note, it appends to @sdt_notes list.
+ */
+static int populate_sdt_note(Elf **elf, const char *data, size_t len,
+			     struct list_head *sdt_notes)
+{
+	const char *provider, *name;
+	struct sdt_note *tmp = NULL;
+	GElf_Ehdr ehdr;
+	GElf_Addr base_off = 0;
+	GElf_Shdr shdr;
+	int ret = -EINVAL;
+
+	union {
+		Elf64_Addr a64[NR_ADDR];
+		Elf32_Addr a32[NR_ADDR];
+	} buf;
+
+	Elf_Data dst = {
+		.d_buf = &buf, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+		.d_size = gelf_fsize((*elf), ELF_T_ADDR, NR_ADDR, EV_CURRENT),
+		.d_off = 0, .d_align = 0
+	};
+	Elf_Data src = {
+		.d_buf = (void *) data, .d_type = ELF_T_ADDR,
+		.d_version = EV_CURRENT, .d_size = dst.d_size, .d_off = 0,
+		.d_align = 0
+	};
+
+	tmp = (struct sdt_note *)calloc(1, sizeof(struct sdt_note));
+	if (!tmp) {
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	INIT_LIST_HEAD(&tmp->note_list);
+
+	if (len < dst.d_size + 3)
+		goto out_free_note;
+
+	/* Translation from file representation to memory representation */
+	if (gelf_xlatetom(*elf, &dst, &src,
+			  elf_getident(*elf, NULL)[EI_DATA]) == NULL) {
+		pr_err("gelf_xlatetom : %s\n", elf_errmsg(-1));
+		goto out_free_note;
+	}
+
+	/* Populate the fields of sdt_note */
+	provider = data + dst.d_size;
+
+	name = (const char *)memchr(provider, '\0', data + len - provider);
+	if (name++ == NULL)
+		goto out_free_note;
+
+	tmp->provider = strdup(provider);
+	if (!tmp->provider) {
+		ret = -ENOMEM;
+		goto out_free_note;
+	}
+	tmp->name = strdup(name);
+	if (!tmp->name) {
+		ret = -ENOMEM;
+		goto out_free_prov;
+	}
+
+	if (gelf_getclass(*elf) == ELFCLASS32) {
+		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
+		tmp->bit32 = true;
+	} else {
+		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf64_Addr));
+		tmp->bit32 = false;
+	}
+
+	if (!gelf_getehdr(*elf, &ehdr)) {
+		pr_debug("%s : cannot get elf header.\n", __func__);
+		ret = -EBADF;
+		goto out_free_name;
+	}
+
+	/* Adjust the prelink effect :
+	 * Find out the .stapsdt.base section.
+	 * This scn will help us to handle prelinking (if present).
+	 * Compare the retrieved file offset of the base section with the
+	 * base address in the description of the SDT note. If its different,
+	 * then accordingly, adjust the note location.
+	 */
+	if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL)) {
+		base_off = shdr.sh_offset;
+		if (base_off) {
+			if (tmp->bit32)
+				tmp->addr.a32[0] = tmp->addr.a32[0] + base_off -
+					tmp->addr.a32[1];
+			else
+				tmp->addr.a64[0] = tmp->addr.a64[0] + base_off -
+					tmp->addr.a64[1];
+		}
+	}
+
+	list_add_tail(&tmp->note_list, sdt_notes);
+	return 0;
+
+out_free_name:
+	free(tmp->name);
+out_free_prov:
+	free(tmp->provider);
+out_free_note:
+	free(tmp);
+out_err:
+	return ret;
+}
+
+/**
+ * construct_sdt_notes_list : constructs a list of SDT notes
+ * @elf : elf to look into
+ * @sdt_notes : empty list_head
+ *
+ * Scans the sections in 'elf' for the section
+ * .note.stapsdt. It, then calls populate_sdt_note to find
+ * out the SDT events and populates the 'sdt_notes'.
+ */
+static int construct_sdt_notes_list(Elf *elf, struct list_head *sdt_notes)
+{
+	GElf_Ehdr ehdr;
+	Elf_Scn *scn = NULL;
+	Elf_Data *data;
+	GElf_Shdr shdr;
+	size_t shstrndx, next;
+	GElf_Nhdr nhdr;
+	size_t name_off, desc_off, offset;
+	int ret = 0;
+
+	if (gelf_getehdr(elf, &ehdr) == NULL) {
+		ret = -EBADF;
+		goto out_ret;
+	}
+	if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
+		ret = -EBADF;
+		goto out_ret;
+	}
+
+	/* Look for the required section */
+	scn = elf_section_by_name(elf, &ehdr, &shdr, SDT_NOTE_SCN, NULL);
+	if (!scn) {
+		ret = -ENOENT;
+		goto out_ret;
+	}
+
+	if ((shdr.sh_type != SHT_NOTE) || (shdr.sh_flags & SHF_ALLOC)) {
+		ret = -ENOENT;
+		goto out_ret;
+	}
+
+	data = elf_getdata(scn, NULL);
+
+	/* Get the SDT notes */
+	for (offset = 0; (next = gelf_getnote(data, offset, &nhdr, &name_off,
+					      &desc_off)) > 0; offset = next) {
+		if (nhdr.n_namesz == sizeof(SDT_NOTE_NAME) &&
+		    !memcmp(data->d_buf + name_off, SDT_NOTE_NAME,
+			    sizeof(SDT_NOTE_NAME))) {
+			/* Check the type of the note */
+			if (nhdr.n_type != SDT_NOTE_TYPE)
+				goto out_ret;
+
+			ret = populate_sdt_note(&elf, ((data->d_buf) + desc_off),
+						nhdr.n_descsz, sdt_notes);
+			if (ret < 0)
+				goto out_ret;
+		}
+	}
+	if (list_empty(sdt_notes))
+		ret = -ENOENT;
+
+out_ret:
+	return ret;
+}
+
+/**
+ * get_sdt_note_list : Wrapper to construct a list of sdt notes
+ * @head : empty list_head
+ * @target : file to find SDT notes from
+ *
+ * This opens the file, initializes
+ * the ELF and then calls construct_sdt_notes_list.
+ */
+int get_sdt_note_list(struct list_head *head, const char *target)
+{
+	Elf *elf;
+	int fd, ret;
+
+	fd = open(target, O_RDONLY);
+	if (fd < 0)
+		return -EBADF;
+
+	elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+	if (!elf) {
+		ret = -EBADF;
+		goto out_close;
+	}
+	ret = construct_sdt_notes_list(elf, head);
+	elf_end(elf);
+out_close:
+	close(fd);
+	return ret;
+}
+
+/**
+ * cleanup_sdt_note_list : free the sdt notes' list
+ * @sdt_notes: sdt notes' list
+ *
+ * Free up the SDT notes in @sdt_notes.
+ * Returns the number of SDT notes free'd.
+ */
+int cleanup_sdt_note_list(struct list_head *sdt_notes)
+{
+	struct sdt_note *tmp, *pos;
+	int nr_free = 0;
+
+	list_for_each_entry_safe(pos, tmp, sdt_notes, note_list) {
+		list_del(&pos->note_list);
+		free(pos->name);
+		free(pos->provider);
+		free(pos);
+		nr_free++;
+	}
+	return nr_free;
+}
+
+/**
+ * sdt_notes__get_count: Counts the number of sdt events
+ * @start: list_head to sdt_notes list
+ *
+ * Returns the number of SDT notes in a list
+ */
+int sdt_notes__get_count(struct list_head *start)
+{
+	struct sdt_note *sdt_ptr;
+	int count = 0;
+
+	list_for_each_entry(sdt_ptr, start, note_list)
+		count++;
+	return count;
+}
+
 void symbol__elf_init(void)
 {
 	elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index bef47ead..c38af26 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -311,4 +311,26 @@ void arch__elf_sym_adjust(GElf_Sym *sym);
 
 int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
 
+/* structure containing an SDT note's info */
+struct sdt_note {
+	char *name;			/* name of the note*/
+	char *provider;			/* provider name */
+	bool bit32;			/* whether the location is 32 bits? */
+	union {				/* location, base and semaphore addrs */
+		Elf64_Addr a64[3];
+		Elf32_Addr a32[3];
+	} addr;
+	struct list_head note_list;	/* SDT notes' list */
+};
+
+int get_sdt_note_list(struct list_head *head, const char *target);
+int cleanup_sdt_note_list(struct list_head *sdt_notes);
+int sdt_notes__get_count(struct list_head *start);
+
+#define SDT_BASE_SCN ".stapsdt.base"
+#define SDT_NOTE_SCN  ".note.stapsdt"
+#define SDT_NOTE_TYPE 3
+#define SDT_NOTE_NAME "stapsdt"
+#define NR_ADDR 3
+
 #endif /* __PERF_SYMBOL */


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1184486 — [RFC PATCH perf/core v2 16/16] perf probe: Accept %sdt and %cached event name

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-15 11:30 +0200
Subject[RFC PATCH perf/core v2 16/16] perf probe: Accept %sdt and %cached event name
Message-ID<pMraP-3iJ-29@gated-at.bofh.it>
In reply to#1184459
To improbe usability, support %[PROVIDER:]SDTEVENT format to
add new probes on SDT and cached events.

e.g.
  ----
  # perf probe -x /lib/libc-2.17.so  %lll_lock_wait_private
  Added new event:
    libc:lll_lock_wait_private (on %lll_lock_wait_private in
  /usr/lib/libc-2.17.so)

  You can now use it in all perf tools, such as:

          perf record -e libc:lll_lock_wait_private -aR sleep 1

  # perf probe -l | more
    libc:lll_lock_wait_private (on __lll_lock_wait_private+21
   in /usr/lib/libc-2.17.so)
  ----

Note that this is not only for SDT events, but also normal
events with event-name.

e.g. define "myevent" on cache (-n doesn't add the real probe)
  ----
  # perf probe -x ./perf --cache -n --add 'myevent=dso__load $params'
  ----
  Reuse the "myevent" from cache as below.
  ----
  # perf probe -x ./perf %myevent
  ----

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
---
 tools/perf/Documentation/perf-probe.txt |    3 +
 tools/perf/util/probe-event.c           |   78 ++++++++++++++++++++++---------
 tools/perf/util/probe-event.h           |    1 
 tools/perf/util/probe-file.c            |    9 ++++
 4 files changed, 69 insertions(+), 22 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 8d09173..1d38221 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -151,11 +151,14 @@ Probe points are defined by following syntax.
     3) Define event based on source file with lazy pattern
      [EVENT=]SRC;PTN [ARG ...]
 
+    4) Pre-defined SDT events
+     %[PROVIDER:]SDTEVENT
 
 'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'.
 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition.  In addition, '@SRC' specifies a source file which has that function.
 It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern.
 'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT).
+'SDTEVENT' and 'PROVIDER' is the pre-defined event name which is defined by user SDT (Statically Defined Tracing) or the pre-cached probes with event name.
 
 PROBE ARGUMENT
 --------------
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index c19a380..0aad70d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1132,6 +1132,34 @@ err:
 	return err;
 }
 
+static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
+{
+	char *ptr;
+
+	ptr = strchr(*arg, ':');
+	if (ptr) {
+		*ptr = '\0';
+		if (!is_c_func_name(*arg))
+			goto ng_name;
+		pev->group = strdup(*arg);
+		if (!pev->group)
+			return -ENOMEM;
+		*arg = ptr + 1;
+	} else
+		pev->group = NULL;
+	if (!is_c_func_name(*arg)) {
+ng_name:
+		semantic_error("%s is bad for event name -it must "
+			       "follow C symbol-naming rule.\n", *arg);
+		return -EINVAL;
+	}
+	pev->event = strdup(*arg);
+	if (pev->event == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
 /* Parse probepoint definition. */
 static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 {
@@ -1139,38 +1167,43 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 	char *ptr, *tmp;
 	char c, nc = 0;
 	bool file_spec = false;
+	int ret;
+
 	/*
 	 * <Syntax>
 	 * perf probe [GRP:][EVENT=]SRC[:LN|;PTN]
 	 * perf probe [GRP:][EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
+	 * perf probe %[GRP:]SDT_EVENT
 	 */
 	if (!arg)
 		return -EINVAL;
 
+	if (arg[0] == '%') {
+		pev->sdt = true;
+		arg++;
+	}
+
 	ptr = strpbrk(arg, ";=@+%");
-	if (ptr && *ptr == '=') {	/* Event name */
-		*ptr = '\0';
-		tmp = ptr + 1;
-		ptr = strchr(arg, ':');
+	if (pev->sdt) {
 		if (ptr) {
-			*ptr = '\0';
-			if (!is_c_func_name(arg))
-				goto not_fname;
-			pev->group = strdup(arg);
-			if (!pev->group)
-				return -ENOMEM;
-			arg = ptr + 1;
-		} else
-			pev->group = NULL;
-		if (!is_c_func_name(arg)) {
-not_fname:
-			semantic_error("%s is bad for event name -it must "
-				       "follow C symbol-naming rule.\n", arg);
+			semantic_error("%s must contain only an SDT event name.\n", arg);
 			return -EINVAL;
 		}
-		pev->event = strdup(arg);
-		if (pev->event == NULL)
-			return -ENOMEM;
+		ret = parse_perf_probe_event_name(&arg, pev);
+		if (ret == 0) {
+			if (asprintf(&pev->point.function, "%%%s", pev->event) < 0)
+				ret = -errno;
+		}
+		return ret;
+	}
+
+	if (ptr && *ptr == '=') {	/* Event name */
+		*ptr = '\0';
+		tmp = ptr + 1;
+		ret = parse_perf_probe_event_name(&arg, pev);
+		if (ret < 0)
+			return ret;
+
 		arg = tmp;
 	}
 
@@ -2624,7 +2657,8 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 						  pev->point.function);
 	}
 	if (!entry) {
-		ret = 0;
+		/* SDT must be in the cache */
+		ret = pev->sdt ? -ENOENT : 0;
 		goto out;
 	}
 
@@ -2663,7 +2697,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 {
 	int ret;
 
-	if (pev->uprobes && !pev->group) {
+	if (pev->uprobes && !pev->sdt && !pev->group) {
 		/* Replace group name if not given */
 		ret = convert_exec_to_group(pev->target, &pev->group);
 		if (ret != 0) {
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 9aceba3..b290194 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -84,6 +84,7 @@ struct perf_probe_event {
 	char			*group;	/* Group name */
 	struct perf_probe_point	point;	/* Probe point */
 	int			nargs;	/* Number of arguments */
+	bool			sdt;	/* SDT/cached event flag */
 	bool			uprobes;	/* Uprobe event flag */
 	char			*target;	/* Target binary */
 	struct perf_probe_arg	*args;	/* Arguments */
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 059f311..8efad73 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -504,6 +504,15 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
 		return NULL;
 
 	list_for_each_entry(entry, &pcache->list, list) {
+		if (pev->sdt) {
+			if (entry->pev.event &&
+			    streql(entry->pev.event, pev->event) &&
+			    (!pev->group ||
+			     streql(entry->pev.group, pev->group)))
+				goto found;
+
+			continue;
+		}
 		/* Hit if same event name or same command-string */
 		if ((pev->event &&
 		     (streql(entry->pev.group, pev->group) &&


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1187560 — Re: [RFC PATCH perf/core v2 16/16] perf probe: Accept %sdt and %cached event name

FromNamhyung Kim <namhyung@kernel.org>
Date2015-07-19 13:00 +0200
SubjectRe: [RFC PATCH perf/core v2 16/16] perf probe: Accept %sdt and %cached event name
Message-ID<pNUu6-sz-9@gated-at.bofh.it>
In reply to#1184486
On Wed, Jul 15, 2015 at 06:15:44PM +0900, Masami Hiramatsu wrote:
> To improbe usability, support %[PROVIDER:]SDTEVENT format to
> add new probes on SDT and cached events.

Ah, you meant we can skip the provider if the event name is unique..


> 
> e.g.
>   ----
>   # perf probe -x /lib/libc-2.17.so  %lll_lock_wait_private

Maybe we can also skip the target path (-x) too in this case.

Thanks,
Namhyung


>   Added new event:
>     libc:lll_lock_wait_private (on %lll_lock_wait_private in
>   /usr/lib/libc-2.17.so)
> 
>   You can now use it in all perf tools, such as:
> 
>           perf record -e libc:lll_lock_wait_private -aR sleep 1
> 
>   # perf probe -l | more
>     libc:lll_lock_wait_private (on __lll_lock_wait_private+21
>    in /usr/lib/libc-2.17.so)
>   ----
> 
> Note that this is not only for SDT events, but also normal
> events with event-name.
> 
> e.g. define "myevent" on cache (-n doesn't add the real probe)
>   ----
>   # perf probe -x ./perf --cache -n --add 'myevent=dso__load $params'
>   ----
>   Reuse the "myevent" from cache as below.
>   ----
>   # perf probe -x ./perf %myevent
>   ----
> 
> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1184487 — [RFC PATCH perf/core v2 15/16] perf buildid-cache: Scan and import user SDT events to probe cache

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-15 11:30 +0200
Subject[RFC PATCH perf/core v2 15/16] perf buildid-cache: Scan and import user SDT events to probe cache
Message-ID<pMraP-3iJ-31@gated-at.bofh.it>
In reply to#1184459
perf buildid-cache --add <binary> scans given binary and add
the SDT events to probe cache. It is possible to use the cached
SDT events as other cached events (perf probe <provider>:<event>=<event>).

e.g.
  ----
  # perf buildid-cache --add /lib/libc-2.17.so
  # perf probe --cache --list | head -n 5
  /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
  libc:setjmp=setjmp
  libc:longjmp=longjmp
  libc:longjmp_target=longjmp_target
  libc:memory_heap_new=memory_heap_new
  # perf probe -x /usr/lib/libc-2.17.so \
    -a libc:memory_heap_new=memory_heap_new
  Added new event:
    libc:memory_heap_new (on memory_heap_new
   in /usr/lib/libc-2.17.so)

  You can now use it in all perf tools, such as:

          perf record -e libc:memory_heap_new -aR sleep 1

  # perf probe -l
    libc:memory_heap_new (on new_heap+183 in /usr/lib/libc-2.17.so)
  ----

Note that SDT event entries in probe-cache file is somewhat different
from normal cached events. Normal one starts with "#", but SDTs are
starting with "%".

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
---
 tools/perf/util/build-id.c   |   27 ++++++++++++++++--
 tools/perf/util/probe-file.c |   64 ++++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/probe-file.h |    2 +
 3 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 63123c1..1adb2c0 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -17,6 +17,7 @@
 #include "tool.h"
 #include "header.h"
 #include "vdso.h"
+#include "probe-file.h"
 
 
 static bool no_buildid_cache;
@@ -432,6 +433,23 @@ int build_id_cache__list_build_ids(const char *pathname,
 	return ret;
 }
 
+#ifdef CONFIG_LIBELF
+static void build_id_cache__add_sdt_cache(const char *sbuild_id,
+					  const char *realname)
+{
+	struct probe_cache *cache;
+
+	cache = probe_cache__new(sbuild_id);
+	if (!cache)
+		return;
+	if (probe_cache__scan_sdt(cache, realname) >= 0)
+		probe_cache__commit(cache);
+	probe_cache__delete(cache);
+}
+#else
+#define build_id_cache__add_sdt_cache(sbuild_id, realname) do { } while (0)
+#endif
+
 int build_id_cache__add_s(const char *sbuild_id, const char *name,
 			  bool is_kallsyms, bool is_vdso)
 {
@@ -470,20 +488,23 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 			goto out_free;
 	}
 
+	/* Make a symbolic link */
 	if (!build_id_cache__linkname(sbuild_id, linkname, size))
 		goto out_free;
+
 	tmp = strrchr(linkname, '/');
 	*tmp = '\0';
-
 	if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
 		goto out_free;
-
 	*tmp = '/';
 	tmp = dir_name + strlen(buildid_dir) - 5;
 	memcpy(tmp, "../..", 5);
-
 	if (symlink(tmp, linkname) == 0)
 		err = 0;
+
+	/* Update SDT cache */
+	build_id_cache__add_sdt_cache(sbuild_id, realname);
+
 out_free:
 	if (!is_kallsyms)
 		free(realname);
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index b3a69a3..059f311 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -403,9 +403,12 @@ static int probe_cache__load(struct probe_cache *pcache)
 		p = strchr(buf, '\n');
 		if (p)
 			*p = '\0';
-		if (buf[0] == '#') {	/* #perf_probe_event */
+		/* #perf_probe_event or %sdt_event */
+		if (buf[0] == '#' || buf[0] == '%') {
 			entry = probe_cache_entry__new(NULL);
 			entry->spev = strdup(buf + 1);
+			if (buf[0] == '%')
+				entry->sdt = true;
 			ret = parse_perf_probe_command(buf + 1, &entry->pev);
 			if (!entry->spev || ret < 0) {
 				probe_cache_entry__delete(entry);
@@ -577,14 +580,69 @@ out_err:
 	return ret;
 }
 
+static unsigned long long sdt_note__get_addr(struct sdt_note *note)
+{
+	return note->bit32 ? (unsigned long long)note->addr.a32[0]
+		 : (unsigned long long)note->addr.a64[0];
+}
+
+int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
+{
+	struct probe_cache_entry *entry = NULL;
+	struct list_head sdtlist;
+	struct sdt_note *note;
+	char *buf;
+	int ret;
+
+	INIT_LIST_HEAD(&sdtlist);
+	ret = get_sdt_note_list(&sdtlist, pathname);
+	if (ret < 0) {
+		pr_debug("Failed to get sdt note: %d\n", ret);
+		return ret;
+	}
+	list_for_each_entry(note, &sdtlist, note_list) {
+		entry = probe_cache__find_by_name(pcache, note->provider,
+						  note->name);
+		if (entry)	/* We've already scanned */
+			continue;
+
+		entry = probe_cache_entry__new(NULL);
+		if (!entry) {
+			ret = -ENOMEM;
+			break;
+		}
+		entry->sdt = true;
+		ret = asprintf(&entry->spev, "%s:%s=%s", note->provider,
+				note->name, note->name);
+		if (ret < 0)
+			break;
+		entry->pev.event = strdup(note->name);
+		entry->pev.group = strdup(note->provider);
+		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
+				note->provider, note->name,
+				pathname, sdt_note__get_addr(note));
+		if (ret < 0)
+			break;
+		strlist__add(entry->tevlist, buf);
+		free(buf);
+		list_add_tail(&entry->list, &pcache->list);
+		entry = NULL;
+	}
+	if (entry)
+		probe_cache_entry__delete(entry);
+	cleanup_sdt_note_list(&sdtlist);
+	return ret;
+}
+
 static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
 {
 	struct str_node *snode;
 	struct iovec iov[3];
+	const char *prefix = entry->sdt ? "%" : "#";
 	int ret;
 
-	pr_debug("Writing cache: #%s\n", entry->spev);
-	iov[0].iov_base = (void *)"#"; iov[0].iov_len = 1;
+	pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
+	iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
 	iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
 	iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
 	ret = writev(fd, iov, 3);
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 391fde0..9a9b0c5 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -18,6 +18,7 @@ int probe_file__del_events(int fd, struct strfilter *filter);
 /* Cache of probe definitions */
 struct probe_cache_entry {
 	struct list_head	list;
+	bool			sdt;
 	struct perf_probe_event pev;
 	char			*spev;
 	struct strlist		*tevlist;
@@ -32,6 +33,7 @@ struct probe_cache *probe_cache__new(const char *target);
 int probe_cache__add_entry(struct probe_cache *pcache,
 			   struct perf_probe_event *pev,
 			   struct probe_trace_event *tevs, int ntevs);
+int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname);
 int probe_cache__commit(struct probe_cache *pcache);
 void probe_cache__delete(struct probe_cache *pcache);
 int probe_cache__remove_entries(struct probe_cache *pcache,


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1187555 — Re: [RFC PATCH perf/core v2 15/16] perf buildid-cache: Scan and import user SDT events to probe cache

FromNamhyung Kim <namhyung@kernel.org>
Date2015-07-19 12:50 +0200
SubjectRe: [RFC PATCH perf/core v2 15/16] perf buildid-cache: Scan and import user SDT events to probe cache
Message-ID<pNUkq-gZ-5@gated-at.bofh.it>
In reply to#1184487
On Wed, Jul 15, 2015 at 06:15:37PM +0900, Masami Hiramatsu wrote:
> perf buildid-cache --add <binary> scans given binary and add
> the SDT events to probe cache. It is possible to use the cached
> SDT events as other cached events (perf probe <provider>:<event>=<event>).

That means lookup the cached SDT events only using event name, right?
What if same event names are used by more than one providers?


> 
> e.g.
>   ----
>   # perf buildid-cache --add /lib/libc-2.17.so
>   # perf probe --cache --list | head -n 5
>   /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
>   libc:setjmp=setjmp
>   libc:longjmp=longjmp
>   libc:longjmp_target=longjmp_target
>   libc:memory_heap_new=memory_heap_new

I expected something like this instead..

    libc:memory_heap_new=new_heap+183


Thanks,
Namhyung


>   # perf probe -x /usr/lib/libc-2.17.so \
>     -a libc:memory_heap_new=memory_heap_new
>   Added new event:
>     libc:memory_heap_new (on memory_heap_new
>    in /usr/lib/libc-2.17.so)
> 
>   You can now use it in all perf tools, such as:
> 
>           perf record -e libc:memory_heap_new -aR sleep 1
> 
>   # perf probe -l
>     libc:memory_heap_new (on new_heap+183 in /usr/lib/libc-2.17.so)
>   ----
> 
> Note that SDT event entries in probe-cache file is somewhat different
> from normal cached events. Normal one starts with "#", but SDTs are
> starting with "%".
> 
> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1185460

FromHemant Kumar <hemant@linux.vnet.ibm.com>
Date2015-07-16 05:20 +0200
Message-ID<pMHSh-2E1-5@gated-at.bofh.it>
In reply to#1184459
Hi Masami,

On 07/15/2015 02:43 PM, Masami Hiramatsu wrote:
> Hi,
>
> Here is the 2nd version of the patchset for probe-cache and
> initial SDT support which are going to be perf-cache finally.

Thanks for adding the SDT support.

> The perf-probe is useful for debugging, but it strongly depends
> on the debuginfo. Without debuginfo, it is just a frontend of
> ftrace's dynamic events. This can usually happen in server
> farms or on cloud system, since no one wants to distribute
> big debuginfo packages.
>
> To solve this issue, I had tried to make a pre-analyzed probes
> ( https://lkml.org/lkml/2014/10/31/207 ) but it has a problm
> that we can't ensure the probed binary is same as what we analyzed.
> Arnaldo gave me an idea to reuse build-id cache for that perpose
> and this series is the first prototype of that.
>
> At the same time, Hemant has started to support SDT probes which
> also use the cache file of SDT info. So I decided to merge this
> into the same build-id cache.
> In this version, SDT support is still very limited, it works
> as a part of probe-cache.
>
> In this version, perf probe supports --cache option which means
> that perf probe manipulate probe caches, for example,
>
>    # perf probe --cache --add "probe-desc"
>
> does not only add probe events but also add "probe-desc" and
> it's result on the cache. (Note that the cached entry is always
> referred even without --cache)
> The --list and --del commands also support --cache. Note that
> both are only manipulate caches, not real events.
>
> To use SDT, we have to scan the target binary at first by using
> perf-buildid-cache, e.g.
>
>    # perf buildid-cache --add /lib/libc-2.17.so
>
> And perf probe --cache --list shows what SDTs are scanned.
>
>    # perf probe --cache --list
>    /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
>    libc:setjmp=setjmp
>    libc:longjmp=longjmp
>    libc:longjmp_target=longjmp_target
>    libc:memory_heap_new=memory_heap_new
>    libc:memory_sbrk_less=memory_sbrk_less
>    libc:memory_arena_reuse_free_list=memory_arena_reuse_free_list
>    libc:memory_arena_reuse=memory_arena_reuse
>    ...
>
> To use the SDT events, perf probe -x BIN %SDTEVENT allows you to
> add a probe on SDTEVENT@BIN.
>
>    # perf probe -x /lib/libc-2.17.so %memory_heap_new
>
> If you define a cached probe with event name, you can also reuse
> it as same as SDT events.
>
>    # perf probe -x ./perf --cache -n 'myevent=dso__load $params'
>
> (Note that "-n" option only updates caches)
> To use the above "myevent", you just have to add "%myevent".
>
>    # perf probe -x ./perf %myevent
>
>
> TODOs:
>   - Show available cached/SDT events by perf-list
>   - Allow perf-record to use cached/SDT events directly

As I was already working on SDT events' recording
https://lkml.org/lkml/2014/11/2/73,
I can re-spin the patches on top of your patchset and make the
required changes to implement the above TODOs.
What would you suggest?

> Thank you,
>
> ---
>
> Hemant Kumar (1):
>        perf/sdt: ELF support for SDT
>
> Masami Hiramatsu (15):
>        perf probe: Simplify __add_probe_trace_events code
>        perf probe: Move ftrace probe-event operations to probe-file.c
>        perf probe: Use strbuf for making strings in probe-event.c
>        perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid
>        perf buildid: Use SBUILD_ID_SIZE macro
>        perf buildid: Introduce sysfs/filename__sprintf_build_id
>        perf: Add lsdir to read a directory
>        perf-buildid-cache: Use lsdir for looking up buildid caches
>        perf probe: Add --cache option to cache the probe definitions
>        perf probe: Use cache entry if possible
>        perf probe: Show all cached probes
>        perf probe: Remove caches when --cache is given
>        perf probe: Add group name support
>        perf buildid-cache: Scan and import user SDT events to probe cache
>        perf probe: Accept %sdt and %cached event name
>
>
>   tools/perf/Documentation/perf-probe.txt |   14
>   tools/perf/builtin-buildid-cache.c      |   22 -
>   tools/perf/builtin-buildid-list.c       |   28 -
>   tools/perf/builtin-probe.c              |    3
>   tools/perf/util/Build                   |    1
>   tools/perf/util/build-id.c              |  230 ++++++--
>   tools/perf/util/build-id.h              |   11
>   tools/perf/util/dso.h                   |    5
>   tools/perf/util/probe-event.c           |  918 ++++++++++++++-----------------
>   tools/perf/util/probe-event.h           |   16 -
>   tools/perf/util/probe-file.c            |  763 ++++++++++++++++++++++++++
>   tools/perf/util/probe-file.h            |   46 ++
>   tools/perf/util/probe-finder.c          |   10
>   tools/perf/util/symbol-elf.c            |  252 +++++++++
>   tools/perf/util/symbol.c                |    2
>   tools/perf/util/symbol.h                |   22 +
>   tools/perf/util/util.c                  |   34 +
>   tools/perf/util/util.h                  |    4
>   18 files changed, 1781 insertions(+), 600 deletions(-)
>   create mode 100644 tools/perf/util/probe-file.c
>   create mode 100644 tools/perf/util/probe-file.h
>
>

-- 
Thanks,
Hemant Kumar

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1189999

FromHemant Kumar <hemant@linux.vnet.ibm.com>
Date2015-07-22 16:20 +0200
Message-ID<pP32i-Ny-29@gated-at.bofh.it>
In reply to#1185460
Hi Masami,

Apologies for the delayed response.

On 07/17/2015 08:51 AM, Masami Hiramatsu wrote:
> Hi Hemant,
>
> On 2015/07/16 12:13, Hemant Kumar wrote:
>> Hi Masami,
>>
>> On 07/15/2015 02:43 PM, Masami Hiramatsu wrote:
>>> Hi,
>>>
>>> Here is the 2nd version of the patchset for probe-cache and
>>> initial SDT support which are going to be perf-cache finally.
>> Thanks for adding the SDT support.
>>
>>> The perf-probe is useful for debugging, but it strongly depends
>>> on the debuginfo. Without debuginfo, it is just a frontend of
>>> ftrace's dynamic events. This can usually happen in server
>>> farms or on cloud system, since no one wants to distribute
>>> big debuginfo packages.
>>>
>>> To solve this issue, I had tried to make a pre-analyzed probes
>>> ( https://lkml.org/lkml/2014/10/31/207 ) but it has a problm
>>> that we can't ensure the probed binary is same as what we analyzed.
>>> Arnaldo gave me an idea to reuse build-id cache for that perpose
>>> and this series is the first prototype of that.
>>>
>>> At the same time, Hemant has started to support SDT probes which
>>> also use the cache file of SDT info. So I decided to merge this
>>> into the same build-id cache.
>>> In this version, SDT support is still very limited, it works
>>> as a part of probe-cache.
>>>
>>> In this version, perf probe supports --cache option which means
>>> that perf probe manipulate probe caches, for example,
>>>
>>>     # perf probe --cache --add "probe-desc"
>>>
>>> does not only add probe events but also add "probe-desc" and
>>> it's result on the cache. (Note that the cached entry is always
>>> referred even without --cache)
>>> The --list and --del commands also support --cache. Note that
>>> both are only manipulate caches, not real events.
>>>
>>> To use SDT, we have to scan the target binary at first by using
>>> perf-buildid-cache, e.g.
>>>
>>>     # perf buildid-cache --add /lib/libc-2.17.so
>>>
>>> And perf probe --cache --list shows what SDTs are scanned.
>>>
>>>     # perf probe --cache --list
>>>     /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
>>>     libc:setjmp=setjmp
>>>     libc:longjmp=longjmp
>>>     libc:longjmp_target=longjmp_target
>>>     libc:memory_heap_new=memory_heap_new
>>>     libc:memory_sbrk_less=memory_sbrk_less
>>>     libc:memory_arena_reuse_free_list=memory_arena_reuse_free_list
>>>     libc:memory_arena_reuse=memory_arena_reuse
>>>     ...
>>>
>>> To use the SDT events, perf probe -x BIN %SDTEVENT allows you to
>>> add a probe on SDTEVENT@BIN.
>>>
>>>     # perf probe -x /lib/libc-2.17.so %memory_heap_new
>>>
>>> If you define a cached probe with event name, you can also reuse
>>> it as same as SDT events.
>>>
>>>     # perf probe -x ./perf --cache -n 'myevent=dso__load $params'
>>>
>>> (Note that "-n" option only updates caches)
>>> To use the above "myevent", you just have to add "%myevent".
>>>
>>>     # perf probe -x ./perf %myevent
>>>
>>>
>>> TODOs:
>>>    - Show available cached/SDT events by perf-list
>>>    - Allow perf-record to use cached/SDT events directly
>> As I was already working on SDT events' recording
>> https://lkml.org/lkml/2014/11/2/73,
>> I can re-spin the patches on top of your patchset and make the
>> required changes to implement the above TODOs.
> Sounds great! :)
> Note that you'll need to re-implement almost from scratch, since
> now the SDT is implemented on buildid-cache. Maybe I have to work
> on the buildid-cache one more to filter out binaries which are gone
> or different version from current running one (e.g. old vmlinux).
> It could help you to get available SDTs when showing it via perf-list.

Sure. That would be great.

>> What would you suggest?
> Now I'm thinking that we should avoid using %event syntax for perf-list
> and perf-record to avoid confusion. For example, suppose that we have
> "libfoo:bar" SDT event, when we just scanned the libfoo binary and
> use it via perf-record, we'll run perf record -e "%libfoo:bar".
> However, after we set the probe via perf-probe, we have to run
> perf record -e "libfoo:bar". That difference looks no good.
> So, I think in both case it should accept -e "libfoo:bar" syntax.

Although I agree to have "perf record" as a higher level tool and not bother
this tool to distinguish between its events, but that way we end up looking
into kprobe_events, uprobe_events, kernel tracepoints and then the entire
cache for any event (which may or may not be an SDT event or even a valid
event) lookup. Right?

The idea behind '%' was to identify the SDT events and take a different path
to lookup through the cache, put a probe, record and then delete the probe.
Or, do you want "perf record" to record any event this way (not just an sdt
event).

Please correct me if I missed something.

> In this series I've introduced %event syntax only to recall cached event
> setting explicitly, because perf-probe is a lower layer tool to set up
> new event. IMO, perf-list and perf-record should be higher tools which
> handle abstract events.
>
> Thanks!
>
>

-- 
Thanks,
Hemant Kumar

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1190909 — Re: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-23 15:20 +0200
SubjectRe: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support
Message-ID<pPozL-7MD-11@gated-at.bofh.it>
In reply to#1189999
On 2015/07/22 23:12, Hemant Kumar wrote:
> Hi Masami,
> 
> Apologies for the delayed response.
> 
> On 07/17/2015 08:51 AM, Masami Hiramatsu wrote:
>> Hi Hemant,
>>
>> On 2015/07/16 12:13, Hemant Kumar wrote:
>>> Hi Masami,
>>>
>>> On 07/15/2015 02:43 PM, Masami Hiramatsu wrote:
>>>> Hi,
>>>>
>>>> Here is the 2nd version of the patchset for probe-cache and
>>>> initial SDT support which are going to be perf-cache finally.
>>> Thanks for adding the SDT support.
>>>
>>>> The perf-probe is useful for debugging, but it strongly depends
>>>> on the debuginfo. Without debuginfo, it is just a frontend of
>>>> ftrace's dynamic events. This can usually happen in server
>>>> farms or on cloud system, since no one wants to distribute
>>>> big debuginfo packages.
>>>>
>>>> To solve this issue, I had tried to make a pre-analyzed probes
>>>> ( https://lkml.org/lkml/2014/10/31/207 ) but it has a problm
>>>> that we can't ensure the probed binary is same as what we analyzed.
>>>> Arnaldo gave me an idea to reuse build-id cache for that perpose
>>>> and this series is the first prototype of that.
>>>>
>>>> At the same time, Hemant has started to support SDT probes which
>>>> also use the cache file of SDT info. So I decided to merge this
>>>> into the same build-id cache.
>>>> In this version, SDT support is still very limited, it works
>>>> as a part of probe-cache.
>>>>
>>>> In this version, perf probe supports --cache option which means
>>>> that perf probe manipulate probe caches, for example,
>>>>
>>>>     # perf probe --cache --add "probe-desc"
>>>>
>>>> does not only add probe events but also add "probe-desc" and
>>>> it's result on the cache. (Note that the cached entry is always
>>>> referred even without --cache)
>>>> The --list and --del commands also support --cache. Note that
>>>> both are only manipulate caches, not real events.
>>>>
>>>> To use SDT, we have to scan the target binary at first by using
>>>> perf-buildid-cache, e.g.
>>>>
>>>>     # perf buildid-cache --add /lib/libc-2.17.so
>>>>
>>>> And perf probe --cache --list shows what SDTs are scanned.
>>>>
>>>>     # perf probe --cache --list
>>>>     /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
>>>>     libc:setjmp=setjmp
>>>>     libc:longjmp=longjmp
>>>>     libc:longjmp_target=longjmp_target
>>>>     libc:memory_heap_new=memory_heap_new
>>>>     libc:memory_sbrk_less=memory_sbrk_less
>>>>     libc:memory_arena_reuse_free_list=memory_arena_reuse_free_list
>>>>     libc:memory_arena_reuse=memory_arena_reuse
>>>>     ...
>>>>
>>>> To use the SDT events, perf probe -x BIN %SDTEVENT allows you to
>>>> add a probe on SDTEVENT@BIN.
>>>>
>>>>     # perf probe -x /lib/libc-2.17.so %memory_heap_new
>>>>
>>>> If you define a cached probe with event name, you can also reuse
>>>> it as same as SDT events.
>>>>
>>>>     # perf probe -x ./perf --cache -n 'myevent=dso__load $params'
>>>>
>>>> (Note that "-n" option only updates caches)
>>>> To use the above "myevent", you just have to add "%myevent".
>>>>
>>>>     # perf probe -x ./perf %myevent
>>>>
>>>>
>>>> TODOs:
>>>>    - Show available cached/SDT events by perf-list
>>>>    - Allow perf-record to use cached/SDT events directly
>>> As I was already working on SDT events' recording
>>> https://lkml.org/lkml/2014/11/2/73,
>>> I can re-spin the patches on top of your patchset and make the
>>> required changes to implement the above TODOs.
>> Sounds great! :)
>> Note that you'll need to re-implement almost from scratch, since
>> now the SDT is implemented on buildid-cache. Maybe I have to work
>> on the buildid-cache one more to filter out binaries which are gone
>> or different version from current running one (e.g. old vmlinux).
>> It could help you to get available SDTs when showing it via perf-list.
> 
> Sure. That would be great.
> 
>>> What would you suggest?
>> Now I'm thinking that we should avoid using %event syntax for perf-list
>> and perf-record to avoid confusion. For example, suppose that we have
>> "libfoo:bar" SDT event, when we just scanned the libfoo binary and
>> use it via perf-record, we'll run perf record -e "%libfoo:bar".
>> However, after we set the probe via perf-probe, we have to run
>> perf record -e "libfoo:bar". That difference looks no good.
>> So, I think in both case it should accept -e "libfoo:bar" syntax.
> 
> Although I agree to have "perf record" as a higher level tool and not bother
> this tool to distinguish between its events, but that way we end up looking
> into kprobe_events, uprobe_events, kernel tracepoints and then the entire
> cache for any event (which may or may not be an SDT event or even a valid
> event) lookup. Right?

Yeah, right.

> 
> The idea behind '%' was to identify the SDT events and take a different path
> to lookup through the cache, put a probe, record and then delete the probe.
> Or, do you want "perf record" to record any event this way (not just an sdt
> event).

I see, but I think that is not good by following reasons,

- when we record event with "-e %provider:event", it will be shown as
  "provider:event"
- if perf-list shows the SDT(cached) events as "%provider:event", that
  will not match the recorded result.
- it is somewhat fragile that we temporary add the SDT event and remove it
  after record, because the event will not hide from ftrace users (this
  means that we'll fail removing the event by -EBUSY if someone use it
  via ftrace)
- if we set SDT events perf-probe, it will be shown as "provider:event" name
  because "%" will be rejected by ftrace. In that case, what the perf-list show
  those events, both of %provider:event and provider:event ?

thus I pushed the "%" as a "special remembering mark" only for looking
up the event from cache by perf-probe.

So I'd like to suggest that the following behavior

1) perf-list shows the cached-with-name and SDT events as Tracepoint events
  even if it is not yet probed.

# perf list

List of pre-defined events (to be used in -e):
...
  libc:memory_heap_new                             [Tracepoint event]
...
  probes:myevent                                   [Tracepoint event]
...

2) perf-record -e with no-probed event should try to set up the given probe
 by using perf-probe. It is possible to remove that the probe after recording,
 but also ignore if it fails by -EBUSY. (anyway, there is no difference for
 users)

This rule will solve the contradiction between the event name on recorded
data and listed events. However, as we discussed there are other clashes.

A) clash among binaries: Since the binary builders can freely use the
provider name, it is possible to clash to other binaries' SDTs.

B) clash among different versions: Of course the different versions of binaries
can be co-exist on the system. Those usually have the same SDTs and same
basename, just different build-ids.

These issues are not solved by using "%" because it happens among SDTs.
So we need to find another way to distinguish the SDTs.

Thank you,

> 
> Please correct me if I missed something.
> 
>> In this series I've introduced %event syntax only to recall cached event
>> setting explicitly, because perf-probe is a lower layer tool to set up
>> new event. IMO, perf-list and perf-record should be higher tools which
>> handle abstract events.
>>
>> Thanks!
>>
>>
> 


-- 
Masami HIRAMATSU
Linux Technology Research Center, System Productivity Research Dept.
Center for Technology Innovation - Systems Engineering
Hitachi, Ltd., Research & Development Group
E-mail: masami.hiramatsu.pt@hitachi.com
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1190945 — Re: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2015-07-23 16:10 +0200
SubjectRe: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support
Message-ID<pPpma-v1-17@gated-at.bofh.it>
In reply to#1190909
Em Thu, Jul 23, 2015 at 10:13:22PM +0900, Masami Hiramatsu escreveu:
> On 2015/07/22 23:12, Hemant Kumar wrote:
> > On 07/17/2015 08:51 AM, Masami Hiramatsu wrote:
> >> On 2015/07/16 12:13, Hemant Kumar wrote:
> > The idea behind '%' was to identify the SDT events and take a different path
> > to lookup through the cache, put a probe, record and then delete the probe.
> > Or, do you want "perf record" to record any event this way (not just an sdt
> > event).
 
> I see, but I think that is not good by following reasons,
 
> - when we record event with "-e %provider:event", it will be shown as
>   "provider:event"
> - if perf-list shows the SDT(cached) events as "%provider:event", that
>   will not match the recorded result.
> - it is somewhat fragile that we temporary add the SDT event and remove it
>   after record, because the event will not hide from ftrace users (this
>   means that we'll fail removing the event by -EBUSY if someone use it
>   via ftrace)

We should avoid that, if we say record event "foo:bar", then we should
consistently show "foo:bar" everywhere this is referenced.

> - if we set SDT events perf-probe, it will be shown as "provider:event" name
>   because "%" will be rejected by ftrace. In that case, what the perf-list show
>   those events, both of %provider:event and provider:event ?
 
> thus I pushed the "%" as a "special remembering mark" only for looking
> up the event from cache by perf-probe.
 
> So I'd like to suggest that the following behavior
 
> 1) perf-list shows the cached-with-name and SDT events as Tracepoint events
>   even if it is not yet probed.

I can agree with 'perf list' showing what can be used as events, and
SDTs, AFAIK, match that definition, i.e. we have somewhere (in the DSOs,
right?) information about where to ask for an event to be enabled.

If there are details on how that needs to be obtained, then passed to
the kernel somehow to then become really, really accessible, then these
details are completely internal.

> # perf list
> 
> List of pre-defined events (to be used in -e):
> ...
>   libc:memory_heap_new                             [Tracepoint event]

Is it like this or is it like [ku]probes where we already have a
namespace qualifier, i.e.:

[root@zoo ~]# perf probe icmp_rcv
Added new event:
  probe:icmp_rcv       (on icmp_rcv)

You can now use it in all perf tools, such as:

	perf record -e probe:icmp_rcv -aR sleep 1

[root@zoo ~]#

[root@zoo ~]# perf probe /lib64/libc-2.20.so malloc
Added new events:
  probe_libc:malloc    (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_1  (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_2  (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_3  (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_4  (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_5  (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_6  (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_7  (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_8  (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_9  (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_10 (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_11 (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_12 (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_13 (on malloc in /lib64/libc-2.20.so)
  probe_libc:malloc_14 (on malloc in /lib64/libc-2.20.so)

You can now use it in all perf tools, such as:

	perf record -e probe_libc:malloc_14 -aR sleep 1

[root@zoo ~]#

"probe" for kernel events, "probe_%s" % DSO basename for userspace
events.

Why not continue with that and have SDTs use the probe_%s: namespace?
Sorry if this was already discussed here...

If there is some ambiguity, that can be resolved by explicitely setting
a new name, 'perf probe' has provision for that, right? I.e.:

[root@zoo ~]# perf probe /lib64/libc-2.20.so another_name=malloc
Added new events:
<SNIP>
  probe_libc:another_name_14 (on malloc in /lib64/libc-2.20.so)

You can now use it in all perf tools, such as:

	perf record -e probe_libc:another_name_14 -aR sleep 1

[root@zoo ~]#

> ...
>   probes:myevent                                   [Tracepoint event]
> ...
 
> 2) perf-record -e with no-probed event should try to set up the given probe
>  by using perf-probe. It is possible to remove that the probe after recording,
>  but also ignore if it fails by -EBUSY. (anyway, there is no difference for
>  users)

Right, being able to add new probes _without_ calling 'perf probe', but
instead functions used by 'perf probe' is something the eBPF does (I'm
almost getting there... :) ) and that I want to do in other tools, like
'trace' as well...

There are permission problems about how to add new probes and how to
_enable_ them, i.e. I think it is ok to allow users to ask for
probe:foo, if they are monitoring just their workloads...

[root@zoo ~]# perf probe 'vfs_getname=getname_flags:72 pathname=filename:string'
Added new event:
  probe:vfs_getname    (on getname_flags:72 with pathname=filename:string)

You can now use it in all perf tools, such as:

	perf record -e probe:vfs_getname -aR sleep 1

[root@zoo ~]#

Then, as !root:

  [acme@zoo linux]$ trace cat /etc/passwd
  Error:	No permissions to read /sys/kernel/debug/tracing/events/raw_syscalls/sys_(enter|exit)
  Hint:	Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'

By default, !root users can't see debugfs, so, no dice in trying to use
the raw_syscalls tracepoints, bummer, then:

  [acme@zoo linux]$ sudo mount -o remount,mode=755 /sys/kernel/debug
  [sudo] password for acme: 
  [acme@zoo linux]$ trace cat /etc/passwd
  Error:	No permissions to read /sys/kernel/debug/tracing/events/raw_syscalls/sys_(enter|exit)
  Hint:	Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'

Ouch, now this tracefs thing inside debugfs, at least sudo doesn't asks me for the
password this time!

But then, since 'perf trace' knows there is a probe:vfs_getname syscall in place, it
will try to use it, to monitor a workload it is about to start, but:

  [acme@zoo linux]$ sudo mount -o remount,mode=755 /sys/kernel/debug/tracing
  [acme@zoo linux]$ trace cat /etc/passwd
  Error:	Operation not permitted.
  Hint:	Check /proc/sys/kernel/perf_event_paranoid setting.
  Hint:	For system wide tracing it needs to be set to -1.
  Hint:	Try: 'sudo sh -c "echo -1 > /proc/sys/kernel/perf_event_paranoid"'
  Hint:	The current value is 1.
  [acme@zoo linux]$

This needs refining, i.e. I should just warn that albeit "probe:vfs_getname" is available,
it can't be used, unless we open the doors wide.

Sorry for the digression, but these permission issues will hit us with SDT as well, no?
 
> This rule will solve the contradiction between the event name on recorded
> data and listed events. However, as we discussed there are other clashes.

> A) clash among binaries: Since the binary builders can freely use the
> provider name, it is possible to clash to other binaries' SDTs.

Yes, one way to disambiguate is to use the buildid, i.e. content based, when/if
the need arises. We should _always_ store the build-id, together with any probe
used, so that we can bail out when trying to run those with a non matching DSO
(kernel, module, library, whatever).

When specifying some SDT that is ambiguous, we should bail out and ask for further
namespacing, like:

[acme@zoo linux]$ git show --oneline 25b6
error: short SHA1 25b6 is ambiguous.
error: short SHA1 25b6 is ambiguous.
fatal: ambiguous argument '25b6': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
[acme@zoo linux]$ git show --oneline 25b67
error: short SHA1 25b67 is ambiguous.
error: short SHA1 25b67 is ambiguous.
fatal: ambiguous argument '25b67': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

It can be via build-id or by asking for the full pathname to the DSO, etc.
 
> B) clash among different versions: Of course the different versions of binaries
> can be co-exist on the system. Those usually have the same SDTs and same
> basename, just different build-ids.

Right, in that case the build-id or the full pathname needs to be specified somehow

> These issues are not solved by using "%" because it happens among SDTs.
> So we need to find another way to distinguish the SDTs.

From what I've read so far (not much): agreed.

- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1191584 — Re: Re: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support

FromNamhyung Kim <namhyung@kernel.org>
Date2015-07-24 10:10 +0200
SubjectRe: Re: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support
Message-ID<pPGdk-8is-15@gated-at.bofh.it>
In reply to#1190945
Hi Masami and Arnaldo,

On Fri, Jul 24, 2015 at 01:24:53AM +0900, Masami Hiramatsu wrote:
> On 2015/07/23 23:01, Arnaldo Carvalho de Melo wrote:
> > Em Thu, Jul 23, 2015 at 10:13:22PM +0900, Masami Hiramatsu escreveu:
> >> # perf list
> >>
> >> List of pre-defined events (to be used in -e):
> >> ...
> >>   libc:memory_heap_new                             [Tracepoint event]
> > 
> > Is it like this or is it like [ku]probes where we already have a
> > namespace qualifier, i.e.:
> > 
> > [root@zoo ~]# perf probe icmp_rcv
> > Added new event:
> >   probe:icmp_rcv       (on icmp_rcv)
> > 
> > You can now use it in all perf tools, such as:
> > 
> > 	perf record -e probe:icmp_rcv -aR sleep 1
> > 
> > [root@zoo ~]#
> > 
> > [root@zoo ~]# perf probe /lib64/libc-2.20.so malloc
> > Added new events:
> >   probe_libc:malloc    (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_1  (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_2  (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_3  (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_4  (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_5  (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_6  (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_7  (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_8  (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_9  (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_10 (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_11 (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_12 (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_13 (on malloc in /lib64/libc-2.20.so)
> >   probe_libc:malloc_14 (on malloc in /lib64/libc-2.20.so)
> > 
> > You can now use it in all perf tools, such as:
> > 
> > 	perf record -e probe_libc:malloc_14 -aR sleep 1
> > 
> > [root@zoo ~]#
> > 
> > "probe" for kernel events, "probe_%s" % DSO basename for userspace
> > events.
> > 
> > Why not continue with that and have SDTs use the probe_%s: namespace?
> > Sorry if this was already discussed here...
> 
> :) We are discussing about that in another thread, anyway, probe_%s can
> solve a little part of the clash of names.
> 
> > 
> > If there is some ambiguity, that can be resolved by explicitely setting
> > a new name, 'perf probe' has provision for that, right? I.e.:
> 
> Yes, but that means we'll have to give new names before using that.
> 
> Actually, SDT has "provider-name", "event-name" and "probe location" (also
> have arguments, but not supported). And provider name is not always same
> as the binary name. (actually, the application developers can use any
> name for it...)
> So adding something special prefix or detect clash before using will
> be the option.
> 
> The following patterns we've discussed.
> 
>  - <provider>:<name>
> 	simple, but could easily clash with others.
>  - probe_<provider>:<name>
>  - sdt_<provider>:<name>
> 	also simple and similar to current solution. but fragile against
> 	clash among SDTs.
>  - probe_<binary>:<provider>_<name>
> 	also simple, but if provider or/and name has '_', it is hard to
> 	split the provider and name. and fragile against clash among SDTs too.
>  - <provider>_<buildid>/<name>
> 	possible, but ugly since buildid is a random long xdigits(maybe cut up
> 	to 8 or 12 bytes).

As I said, we might allow name clashes as they're rare.  I don't want
to make it complex just for an uncommon case.  I think such a
duplicate name is fine as long as 'perf list' indicates it and 'perf
record' enable them all.

If we agreed to extend the event format, I'd like to keep it simple
and to make it optional to add more info (separated by colon?).

Maybe something like below.  Suppose we have 3 SDT events with a same
name:

 /some/where/dir1/libfoo1.so (build-id: 0x1234...) -->  foo:bar
 /some/where/dir2/libfoo1.so (build-id: 0x5678...) -->  foo:bar
 /some/where/dir2/libfoo2.so (build-id: 0xabcd...) -->  foo:bar

So perf list shows the single name, but also says it has 3 events.

  $ perf list sdt_foo:bar
  
  sdt_foo:bar (total 3 events)            [User SDT event]


  $ perf list -v sdt_foo:bar
  
  sdt_foo:bar:libfoo1.so:0x1234...        [User SDT event]
  sdt_foo:bar:libfoo1.so:0x5678...        [User SDT event]
  sdt_foo:bar:libfoo2.so:0xabcd...        [User SDT event]


Now perf record can accept any of these forms..

  # record all 3 events
  $ perf record -e 'sdt_foo:bar'

  # record 2 events from libfoo1.so
  $ perf record -e 'sdt_foo:bar:libfoo1.so'

  # record only 1 event
  $ perf record -e 'sdt_foo:bar:libfoo1.so:0x1234...'


What do you think?

Thanks,
Namhyung
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1193138 — Re: Re: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support

FromNamhyung Kim <namhyung@kernel.org>
Date2015-07-27 16:10 +0200
SubjectRe: Re: Re: [RFC PATCH perf/core v2 00/16] perf-probe --cache and SDT support
Message-ID<pQRgm-46U-15@gated-at.bofh.it>
In reply to#1191584
Hi Arnaldo,

On Fri, Jul 24, 2015 at 12:52:37PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Fri, Jul 24, 2015 at 04:55:19PM +0900, Namhyung Kim escreveu:
> > On Fri, Jul 24, 2015 at 01:24:53AM +0900, Masami Hiramatsu wrote:
> > > On 2015/07/23 23:01, Arnaldo Carvalho de Melo wrote:
> > > > Em Thu, Jul 23, 2015 at 10:13:22PM +0900, Masami Hiramatsu escreveu:
> 
> > > The following patterns we've discussed.
> > > 
> > >  - <provider>:<name>
> > > 	simple, but could easily clash with others.
> > >  - probe_<provider>:<name>
> > >  - sdt_<provider>:<name>
> > > 	also simple and similar to current solution. but fragile against
> > > 	clash among SDTs.
> > >  - probe_<binary>:<provider>_<name>
> > > 	also simple, but if provider or/and name has '_', it is hard to
> > > 	split the provider and name. and fragile against clash among SDTs too.
> > >  - <provider>_<buildid>/<name>
> > > 	possible, but ugly since buildid is a random long xdigits(maybe cut up
> > > 	to 8 or 12 bytes).
>  
> > As I said, we might allow name clashes as they're rare.  I don't want
> > to make it complex just for an uncommon case.  I think such a
> > duplicate name is fine as long as 'perf list' indicates it and 'perf
> > record' enable them all.
> 
> I made some comments about enabling it all by default, look below.

OK.


>  
> > If we agreed to extend the event format, I'd like to keep it simple
> > and to make it optional to add more info (separated by colon?).
> 
> Reading this again after writing what is below: my suggestion is to use
> @, see rationale below.

I'm fine with using @.


>  
> > Maybe something like below.  Suppose we have 3 SDT events with a same
> > name:
> > 
> >  /some/where/dir1/libfoo1.so (build-id: 0x1234...) -->  foo:bar
> >  /some/where/dir2/libfoo1.so (build-id: 0x5678...) -->  foo:bar
> >  /some/where/dir2/libfoo2.so (build-id: 0xabcd...) -->  foo:bar
> > 
> > So perf list shows the single name, but also says it has 3 events.
> > 
> >   $ perf list sdt_foo:bar
> >   
> >   sdt_foo:bar (total 3 events)            [User SDT event]
> 
> I would show what desambiguates them in non verbose mode, i.e., the
> above would be:
> 
>    $ perf list sdt_foo:bar
> 
>    sdt_foo:bar:dir1/libfoo1.so   [User SDT event]
>    sdt_foo:bar:dir2/libfoo1.so   [User SDT event]
>    sdt_foo:bar:libfoo2.so        [User SDT event]

Then it should use @ here too.


> 
>  The -v one would should both the full path and the buildid, but this
> is just polishing up the default output a bit to make it more
> informative.

Fair enough.


> 
> 	Now what should be the default when one does:
> 
>    perf record -e sdt_foo:bar
> 
>         Will it enable all events or bail out and state that multiple
> events with that name matches, requiring a '--all-matches' to really
> apply it to all events with the same name?
> 
> 	Humm, this probably will not be that common, so perhaps just
> use all matches by default while telling the user that all those places
> were used and if the user wants just one of them, be more precise,
> adding somehow a disambiguator.

Either is fine to me.  Mayb we can add a config option to select the
default bahavior.. :)


> 
> 	That would be something like this:
> 
>     perf record -e sdt_foo:bar:0x1234
> 
> 	Or perhaps:
> 
>     perf record -e sdt_foo:bar@0x1234
> 
> 	Because in this case the 'at' meaning of '@' makes sense, i.e.
> use the std_foo:bar event at the DSO with a 0x1234 buildid?

IMHO @ looks perfect for pathnames but I don't know about build-id as
it can be thought as some address.  Anyway I still think @ is a good
choice though. ;-)


> 
> 	Additionally, for people that don't want to mess with buildids
> because its environment is deemed well controlled and this works and is
> unambiguous, looking at the LD_LIBRARY_PATH or equivalent:

Ah, good idea.


> 
>     perf record -e sdt_foo:bar@libfoo2
> 
> 	Full paths could be used as well.
> > 
> >   $ perf list -v sdt_foo:bar
> >   
> >   sdt_foo:bar:libfoo1.so:0x1234...        [User SDT event]
> >   sdt_foo:bar:libfoo1.so:0x5678...        [User SDT event]
> >   sdt_foo:bar:libfoo2.so:0xabcd...        [User SDT event]
> 
> > 
> > Now perf record can accept any of these forms..
> > 
> >   # record all 3 events
> >   $ perf record -e 'sdt_foo:bar'
> > 
> >   # record 2 events from libfoo1.so
> >   $ perf record -e 'sdt_foo:bar:libfoo1.so'
> > 
> >   # record only 1 event
> >   $ perf record -e 'sdt_foo:bar:libfoo1.so:0x1234...'
> > 
> > 
> > What do you think?
> 
> If nothing prevents using @ with the meaning of "event at LOCATION"
> where LOCATION is a buildid (noticed because it starts with 0x) or
> a library name or pathname, then that looks more natural.

Agreed.

Thanks,
Namhyung
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1193666

FromMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Date2015-07-28 02:50 +0200
Message-ID<pR1fH-1AI-1@gated-at.bofh.it>
In reply to#1193138
On 2015/07/28 0:16, Arnaldo Carvalho de Melo wrote:
> Em Mon, Jul 27, 2015 at 11:03:20PM +0900, Namhyung Kim escreveu:
>> On Fri, Jul 24, 2015 at 12:52:37PM -0300, Arnaldo Carvalho de Melo wrote:
>>>> If we agreed to extend the event format, I'd like to keep it simple
>>>> and to make it optional to add more info (separated by colon?).
>>>
>>> Reading this again after writing what is below: my suggestion is to use
>>> @, see rationale below.
>>
>> I'm fine with using @.
>  
>>> I would show what desambiguates them in non verbose mode, i.e., the
>>> above would be:
>>>
>>>    $ perf list sdt_foo:bar
>>>
>>>    sdt_foo:bar:dir1/libfoo1.so   [User SDT event]
>>>    sdt_foo:bar:dir2/libfoo1.so   [User SDT event]
>>>    sdt_foo:bar:libfoo2.so        [User SDT event]
>>
>> Then it should use @ here too.
> 
> Right.
>  
> <SNIP>
> 
>>> 	That would be something like this:
> 
>>>     perf record -e sdt_foo:bar@0x1234
> 
>>> 	Because in this case the 'at' meaning of '@' makes sense, i.e.
>>> use the std_foo:bar event at the DSO with a 0x1234 buildid?
>>
>> IMHO @ looks perfect for pathnames but I don't know about build-id as
>> it can be thought as some address.  Anyway I still think @ is a good
>> choice though. ;-)
> 
> Yeah, perhaps we need further clarification? I.e. something like:
> 
> 	sdt_foo:bar:libfoo1.so@buildid(0x1234)
> 
> Or something else, perhaps shorter, that clarifies that it is a buildid?

Hmm, Do we really need such additional buildid? Even though, I think
the build id should have different delimiter, like '%', as below.

sdt_foo:bar@libfoo1.so%buildid


Thank you,

-- 
Masami HIRAMATSU
Linux Technology Research Center, System Productivity Research Dept.
Center for Technology Innovation - Systems Engineering
Hitachi, Ltd., Research & Development Group
E-mail: masami.hiramatsu.pt@hitachi.com
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.kernel


csiph-web