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>
This commit is contained in:
parent
f6eb0518f3
commit
36a009fe07
|
@ -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]
|
||||
|
|
|
@ -1197,6 +1197,34 @@ err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = strchr(*arg, ':');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
if (!is_c_func_name(*arg))
|
||||
goto ng_name;
|
||||
pev->group = strdup(*arg);
|
||||
if (!pev->group)
|
||||
return -ENOMEM;
|
||||
*arg = ptr + 1;
|
||||
} else
|
||||
pev->group = NULL;
|
||||
if (!is_c_func_name(*arg)) {
|
||||
ng_name:
|
||||
semantic_error("%s is bad for event name -it must "
|
||||
"follow C symbol-naming rule.\n", *arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
pev->event = strdup(*arg);
|
||||
if (pev->event == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse probepoint definition. */
|
||||
static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
|
||||
{
|
||||
|
@ -1204,38 +1232,43 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
|
|||
char *ptr, *tmp;
|
||||
char c, nc = 0;
|
||||
bool file_spec = false;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* <Syntax>
|
||||
* perf probe [GRP:][EVENT=]SRC[:LN|;PTN]
|
||||
* perf probe [GRP:][EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
|
||||
* perf probe %[GRP:]SDT_EVENT
|
||||
*/
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
|
||||
if (arg[0] == '%') {
|
||||
pev->sdt = true;
|
||||
arg++;
|
||||
}
|
||||
|
||||
ptr = strpbrk(arg, ";=@+%");
|
||||
if (pev->sdt) {
|
||||
if (ptr) {
|
||||
semantic_error("%s must contain only an SDT event name.\n", arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = parse_perf_probe_event_name(&arg, pev);
|
||||
if (ret == 0) {
|
||||
if (asprintf(&pev->point.function, "%%%s", pev->event) < 0)
|
||||
ret = -errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ptr && *ptr == '=') { /* Event name */
|
||||
*ptr = '\0';
|
||||
tmp = ptr + 1;
|
||||
ptr = strchr(arg, ':');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
if (!is_c_func_name(arg))
|
||||
goto not_fname;
|
||||
pev->group = strdup(arg);
|
||||
if (!pev->group)
|
||||
return -ENOMEM;
|
||||
arg = ptr + 1;
|
||||
} else
|
||||
pev->group = NULL;
|
||||
if (!is_c_func_name(arg)) {
|
||||
not_fname:
|
||||
semantic_error("%s is bad for event name -it must "
|
||||
"follow C symbol-naming rule.\n", arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
pev->event = strdup(arg);
|
||||
if (pev->event == NULL)
|
||||
return -ENOMEM;
|
||||
ret = parse_perf_probe_event_name(&arg, pev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
arg = tmp;
|
||||
}
|
||||
|
||||
|
@ -2876,7 +2909,8 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
|
|||
|
||||
entry = probe_cache__find(cache, pev);
|
||||
if (!entry) {
|
||||
ret = 0;
|
||||
/* SDT must be in the cache */
|
||||
ret = pev->sdt ? -ENOENT : 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -2915,7 +2949,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (!pev->group) {
|
||||
if (!pev->group && !pev->sdt) {
|
||||
/* Set group name if not given */
|
||||
if (!pev->uprobes) {
|
||||
pev->group = strdup(PERFPROBE_GROUP);
|
||||
|
@ -2934,8 +2968,8 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
|
|||
|
||||
/* At first, we need to lookup cache entry */
|
||||
ret = find_probe_trace_events_from_cache(pev, tevs);
|
||||
if (ret > 0)
|
||||
return ret; /* Found in probe cache */
|
||||
if (ret > 0 || pev->sdt) /* SDT can be found only in the cache */
|
||||
return ret == 0 ? -ENOENT : ret; /* Found in probe cache */
|
||||
|
||||
if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
|
||||
ret = find_probe_trace_events_from_map(pev, tevs);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) &&
|
||||
|
|
Loading…
Reference in New Issue