lkml.org 
[lkml]   [2016]   [Jul]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 10/19] perf probe: Accept %sdt and %cached event name
    Date
    From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

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

    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.
    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]
    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:
    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 (ptr && *ptr == '=') { /* Event name */
    - *ptr = '\0';
    - tmp = ptr + 1;
    - ptr = strchr(arg, ':');
    + if (pev->sdt) {
    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);
    + semantic_error("%s must contain only an SDT event name.\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) {
    + if (asprintf(&pev->point.function, "%%%s", pev->event) < 0)
    + ret = -errno;
    + }
    + return ret;
    + }
    +
    + if (ptr && *ptr == '=') { /* Event name */
    + *ptr = '\0';
    + tmp = ptr + 1;
    + 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);
    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 {
    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 */
    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)
    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) &&
    --
    2.7.4
    \
     
     \ /
      Last update: 2016-07-14 05:01    [W:4.532 / U:1.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site