All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH perf/core v7 00/21] perf-probe --cache and SDT support
@ 2016-05-11 13:51 Masami Hiramatsu
  2016-05-11 13:51 ` [PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly Masami Hiramatsu
                   ` (20 more replies)
  0 siblings, 21 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:51 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

Hi,

Here is the 7th version of the patchset for probe-cache and 
initial SDT support.

The previous version is here; https://lkml.org/lkml/2116/4/29/358

This version add some bugfixes and cleanup patches. Also, tested
by using runtests (https://github.com/mhiramat/runtests) which found
several bugs in previous version.
(I've added test.d/buildid-cache/*.tc, test.d/probe/cache*.tc and
 test.d/probe/sdt.tc for this series)

Changes in v7:
 - [1/21]-[5/21], [7/21] Newly added for bugfix and cleanup.
 - [6/21] Remove unneeded local strlist.
 - [8/21] Move kallsyms buildid related code into build-id.c
    (as build_id_cache__kallsyms_path).
 - [11/21] Remove the top '/' from binary name if it is not a regular file.
 - [16/21] Fix a bug to return an error if no SDT/cached events found in cache.
 - [18/21] Validate build-id via sysfs if it is for kallsyms,
 - [19/21] Continue to search caches if a build-id cache has no probe cache.
 - [19/21] Make probe_cache__open() to accept DSO__NAME_KALLSYMS for kernel.
 - [19/21] Fix to add probes correctly when a wildcard matchs both of
    uprobes and kprobes.
 - [21/21] as Brendan suggested, special support for "sdt_" prefix
      (treat it as same as "%sdt_" )


Thank you,

---

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

Masami Hiramatsu (20):
      tools/perf: Fix lsdir to set errno correctly
      perf buildid: Fix to set correct dso name for kallsyms
      perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE
      perf: Use SBUILD_ID_SIZE macro instead of BUILD_ID_SIZE macro
      perf symbol: Use lsdir for search in kcore cache directory
      perf-buildid-cache: Use lsdir for looking up buildid caches
      perf symbol: Cleanup the code flow of dso__find_kallsyms
      perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid
      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
      perf-list: Show SDT and pre-cached events
      perf-list: Skip SDTs placed in invalid binaries
      perf probe: Allow wildcard for cached events
      perf probe: Support @BUILDID or @FILE suffix for SDT events
      perf probe: Support a special SDT probe format


 tools/perf/Documentation/perf-probe.txt            |   26 +
 tools/perf/builtin-buildid-cache.c                 |    8 
 tools/perf/builtin-list.c                          |    4 
 tools/perf/builtin-probe.c                         |   30 +
 tools/perf/util/annotate.c                         |    4 
 tools/perf/util/build-id.c                         |  334 +++++++++++--
 tools/perf/util/build-id.h                         |    8 
 tools/perf/util/dso.c                              |    4 
 tools/perf/util/dso.h                              |    5 
 tools/perf/util/header.c                           |    2 
 tools/perf/util/machine.c                          |    2 
 tools/perf/util/map.c                              |    2 
 tools/perf/util/parse-events.c                     |   83 +++
 tools/perf/util/parse-events.h                     |    2 
 tools/perf/util/probe-event.c                      |  492 +++++++++++++++++---
 tools/perf/util/probe-event.h                      |    7 
 tools/perf/util/probe-file.c                       |  502 ++++++++++++++++++++
 tools/perf/util/probe-file.h                       |   41 ++
 .../util/scripting-engines/trace-event-python.c    |    2 
 tools/perf/util/symbol-elf.c                       |  252 ++++++++++
 tools/perf/util/symbol.c                           |   93 ++--
 tools/perf/util/symbol.h                           |   25 +
 tools/perf/util/util.c                             |    2 
 23 files changed, 1743 insertions(+), 187 deletions(-)

--
Masami Hiramatsu

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
@ 2016-05-11 13:51 ` Masami Hiramatsu
  2016-05-11 13:59   ` Arnaldo Carvalho de Melo
  2016-05-12 10:25   ` [tip:perf/core] perf tools: " tip-bot for Masami Hiramatsu
  2016-05-11 13:51 ` [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms Masami Hiramatsu
                   ` (19 subsequent siblings)
  20 siblings, 2 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:51 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

Fix lsdir() to set correct positive error number (ENOMEM).
Since "errno" must have a positive error number instead of
negative number, fix lsdir to set it correctly.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/util/util.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 01c9433..eab077a 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -139,7 +139,7 @@ struct strlist *lsdir(const char *name,
 
 	list = strlist__new(NULL, NULL);
 	if (!list) {
-		errno = -ENOMEM;
+		errno = ENOMEM;
 		goto out;
 	}
 

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
  2016-05-11 13:51 ` [PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly Masami Hiramatsu
@ 2016-05-11 13:51 ` Masami Hiramatsu
  2016-05-11 15:45   ` Arnaldo Carvalho de Melo
  2016-05-11 13:51 ` [PATCH perf/core v7 03/21] perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE Masami Hiramatsu
                   ` (18 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:51 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

Fix to set correct dso name ("[kernel.kallsyms]") for
kallsyms, as for vdso does.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/util/build-id.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index b6ecf87..234d8a1 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -343,21 +343,25 @@ void disable_buildid_cache(void)
 static char *build_id_cache__dirname_from_path(const char *name,
 					       bool is_kallsyms, bool is_vdso)
 {
-	char *realname = (char *)name, *filename;
+	const char *realname = name;
+	char *filename;
 	bool slash = is_kallsyms || is_vdso;
 
 	if (!slash) {
 		realname = realpath(name, NULL);
 		if (!realname)
 			return NULL;
-	}
+	} else if (is_vdso)
+		realname = DSO__NAME_VDSO;
+	else
+		realname = "[kernel.kallsyms]";
 
 	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
-		     is_vdso ? DSO__NAME_VDSO : realname) < 0)
+		     realname) < 0)
 		filename = NULL;
 
 	if (!slash)
-		free(realname);
+		free((char *)realname);
 
 	return filename;
 }

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 03/21] perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
  2016-05-11 13:51 ` [PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly Masami Hiramatsu
  2016-05-11 13:51 ` [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms Masami Hiramatsu
@ 2016-05-11 13:51 ` Masami Hiramatsu
  2016-05-11 15:47   ` Arnaldo Carvalho de Melo
  2016-05-11 13:51 ` [PATCH perf/core v7 04/21] perf: Use SBUILD_ID_SIZE macro instead of BUILD_ID_SIZE macro Masami Hiramatsu
                   ` (17 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:51 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

Instead of using raw string, use DSO__NAME_KALLSYMS and DSO__NAME_KCORE
macros for kallsyms and kcore.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/builtin-buildid-cache.c |    8 ++++----
 tools/perf/util/annotate.c         |    2 +-
 tools/perf/util/build-id.c         |    2 +-
 tools/perf/util/machine.c          |    2 +-
 tools/perf/util/symbol.c           |   10 +++++-----
 tools/perf/util/symbol.h           |    3 +++
 6 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 632efc6..d75bded 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -119,8 +119,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
 	if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0)
 		return -1;
 
-	scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
-		  buildid_dir, sbuildid);
+	scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s",
+		  buildid_dir, DSO__NAME_KCORE, sbuildid);
 
 	if (!force &&
 	    !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
@@ -131,8 +131,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
 	if (build_id_cache__kcore_dir(dir, sizeof(dir)))
 		return -1;
 
-	scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
-		  buildid_dir, sbuildid, dir);
+	scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s/%s",
+		  buildid_dir, DSO__NAME_KCORE, sbuildid, dir);
 
 	if (mkdir_p(to_dir, 0755))
 		return -1;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index d4b3d03..1168442 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1122,7 +1122,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
 	} else if (dso__is_kcore(dso)) {
 		goto fallback;
 	} else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
-		   strstr(command, "[kernel.kallsyms]") ||
+		   strstr(command, DSO__NAME_KALLSYMS) ||
 		   access(symfs_filename, R_OK)) {
 		free(filename);
 fallback:
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 234d8a1..53df9aa 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -354,7 +354,7 @@ static char *build_id_cache__dirname_from_path(const char *name,
 	} else if (is_vdso)
 		realname = DSO__NAME_VDSO;
 	else
-		realname = "[kernel.kallsyms]";
+		realname = DSO__NAME_KALLSYMS;
 
 	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
 		     realname) < 0)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 639a290..18dd96b 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -709,7 +709,7 @@ static struct dso *machine__get_kernel(struct machine *machine)
 	if (machine__is_host(machine)) {
 		vmlinux_name = symbol_conf.vmlinux_name;
 		if (!vmlinux_name)
-			vmlinux_name = "[kernel.kallsyms]";
+			vmlinux_name = DSO__NAME_KALLSYMS;
 
 		kernel = machine__findnew_kernel(machine, vmlinux_name,
 						 "[kernel]", DSO_TYPE_KERNEL);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 2946295..49caa91 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1648,8 +1648,8 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 
 	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
 
-	scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir,
-		  sbuild_id);
+	scnprintf(path, sizeof(path), "%s/%s/%s", buildid_dir,
+		  DSO__NAME_KCORE, sbuild_id);
 
 	/* Use /proc/kallsyms if possible */
 	if (is_host) {
@@ -1685,8 +1685,8 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 	if (!find_matching_kcore(map, path, sizeof(path)))
 		return strdup(path);
 
-	scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
-		  buildid_dir, sbuild_id);
+	scnprintf(path, sizeof(path), "%s/%s/%s",
+		  buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
 
 	if (access(path, F_OK)) {
 		pr_err("No kallsyms or vmlinux with build-id %s was found\n",
@@ -1755,7 +1755,7 @@ do_kallsyms:
 
 	if (err > 0 && !dso__is_kcore(dso)) {
 		dso->binary_type = DSO_BINARY_TYPE__KALLSYMS;
-		dso__set_long_name(dso, "[kernel.kallsyms]", false);
+		dso__set_long_name(dso, DSO__NAME_KALLSYMS, false);
 		map__fixup_start(map);
 		map__fixup_end(map);
 	}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 07211c2..78e3bbf 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -44,6 +44,9 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
 #define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
 #endif
 
+#define DSO__NAME_KALLSYMS	"[kernel.kallsyms]"
+#define DSO__NAME_KCORE		"[kernel.kcore]"
+
 /** struct symbol - symtab entry
  *
  * @ignore - resolvable but tools ignore it (e.g. idle routines)

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 04/21] perf: Use SBUILD_ID_SIZE macro instead of BUILD_ID_SIZE macro
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (2 preceding siblings ...)
  2016-05-11 13:51 ` [PATCH perf/core v7 03/21] perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE Masami Hiramatsu
@ 2016-05-11 13:51 ` Masami Hiramatsu
  2016-05-11 15:47   ` Arnaldo Carvalho de Melo
  2016-05-12 10:25   ` [tip:perf/core] perf tools: Use SBUILD_ID_SIZE where applicable tip-bot for Masami Hiramatsu
  2016-05-11 13:52 ` [PATCH perf/core v7 05/21] perf symbol: Use lsdir for search in kcore cache directory Masami Hiramatsu
                   ` (16 subsequent siblings)
  20 siblings, 2 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:51 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

Use SBUILD_ID_SIZE macro instead of BUILD_ID_SIZE * 2 + 1 for
allocating a buffer for build-id string.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/util/annotate.c                         |    2 +-
 tools/perf/util/dso.c                              |    4 ++--
 tools/perf/util/header.c                           |    2 +-
 tools/perf/util/map.c                              |    2 +-
 .../util/scripting-engines/trace-event-python.c    |    2 +-
 tools/perf/util/symbol.c                           |    2 +-
 6 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 1168442..b811924 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1138,7 +1138,7 @@ fallback:
 
 	if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
 	    !dso__is_kcore(dso)) {
-		char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
+		char bf[SBUILD_ID_SIZE + 15] = " with build id ";
 		char *build_id_msg = NULL;
 
 		if (dso->annotate_warned)
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 8e639543..3357479 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -38,7 +38,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
 				   enum dso_binary_type type,
 				   char *root_dir, char *filename, size_t size)
 {
-	char build_id_hex[BUILD_ID_SIZE * 2 + 1];
+	char build_id_hex[SBUILD_ID_SIZE];
 	int ret = 0;
 	size_t len;
 
@@ -1301,7 +1301,7 @@ size_t __dsos__fprintf(struct list_head *head, FILE *fp)
 
 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
 {
-	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+	char sbuild_id[SBUILD_ID_SIZE];
 
 	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
 	return fprintf(fp, "%s", sbuild_id);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c6000d4..08852dd 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1474,7 +1474,7 @@ static int __event_process_build_id(struct build_id_event *bev,
 
 	dso = machine__findnew_dso(machine, filename);
 	if (dso != NULL) {
-		char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+		char sbuild_id[SBUILD_ID_SIZE];
 
 		dso__set_build_id(dso, &bev->build_id);
 
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 02c3186..b19bcd3 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -289,7 +289,7 @@ int map__load(struct map *map, symbol_filter_t filter)
 	nr = dso__load(map->dso, map, filter);
 	if (nr < 0) {
 		if (map->dso->has_build_id) {
-			char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+			char sbuild_id[SBUILD_ID_SIZE];
 
 			build_id__sprintf(map->dso->build_id,
 					  sizeof(map->dso->build_id),
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 73ee12d..ff13470 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -618,7 +618,7 @@ static int python_export_dso(struct db_export *dbe, struct dso *dso,
 			     struct machine *machine)
 {
 	struct tables *tables = container_of(dbe, struct tables, dbe);
-	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+	char sbuild_id[SBUILD_ID_SIZE];
 	PyObject *t;
 
 	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 49caa91..18d81c1 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1630,7 +1630,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
 static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 {
 	u8 host_build_id[BUILD_ID_SIZE];
-	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+	char sbuild_id[SBUILD_ID_SIZE];
 	bool is_host = false;
 	char path[PATH_MAX];
 

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 05/21] perf symbol: Use lsdir for search in kcore cache directory
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (3 preceding siblings ...)
  2016-05-11 13:51 ` [PATCH perf/core v7 04/21] perf: Use SBUILD_ID_SIZE macro instead of BUILD_ID_SIZE macro Masami Hiramatsu
@ 2016-05-11 13:52 ` Masami Hiramatsu
  2016-05-11 15:49   ` Arnaldo Carvalho de Melo
  2016-05-12 10:26   ` [tip:perf/core] perf symbols: Use lsdir() for the " tip-bot for Masami Hiramatsu
  2016-05-11 13:52 ` [PATCH perf/core v7 06/21] perf-buildid-cache: Use lsdir for looking up buildid caches Masami Hiramatsu
                   ` (15 subsequent siblings)
  20 siblings, 2 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:52 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

Use lsdir for search in kcore cache directory. This also
avoid checking hidden dot directory entries, because
kcore cache directories must always have the name from
timestamps when taking the kcore snapshots, and it never
start with dot.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/util/symbol.c |   26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 18d81c1..e112bbd 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1596,25 +1596,27 @@ out:
 	return err;
 }
 
+static bool visible_dir_filter(const char *name, struct dirent *d)
+{
+	if (d->d_type != DT_DIR)
+		return false;
+	return lsdir_no_dot_filter(name, d);
+}
+
 static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
 {
 	char kallsyms_filename[PATH_MAX];
-	struct dirent *dent;
 	int ret = -1;
-	DIR *d;
+	struct strlist *dirs;
+	struct str_node *nd;
 
-	d = opendir(dir);
-	if (!d)
+	dirs = lsdir(dir, visible_dir_filter);
+	if (!dirs)
 		return -1;
 
-	while (1) {
-		dent = readdir(d);
-		if (!dent)
-			break;
-		if (dent->d_type != DT_DIR)
-			continue;
+	strlist__for_each(nd, dirs) {
 		scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
-			  "%s/%s/kallsyms", dir, dent->d_name);
+			  "%s/%s/kallsyms", dir, nd->s);
 		if (!validate_kcore_addresses(kallsyms_filename, map)) {
 			strlcpy(dir, kallsyms_filename, dir_sz);
 			ret = 0;
@@ -1622,7 +1624,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
 		}
 	}
 
-	closedir(d);
+	strlist__delete(dirs);
 
 	return ret;
 }

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 06/21] perf-buildid-cache: Use lsdir for looking up buildid caches
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (4 preceding siblings ...)
  2016-05-11 13:52 ` [PATCH perf/core v7 05/21] perf symbol: Use lsdir for search in kcore cache directory Masami Hiramatsu
@ 2016-05-11 13:52 ` Masami Hiramatsu
  2016-05-11 15:50   ` Arnaldo Carvalho de Melo
  2016-05-12 10:26   ` [tip:perf/core] perf buildid-cache: Use lsdir() " tip-bot for Masami Hiramatsu
  2016-05-11 13:52 ` [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms Masami Hiramatsu
                   ` (14 subsequent siblings)
  20 siblings, 2 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:52 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

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>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v7:
  - Remove unneeded local strlist.
---
 tools/perf/util/build-id.c |   30 ++++--------------------------
 1 file changed, 4 insertions(+), 26 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 53df9aa..2cb6454 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -369,39 +369,17 @@ static char *build_id_cache__dirname_from_path(const char *name,
 int build_id_cache__list_build_ids(const char *pathname,
 				   struct strlist **result)
 {
-	struct strlist *list;
 	char *dir_name;
-	DIR *dir;
-	struct dirent *d;
 	int ret = 0;
 
-	list = strlist__new(NULL, NULL);
 	dir_name = build_id_cache__dirname_from_path(pathname, false, false);
-	if (!list || !dir_name) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!dir_name)
+		return -ENOMEM;
 
-	/* List up all dirents */
-	dir = opendir(dir_name);
-	if (!dir) {
+	*result = lsdir(dir_name, lsdir_no_dot_filter);
+	if (!*result)
 		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:
 	free(dir_name);
-	if (ret)
-		strlist__delete(list);
-	else
-		*result = list;
 
 	return ret;
 }

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (5 preceding siblings ...)
  2016-05-11 13:52 ` [PATCH perf/core v7 06/21] perf-buildid-cache: Use lsdir for looking up buildid caches Masami Hiramatsu
@ 2016-05-11 13:52 ` Masami Hiramatsu
  2016-05-11 15:55   ` Arnaldo Carvalho de Melo
  2016-05-11 13:52 ` [PATCH perf/core v7 08/21] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid Masami Hiramatsu
                   ` (13 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:52 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

Cleanup the code flow of dso__find_kallsyms() to remove
redundant checking code and add some comment for readability.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/util/symbol.c |   60 +++++++++++++++++++++-------------------------
 1 file changed, 27 insertions(+), 33 deletions(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e112bbd..b2b06b7 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1629,6 +1629,15 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
 	return ret;
 }
 
+static bool filename__readable(const char *file)
+{
+	int fd = open(file, O_RDONLY);
+	if (fd < 0)
+		return false;
+	close(fd);
+	return true;
+}
+
 static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 {
 	u8 host_build_id[BUILD_ID_SIZE];
@@ -1648,45 +1657,33 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 				 sizeof(host_build_id)) == 0)
 		is_host = dso__build_id_equal(dso, host_build_id);
 
-	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
-
-	scnprintf(path, sizeof(path), "%s/%s/%s", buildid_dir,
-		  DSO__NAME_KCORE, sbuild_id);
-
-	/* Use /proc/kallsyms if possible */
+	/* Try a fast path for /proc/kallsyms if possible */
 	if (is_host) {
-		DIR *d;
-		int fd;
-
-		/* If no cached kcore go with /proc/kallsyms */
-		d = opendir(path);
-		if (!d)
-			goto proc_kallsyms;
-		closedir(d);
-
 		/*
-		 * Do not check the build-id cache, until we know we cannot use
-		 * /proc/kcore.
+		 * Do not check the build-id cache, unless we know we cannot use
+		 * /proc/kcore or module maps don't match to /proc/kallsyms.
 		 */
-		fd = open("/proc/kcore", O_RDONLY);
-		if (fd != -1) {
-			close(fd);
-			/* If module maps match go with /proc/kallsyms */
-			if (!validate_kcore_addresses("/proc/kallsyms", map))
-				goto proc_kallsyms;
-		}
-
-		/* Find kallsyms in build-id cache with kcore */
-		if (!find_matching_kcore(map, path, sizeof(path)))
-			return strdup(path);
-
-		goto proc_kallsyms;
+		if (filename__readable("/proc/kcore") &&
+		    !validate_kcore_addresses("/proc/kallsyms", map))
+			goto proc_kallsyms;
 	}
 
+	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
+
 	/* Find kallsyms in build-id cache with kcore */
+	scnprintf(path, sizeof(path), "%s/%s/%s",
+		  buildid_dir, DSO__NAME_KCORE, sbuild_id);
+
 	if (!find_matching_kcore(map, path, sizeof(path)))
 		return strdup(path);
 
+	/* Use current /proc/kallsyms if possible */
+	if (is_host) {
+proc_kallsyms:
+		return strdup("/proc/kallsyms");
+	}
+
+	/* Finally, find a cache of kallsyms */
 	scnprintf(path, sizeof(path), "%s/%s/%s",
 		  buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
 
@@ -1697,9 +1694,6 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 	}
 
 	return strdup(path);
-
-proc_kallsyms:
-	return strdup("/proc/kallsyms");
 }
 
 static int dso__load_kernel_sym(struct dso *dso, struct map *map,

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 08/21] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (6 preceding siblings ...)
  2016-05-11 13:52 ` [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms Masami Hiramatsu
@ 2016-05-11 13:52 ` Masami Hiramatsu
  2016-05-11 13:52 ` [PATCH perf/core v7 09/21] perf probe: Add --cache option to cache the probe definitions Masami Hiramatsu
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:52 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Use path/to/bin/buildid/elf instead of path/to/bin/buildid
to store corresponding elf binary.
This also stores vdso in buildid/vdso, kallsyms in buildid/kallsyms.

Note that the existing caches are not updated until user adds
or updates the cache. Anyway, if there is the old style build-id
cache it falls back to use it. (IOW, it is backward compatible)

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v7:
  - Move kallsyms buildid related code into build-id.c
    (as build_id_cache__kallsyms_path).
 Changes in v6:
  - Replace local __is_regular_file with is_regular_file in util.c.
    (Thank you Namhyung!)
  - Fix dso__build_id_is_kmod() to check symlink in buildid cache correctly.
 Changes in v5:
  - Support old style buildid caches.
---
 tools/perf/util/build-id.c |  114 ++++++++++++++++++++++++++++++++++----------
 tools/perf/util/build-id.h |    2 +
 tools/perf/util/dso.h      |    5 ++
 tools/perf/util/symbol.c   |    5 --
 4 files changed, 95 insertions(+), 31 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 2cb6454..39d1667 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -144,7 +144,32 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
 	return ret;
 }
 
-static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
+char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
+				    size_t size)
+{
+	bool is_alloc = !!bf;
+	bool retry_old = true;
+
+	asnprintf(&bf, size, "%s/%s/%s/kallsyms",
+		  buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
+retry:
+	if (!access(bf, F_OK))
+		return bf;
+	if (is_alloc)
+		free(bf);
+	if (retry_old) {
+		/* Try old style kallsyms cache */
+		asnprintf(&bf, size, "%s/%s/%s",
+			  buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
+		retry_old = false;
+		goto retry;
+	}
+
+	return NULL;
+}
+
+static 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,
@@ -154,23 +179,52 @@ static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
 	return bf;
 }
 
+static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
+{
+	return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
+}
+
 char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
 {
-	char build_id_hex[SBUILD_ID_SIZE];
+	bool is_kallsyms = dso__is_kallsyms((struct dso *)dso);
+	bool is_vdso = dso__is_vdso((struct dso *)dso);
+	char sbuild_id[SBUILD_ID_SIZE];
+	char *linkname;
+	bool alloc = (bf == NULL);
+	int ret;
 
 	if (!dso->has_build_id)
 		return NULL;
 
-	build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
-	return build_id__filename(build_id_hex, bf, size);
+	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
+	linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
+	if (!linkname)
+		return NULL;
+
+	/* Check if old style build_id cache */
+	if (is_regular_file(linkname))
+		ret = asnprintf(&bf, size, "%s", linkname);
+	else
+		ret = asnprintf(&bf, size, "%s/%s", linkname,
+			 build_id_cache__basename(is_kallsyms, is_vdso));
+	if (ret < 0 || (!alloc && size < (unsigned int)ret))
+		bf = NULL;
+	free(linkname);
+
+	return bf;
 }
 
 bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
 {
-	char *id_name, *ch;
+	char *id_name = NULL, *ch;
 	struct stat sb;
+	char sbuild_id[SBUILD_ID_SIZE];
+
+	if (!dso->has_build_id)
+		goto err;
 
-	id_name = dso__build_id_filename(dso, bf, size);
+	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
+	id_name = build_id_cache__linkname(sbuild_id, NULL, 0);
 	if (!id_name)
 		goto err;
 	if (access(id_name, F_OK))
@@ -194,18 +248,14 @@ bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
 	if (ch - 3 < bf)
 		goto err;
 
+	free(id_name);
 	return strncmp(".ko", ch - 3, 3) == 0;
 err:
-	/*
-	 * If dso__build_id_filename work, get id_name again,
-	 * because id_name points to bf and is broken.
-	 */
-	if (id_name)
-		id_name = dso__build_id_filename(dso, bf, size);
 	pr_err("Invalid build id: %s\n", id_name ? :
 					 dso->long_name ? :
 					 dso->short_name ? :
 					 "[unknown]");
+	free(id_name);
 	return false;
 }
 
@@ -341,7 +391,8 @@ void disable_buildid_cache(void)
 }
 
 static char *build_id_cache__dirname_from_path(const char *name,
-					       bool is_kallsyms, bool is_vdso)
+					       bool is_kallsyms, bool is_vdso,
+					       const char *sbuild_id)
 {
 	const char *realname = name;
 	char *filename;
@@ -356,8 +407,8 @@ static char *build_id_cache__dirname_from_path(const char *name,
 	else
 		realname = DSO__NAME_KALLSYMS;
 
-	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
-		     realname) < 0)
+	if (asprintf(&filename, "%s%s%s%s%s", buildid_dir, slash ? "/" : "",
+		     realname, sbuild_id ? "/" : "", sbuild_id ?: "") < 0)
 		filename = NULL;
 
 	if (!slash)
@@ -372,7 +423,8 @@ int build_id_cache__list_build_ids(const char *pathname,
 	char *dir_name;
 	int ret = 0;
 
-	dir_name = build_id_cache__dirname_from_path(pathname, false, false);
+	dir_name = build_id_cache__dirname_from_path(pathname, false, false,
+						     NULL);
 	if (!dir_name)
 		return -ENOMEM;
 
@@ -389,7 +441,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 {
 	const size_t size = PATH_MAX;
 	char *realname = NULL, *filename = NULL, *dir_name = NULL,
-	     *linkname = zalloc(size), *targetname, *tmp;
+	     *linkname = zalloc(size), *tmp;
 	int err = -1;
 
 	if (!is_kallsyms) {
@@ -398,14 +450,22 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 			goto out_free;
 	}
 
-	dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
+	dir_name = build_id_cache__dirname_from_path(name, is_kallsyms,
+						     is_vdso, sbuild_id);
 	if (!dir_name)
 		goto out_free;
 
+	/* Remove old style build-id cache */
+	if (is_regular_file(dir_name))
+		if (unlink(dir_name))
+			goto out_free;
+
 	if (mkdir_p(dir_name, 0755))
 		goto out_free;
 
-	if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
+	/* Save the allocated buildid dirname */
+	if (asprintf(&filename, "%s/%s", dir_name,
+		     build_id_cache__basename(is_kallsyms, is_vdso)) < 0) {
 		filename = NULL;
 		goto out_free;
 	}
@@ -419,7 +479,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 			goto out_free;
 	}
 
-	if (!build_id__filename(sbuild_id, linkname, size))
+	if (!build_id_cache__linkname(sbuild_id, linkname, size))
 		goto out_free;
 	tmp = strrchr(linkname, '/');
 	*tmp = '\0';
@@ -428,10 +488,10 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 		goto out_free;
 
 	*tmp = '/';
-	targetname = filename + strlen(buildid_dir) - 5;
-	memcpy(targetname, "../..", 5);
+	tmp = dir_name + strlen(buildid_dir) - 5;
+	memcpy(tmp, "../..", 5);
 
-	if (symlink(targetname, linkname) == 0)
+	if (symlink(tmp, linkname) == 0)
 		err = 0;
 out_free:
 	if (!is_kallsyms)
@@ -456,7 +516,7 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
 bool build_id_cache__cached(const char *sbuild_id)
 {
 	bool ret = false;
-	char *filename = build_id__filename(sbuild_id, NULL, 0);
+	char *filename = build_id_cache__linkname(sbuild_id, NULL, 0);
 
 	if (filename && !access(filename, F_OK))
 		ret = true;
@@ -475,7 +535,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
 	if (filename == NULL || linkname == NULL)
 		goto out_free;
 
-	if (!build_id__filename(sbuild_id, linkname, size))
+	if (!build_id_cache__linkname(sbuild_id, linkname, size))
 		goto out_free;
 
 	if (access(linkname, F_OK))
@@ -493,7 +553,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
 	tmp = strrchr(linkname, '/') + 1;
 	snprintf(tmp, size - (tmp - linkname), "%s", filename);
 
-	if (unlink(linkname))
+	if (rm_rf(linkname))
 		goto out_free;
 
 	err = 0;
@@ -505,7 +565,7 @@ out_free:
 
 static int dso__cache_build_id(struct dso *dso, struct machine *machine)
 {
-	bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
+	bool is_kallsyms = dso__is_kallsyms(dso);
 	bool is_vdso = dso__is_vdso(dso);
 	const char *name = dso->long_name;
 	char nm[PATH_MAX];
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 64af3e2..e5435f4 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -14,6 +14,8 @@ struct dso;
 int build_id__sprintf(const u8 *build_id, int len, char *bf);
 int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
 int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
+char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
+				    size_t size);
 
 char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
 bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 0953280..76d79d0 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -349,6 +349,11 @@ static inline bool dso__is_kcore(struct dso *dso)
 	       dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE;
 }
 
+static inline bool dso__is_kallsyms(struct dso *dso)
+{
+	return dso->kernel && dso->long_name[0] != '/';
+}
+
 void dso__free_a2l(struct dso *dso);
 
 enum dso_type dso__type(struct dso *dso, struct machine *machine);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b2b06b7..df3d0d9 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1684,10 +1684,7 @@ proc_kallsyms:
 	}
 
 	/* Finally, find a cache of kallsyms */
-	scnprintf(path, sizeof(path), "%s/%s/%s",
-		  buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
-
-	if (access(path, F_OK)) {
+	if (!build_id_cache__kallsyms_path(sbuild_id, path, sizeof(path))) {
 		pr_err("No kallsyms or vmlinux with build-id %s was found\n",
 		       sbuild_id);
 		return NULL;

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 09/21] perf probe: Add --cache option to cache the probe definitions
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (7 preceding siblings ...)
  2016-05-11 13:52 ` [PATCH perf/core v7 08/21] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid Masami Hiramatsu
@ 2016-05-11 13:52 ` Masami Hiramatsu
  2016-05-11 13:52 ` [PATCH perf/core v7 10/21] perf probe: Use cache entry if possible Masami Hiramatsu
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:52 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Add --cache option to cache the probe definitions. This
just saves the result of the dwarf analysis to probe cache.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v6:
  - Remove unneeded O_APPEND from open(). (Thanks Namhyung!)
  - Fix to check the return value of probe_cache_entry__new and strdup.(ditto)
 Changes in v5:
  - Move probe_cache* definitions. (code cleanup)

 Changes in v4:
  - Remove cache saving failure message.
---
 tools/perf/Documentation/perf-probe.txt |    4 
 tools/perf/builtin-probe.c              |    1 
 tools/perf/util/build-id.c              |   12 +
 tools/perf/util/build-id.h              |    2 
 tools/perf/util/probe-event.c           |  124 +++++++++++--
 tools/perf/util/probe-event.h           |    5 +
 tools/perf/util/probe-file.c            |  307 +++++++++++++++++++++++++++++++
 tools/perf/util/probe-file.h            |   19 ++
 8 files changed, 447 insertions(+), 27 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 3a8a9ba..947db6f 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -109,6 +109,10 @@ OPTIONS
 	Dry run. With this option, --add and --del doesn't execute actual
 	adding and removal operations.
 
+--cache::
+	Cache the probes (with --add option). Any events which successfully added
+	are also stored in the cache file.
+
 --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 9af859b..6d7ab431 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -512,6 +512,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 		    "Enable symbol demangling"),
 	OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
 		    "Enable kernel symbol demangling"),
+	OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
 	OPT_END()
 	};
 	int ret;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 39d1667..9b8edf3 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -390,9 +390,8 @@ void disable_buildid_cache(void)
 	no_buildid_cache = true;
 }
 
-static char *build_id_cache__dirname_from_path(const char *name,
-					       bool is_kallsyms, bool is_vdso,
-					       const char *sbuild_id)
+char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
+			       bool is_kallsyms, bool is_vdso)
 {
 	const char *realname = name;
 	char *filename;
@@ -423,8 +422,7 @@ int build_id_cache__list_build_ids(const char *pathname,
 	char *dir_name;
 	int ret = 0;
 
-	dir_name = build_id_cache__dirname_from_path(pathname, false, false,
-						     NULL);
+	dir_name = build_id_cache__cachedir(NULL, pathname, false, false);
 	if (!dir_name)
 		return -ENOMEM;
 
@@ -450,8 +448,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 			goto out_free;
 	}
 
-	dir_name = build_id_cache__dirname_from_path(name, is_kallsyms,
-						     is_vdso, sbuild_id);
+	dir_name = build_id_cache__cachedir(sbuild_id, name,
+					    is_kallsyms, is_vdso);
 	if (!dir_name)
 		goto out_free;
 
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index e5435f4..d8c7f2f 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -30,6 +30,8 @@ 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__cachedir(const char *sbuild_id, const char *name,
+			       bool is_kallsyms, bool is_vdso);
 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 74401a2..854885b 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -67,7 +67,6 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
 	return ret;
 }
 
-static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
 static struct machine *host_machine;
 
 /* Initialize symbol maps and path of vmlinux/modules */
@@ -1712,7 +1711,7 @@ out:
 }
 
 /* Compose only probe point (not argument) */
-static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
+char *synthesize_perf_probe_point(struct perf_probe_point *pp)
 {
 	struct strbuf buf;
 	char *tmp, *ret = NULL;
@@ -1751,30 +1750,36 @@ out:
 	return ret;
 }
 
-#if 0
 char *synthesize_perf_probe_command(struct perf_probe_event *pev)
 {
-	char *buf;
-	int i, len, ret;
+	struct strbuf buf;
+	char *tmp, *ret = NULL;
+	int i;
 
-	buf = synthesize_perf_probe_point(&pev->point);
-	if (!buf)
+	if (strbuf_init(&buf, 64))
 		return NULL;
+	if (pev->event)
+		if (strbuf_addf(&buf, "%s:%s=", pev->group ?: PERFPROBE_GROUP,
+				pev->event) < 0)
+			goto out;
+
+	tmp = synthesize_perf_probe_point(&pev->point);
+	if (!tmp || strbuf_addstr(&buf, tmp) < 0)
+		goto out;
+	free(tmp);
 
-	len = strlen(buf);
 	for (i = 0; i < pev->nargs; i++) {
-		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
-				 pev->args[i].name);
-		if (ret <= 0) {
-			free(buf);
-			return NULL;
-		}
-		len += ret;
+		tmp = synthesize_perf_probe_arg(pev->args + i);
+		if (!tmp || strbuf_addf(&buf, " %s", tmp) < 0)
+			goto out;
+		free(tmp);
 	}
 
-	return buf;
+	ret = strbuf_detach(&buf, NULL);
+out:
+	strbuf_release(&buf);
+	return ret;
 }
-#endif
 
 static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
 					    struct strbuf *buf, int depth)
@@ -2026,6 +2031,79 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
 	memset(pev, 0, sizeof(*pev));
 }
 
+#define strdup_or_goto(str, label)	\
+({ char *__p = NULL; if (str && !(__p = strdup(str))) goto label; __p; })
+
+static int perf_probe_point__copy(struct perf_probe_point *dst,
+				  struct perf_probe_point *src)
+{
+	dst->file = strdup_or_goto(src->file, out_err);
+	dst->function = strdup_or_goto(src->function, out_err);
+	dst->lazy_line = strdup_or_goto(src->lazy_line, out_err);
+	dst->line = src->line;
+	dst->retprobe = src->retprobe;
+	dst->offset = src->offset;
+	return 0;
+
+out_err:
+	clear_perf_probe_point(dst);
+	return -ENOMEM;
+}
+
+static int perf_probe_arg__copy(struct perf_probe_arg *dst,
+				struct perf_probe_arg *src)
+{
+	struct perf_probe_arg_field *field, **ppfield;
+
+	dst->name = strdup_or_goto(src->name, out_err);
+	dst->var = strdup_or_goto(src->var, out_err);
+	dst->type = strdup_or_goto(src->type, out_err);
+
+	field = src->field;
+	ppfield = &(dst->field);
+	while (field) {
+		*ppfield = zalloc(sizeof(*field));
+		if (!*ppfield)
+			goto out_err;
+		(*ppfield)->name = strdup_or_goto(field->name, out_err);
+		(*ppfield)->index = field->index;
+		(*ppfield)->ref = field->ref;
+		field = field->next;
+		ppfield = &((*ppfield)->next);
+	}
+	return 0;
+out_err:
+	return -ENOMEM;
+}
+
+int perf_probe_event__copy(struct perf_probe_event *dst,
+			   struct perf_probe_event *src)
+{
+	int i;
+
+	dst->event = strdup_or_goto(src->event, out_err);
+	dst->group = strdup_or_goto(src->group, out_err);
+	dst->target = strdup_or_goto(src->target, out_err);
+	dst->uprobes = src->uprobes;
+
+	if (perf_probe_point__copy(&dst->point, &src->point) < 0)
+		goto out_err;
+
+	dst->args = zalloc(sizeof(struct perf_probe_arg) * src->nargs);
+	if (!dst->args)
+		goto out_err;
+	dst->nargs = src->nargs;
+
+	for (i = 0; i < src->nargs; i++)
+		if (perf_probe_arg__copy(&dst->args[i], &src->args[i]) < 0)
+			goto out_err;
+	return 0;
+
+out_err:
+	clear_perf_probe_event(dst);
+	return -ENOMEM;
+}
+
 void clear_probe_trace_event(struct probe_trace_event *tev)
 {
 	struct probe_trace_arg_ref *ref, *next;
@@ -2432,6 +2510,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 {
 	int i, fd, ret;
 	struct probe_trace_event *tev = NULL;
+	struct probe_cache *cache = NULL;
 	struct strlist *namelist;
 
 	fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0));
@@ -2473,6 +2552,14 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 	}
 	if (ret == -EINVAL && pev->uprobes)
 		warn_uprobe_event_compat(tev);
+	if (ret == 0 && probe_conf.cache) {
+		cache = probe_cache__new(pev->target);
+		if (cache) {
+			probe_cache__add_entry(cache, pev, tevs, ntevs);
+			probe_cache__commit(cache);
+			probe_cache__delete(cache);
+		}
+	}
 
 	strlist__delete(namelist);
 close_out:
@@ -2501,9 +2588,6 @@ static int find_probe_functions(struct map *map, char *name,
 	return found;
 }
 
-#define strdup_or_goto(str, label)	\
-	({ char *__p = strdup(str); if (!__p) goto label; __p; })
-
 void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
 				struct probe_trace_event *tev __maybe_unused,
 				struct map *map __maybe_unused,
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 5a27eb4..432b690 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -12,6 +12,7 @@ struct probe_conf {
 	bool	show_location_range;
 	bool	force_add;
 	bool	no_inlines;
+	bool	cache;
 	int	max_probes;
 };
 extern struct probe_conf probe_conf;
@@ -121,6 +122,10 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev);
 char *synthesize_perf_probe_command(struct perf_probe_event *pev);
 char *synthesize_probe_trace_command(struct probe_trace_event *tev);
 char *synthesize_perf_probe_arg(struct perf_probe_arg *pa);
+char *synthesize_perf_probe_point(struct perf_probe_point *pp);
+
+int perf_probe_event__copy(struct perf_probe_event *dst,
+			   struct perf_probe_event *src);
 
 /* Check the perf_probe_event needs debuginfo */
 bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 3fe6214..689d874 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -14,6 +14,7 @@
  * GNU General Public License for more details.
  *
  */
+#include <sys/uio.h>
 #include "util.h"
 #include "event.h"
 #include "strlist.h"
@@ -324,3 +325,309 @@ int probe_file__del_events(int fd, struct strfilter *filter)
 
 	return ret;
 }
+
+static void probe_cache_entry__delete(struct probe_cache_entry *node)
+{
+	if (!list_empty(&node->list))
+		list_del(&node->list);
+	if (node->tevlist)
+		strlist__delete(node->tevlist);
+	clear_perf_probe_event(&node->pev);
+	free(node->spev);
+	free(node);
+}
+
+static struct probe_cache_entry *
+probe_cache_entry__new(struct perf_probe_event *pev)
+{
+	struct probe_cache_entry *ret = zalloc(sizeof(*ret));
+
+	if (ret) {
+		INIT_LIST_HEAD(&ret->list);
+		ret->tevlist = strlist__new(NULL, NULL);
+		if (!ret->tevlist)
+			zfree(&ret);
+		if (ret && pev) {
+			ret->spev = synthesize_perf_probe_command(pev);
+			if (!ret->spev ||
+			    perf_probe_event__copy(&ret->pev, pev) < 0) {
+				probe_cache_entry__delete(ret);
+				return NULL;
+			}
+		}
+	}
+
+	return ret;
+}
+
+/* For the kernel probe caches, pass target = NULL */
+static int probe_cache__open(struct probe_cache *pcache, const char *target)
+{
+	char cpath[PATH_MAX];
+	char sbuildid[SBUILD_ID_SIZE];
+	char *dir_name;
+	bool is_kallsyms = !target;
+	int ret, fd;
+
+	if (target)
+		ret = filename__sprintf_build_id(target, sbuildid);
+	else {
+		target = DSO__NAME_KALLSYMS;
+		ret = sysfs__sprintf_build_id("/", sbuildid);
+	}
+	if (ret < 0) {
+		pr_debug("Failed to get build-id from %s.\n", target);
+		return ret;
+	}
+
+	/* If we have no buildid cache, make it */
+	if (!build_id_cache__cached(sbuildid)) {
+		ret = build_id_cache__add_s(sbuildid, target,
+					    is_kallsyms, NULL);
+		if (ret < 0) {
+			pr_debug("Failed to add build-id cache: %s\n", target);
+			return ret;
+		}
+	}
+
+	dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms,
+					    false);
+	if (!dir_name)
+		return -ENOMEM;
+
+	snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
+	fd = open(cpath, O_CREAT | O_RDWR, 0644);
+	if (fd < 0)
+		pr_debug("Failed to open cache(%d): %s\n", fd, cpath);
+	free(dir_name);
+	pcache->fd = fd;
+
+	return fd;
+}
+
+static int probe_cache__load(struct probe_cache *pcache)
+{
+	struct probe_cache_entry *entry = NULL;
+	char buf[MAX_CMDLEN], *p;
+	int ret = 0;
+	FILE *fp;
+
+	fp = fdopen(dup(pcache->fd), "r");
+	while (!feof(fp)) {
+		if (!fgets(buf, MAX_CMDLEN, fp))
+			break;
+		p = strchr(buf, '\n');
+		if (p)
+			*p = '\0';
+		if (buf[0] == '#') {	/* #perf_probe_event */
+			entry = probe_cache_entry__new(NULL);
+			if (!entry) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			entry->spev = strdup(buf + 1);
+			if (entry->spev)
+				ret = parse_perf_probe_command(buf + 1,
+								&entry->pev);
+			else
+				ret = -ENOMEM;
+			if (ret < 0) {
+				probe_cache_entry__delete(entry);
+				goto out;
+			}
+			list_add_tail(&entry->list, &pcache->list);
+		} else {	/* trace_probe_event */
+			if (!entry) {
+				ret = -EINVAL;
+				goto out;
+			}
+			strlist__add(entry->tevlist, buf);
+		}
+	}
+out:
+	fclose(fp);
+	return ret;
+}
+
+static struct probe_cache *probe_cache__alloc(void)
+{
+	struct probe_cache *ret = zalloc(sizeof(*ret));
+
+	if (ret) {
+		INIT_LIST_HEAD(&ret->list);
+		ret->fd = -EINVAL;
+	}
+	return ret;
+}
+
+void probe_cache__delete(struct probe_cache *pcache)
+{
+	struct probe_cache_entry *entry;
+
+	if (!pcache)
+		return;
+
+	while (!list_empty(&pcache->list)) {
+		entry = list_first_entry(&pcache->list, typeof(*entry), list);
+		probe_cache_entry__delete(entry);
+	}
+	if (pcache->fd > 0)
+		close(pcache->fd);
+	free(pcache);
+}
+
+struct probe_cache *probe_cache__new(const char *target)
+{
+	struct probe_cache *pcache = probe_cache__alloc();
+	int ret;
+
+	if (!pcache)
+		return NULL;
+
+	ret = probe_cache__open(pcache, target);
+	if (ret < 0) {
+		pr_debug("Cache open error: %d\n", ret);
+		goto out_err;
+	}
+
+	ret = probe_cache__load(pcache);
+	if (ret < 0) {
+		pr_debug("Cache read error: %d\n", ret);
+		goto out_err;
+	}
+
+	return pcache;
+
+out_err:
+	probe_cache__delete(pcache);
+	return NULL;
+}
+
+static bool streql(const char *a, const char *b)
+{
+	if (a == b)
+		return true;
+
+	if (!a || !b)
+		return false;
+
+	return !strcmp(a, b);
+}
+
+static struct probe_cache_entry *
+probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
+{
+	struct probe_cache_entry *entry = NULL;
+	char *cmd = NULL;
+
+	cmd = synthesize_perf_probe_command(pev);
+	if (!cmd)
+		return NULL;
+
+	list_for_each_entry(entry, &pcache->list, list) {
+		/* Hit if same event name or same command-string */
+		if ((pev->event &&
+		     (streql(entry->pev.group, pev->group) &&
+		      streql(entry->pev.event, pev->event))) ||
+		    (!strcmp(entry->spev, cmd)))
+			goto found;
+	}
+	entry = NULL;
+
+found:
+	free(cmd);
+	return entry;
+}
+
+int probe_cache__add_entry(struct probe_cache *pcache,
+			   struct perf_probe_event *pev,
+			   struct probe_trace_event *tevs, int ntevs)
+{
+	struct probe_cache_entry *entry = NULL;
+	char *command;
+	int i, ret = 0;
+
+	if (!pcache || !pev || !tevs || ntevs <= 0) {
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	/* Remove old cache entry */
+	entry = probe_cache__find(pcache, pev);
+	if (entry)
+		probe_cache_entry__delete(entry);
+
+	ret = -ENOMEM;
+	entry = probe_cache_entry__new(pev);
+	if (!entry)
+		goto out_err;
+
+	for (i = 0; i < ntevs; i++) {
+		if (!tevs[i].point.symbol)
+			continue;
+
+		command = synthesize_probe_trace_command(&tevs[i]);
+		if (!command)
+			goto out_err;
+		strlist__add(entry->tevlist, command);
+		free(command);
+	}
+	list_add_tail(&entry->list, &pcache->list);
+	pr_debug("Added probe cache: %d\n", ntevs);
+	return 0;
+
+out_err:
+	pr_debug("Failed to add probe caches\n");
+	if (entry)
+		probe_cache_entry__delete(entry);
+	return ret;
+}
+
+static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
+{
+	struct str_node *snode;
+	struct iovec iov[3];
+	int ret;
+
+	pr_debug("Writing cache: #%s\n", entry->spev);
+	iov[0].iov_base = (void *)"#"; 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);
+	if (ret < 0)
+		return ret;
+
+	strlist__for_each(snode, entry->tevlist) {
+		iov[0].iov_base = (void *)snode->s;
+		iov[0].iov_len = strlen(snode->s);
+		iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1;
+		ret = writev(fd, iov, 2);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+int probe_cache__commit(struct probe_cache *pcache)
+{
+	struct probe_cache_entry *entry;
+	int ret = 0;
+
+	/* TBD: if we do not update existing entries, skip it */
+	ret = lseek(pcache->fd, 0, SEEK_SET);
+	if (ret < 0)
+		goto out;
+
+	ret = ftruncate(pcache->fd, 0);
+	if (ret < 0)
+		goto out;
+
+	list_for_each_entry(entry, &pcache->list, list) {
+		ret = probe_cache_entry__write(entry, pcache->fd);
+		pr_debug("Cache committed: %d\n", ret);
+		if (ret < 0)
+			break;
+	}
+out:
+	return ret;
+}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 18ac9cf..d2b8791d 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -5,6 +5,19 @@
 #include "strfilter.h"
 #include "probe-event.h"
 
+/* Cache of probe definitions */
+struct probe_cache_entry {
+	struct list_head	list;
+	struct perf_probe_event pev;
+	char			*spev;
+	struct strlist		*tevlist;
+};
+
+struct probe_cache {
+	int	fd;
+	struct list_head list;
+};
+
 #define PF_FL_UPROBE	1
 #define PF_FL_RW	2
 
@@ -18,5 +31,11 @@ int probe_file__get_events(int fd, struct strfilter *filter,
 				  struct strlist *plist);
 int probe_file__del_strlist(int fd, struct strlist *namelist);
 
+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__commit(struct probe_cache *pcache);
+void probe_cache__delete(struct probe_cache *pcache);
 
 #endif

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 10/21] perf probe: Use cache entry if possible
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (8 preceding siblings ...)
  2016-05-11 13:52 ` [PATCH perf/core v7 09/21] perf probe: Add --cache option to cache the probe definitions Masami Hiramatsu
@ 2016-05-11 13:52 ` Masami Hiramatsu
  2016-05-11 13:53 ` [PATCH perf/core v7 11/21] perf probe: Show all cached probes Masami Hiramatsu
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:52 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

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>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v6:
  - Remove fallback lookup routine by using function name
    as cached event name, because it should be done by following
    patch which supports %cached-event.
---
 tools/perf/util/probe-event.c |   65 ++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/probe-file.c  |   20 ++++++++++++-
 tools/perf/util/probe-file.h  |    5 +++
 3 files changed, 86 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 854885b..acc8341 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2472,17 +2472,24 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 	char buf[64];
 	int ret;
 
+	/* If probe_event or trace_event already have the name, reuse it */
 	if (pev->event)
 		event = pev->event;
-	else
+	else if (tev->event)
+		event = tev->event;
+	else {
+		/* Or generate new one from probe point */
 		if (pev->point.function &&
 			(strncmp(pev->point.function, "0x", 2) != 0) &&
 			!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;
 
@@ -2529,7 +2536,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) */
@@ -2842,6 +2849,55 @@ errout:
 
 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) {
+		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)
 {
@@ -2864,6 +2920,11 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 	if (ret > 0)
 		return ret;
 
+	/* 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 689d874..f30f609 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -514,7 +514,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;
@@ -539,6 +539,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 d2b8791d..1385c8b 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -37,5 +37,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

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 11/21] perf probe: Show all cached probes
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (9 preceding siblings ...)
  2016-05-11 13:52 ` [PATCH perf/core v7 10/21] perf probe: Use cache entry if possible Masami Hiramatsu
@ 2016-05-11 13:53 ` Masami Hiramatsu
  2016-05-11 13:53 ` [PATCH perf/core v7 12/21] perf probe: Remove caches when --cache is given Masami Hiramatsu
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:53 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

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>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v7:
  - Remove the top '/' from binary name if it is not a regular file.
---
 tools/perf/Documentation/perf-probe.txt |    8 ++-
 tools/perf/builtin-probe.c              |    2 -
 tools/perf/util/build-id.c              |   86 ++++++++++++++++++++++++++++++-
 tools/perf/util/build-id.h              |    3 +
 tools/perf/util/probe-event.c           |    3 +
 tools/perf/util/probe-file.c            |   67 +++++++++++++++++++++++-
 tools/perf/util/probe-file.h            |    1 
 7 files changed, 163 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 6d7ab431..53e380c0e 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 9b8edf3..be84c17 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -168,8 +168,7 @@ retry:
 	return NULL;
 }
 
-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,
@@ -179,6 +178,36 @@ 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;
+	size_t offs = 5;	/* == strlen("../..") */
+
+	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 > buf + offs)) {
+		*p = '\0';
+		if (buf[offs + 1] == '[')
+			offs++;	/*
+				 * This is a DSO name, like [kernel.kallsyms].
+				 * Skip the first '/', since this is not the
+				 * cache of a regular file.
+				 */
+		ret = strdup(buf + offs);	/* 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");
@@ -390,6 +419,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(NULL, 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__cachedir(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 d8c7f2f..c05503e 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -30,8 +30,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__cachedir(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 acc8341..57fd657 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2364,6 +2364,9 @@ int show_perf_probe_events(struct strfilter *filter)
 
 	setup_pager();
 
+	if (probe_conf.cache)
+		return probe_cache__show_all_caches(filter);
+
 	ret = init_probe_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 f30f609..a6d4a67 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -365,10 +365,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 {
@@ -392,8 +399,11 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
 
 	dir_name = build_id_cache__cachedir(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, 0644);
@@ -649,3 +659,56 @@ 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);
+	}
+	strlist__delete(bidlist);
+
+	return 0;
+}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 1385c8b..ac70446 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -41,4 +41,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

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 12/21] perf probe: Remove caches when --cache is given
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (10 preceding siblings ...)
  2016-05-11 13:53 ` [PATCH perf/core v7 11/21] perf probe: Show all cached probes Masami Hiramatsu
@ 2016-05-11 13:53 ` Masami Hiramatsu
  2016-05-11 13:53 ` [PATCH perf/core v7 13/21] perf/sdt: ELF support for SDT Masami Hiramatsu
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:53 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

perf-probe --del removes caches when --cache is given.
Note that the delete pattern is not same as normal events.

If you cached probes with event name, --del "eventname"
works as expected. However, if you skipped it, the cached
probes doesn't have actual event name. In that case
 --del "probe-desc" is required (wildcard is acceptable).
For example a cache entry has the probe-desc "vfs_read $params",
you can remove it with --del 'vfs_read*'.

  -----
  # perf probe --cache --list
  /[kernel.kallsyms] (1466a0a250b5d0070c6d0f03c5fed30b237970a1):
  vfs_read $params
  /usr/lib64/libc-2.17.so (c31ffe7942bfd77b2fca8f9bd5709d387a86d3bc):
  getaddrinfo $params

  # perf probe --cache --del vfs_read\*
  Removed event: probe:vfs_read

  # perf probe --cache --list
  /[kernel.kallsyms] (1466a0a250b5d0070c6d0f03c5fed30b237970a1):
  /usr/lib64/libc-2.17.so (c31ffe7942bfd77b2fca8f9bd5709d387a86d3bc):
  getaddrinfo $params
  -----

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v4:
  - move del_perf_probe_caches() into builtin-probe.c since
    command-line related delete procedure is there now.
---
 tools/perf/Documentation/perf-probe.txt |    1 +
 tools/perf/builtin-probe.c              |   27 ++++++++++++++++++++++++++
 tools/perf/util/probe-file.c            |   32 ++++++++++++++++++++++++-------
 tools/perf/util/probe-file.h            |    2 ++
 4 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 5a70d45..8d09173 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -116,6 +116,7 @@ OPTIONS
 	(With --add) Cache the probes. Any events which successfully added
 	are also stored in the cache file.
 	(With --list) Show cached probes.
+	(With --del) Remove 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 53e380c0e..8f61525 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -363,6 +363,30 @@ out_cleanup:
 	return ret;
 }
 
+static int del_perf_probe_caches(struct strfilter *filter)
+{
+	struct probe_cache *cache;
+	struct strlist *bidlist;
+	struct str_node *nd;
+	int ret;
+
+	ret = build_id_cache__list_all(&bidlist);
+	if (ret < 0) {
+		pr_debug("Failed to get buildids: %d\n", ret);
+		return ret;
+	}
+
+	strlist__for_each(nd, bidlist) {
+		cache = probe_cache__new(nd->s);
+		if (!cache)
+			continue;
+		probe_cache__remove_entries(cache, filter);
+		probe_cache__commit(cache);
+		probe_cache__delete(cache);
+	}
+	return 0;
+}
+
 static int perf_del_probe_events(struct strfilter *filter)
 {
 	int ret, ret2, ufd = -1, kfd = -1;
@@ -375,6 +399,9 @@ static int perf_del_probe_events(struct strfilter *filter)
 
 	pr_debug("Delete filter: \'%s\'\n", str);
 
+	if (probe_conf.cache)
+		return del_perf_probe_caches(filter);
+
 	/* Get current event names */
 	ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW);
 	if (ret < 0)
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index a6d4a67..cc0f183 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -660,19 +660,37 @@ out:
 	return ret;
 }
 
+static bool probe_cache_entry__compare(struct probe_cache_entry *entry,
+				       struct strfilter *filter)
+{
+	char buf[128], *ptr = entry->spev;
+
+	if (entry->pev.event) {
+		snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event);
+		ptr = buf;
+	}
+	return strfilter__compare(filter, ptr);
+}
+
+int probe_cache__remove_entries(struct probe_cache *pcache,
+				struct strfilter *filter)
+{
+	struct probe_cache_entry *entry, *tmp;
+
+	list_for_each_entry_safe(entry, tmp, &pcache->list, list) {
+		if (probe_cache_entry__compare(entry, filter))
+			probe_cache_entry__delete(entry);
+	}
+	return 0;
+}
+
 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))
+		if (probe_cache_entry__compare(entry, filter))
 			printf("%s\n", entry->spev);
 	}
 	return 0;
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index ac70446..e6fd9b9 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -37,6 +37,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);
+int probe_cache__remove_entries(struct probe_cache *pcache,
+				struct strfilter *filter);
 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,

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 13/21] perf/sdt: ELF support for SDT
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (11 preceding siblings ...)
  2016-05-11 13:53 ` [PATCH perf/core v7 12/21] perf probe: Remove caches when --cache is given Masami Hiramatsu
@ 2016-05-11 13:53 ` Masami Hiramatsu
  2016-05-11 13:53 ` [PATCH perf/core v7 14/21] perf probe: Add group name support Masami Hiramatsu
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:53 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

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>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
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 87a297d..e74ce17 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1781,6 +1781,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 78e3bbf..f63e0ad 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -335,4 +335,26 @@ void arch__sym_update(struct symbol *s, 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 */

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 14/21] perf probe: Add group name support
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (12 preceding siblings ...)
  2016-05-11 13:53 ` [PATCH perf/core v7 13/21] perf/sdt: ELF support for SDT Masami Hiramatsu
@ 2016-05-11 13:53 ` Masami Hiramatsu
  2016-05-11 13:54 ` [PATCH perf/core v7 15/21] perf buildid-cache: Scan and import user SDT events to probe cache Masami Hiramatsu
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:53 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Allow user to set group name for adding new event.
Note that user must ensure that the group name doesn't
conflict with existing group name carefully.
E.g. Existing group name can conflict with other events.
Especially, using the group name reserved for kernel
modules can hide kernel embedded events when loading
modules.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v4:
  - Update Documentation/perf-probe.txt too.
---
 tools/perf/Documentation/perf-probe.txt |   10 ++++++----
 tools/perf/util/probe-event.c           |   23 ++++++++++++++---------
 2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 8d09173..7a258e9 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -143,16 +143,18 @@ PROBE SYNTAX
 Probe points are defined by following syntax.
 
     1) Define event based on function name
-     [EVENT=]FUNC[@SRC][:RLN|+OFFS|%return|;PTN] [ARG ...]
+     [[GROUP:]EVENT=]FUNC[@SRC][:RLN|+OFFS|%return|;PTN] [ARG ...]
 
     2) Define event based on source file with line number
-     [EVENT=]SRC:ALN [ARG ...]
+     [[GROUP:]EVENT=]SRC:ALN [ARG ...]
 
     3) Define event based on source file with lazy pattern
-     [EVENT=]SRC;PTN [ARG ...]
+     [[GROUP:]EVENT=]SRC;PTN [ARG ...]
 
 
-'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'.
+'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. You can also specify a group name by 'GROUP', if omitted, set 'probe' is used for kprobe and 'probe_<bin>' is used for uprobe.
+Note that using existing group name can conflict with other events. Especially, using the group name reserved for kernel modules can hide embedded events in the
+modules.
 '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).
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 57fd657..79da841 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1208,10 +1208,8 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 	bool file_spec = false;
 	/*
 	 * <Syntax>
-	 * perf probe [EVENT=]SRC[:LN|;PTN]
-	 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
-	 *
-	 * TODO:Group name support
+	 * perf probe [GRP:][EVENT=]SRC[:LN|;PTN]
+	 * perf probe [GRP:][EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
 	 */
 	if (!arg)
 		return -EINVAL;
@@ -1220,11 +1218,19 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 	if (ptr && *ptr == '=') {	/* Event name */
 		*ptr = '\0';
 		tmp = ptr + 1;
-		if (strchr(arg, ':')) {
-			semantic_error("Group name is not supported yet.\n");
-			return -ENOTSUP;
-		}
+		ptr = strchr(arg, ':');
+		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);
 			return -EINVAL;
@@ -1232,7 +1238,6 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 		pev->event = strdup(arg);
 		if (pev->event == NULL)
 			return -ENOMEM;
-		pev->group = NULL;
 		arg = tmp;
 	}
 

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 15/21] perf buildid-cache: Scan and import user SDT events to probe cache
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (13 preceding siblings ...)
  2016-05-11 13:53 ` [PATCH perf/core v7 14/21] perf probe: Add group name support Masami Hiramatsu
@ 2016-05-11 13:54 ` Masami Hiramatsu
  2016-05-11 13:54 ` [PATCH perf/core v7 16/21] perf probe: Accept %sdt and %cached event name Masami Hiramatsu
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

perf buildid-cache --add <binary> scans given binary and add
the SDT events to probe cache. "sdt_" prefix is appended for
all SDT providers to avoid event-name clash with other pre-defined
events. It is possible to use the cached SDT events as other cached
events, via perf probe --add "sdt_<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):
  sdt_libc:setjmp=setjmp
  sdt_libc:longjmp=longjmp
  sdt_libc:longjmp_target=longjmp_target
  sdt_libc:memory_heap_new=memory_heap_new
  # perf probe -x /usr/lib/libc-2.17.so \
    -a sdt_libc:memory_heap_new=memory_heap_new
  Added new event:
    sdt_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 sdt_libc:memory_heap_new -aR sleep 1

  # perf probe -l
    sdt_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>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v4:
  - Fix a bug to copy correct group name to entries.
  - Fix to consolidate same-name entries.
---
 tools/perf/util/build-id.c   |   27 +++++++++++++++--
 tools/perf/util/probe-file.c |   67 ++++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/probe-file.h |    2 +
 3 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index be84c17..6063bee 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;
@@ -516,6 +517,23 @@ int build_id_cache__list_build_ids(const char *pathname,
 	return ret;
 }
 
+#ifdef HAVE_LIBELF_SUPPORT
+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)
 {
@@ -559,20 +577,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 cc0f183..da241ed 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -429,12 +429,15 @@ 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);
 			if (!entry) {
 				ret = -ENOMEM;
 				goto out;
 			}
+			if (buf[0] == '%')
+				entry->sdt = true;
 			entry->spev = strdup(buf + 1);
 			if (entry->spev)
 				ret = parse_perf_probe_command(buf + 1,
@@ -611,14 +614,72 @@ 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;
+	char sdtgrp[64];
+	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) {
+		ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
+		if (ret < 0)
+			break;
+		/* Try to find same-name entry */
+		entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
+		if (!entry) {
+			entry = probe_cache_entry__new(NULL);
+			if (!entry) {
+				ret = -ENOMEM;
+				break;
+			}
+			entry->sdt = true;
+			ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
+					note->name, note->name);
+			if (ret < 0)
+				break;
+			entry->pev.event = strdup(note->name);
+			entry->pev.group = strdup(sdtgrp);
+			list_add_tail(&entry->list, &pcache->list);
+		}
+		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
+				sdtgrp, note->name, pathname,
+				sdt_note__get_addr(note));
+		if (ret < 0)
+			break;
+		strlist__add(entry->tevlist, buf);
+		free(buf);
+		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 e6fd9b9..93aa193 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -8,6 +8,7 @@
 /* Cache of probe definitions */
 struct probe_cache_entry {
 	struct list_head	list;
+	bool			sdt;
 	struct perf_probe_event pev;
 	char			*spev;
 	struct strlist		*tevlist;
@@ -35,6 +36,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,

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 16/21] perf probe: Accept %sdt and %cached event name
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (14 preceding siblings ...)
  2016-05-11 13:54 ` [PATCH perf/core v7 15/21] perf buildid-cache: Scan and import user SDT events to probe cache Masami Hiramatsu
@ 2016-05-11 13:54 ` Masami Hiramatsu
  2016-05-11 13:54 ` [PATCH perf/core v7 17/21] perf-list: Show SDT and pre-cached events Masami Hiramatsu
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

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:
    sdt_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 sdt_libc:lll_lock_wait_private -aR sleep 1

  # perf probe -l | more
    sdt_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>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v7:
  - Fix a bug to return an error if no SDT/cached events found in cache.
---
 tools/perf/Documentation/perf-probe.txt |    3 +
 tools/perf/util/probe-event.c           |   82 ++++++++++++++++++++++---------
 tools/perf/util/probe-event.h           |    1 
 tools/perf/util/probe-file.c            |    9 +++
 4 files changed, 71 insertions(+), 24 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 7a258e9..43523be 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -151,6 +151,8 @@ Probe points are defined by following syntax.
     3) Define event based on source file with lazy pattern
      [[GROUP:]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. You can also specify a group name by 'GROUP', if omitted, set 'probe' is used for kprobe and 'probe_<bin>' is used for uprobe.
 Note that using existing group name can conflict with other events. Especially, using the group name reserved for kernel modules can hide embedded events in the
@@ -158,6 +160,7 @@ modules.
 '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 79da841..5ec98b2 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1199,6 +1199,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)
 {
@@ -1206,38 +1234,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;
 	}
 
@@ -2872,7 +2905,8 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 
 	entry = probe_cache__find(cache, pev);
 	if (!entry) {
-		ret = 0;
+		/* SDT must be in the cache */
+		ret = pev->sdt ? -ENOENT : 0;
 		goto out;
 	}
 
@@ -2911,7 +2945,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 {
 	int ret;
 
-	if (!pev->group) {
+	if (!pev->group && !pev->sdt) {
 		/* Set group name if not given */
 		if (!pev->uprobes) {
 			pev->group = strdup(PERFPROBE_GROUP);
@@ -2930,8 +2964,8 @@ 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 (ret > 0 || pev->sdt)	/* SDT can be found only in the cache */
+		return ret == 0 ? -ENOENT : ret; /* Found in probe cache */
 
 	if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
 		ret = find_probe_trace_events_from_map(pev, tevs);
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 432b690..e18ea9f 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -85,6 +85,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 da241ed..bc82a55 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -538,6 +538,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) &&

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 17/21] perf-list: Show SDT and pre-cached events
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (15 preceding siblings ...)
  2016-05-11 13:54 ` [PATCH perf/core v7 16/21] perf probe: Accept %sdt and %cached event name Masami Hiramatsu
@ 2016-05-11 13:54 ` Masami Hiramatsu
  2016-05-11 13:54 ` [PATCH perf/core v7 18/21] perf-list: Skip SDTs placed in invalid binaries Masami Hiramatsu
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Show SDT and pre-cached events by perf-list with "sdt". This also
shows the binary and build-id where the events are placed only
when there are same name events on different binaries.
e.g.
  ----
  # perf list sdt

  List of pre-defined events (to be used in -e):

    sdt_libc:lll_futex_wake                            [SDT event]
    sdt_libc:lll_lock_wait_private                     [SDT event]
    sdt_libc:longjmp                                   [SDT event]
    sdt_libc:longjmp_target                            [SDT event]
  ...
    sdt_libstdcxx:rethrow@/usr/bin/gcc(0cc207fc4b27)   [SDT event]
    sdt_libstdcxx:rethrow@/usr/lib64/libstdc++.so.6.0.20(91c7a88fdf49)
    sdt_libstdcxx:throw@/usr/bin/gcc(0cc207fc4b27)     [SDT event]
    sdt_libstdcxx:throw@/usr/lib64/libstdc++.so.6.0.20(91c7a88fdf49)
  ----

The binary path and build-id are shown in below format;

  <GROUP>:<EVENT>@<PATH>(<BUILD-ID>)

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v5:
  - Fix a build error for minimal option.

 Changes in v4:
  - Update patch description.
  - Change event list format.
---
 tools/perf/builtin-list.c      |    4 ++
 tools/perf/util/parse-events.c |   83 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/parse-events.h |    2 +
 tools/perf/util/probe-file.h   |    9 ++++
 4 files changed, 98 insertions(+)

diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 5e22db4..3cba865 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -62,6 +62,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 			print_hwcache_events(NULL, raw_dump);
 		else if (strcmp(argv[i], "pmu") == 0)
 			print_pmu_events(NULL, raw_dump);
+		else if (strcmp(argv[i], "sdt") == 0)
+			print_sdt_events(NULL, NULL, raw_dump);
 		else if ((sep = strchr(argv[i], ':')) != NULL) {
 			int sep_idx;
 
@@ -76,6 +78,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 
 			s[sep_idx] = '\0';
 			print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
+			print_sdt_events(s, s + sep_idx + 1, raw_dump);
 			free(s);
 		} else {
 			if (asprintf(&s, "*%s*", argv[i]) < 0) {
@@ -89,6 +92,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 			print_hwcache_events(s, raw_dump);
 			print_pmu_events(s, raw_dump);
 			print_tracepoint_events(NULL, s, raw_dump);
+			print_sdt_events(NULL, s, raw_dump);
 			free(s);
 		}
 	}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index bcbc983..f9c8b7b 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -20,6 +20,7 @@
 #include "pmu.h"
 #include "thread_map.h"
 #include "cpumap.h"
+#include "probe-file.h"
 #include "asm/bug.h"
 
 #define MAX_NAME_LEN 100
@@ -1976,6 +1977,86 @@ static bool is_event_supported(u8 type, unsigned config)
 	return ret;
 }
 
+void print_sdt_events(const char *subsys_glob, const char *event_glob,
+		      bool name_only)
+{
+	struct probe_cache *pcache;
+	struct probe_cache_entry *ent;
+	struct strlist *bidlist, *sdtlist;
+	struct strlist_config cfg = {.dont_dupstr = true};
+	struct str_node *nd, *nd2;
+	char *buf, *path, *ptr = NULL;
+	bool show_detail = false;
+	int ret;
+
+	sdtlist = strlist__new(NULL, &cfg);
+	if (!sdtlist) {
+		pr_debug("Failed to allocate new strlist for SDT\n");
+		return;
+	}
+	ret = build_id_cache__list_all(&bidlist);
+	if (ret < 0) {
+		pr_debug("Failed to get buildids: %d\n", ret);
+		return;
+	}
+	strlist__for_each(nd, bidlist) {
+		pcache = probe_cache__new(nd->s);
+		if (!pcache)
+			continue;
+		if (!list_empty(&pcache->list))
+			list_for_each_entry(ent, &pcache->list, list) {
+				if (!ent->sdt)
+					continue;
+				if (subsys_glob &&
+				    !strglobmatch(ent->pev.group, subsys_glob))
+					continue;
+				if (event_glob &&
+				    !strglobmatch(ent->pev.event, event_glob))
+					continue;
+				ret = asprintf(&buf, "%s:%s@%s", ent->pev.group,
+						ent->pev.event, nd->s);
+				if (ret > 0)
+					strlist__add(sdtlist, buf);
+			}
+		probe_cache__delete(pcache);
+	}
+	strlist__delete(bidlist);
+
+	strlist__for_each(nd, sdtlist) {
+		buf = strchr(nd->s, '@');
+		if (buf)
+			*(buf++) = '\0';
+		if (name_only) {
+			printf("%s ", nd->s);
+			continue;
+		}
+		nd2 = strlist__next(nd);
+		if (nd2) {
+			ptr = strchr(nd2->s, '@');
+			if (ptr)
+				*ptr = '\0';
+			if (strcmp(nd->s, nd2->s) == 0)
+				show_detail = true;
+		}
+		if (show_detail) {
+			path = build_id_cache__origname(buf);
+			ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf);
+			if (ret > 0) {
+				printf("  %-50s [%s]\n", buf, "SDT event");
+				free(buf);
+			}
+		} else
+			printf("  %-50s [%s]\n", nd->s, "SDT event");
+		if (nd2) {
+			if (strcmp(nd->s, nd2->s) != 0)
+				show_detail = false;
+			if (ptr)
+				*ptr = '@';
+		}
+	}
+	strlist__delete(sdtlist);
+}
+
 int print_hwcache_events(const char *event_glob, bool name_only)
 {
 	unsigned int type, op, i, evt_i = 0, evt_num = 0;
@@ -2158,6 +2239,8 @@ void print_events(const char *event_glob, bool name_only)
 	}
 
 	print_tracepoint_events(NULL, NULL, name_only);
+
+	print_sdt_events(NULL, NULL, name_only);
 }
 
 int parse_events__is_hardcoded_term(struct parse_events_term *term)
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index d740c3c..c08daa9 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -182,6 +182,8 @@ void print_symbol_events(const char *event_glob, unsigned type,
 void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
 			     bool name_only);
 int print_hwcache_events(const char *event_glob, bool name_only);
+void print_sdt_events(const char *subsys_glob, const char *event_glob,
+		      bool name_only);
 int is_valid_tracepoint(const char *event_string);
 
 int valid_event_mount(const char *eventfs);
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 93aa193..ce98162 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -22,6 +22,8 @@ struct probe_cache {
 #define PF_FL_UPROBE	1
 #define PF_FL_RW	2
 
+/* probe-file.c depends on libelf */
+#ifdef HAVE_LIBELF_SUPPORT
 int probe_file__open(int flag);
 int probe_file__open_both(int *kfd, int *ufd, int flag);
 struct strlist *probe_file__get_namelist(int fd);
@@ -46,4 +48,11 @@ struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
 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);
+#else	/* ! HAVE_LIBELF_SUPPORT */
+static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused)
+{
+	return NULL;
+}
+#define probe_cache__delete(pcache) do {} while(0)
+#endif
 #endif

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 18/21] perf-list: Skip SDTs placed in invalid binaries
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (16 preceding siblings ...)
  2016-05-11 13:54 ` [PATCH perf/core v7 17/21] perf-list: Show SDT and pre-cached events Masami Hiramatsu
@ 2016-05-11 13:54 ` Masami Hiramatsu
  2016-05-11 13:54 ` [PATCH perf/core v7 19/21] perf probe: Allow wildcard for cached events Masami Hiramatsu
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Skip SDTs placed in invalid (non-exist, or older version)
binaries. Note that perf-probe --cache --list and
perf-probe --cache --del still handle all the caches
including invalid binaries.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v7:
  - Validate build-id via sysfs if it is for kallsyms,
 Changes in v4:
  - Rename a parameter 'valid' to 'validonly' :)
---
 tools/perf/builtin-probe.c     |    2 +-
 tools/perf/util/build-id.c     |   33 ++++++++++++++++++++++++++++++++-
 tools/perf/util/build-id.h     |    2 +-
 tools/perf/util/parse-events.c |    2 +-
 tools/perf/util/probe-file.c   |    2 +-
 5 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 8f61525..4a86aea 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -370,7 +370,7 @@ static int del_perf_probe_caches(struct strfilter *filter)
 	struct str_node *nd;
 	int ret;
 
-	ret = build_id_cache__list_all(&bidlist);
+	ret = build_id_cache__list_all(&bidlist, false);
 	if (ret < 0) {
 		pr_debug("Failed to get buildids: %d\n", ret);
 		return ret;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 6063bee..ce02668 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -209,6 +209,31 @@ out:
 	return ret;
 }
 
+/* Check if the given build_id cache is valid on current running system */
+static bool build_id_cache__valid_id(char *sbuild_id)
+{
+	char real_sbuild_id[SBUILD_ID_SIZE] = "";
+	char *pathname;
+	int ret = 0;
+	bool result = false;
+
+	pathname = build_id_cache__origname(sbuild_id);
+	if (!pathname)
+		return false;
+
+	if (!strcmp(pathname, DSO__NAME_KALLSYMS))
+		ret = sysfs__sprintf_build_id("/", real_sbuild_id);
+	else if (pathname[0] == '/')
+		ret = filename__sprintf_build_id(pathname, real_sbuild_id);
+	else
+		ret = -EINVAL;	/* Should we support other special DSO cache? */
+	if (ret >= 0)
+		result = (strcmp(sbuild_id, real_sbuild_id) == 0);
+	free(pathname);
+
+	return result;
+}
+
 static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
 {
 	return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
@@ -420,7 +445,7 @@ void disable_buildid_cache(void)
 	no_buildid_cache = true;
 }
 
-int build_id_cache__list_all(struct strlist **result)
+int build_id_cache__list_all(struct strlist **result, bool validonly)
 {
 	struct strlist *toplist, *list, *bidlist;
 	struct str_node *nd, *nd2;
@@ -428,6 +453,10 @@ int build_id_cache__list_all(struct strlist **result)
 	char sbuild_id[SBUILD_ID_SIZE];
 	int ret = 0;
 
+	/* for filename__ functions */
+	if (validonly)
+		symbol__init(NULL);
+
 	/* Open the top-level directory */
 	if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
 		return -errno;
@@ -457,6 +486,8 @@ int build_id_cache__list_all(struct strlist **result)
 					nd->s, nd2->s);
 				continue;
 			}
+			if (validonly && !build_id_cache__valid_id(sbuild_id))
+				continue;
 			strlist__add(bidlist, sbuild_id);
 		}
 		strlist__delete(list);
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index c05503e..480600b 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -34,7 +34,7 @@ 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__cachedir(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_all(struct strlist **result, bool validonly);
 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/parse-events.c b/tools/perf/util/parse-events.c
index f9c8b7b..53d52a3 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1994,7 +1994,7 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,
 		pr_debug("Failed to allocate new strlist for SDT\n");
 		return;
 	}
-	ret = build_id_cache__list_all(&bidlist);
+	ret = build_id_cache__list_all(&bidlist, true);
 	if (ret < 0) {
 		pr_debug("Failed to get buildids: %d\n", ret);
 		return;
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index bc82a55..c4104c4 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -779,7 +779,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
 	pr_debug("list cache with filter: %s\n", buf);
 	free(buf);
 
-	ret = build_id_cache__list_all(&bidlist);
+	ret = build_id_cache__list_all(&bidlist, false);
 	if (ret < 0) {
 		pr_debug("Failed to get buildids: %d\n", ret);
 		return ret == -ENOENT ? 0 : ret;

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 19/21] perf probe: Allow wildcard for cached events
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (17 preceding siblings ...)
  2016-05-11 13:54 ` [PATCH perf/core v7 18/21] perf-list: Skip SDTs placed in invalid binaries Masami Hiramatsu
@ 2016-05-11 13:54 ` Masami Hiramatsu
  2016-05-11 13:54 ` [PATCH perf/core v7 20/21] perf probe: Support @BUILDID or @FILE suffix for SDT events Masami Hiramatsu
  2016-05-11 13:55 ` [PATCH perf/core v7 21/21] perf probe: Support a special SDT probe format Masami Hiramatsu
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

Allo glob wildcard for reusing cached/SDT events. This also
automatically find the target binaries, e.g.

  # perf probe -a %sdt_libc:\*

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

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v7:
  - Continue to search caches if a build-id cache has no probe cache.
  - Make probe_cache__open() to accept DSO__NAME_KALLSYMS for kernel.
  - Fix to add probes correctly when a wildcard matchs both of
    uprobes and kprobes.
 Changes in v5.1:
  - Fix a SEGV bug when a group name is omitted. (Thanks Hemant!)
---
 tools/perf/util/probe-event.c |  211 +++++++++++++++++++++++++++++++++++++----
 tools/perf/util/probe-event.h |    1 
 tools/perf/util/probe-file.c  |   46 +++++++--
 tools/perf/util/probe-file.h  |    5 +
 4 files changed, 232 insertions(+), 31 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 5ec98b2..0019a22 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -236,7 +236,7 @@ static void clear_perf_probe_point(struct perf_probe_point *pp)
 	free(pp->lazy_line);
 }
 
-static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
+void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
 {
 	int i;
 
@@ -1206,7 +1206,7 @@ static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
 	ptr = strchr(*arg, ':');
 	if (ptr) {
 		*ptr = '\0';
-		if (!is_c_func_name(*arg))
+		if (!pev->sdt && !is_c_func_name(*arg))
 			goto ng_name;
 		pev->group = strdup(*arg);
 		if (!pev->group)
@@ -1214,7 +1214,7 @@ static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
 		*arg = ptr + 1;
 	} else
 		pev->group = NULL;
-	if (!is_c_func_name(*arg)) {
+	if (!pev->sdt && !is_c_func_name(*arg)) {
 ng_name:
 		semantic_error("%s is bad for event name -it must "
 			       "follow C symbol-naming rule.\n", *arg);
@@ -1640,6 +1640,11 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
 	p = strchr(argv[1], ':');
 	if (p) {
 		tp->module = strndup(argv[1], p - argv[1]);
+		if (!tp->module) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		tev->uprobes = (tp->module[0] == '/');
 		p++;
 	} else
 		p = argv[1];
@@ -2514,7 +2519,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 	int ret;
 
 	/* If probe_event or trace_event already have the name, reuse it */
-	if (pev->event)
+	if (pev->event && !pev->sdt)
 		event = pev->event;
 	else if (tev->event)
 		event = tev->event;
@@ -2527,7 +2532,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 		else
 			event = tev->point.realname;
 	}
-	if (pev->group)
+	if (pev->group && !pev->sdt)
 		group = pev->group;
 	else if (tev->group)
 		group = tev->group;
@@ -2552,41 +2557,60 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 	return 0;
 }
 
-static int __add_probe_trace_events(struct perf_probe_event *pev,
-				     struct probe_trace_event *tevs,
-				     int ntevs, bool allow_suffix)
+static int __open_probe_file_and_namelist(bool uprobe,
+					  struct strlist **namelist)
 {
-	int i, fd, ret;
-	struct probe_trace_event *tev = NULL;
-	struct probe_cache *cache = NULL;
-	struct strlist *namelist;
+	int fd;
 
-	fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0));
+	fd = probe_file__open(PF_FL_RW | (uprobe ? PF_FL_UPROBE : 0));
 	if (fd < 0)
 		return fd;
 
 	/* Get current event names */
-	namelist = probe_file__get_namelist(fd);
-	if (!namelist) {
+	*namelist = probe_file__get_namelist(fd);
+	if (!(*namelist)) {
 		pr_debug("Failed to get current event list.\n");
-		ret = -ENOMEM;
-		goto close_out;
+		close(fd);
+		return -ENOMEM;
 	}
+	return fd;
+}
+
+static int __add_probe_trace_events(struct perf_probe_event *pev,
+				     struct probe_trace_event *tevs,
+				     int ntevs, bool allow_suffix)
+{
+	int i, fd[2] = {-1, -1}, up, ret;
+	struct probe_trace_event *tev = NULL;
+	struct probe_cache *cache = NULL;
+	struct strlist *namelist[2] = {NULL, NULL};
+
+	up = pev->uprobes ? 1 : 0;
+	fd[up] = __open_probe_file_and_namelist(up, &namelist[up]);
+	if (fd[up] < 0)
+		return fd[up];
 
 	ret = 0;
 	for (i = 0; i < ntevs; i++) {
 		tev = &tevs[i];
+		up = tev->uprobes ? 1 : 0;
+		if (fd[up] == -1) {	/* Open the kprobe/uprobe_events */
+			fd[up] = __open_probe_file_and_namelist(up,
+								&namelist[up]);
+			if (fd[up] < 0)
+				goto close_out;
+		}
 		/* Skip if the symbol is out of .text or blacklisted */
 		if (!tev->point.symbol && !pev->uprobes)
 			continue;
 
 		/* Set new name for tev (and update namelist) */
-		ret = probe_trace_event__set_name(tev, pev, namelist,
+		ret = probe_trace_event__set_name(tev, pev, namelist[up],
 						  allow_suffix);
 		if (ret < 0)
 			break;
 
-		ret = probe_file__add_event(fd, tev);
+		ret = probe_file__add_event(fd[up], tev);
 		if (ret < 0)
 			break;
 
@@ -2609,9 +2633,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 		}
 	}
 
-	strlist__delete(namelist);
 close_out:
-	close(fd);
+	for (up = 0; up < 2; up++) {
+		strlist__delete(namelist[up]);
+		if (fd[up] >= 0)
+			close(fd[up]);
+	}
 	return ret;
 }
 
@@ -2890,6 +2917,141 @@ errout:
 
 bool __weak arch__prefers_symtab(void) { return false; }
 
+/* Concatinate two arrays */
+static void *memcat(void *a, size_t sz_a, void *b, size_t sz_b)
+{
+	void *ret;
+
+	ret = malloc(sz_a + sz_b);
+	if (ret) {
+		memcpy(ret, a, sz_a);
+		memcpy(ret + sz_a, b, sz_b);
+	}
+	return ret;
+}
+
+static int
+concat_probe_trace_events(struct probe_trace_event **tevs, int *ntevs,
+			  struct probe_trace_event **tevs2, int ntevs2)
+{
+	struct probe_trace_event *new_tevs;
+	int ret = 0;
+
+	if (ntevs == 0) {
+		*tevs = *tevs2;
+		*ntevs = ntevs2;
+		*tevs2 = NULL;
+		return 0;
+	}
+
+	if (*ntevs + ntevs2 > probe_conf.max_probes)
+		ret = -E2BIG;
+	else {
+		/* Concatinate the array of probe_trace_event */
+		new_tevs = memcat(*tevs, (*ntevs) * sizeof(**tevs),
+				  *tevs2, ntevs2 * sizeof(**tevs2));
+		if (!new_tevs)
+			ret = -ENOMEM;
+		else {
+			free(*tevs);
+			*tevs = new_tevs;
+			*ntevs += ntevs2;
+		}
+	}
+	if (ret < 0)
+		clear_probe_trace_events(*tevs2, ntevs2);
+	zfree(tevs2);
+
+	return ret;
+}
+
+/*
+ * Try to find probe_trace_event from given probe caches. Return the number
+ * of cached events found, if an error occurs return the error.
+ */
+static int find_cached_events(struct perf_probe_event *pev,
+			      struct probe_trace_event **tevs,
+			      const char *target)
+{
+	struct probe_cache *cache;
+	struct probe_cache_entry *entry;
+	struct probe_trace_event *tmp_tevs = NULL;
+	int ntevs = 0;
+	int ret = 0;
+
+	cache = probe_cache__new(target);
+	/* Return 0 ("not found") if the target has no probe cache. */
+	if (!cache)
+		return 0;
+
+	for_each_probe_cache_entry(entry, cache) {
+		/* Skip the cache entry which has no name */
+		if (!entry->pev.event || !entry->pev.group)
+			continue;
+		if ((!pev->group || strglobmatch(entry->pev.group, pev->group)) &&
+		    strglobmatch(entry->pev.event, pev->event)) {
+			ret = probe_cache_entry__get_event(entry, &tmp_tevs);
+			if (ret > 0)
+				ret = concat_probe_trace_events(tevs, &ntevs,
+								&tmp_tevs, ret);
+			if (ret < 0)
+				break;
+		}
+	}
+	probe_cache__delete(cache);
+	if (ret < 0) {
+		clear_probe_trace_events(*tevs, ntevs);
+		zfree(tevs);
+	} else {
+		ret = ntevs;
+		if (ntevs > 0 && target[0] == '/')
+			pev->uprobes = true;
+	}
+
+	return ret;
+}
+
+/* Try to find probe_trace_event from all probe caches */
+static int find_cached_events_all(struct perf_probe_event *pev,
+				   struct probe_trace_event **tevs)
+{
+	struct probe_trace_event *tmp_tevs = NULL;
+	struct strlist *bidlist;
+	struct str_node *nd;
+	char *pathname;
+	int ntevs = 0;
+	int ret;
+
+	/* Get the buildid list of all valid caches */
+	ret = build_id_cache__list_all(&bidlist, true);
+	if (ret < 0) {
+		pr_debug("Failed to get buildids: %d\n", ret);
+		return ret;
+	}
+
+	ret = 0;
+	strlist__for_each(nd, bidlist) {
+		pathname = build_id_cache__origname(nd->s);
+		ret = find_cached_events(pev, &tmp_tevs, pathname);
+		/* In the case of cnt == 0, we just skip it */
+		if (ret > 0)
+			ret = concat_probe_trace_events(tevs, &ntevs,
+							&tmp_tevs, ret);
+		free(pathname);
+		if (ret < 0)
+			break;
+	}
+	strlist__delete(bidlist);
+
+	if (ret < 0) {
+		clear_probe_trace_events(*tevs, ntevs);
+		zfree(tevs);
+	} else
+		ret = ntevs;
+
+	return ret;
+}
+
 static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 					      struct probe_trace_event **tevs)
 {
@@ -2899,6 +3061,13 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 	struct str_node *node;
 	int ret, i;
 
+	if (pev->sdt) {
+		/* For SDT/cached events, we use special search functions */
+		if (!pev->target)
+			return find_cached_events_all(pev, tevs);
+		else
+			return find_cached_events(pev, tevs, pev->target);
+	}
 	cache = probe_cache__new(pev->target);
 	if (!cache)
 		return 0;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e18ea9f..a027bfe 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -134,6 +134,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
 /* Release event contents */
 void clear_perf_probe_event(struct perf_probe_event *pev);
 void clear_probe_trace_event(struct probe_trace_event *tev);
+void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs);
 
 /* Command string to line-range */
 int parse_line_range_desc(const char *cmd, struct line_range *lr);
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index c4104c4..4d25882 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -360,13 +360,38 @@ probe_cache_entry__new(struct perf_probe_event *pev)
 	return ret;
 }
 
-/* For the kernel probe caches, pass target = NULL */
+int probe_cache_entry__get_event(struct probe_cache_entry *entry,
+				 struct probe_trace_event **tevs)
+{
+	struct probe_trace_event *tev;
+	struct str_node *node;
+	int ret, i;
+
+	ret = strlist__nr_entries(entry->tevlist);
+	if (ret > probe_conf.max_probes)
+		return -E2BIG;
+
+	*tevs = zalloc(ret * sizeof(*tev));
+	if (!*tevs)
+		return -ENOMEM;
+
+	i = 0;
+	strlist__for_each(node, entry->tevlist) {
+		tev = &(*tevs)[i++];
+		ret = parse_probe_trace_command(node->s, tev);
+		if (ret < 0)
+			break;
+	}
+	return i;
+}
+
+/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
 static int probe_cache__open(struct probe_cache *pcache, const char *target)
 {
 	char cpath[PATH_MAX];
 	char sbuildid[SBUILD_ID_SIZE];
 	char *dir_name = NULL;
-	bool is_kallsyms = !target;
+	bool is_kallsyms = false;
 	int ret, fd;
 
 	if (target && build_id_cache__cached(target)) {
@@ -376,12 +401,13 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
 		goto found;
 	}
 
-	if (target)
-		ret = filename__sprintf_build_id(target, sbuildid);
-	else {
+	if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) {
 		target = DSO__NAME_KALLSYMS;
+		is_kallsyms = true;
 		ret = sysfs__sprintf_build_id("/", sbuildid);
-	}
+	} else
+		ret = filename__sprintf_build_id(target, sbuildid);
+
 	if (ret < 0) {
 		pr_debug("Failed to get build-id from %s.\n", target);
 		return ret;
@@ -537,7 +563,7 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
 	if (!cmd)
 		return NULL;
 
-	list_for_each_entry(entry, &pcache->list, list) {
+	for_each_probe_cache_entry(entry, pcache) {
 		if (pev->sdt) {
 			if (entry->pev.event &&
 			    streql(entry->pev.event, pev->event) &&
@@ -567,7 +593,7 @@ probe_cache__find_by_name(struct probe_cache *pcache,
 {
 	struct probe_cache_entry *entry = NULL;
 
-	list_for_each_entry(entry, &pcache->list, list) {
+	for_each_probe_cache_entry(entry, pcache) {
 		/* Hit if same event name or same command-string */
 		if (streql(entry->pev.group, group) &&
 		    streql(entry->pev.event, event))
@@ -720,7 +746,7 @@ int probe_cache__commit(struct probe_cache *pcache)
 	if (ret < 0)
 		goto out;
 
-	list_for_each_entry(entry, &pcache->list, list) {
+	for_each_probe_cache_entry(entry, pcache) {
 		ret = probe_cache_entry__write(entry, pcache->fd);
 		pr_debug("Cache committed: %d\n", ret);
 		if (ret < 0)
@@ -759,7 +785,7 @@ static int probe_cache__show_entries(struct probe_cache *pcache,
 {
 	struct probe_cache_entry *entry;
 
-	list_for_each_entry(entry, &pcache->list, list) {
+	for_each_probe_cache_entry(entry, pcache) {
 		if (probe_cache_entry__compare(entry, filter))
 			printf("%s\n", entry->spev);
 	}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index ce98162..0faf083 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -21,6 +21,8 @@ struct probe_cache {
 
 #define PF_FL_UPROBE	1
 #define PF_FL_RW	2
+#define for_each_probe_cache_entry(entry, pcache) \
+	list_for_each_entry(entry, &pcache->list, list)
 
 /* probe-file.c depends on libelf */
 #ifdef HAVE_LIBELF_SUPPORT
@@ -34,6 +36,9 @@ int probe_file__get_events(int fd, struct strfilter *filter,
 				  struct strlist *plist);
 int probe_file__del_strlist(int fd, struct strlist *namelist);
 
+int probe_cache_entry__get_event(struct probe_cache_entry *entry,
+				 struct probe_trace_event **tevs);
+
 struct probe_cache *probe_cache__new(const char *target);
 int probe_cache__add_entry(struct probe_cache *pcache,
 			   struct perf_probe_event *pev,

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 20/21] perf probe: Support @BUILDID or @FILE suffix for SDT events
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (18 preceding siblings ...)
  2016-05-11 13:54 ` [PATCH perf/core v7 19/21] perf probe: Allow wildcard for cached events Masami Hiramatsu
@ 2016-05-11 13:54 ` Masami Hiramatsu
  2016-05-11 13:55 ` [PATCH perf/core v7 21/21] perf probe: Support a special SDT probe format Masami Hiramatsu
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

Support @BUILDID or @FILE suffix for SDT events. This allows
perf to add probes on SDTs/pre-cached events on given FILE
or the file which has given BUILDID (also, this complements
BUILDID.)
For example, both gcc and libstdc++ has same SDTs as below.
If you would like to add a probe on sdt_libstdcxx:catch on gcc,
you can do as below.

  ----
  # perf list sdt | tail -n 6
    sdt_libstdcxx:catch@/usr/bin/gcc(0cc207fc4b27)     [SDT event]
    sdt_libstdcxx:catch@/usr/lib64/libstdc++.so.6.0.20(91c7a88fdf49)
    sdt_libstdcxx:rethrow@/usr/bin/gcc(0cc207fc4b27)   [SDT event]
    sdt_libstdcxx:rethrow@/usr/lib64/libstdc++.so.6.0.20(91c7a88fdf49)
    sdt_libstdcxx:throw@/usr/bin/gcc(0cc207fc4b27)     [SDT event]
    sdt_libstdcxx:throw@/usr/lib64/libstdc++.so.6.0.20(91c7a88fdf49)
  # perf probe -a sdt_libstdcxx:catch@0cc
  Added new event:
    sdt_libstdcxx:catch  (on %catch in /usr/bin/gcc)

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

  	perf record -e sdt_libstdcxx:catch -aR sleep 1
  ----

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/util/build-id.c    |   40 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/build-id.h    |    1 +
 tools/perf/util/probe-event.c |   16 ++++++++++++++--
 3 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index ce02668..eac4c0b 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -504,6 +504,46 @@ out:
 	return ret;
 }
 
+static bool str_is_build_id(const char *maybe_sbuild_id, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++) {
+		if (!isxdigit(maybe_sbuild_id[i]))
+			return false;
+	}
+	return true;
+}
+
+/* Return the valid complete build-id */
+char *build_id_cache__complement(const char *incomplete_sbuild_id)
+{
+	struct strlist *list;
+	struct str_node *nd, *cand = NULL;
+	char *sbuild_id = NULL;
+	size_t len = strlen(incomplete_sbuild_id);
+
+	if (len >= SBUILD_ID_SIZE ||
+	    !str_is_build_id(incomplete_sbuild_id, len) ||
+	    build_id_cache__list_all(&list, true) < 0)
+		return NULL;
+
+	strlist__for_each(nd, list) {
+		if (strncmp(nd->s, incomplete_sbuild_id, len) != 0)
+			continue;
+		if (cand) {	/* Error: There are more than 2 candidates. */
+			cand = NULL;
+			break;
+		}
+		cand = nd;
+	}
+	if (cand)
+		sbuild_id = strdup(cand->s);
+	strlist__delete(list);
+
+	return sbuild_id;
+}
+
 char *build_id_cache__cachedir(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 480600b..9bd6d0b 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -35,6 +35,7 @@ char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
 char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
 			       bool is_kallsyms, bool is_vdso);
 int build_id_cache__list_all(struct strlist **result, bool validonly);
+char *build_id_cache__complement(const char *incomplete_sbuild_id);
 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 0019a22..bd31cac 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1253,8 +1253,20 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 	ptr = strpbrk(arg, ";=@+%");
 	if (pev->sdt) {
 		if (ptr) {
-			semantic_error("%s must contain only an SDT event name.\n", arg);
-			return -EINVAL;
+			if (*ptr != '@') {
+				semantic_error("%s must contain only an SDT event name.\n", arg);
+				return -EINVAL;
+			}
+			/* This must be a target file name or build id */
+			tmp = build_id_cache__complement(ptr + 1);
+			if (tmp) {
+				pev->target = build_id_cache__origname(tmp);
+				free(tmp);
+			} else
+				pev->target = strdup(ptr + 1);
+			if (!pev->target)
+				return -ENOMEM;
+			*ptr = '\0';
 		}
 		ret = parse_perf_probe_event_name(&arg, pev);
 		if (ret == 0) {

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH perf/core v7 21/21] perf probe: Support a special SDT probe format
  2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
                   ` (19 preceding siblings ...)
  2016-05-11 13:54 ` [PATCH perf/core v7 20/21] perf probe: Support @BUILDID or @FILE suffix for SDT events Masami Hiramatsu
@ 2016-05-11 13:55 ` Masami Hiramatsu
  20 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-11 13:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Masami Hiramatsu, linux-kernel, Namhyung Kim, Peter Zijlstra,
	Ingo Molnar, Hemant Kumar, Ananth N Mavinakayanahalli,
	Brendan Gregg

Support a special SDT probe format which can omit the '%' prefix
only if the SDT group name starts with "sdt_". So, for example
both of "%sdt_libc:setjump" and "sdt_libc:setjump" are acceptable
for perf probe --add.

Suggested-by: Brendan Gregg <brendan.d.gregg@gmail.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/Documentation/perf-probe.txt |    4 +++-
 tools/perf/util/probe-event.c           |   12 ++++++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 43523be..2ebde8b 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -152,7 +152,9 @@ Probe points are defined by following syntax.
      [[GROUP:]EVENT=]SRC;PTN [ARG ...]
 
     4) Pre-defined SDT events
-     %[PROVIDER:]SDTEVENT
+     %[sdt_PROVIDER:]SDTEVENT
+     or,
+     sdt_PROVIDER:SDTEVENT
 
 'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. You can also specify a group name by 'GROUP', if omitted, set 'probe' is used for kprobe and 'probe_<bin>' is used for uprobe.
 Note that using existing group name can conflict with other events. Especially, using the group name reserved for kernel modules can hide embedded events in the
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index bd31cac..a4819f9 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1245,9 +1245,17 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 	if (!arg)
 		return -EINVAL;
 
-	if (arg[0] == '%') {
+	/*
+	 * If the probe point starts with '%',
+	 * or starts with "sdt_" and has a ':' but no '=',
+	 * then it should be a SDT/cached probe point.
+	 */
+	if (arg[0] == '%' ||
+	    (!strncmp(arg, "sdt_", 4) &&
+	     !!strchr(arg, ':') && !strchr(arg, '='))) {
 		pev->sdt = true;
-		arg++;
+		if (arg[0] == '%')
+			arg++;
 	}
 
 	ptr = strpbrk(arg, ";=@+%");

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly
  2016-05-11 13:51 ` [PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly Masami Hiramatsu
@ 2016-05-11 13:59   ` Arnaldo Carvalho de Melo
  2016-05-12  1:46     ` Masami Hiramatsu
  2016-05-12 10:25   ` [tip:perf/core] perf tools: " tip-bot for Masami Hiramatsu
  1 sibling, 1 reply; 37+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-05-11 13:59 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: linux-kernel, Namhyung Kim, Peter Zijlstra, Ingo Molnar,
	Hemant Kumar, Ananth N Mavinakayanahalli, Brendan Gregg

Em Wed, May 11, 2016 at 10:51:27PM +0900, Masami Hiramatsu escreveu:
> Fix lsdir() to set correct positive error number (ENOMEM).
> Since "errno" must have a positive error number instead of
> negative number, fix lsdir to set it correctly.

Masami, please try to:

1) Follow existing convention when writing the patch Subject line, when
in doubt: git log tools/perf/util/util.c and check, in this case I
changed it to "perf tools: Fix lsdir to set errno correctly"

2) Add a Fixed line, for this case I used 'git blame' and added:

Fixes: e1ce726e1db2 ("perf tools: Add lsdir() helper to read a directory")

This helps reviewing (now and down the line), because one can go more
quickly check what was the intention in the original patch, to see if it
is really a fix.

In some cases this looks trivial, like in this patch, sometimes its
not...

Thanks,

- Arnaldo
 
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>  tools/perf/util/util.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
> index 01c9433..eab077a 100644
> --- a/tools/perf/util/util.c
> +++ b/tools/perf/util/util.c
> @@ -139,7 +139,7 @@ struct strlist *lsdir(const char *name,
>  
>  	list = strlist__new(NULL, NULL);
>  	if (!list) {
> -		errno = -ENOMEM;
> +		errno = ENOMEM;
>  		goto out;
>  	}
>  

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms
  2016-05-11 13:51 ` [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms Masami Hiramatsu
@ 2016-05-11 15:45   ` Arnaldo Carvalho de Melo
  2016-05-12  2:02     ` Masami Hiramatsu
  0 siblings, 1 reply; 37+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-05-11 15:45 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: linux-kernel, Namhyung Kim, Peter Zijlstra, Ingo Molnar,
	Hemant Kumar, Ananth N Mavinakayanahalli, Brendan Gregg

Em Wed, May 11, 2016 at 10:51:37PM +0900, Masami Hiramatsu escreveu:
> Fix to set correct dso name ("[kernel.kallsyms]") for
> kallsyms, as for vdso does.

Can you rewrite the above comment and also break this down in two
patches, probably decribing what is the problem that it fixes?

- Arnaldo
 
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>  tools/perf/util/build-id.c |   12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> index b6ecf87..234d8a1 100644
> --- a/tools/perf/util/build-id.c
> +++ b/tools/perf/util/build-id.c
> @@ -343,21 +343,25 @@ void disable_buildid_cache(void)
>  static char *build_id_cache__dirname_from_path(const char *name,
>  					       bool is_kallsyms, bool is_vdso)
>  {
> -	char *realname = (char *)name, *filename;
> +	const char *realname = name;
> +	char *filename;
>  	bool slash = is_kallsyms || is_vdso;
>  
>  	if (!slash) {
>  		realname = realpath(name, NULL);
>  		if (!realname)
>  			return NULL;
> -	}
> +	} else if (is_vdso)
> +		realname = DSO__NAME_VDSO;
> +	else
> +		realname = "[kernel.kallsyms]";
>  
>  	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
> -		     is_vdso ? DSO__NAME_VDSO : realname) < 0)
> +		     realname) < 0)
>  		filename = NULL;
>  
>  	if (!slash)
> -		free(realname);
> +		free((char *)realname);
>  
>  	return filename;
>  }

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 04/21] perf: Use SBUILD_ID_SIZE macro instead of BUILD_ID_SIZE macro
  2016-05-11 13:51 ` [PATCH perf/core v7 04/21] perf: Use SBUILD_ID_SIZE macro instead of BUILD_ID_SIZE macro Masami Hiramatsu
@ 2016-05-11 15:47   ` Arnaldo Carvalho de Melo
  2016-05-12 10:25   ` [tip:perf/core] perf tools: Use SBUILD_ID_SIZE where applicable tip-bot for Masami Hiramatsu
  1 sibling, 0 replies; 37+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-05-11 15:47 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: linux-kernel, Namhyung Kim, Peter Zijlstra, Ingo Molnar,
	Hemant Kumar, Ananth N Mavinakayanahalli, Brendan Gregg

Em Wed, May 11, 2016 at 10:51:59PM +0900, Masami Hiramatsu escreveu:
> Use SBUILD_ID_SIZE macro instead of BUILD_ID_SIZE * 2 + 1 for
> allocating a buffer for build-id string.

Applied
 
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>  tools/perf/util/annotate.c                         |    2 +-
>  tools/perf/util/dso.c                              |    4 ++--
>  tools/perf/util/header.c                           |    2 +-
>  tools/perf/util/map.c                              |    2 +-
>  .../util/scripting-engines/trace-event-python.c    |    2 +-
>  tools/perf/util/symbol.c                           |    2 +-
>  6 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> index 1168442..b811924 100644
> --- a/tools/perf/util/annotate.c
> +++ b/tools/perf/util/annotate.c
> @@ -1138,7 +1138,7 @@ fallback:
>  
>  	if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
>  	    !dso__is_kcore(dso)) {
> -		char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
> +		char bf[SBUILD_ID_SIZE + 15] = " with build id ";
>  		char *build_id_msg = NULL;
>  
>  		if (dso->annotate_warned)
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index 8e639543..3357479 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -38,7 +38,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
>  				   enum dso_binary_type type,
>  				   char *root_dir, char *filename, size_t size)
>  {
> -	char build_id_hex[BUILD_ID_SIZE * 2 + 1];
> +	char build_id_hex[SBUILD_ID_SIZE];
>  	int ret = 0;
>  	size_t len;
>  
> @@ -1301,7 +1301,7 @@ size_t __dsos__fprintf(struct list_head *head, FILE *fp)
>  
>  size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
>  {
> -	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
> +	char sbuild_id[SBUILD_ID_SIZE];
>  
>  	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
>  	return fprintf(fp, "%s", sbuild_id);
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index c6000d4..08852dd 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -1474,7 +1474,7 @@ static int __event_process_build_id(struct build_id_event *bev,
>  
>  	dso = machine__findnew_dso(machine, filename);
>  	if (dso != NULL) {
> -		char sbuild_id[BUILD_ID_SIZE * 2 + 1];
> +		char sbuild_id[SBUILD_ID_SIZE];
>  
>  		dso__set_build_id(dso, &bev->build_id);
>  
> diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
> index 02c3186..b19bcd3 100644
> --- a/tools/perf/util/map.c
> +++ b/tools/perf/util/map.c
> @@ -289,7 +289,7 @@ int map__load(struct map *map, symbol_filter_t filter)
>  	nr = dso__load(map->dso, map, filter);
>  	if (nr < 0) {
>  		if (map->dso->has_build_id) {
> -			char sbuild_id[BUILD_ID_SIZE * 2 + 1];
> +			char sbuild_id[SBUILD_ID_SIZE];
>  
>  			build_id__sprintf(map->dso->build_id,
>  					  sizeof(map->dso->build_id),
> diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
> index 73ee12d..ff13470 100644
> --- a/tools/perf/util/scripting-engines/trace-event-python.c
> +++ b/tools/perf/util/scripting-engines/trace-event-python.c
> @@ -618,7 +618,7 @@ static int python_export_dso(struct db_export *dbe, struct dso *dso,
>  			     struct machine *machine)
>  {
>  	struct tables *tables = container_of(dbe, struct tables, dbe);
> -	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
> +	char sbuild_id[SBUILD_ID_SIZE];
>  	PyObject *t;
>  
>  	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index 49caa91..18d81c1 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -1630,7 +1630,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
>  static char *dso__find_kallsyms(struct dso *dso, struct map *map)
>  {
>  	u8 host_build_id[BUILD_ID_SIZE];
> -	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
> +	char sbuild_id[SBUILD_ID_SIZE];
>  	bool is_host = false;
>  	char path[PATH_MAX];
>  

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 03/21] perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE
  2016-05-11 13:51 ` [PATCH perf/core v7 03/21] perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE Masami Hiramatsu
@ 2016-05-11 15:47   ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 37+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-05-11 15:47 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: linux-kernel, Namhyung Kim, Peter Zijlstra, Ingo Molnar,
	Hemant Kumar, Ananth N Mavinakayanahalli, Brendan Gregg

Em Wed, May 11, 2016 at 10:51:49PM +0900, Masami Hiramatsu escreveu:
> Instead of using raw string, use DSO__NAME_KALLSYMS and DSO__NAME_KCORE
> macros for kallsyms and kcore.

Depends on the previous patch,

- Arnaldo
 
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>  tools/perf/builtin-buildid-cache.c |    8 ++++----
>  tools/perf/util/annotate.c         |    2 +-
>  tools/perf/util/build-id.c         |    2 +-
>  tools/perf/util/machine.c          |    2 +-
>  tools/perf/util/symbol.c           |   10 +++++-----
>  tools/perf/util/symbol.h           |    3 +++
>  6 files changed, 15 insertions(+), 12 deletions(-)
> 
> diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
> index 632efc6..d75bded 100644
> --- a/tools/perf/builtin-buildid-cache.c
> +++ b/tools/perf/builtin-buildid-cache.c
> @@ -119,8 +119,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
>  	if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0)
>  		return -1;
>  
> -	scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
> -		  buildid_dir, sbuildid);
> +	scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s",
> +		  buildid_dir, DSO__NAME_KCORE, sbuildid);
>  
>  	if (!force &&
>  	    !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
> @@ -131,8 +131,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
>  	if (build_id_cache__kcore_dir(dir, sizeof(dir)))
>  		return -1;
>  
> -	scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
> -		  buildid_dir, sbuildid, dir);
> +	scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s/%s",
> +		  buildid_dir, DSO__NAME_KCORE, sbuildid, dir);
>  
>  	if (mkdir_p(to_dir, 0755))
>  		return -1;
> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> index d4b3d03..1168442 100644
> --- a/tools/perf/util/annotate.c
> +++ b/tools/perf/util/annotate.c
> @@ -1122,7 +1122,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
>  	} else if (dso__is_kcore(dso)) {
>  		goto fallback;
>  	} else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
> -		   strstr(command, "[kernel.kallsyms]") ||
> +		   strstr(command, DSO__NAME_KALLSYMS) ||
>  		   access(symfs_filename, R_OK)) {
>  		free(filename);
>  fallback:
> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> index 234d8a1..53df9aa 100644
> --- a/tools/perf/util/build-id.c
> +++ b/tools/perf/util/build-id.c
> @@ -354,7 +354,7 @@ static char *build_id_cache__dirname_from_path(const char *name,
>  	} else if (is_vdso)
>  		realname = DSO__NAME_VDSO;
>  	else
> -		realname = "[kernel.kallsyms]";
> +		realname = DSO__NAME_KALLSYMS;
>  
>  	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
>  		     realname) < 0)
> diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
> index 639a290..18dd96b 100644
> --- a/tools/perf/util/machine.c
> +++ b/tools/perf/util/machine.c
> @@ -709,7 +709,7 @@ static struct dso *machine__get_kernel(struct machine *machine)
>  	if (machine__is_host(machine)) {
>  		vmlinux_name = symbol_conf.vmlinux_name;
>  		if (!vmlinux_name)
> -			vmlinux_name = "[kernel.kallsyms]";
> +			vmlinux_name = DSO__NAME_KALLSYMS;
>  
>  		kernel = machine__findnew_kernel(machine, vmlinux_name,
>  						 "[kernel]", DSO_TYPE_KERNEL);
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index 2946295..49caa91 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -1648,8 +1648,8 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
>  
>  	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
>  
> -	scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir,
> -		  sbuild_id);
> +	scnprintf(path, sizeof(path), "%s/%s/%s", buildid_dir,
> +		  DSO__NAME_KCORE, sbuild_id);
>  
>  	/* Use /proc/kallsyms if possible */
>  	if (is_host) {
> @@ -1685,8 +1685,8 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
>  	if (!find_matching_kcore(map, path, sizeof(path)))
>  		return strdup(path);
>  
> -	scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
> -		  buildid_dir, sbuild_id);
> +	scnprintf(path, sizeof(path), "%s/%s/%s",
> +		  buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
>  
>  	if (access(path, F_OK)) {
>  		pr_err("No kallsyms or vmlinux with build-id %s was found\n",
> @@ -1755,7 +1755,7 @@ do_kallsyms:
>  
>  	if (err > 0 && !dso__is_kcore(dso)) {
>  		dso->binary_type = DSO_BINARY_TYPE__KALLSYMS;
> -		dso__set_long_name(dso, "[kernel.kallsyms]", false);
> +		dso__set_long_name(dso, DSO__NAME_KALLSYMS, false);
>  		map__fixup_start(map);
>  		map__fixup_end(map);
>  	}
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index 07211c2..78e3bbf 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -44,6 +44,9 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
>  #define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
>  #endif
>  
> +#define DSO__NAME_KALLSYMS	"[kernel.kallsyms]"
> +#define DSO__NAME_KCORE		"[kernel.kcore]"
> +
>  /** struct symbol - symtab entry
>   *
>   * @ignore - resolvable but tools ignore it (e.g. idle routines)

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 05/21] perf symbol: Use lsdir for search in kcore cache directory
  2016-05-11 13:52 ` [PATCH perf/core v7 05/21] perf symbol: Use lsdir for search in kcore cache directory Masami Hiramatsu
@ 2016-05-11 15:49   ` Arnaldo Carvalho de Melo
  2016-05-12 10:26   ` [tip:perf/core] perf symbols: Use lsdir() for the " tip-bot for Masami Hiramatsu
  1 sibling, 0 replies; 37+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-05-11 15:49 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: linux-kernel, Namhyung Kim, Peter Zijlstra, Ingo Molnar,
	Hemant Kumar, Ananth N Mavinakayanahalli, Brendan Gregg

Em Wed, May 11, 2016 at 10:52:08PM +0900, Masami Hiramatsu escreveu:
> Use lsdir for search in kcore cache directory. This also
> avoid checking hidden dot directory entries, because
> kcore cache directories must always have the name from
> timestamps when taking the kcore snapshots, and it never
> start with dot.

Applied

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 06/21] perf-buildid-cache: Use lsdir for looking up buildid caches
  2016-05-11 13:52 ` [PATCH perf/core v7 06/21] perf-buildid-cache: Use lsdir for looking up buildid caches Masami Hiramatsu
@ 2016-05-11 15:50   ` Arnaldo Carvalho de Melo
  2016-05-12 10:26   ` [tip:perf/core] perf buildid-cache: Use lsdir() " tip-bot for Masami Hiramatsu
  1 sibling, 0 replies; 37+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-05-11 15:50 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: linux-kernel, Namhyung Kim, Peter Zijlstra, Ingo Molnar,
	Hemant Kumar, Ananth N Mavinakayanahalli, Brendan Gregg

Em Wed, May 11, 2016 at 10:52:17PM +0900, Masami Hiramatsu escreveu:
> From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> 
> 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.

Applied
 
> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>  Changes in v7:
>   - Remove unneeded local strlist.
> ---
>  tools/perf/util/build-id.c |   30 ++++--------------------------
>  1 file changed, 4 insertions(+), 26 deletions(-)
> 
> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> index 53df9aa..2cb6454 100644
> --- a/tools/perf/util/build-id.c
> +++ b/tools/perf/util/build-id.c
> @@ -369,39 +369,17 @@ static char *build_id_cache__dirname_from_path(const char *name,
>  int build_id_cache__list_build_ids(const char *pathname,
>  				   struct strlist **result)
>  {
> -	struct strlist *list;
>  	char *dir_name;
> -	DIR *dir;
> -	struct dirent *d;
>  	int ret = 0;
>  
> -	list = strlist__new(NULL, NULL);
>  	dir_name = build_id_cache__dirname_from_path(pathname, false, false);
> -	if (!list || !dir_name) {
> -		ret = -ENOMEM;
> -		goto out;
> -	}
> +	if (!dir_name)
> +		return -ENOMEM;
>  
> -	/* List up all dirents */
> -	dir = opendir(dir_name);
> -	if (!dir) {
> +	*result = lsdir(dir_name, lsdir_no_dot_filter);
> +	if (!*result)
>  		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:
>  	free(dir_name);
> -	if (ret)
> -		strlist__delete(list);
> -	else
> -		*result = list;
>  
>  	return ret;
>  }

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms
  2016-05-11 13:52 ` [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms Masami Hiramatsu
@ 2016-05-11 15:55   ` Arnaldo Carvalho de Melo
  2016-05-12  1:46     ` Masami Hiramatsu
  0 siblings, 1 reply; 37+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-05-11 15:55 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: linux-kernel, Namhyung Kim, Peter Zijlstra, Ingo Molnar,
	Hemant Kumar, Ananth N Mavinakayanahalli, Brendan Gregg

Em Wed, May 11, 2016 at 10:52:27PM +0900, Masami Hiramatsu escreveu:
> Cleanup the code flow of dso__find_kallsyms() to remove
> redundant checking code and add some comment for readability.
> 
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>  tools/perf/util/symbol.c |   60 +++++++++++++++++++++-------------------------
>  1 file changed, 27 insertions(+), 33 deletions(-)
> 
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index e112bbd..b2b06b7 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -1629,6 +1629,15 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
>  	return ret;
>  }
>  
> +static bool filename__readable(const char *file)
> +{
> +	int fd = open(file, O_RDONLY);
> +	if (fd < 0)
> +		return false;
> +	close(fd);
> +	return true;
> +}

Do we really have to use this big hammer just for checking if a file is
readable? What is wronte with:

	access(pathname, R_OK)

?

I see, you're keeping the existing logic, but since you've gone to the
trouble of introducing a seemingly generic function like
filename__readable(), you could as well use the canonical way to check
if a file is readable, namely access(R_OK), no?

Adrian, is there something magical about /proc/kcore for this test to be
done that way? If so, we better document not to waste our time next time
we look at this...

- Arnaldo

> +
>  static char *dso__find_kallsyms(struct dso *dso, struct map *map)
>  {
>  	u8 host_build_id[BUILD_ID_SIZE];
> @@ -1648,45 +1657,33 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
>  				 sizeof(host_build_id)) == 0)
>  		is_host = dso__build_id_equal(dso, host_build_id);
>  
> -	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
> -
> -	scnprintf(path, sizeof(path), "%s/%s/%s", buildid_dir,
> -		  DSO__NAME_KCORE, sbuild_id);
> -
> -	/* Use /proc/kallsyms if possible */
> +	/* Try a fast path for /proc/kallsyms if possible */

How that improves the previous comment?

>  	if (is_host) {
> -		DIR *d;
> -		int fd;
> -
> -		/* If no cached kcore go with /proc/kallsyms */
> -		d = opendir(path);
> -		if (!d)
> -			goto proc_kallsyms;
> -		closedir(d);
> -
>  		/*
> -		 * Do not check the build-id cache, until we know we cannot use
> -		 * /proc/kcore.
> +		 * Do not check the build-id cache, unless we know we cannot use
> +		 * /proc/kcore or module maps don't match to /proc/kallsyms.
>  		 */
> -		fd = open("/proc/kcore", O_RDONLY);
> -		if (fd != -1) {
> -			close(fd);
> -			/* If module maps match go with /proc/kallsyms */
> -			if (!validate_kcore_addresses("/proc/kallsyms", map))
> -				goto proc_kallsyms;
> -		}
> -
> -		/* Find kallsyms in build-id cache with kcore */
> -		if (!find_matching_kcore(map, path, sizeof(path)))
> -			return strdup(path);
> -
> -		goto proc_kallsyms;
> +		if (filename__readable("/proc/kcore") &&
> +		    !validate_kcore_addresses("/proc/kallsyms", map))
> +			goto proc_kallsyms;
>  	}
>  
> +	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
> +
>  	/* Find kallsyms in build-id cache with kcore */
> +	scnprintf(path, sizeof(path), "%s/%s/%s",
> +		  buildid_dir, DSO__NAME_KCORE, sbuild_id);
> +
>  	if (!find_matching_kcore(map, path, sizeof(path)))
>  		return strdup(path);
>  
> +	/* Use current /proc/kallsyms if possible */
> +	if (is_host) {
> +proc_kallsyms:
> +		return strdup("/proc/kallsyms");
> +	}
> +
> +	/* Finally, find a cache of kallsyms */
>  	scnprintf(path, sizeof(path), "%s/%s/%s",
>  		  buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
>  
> @@ -1697,9 +1694,6 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
>  	}
>  
>  	return strdup(path);
> -
> -proc_kallsyms:
> -	return strdup("/proc/kallsyms");
>  }
>  
>  static int dso__load_kernel_sym(struct dso *dso, struct map *map,

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms
  2016-05-11 15:55   ` Arnaldo Carvalho de Melo
@ 2016-05-12  1:46     ` Masami Hiramatsu
  0 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-12  1:46 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, Namhyung Kim, Peter Zijlstra, Ingo Molnar,
	Hemant Kumar, Ananth N Mavinakayanahalli, Brendan Gregg

On Wed, 11 May 2016 12:55:50 -0300
Arnaldo Carvalho de Melo <acme@kernel.org> wrote:

> Em Wed, May 11, 2016 at 10:52:27PM +0900, Masami Hiramatsu escreveu:
> > Cleanup the code flow of dso__find_kallsyms() to remove
> > redundant checking code and add some comment for readability.
> > 
> > Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> > ---
> >  tools/perf/util/symbol.c |   60 +++++++++++++++++++++-------------------------
> >  1 file changed, 27 insertions(+), 33 deletions(-)
> > 
> > diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> > index e112bbd..b2b06b7 100644
> > --- a/tools/perf/util/symbol.c
> > +++ b/tools/perf/util/symbol.c
> > @@ -1629,6 +1629,15 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
> >  	return ret;
> >  }
> >  
> > +static bool filename__readable(const char *file)
> > +{
> > +	int fd = open(file, O_RDONLY);
> > +	if (fd < 0)
> > +		return false;
> > +	close(fd);
> > +	return true;
> > +}
> 
> Do we really have to use this big hammer just for checking if a file is
> readable? What is wronte with:
> 
> 	access(pathname, R_OK)
> 
> ?

Yes, I actually had done that at prototyping. But as the manpage of access
said, access() checks accessibility by real uid/gid, but open() checks
by effective uid/gid. So, I considered this could cause unexpected
issue if we decided to use setuid(). I just wanted to check it was OK.

> I see, you're keeping the existing logic, but since you've gone to the
> trouble of introducing a seemingly generic function like
> filename__readable(), you could as well use the canonical way to check
> if a file is readable, namely access(R_OK), no?

I agreed in general :) If we don't can use access(R_OK) I'd like to use it.

> 
> Adrian, is there something magical about /proc/kcore for this test to be
> done that way? If so, we better document not to waste our time next time
> we look at this...

Ah, right. At least I had to write a comment about it.

Thank you,

> 
> - Arnaldo
> 
> > +
> >  static char *dso__find_kallsyms(struct dso *dso, struct map *map)
> >  {
> >  	u8 host_build_id[BUILD_ID_SIZE];
> > @@ -1648,45 +1657,33 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
> >  				 sizeof(host_build_id)) == 0)
> >  		is_host = dso__build_id_equal(dso, host_build_id);
> >  
> > -	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
> > -
> > -	scnprintf(path, sizeof(path), "%s/%s/%s", buildid_dir,
> > -		  DSO__NAME_KCORE, sbuild_id);
> > -
> > -	/* Use /proc/kallsyms if possible */
> > +	/* Try a fast path for /proc/kallsyms if possible */
> 
> How that improves the previous comment?
> 
> >  	if (is_host) {
> > -		DIR *d;
> > -		int fd;
> > -
> > -		/* If no cached kcore go with /proc/kallsyms */
> > -		d = opendir(path);
> > -		if (!d)
> > -			goto proc_kallsyms;
> > -		closedir(d);
> > -
> >  		/*
> > -		 * Do not check the build-id cache, until we know we cannot use
> > -		 * /proc/kcore.
> > +		 * Do not check the build-id cache, unless we know we cannot use
> > +		 * /proc/kcore or module maps don't match to /proc/kallsyms.
> >  		 */
> > -		fd = open("/proc/kcore", O_RDONLY);
> > -		if (fd != -1) {
> > -			close(fd);
> > -			/* If module maps match go with /proc/kallsyms */
> > -			if (!validate_kcore_addresses("/proc/kallsyms", map))
> > -				goto proc_kallsyms;
> > -		}
> > -
> > -		/* Find kallsyms in build-id cache with kcore */
> > -		if (!find_matching_kcore(map, path, sizeof(path)))
> > -			return strdup(path);
> > -
> > -		goto proc_kallsyms;
> > +		if (filename__readable("/proc/kcore") &&
> > +		    !validate_kcore_addresses("/proc/kallsyms", map))
> > +			goto proc_kallsyms;
> >  	}
> >  
> > +	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
> > +
> >  	/* Find kallsyms in build-id cache with kcore */
> > +	scnprintf(path, sizeof(path), "%s/%s/%s",
> > +		  buildid_dir, DSO__NAME_KCORE, sbuild_id);
> > +
> >  	if (!find_matching_kcore(map, path, sizeof(path)))
> >  		return strdup(path);
> >  
> > +	/* Use current /proc/kallsyms if possible */
> > +	if (is_host) {
> > +proc_kallsyms:
> > +		return strdup("/proc/kallsyms");
> > +	}
> > +
> > +	/* Finally, find a cache of kallsyms */
> >  	scnprintf(path, sizeof(path), "%s/%s/%s",
> >  		  buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
> >  
> > @@ -1697,9 +1694,6 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
> >  	}
> >  
> >  	return strdup(path);
> > -
> > -proc_kallsyms:
> > -	return strdup("/proc/kallsyms");
> >  }
> >  
> >  static int dso__load_kernel_sym(struct dso *dso, struct map *map,


-- 
Masami Hiramatsu <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly
  2016-05-11 13:59   ` Arnaldo Carvalho de Melo
@ 2016-05-12  1:46     ` Masami Hiramatsu
  0 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-12  1:46 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, Namhyung Kim, Peter Zijlstra, Ingo Molnar,
	Hemant Kumar, Ananth N Mavinakayanahalli, Brendan Gregg

Hi Arnaldo,

On Wed, 11 May 2016 10:59:39 -0300
Arnaldo Carvalho de Melo <acme@kernel.org> wrote:

> Em Wed, May 11, 2016 at 10:51:27PM +0900, Masami Hiramatsu escreveu:
> > Fix lsdir() to set correct positive error number (ENOMEM).
> > Since "errno" must have a positive error number instead of
> > negative number, fix lsdir to set it correctly.
> 
> Masami, please try to:
> 
> 1) Follow existing convention when writing the patch Subject line, when
> in doubt: git log tools/perf/util/util.c and check, in this case I
> changed it to "perf tools: Fix lsdir to set errno correctly"

OK, I see.

> 2) Add a Fixed line, for this case I used 'git blame' and added:
> 
> Fixes: e1ce726e1db2 ("perf tools: Add lsdir() helper to read a directory")
> 
> This helps reviewing (now and down the line), because one can go more
> quickly check what was the intention in the original patch, to see if it
> is really a fix.

Oops! I just missed that. Of course I will do.

> 
> In some cases this looks trivial, like in this patch, sometimes its
> not...

I see.

Thank you,

> 
> Thanks,
> 
> - Arnaldo
>  
> > Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> > ---
> >  tools/perf/util/util.c |    2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
> > index 01c9433..eab077a 100644
> > --- a/tools/perf/util/util.c
> > +++ b/tools/perf/util/util.c
> > @@ -139,7 +139,7 @@ struct strlist *lsdir(const char *name,
> >  
> >  	list = strlist__new(NULL, NULL);
> >  	if (!list) {
> > -		errno = -ENOMEM;
> > +		errno = ENOMEM;
> >  		goto out;
> >  	}
> >  


-- 
Masami Hiramatsu <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms
  2016-05-11 15:45   ` Arnaldo Carvalho de Melo
@ 2016-05-12  2:02     ` Masami Hiramatsu
  2016-05-12  8:57       ` Masami Hiramatsu
  0 siblings, 1 reply; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-12  2:02 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, Namhyung Kim, Peter Zijlstra, Ingo Molnar,
	Hemant Kumar, Ananth N Mavinakayanahalli, Brendan Gregg

On Wed, 11 May 2016 12:45:00 -0300
Arnaldo Carvalho de Melo <acme@kernel.org> wrote:

> Em Wed, May 11, 2016 at 10:51:37PM +0900, Masami Hiramatsu escreveu:
> > Fix to set correct dso name ("[kernel.kallsyms]") for
> > kallsyms, as for vdso does.
> 
> Can you rewrite the above comment and also break this down in two
> patches,

No, could you explain what parts this consists of?
I think this patch is done just one thing. Actually I can rewrite
this as one-line patch like below

  	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
-		     is_vdso ? DSO__NAME_VDSO : realname) < 0)
+		     is_vdso ? DSO__NAME_VDSO : (is_kallsyms ? "[kernel.kallsyms]": realname)) < 0)

But indeed this is not readable so clean it up like below.

> probably decribing what is the problem that it fixes?

Ah, indeed. This is actually not a fix for existing bug, instead
it will prevent buggy behavior. Current function can get any filepath
with is_vdso = true or is_kallsyms = true, but it seems easily giving
contradictory combination.

Hmm, OK, I think I have to solve this issue in another way.

Thanks!

> 
> - Arnaldo
>  
> > Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> > ---
> >  tools/perf/util/build-id.c |   12 ++++++++----
> >  1 file changed, 8 insertions(+), 4 deletions(-)
> > 
> > diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> > index b6ecf87..234d8a1 100644
> > --- a/tools/perf/util/build-id.c
> > +++ b/tools/perf/util/build-id.c
> > @@ -343,21 +343,25 @@ void disable_buildid_cache(void)
> >  static char *build_id_cache__dirname_from_path(const char *name,
> >  					       bool is_kallsyms, bool is_vdso)
> >  {
> > -	char *realname = (char *)name, *filename;
> > +	const char *realname = name;
> > +	char *filename;
> >  	bool slash = is_kallsyms || is_vdso;
> >  
> >  	if (!slash) {
> >  		realname = realpath(name, NULL);
> >  		if (!realname)
> >  			return NULL;
> > -	}
> > +	} else if (is_vdso)
> > +		realname = DSO__NAME_VDSO;
> > +	else
> > +		realname = "[kernel.kallsyms]";
> >  
> >  	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
> > -		     is_vdso ? DSO__NAME_VDSO : realname) < 0)
> > +		     realname) < 0)
> >  		filename = NULL;
> >  
> >  	if (!slash)
> > -		free(realname);
> > +		free((char *)realname);
> >  
> >  	return filename;
> >  }


-- 
Masami Hiramatsu <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms
  2016-05-12  2:02     ` Masami Hiramatsu
@ 2016-05-12  8:57       ` Masami Hiramatsu
  0 siblings, 0 replies; 37+ messages in thread
From: Masami Hiramatsu @ 2016-05-12  8:57 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Arnaldo Carvalho de Melo, linux-kernel, Namhyung Kim,
	Peter Zijlstra, Ingo Molnar, Hemant Kumar,
	Ananth N Mavinakayanahalli, Brendan Gregg

On Thu, 12 May 2016 11:02:12 +0900
Masami Hiramatsu <mhiramat@kernel.org> wrote:

> On Wed, 11 May 2016 12:45:00 -0300
> Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> 
> > Em Wed, May 11, 2016 at 10:51:37PM +0900, Masami Hiramatsu escreveu:
> > > Fix to set correct dso name ("[kernel.kallsyms]") for
> > > kallsyms, as for vdso does.
> > 
> > Can you rewrite the above comment and also break this down in two
> > patches,
> 
> No, could you explain what parts this consists of?
> I think this patch is done just one thing. Actually I can rewrite
> this as one-line patch like below
> 
>   	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
> -		     is_vdso ? DSO__NAME_VDSO : realname) < 0)
> +		     is_vdso ? DSO__NAME_VDSO : (is_kallsyms ? "[kernel.kallsyms]": realname)) < 0)
> 
> But indeed this is not readable so clean it up like below.
> 
> > probably decribing what is the problem that it fixes?
> 
> Ah, indeed. This is actually not a fix for existing bug, instead
> it will prevent buggy behavior. Current function can get any filepath
> with is_vdso = true or is_kallsyms = true, but it seems easily giving
> contradictory combination.
> 
> Hmm, OK, I think I have to solve this issue in another way.

OK, from further investigation, I found this is not a real bug, but
just an unneeded behavior changing. At this moment, I should drop this
from the series. Here is what I understand.

At first, the path of the original binary is used only when storing
build-id caches.
When loading the cache, perf uses build-id symlink to access it.

OK, so this is the callgraph of build_id_cache__dirname_from_path.
'<-' shows the caller, and with what parameters given.
 
build_id_cache__dirname_from_path
	<- build_id_cache__add_s, with (pathname, is_kallsyms, is_vdso)
		<- build_id_cache__add_b, with (sbuild_id, name, is_kallsyms, is_vdso)
			<-dso__cache_build_id
		<- build_id_cache__add_file, with (sbuild_id,filepath,false,false)
		<- build_id_cache__update_file, with (sbuild_id,filepath,false,false)
	<- build_id_cache__list_build_ids, with (pathname, false, false)

Focusing on the is_kallsyms and is_vdso, the callgraph to
build_id_cache__list_build_ids(), build_id_cache__add_file()
and build_id_cache__update_file() are not using those parameters.
These functions just pass the file path, so we can ignore.
(BTW, in this case we can not remove/purge the caches for vdso, kallsyms and
 kcore from buildid directory ...)

The last callgraph is dso__cache_build_id(), and only it uses is_kallsyms and is_vdso.
Those parameters are given as below

  is_kallsyms = dso->kernel && dso->long_name[0] != '/'
  is_vdso = dso__is_vdso(dso) <- check the dso->short_name is DSO__NAME_VDSO*
  pathname = dso->long_name

So, is_vdso == true, build_id_cache__dirname_from_path() stores all
DSO__NAME_VDSO* ("[vdso]", "[vdso32]", and "[vdsox32]") caches under
DSO__NAME_VDSO("[vdso]").

This seems is_kallsyms == true, the pathname has no real filename.

And the kernel dso will be made by machine__get_kernel(), which sets the
kernel dso's long name is whether the user given (guest)vmlinux name or
the name given by machine__mmap_name(). The machine__mmap_name() returns
[kernel.kallsyms], [guest.kernel.kallsyms] or [guest.kernel.kallsyms.<PID>].

OK, so the question is, should we do same thing on kallsyms as vdso?
This patch actually tried it, all the "[*kernel.kallsyms*]" dso caches
stored under "[kernel.kallsyms]".

Thank you,


> >  
> > > Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> > > ---
> > >  tools/perf/util/build-id.c |   12 ++++++++----
> > >  1 file changed, 8 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> > > index b6ecf87..234d8a1 100644
> > > --- a/tools/perf/util/build-id.c
> > > +++ b/tools/perf/util/build-id.c
> > > @@ -343,21 +343,25 @@ void disable_buildid_cache(void)
> > >  static char *build_id_cache__dirname_from_path(const char *name,
> > >  					       bool is_kallsyms, bool is_vdso)
> > >  {
> > > -	char *realname = (char *)name, *filename;
> > > +	const char *realname = name;
> > > +	char *filename;
> > >  	bool slash = is_kallsyms || is_vdso;
> > >  
> > >  	if (!slash) {
> > >  		realname = realpath(name, NULL);
> > >  		if (!realname)
> > >  			return NULL;
> > > -	}
> > > +	} else if (is_vdso)
> > > +		realname = DSO__NAME_VDSO;
> > > +	else
> > > +		realname = "[kernel.kallsyms]";
> > >  
> > >  	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
> > > -		     is_vdso ? DSO__NAME_VDSO : realname) < 0)
> > > +		     realname) < 0)
> > >  		filename = NULL;
> > >  
> > >  	if (!slash)
> > > -		free(realname);
> > > +		free((char *)realname);
> > >  
> > >  	return filename;
> > >  }
> 
> 
> -- 
> Masami Hiramatsu <mhiramat@kernel.org>


-- 
Masami Hiramatsu <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [tip:perf/core] perf tools: Fix lsdir to set errno correctly
  2016-05-11 13:51 ` [PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly Masami Hiramatsu
  2016-05-11 13:59   ` Arnaldo Carvalho de Melo
@ 2016-05-12 10:25   ` tip-bot for Masami Hiramatsu
  1 sibling, 0 replies; 37+ messages in thread
From: tip-bot for Masami Hiramatsu @ 2016-05-12 10:25 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, linux-kernel, mhiramat, acme, mingo, ananth,
	brendan.d.gregg, namhyung, tglx, hemant, hpa

Commit-ID:  357a54f32a065835d3e6a08b07a91a57e52f32c7
Gitweb:     http://git.kernel.org/tip/357a54f32a065835d3e6a08b07a91a57e52f32c7
Author:     Masami Hiramatsu <mhiramat@kernel.org>
AuthorDate: Wed, 11 May 2016 22:51:27 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 11 May 2016 13:06:05 -0300

perf tools: Fix lsdir to set errno correctly

Fix lsdir() to set correct positive error number (ENOMEM).  Since
"errno" must have a positive error number instead of negative number,
fix lsdir to set it correctly.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Fixes: e1ce726e1db2 ("perf tools: Add lsdir() helper to read a directory")
Link: http://lkml.kernel.org/r/20160511135127.23943.40644.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 01c9433..eab077a 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -139,7 +139,7 @@ struct strlist *lsdir(const char *name,
 
 	list = strlist__new(NULL, NULL);
 	if (!list) {
-		errno = -ENOMEM;
+		errno = ENOMEM;
 		goto out;
 	}
 

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [tip:perf/core] perf tools: Use SBUILD_ID_SIZE where applicable
  2016-05-11 13:51 ` [PATCH perf/core v7 04/21] perf: Use SBUILD_ID_SIZE macro instead of BUILD_ID_SIZE macro Masami Hiramatsu
  2016-05-11 15:47   ` Arnaldo Carvalho de Melo
@ 2016-05-12 10:25   ` tip-bot for Masami Hiramatsu
  1 sibling, 0 replies; 37+ messages in thread
From: tip-bot for Masami Hiramatsu @ 2016-05-12 10:25 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ananth, namhyung, tglx, linux-kernel, peterz, mingo, acme, hpa,
	mhiramat, hemant, brendan.d.gregg

Commit-ID:  b5d8bbe8601a45b908f7952707bbb30bf221ca3b
Gitweb:     http://git.kernel.org/tip/b5d8bbe8601a45b908f7952707bbb30bf221ca3b
Author:     Masami Hiramatsu <mhiramat@kernel.org>
AuthorDate: Wed, 11 May 2016 22:51:59 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 11 May 2016 13:06:06 -0300

perf tools: Use SBUILD_ID_SIZE where applicable

Use the existing SBUILD_ID_SIZE macro instead of the equivalent
BUILD_ID_SIZE * 2 + 1 expression for allocating a buffer for build-id
strings.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20160511135159.23943.57120.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/annotate.c                             | 2 +-
 tools/perf/util/dso.c                                  | 4 ++--
 tools/perf/util/header.c                               | 2 +-
 tools/perf/util/map.c                                  | 2 +-
 tools/perf/util/scripting-engines/trace-event-python.c | 2 +-
 tools/perf/util/symbol.c                               | 2 +-
 6 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index d4b3d03..4db73d5 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1138,7 +1138,7 @@ fallback:
 
 	if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
 	    !dso__is_kcore(dso)) {
-		char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
+		char bf[SBUILD_ID_SIZE + 15] = " with build id ";
 		char *build_id_msg = NULL;
 
 		if (dso->annotate_warned)
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 8e639543..3357479 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -38,7 +38,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
 				   enum dso_binary_type type,
 				   char *root_dir, char *filename, size_t size)
 {
-	char build_id_hex[BUILD_ID_SIZE * 2 + 1];
+	char build_id_hex[SBUILD_ID_SIZE];
 	int ret = 0;
 	size_t len;
 
@@ -1301,7 +1301,7 @@ size_t __dsos__fprintf(struct list_head *head, FILE *fp)
 
 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
 {
-	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+	char sbuild_id[SBUILD_ID_SIZE];
 
 	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
 	return fprintf(fp, "%s", sbuild_id);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c6000d4..08852dd 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1474,7 +1474,7 @@ static int __event_process_build_id(struct build_id_event *bev,
 
 	dso = machine__findnew_dso(machine, filename);
 	if (dso != NULL) {
-		char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+		char sbuild_id[SBUILD_ID_SIZE];
 
 		dso__set_build_id(dso, &bev->build_id);
 
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 02c3186..b19bcd3 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -289,7 +289,7 @@ int map__load(struct map *map, symbol_filter_t filter)
 	nr = dso__load(map->dso, map, filter);
 	if (nr < 0) {
 		if (map->dso->has_build_id) {
-			char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+			char sbuild_id[SBUILD_ID_SIZE];
 
 			build_id__sprintf(map->dso->build_id,
 					  sizeof(map->dso->build_id),
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 73ee12d..ff13470 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -618,7 +618,7 @@ static int python_export_dso(struct db_export *dbe, struct dso *dso,
 			     struct machine *machine)
 {
 	struct tables *tables = container_of(dbe, struct tables, dbe);
-	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+	char sbuild_id[SBUILD_ID_SIZE];
 	PyObject *t;
 
 	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 21af8e8..4ada5a4 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1642,7 +1642,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
 static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 {
 	u8 host_build_id[BUILD_ID_SIZE];
-	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+	char sbuild_id[SBUILD_ID_SIZE];
 	bool is_host = false;
 	char path[PATH_MAX];
 

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [tip:perf/core] perf symbols: Use lsdir() for the search in kcore cache directory
  2016-05-11 13:52 ` [PATCH perf/core v7 05/21] perf symbol: Use lsdir for search in kcore cache directory Masami Hiramatsu
  2016-05-11 15:49   ` Arnaldo Carvalho de Melo
@ 2016-05-12 10:26   ` tip-bot for Masami Hiramatsu
  1 sibling, 0 replies; 37+ messages in thread
From: tip-bot for Masami Hiramatsu @ 2016-05-12 10:26 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hemant, ananth, peterz, mhiramat, acme, hpa, mingo,
	brendan.d.gregg, namhyung, tglx

Commit-ID:  c48903b816e6cdffb09b473352851bf199d0c582
Gitweb:     http://git.kernel.org/tip/c48903b816e6cdffb09b473352851bf199d0c582
Author:     Masami Hiramatsu <mhiramat@kernel.org>
AuthorDate: Wed, 11 May 2016 22:52:08 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 11 May 2016 13:06:07 -0300

perf symbols: Use lsdir() for the search in kcore cache directory

Use lsdir() to search in kcore cache directory. This also avoids
checking hidden dot directory entries, because kcore cache directories
must always have the name from timestamps when taking the kcore
snapshots, and it never start with dot.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20160511135208.23943.68071.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/symbol.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 4ada5a4..7fb3330 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1608,25 +1608,27 @@ out:
 	return err;
 }
 
+static bool visible_dir_filter(const char *name, struct dirent *d)
+{
+	if (d->d_type != DT_DIR)
+		return false;
+	return lsdir_no_dot_filter(name, d);
+}
+
 static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
 {
 	char kallsyms_filename[PATH_MAX];
-	struct dirent *dent;
 	int ret = -1;
-	DIR *d;
+	struct strlist *dirs;
+	struct str_node *nd;
 
-	d = opendir(dir);
-	if (!d)
+	dirs = lsdir(dir, visible_dir_filter);
+	if (!dirs)
 		return -1;
 
-	while (1) {
-		dent = readdir(d);
-		if (!dent)
-			break;
-		if (dent->d_type != DT_DIR)
-			continue;
+	strlist__for_each(nd, dirs) {
 		scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
-			  "%s/%s/kallsyms", dir, dent->d_name);
+			  "%s/%s/kallsyms", dir, nd->s);
 		if (!validate_kcore_addresses(kallsyms_filename, map)) {
 			strlcpy(dir, kallsyms_filename, dir_sz);
 			ret = 0;
@@ -1634,7 +1636,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
 		}
 	}
 
-	closedir(d);
+	strlist__delete(dirs);
 
 	return ret;
 }

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [tip:perf/core] perf buildid-cache: Use lsdir() for looking up buildid caches
  2016-05-11 13:52 ` [PATCH perf/core v7 06/21] perf-buildid-cache: Use lsdir for looking up buildid caches Masami Hiramatsu
  2016-05-11 15:50   ` Arnaldo Carvalho de Melo
@ 2016-05-12 10:26   ` tip-bot for Masami Hiramatsu
  1 sibling, 0 replies; 37+ messages in thread
From: tip-bot for Masami Hiramatsu @ 2016-05-12 10:26 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, brendan.d.gregg, ananth, peterz, acme, namhyung,
	tglx, hpa, mingo, hemant, masami.hiramatsu.pt, mhiramat

Commit-ID:  d65444d2fba98dcd4fa028ffada39c36a46f0038
Gitweb:     http://git.kernel.org/tip/d65444d2fba98dcd4fa028ffada39c36a46f0038
Author:     Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
AuthorDate: Wed, 11 May 2016 22:52:17 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 11 May 2016 13:06:08 -0300

perf buildid-cache: Use lsdir() for looking up buildid caches

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 <mhiramat@kernel.org>
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20160511135217.23943.94596.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/build-id.c | 30 ++++--------------------------
 1 file changed, 4 insertions(+), 26 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index b6ecf87..bff425e 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -365,39 +365,17 @@ static char *build_id_cache__dirname_from_path(const char *name,
 int build_id_cache__list_build_ids(const char *pathname,
 				   struct strlist **result)
 {
-	struct strlist *list;
 	char *dir_name;
-	DIR *dir;
-	struct dirent *d;
 	int ret = 0;
 
-	list = strlist__new(NULL, NULL);
 	dir_name = build_id_cache__dirname_from_path(pathname, false, false);
-	if (!list || !dir_name) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!dir_name)
+		return -ENOMEM;
 
-	/* List up all dirents */
-	dir = opendir(dir_name);
-	if (!dir) {
+	*result = lsdir(dir_name, lsdir_no_dot_filter);
+	if (!*result)
 		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:
 	free(dir_name);
-	if (ret)
-		strlist__delete(list);
-	else
-		*result = list;
 
 	return ret;
 }

^ permalink raw reply related	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2016-05-12 10:27 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-11 13:51 [PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu
2016-05-11 13:51 ` [PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly Masami Hiramatsu
2016-05-11 13:59   ` Arnaldo Carvalho de Melo
2016-05-12  1:46     ` Masami Hiramatsu
2016-05-12 10:25   ` [tip:perf/core] perf tools: " tip-bot for Masami Hiramatsu
2016-05-11 13:51 ` [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms Masami Hiramatsu
2016-05-11 15:45   ` Arnaldo Carvalho de Melo
2016-05-12  2:02     ` Masami Hiramatsu
2016-05-12  8:57       ` Masami Hiramatsu
2016-05-11 13:51 ` [PATCH perf/core v7 03/21] perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE Masami Hiramatsu
2016-05-11 15:47   ` Arnaldo Carvalho de Melo
2016-05-11 13:51 ` [PATCH perf/core v7 04/21] perf: Use SBUILD_ID_SIZE macro instead of BUILD_ID_SIZE macro Masami Hiramatsu
2016-05-11 15:47   ` Arnaldo Carvalho de Melo
2016-05-12 10:25   ` [tip:perf/core] perf tools: Use SBUILD_ID_SIZE where applicable tip-bot for Masami Hiramatsu
2016-05-11 13:52 ` [PATCH perf/core v7 05/21] perf symbol: Use lsdir for search in kcore cache directory Masami Hiramatsu
2016-05-11 15:49   ` Arnaldo Carvalho de Melo
2016-05-12 10:26   ` [tip:perf/core] perf symbols: Use lsdir() for the " tip-bot for Masami Hiramatsu
2016-05-11 13:52 ` [PATCH perf/core v7 06/21] perf-buildid-cache: Use lsdir for looking up buildid caches Masami Hiramatsu
2016-05-11 15:50   ` Arnaldo Carvalho de Melo
2016-05-12 10:26   ` [tip:perf/core] perf buildid-cache: Use lsdir() " tip-bot for Masami Hiramatsu
2016-05-11 13:52 ` [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms Masami Hiramatsu
2016-05-11 15:55   ` Arnaldo Carvalho de Melo
2016-05-12  1:46     ` Masami Hiramatsu
2016-05-11 13:52 ` [PATCH perf/core v7 08/21] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid Masami Hiramatsu
2016-05-11 13:52 ` [PATCH perf/core v7 09/21] perf probe: Add --cache option to cache the probe definitions Masami Hiramatsu
2016-05-11 13:52 ` [PATCH perf/core v7 10/21] perf probe: Use cache entry if possible Masami Hiramatsu
2016-05-11 13:53 ` [PATCH perf/core v7 11/21] perf probe: Show all cached probes Masami Hiramatsu
2016-05-11 13:53 ` [PATCH perf/core v7 12/21] perf probe: Remove caches when --cache is given Masami Hiramatsu
2016-05-11 13:53 ` [PATCH perf/core v7 13/21] perf/sdt: ELF support for SDT Masami Hiramatsu
2016-05-11 13:53 ` [PATCH perf/core v7 14/21] perf probe: Add group name support Masami Hiramatsu
2016-05-11 13:54 ` [PATCH perf/core v7 15/21] perf buildid-cache: Scan and import user SDT events to probe cache Masami Hiramatsu
2016-05-11 13:54 ` [PATCH perf/core v7 16/21] perf probe: Accept %sdt and %cached event name Masami Hiramatsu
2016-05-11 13:54 ` [PATCH perf/core v7 17/21] perf-list: Show SDT and pre-cached events Masami Hiramatsu
2016-05-11 13:54 ` [PATCH perf/core v7 18/21] perf-list: Skip SDTs placed in invalid binaries Masami Hiramatsu
2016-05-11 13:54 ` [PATCH perf/core v7 19/21] perf probe: Allow wildcard for cached events Masami Hiramatsu
2016-05-11 13:54 ` [PATCH perf/core v7 20/21] perf probe: Support @BUILDID or @FILE suffix for SDT events Masami Hiramatsu
2016-05-11 13:55 ` [PATCH perf/core v7 21/21] perf probe: Support a special SDT probe format Masami Hiramatsu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.