diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2016-07-12 06:04:43 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-07-13 22:09:05 -0400 |
commit | 36a009fe07bdecd201335f982babb8af34b603e2 (patch) | |
tree | 5fbbcbbe1835c309924aa8be8f05580ea3814eef | |
parent | f6eb0518f325ef0d6557fbef5c7ebe48a81e74db (diff) |
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
----
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/146831788372.17065.3645054540325909346.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/Documentation/perf-probe.txt | 9 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 82 | ||||
-rw-r--r-- | tools/perf/util/probe-event.h | 1 | ||||
-rw-r--r-- | tools/perf/util/probe-file.c | 9 |
4 files changed, 76 insertions, 25 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 7a258e953252..39e387042098 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt | |||
@@ -151,6 +151,8 @@ Probe points are defined by following syntax. | |||
151 | 3) Define event based on source file with lazy pattern | 151 | 3) Define event based on source file with lazy pattern |
152 | [[GROUP:]EVENT=]SRC;PTN [ARG ...] | 152 | [[GROUP:]EVENT=]SRC;PTN [ARG ...] |
153 | 153 | ||
154 | 4) Pre-defined SDT events or cached event with name | ||
155 | %[PROVIDER:]SDTEVENT | ||
154 | 156 | ||
155 | '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. | 157 | '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. |
156 | 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 | 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. | |||
158 | '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. | 160 | '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. |
159 | 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. | 161 | 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. |
160 | 'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT). | 162 | 'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT). |
163 | '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. | ||
164 | 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. | ||
165 | |||
166 | For details of the SDT, see below. | ||
167 | https://sourceware.org/gdb/onlinedocs/gdb/Static-Probe-Points.html | ||
161 | 168 | ||
162 | PROBE ARGUMENT | 169 | PROBE ARGUMENT |
163 | -------------- | 170 | -------------- |
@@ -237,4 +244,4 @@ Add probes at malloc() function on libc | |||
237 | 244 | ||
238 | SEE ALSO | 245 | SEE ALSO |
239 | -------- | 246 | -------- |
240 | linkperf:perf-trace[1], linkperf:perf-record[1] | 247 | linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1] |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index fef9768df429..85f25d41cf8d 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -1197,6 +1197,34 @@ err: | |||
1197 | return err; | 1197 | return err; |
1198 | } | 1198 | } |
1199 | 1199 | ||
1200 | static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev) | ||
1201 | { | ||
1202 | char *ptr; | ||
1203 | |||
1204 | ptr = strchr(*arg, ':'); | ||
1205 | if (ptr) { | ||
1206 | *ptr = '\0'; | ||
1207 | if (!is_c_func_name(*arg)) | ||
1208 | goto ng_name; | ||
1209 | pev->group = strdup(*arg); | ||
1210 | if (!pev->group) | ||
1211 | return -ENOMEM; | ||
1212 | *arg = ptr + 1; | ||
1213 | } else | ||
1214 | pev->group = NULL; | ||
1215 | if (!is_c_func_name(*arg)) { | ||
1216 | ng_name: | ||
1217 | semantic_error("%s is bad for event name -it must " | ||
1218 | "follow C symbol-naming rule.\n", *arg); | ||
1219 | return -EINVAL; | ||
1220 | } | ||
1221 | pev->event = strdup(*arg); | ||
1222 | if (pev->event == NULL) | ||
1223 | return -ENOMEM; | ||
1224 | |||
1225 | return 0; | ||
1226 | } | ||
1227 | |||
1200 | /* Parse probepoint definition. */ | 1228 | /* Parse probepoint definition. */ |
1201 | static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) | 1229 | static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) |
1202 | { | 1230 | { |
@@ -1204,38 +1232,43 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) | |||
1204 | char *ptr, *tmp; | 1232 | char *ptr, *tmp; |
1205 | char c, nc = 0; | 1233 | char c, nc = 0; |
1206 | bool file_spec = false; | 1234 | bool file_spec = false; |
1235 | int ret; | ||
1236 | |||
1207 | /* | 1237 | /* |
1208 | * <Syntax> | 1238 | * <Syntax> |
1209 | * perf probe [GRP:][EVENT=]SRC[:LN|;PTN] | 1239 | * perf probe [GRP:][EVENT=]SRC[:LN|;PTN] |
1210 | * perf probe [GRP:][EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] | 1240 | * perf probe [GRP:][EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] |
1241 | * perf probe %[GRP:]SDT_EVENT | ||
1211 | */ | 1242 | */ |
1212 | if (!arg) | 1243 | if (!arg) |
1213 | return -EINVAL; | 1244 | return -EINVAL; |
1214 | 1245 | ||
1246 | if (arg[0] == '%') { | ||
1247 | pev->sdt = true; | ||
1248 | arg++; | ||
1249 | } | ||
1250 | |||
1215 | ptr = strpbrk(arg, ";=@+%"); | 1251 | ptr = strpbrk(arg, ";=@+%"); |
1216 | if (ptr && *ptr == '=') { /* Event name */ | 1252 | if (pev->sdt) { |
1217 | *ptr = '\0'; | ||
1218 | tmp = ptr + 1; | ||
1219 | ptr = strchr(arg, ':'); | ||
1220 | if (ptr) { | 1253 | if (ptr) { |
1221 | *ptr = '\0'; | 1254 | semantic_error("%s must contain only an SDT event name.\n", arg); |
1222 | if (!is_c_func_name(arg)) | ||
1223 | goto not_fname; | ||
1224 | pev->group = strdup(arg); | ||
1225 | if (!pev->group) | ||
1226 | return -ENOMEM; | ||
1227 | arg = ptr + 1; | ||
1228 | } else | ||
1229 | pev->group = NULL; | ||
1230 | if (!is_c_func_name(arg)) { | ||
1231 | not_fname: | ||
1232 | semantic_error("%s is bad for event name -it must " | ||
1233 | "follow C symbol-naming rule.\n", arg); | ||
1234 | return -EINVAL; | 1255 | return -EINVAL; |
1235 | } | 1256 | } |
1236 | pev->event = strdup(arg); | 1257 | ret = parse_perf_probe_event_name(&arg, pev); |
1237 | if (pev->event == NULL) | 1258 | if (ret == 0) { |
1238 | return -ENOMEM; | 1259 | if (asprintf(&pev->point.function, "%%%s", pev->event) < 0) |
1260 | ret = -errno; | ||
1261 | } | ||
1262 | return ret; | ||
1263 | } | ||
1264 | |||
1265 | if (ptr && *ptr == '=') { /* Event name */ | ||
1266 | *ptr = '\0'; | ||
1267 | tmp = ptr + 1; | ||
1268 | ret = parse_perf_probe_event_name(&arg, pev); | ||
1269 | if (ret < 0) | ||
1270 | return ret; | ||
1271 | |||
1239 | arg = tmp; | 1272 | arg = tmp; |
1240 | } | 1273 | } |
1241 | 1274 | ||
@@ -2876,7 +2909,8 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev, | |||
2876 | 2909 | ||
2877 | entry = probe_cache__find(cache, pev); | 2910 | entry = probe_cache__find(cache, pev); |
2878 | if (!entry) { | 2911 | if (!entry) { |
2879 | ret = 0; | 2912 | /* SDT must be in the cache */ |
2913 | ret = pev->sdt ? -ENOENT : 0; | ||
2880 | goto out; | 2914 | goto out; |
2881 | } | 2915 | } |
2882 | 2916 | ||
@@ -2915,7 +2949,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
2915 | { | 2949 | { |
2916 | int ret; | 2950 | int ret; |
2917 | 2951 | ||
2918 | if (!pev->group) { | 2952 | if (!pev->group && !pev->sdt) { |
2919 | /* Set group name if not given */ | 2953 | /* Set group name if not given */ |
2920 | if (!pev->uprobes) { | 2954 | if (!pev->uprobes) { |
2921 | pev->group = strdup(PERFPROBE_GROUP); | 2955 | pev->group = strdup(PERFPROBE_GROUP); |
@@ -2934,8 +2968,8 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
2934 | 2968 | ||
2935 | /* At first, we need to lookup cache entry */ | 2969 | /* At first, we need to lookup cache entry */ |
2936 | ret = find_probe_trace_events_from_cache(pev, tevs); | 2970 | ret = find_probe_trace_events_from_cache(pev, tevs); |
2937 | if (ret > 0) | 2971 | if (ret > 0 || pev->sdt) /* SDT can be found only in the cache */ |
2938 | return ret; /* Found in probe cache */ | 2972 | return ret == 0 ? -ENOENT : ret; /* Found in probe cache */ |
2939 | 2973 | ||
2940 | if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { | 2974 | if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { |
2941 | ret = find_probe_trace_events_from_map(pev, tevs); | 2975 | ret = find_probe_trace_events_from_map(pev, tevs); |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 432b690d3f17..e18ea9fe6385 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -85,6 +85,7 @@ struct perf_probe_event { | |||
85 | char *group; /* Group name */ | 85 | char *group; /* Group name */ |
86 | struct perf_probe_point point; /* Probe point */ | 86 | struct perf_probe_point point; /* Probe point */ |
87 | int nargs; /* Number of arguments */ | 87 | int nargs; /* Number of arguments */ |
88 | bool sdt; /* SDT/cached event flag */ | ||
88 | bool uprobes; /* Uprobe event flag */ | 89 | bool uprobes; /* Uprobe event flag */ |
89 | char *target; /* Target binary */ | 90 | char *target; /* Target binary */ |
90 | struct perf_probe_arg *args; /* Arguments */ | 91 | struct perf_probe_arg *args; /* Arguments */ |
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c index e705a742ee1e..fc16b172579f 100644 --- a/tools/perf/util/probe-file.c +++ b/tools/perf/util/probe-file.c | |||
@@ -547,6 +547,15 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev) | |||
547 | return NULL; | 547 | return NULL; |
548 | 548 | ||
549 | list_for_each_entry(entry, &pcache->entries, node) { | 549 | list_for_each_entry(entry, &pcache->entries, node) { |
550 | if (pev->sdt) { | ||
551 | if (entry->pev.event && | ||
552 | streql(entry->pev.event, pev->event) && | ||
553 | (!pev->group || | ||
554 | streql(entry->pev.group, pev->group))) | ||
555 | goto found; | ||
556 | |||
557 | continue; | ||
558 | } | ||
550 | /* Hit if same event name or same command-string */ | 559 | /* Hit if same event name or same command-string */ |
551 | if ((pev->event && | 560 | if ((pev->event && |
552 | (streql(entry->pev.group, pev->group) && | 561 | (streql(entry->pev.group, pev->group) && |