[RFC PATCH perf/core v3 17/17] perf record: Support recording SDT events

From: Masami Hiramatsu
Date: Sat Aug 15 2015 - 07:48:55 EST


perf record -e "sdt_PROVIDER:EVENT" is available as same as
other tracepoint events.
In this version, the wildcard and @filename or build-id are not
supported yet.

Note that this doesn't clear (unregister) probe event after recorded
events, since that can skip to register same event next time and
anyway we can not unregister it if someone use the event via ftrace.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@xxxxxxxxxxx>
---
tools/perf/builtin-probe.c | 3 --
tools/perf/util/parse-events.c | 59 +++++++++++++++++++++++++++++++++++++++-
tools/perf/util/probe-event.c | 18 ++++++++----
tools/perf/util/probe-event.h | 1 +
4 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 5d0c246..a94e54f 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -441,9 +441,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
verbose = -1;
}

- if (probe_conf.max_probes == 0)
- probe_conf.max_probes = MAX_PROBES;
-
/*
* Only consider the user's kernel image path if given.
*/
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a19f7f9..36d88f0 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -473,8 +473,8 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
return ret;
}

-int parse_events_add_tracepoint(struct list_head *list, int *idx,
- char *sys, char *event)
+static int __parse_events_add_tracepoint(struct list_head *list, int *idx,
+ char *sys, char *event)
{
if (strpbrk(sys, "*?"))
return add_tracepoint_multi_sys(list, idx, sys, event);
@@ -482,6 +482,61 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
return add_tracepoint_event(list, idx, sys, event);
}

+static int activate_sdt_events(char *sys, char *event)
+{
+ struct probe_cache *cache;
+ struct probe_cache_entry *entry;
+ struct strlist *bidlist;
+ struct str_node *nd;
+ struct perf_probe_event pev;
+ char *path = NULL;
+ int ret;
+
+ ret = build_id_cache__list_all(&bidlist, true);
+ if (ret < 0) {
+ pr_debug("Failed to get buildids: %d\n", ret);
+ return ret;
+ }
+
+ strlist__for_each(nd, bidlist) {
+ cache = probe_cache__new(nd->s);
+ if (!cache)
+ continue;
+ entry = probe_cache__find_by_name(cache, sys, event);
+ probe_cache__delete(cache);
+ if (entry) {
+ path = build_id_cache__origname(nd->s);
+ break;
+ }
+ }
+ if (!path) {
+ pr_debug("Failed to find %s:%s in probe cache\n", sys, event);
+ return -ENOENT;
+ }
+
+ memset(&pev, 0, sizeof(pev));
+ pev.point.function = event;
+ pev.event = event;
+ pev.group = sys;
+ pev.sdt = true;
+ pev.uprobes = true;
+ pev.target = path;
+ probe_conf.internal_call = true;
+ ret = add_perf_probe_events(&pev, 1);
+ free(path);
+ return ret;
+}
+
+int parse_events_add_tracepoint(struct list_head *list, int *idx,
+ char *sys, char *event)
+{
+ int ret = __parse_events_add_tracepoint(list, idx, sys, event);
+ /* Retry with activating SDTs */
+ if (ret < 0 && activate_sdt_events(sys, event) > 0)
+ return __parse_events_add_tracepoint(list, idx, sys, event);
+ return ret;
+}
+
static int
parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
{
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index d2fa266..ecb953c 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -52,7 +52,9 @@
#define PERFPROBE_GROUP "probe"

bool probe_event_dry_run; /* Dry run flag */
-struct probe_conf probe_conf;
+struct probe_conf probe_conf = {
+ .max_probes = MAX_PROBES,
+};

#define semantic_error(msg ...) pr_err("Semantic error :" msg)

@@ -2404,7 +2406,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
}

ret = 0;
- pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
+ if (!probe_conf.internal_call)
+ pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
for (i = 0; i < ntevs; i++) {
tev = &tevs[i];
/* Skip if the symbol is out of .text or blacklisted */
@@ -2422,8 +2425,9 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
break;

/* We use tev's name for showing new events */
- show_perf_probe_event(tev->group, tev->event, pev,
- tev->point.module, false);
+ if (!probe_conf.internal_call)
+ show_perf_probe_event(tev->group, tev->event, pev,
+ tev->point.module, false);
/* Save the last valid name */
event = tev->event;
group = tev->group;
@@ -2452,8 +2456,10 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
}
}
/* Show how to use the event. */
- pr_info("\nYou can now use it in all perf tools, such as:\n\n");
- pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event);
+ if (!probe_conf.internal_call) {
+ pr_info("\nYou can now use it in all perf tools, such as:\n\n");
+ pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event);
+ }
}

strlist__delete(namelist);
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 2cd60e6..8cab4a6 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -13,6 +13,7 @@ struct probe_conf {
bool force_add;
bool no_inlines;
bool cache;
+ bool internal_call; /* Internal use */
int max_probes;
};
extern struct probe_conf probe_conf;

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/