aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2016-07-01 04:03:26 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-07-01 10:34:57 -0400
commit1f3736c9c833e40ac4d3a8dc6d661e341df8a259 (patch)
tree25181ab3dfea97bc4986f2c4c49866e037a51873 /tools/perf
parentbc0622302f344551050995491b7d14176f39c628 (diff)
perf probe: Show all cached probes
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 <mhiramat@kernel.org> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.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/146736020674.27797.13488316780383460180.stgit@devbox Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-probe.txt8
-rw-r--r--tools/perf/builtin-probe.c2
-rw-r--r--tools/perf/util/build-id.c108
-rw-r--r--tools/perf/util/build-id.h3
-rw-r--r--tools/perf/util/probe-event.c3
-rw-r--r--tools/perf/util/probe-file.c66
-rw-r--r--tools/perf/util/probe-file.h1
7 files changed, 184 insertions, 7 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 947db6fe512c..5a70d45015ea 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -67,7 +67,10 @@ OPTIONS
67 67
68-l:: 68-l::
69--list[=[GROUP:]EVENT]:: 69--list[=[GROUP:]EVENT]::
70 List up current probe events. This can also accept filtering patterns of event names. 70 List up current probe events. This can also accept filtering patterns of
71 event names.
72 When this is used with --cache, perf shows all cached probes instead of
73 the live probes.
71 74
72-L:: 75-L::
73--line=:: 76--line=::
@@ -110,8 +113,9 @@ OPTIONS
110 adding and removal operations. 113 adding and removal operations.
111 114
112--cache:: 115--cache::
113 Cache the probes (with --add option). Any events which successfully added 116 (With --add) Cache the probes. Any events which successfully added
114 are also stored in the cache file. 117 are also stored in the cache file.
118 (With --list) Show cached probes.
115 119
116--max-probes=NUM:: 120--max-probes=NUM::
117 Set the maximum number of probe points for an event. Default is 128. 121 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 34262329f405..0bb9084bf6cf 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -44,7 +44,7 @@
44 44
45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" 45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
46#define DEFAULT_FUNC_FILTER "!_*" 46#define DEFAULT_FUNC_FILTER "!_*"
47#define DEFAULT_LIST_FILTER "*:*" 47#define DEFAULT_LIST_FILTER "*"
48 48
49/* Session management structure */ 49/* Session management structure */
50static struct { 50static struct {
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 62b147366d01..1c49620e98b2 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -165,8 +165,7 @@ retry:
165 return NULL; 165 return NULL;
166} 166}
167 167
168static char *build_id_cache__linkname(const char *sbuild_id, char *bf, 168char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size)
169 size_t size)
170{ 169{
171 char *tmp = bf; 170 char *tmp = bf;
172 int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir, 171 int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
@@ -176,6 +175,36 @@ static char *build_id_cache__linkname(const char *sbuild_id, char *bf,
176 return bf; 175 return bf;
177} 176}
178 177
178char *build_id_cache__origname(const char *sbuild_id)
179{
180 char *linkname;
181 char buf[PATH_MAX];
182 char *ret = NULL, *p;
183 size_t offs = 5; /* == strlen("../..") */
184
185 linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
186 if (!linkname)
187 return NULL;
188
189 if (readlink(linkname, buf, PATH_MAX) < 0)
190 goto out;
191 /* The link should be "../..<origpath>/<sbuild_id>" */
192 p = strrchr(buf, '/'); /* Cut off the "/<sbuild_id>" */
193 if (p && (p > buf + offs)) {
194 *p = '\0';
195 if (buf[offs + 1] == '[')
196 offs++; /*
197 * This is a DSO name, like [kernel.kallsyms].
198 * Skip the first '/', since this is not the
199 * cache of a regular file.
200 */
201 ret = strdup(buf + offs); /* Skip "../..[/]" */
202 }
203out:
204 free(linkname);
205 return ret;
206}
207
179static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso) 208static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
180{ 209{
181 return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf"); 210 return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
@@ -387,6 +416,81 @@ void disable_buildid_cache(void)
387 no_buildid_cache = true; 416 no_buildid_cache = true;
388} 417}
389 418
419static bool lsdir_bid_head_filter(const char *name __maybe_unused,
420 struct dirent *d __maybe_unused)
421{
422 return (strlen(d->d_name) == 2) &&
423 isxdigit(d->d_name[0]) && isxdigit(d->d_name[1]);
424}
425
426static bool lsdir_bid_tail_filter(const char *name __maybe_unused,
427 struct dirent *d __maybe_unused)
428{
429 int i = 0;
430 while (isxdigit(d->d_name[i]) && i < SBUILD_ID_SIZE - 3)
431 i++;
432 return (i == SBUILD_ID_SIZE - 3) && (d->d_name[i] == '\0');
433}
434
435struct strlist *build_id_cache__list_all(void)
436{
437 struct strlist *toplist, *linklist = NULL, *bidlist;
438 struct str_node *nd, *nd2;
439 char *topdir, *linkdir = NULL;
440 char sbuild_id[SBUILD_ID_SIZE];
441
442 /* Open the top-level directory */
443 if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
444 return NULL;
445
446 bidlist = strlist__new(NULL, NULL);
447 if (!bidlist)
448 goto out;
449
450 toplist = lsdir(topdir, lsdir_bid_head_filter);
451 if (!toplist) {
452 pr_debug("Error in lsdir(%s): %d\n", topdir, errno);
453 /* If there is no buildid cache, return an empty list */
454 if (errno == ENOENT)
455 goto out;
456 goto err_out;
457 }
458
459 strlist__for_each_entry(nd, toplist) {
460 if (asprintf(&linkdir, "%s/%s", topdir, nd->s) < 0)
461 goto err_out;
462 /* Open the lower-level directory */
463 linklist = lsdir(linkdir, lsdir_bid_tail_filter);
464 if (!linklist) {
465 pr_debug("Error in lsdir(%s): %d\n", linkdir, errno);
466 goto err_out;
467 }
468 strlist__for_each_entry(nd2, linklist) {
469 if (snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s",
470 nd->s, nd2->s) != SBUILD_ID_SIZE - 1)
471 goto err_out;
472 if (strlist__add(bidlist, sbuild_id) < 0)
473 goto err_out;
474 }
475 strlist__delete(linklist);
476 zfree(&linkdir);
477 }
478
479out_free:
480 strlist__delete(toplist);
481out:
482 free(topdir);
483
484 return bidlist;
485
486err_out:
487 strlist__delete(linklist);
488 zfree(&linkdir);
489 strlist__delete(bidlist);
490 bidlist = NULL;
491 goto out_free;
492}
493
390char *build_id_cache__cachedir(const char *sbuild_id, const char *name, 494char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
391 bool is_kallsyms, bool is_vdso) 495 bool is_kallsyms, bool is_vdso)
392{ 496{
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index d8c7f2fc6a87..b742e271ea2c 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);
30int perf_session__write_buildid_table(struct perf_session *session, int fd); 30int perf_session__write_buildid_table(struct perf_session *session, int fd);
31int perf_session__cache_build_ids(struct perf_session *session); 31int perf_session__cache_build_ids(struct perf_session *session);
32 32
33char *build_id_cache__origname(const char *sbuild_id);
34char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
33char *build_id_cache__cachedir(const char *sbuild_id, const char *name, 35char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
34 bool is_kallsyms, bool is_vdso); 36 bool is_kallsyms, bool is_vdso);
37struct strlist *build_id_cache__list_all(void);
35int build_id_cache__list_build_ids(const char *pathname, 38int build_id_cache__list_build_ids(const char *pathname,
36 struct strlist **result); 39 struct strlist **result);
37bool build_id_cache__cached(const char *sbuild_id); 40bool 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 47b6b8b7206e..f81b5dd7f1b1 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2366,6 +2366,9 @@ int show_perf_probe_events(struct strfilter *filter)
2366 2366
2367 setup_pager(); 2367 setup_pager();
2368 2368
2369 if (probe_conf.cache)
2370 return probe_cache__show_all_caches(filter);
2371
2369 ret = init_probe_symbol_maps(false); 2372 ret = init_probe_symbol_maps(false);
2370 if (ret < 0) 2373 if (ret < 0)
2371 return ret; 2374 return ret;
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index a94ee478178d..156e3d883965 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -367,10 +367,17 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
367{ 367{
368 char cpath[PATH_MAX]; 368 char cpath[PATH_MAX];
369 char sbuildid[SBUILD_ID_SIZE]; 369 char sbuildid[SBUILD_ID_SIZE];
370 char *dir_name; 370 char *dir_name = NULL;
371 bool is_kallsyms = !target; 371 bool is_kallsyms = !target;
372 int ret, fd; 372 int ret, fd;
373 373
374 if (target && build_id_cache__cached(target)) {
375 /* This is a cached buildid */
376 strncpy(sbuildid, target, SBUILD_ID_SIZE);
377 dir_name = build_id_cache__linkname(sbuildid, NULL, 0);
378 goto found;
379 }
380
374 if (target) 381 if (target)
375 ret = filename__sprintf_build_id(target, sbuildid); 382 ret = filename__sprintf_build_id(target, sbuildid);
376 else { 383 else {
@@ -394,8 +401,11 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
394 401
395 dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms, 402 dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms,
396 false); 403 false);
397 if (!dir_name) 404found:
405 if (!dir_name) {
406 pr_debug("Failed to get cache from %s\n", target);
398 return -ENOMEM; 407 return -ENOMEM;
408 }
399 409
400 snprintf(cpath, PATH_MAX, "%s/probes", dir_name); 410 snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
401 fd = open(cpath, O_CREAT | O_RDWR, 0644); 411 fd = open(cpath, O_CREAT | O_RDWR, 0644);
@@ -673,3 +683,55 @@ int probe_cache__commit(struct probe_cache *pcache)
673out: 683out:
674 return ret; 684 return ret;
675} 685}
686
687static int probe_cache__show_entries(struct probe_cache *pcache,
688 struct strfilter *filter)
689{
690 struct probe_cache_entry *entry;
691 char buf[128], *ptr;
692
693 list_for_each_entry(entry, &pcache->entries, node) {
694 if (entry->pev.event) {
695 ptr = buf;
696 snprintf(buf, 128, "%s:%s",
697 entry->pev.group, entry->pev.event);
698 } else
699 ptr = entry->spev;
700 if (strfilter__compare(filter, ptr))
701 printf("%s\n", entry->spev);
702 }
703 return 0;
704}
705
706/* Show all cached probes */
707int probe_cache__show_all_caches(struct strfilter *filter)
708{
709 struct probe_cache *pcache;
710 struct strlist *bidlist;
711 struct str_node *nd;
712 char *buf = strfilter__string(filter);
713
714 pr_debug("list cache with filter: %s\n", buf);
715 free(buf);
716
717 bidlist = build_id_cache__list_all();
718 if (!bidlist) {
719 pr_debug("Failed to get buildids: %d\n", errno);
720 return -EINVAL;
721 }
722 strlist__for_each_entry(nd, bidlist) {
723 pcache = probe_cache__new(nd->s);
724 if (!pcache)
725 continue;
726 if (!list_empty(&pcache->entries)) {
727 buf = build_id_cache__origname(nd->s);
728 printf("%s (%s):\n", buf, nd->s);
729 free(buf);
730 probe_cache__show_entries(pcache, filter);
731 }
732 probe_cache__delete(pcache);
733 }
734 strlist__delete(bidlist);
735
736 return 0;
737}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 910aa74953e9..0009b8a65a5c 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -42,4 +42,5 @@ struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
42 struct perf_probe_event *pev); 42 struct perf_probe_event *pev);
43struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache, 43struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
44 const char *group, const char *event); 44 const char *group, const char *event);
45int probe_cache__show_all_caches(struct strfilter *filter);
45#endif 46#endif