aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-event.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2016-07-12 06:04:43 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-07-13 22:09:05 -0400
commit36a009fe07bdecd201335f982babb8af34b603e2 (patch)
tree5fbbcbbe1835c309924aa8be8f05580ea3814eef /tools/perf/util/probe-event.c
parentf6eb0518f325ef0d6557fbef5c7ebe48a81e74db (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>
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r--tools/perf/util/probe-event.c82
1 files changed, 58 insertions, 24 deletions
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
1200static 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)) {
1216ng_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. */
1201static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 1229static 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)) {
1231not_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);