Skip to contentSkip to conversation

perf-probe --cache and SDT support

PATCH In review Masami Hiramatsu 3 participants 30 messages Jul 12, 2016 – Jul 14, 2016 perf events

lore
Share & tools
lore
#0 lore raw

cover perf-probe --cache and SDT support

Hi,

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

Here is the previous v13: https://lkml.org/lkml/2016/7/1/133

This version includes patches which not merged yet. This also adds a bugfix;
- [1/10] Resend the bugfix patch which was sent 4th July.

          (https://lkml.org/lkml/2016/7/3/217)

Thank you,

---

Masami Hiramatsu (10):
[BUGFIX] perf-probe: Fix to show correct error message for $vars and $params perf probe: Accept %sdt and %cached event name
perf-probe: Make --list shows only available cached events
perf: probe-cache: Add for_each_probe_cache_entry() wrapper perf probe: Allow wildcard for cached events
perf probe: Search SDT/cached event from all probe caches
perf probe: Support @BUILDID or @FILE suffix for SDT events perf probe: Support a special SDT probe format
perf build: Add sdt feature detection
perf-test: Add a test case for SDT event

 tools/perf/Documentation/perf-probe.txt |   11 +
 tools/perf/Makefile.perf                |    3 
 tools/perf/builtin-probe.c              |    2 
 tools/perf/config/Makefile              |   10 +
 tools/perf/tests/Build                  |    1 
 tools/perf/tests/builtin-test.c         |    4 
 tools/perf/tests/make                   |    3 
 tools/perf/tests/sdt.c                  |  115 ++++++++++++
 tools/perf/tests/tests.h                |    1 
 tools/perf/util/build-id.c              |   76 ++++++++
 tools/perf/util/build-id.h              |    3 
 tools/perf/util/probe-event.c           |  309 +++++++++++++++++++++++++++----
 tools/perf/util/probe-event.h           |    1 
 tools/perf/util/probe-file.c            |   57 +++++-
 tools/perf/util/probe-file.h            |    5 +
 15 files changed, 542 insertions(+), 59 deletions(-)
 create mode 100644 tools/perf/tests/sdt.c

--
Masami Hiramatsu

#1 lore raw

PATCH 1/10 perf-probe: Fix to show correct error message for $vars and $params

Fix to show correct error messages for $vars and $params because those special variables requires debug information to find the real variables or function parameters.

E.g. without this fix;
----

  # perf probe -x /lib64/libc-2.23.so getaddrinfo \$params
  Failed to write event: Invalid argument
  Please upgrade your kernel to at least 3.14 to have access to feature $params
    Error: Failed to add events.
  ----
Perf ends up with an error, but the message is not correct.
With this fix, perf shows correct error message as below.
  ----
  # perf probe -x /lib64/libc-2.23.so getaddrinfo \$params
  The /usr/lib64/libc-2.23.so file has no debug information.
  Rebuild with -g, or install an appropriate debuginfo package.
    Error: Failed to add events.
  ----
---
 tools/perf/util/probe-event.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/probe-event.c +3 -1
index 0201f66..dff9a54 100644
@@ -1547,7 +1547,9 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
 		return true;
 
 	for (i = 0; i < pev->nargs; i++)
-		if (is_c_varname(pev->args[i].var))
+		if (is_c_varname(pev->args[i].var) ||
+		    !strcmp(pev->args[i].var, "$params") ||
+		    !strcmp(pev->args[i].var, "$vars"))
 			return true;
 
 	return false;
#2 lore raw

[tip:perf/core] perf probe: Fix to show correct error message for $vars and $params

perf probe: Fix to show correct error message for $vars and $params
Commit-ID:  f6eb0518f325ef0d6557fbef5c7ebe48a81e74db
Gitweb:     http://git.kernel.org/tip/f6eb0518f325ef0d6557fbef5c7ebe48a81e74db
Author:     Masami Hiramatsu <[email protected]>
AuthorDate: Tue, 12 Jul 2016 19:04:34 +0900
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 13 Jul 2016 23:09:04 -0300

perf probe: Fix to show correct error message for $vars and $params

Fix to show correct error messages for $vars and $params because those special variables requires debug information to find the real variables or function parameters.

E.g. without this fix;
----

  # perf probe -x /lib64/libc-2.23.so getaddrinfo \$params
  Failed to write event: Invalid argument
  Please upgrade your kernel to at least 3.14 to have access to feature $params
    Error: Failed to add events.
  ----

Perf ends up with an error, but the message is not correct. With this fix, perf shows correct error message as below.

----

  # perf probe -x /lib64/libc-2.23.so getaddrinfo \$params
  The /usr/lib64/libc-2.23.so file has no debug information.
  Rebuild with -g, or install an appropriate debuginfo package.
    Error: Failed to add events.
  ----
---
 tools/perf/util/probe-event.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/probe-event.c +3 -1
index 2b222a7..fef9768 100644
@@ -1547,7 +1547,9 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
 		return true;
 
 	for (i = 0; i < pev->nargs; i++)
-		if (is_c_varname(pev->args[i].var))
+		if (is_c_varname(pev->args[i].var) ||
+		    !strcmp(pev->args[i].var, "$params") ||
+		    !strcmp(pev->args[i].var, "$vars"))
 			return true;
 
 	return false;
#3 lore raw

PATCH 2/10 perf probe: Accept %sdt and %cached event name

In reply to Masami Hiramatsu

From: Masami Hiramatsu <[email protected]>

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
  ----

---
Changes in v10:
- Update Documentation/perf-probe.txt to add a link about SDT.
Changes in v7:
- Fix a bug to return an error if no SDT/cached events found in cache.

---
 tools/perf/Documentation/perf-probe.txt |    9 +++
 tools/perf/util/probe-event.c           |   82 ++++++++++++++++++++++---------
 tools/perf/util/probe-event.h           |    1 
 tools/perf/util/probe-file.c            |    9 +++
 4 files changed, 76 insertions(+), 25 deletions(-)
tools/perf/Documentation/perf-probe.txt +8 -1
index 7a258e9..39e3870 100644
@@ -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 or cached event with name
+     %[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,11 @@ 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.
+Note that before using the SDT event, the target binary (on which SDT events are defined) must be scanned by linkperf:perf-buildid-cache[1] to make SDT events as cached events.
+
+For details of the SDT, see below.
+https://sourceware.org/gdb/onlinedocs/gdb/Static-Probe-Points.html
 
 PROBE ARGUMENT
 --------------
@@ -237,4 +244,4 @@ Add probes at malloc() function on libc
 
 SEE ALSO
 --------
-linkperf:perf-trace[1], linkperf:perf-record[1]
+linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
tools/perf/util/probe-event.c +58 -24

124 lines not on this page · raw message

tools/perf/util/probe-event.h +1 -0
index 432b690..e18ea9f 100644
@@ -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 */
tools/perf/util/probe-file.c +9 -0
index 5b563b2..b642d06 100644
@@ -547,6 +547,15 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
 		return NULL;
 
 	list_for_each_entry(entry, &pcache->entries, node) {
+		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) &&
#4 lore raw

[tip:perf/core] perf probe: Accept %sdt and %cached event name

perf probe: Accept %sdt and %cached event name
Commit-ID:  36a009fe07bdecd201335f982babb8af34b603e2
Gitweb:     http://git.kernel.org/tip/36a009fe07bdecd201335f982babb8af34b603e2
Author:     Masami Hiramatsu <[email protected]>
AuthorDate: Tue, 12 Jul 2016 19:04:43 +0900
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 13 Jul 2016 23:09:05 -0300

perf probe: Accept %sdt and %cached event name

To improve 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
  ----
---
 tools/perf/Documentation/perf-probe.txt |  9 +++-
 tools/perf/util/probe-event.c           | 82 +++++++++++++++++++++++----------
 tools/perf/util/probe-event.h           |  1 +
 tools/perf/util/probe-file.c            |  9 ++++
 4 files changed, 76 insertions(+), 25 deletions(-)
tools/perf/Documentation/perf-probe.txt +8 -1
index 7a258e9..39e3870 100644
@@ -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 or cached event with name
+     %[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,11 @@ 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.
+Note that before using the SDT event, the target binary (on which SDT events are defined) must be scanned by linkperf:perf-buildid-cache[1] to make SDT events as cached events.
+
+For details of the SDT, see below.
+https://sourceware.org/gdb/onlinedocs/gdb/Static-Probe-Points.html
 
 PROBE ARGUMENT
 --------------
@@ -237,4 +244,4 @@ Add probes at malloc() function on libc
 
 SEE ALSO
 --------
-linkperf:perf-trace[1], linkperf:perf-record[1]
+linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
tools/perf/util/probe-event.c +58 -24

124 lines not on this page · raw message

tools/perf/util/probe-event.h +1 -0
index 432b690..e18ea9f 100644
@@ -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 */
tools/perf/util/probe-file.c +9 -0
index e705a74..fc16b17 100644
@@ -547,6 +547,15 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
 		return NULL;
 
 	list_for_each_entry(entry, &pcache->entries, node) {
+		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) &&
#5 lore raw

PATCH 3/10 perf-probe: Make --list shows only available cached events

In reply to Masami Hiramatsu

From: Masami Hiramatsu <[email protected]>

Make "perf probe --cache --list" shows only available cached events by checking build-id validity.

E.g. without this patch:
----

  $ ./perf probe --cache --add oldevent=cmd_probe
  $ make #(to update ./perf)
  $ ./perf probe --cache --add newevent=cmd_probe
  $ ./perf probe --cache --list
  /home/mhiramat/ksrc/linux/tools/perf/perf (061e90539bac69
  probe_perf:newevent=cmd_probe
  /home/mhiramat/ksrc/linux/tools/perf/perf (c2e44d614e33e1
  probe_perf:oldevent=cmd_probe
  ----
It shows both of old and new events but user can not use old one.
With this;
  ----
  $ ./perf probe --cache -l
  /home/mhiramat/ksrc/linux/tools/perf/perf (061e90539bac69
  probe_perf:newevent=cmd_probe
  ----
This show only new event which is on the existing binary.

---
Changes in v13:
- Instead of the perf-list, apply this change for perf-probe --list because of avoiding to confuse user.
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/probe-file.c |    2 +-
 4 files changed, 35 insertions(+), 4 deletions(-)
tools/perf/builtin-probe.c +1 -1
index a1a5cd1..de75af5 100644
@@ -370,7 +370,7 @@ static int del_perf_probe_caches(struct strfilter *filter)
 	struct str_node *nd;
 	int ret;
 
-	bidlist = build_id_cache__list_all();
+	bidlist = build_id_cache__list_all(false);
 	if (!bidlist) {
 		ret = -errno;
 		pr_debug("Failed to get buildids: %d\n", ret);
tools/perf/util/build-id.c +32 -1
index e1a1640..8e86a83 100644
@@ -206,6 +206,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");
@@ -433,13 +458,17 @@ static bool lsdir_bid_tail_filter(const char *name __maybe_unused,
 	return (i == SBUILD_ID_SIZE - 3) && (d->d_name[i] == '\0');
 }
 
-struct strlist *build_id_cache__list_all(void)
+struct strlist *build_id_cache__list_all(bool validonly)
 {
 	struct strlist *toplist, *linklist = NULL, *bidlist;
 	struct str_node *nd, *nd2;
 	char *topdir, *linkdir = NULL;
 	char sbuild_id[SBUILD_ID_SIZE];
 
+	/* for filename__ functions */
+	if (validonly)
+		symbol__init(NULL);
+
 	/* Open the top-level directory */
 	if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
 		return NULL;
@@ -470,6 +499,8 @@ struct strlist *build_id_cache__list_all(void)
 			if (snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s",
 				     nd->s, nd2->s) != SBUILD_ID_SIZE - 1)
 				goto err_out;
+			if (validonly && !build_id_cache__valid_id(sbuild_id))
+				continue;
 			if (strlist__add(bidlist, sbuild_id) < 0)
 				goto err_out;
 		}
tools/perf/util/build-id.h +1 -1
index b742e27..64e740f 100644
@@ -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);
-struct strlist *build_id_cache__list_all(void);
+struct strlist *build_id_cache__list_all(bool validonly);
 int build_id_cache__list_build_ids(const char *pathname,
 				   struct strlist **result);
 bool build_id_cache__cached(const char *sbuild_id);
tools/perf/util/probe-file.c +1 -1
index b642d06..b062545 100644
@@ -806,7 +806,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
 	pr_debug("list cache with filter: %s\n", buf);
 	free(buf);
 
-	bidlist = build_id_cache__list_all();
+	bidlist = build_id_cache__list_all(true);
 	if (!bidlist) {
 		pr_debug("Failed to get buildids: %d\n", errno);
 		return -EINVAL;
#6 lore raw

Re: [PATCH perf/core 03/10] perf-probe: Make --list shows only available cached events

Em Tue, Jul 12, 2016 at 07:04:54PM +0900, Masami Hiramatsu escreveu:

Quoted 4 lines

From: Masami Hiramatsu <[email protected]>

Make "perf probe --cache --list" shows only available cached events by checking build-id validity.

Something is missing here, I tried following these steps and couldn't get to the same results, can you retry them at this point in time, i.e. after applying just the three first patches in this series?

I'm continuing anyway, as I want to check the rest...

- Arnaldo

Quoted 140 lines

E.g. without this patch:
----

  $ ./perf probe --cache --add oldevent=cmd_probe
  $ make #(to update ./perf)
  $ ./perf probe --cache --add newevent=cmd_probe
  $ ./perf probe --cache --list
  /home/mhiramat/ksrc/linux/tools/perf/perf (061e90539bac69
  probe_perf:newevent=cmd_probe
  /home/mhiramat/ksrc/linux/tools/perf/perf (c2e44d614e33e1
  probe_perf:oldevent=cmd_probe
  ----
It shows both of old and new events but user can not use old one.
With this;
  ----
  $ ./perf probe --cache -l
  /home/mhiramat/ksrc/linux/tools/perf/perf (061e90539bac69
  probe_perf:newevent=cmd_probe
  ----
This show only new event which is on the existing binary.

---
Changes in v13:
- Instead of the perf-list, apply this change for perf-probe --list because of avoiding to confuse user.
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/probe-file.c |    2 +-
 4 files changed, 35 insertions(+), 4 deletions(-)
tools/perf/builtin-probe.c +1 -1
index a1a5cd1..de75af5 100644
@@ -370,7 +370,7 @@ static int del_perf_probe_caches(struct strfilter *filter)
 	struct str_node *nd;
 	int ret;
 
-	bidlist = build_id_cache__list_all();
+	bidlist = build_id_cache__list_all(false);
 	if (!bidlist) {
 		ret = -errno;
 		pr_debug("Failed to get buildids: %d\n", ret);
tools/perf/util/build-id.c +32 -1
index e1a1640..8e86a83 100644
@@ -206,6 +206,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");
@@ -433,13 +458,17 @@ static bool lsdir_bid_tail_filter(const char *name __maybe_unused,
 	return (i == SBUILD_ID_SIZE - 3) && (d->d_name[i] == '\0');
 }
 
-struct strlist *build_id_cache__list_all(void)
+struct strlist *build_id_cache__list_all(bool validonly)
 {
 	struct strlist *toplist, *linklist = NULL, *bidlist;
 	struct str_node *nd, *nd2;
 	char *topdir, *linkdir = NULL;
 	char sbuild_id[SBUILD_ID_SIZE];
 
+	/* for filename__ functions */
+	if (validonly)
+		symbol__init(NULL);
+
 	/* Open the top-level directory */
 	if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
 		return NULL;
@@ -470,6 +499,8 @@ struct strlist *build_id_cache__list_all(void)
 			if (snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s",
 				     nd->s, nd2->s) != SBUILD_ID_SIZE - 1)
 				goto err_out;
+			if (validonly && !build_id_cache__valid_id(sbuild_id))
+				continue;
 			if (strlist__add(bidlist, sbuild_id) < 0)
 				goto err_out;
 		}
tools/perf/util/build-id.h +1 -1
index b742e27..64e740f 100644
@@ -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);
-struct strlist *build_id_cache__list_all(void);
+struct strlist *build_id_cache__list_all(bool validonly);
 int build_id_cache__list_build_ids(const char *pathname,
 				   struct strlist **result);
 bool build_id_cache__cached(const char *sbuild_id);
tools/perf/util/probe-file.c +1 -1
index b642d06..b062545 100644
@@ -806,7 +806,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
 	pr_debug("list cache with filter: %s\n", buf);
 	free(buf);
 
-	bidlist = build_id_cache__list_all();
+	bidlist = build_id_cache__list_all(true);
 	if (!bidlist) {
 		pr_debug("Failed to get buildids: %d\n", errno);
 		return -EINVAL;
#7 lore raw

Re: [PATCH perf/core 03/10] perf-probe: Make --list shows only available cached events

Quoted 9 lines · On Wed, 13 Jul 2016 16:28:37 -0300 Arnaldo Carvalho de Melo <[email protected]>…

Em Tue, Jul 12, 2016 at 07:04:54PM +0900, Masami Hiramatsu escreveu:

Quoted 4 lines

From: Masami Hiramatsu <[email protected]>

Make "perf probe --cache --list" shows only available cached events by checking build-id validity.

Something is missing here, I tried following these steps and couldn't get to the same results, can you retry them at this point in time, i.e. after applying just the three first patches in this series?

Sorry, I missed some steps, see below;

Quoted 8 lines

I'm continuing anyway, as I want to check the rest...

- Arnaldo

Quoted 3 lines

E.g. without this patch:
----

  $ ./perf probe --cache --add oldevent=cmd_probe

Here, you have to change perf source code so that perf binary build-id is changed.

And make a copy of perf (as perf.old) so that you can get build-id of both binary.

Quoted 1 line
Quoted 1 line
  $ make #(to update ./perf)

So, prese ensure that the new perf binary has different build-id.

If both binary has same build-id, you'll see just one cache.

Thank you,

Quoted 136 lines
Quoted 136 lines
  $ ./perf probe --cache --add newevent=cmd_probe
  $ ./perf probe --cache --list
  /home/mhiramat/ksrc/linux/tools/perf/perf (061e90539bac69
  probe_perf:newevent=cmd_probe
  /home/mhiramat/ksrc/linux/tools/perf/perf (c2e44d614e33e1
  probe_perf:oldevent=cmd_probe
  ----
It shows both of old and new events but user can not use old one.
With this;
  ----
  $ ./perf probe --cache -l
  /home/mhiramat/ksrc/linux/tools/perf/perf (061e90539bac69
  probe_perf:newevent=cmd_probe
  ----
This show only new event which is on the existing binary.

---
Changes in v13:
- Instead of the perf-list, apply this change for perf-probe --list because of avoiding to confuse user.
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/probe-file.c |    2 +-
 4 files changed, 35 insertions(+), 4 deletions(-)
tools/perf/builtin-probe.c +1 -1
index a1a5cd1..de75af5 100644
@@ -370,7 +370,7 @@ static int del_perf_probe_caches(struct strfilter *filter)
 	struct str_node *nd;
 	int ret;
 
-	bidlist = build_id_cache__list_all();
+	bidlist = build_id_cache__list_all(false);
 	if (!bidlist) {
 		ret = -errno;
 		pr_debug("Failed to get buildids: %d\n", ret);
tools/perf/util/build-id.c +32 -1
index e1a1640..8e86a83 100644
@@ -206,6 +206,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");
@@ -433,13 +458,17 @@ static bool lsdir_bid_tail_filter(const char *name __maybe_unused,
 	return (i == SBUILD_ID_SIZE - 3) && (d->d_name[i] == '\0');
 }
 
-struct strlist *build_id_cache__list_all(void)
+struct strlist *build_id_cache__list_all(bool validonly)
 {
 	struct strlist *toplist, *linklist = NULL, *bidlist;
 	struct str_node *nd, *nd2;
 	char *topdir, *linkdir = NULL;
 	char sbuild_id[SBUILD_ID_SIZE];
 
+	/* for filename__ functions */
+	if (validonly)
+		symbol__init(NULL);
+
 	/* Open the top-level directory */
 	if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
 		return NULL;
@@ -470,6 +499,8 @@ struct strlist *build_id_cache__list_all(void)
 			if (snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s",
 				     nd->s, nd2->s) != SBUILD_ID_SIZE - 1)
 				goto err_out;
+			if (validonly && !build_id_cache__valid_id(sbuild_id))
+				continue;
 			if (strlist__add(bidlist, sbuild_id) < 0)
 				goto err_out;
 		}
tools/perf/util/build-id.h +1 -1
index b742e27..64e740f 100644
@@ -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);
-struct strlist *build_id_cache__list_all(void);
+struct strlist *build_id_cache__list_all(bool validonly);
 int build_id_cache__list_build_ids(const char *pathname,
 				   struct strlist **result);
 bool build_id_cache__cached(const char *sbuild_id);
tools/perf/util/probe-file.c +1 -1
index b642d06..b062545 100644
@@ -806,7 +806,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
 	pr_debug("list cache with filter: %s\n", buf);
 	free(buf);
 
-	bidlist = build_id_cache__list_all();
+	bidlist = build_id_cache__list_all(true);
 	if (!bidlist) {
 		pr_debug("Failed to get buildids: %d\n", errno);
 		return -EINVAL;
Signature · 1 line
Masami Hiramatsu <[email protected]>
#8 lore raw

[tip:perf/core] perf probe: Make --list show only available cached events

In reply to Masami Hiramatsu
perf probe: Make --list show only available cached events
Commit-ID:  c3492a3a4e58117f18d96125e67b0bed7c4231e1
Gitweb:     http://git.kernel.org/tip/c3492a3a4e58117f18d96125e67b0bed7c4231e1
Author:     Masami Hiramatsu <[email protected]>
AuthorDate: Tue, 12 Jul 2016 19:04:54 +0900
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 13 Jul 2016 23:09:05 -0300

perf probe: Make --list show only available cached events

Make "perf probe --cache --list" show only available cached events by checking build-id validity.

E.g. without this patch:
----

  $ ./perf probe --cache --add oldevent=cmd_probe
  $ make #(to update ./perf)
  $ ./perf probe --cache --add newevent=cmd_probe
  $ ./perf probe --cache --list
  /home/mhiramat/ksrc/linux/tools/perf/perf (061e90539bac69
  probe_perf:newevent=cmd_probe
  /home/mhiramat/ksrc/linux/tools/perf/perf (c2e44d614e33e1
  probe_perf:oldevent=cmd_probe
  ----
It shows both of old and new events but user can not use old one.
With this;
  ----
  $ ./perf probe --cache -l
  /home/mhiramat/ksrc/linux/tools/perf/perf (061e90539bac69
  probe_perf:newevent=cmd_probe
  ----

This shows only new events which are on the existing binary.

---
 tools/perf/builtin-probe.c   |  2 +-
 tools/perf/util/build-id.c   | 33 ++++++++++++++++++++++++++++++++-
 tools/perf/util/build-id.h   |  2 +-
 tools/perf/util/probe-file.c |  2 +-
 4 files changed, 35 insertions(+), 4 deletions(-)
tools/perf/builtin-probe.c +1 -1
index c6d890a..ee5b421 100644
@@ -370,7 +370,7 @@ static int del_perf_probe_caches(struct strfilter *filter)
 	struct str_node *nd;
 	int ret;
 
-	bidlist = build_id_cache__list_all();
+	bidlist = build_id_cache__list_all(false);
 	if (!bidlist) {
 		ret = -errno;
 		pr_debug("Failed to get buildids: %d\n", ret);
tools/perf/util/build-id.c +32 -1
index 1e504e4..36b4279 100644
@@ -206,6 +206,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");
@@ -433,13 +458,17 @@ static bool lsdir_bid_tail_filter(const char *name __maybe_unused,
 	return (i == SBUILD_ID_SIZE - 3) && (d->d_name[i] == '\0');
 }
 
-struct strlist *build_id_cache__list_all(void)
+struct strlist *build_id_cache__list_all(bool validonly)
 {
 	struct strlist *toplist, *linklist = NULL, *bidlist;
 	struct str_node *nd, *nd2;
 	char *topdir, *linkdir = NULL;
 	char sbuild_id[SBUILD_ID_SIZE];
 
+	/* for filename__ functions */
+	if (validonly)
+		symbol__init(NULL);
+
 	/* Open the top-level directory */
 	if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
 		return NULL;
@@ -470,6 +499,8 @@ struct strlist *build_id_cache__list_all(void)
 			if (snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s",
 				     nd->s, nd2->s) != SBUILD_ID_SIZE - 1)
 				goto err_out;
+			if (validonly && !build_id_cache__valid_id(sbuild_id))
+				continue;
 			if (strlist__add(bidlist, sbuild_id) < 0)
 				goto err_out;
 		}
tools/perf/util/build-id.h +1 -1
index b742e27..64e740f 100644
@@ -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);
-struct strlist *build_id_cache__list_all(void);
+struct strlist *build_id_cache__list_all(bool validonly);
 int build_id_cache__list_build_ids(const char *pathname,
 				   struct strlist **result);
 bool build_id_cache__cached(const char *sbuild_id);
tools/perf/util/probe-file.c +1 -1
index fc16b17..a5059dc 100644
@@ -808,7 +808,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
 	pr_debug("list cache with filter: %s\n", buf);
 	free(buf);
 
-	bidlist = build_id_cache__list_all();
+	bidlist = build_id_cache__list_all(true);
 	if (!bidlist) {
 		pr_debug("Failed to get buildids: %d\n", errno);
 		return -EINVAL;
#9 lore raw

PATCH 4/10 perf: probe-cache: Add for_each_probe_cache_entry() wrapper

In reply to Masami Hiramatsu

Add for_each_probe_cache_entry() wrapper macro
for hiding list in probe_cache.

---
Changes in v10:
- Splitted from "perf probe: Allow wildcard for cached events"

---
 tools/perf/util/probe-file.c |    8 ++++----
 tools/perf/util/probe-file.h |    2 ++
 2 files changed, 6 insertions(+), 4 deletions(-)
tools/perf/util/probe-file.c +4 -4
index b062545..9152ad2 100644
@@ -546,7 +546,7 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
 	if (!cmd)
 		return NULL;
 
-	list_for_each_entry(entry, &pcache->entries, node) {
+	for_each_probe_cache_entry(entry, pcache) {
 		if (pev->sdt) {
 			if (entry->pev.event &&
 			    streql(entry->pev.event, pev->event) &&
@@ -576,7 +576,7 @@ probe_cache__find_by_name(struct probe_cache *pcache,
 {
 	struct probe_cache_entry *entry = NULL;
 
-	list_for_each_entry(entry, &pcache->entries, node) {
+	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))
@@ -746,7 +746,7 @@ int probe_cache__commit(struct probe_cache *pcache)
 	if (ret < 0)
 		goto out;
 
-	list_for_each_entry(entry, &pcache->entries, node) {
+	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)
@@ -788,7 +788,7 @@ static int probe_cache__show_entries(struct probe_cache *pcache,
 {
 	struct probe_cache_entry *entry;
 
-	list_for_each_entry(entry, &pcache->entries, node) {
+	for_each_probe_cache_entry(entry, pcache) {
 		if (probe_cache_entry__compare(entry, filter))
 			printf("%s\n", entry->spev);
 	}
tools/perf/util/probe-file.h +2 -0
index ddf5ae2..d513b34 100644
@@ -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->entries, node)
 
 int probe_file__open(int flag);
 int probe_file__open_both(int *kfd, int *ufd, int flag);
#10 lore raw

[tip:perf/core] perf probe-cache: Add for_each_probe_cache_entry() wrapper

perf probe-cache: Add for_each_probe_cache_entry() wrapper
Commit-ID:  05bf2c8a2a819132b4a8f35d4315ff22e8e84a20
Gitweb:     http://git.kernel.org/tip/05bf2c8a2a819132b4a8f35d4315ff22e8e84a20
Author:     Masami Hiramatsu <[email protected]>
AuthorDate: Tue, 12 Jul 2016 19:05:04 +0900
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 13 Jul 2016 23:09:06 -0300

perf probe-cache: Add for_each_probe_cache_entry() wrapper

Add for_each_probe_cache_entry() wrapper macro for hiding list in probe_cache.

---
 tools/perf/util/probe-file.c | 8 ++++----
 tools/perf/util/probe-file.h | 2 ++
 2 files changed, 6 insertions(+), 4 deletions(-)
tools/perf/util/probe-file.c +4 -4
index a5059dc..abfb05c 100644
@@ -546,7 +546,7 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
 	if (!cmd)
 		return NULL;
 
-	list_for_each_entry(entry, &pcache->entries, node) {
+	for_each_probe_cache_entry(entry, pcache) {
 		if (pev->sdt) {
 			if (entry->pev.event &&
 			    streql(entry->pev.event, pev->event) &&
@@ -576,7 +576,7 @@ probe_cache__find_by_name(struct probe_cache *pcache,
 {
 	struct probe_cache_entry *entry = NULL;
 
-	list_for_each_entry(entry, &pcache->entries, node) {
+	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))
@@ -748,7 +748,7 @@ int probe_cache__commit(struct probe_cache *pcache)
 	if (ret < 0)
 		goto out;
 
-	list_for_each_entry(entry, &pcache->entries, node) {
+	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)
@@ -790,7 +790,7 @@ static int probe_cache__show_entries(struct probe_cache *pcache,
 {
 	struct probe_cache_entry *entry;
 
-	list_for_each_entry(entry, &pcache->entries, node) {
+	for_each_probe_cache_entry(entry, pcache) {
 		if (probe_cache_entry__compare(entry, filter))
 			printf("%s\n", entry->spev);
 	}
tools/perf/util/probe-file.h +2 -0
index ddf5ae2..d513b34 100644
@@ -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->entries, node)
 
 int probe_file__open(int flag);
 int probe_file__open_both(int *kfd, int *ufd, int flag);
#11 lore raw

PATCH 5/10 perf probe: Allow wildcard for cached events

In reply to Masami Hiramatsu

Allo glob wildcard for reusing cached/SDT events. E.g.

  # perf probe -x /usr/lib64/libc-2.20.so -a %sdt_libc:\*

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

---
Changes in v12:
- Rename strlist__for_each to strlist__for_each_entry.
Changes in v10:
- Split off bugfix, adding interface, and target search patches.
- Do not export clear_probe_trace_events().
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 |  107 +++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/probe-file.c  |   38 ++++++++++++---
 tools/perf/util/probe-file.h  |    3 +
 3 files changed, 138 insertions(+), 10 deletions(-)
tools/perf/util/probe-event.c +103 -4
index 3642cca..1aeac09 100644
@@ -1204,7 +1204,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)
@@ -1212,7 +1212,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);
@@ -1644,6 +1644,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
 			ret = -ENOMEM;
 			goto out;
 		}
+		tev->uprobes = (tp->module[0] == '/');
 		p++;
 	} else
 		p = argv[1];
@@ -2518,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;
@@ -2531,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;
@@ -2894,6 +2895,100 @@ 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 && target[0] == '/')
+			pev->uprobes = true;
+	}
+
+	return ret;
+}
+
 static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 					      struct probe_trace_event **tevs)
 {
@@ -2903,6 +2998,10 @@ 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 */
+		return find_cached_events(pev, tevs, pev->target);
+
 	cache = probe_cache__new(pev->target);
 	if (!cache)
 		return 0;
tools/perf/util/probe-file.c +32 -6
index 9152ad2..78a84f5 100644
@@ -362,13 +362,38 @@ probe_cache_entry__new(struct perf_probe_event *pev)
 	return entry;
 }
 
-/* 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_entry(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)) {
@@ -378,12 +403,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;
tools/perf/util/probe-file.h +3 -0
index d513b34..cafbe1d 100644
@@ -34,6 +34,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,
#12 lore raw

Re: [PATCH perf/core 05/10] perf probe: Allow wildcard for cached events

Em Tue, Jul 12, 2016 at 07:05:18PM +0900, Masami Hiramatsu escreveu:

Quoted 3 lines

Allo glob wildcard for reusing cached/SDT events. E.g.

  # perf probe -x /usr/lib64/libc-2.20.so -a %sdt_libc:\*

The example message for this could be improved to also use a wildcard :-)

Quoted 260 lines

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

---
Changes in v12:
- Rename strlist__for_each to strlist__for_each_entry.
Changes in v10:
- Split off bugfix, adding interface, and target search patches.
- Do not export clear_probe_trace_events().
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 |  107 +++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/probe-file.c  |   38 ++++++++++++---
 tools/perf/util/probe-file.h  |    3 +
 3 files changed, 138 insertions(+), 10 deletions(-)
tools/perf/util/probe-event.c +103 -4
index 3642cca..1aeac09 100644
@@ -1204,7 +1204,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)
@@ -1212,7 +1212,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);
@@ -1644,6 +1644,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
 			ret = -ENOMEM;
 			goto out;
 		}
+		tev->uprobes = (tp->module[0] == '/');
 		p++;
 	} else
 		p = argv[1];
@@ -2518,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;
@@ -2531,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;
@@ -2894,6 +2895,100 @@ 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 && target[0] == '/')
+			pev->uprobes = true;
+	}
+
+	return ret;
+}
+
 static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 					      struct probe_trace_event **tevs)
 {
@@ -2903,6 +2998,10 @@ 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 */
+		return find_cached_events(pev, tevs, pev->target);
+
 	cache = probe_cache__new(pev->target);
 	if (!cache)
 		return 0;
tools/perf/util/probe-file.c +32 -6
index 9152ad2..78a84f5 100644
@@ -362,13 +362,38 @@ probe_cache_entry__new(struct perf_probe_event *pev)
 	return entry;
 }
 
-/* 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_entry(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)) {
@@ -378,12 +403,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;
tools/perf/util/probe-file.h +3 -0
index d513b34..cafbe1d 100644
@@ -34,6 +34,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,
#13 lore raw

[tip:perf/core] perf probe: Allow wildcard for cached events

In reply to Masami Hiramatsu
perf probe: Allow wildcard for cached events
Commit-ID:  42bba263eb58800b6239a0cb35ac17fd29379277
Gitweb:     http://git.kernel.org/tip/42bba263eb58800b6239a0cb35ac17fd29379277
Author:     Masami Hiramatsu <[email protected]>
AuthorDate: Tue, 12 Jul 2016 19:05:18 +0900
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 13 Jul 2016 23:09:07 -0300

perf probe: Allow wildcard for cached events

Allo glob wildcard for reusing cached/SDT events. E.g.

  # perf probe -x /usr/lib64/libc-2.20.so -a %sdt_libc:\*

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

Committer note:

Using it to check what of those SDT probes would take place when doing a cargo run (rust):

  # trace --no-sys --event sdt_libc:* cargo run
     0.000 sdt_libc:setjmp:(7f326b69c4d1))
    28.423 sdt_libc:setjmp:(7f4b0a5364d1))
    29.000 sdt_libc:setjmp:(7f4b0a5364d1))
    88.597 sdt_libc:setjmp:(7fc01fd414d1))
    89.220 sdt_libc:setjmp:(7fc01fd414d1))
    95.501 sdt_libc:setjmp:(7f326b69c4d1))
     Running `target/debug/hello_world`
    97.110 sdt_libc:setjmp:(7f95e09234d1))
  Hello, world!
  #
---
 tools/perf/util/probe-event.c | 107 ++++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/probe-file.c  |  38 ++++++++++++---
 tools/perf/util/probe-file.h  |   3 ++
 3 files changed, 138 insertions(+), 10 deletions(-)
tools/perf/util/probe-event.c +103 -4
index 85f25d4..7b96e68 100644
@@ -1204,7 +1204,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)
@@ -1212,7 +1212,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);
@@ -1644,6 +1644,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
 			ret = -ENOMEM;
 			goto out;
 		}
+		tev->uprobes = (tp->module[0] == '/');
 		p++;
 	} else
 		p = argv[1];
@@ -2518,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;
@@ -2531,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;
@@ -2894,6 +2895,100 @@ 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 && target[0] == '/')
+			pev->uprobes = true;
+	}
+
+	return ret;
+}
+
 static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 					      struct probe_trace_event **tevs)
 {
@@ -2903,6 +2998,10 @@ 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 */
+		return find_cached_events(pev, tevs, pev->target);
+
 	cache = probe_cache__new(pev->target);
 	if (!cache)
 		return 0;
tools/perf/util/probe-file.c +32 -6
index abfb05c..9aed9c3 100644
@@ -362,13 +362,38 @@ probe_cache_entry__new(struct perf_probe_event *pev)
 	return entry;
 }
 
-/* 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_entry(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)) {
@@ -378,12 +403,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;
tools/perf/util/probe-file.h +3 -0
index d513b34..cafbe1d 100644
@@ -34,6 +34,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,
#14 lore raw

PATCH 6/10 perf probe: Search SDT/cached event from all probe caches

In reply to Masami Hiramatsu

Search SDT/cached event from all probe caches if user doesn't pass any binary. With this, we don't have to specify target binary for SDT and named cached events (which start with %).

E.g. without this, a target binary must be passed with -x.

 # perf probe -x /usr/lib64/libc-2.20.so -a %sdt_libc:\*

With this change, we don't need it anymore.

 # perf probe -a %sdt_libc:\*

---
Changes in v12:
- Rename strlist__for_each to strlist__for_each_entry.
Changes from v10:
- Splitted from "perf probe: Allow wildcard for cached events"

---
 tools/perf/util/probe-event.c |  105 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 86 insertions(+), 19 deletions(-)
tools/perf/util/probe-event.c +86 -19
index 1aeac09..679aa6b 100644
@@ -2557,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;
 
@@ -2614,9 +2633,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 		probe_cache__delete(cache);
 	}
 
-	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;
 }
 
@@ -2989,6 +3011,48 @@ static int find_cached_events(struct perf_probe_event *pev,
 	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 */
+	bidlist = build_id_cache__list_all(true);
+	if (!bidlist) {
+		ret = -errno;
+		pr_debug("Failed to get buildids: %d\n", ret);
+		return ret;
+	}
+
+	ret = 0;
+	strlist__for_each_entry(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)
 {
@@ -2998,10 +3062,13 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 	struct str_node *node;
 	int ret, i;
 
-	if (pev->sdt)
+	if (pev->sdt) {
 		/* For SDT/cached events, we use special search functions */
-		return find_cached_events(pev, tevs, pev->target);
-
+		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;
#15 lore raw

[tip:perf/core] perf probe: Search SDT/cached event from all probe caches

perf probe: Search SDT/cached event from all probe caches
Commit-ID:  1de7b8bf728fd8d51b0cc644003d0694c6e0feef
Gitweb:     http://git.kernel.org/tip/1de7b8bf728fd8d51b0cc644003d0694c6e0feef
Author:     Masami Hiramatsu <[email protected]>
AuthorDate: Tue, 12 Jul 2016 19:05:28 +0900
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 13 Jul 2016 23:09:07 -0300

perf probe: Search SDT/cached event from all probe caches

Search SDT/cached event from all probe caches if user doesn't pass any binary. With this, we don't have to specify target binary for SDT and named cached events (which start with %).

E.g. without this, a target binary must be passed with -x.

  # perf probe -x /usr/lib64/libc-2.20.so -a %sdt_libc:\*

With this change, we don't need it anymore.

  # perf probe -a %sdt_libc:\*
---
 tools/perf/util/probe-event.c | 105 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 86 insertions(+), 19 deletions(-)
tools/perf/util/probe-event.c +86 -19
index 7b96e68..c63e3b8 100644
@@ -2557,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;
 
@@ -2614,9 +2633,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 		probe_cache__delete(cache);
 	}
 
-	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;
 }
 
@@ -2989,6 +3011,48 @@ static int find_cached_events(struct perf_probe_event *pev,
 	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 */
+	bidlist = build_id_cache__list_all(true);
+	if (!bidlist) {
+		ret = -errno;
+		pr_debug("Failed to get buildids: %d\n", ret);
+		return ret;
+	}
+
+	ret = 0;
+	strlist__for_each_entry(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)
 {
@@ -2998,10 +3062,13 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 	struct str_node *node;
 	int ret, i;
 
-	if (pev->sdt)
+	if (pev->sdt) {
 		/* For SDT/cached events, we use special search functions */
-		return find_cached_events(pev, tevs, pev->target);
-
+		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;
#16 lore raw

PATCH 7/10 perf probe: Support @BUILDID or @FILE suffix for SDT events

In reply to Masami Hiramatsu

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
----

---
Changes in v12:
- Rename strlist__for_each to strlist__for_each_entry.

---
 tools/perf/util/build-id.c    |   43 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/build-id.h    |    1 +
 tools/perf/util/probe-event.c |   17 ++++++++++++++--
 3 files changed, 59 insertions(+), 2 deletions(-)
tools/perf/util/build-id.c +43 -0
index 8e86a83..e59003e 100644
@@ -523,6 +523,49 @@ err_out:
 	goto out_free;
 }
 
+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 *bidlist;
+	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))
+		return NULL;
+
+	bidlist = build_id_cache__list_all(true);
+	if (!bidlist)
+		return NULL;
+
+	strlist__for_each_entry(nd, bidlist) {
+		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(bidlist);
+
+	return sbuild_id;
+}
+
 char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
 			       bool is_kallsyms, bool is_vdso)
 {
tools/perf/util/build-id.h +1 -0
index 64e740f..d279906 100644
@@ -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);
 struct strlist *build_id_cache__list_all(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);
tools/perf/util/probe-event.c +15 -2
index 679aa6b..0dadaa3 100644
@@ -1251,8 +1251,21 @@ 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 be an SDT 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) {
#17 lore raw

Re: [PATCH perf/core 07/10] perf probe: Support @BUILDID or @FILE suffix for SDT events

Em Tue, Jul 12, 2016 at 07:05:37PM +0900, Masami Hiramatsu escreveu:

Quoted 7 lines

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.

Ok, how to add those entries?

[root@jouet hello_world]# perf probe -x /usr/bin/gcc -a %sdt_gcc:\*
Error: Failed to add events.
[root@jouet hello_world]# perf probe --verbose -x /usr/bin/gcc -a %sdt_gcc:\* probe-definition(0): %sdt_gcc:*
0 arguments
symbol:throw file:(null) line:0 offset:0 return:0 lazy:(null) symbol:rethrow file:(null) line:0 offset:0 return:0 lazy:(null) symbol:catch file:(null) line:0 offset:0 return:0 lazy:(null) symbol:unwind file:(null) line:0 offset:0 return:0 lazy:(null)
Error: Failed to add events. Reason: No such file or directory (Code: -2)
[root@jouet hello_world]#

Can those messages be improved? What am I missing?

Quoted 121 lines

----

  # 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
----

---
Changes in v12:
- Rename strlist__for_each to strlist__for_each_entry.

---
 tools/perf/util/build-id.c    |   43 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/build-id.h    |    1 +
 tools/perf/util/probe-event.c |   17 ++++++++++++++--
 3 files changed, 59 insertions(+), 2 deletions(-)
tools/perf/util/build-id.c +43 -0
index 8e86a83..e59003e 100644
@@ -523,6 +523,49 @@ err_out:
 	goto out_free;
 }
 
+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 *bidlist;
+	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))
+		return NULL;
+
+	bidlist = build_id_cache__list_all(true);
+	if (!bidlist)
+		return NULL;
+
+	strlist__for_each_entry(nd, bidlist) {
+		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(bidlist);
+
+	return sbuild_id;
+}
+
 char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
 			       bool is_kallsyms, bool is_vdso)
 {
tools/perf/util/build-id.h +1 -0
index 64e740f..d279906 100644
@@ -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);
 struct strlist *build_id_cache__list_all(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);
tools/perf/util/probe-event.c +15 -2
index 679aa6b..0dadaa3 100644
@@ -1251,8 +1251,21 @@ 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 be an SDT 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) {
#18 lore raw

Re: [PATCH perf/core 07/10] perf probe: Support @BUILDID or @FILE suffix for SDT events

Em Wed, Jul 13, 2016 at 04:50:19PM -0300, Arnaldo Carvalho de Melo escreveu:

Quoted 11 lines

Em Tue, Jul 12, 2016 at 07:05:37PM +0900, Masami Hiramatsu escreveu:

Quoted 7 lines

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.

Ok, how to add those entries?

Quoted 11 lines

[root@jouet hello_world]# perf probe -x /usr/bin/gcc -a %sdt_gcc:\*
Error: Failed to add events.
[root@jouet hello_world]# perf probe --verbose -x /usr/bin/gcc -a %sdt_gcc:\* probe-definition(0): %sdt_gcc:*
0 arguments
symbol:throw file:(null) line:0 offset:0 return:0 lazy:(null) symbol:rethrow file:(null) line:0 offset:0 return:0 lazy:(null) symbol:catch file:(null) line:0 offset:0 return:0 lazy:(null) symbol:unwind file:(null) line:0 offset:0 return:0 lazy:(null)
Error: Failed to add events. Reason: No such file or directory (Code: -2)
[root@jouet hello_world]#

So, ok, I managed with:

[root@jouet ~]# perf probe -x /usr/bin/gcc %sdt_libstdcxx:\* Added new events:
sdt_libstdcxx:throw (on %* in /usr/bin/gcc) sdt_libstdcxx:rethrow (on %* in /usr/bin/gcc) sdt_libstdcxx:catch (on %* in /usr/bin/gcc)

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

perf record -e sdt_libstdcxx:catch -aR sleep 1

[root@jouet ~]#

I then tried to remove the events just created:

# perf probe -d  %sdt_libstdcxx:\*
#

It tells me nothing, cool, probably it removed it all, then I go and try re-adding them:

[root@jouet ~]# perf probe -x /usr/bin/gcc %sdt_libstdcxx:\*
Error: event "throw" already exists.
Hint: Remove existing event by 'perf probe -d'
or force duplicates by 'perf probe -f'
or set 'force=yes' in BPF source.
Error: Failed to add events.
[root@jouet ~]#

Huh?

Then I tried like you did above, using 'perf list sdt'

[root@jouet ~]# perf list sdt

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

[root@jouet ~]#

But they appear via 'perf probe -l'

[root@jouet ~]# perf probe -l sdt_libs*
sdt_libstdcxx:catch (on execute_cfa_program+1551@../../../libgcc/unwind-dw2.c in /usr/bin/gcc) sdt_libstdcxx:rethrow (on d_print_subexpr+280@libsupc++/cp-demangle.c in /usr/bin/gcc) sdt_libstdcxx:throw (on d_print_subexpr+93@libsupc++/cp-demangle.c in /usr/bin/gcc)
[root@jouet ~]#

There is no event, then, guessing, I tried removing that %, since I don't see it in the 'perf probe -l' output, so it must've been just some distracting artifact at the time of adding the SDT prove:

[root@jouet ~]# perf probe -d sdt_libstdcxx:\*
Removed event: sdt_libstdcxx:catch
Removed event: sdt_libstdcxx:rethrow
Removed event: sdt_libstdcxx:throw
[root@jouet ~]# perf probe -l sdt_libs*
[root@jouet ~]#

Ok, now it works, but then if I try having both the gcc and libstdc++ ones, I can't:

[root@jouet ~]# perf probe -x /usr/lib64/libstdc++.so.6 %sdt_libstdcxx:\*
Error: event "catch" already exists.
Hint: Remove existing event by 'perf probe -d'
or force duplicates by 'perf probe -f'
or set 'force=yes' in BPF source.
Error: Failed to add events.

So I forced it:

[root@jouet ~]# perf probe -f -x /usr/lib64/libstdc++.so.6 %sdt_libstdcxx:\* Added new events:
sdt_libstdcxx:catch_1 (on %* in /usr/lib64/libstdc++.so.6.0.22) sdt_libstdcxx:throw_1 (on %* in /usr/lib64/libstdc++.so.6.0.22) sdt_libstdcxx:rethrow_1 (on %* in /usr/lib64/libstdc++.so.6.0.22)

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

perf record -e sdt_libstdcxx:rethrow_1 -aR sleep 1

[root@jouet ~]#

If it will rename it, why require -f? Where is the duplicity?

If I go and re-read all the discussion on the thread that lead to these patches, I may figure out all those questions, but then, that would be a lot of info to have in mind :-\

I.e. I would suggest that no -f should be needed, that that "Error: event "catch" already exists" shouldn't be even emitted, since those will be different events, i.e. one is named "sdt_libstdcxx:catch" and the other "sdt_libstdcxx:catch_1"...

But that becomes an usability problem, couldn't it have the basename in it? I.e.:

sdt_gcc_libstdcxx:catch and sdt_libstdc++:catch?

I'm going to look my inbox for patches I overlook that added 'perf list sdt'...

- Arnaldo

Quoted 123 lines

Can those messages be improved? What am I missing?

Quoted 121 lines

----

  # 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
----

---
Changes in v12:
- Rename strlist__for_each to strlist__for_each_entry.

---
 tools/perf/util/build-id.c    |   43 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/build-id.h    |    1 +
 tools/perf/util/probe-event.c |   17 ++++++++++++++--
 3 files changed, 59 insertions(+), 2 deletions(-)
tools/perf/util/build-id.c +43 -0
index 8e86a83..e59003e 100644
@@ -523,6 +523,49 @@ err_out:
 	goto out_free;
 }
 
+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 *bidlist;
+	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))
+		return NULL;
+
+	bidlist = build_id_cache__list_all(true);
+	if (!bidlist)
+		return NULL;
+
+	strlist__for_each_entry(nd, bidlist) {
+		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(bidlist);
+
+	return sbuild_id;
+}
+
 char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
 			       bool is_kallsyms, bool is_vdso)
 {
tools/perf/util/build-id.h +1 -0
index 64e740f..d279906 100644
@@ -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);
 struct strlist *build_id_cache__list_all(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);
tools/perf/util/probe-event.c +15 -2
index 679aa6b..0dadaa3 100644
@@ -1251,8 +1251,21 @@ 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 be an SDT 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) {
#19 lore raw

Re: [PATCH perf/core 07/10] perf probe: Support @BUILDID or @FILE suffix for SDT events

Em Wed, Jul 13, 2016 at 09:07:19PM -0300, Arnaldo Carvalho de Melo escreveu:

Quoted 1 line

I'm going to look my inbox for patches I overlook that added 'perf list sdt'...

So it is here:

-> 976 T 06/24 Masami Hiramats (7.2K) [PATCH perf/core v12 08/16] perf-list: Show SDT and pre-cached events

June, 24, you forgot to rebase it for this new cset series, I'm doing that now.

- Arnaldo

#20 lore raw

Re: [PATCH perf/core 07/10] perf probe: Support @BUILDID or @FILE suffix for SDT events

Em Wed, Jul 13, 2016 at 09:16:32PM -0300, Arnaldo Carvalho de Melo escreveu:

Quoted 9 lines

Em Wed, Jul 13, 2016 at 09:07:19PM -0300, Arnaldo Carvalho de Melo escreveu:

Quoted 1 line

I'm going to look my inbox for patches I overlook that added 'perf list sdt'...

So it is here:

-> 976 T 06/24 Masami Hiramats (7.2K) [PATCH perf/core v12 08/16] perf-list: Show SDT and pre-cached events

June, 24, you forgot to rebase it for this new cset series, I'm doing that now.

Ok, now it works:

[root@jouet ~]# perf list sdt

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

  sdt_libc:lll_lock_wait_private                     [SDT event]
  sdt_libc:longjmp                                   [SDT event]
  sdt_libc:longjmp_target                            [SDT event]
  sdt_libc:memory_arena_new                          [SDT event]
  sdt_libc:memory_arena_retry                        [SDT event]
  sdt_libc:memory_arena_reuse                        [SDT event]
  sdt_libc:memory_arena_reuse_free_list              [SDT event]
  sdt_libc:memory_arena_reuse_wait                   [SDT event]
  sdt_libc:memory_calloc_retry                       [SDT event]
  sdt_libc:memory_heap_free                          [SDT event]
  sdt_libc:memory_heap_less                          [SDT event]
  sdt_libc:memory_heap_more                          [SDT event]
  sdt_libc:memory_heap_new                           [SDT event]
  sdt_libc:memory_malloc_retry                       [SDT event]
  sdt_libc:memory_mallopt                            [SDT event]
  sdt_libc:memory_mallopt_arena_max                  [SDT event]
  sdt_libc:memory_mallopt_arena_test                 [SDT event]
  sdt_libc:memory_mallopt_check_action               [SDT event]
  sdt_libc:memory_mallopt_free_dyn_thresholds        [SDT event]
  sdt_libc:memory_mallopt_mmap_max                   [SDT event]
  sdt_libc:memory_mallopt_mmap_threshold             [SDT event]
  sdt_libc:memory_mallopt_mxfast                     [SDT event]
  sdt_libc:memory_mallopt_perturb                    [SDT event]
  sdt_libc:memory_mallopt_top_pad                    [SDT event]
  sdt_libc:memory_mallopt_trim_threshold             [SDT event]
  sdt_libc:memory_memalign_retry                     [SDT event]
  sdt_libc:memory_realloc_retry                      [SDT event]
  sdt_libc:memory_sbrk_less                          [SDT event]
  sdt_libc:memory_sbrk_more                          [SDT event]
  sdt_libc:setjmp                                    [SDT event]
  sdt_libgcc:unwind                                  [SDT event]
  sdt_libstdcxx:catch@/usr/bin/gcc(9a0730e2bcc6)     [SDT event]

sdt_libstdcxx:catch@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]
sdt_libstdcxx:rethrow@/usr/bin/gcc(9a0730e2bcc6) [SDT event]
sdt_libstdcxx:rethrow@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]
sdt_libstdcxx:throw@/usr/bin/gcc(9a0730e2bcc6) [SDT event]
sdt_libstdcxx:throw@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]
[root@jouet ~]#

#21 lore raw

Re: [PATCH perf/core 07/10] perf probe: Support @BUILDID or @FILE suffix for SDT events

Quoted 10 lines · On Wed, 13 Jul 2016 21:20:48 -0300 Arnaldo Carvalho de Melo <[email protected]>…

Em Wed, Jul 13, 2016 at 09:16:32PM -0300, Arnaldo Carvalho de Melo escreveu:

Quoted 9 lines

Em Wed, Jul 13, 2016 at 09:07:19PM -0300, Arnaldo Carvalho de Melo escreveu:

Quoted 1 line

I'm going to look my inbox for patches I overlook that added 'perf list sdt'...

So it is here:

-> 976 T 06/24 Masami Hiramats (7.2K) [PATCH perf/core v12 08/16] perf-list: Show SDT and pre-cached events

June, 24, you forgot to rebase it for this new cset series, I'm doing that now.

Ah, I just dropped it because this series still not support direct recording yet. If we show the below SDTs by perf-list, we have to support it on perf-record which is under developed now.

Thank you,

Quoted 46 lines

Ok, now it works:

[root@jouet ~]# perf list sdt

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

  sdt_libc:lll_lock_wait_private                     [SDT event]
  sdt_libc:longjmp                                   [SDT event]
  sdt_libc:longjmp_target                            [SDT event]
  sdt_libc:memory_arena_new                          [SDT event]
  sdt_libc:memory_arena_retry                        [SDT event]
  sdt_libc:memory_arena_reuse                        [SDT event]
  sdt_libc:memory_arena_reuse_free_list              [SDT event]
  sdt_libc:memory_arena_reuse_wait                   [SDT event]
  sdt_libc:memory_calloc_retry                       [SDT event]
  sdt_libc:memory_heap_free                          [SDT event]
  sdt_libc:memory_heap_less                          [SDT event]
  sdt_libc:memory_heap_more                          [SDT event]
  sdt_libc:memory_heap_new                           [SDT event]
  sdt_libc:memory_malloc_retry                       [SDT event]
  sdt_libc:memory_mallopt                            [SDT event]
  sdt_libc:memory_mallopt_arena_max                  [SDT event]
  sdt_libc:memory_mallopt_arena_test                 [SDT event]
  sdt_libc:memory_mallopt_check_action               [SDT event]
  sdt_libc:memory_mallopt_free_dyn_thresholds        [SDT event]
  sdt_libc:memory_mallopt_mmap_max                   [SDT event]
  sdt_libc:memory_mallopt_mmap_threshold             [SDT event]
  sdt_libc:memory_mallopt_mxfast                     [SDT event]
  sdt_libc:memory_mallopt_perturb                    [SDT event]
  sdt_libc:memory_mallopt_top_pad                    [SDT event]
  sdt_libc:memory_mallopt_trim_threshold             [SDT event]
  sdt_libc:memory_memalign_retry                     [SDT event]
  sdt_libc:memory_realloc_retry                      [SDT event]
  sdt_libc:memory_sbrk_less                          [SDT event]
  sdt_libc:memory_sbrk_more                          [SDT event]
  sdt_libc:setjmp                                    [SDT event]
  sdt_libgcc:unwind                                  [SDT event]
  sdt_libstdcxx:catch@/usr/bin/gcc(9a0730e2bcc6)     [SDT event]

sdt_libstdcxx:catch@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]
sdt_libstdcxx:rethrow@/usr/bin/gcc(9a0730e2bcc6) [SDT event]
sdt_libstdcxx:rethrow@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]
sdt_libstdcxx:throw@/usr/bin/gcc(9a0730e2bcc6) [SDT event]
sdt_libstdcxx:throw@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]
[root@jouet ~]#

Signature · 1 line
Masami Hiramatsu <[email protected]>
#22 lore raw

[tip:perf/core] perf probe: Support @BUILDID or @FILE suffix for SDT events

In reply to Masami Hiramatsu
perf probe: Support @BUILDID or @FILE suffix for SDT events
Commit-ID:  a598180aa1279bac4d24dfc85cd2d78553c4210d
Gitweb:     http://git.kernel.org/tip/a598180aa1279bac4d24dfc85cd2d78553c4210d
Author:     Masami Hiramatsu <[email protected]>
AuthorDate: Tue, 12 Jul 2016 19:05:37 +0900
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 13 Jul 2016 23:09:08 -0300

perf probe: Support @BUILDID or @FILE suffix for SDT events

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
----

Committer note:

Doing the full sequence of steps to get the results above:

With a clean build-id cache:

[root@jouet ~]# rm -rf ~/.debug/
[root@jouet ~]# perf list sdt

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

[root@jouet ~]#

No events whatsoever, then, we can add all events in gcc to the build-id cache, doing a --add + --dry-run:

  [root@jouet ~]# perf probe --dry-run --cache -x /usr/bin/gcc --add %sdt_libstdcxx:\*
  Added new events:
    sdt_libstdcxx:throw  (on %* in /usr/bin/gcc)
    sdt_libstdcxx:rethrow (on %* in /usr/bin/gcc)
    sdt_libstdcxx:catch  (on %* in /usr/bin/gcc)

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

perf record -e sdt_libstdcxx:catch -aR sleep 1

[root@jouet ~]#

It really didn't add any events, it just cached them:

[root@jouet ~]# perf probe -l
[root@jouet ~]#

We can see that it was cached as:

[root@jouet ~]# ls -la ~/.debug/usr/bin/gcc/9a0730e2bcc6d2a2003d21ac46807e8ee6bcb7c2/
total 976
drwxr-xr-x. 2 root root 4096 Jul 13 21:47 .
drwxr-xr-x. 3 root root 4096 Jul 13 21:47 ..
-rwxr-xr-x. 4 root root 985912 Jun 22 18:52 elf
-rw-r--r--. 1 root root 303 Jul 13 21:47 probes
[root@jouet ~]# file ~/.debug/usr/bin/gcc/9a0730e2bcc6d2a2003d21ac46807e8ee6bcb7c2/elf
/root/.debug/usr/bin/gcc/9a0730e2bcc6d2a2003d21ac46807e8ee6bcb7c2/elf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=9a0730e2bcc6d2a2003d21ac46807e8ee6bcb7c2, stripped [root@jouet ~]# cat ~/.debug/usr/bin/gcc/9a0730e2bcc6d2a2003d21ac46807e8ee6bcb7c2/probes
%sdt_libstdcxx:throw=throw
p:sdt_libstdcxx/throw /usr/bin/gcc:0x71ffd
%sdt_libstdcxx:rethrow=rethrow
p:sdt_libstdcxx/rethrow /usr/bin/gcc:0x720b8
%sdt_libstdcxx:catch=catch
p:sdt_libstdcxx/catch /usr/bin/gcc:0x7307f
%sdt_libgcc:unwind=unwind
p:sdt_libgcc/unwind /usr/bin/gcc:0x7eec0
#sdt_libstdcxx:*=%*
[root@jouet ~]#

Ok, now we can use 'perf probe' to refer to those cached entries as:

Humm, nope, doing as above we end up with:

[root@jouet ~]# perf probe -a %sdt_libstdcxx:catch
Semantic error :* is bad for event name -it must follow C symbol-naming rule.
Error: Failed to add events.
[root@jouet ~]#

But it worked at some point, lets try not using --dry-run:

Resetting everything:

  # rm -rf ~/.debug/
  # perf probe -d *:*
  # perf probe -l
  # perf list sdt

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

#

Ok, now it cached everything, even things we haven't asked it to (sdt_libgcc:unwind):

  [root@jouet ~]# perf probe -x /usr/bin/gcc --add %sdt_libstdcxx:\*
  Added new events:
    sdt_libstdcxx:throw  (on %* in /usr/bin/gcc)
    sdt_libstdcxx:rethrow (on %* in /usr/bin/gcc)
    sdt_libstdcxx:catch  (on %* in /usr/bin/gcc)

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

perf record -e sdt_libstdcxx:catch -aR sleep 1

[root@jouet ~]# perf list sdt

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

    sdt_libgcc:unwind                                  [SDT event]
    sdt_libstdcxx:catch                                [SDT event]
    sdt_libstdcxx:rethrow                              [SDT event]
    sdt_libstdcxx:throw                                [SDT event]

[root@jouet ~]#

And we have the events in place:

[root@jouet ~]# perf probe -l
sdt_libstdcxx:catch (on execute_cfa_program+1551@../../../libgcc/unwind-dw2.c in /usr/bin/gcc) sdt_libstdcxx:rethrow (on d_print_subexpr+280@libsupc++/cp-demangle.c in /usr/bin/gcc) sdt_libstdcxx:throw (on d_print_subexpr+93@libsupc++/cp-demangle.c in /usr/bin/gcc)
[root@jouet ~]#

And trying to use them at least has 'perf trace --event sdt*:*' working.

Then, if we try to add the ones in libstdc++:

[root@jouet ~]# perf probe -x /usr/lib64/libstdc++.so.6 -a %sdt_libstdcxx:\*
Error: event "catch" already exists.
Hint: Remove existing event by 'perf probe -d'
or force duplicates by 'perf probe -f'
or set 'force=yes' in BPF source.
Error: Failed to add events.
[root@jouet ~]#

Doesn't work, dups, but at least this served to, unbeknownst to the user, add the SDT probes in /usr/lib64/libstdc++.so.6!

[root@jouet ~]# perf list sdt

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

    sdt_libgcc:unwind                                  [SDT event]
    sdt_libstdcxx:catch@/usr/bin/gcc(9a0730e2bcc6)     [SDT event]
    sdt_libstdcxx:catch@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]
    sdt_libstdcxx:rethrow@/usr/bin/gcc(9a0730e2bcc6)   [SDT event]
    sdt_libstdcxx:rethrow@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]
    sdt_libstdcxx:throw@/usr/bin/gcc(9a0730e2bcc6)     [SDT event]
    sdt_libstdcxx:throw@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]

[root@jouet ~]#

Now we should be able to get to the original cset comment, if we remove all SDTs events in place, not from the cache, from the kernel, where it was set up as:

[root@jouet ~]# ls -la /sys/kernel/debug/tracing/events/sdt_libstdcxx/ total 0
drwxr-xr-x. 5 root root 0 Jul 13 22:00 .
drwxr-xr-x. 80 root root 0 Jul 13 21:56 ..

  drwxr-xr-x.  2 root root 0 Jul 13 22:00 catch
  -rw-r--r--.  1 root root 0 Jul 13 22:00 enable
  -rw-r--r--.  1 root root 0 Jul 13 22:00 filter
  drwxr-xr-x.  2 root root 0 Jul 13 22:00 rethrow
  drwxr-xr-x.  2 root root 0 Jul 13 22:00 throw

[root@jouet ~]#

[root@jouet ~]# head -2 /sys/kernel/debug/tracing/events/sdt_libstdcxx/throw/format
name: throw
ID: 2059
[root@jouet ~]#

Now to remove it:

[root@jouet ~]# perf probe -d sdt_libstdc*:*
Removed event: sdt_libstdcxx:catch
Removed event: sdt_libstdcxx:rethrow
Removed event: sdt_libstdcxx:throw
[root@jouet ~]#

Which caused:

[root@jouet ~]# ls -la /sys/kernel/debug/tracing/events/sdt_libstdcxx/
ls: cannot access '/sys/kernel/debug/tracing/events/sdt_libstdcxx/': No such file or directory [root@jouet ~]#

Ok, now we can do:

[root@jouet ~]# perf list sdt_libstdcxx:catch

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

    sdt_libstdcxx:catch@/usr/bin/gcc(9a0730e2bcc6)     [SDT event]
    sdt_libstdcxx:catch@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]

[root@jouet ~]#

So, these are not really 'pre-defined events', i.e. we can't use them with 'perf record --event':

  [root@jouet ~]# perf record --event sdt_libstdcxx:catch*
  event syntax error: 'sdt_libstdcxx:catch*'
                       \___ unknown tracepoint

Error: File /sys/kernel/debug/tracing/events/sdt_libstdcxx/catch* not found.
Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
<SNIP>
[root@jouet ~]#

To have it really pre-defined we must use perf probe to get its definition from the cache and set it up in the kernel, creating the tracepoint to _then_ use it with 'perf record --event':

[root@jouet ~]# perf probe -a sdt_libstdcxx:catch Semantic error :There is non-digit char in line number. <SNIP>

Oops, there is another gotcha here, we need that pesky '%' character:

[root@jouet ~]# perf probe -a %sdt_libstdcxx:catch
Added new events:
sdt_libstdcxx:catch (on %catch in /usr/bin/gcc) sdt_libstdcxx:catch_1 (on %catch in /usr/lib64/libstdc++.so.6.0.22)

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

perf record -e sdt_libstdcxx:catch_1 -aR sleep 1

[root@jouet ~]#

But then we added _two_ events, one with the name we expected, the other one with a _ added, when doing the analysis we need to pay attention to who maps to who.

And here is where we get to the point of this patch, which is to be able to disambiguate those definitions for 'catch' in the build-id cache, but first we need remove those events we just added:

[root@jouet ~]# perf probe -d %sdt_libstdcxx:catch

Oops, that didn't remove anything, we need to _remove_ that % char in this case:

[root@jouet ~]# perf probe -d sdt_libstdcxx:catch Removed event: sdt_libstdcxx:catch

And we need to remove the other event added, i.e. I forgot to add a * at the end:

[root@jouet ~]# perf probe -d sdt_libstdcxx:catch* Removed event: sdt_libstdcxx:catch_1 [root@jouet ~]#

Ok, disambiguating it using what is in this patch:

[root@jouet ~]# perf list sdt_libstdcxx:catch

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

    sdt_libstdcxx:catch@/usr/bin/gcc(9a0730e2bcc6)     [SDT event]
    sdt_libstdcxx:catch@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]

[root@jouet ~]#
[root@jouet ~]# perf probe -a %sdt_libstdcxx:catch@9a07 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

[root@jouet ~]# perf probe -l

    sdt_libstdcxx:catch  (on execute_cfa_program+1551@../../../libgcc/unwind-dw2.c in /usr/bin/gcc)

[root@jouet ~]#

Yeah, it works! But we need to try and simplify this :-)

Update: Some aspects of this simplification take place in the following
patches.

---
 tools/perf/util/build-id.c    | 43 +++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/build-id.h    |  1 +
 tools/perf/util/probe-event.c | 17 +++++++++++++++--
 3 files changed, 59 insertions(+), 2 deletions(-)
tools/perf/util/build-id.c +43 -0
index 36b4279..5651f3c 100644
@@ -523,6 +523,49 @@ err_out:
 	goto out_free;
 }
 
+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 *bidlist;
+	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))
+		return NULL;
+
+	bidlist = build_id_cache__list_all(true);
+	if (!bidlist)
+		return NULL;
+
+	strlist__for_each_entry(nd, bidlist) {
+		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(bidlist);
+
+	return sbuild_id;
+}
+
 char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
 			       bool is_kallsyms, bool is_vdso)
 {
tools/perf/util/build-id.h +1 -0
index 64e740f..d279906 100644
@@ -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);
 struct strlist *build_id_cache__list_all(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);
tools/perf/util/probe-event.c +15 -2
index c63e3b8..f12081e 100644
@@ -1251,8 +1251,21 @@ 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 be an SDT 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) {
#23 lore raw

PATCH 8/10 perf probe: Support a special SDT probe format

In reply to Masami Hiramatsu

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

E.g. without this:
----

  # perf probe -a sdt_libc:setjmp
  Semantic error :There is non-digit char in line number.
  ...
  ----
With this:
  ----
  # perf probe -a sdt_libc:setjmp
  Added new event:
    sdt_libc:setjmp      (on %setjmp in /usr/lib64/libc-2.20.so)

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

perf record -e sdt_libc:setjmp -aR sleep 1
----

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

[tip:perf/core] perf probe: Support a special SDT probe format

perf probe: Support a special SDT probe format
Commit-ID:  7e9fca51fbf8430e27fb6b29299eda575e3f00cf
Gitweb:     http://git.kernel.org/tip/7e9fca51fbf8430e27fb6b29299eda575e3f00cf
Author:     Masami Hiramatsu <[email protected]>
AuthorDate: Tue, 12 Jul 2016 19:05:46 +0900
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 13 Jul 2016 23:09:09 -0300

perf probe: Support a special SDT probe format

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

E.g. without this:

  # perf probe -a sdt_libc:setjmp
  Semantic error :There is non-digit char in line number.
  ...

With this:

  # perf probe -a sdt_libc:setjmp
  Added new event:
    sdt_libc:setjmp      (on %setjmp in /usr/lib64/libc-2.20.so)

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

perf record -e sdt_libc:setjmp -aR sleep 1

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

PATCH 9/10 perf build: Add sdt feature detection

In reply to Masami Hiramatsu

This checks whether sys/sdt.h is available or not, which is required for DTRACE_PROBE().
We can disable this feature by passing NO_SDT=1 when building.
This flag will be used for SDT test case and further SDT events in perftools.

---
 tools/perf/Makefile.perf   |    3 +++
 tools/perf/config/Makefile |   10 ++++++++++
 tools/perf/tests/make      |    3 ++-
 3 files changed, 15 insertions(+), 1 deletion(-)
tools/build/Makefile.feature +2 -1
index 3dd529b..a1ec630 100644
@@ -61,7 +61,8 @@ FEATURE_TESTS_BASIC :=			\
 	zlib				\
 	lzma				\
 	get_cpuid			\
-	bpf
+	bpf				\
+	sdt
 
 # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
 # of all feature tests
tools/build/feature/Makefile +5 -1
index 6747116..8716ab2 100644
@@ -44,7 +44,8 @@ FILES=					\
 	test-zlib.bin			\
 	test-lzma.bin			\
 	test-bpf.bin			\
-	test-get_cpuid.bin
+	test-get_cpuid.bin		\
+	test-sdt.bin
 
 FILES := $(addprefix $(OUTPUT),$(FILES))
 
@@ -209,6 +210,9 @@ $(OUTPUT)test-get_cpuid.bin:
 $(OUTPUT)test-bpf.bin:
 	$(BUILD)
 
+$(OUTPUT)test-sdt.bin:
+	$(BUILD)
+
 -include $(OUTPUT)*.d
 
 ###############################
tools/build/feature/test-all.c +5 -0
index 7433cca..bab33d8 100644
@@ -141,6 +141,10 @@
 # include "test-libcrypto.c"
 #undef main
 
+#define main main_test_sdt
+# include "test-sdt.c"
+#undef main
+
 int main(int argc, char *argv[])
 {
 	main_test_libpython();
@@ -173,6 +177,7 @@ int main(int argc, char *argv[])
 	main_test_get_cpuid();
 	main_test_bpf();
 	main_test_libcrypto();
+	main_test_sdt();
 
 	return 0;
 }
tools/build/feature/test-sdt.c new file +7 -0
new file mode 100644
index 0000000..e4531a6
@@ -0,0 +1,7 @@
+#include <sys/sdt.h>
+
+int main(void)
+{
+	DTRACE_PROBE(provider, name);
+	return 0;
+}
tools/perf/Makefile.perf +3 -0
index d0a2cb1..458eaf5 100644
@@ -81,6 +81,9 @@ include ../scripts/utilities.mak
 #
 # Define NO_LIBBPF if you do not want BPF support
 #
+# Define NO_SDT if you do not want to define SDT event in perf tools,
+# note that it doesn't disable SDT scanning support.
+#
 # Define FEATURES_DUMP to provide features detection dump file
 # and bypass the feature detection
 
tools/perf/config/Makefile +10 -0
index c7e269a..b55f9ec 100644
@@ -349,6 +349,16 @@ ifndef NO_LIBELF
   endif # NO_LIBBPF
 endif # NO_LIBELF
 
+ifndef NO_SDT
+  ifneq ($(feature-sdt), 1)
+    msg := $(warning No sys/sdt.h found, no SDT events are defined, please install systemtap-sdt-devel or systemtap-sdt-dev);
+    NO_SDT := 1;
+  else
+    CFLAGS += -DHAVE_SDT_EVENT
+    $(call detected,CONFIG_SDT_EVENT)
+  endif
+endif
+
 ifdef PERF_HAVE_JITDUMP
   ifndef NO_DWARF
     $(call detected,CONFIG_JITDUMP)
tools/perf/tests/make +2 -1
index 51966d9..143f4d5 100644
@@ -82,6 +82,7 @@ make_no_auxtrace    := NO_AUXTRACE=1
 make_no_libbpf	    := NO_LIBBPF=1
 make_no_libcrypto   := NO_LIBCRYPTO=1
 make_with_babeltrace:= LIBBABELTRACE=1
+make_no_sdt	    := NO_SDT=1
 make_tags           := tags
 make_cscope         := cscope
 make_help           := help
@@ -105,7 +106,7 @@ make_minimal        := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
 make_minimal        += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
 make_minimal        += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
 make_minimal        += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
-make_minimal        += NO_LIBCRYPTO=1
+make_minimal        += NO_LIBCRYPTO=1 NO_SDT=1
 
 # $(run) contains all available tests
 run := make_pure
#26 lore raw

[tip:perf/core] perf build: Add sdt feature detection

perf build: Add sdt feature detection
Commit-ID:  e26e63be64a108c1fd12020b93b5b447ffe0532b
Gitweb:     http://git.kernel.org/tip/e26e63be64a108c1fd12020b93b5b447ffe0532b
Author:     Masami Hiramatsu <[email protected]>
AuthorDate: Tue, 12 Jul 2016 19:05:56 +0900
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 13 Jul 2016 23:09:09 -0300

perf build: Add sdt feature detection

This checks whether sys/sdt.h is available or not, which is required for DTRACE_PROBE().

We can disable this feature by passing NO_SDT=1 when building.

This flag will be used for SDT test case and further SDT events in perftools.

---
 tools/build/Makefile.feature   |  3 ++-
 tools/build/feature/Makefile   |  6 +++++-
 tools/build/feature/test-all.c |  5 +++++
 tools/build/feature/test-sdt.c |  7 +++++++
 tools/perf/Makefile.perf       |  3 +++
 tools/perf/config/Makefile     | 10 ++++++++++
 tools/perf/tests/make          |  3 ++-
 7 files changed, 34 insertions(+), 3 deletions(-)
tools/build/Makefile.feature +2 -1
index fe12bee..a120c6b 100644
@@ -62,7 +62,8 @@ FEATURE_TESTS_BASIC :=			\
 	zlib				\
 	lzma				\
 	get_cpuid			\
-	bpf
+	bpf				\
+	sdt
 
 # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
 # of all feature tests
tools/build/feature/Makefile +5 -1
index d6017c1..a0b29a3 100644
@@ -45,7 +45,8 @@ FILES=					\
 	test-zlib.bin			\
 	test-lzma.bin			\
 	test-bpf.bin			\
-	test-get_cpuid.bin
+	test-get_cpuid.bin		\
+	test-sdt.bin
 
 FILES := $(addprefix $(OUTPUT),$(FILES))
 
@@ -213,6 +214,9 @@ $(OUTPUT)test-get_cpuid.bin:
 $(OUTPUT)test-bpf.bin:
 	$(BUILD)
 
+$(OUTPUT)test-sdt.bin:
+	$(BUILD)
+
 -include $(OUTPUT)*.d
 
 ###############################
tools/build/feature/test-all.c +5 -0
index 843aed0..699e436 100644
@@ -145,6 +145,10 @@
 # include "test-libcrypto.c"
 #undef main
 
+#define main main_test_sdt
+# include "test-sdt.c"
+#undef main
+
 int main(int argc, char *argv[])
 {
 	main_test_libpython();
@@ -178,6 +182,7 @@ int main(int argc, char *argv[])
 	main_test_get_cpuid();
 	main_test_bpf();
 	main_test_libcrypto();
+	main_test_sdt();
 
 	return 0;
 }
tools/build/feature/test-sdt.c new file +7 -0
new file mode 100644
index 0000000..e4531a6
@@ -0,0 +1,7 @@
+#include <sys/sdt.h>
+
+int main(void)
+{
+	DTRACE_PROBE(provider, name);
+	return 0;
+}
tools/perf/Makefile.perf +3 -0
index feb2c66..a129fbc 100644
@@ -81,6 +81,9 @@ include ../scripts/utilities.mak
 #
 # Define NO_LIBBPF if you do not want BPF support
 #
+# Define NO_SDT if you do not want to define SDT event in perf tools,
+# note that it doesn't disable SDT scanning support.
+#
 # Define FEATURES_DUMP to provide features detection dump file
 # and bypass the feature detection
 
tools/perf/config/Makefile +10 -0
index 5ac4280..24803c5 100644
@@ -355,6 +355,16 @@ ifndef NO_LIBELF
   endif # NO_LIBBPF
 endif # NO_LIBELF
 
+ifndef NO_SDT
+  ifneq ($(feature-sdt), 1)
+    msg := $(warning No sys/sdt.h found, no SDT events are defined, please install systemtap-sdt-devel or systemtap-sdt-dev);
+    NO_SDT := 1;
+  else
+    CFLAGS += -DHAVE_SDT_EVENT
+    $(call detected,CONFIG_SDT_EVENT)
+  endif
+endif
+
 ifdef PERF_HAVE_JITDUMP
   ifndef NO_DWARF
     $(call detected,CONFIG_JITDUMP)
tools/perf/tests/make +2 -1
index 51966d9..143f4d5 100644
@@ -82,6 +82,7 @@ make_no_auxtrace    := NO_AUXTRACE=1
 make_no_libbpf	    := NO_LIBBPF=1
 make_no_libcrypto   := NO_LIBCRYPTO=1
 make_with_babeltrace:= LIBBABELTRACE=1
+make_no_sdt	    := NO_SDT=1
 make_tags           := tags
 make_cscope         := cscope
 make_help           := help
@@ -105,7 +106,7 @@ make_minimal        := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
 make_minimal        += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
 make_minimal        += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
 make_minimal        += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
-make_minimal        += NO_LIBCRYPTO=1
+make_minimal        += NO_LIBCRYPTO=1 NO_SDT=1
 
 # $(run) contains all available tests
 run := make_pure
#27 lore raw

PATCH 10/10 perf-test: Add a test case for SDT event

In reply to Masami Hiramatsu

Add a basic test case for SDT event support.
This test scans an SDT event in perftools and
check whether the SDT event is correctly stored
into the buildid cache.
Here is an example:
----

  $ perf test sdt -v
  47: Test SDT event probing                                   :
  --- start ---
  test child forked, pid 20732
  Found 72 SDTs in /home/mhiramat/ksrc/linux/tools/perf/perf
  Writing cache: %sdt_perf:test_target=test_target
  Cache committed: 0
  symbol:test_target file:(null) line:0 offset:0 return:0 lazy:(null)
  test child finished with 0
  ---- end ----
  Test SDT event probing: Ok
  ----
---
 tools/perf/tests/Build          |    1 
 tools/perf/tests/builtin-test.c |    4 +
 tools/perf/tests/sdt.c          |  115 +++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h        |    1 
 4 files changed, 121 insertions(+)
 create mode 100644 tools/perf/tests/sdt.c
tools/perf/tests/Build +1 -0
index 66a2898..4158422 100644
@@ -39,6 +39,7 @@ perf-y += stat.o
 perf-y += event_update.o
 perf-y += event-times.o
 perf-y += backward-ring-buffer.o
+perf-y += sdt.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
 	$(call rule_mkdir)
tools/perf/tests/builtin-test.c +4 -0
index 07c14e9..74ed9f5 100644
@@ -218,6 +218,10 @@ static struct test generic_tests[] = {
 		.func = test__cpu_map_print,
 	},
 	{
+		.desc = "Test SDT event probing",
+		.func = test__sdt_event,
+	},
+	{
 		.func = NULL,
 	},
 };
tools/perf/tests/sdt.c new file +115 -0

115 lines not on this page · raw message

tools/perf/tests/tests.h +1 -0
index 52f9695..a0288f8 100644
@@ -88,6 +88,7 @@ int test__event_update(int subtest);
 int test__event_times(int subtest);
 int test__backward_ring_buffer(int subtest);
 int test__cpu_map_print(int subtest);
+int test__sdt_event(int subtest);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
#28 lore raw

[tip:perf/core] perf test: Add a test case for SDT event

perf test: Add a test case for SDT event
Commit-ID:  8e5dc848356ecf6ea8d27d641c4d7ad8d42fe92b
Gitweb:     http://git.kernel.org/tip/8e5dc848356ecf6ea8d27d641c4d7ad8d42fe92b
Author:     Masami Hiramatsu <[email protected]>
AuthorDate: Tue, 12 Jul 2016 19:06:05 +0900
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 13 Jul 2016 23:09:10 -0300

perf test: Add a test case for SDT event

Add a basic test case for SDT event support. This test scans an SDT event in perftools and check whether the SDT event is correctly stored into the buildid cache.

Here is an example:

----

  $ perf test sdt -v
  47: Test SDT event probing                                   :
  --- start ---
  test child forked, pid 20732
  Found 72 SDTs in /home/mhiramat/ksrc/linux/tools/perf/perf
  Writing cache: %sdt_perf:test_target=test_target
  Cache committed: 0
  symbol:test_target file:(null) line:0 offset:0 return:0 lazy:(null)
  test child finished with 0
  ---- end ----
  Test SDT event probing: Ok
  ----
---
 tools/perf/tests/Build          |   1 +
 tools/perf/tests/builtin-test.c |   4 ++
 tools/perf/tests/sdt.c          | 115 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h        |   1 +
 4 files changed, 121 insertions(+)
tools/perf/tests/Build +1 -0
index 66a2898..4158422 100644
@@ -39,6 +39,7 @@ perf-y += stat.o
 perf-y += event_update.o
 perf-y += event-times.o
 perf-y += backward-ring-buffer.o
+perf-y += sdt.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
 	$(call rule_mkdir)
tools/perf/tests/builtin-test.c +4 -0
index c23cbf7..4dd2d05 100644
@@ -218,6 +218,10 @@ static struct test generic_tests[] = {
 		.func = test__cpu_map_print,
 	},
 	{
+		.desc = "Test SDT event probing",
+		.func = test__sdt_event,
+	},
+	{
 		.func = NULL,
 	},
 };
tools/perf/tests/sdt.c new file +115 -0

115 lines not on this page · raw message

tools/perf/tests/tests.h +1 -0
index 52f9695..a0288f8 100644
@@ -88,6 +88,7 @@ int test__event_update(int subtest);
 int test__event_times(int subtest);
 int test__backward_ring_buffer(int subtest);
 int test__cpu_map_print(int subtest);
+int test__sdt_event(int subtest);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
#29 lore raw
In reply to Masami Hiramatsu

Em Tue, Jul 12, 2016 at 07:04:23PM +0900, Masami Hiramatsu escreveu:

Quoted 6 lines

Hi,

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

Here is the previous v13: https://lkml.org/lkml/2016/7/1/133

Ok, applied it and also one that you missed in this set, the one adding 'perf list sdt', that I rebased and tested,

Thanks,

- Arnaldo

Quoted 42 lines

This version includes patches which not merged yet. This also adds a bugfix;
- [1/10] Resend the bugfix patch which was sent 4th July.

          (https://lkml.org/lkml/2016/7/3/217)

Thank you,

---

Masami Hiramatsu (10):
[BUGFIX] perf-probe: Fix to show correct error message for $vars and $params perf probe: Accept %sdt and %cached event name
perf-probe: Make --list shows only available cached events
perf: probe-cache: Add for_each_probe_cache_entry() wrapper perf probe: Allow wildcard for cached events
perf probe: Search SDT/cached event from all probe caches
perf probe: Support @BUILDID or @FILE suffix for SDT events perf probe: Support a special SDT probe format
perf build: Add sdt feature detection
perf-test: Add a test case for SDT event

 tools/perf/Documentation/perf-probe.txt |   11 +
 tools/perf/Makefile.perf                |    3 
 tools/perf/builtin-probe.c              |    2 
 tools/perf/config/Makefile              |   10 +
 tools/perf/tests/Build                  |    1 
 tools/perf/tests/builtin-test.c         |    4 
 tools/perf/tests/make                   |    3 
 tools/perf/tests/sdt.c                  |  115 ++++++++++++
 tools/perf/tests/tests.h                |    1 
 tools/perf/util/build-id.c              |   76 ++++++++
 tools/perf/util/build-id.h              |    3 
 tools/perf/util/probe-event.c           |  309 +++++++++++++++++++++++++++----
 tools/perf/util/probe-event.h           |    1 
 tools/perf/util/probe-file.c            |   57 +++++-
 tools/perf/util/probe-file.h            |    5 +
 15 files changed, 542 insertions(+), 59 deletions(-)
 create mode 100644 tools/perf/tests/sdt.c

--
Masami Hiramatsu