Root/tools/perf/builtin-probe.c

1/*
2 * builtin-probe.c
3 *
4 * Builtin probe command: Set up probe events by C expression
5 *
6 * Written by Masami Hiramatsu <mhiramat@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 */
23#include <sys/utsname.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include <errno.h>
28#include <stdio.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include "perf.h"
34#include "builtin.h"
35#include "util/util.h"
36#include "util/strlist.h"
37#include "util/strfilter.h"
38#include "util/symbol.h"
39#include "util/debug.h"
40#include "util/debugfs.h"
41#include "util/parse-options.h"
42#include "util/probe-finder.h"
43#include "util/probe-event.h"
44
45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
46#define DEFAULT_FUNC_FILTER "!_*"
47
48/* Session management structure */
49static struct {
50    bool list_events;
51    bool force_add;
52    bool show_lines;
53    bool show_vars;
54    bool show_ext_vars;
55    bool show_funcs;
56    bool mod_events;
57    int nevents;
58    struct perf_probe_event events[MAX_PROBES];
59    struct strlist *dellist;
60    struct line_range line_range;
61    const char *target;
62    int max_probe_points;
63    struct strfilter *filter;
64} params;
65
66/* Parse an event definition. Note that any error must die. */
67static int parse_probe_event(const char *str)
68{
69    struct perf_probe_event *pev = &params.events[params.nevents];
70    int ret;
71
72    pr_debug("probe-definition(%d): %s\n", params.nevents, str);
73    if (++params.nevents == MAX_PROBES) {
74        pr_err("Too many probes (> %d) were specified.", MAX_PROBES);
75        return -1;
76    }
77
78    /* Parse a perf-probe command into event */
79    ret = parse_perf_probe_command(str, pev);
80    pr_debug("%d arguments\n", pev->nargs);
81
82    return ret;
83}
84
85static int parse_probe_event_argv(int argc, const char **argv)
86{
87    int i, len, ret;
88    char *buf;
89
90    /* Bind up rest arguments */
91    len = 0;
92    for (i = 0; i < argc; i++)
93        len += strlen(argv[i]) + 1;
94    buf = zalloc(len + 1);
95    if (buf == NULL)
96        return -ENOMEM;
97    len = 0;
98    for (i = 0; i < argc; i++)
99        len += sprintf(&buf[len], "%s ", argv[i]);
100    params.mod_events = true;
101    ret = parse_probe_event(buf);
102    free(buf);
103    return ret;
104}
105
106static int opt_add_probe_event(const struct option *opt __used,
107                  const char *str, int unset __used)
108{
109    if (str) {
110        params.mod_events = true;
111        return parse_probe_event(str);
112    } else
113        return 0;
114}
115
116static int opt_del_probe_event(const struct option *opt __used,
117                   const char *str, int unset __used)
118{
119    if (str) {
120        params.mod_events = true;
121        if (!params.dellist)
122            params.dellist = strlist__new(true, NULL);
123        strlist__add(params.dellist, str);
124    }
125    return 0;
126}
127
128#ifdef DWARF_SUPPORT
129static int opt_show_lines(const struct option *opt __used,
130              const char *str, int unset __used)
131{
132    int ret = 0;
133
134    if (!str)
135        return 0;
136
137    if (params.show_lines) {
138        pr_warning("Warning: more than one --line options are"
139               " detected. Only the first one is valid.\n");
140        return 0;
141    }
142
143    params.show_lines = true;
144    ret = parse_line_range_desc(str, &params.line_range);
145    INIT_LIST_HEAD(&params.line_range.line_list);
146
147    return ret;
148}
149
150static int opt_show_vars(const struct option *opt __used,
151             const char *str, int unset __used)
152{
153    struct perf_probe_event *pev = &params.events[params.nevents];
154    int ret;
155
156    if (!str)
157        return 0;
158
159    ret = parse_probe_event(str);
160    if (!ret && pev->nargs != 0) {
161        pr_err(" Error: '--vars' doesn't accept arguments.\n");
162        return -EINVAL;
163    }
164    params.show_vars = true;
165
166    return ret;
167}
168#endif
169
170static int opt_set_filter(const struct option *opt __used,
171              const char *str, int unset __used)
172{
173    const char *err;
174
175    if (str) {
176        pr_debug2("Set filter: %s\n", str);
177        if (params.filter)
178            strfilter__delete(params.filter);
179        params.filter = strfilter__new(str, &err);
180        if (!params.filter) {
181            pr_err("Filter parse error at %td.\n", err - str + 1);
182            pr_err("Source: \"%s\"\n", str);
183            pr_err(" %*c\n", (int)(err - str + 1), '^');
184            return -EINVAL;
185        }
186    }
187
188    return 0;
189}
190
191static const char * const probe_usage[] = {
192    "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
193    "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
194    "perf probe [<options>] --del '[GROUP:]EVENT' ...",
195    "perf probe --list",
196#ifdef DWARF_SUPPORT
197    "perf probe [<options>] --line 'LINEDESC'",
198    "perf probe [<options>] --vars 'PROBEPOINT'",
199#endif
200    NULL
201};
202
203static const struct option options[] = {
204    OPT_INCR('v', "verbose", &verbose,
205            "be more verbose (show parsed arguments, etc)"),
206    OPT_BOOLEAN('l', "list", &params.list_events,
207            "list up current probe events"),
208    OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
209        opt_del_probe_event),
210    OPT_CALLBACK('a', "add", NULL,
211#ifdef DWARF_SUPPORT
212        "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
213        " [[NAME=]ARG ...]",
214#else
215        "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
216#endif
217        "probe point definition, where\n"
218        "\t\tGROUP:\tGroup name (optional)\n"
219        "\t\tEVENT:\tEvent name\n"
220        "\t\tFUNC:\tFunction name\n"
221        "\t\tOFF:\tOffset from function entry (in byte)\n"
222        "\t\t%return:\tPut the probe at function return\n"
223#ifdef DWARF_SUPPORT
224        "\t\tSRC:\tSource code path\n"
225        "\t\tRL:\tRelative line number from function entry.\n"
226        "\t\tAL:\tAbsolute line number in file.\n"
227        "\t\tPT:\tLazy expression of line code.\n"
228        "\t\tARG:\tProbe argument (local variable name or\n"
229        "\t\t\tkprobe-tracer argument format.)\n",
230#else
231        "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
232#endif
233        opt_add_probe_event),
234    OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
235            " with existing name"),
236#ifdef DWARF_SUPPORT
237    OPT_CALLBACK('L', "line", NULL,
238             "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
239             "Show source code lines.", opt_show_lines),
240    OPT_CALLBACK('V', "vars", NULL,
241             "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
242             "Show accessible variables on PROBEDEF", opt_show_vars),
243    OPT_BOOLEAN('\0', "externs", &params.show_ext_vars,
244            "Show external variables too (with --vars only)"),
245    OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
246           "file", "vmlinux pathname"),
247    OPT_STRING('s', "source", &symbol_conf.source_prefix,
248           "directory", "path to kernel source"),
249    OPT_STRING('m', "module", &params.target,
250           "modname|path",
251           "target module name (for online) or path (for offline)"),
252#endif
253    OPT__DRY_RUN(&probe_event_dry_run),
254    OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
255         "Set how many probe points can be found for a probe."),
256    OPT_BOOLEAN('F', "funcs", &params.show_funcs,
257            "Show potential probe-able functions."),
258    OPT_CALLBACK('\0', "filter", NULL,
259             "[!]FILTER", "Set a filter (with --vars/funcs only)\n"
260             "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
261             "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
262             opt_set_filter),
263    OPT_END()
264};
265
266int cmd_probe(int argc, const char **argv, const char *prefix __used)
267{
268    int ret;
269
270    argc = parse_options(argc, argv, options, probe_usage,
271                 PARSE_OPT_STOP_AT_NON_OPTION);
272    if (argc > 0) {
273        if (strcmp(argv[0], "-") == 0) {
274            pr_warning(" Error: '-' is not supported.\n");
275            usage_with_options(probe_usage, options);
276        }
277        ret = parse_probe_event_argv(argc, argv);
278        if (ret < 0) {
279            pr_err(" Error: Parse Error. (%d)\n", ret);
280            return ret;
281        }
282    }
283
284    if (params.max_probe_points == 0)
285        params.max_probe_points = MAX_PROBES;
286
287    if ((!params.nevents && !params.dellist && !params.list_events &&
288         !params.show_lines && !params.show_funcs))
289        usage_with_options(probe_usage, options);
290
291    /*
292     * Only consider the user's kernel image path if given.
293     */
294    symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
295
296    if (params.list_events) {
297        if (params.mod_events) {
298            pr_err(" Error: Don't use --list with --add/--del.\n");
299            usage_with_options(probe_usage, options);
300        }
301        if (params.show_lines) {
302            pr_err(" Error: Don't use --list with --line.\n");
303            usage_with_options(probe_usage, options);
304        }
305        if (params.show_vars) {
306            pr_err(" Error: Don't use --list with --vars.\n");
307            usage_with_options(probe_usage, options);
308        }
309        if (params.show_funcs) {
310            pr_err(" Error: Don't use --list with --funcs.\n");
311            usage_with_options(probe_usage, options);
312        }
313        ret = show_perf_probe_events();
314        if (ret < 0)
315            pr_err(" Error: Failed to show event list. (%d)\n",
316                   ret);
317        return ret;
318    }
319    if (params.show_funcs) {
320        if (params.nevents != 0 || params.dellist) {
321            pr_err(" Error: Don't use --funcs with"
322                   " --add/--del.\n");
323            usage_with_options(probe_usage, options);
324        }
325        if (params.show_lines) {
326            pr_err(" Error: Don't use --funcs with --line.\n");
327            usage_with_options(probe_usage, options);
328        }
329        if (params.show_vars) {
330            pr_err(" Error: Don't use --funcs with --vars.\n");
331            usage_with_options(probe_usage, options);
332        }
333        if (!params.filter)
334            params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
335                               NULL);
336        ret = show_available_funcs(params.target,
337                       params.filter);
338        strfilter__delete(params.filter);
339        if (ret < 0)
340            pr_err(" Error: Failed to show functions."
341                   " (%d)\n", ret);
342        return ret;
343    }
344
345#ifdef DWARF_SUPPORT
346    if (params.show_lines) {
347        if (params.mod_events) {
348            pr_err(" Error: Don't use --line with"
349                   " --add/--del.\n");
350            usage_with_options(probe_usage, options);
351        }
352        if (params.show_vars) {
353            pr_err(" Error: Don't use --line with --vars.\n");
354            usage_with_options(probe_usage, options);
355        }
356
357        ret = show_line_range(&params.line_range, params.target);
358        if (ret < 0)
359            pr_err(" Error: Failed to show lines. (%d)\n", ret);
360        return ret;
361    }
362    if (params.show_vars) {
363        if (params.mod_events) {
364            pr_err(" Error: Don't use --vars with"
365                   " --add/--del.\n");
366            usage_with_options(probe_usage, options);
367        }
368        if (!params.filter)
369            params.filter = strfilter__new(DEFAULT_VAR_FILTER,
370                               NULL);
371
372        ret = show_available_vars(params.events, params.nevents,
373                      params.max_probe_points,
374                      params.target,
375                      params.filter,
376                      params.show_ext_vars);
377        strfilter__delete(params.filter);
378        if (ret < 0)
379            pr_err(" Error: Failed to show vars. (%d)\n", ret);
380        return ret;
381    }
382#endif
383
384    if (params.dellist) {
385        ret = del_perf_probe_events(params.dellist);
386        strlist__delete(params.dellist);
387        if (ret < 0) {
388            pr_err(" Error: Failed to delete events. (%d)\n", ret);
389            return ret;
390        }
391    }
392
393    if (params.nevents) {
394        ret = add_perf_probe_events(params.events, params.nevents,
395                        params.max_probe_points,
396                        params.target,
397                        params.force_add);
398        if (ret < 0) {
399            pr_err(" Error: Failed to add events. (%d)\n", ret);
400            return ret;
401        }
402    }
403    return 0;
404}
405

Archive Download this file



interactive