Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1399123 > unrolled thread
| Started by | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| First post | 2016-05-11 16:00 +0200 |
| Last post | 2016-05-11 17:50 +0200 |
| Articles | 20 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH perf/core v7 00/21] perf-probe --cache and SDT support Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
[PATCH perf/core v7 18/21] perf-list: Skip SDTs placed in invalid binaries Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
[PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
Re: [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-05-11 18:00 +0200
Re: [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-12 03:50 +0200
[PATCH perf/core v7 17/21] perf-list: Show SDT and pre-cached events Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
[PATCH perf/core v7 16/21] perf probe: Accept %sdt and %cached event name Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
[PATCH perf/core v7 10/21] perf probe: Use cache entry if possible Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
[PATCH perf/core v7 15/21] perf buildid-cache: Scan and import user SDT events to probe cache Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
[PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
[tip:perf/core] perf tools: Fix lsdir to set errno correctly tip-bot for Masami Hiramatsu <tipbot@zytor.com> - 2016-05-12 12:30 +0200
[PATCH perf/core v7 20/21] perf probe: Support @BUILDID or @FILE suffix for SDT events Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
[PATCH perf/core v7 19/21] perf probe: Allow wildcard for cached events Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
[PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
Re: [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-05-11 17:50 +0200
Re: [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-12 04:10 +0200
Re: [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-12 11:00 +0200
[PATCH perf/core v7 09/21] perf probe: Add --cache option to cache the probe definitions Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:00 +0200
[PATCH perf/core v7 03/21] perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE Masami Hiramatsu <mhiramat@kernel.org> - 2016-05-11 16:10 +0200
Re: [PATCH perf/core v7 03/21] perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-05-11 17:50 +0200
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 00/21] perf-probe --cache and SDT support |
| Message-ID | <rxCQa-UH-17@gated-at.bofh.it> |
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
[toc] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 18/21] perf-list: Skip SDTs placed in invalid binaries |
| Message-ID | <rxCQc-UH-63@gated-at.bofh.it> |
| In reply to | #1399123 |
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;
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms |
| Message-ID | <rxCQc-UH-67@gated-at.bofh.it> |
| In reply to | #1399123 |
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,
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-05-11 18:00 +0200 |
| Subject | Re: [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms |
| Message-ID | <rxEIh-2LV-1@gated-at.bofh.it> |
| In reply to | #1399126 |
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,
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-12 03:50 +0200 |
| Subject | Re: [PATCH perf/core v7 07/21] perf symbol: Cleanup the code flow of dso__find_kallsyms |
| Message-ID | <rxNVg-3vp-11@gated-at.bofh.it> |
| In reply to | #1399288 |
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>
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 17/21] perf-list: Show SDT and pre-cached events |
| Message-ID | <rxCQc-UH-71@gated-at.bofh.it> |
| In reply to | #1399123 |
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
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 16/21] perf probe: Accept %sdt and %cached event name |
| Message-ID | <rxCQe-UH-77@gated-at.bofh.it> |
| In reply to | #1399123 |
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) &&
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 10/21] perf probe: Use cache entry if possible |
| Message-ID | <rxCQd-UH-73@gated-at.bofh.it> |
| In reply to | #1399123 |
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
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 15/21] perf buildid-cache: Scan and import user SDT events to probe cache |
| Message-ID | <rxCQe-UH-75@gated-at.bofh.it> |
| In reply to | #1399123 |
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,
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 01/21] tools/perf: Fix lsdir to set errno correctly |
| Message-ID | <rxCQa-UH-27@gated-at.bofh.it> |
| In reply to | #1399123 |
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;
}
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Masami Hiramatsu <tipbot@zytor.com> |
|---|---|
| Date | 2016-05-12 12:30 +0200 |
| Subject | [tip:perf/core] perf tools: Fix lsdir to set errno correctly |
| Message-ID | <rxW2w-3Gh-43@gated-at.bofh.it> |
| In reply to | #1399132 |
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;
}
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 20/21] perf probe: Support @BUILDID or @FILE suffix for SDT events |
| Message-ID | <rxCQe-UH-81@gated-at.bofh.it> |
| In reply to | #1399123 |
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) {
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 19/21] perf probe: Allow wildcard for cached events |
| Message-ID | <rxCQf-UH-93@gated-at.bofh.it> |
| In reply to | #1399123 |
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,
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms |
| Message-ID | <rxCQf-UH-95@gated-at.bofh.it> |
| In reply to | #1399123 |
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;
}
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-05-11 17:50 +0200 |
| Subject | Re: [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms |
| Message-ID | <rxEyC-2Hv-29@gated-at.bofh.it> |
| In reply to | #1399138 |
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;
> }
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-12 04:10 +0200 |
| Subject | Re: [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms |
| Message-ID | <rxOeC-3YK-3@gated-at.bofh.it> |
| In reply to | #1399287 |
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>
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-12 11:00 +0200 |
| Subject | Re: [PATCH perf/core v7 02/21] perf buildid: Fix to set correct dso name for kallsyms |
| Message-ID | <rxUDq-21y-47@gated-at.bofh.it> |
| In reply to | #1399639 |
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>
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:00 +0200 |
| Subject | [PATCH perf/core v7 09/21] perf probe: Add --cache option to cache the probe definitions |
| Message-ID | <rxCQf-UH-89@gated-at.bofh.it> |
| In reply to | #1399123 |
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
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-05-11 16:10 +0200 |
| Subject | [PATCH perf/core v7 03/21] perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE |
| Message-ID | <rxCZP-1jh-3@gated-at.bofh.it> |
| In reply to | #1399123 |
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)
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-05-11 17:50 +0200 |
| Subject | Re: [PATCH perf/core v7 03/21] perf buildid: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE |
| Message-ID | <rxEyB-2Hv-9@gated-at.bofh.it> |
| In reply to | #1399142 |
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)
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web