mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									bc0622302f
								
							
						
					
					
						commit
						1f3736c9c8
					
				
					 7 changed files with 184 additions and 7 deletions
				
			
		| 
						 | 
					@ -67,7 +67,10 @@ OPTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-l::
 | 
					-l::
 | 
				
			||||||
--list[=[GROUP:]EVENT]::
 | 
					--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::
 | 
					-L::
 | 
				
			||||||
--line=::
 | 
					--line=::
 | 
				
			||||||
| 
						 | 
					@ -110,8 +113,9 @@ OPTIONS
 | 
				
			||||||
	adding and removal operations.
 | 
						adding and removal operations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--cache::
 | 
					--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.
 | 
						are also stored in the cache file.
 | 
				
			||||||
 | 
						(With --list) Show cached probes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--max-probes=NUM::
 | 
					--max-probes=NUM::
 | 
				
			||||||
	Set the maximum number of probe points for an event. Default is 128.
 | 
						Set the maximum number of probe points for an event. Default is 128.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
 | 
					#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
 | 
				
			||||||
#define DEFAULT_FUNC_FILTER "!_*"
 | 
					#define DEFAULT_FUNC_FILTER "!_*"
 | 
				
			||||||
#define DEFAULT_LIST_FILTER "*:*"
 | 
					#define DEFAULT_LIST_FILTER "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Session management structure */
 | 
					/* Session management structure */
 | 
				
			||||||
static struct {
 | 
					static struct {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -165,8 +165,7 @@ char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *build_id_cache__linkname(const char *sbuild_id, char *bf,
 | 
					char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size)
 | 
				
			||||||
				      size_t size)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *tmp = bf;
 | 
						char *tmp = bf;
 | 
				
			||||||
	int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
 | 
						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,
 | 
				
			||||||
	return 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)
 | 
					static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
 | 
						return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
 | 
				
			||||||
| 
						 | 
					@ -387,6 +416,81 @@ void disable_buildid_cache(void)
 | 
				
			||||||
	no_buildid_cache = true;
 | 
						no_buildid_cache = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool lsdir_bid_head_filter(const char *name __maybe_unused,
 | 
				
			||||||
 | 
									  struct dirent *d __maybe_unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (strlen(d->d_name) == 2) &&
 | 
				
			||||||
 | 
							isxdigit(d->d_name[0]) && isxdigit(d->d_name[1]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool lsdir_bid_tail_filter(const char *name __maybe_unused,
 | 
				
			||||||
 | 
									  struct dirent *d __maybe_unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i = 0;
 | 
				
			||||||
 | 
						while (isxdigit(d->d_name[i]) && i < SBUILD_ID_SIZE - 3)
 | 
				
			||||||
 | 
							i++;
 | 
				
			||||||
 | 
						return (i == SBUILD_ID_SIZE - 3) && (d->d_name[i] == '\0');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct strlist *build_id_cache__list_all(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct strlist *toplist, *linklist = NULL, *bidlist;
 | 
				
			||||||
 | 
						struct str_node *nd, *nd2;
 | 
				
			||||||
 | 
						char *topdir, *linkdir = NULL;
 | 
				
			||||||
 | 
						char sbuild_id[SBUILD_ID_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Open the top-level directory */
 | 
				
			||||||
 | 
						if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bidlist = strlist__new(NULL, NULL);
 | 
				
			||||||
 | 
						if (!bidlist)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						toplist = lsdir(topdir, lsdir_bid_head_filter);
 | 
				
			||||||
 | 
						if (!toplist) {
 | 
				
			||||||
 | 
							pr_debug("Error in lsdir(%s): %d\n", topdir, errno);
 | 
				
			||||||
 | 
							/* If there is no buildid cache, return an empty list */
 | 
				
			||||||
 | 
							if (errno == ENOENT)
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							goto err_out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strlist__for_each_entry(nd, toplist) {
 | 
				
			||||||
 | 
							if (asprintf(&linkdir, "%s/%s", topdir, nd->s) < 0)
 | 
				
			||||||
 | 
								goto err_out;
 | 
				
			||||||
 | 
							/* Open the lower-level directory */
 | 
				
			||||||
 | 
							linklist = lsdir(linkdir, lsdir_bid_tail_filter);
 | 
				
			||||||
 | 
							if (!linklist) {
 | 
				
			||||||
 | 
								pr_debug("Error in lsdir(%s): %d\n", linkdir, errno);
 | 
				
			||||||
 | 
								goto err_out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							strlist__for_each_entry(nd2, linklist) {
 | 
				
			||||||
 | 
								if (snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s",
 | 
				
			||||||
 | 
									     nd->s, nd2->s) != SBUILD_ID_SIZE - 1)
 | 
				
			||||||
 | 
									goto err_out;
 | 
				
			||||||
 | 
								if (strlist__add(bidlist, sbuild_id) < 0)
 | 
				
			||||||
 | 
									goto err_out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							strlist__delete(linklist);
 | 
				
			||||||
 | 
							zfree(&linkdir);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out_free:
 | 
				
			||||||
 | 
						strlist__delete(toplist);
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						free(topdir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return bidlist;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_out:
 | 
				
			||||||
 | 
						strlist__delete(linklist);
 | 
				
			||||||
 | 
						zfree(&linkdir);
 | 
				
			||||||
 | 
						strlist__delete(bidlist);
 | 
				
			||||||
 | 
						bidlist = NULL;
 | 
				
			||||||
 | 
						goto out_free;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
 | 
					char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
 | 
				
			||||||
			       bool is_kallsyms, bool is_vdso)
 | 
								       bool is_kallsyms, bool is_vdso)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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__write_buildid_table(struct perf_session *session, int fd);
 | 
				
			||||||
int perf_session__cache_build_ids(struct perf_session *session);
 | 
					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,
 | 
					char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
 | 
				
			||||||
			       bool is_kallsyms, bool is_vdso);
 | 
								       bool is_kallsyms, bool is_vdso);
 | 
				
			||||||
 | 
					struct strlist *build_id_cache__list_all(void);
 | 
				
			||||||
int build_id_cache__list_build_ids(const char *pathname,
 | 
					int build_id_cache__list_build_ids(const char *pathname,
 | 
				
			||||||
				   struct strlist **result);
 | 
									   struct strlist **result);
 | 
				
			||||||
bool build_id_cache__cached(const char *sbuild_id);
 | 
					bool build_id_cache__cached(const char *sbuild_id);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2366,6 +2366,9 @@ int show_perf_probe_events(struct strfilter *filter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setup_pager();
 | 
						setup_pager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (probe_conf.cache)
 | 
				
			||||||
 | 
							return probe_cache__show_all_caches(filter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = init_probe_symbol_maps(false);
 | 
						ret = init_probe_symbol_maps(false);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -367,10 +367,17 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char cpath[PATH_MAX];
 | 
						char cpath[PATH_MAX];
 | 
				
			||||||
	char sbuildid[SBUILD_ID_SIZE];
 | 
						char sbuildid[SBUILD_ID_SIZE];
 | 
				
			||||||
	char *dir_name;
 | 
						char *dir_name = NULL;
 | 
				
			||||||
	bool is_kallsyms = !target;
 | 
						bool is_kallsyms = !target;
 | 
				
			||||||
	int ret, fd;
 | 
						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)
 | 
						if (target)
 | 
				
			||||||
		ret = filename__sprintf_build_id(target, sbuildid);
 | 
							ret = filename__sprintf_build_id(target, sbuildid);
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
| 
						 | 
					@ -394,8 +401,11 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms,
 | 
						dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms,
 | 
				
			||||||
					    false);
 | 
										    false);
 | 
				
			||||||
	if (!dir_name)
 | 
					found:
 | 
				
			||||||
 | 
						if (!dir_name) {
 | 
				
			||||||
 | 
							pr_debug("Failed to get cache from %s\n", target);
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
 | 
						snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
 | 
				
			||||||
	fd = open(cpath, O_CREAT | O_RDWR, 0644);
 | 
						fd = open(cpath, O_CREAT | O_RDWR, 0644);
 | 
				
			||||||
| 
						 | 
					@ -673,3 +683,55 @@ int probe_cache__commit(struct probe_cache *pcache)
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return ret;
 | 
						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->entries, node) {
 | 
				
			||||||
 | 
							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 = strfilter__string(filter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pr_debug("list cache with filter: %s\n", buf);
 | 
				
			||||||
 | 
						free(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bidlist = build_id_cache__list_all();
 | 
				
			||||||
 | 
						if (!bidlist) {
 | 
				
			||||||
 | 
							pr_debug("Failed to get buildids: %d\n", errno);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						strlist__for_each_entry(nd, bidlist) {
 | 
				
			||||||
 | 
							pcache = probe_cache__new(nd->s);
 | 
				
			||||||
 | 
							if (!pcache)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							if (!list_empty(&pcache->entries)) {
 | 
				
			||||||
 | 
								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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,4 +42,5 @@ struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
 | 
				
			||||||
					    struct perf_probe_event *pev);
 | 
										    struct perf_probe_event *pev);
 | 
				
			||||||
struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
 | 
					struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
 | 
				
			||||||
					const char *group, const char *event);
 | 
										const char *group, const char *event);
 | 
				
			||||||
 | 
					int probe_cache__show_all_caches(struct strfilter *filter);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue