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    bool uprobes;
58    int nevents;
59    struct perf_probe_event events[MAX_PROBES];
60    struct strlist *dellist;
61    struct line_range line_range;
62    const char *target;
63    int max_probe_points;
64    struct strfilter *filter;
65} params;
66
67/* Parse an event definition. Note that any error must die. */
68static int parse_probe_event(const char *str)
69{
70    struct perf_probe_event *pev = &params.events[params.nevents];
71    int ret;
72
73    pr_debug("probe-definition(%d): %s\n", params.nevents, str);
74    if (++params.nevents == MAX_PROBES) {
75        pr_err("Too many probes (> %d) were specified.", MAX_PROBES);
76        return -1;
77    }
78
79    pev->uprobes = params.uprobes;
80
81    /* Parse a perf-probe command into event */
82    ret = parse_perf_probe_command(str, pev);
83    pr_debug("%d arguments\n", pev->nargs);
84
85    return ret;
86}
87
88static int set_target(const char *ptr)
89{
90    int found = 0;
91    const char *buf;
92
93    /*
94     * The first argument after options can be an absolute path
95     * to an executable / library or kernel module.
96     *
97     * TODO: Support relative path, and $PATH, $LD_LIBRARY_PATH,
98     * short module name.
99     */
100    if (!params.target && ptr && *ptr == '/') {
101        params.target = ptr;
102        found = 1;
103        buf = ptr + (strlen(ptr) - 3);
104
105        if (strcmp(buf, ".ko"))
106            params.uprobes = true;
107
108    }
109
110    return found;
111}
112
113static int parse_probe_event_argv(int argc, const char **argv)
114{
115    int i, len, ret, found_target;
116    char *buf;
117
118    found_target = set_target(argv[0]);
119    if (found_target && argc == 1)
120        return 0;
121
122    /* Bind up rest arguments */
123    len = 0;
124    for (i = 0; i < argc; i++) {
125        if (i == 0 && found_target)
126            continue;
127
128        len += strlen(argv[i]) + 1;
129    }
130    buf = zalloc(len + 1);
131    if (buf == NULL)
132        return -ENOMEM;
133    len = 0;
134    for (i = 0; i < argc; i++) {
135        if (i == 0 && found_target)
136            continue;
137
138        len += sprintf(&buf[len], "%s ", argv[i]);
139    }
140    params.mod_events = true;
141    ret = parse_probe_event(buf);
142    free(buf);
143    return ret;
144}
145
146static int opt_add_probe_event(const struct option *opt __used,
147                  const char *str, int unset __used)
148{
149    if (str) {
150        params.mod_events = true;
151        return parse_probe_event(str);
152    } else
153        return 0;
154}
155
156static int opt_del_probe_event(const struct option *opt __used,
157                   const char *str, int unset __used)
158{
159    if (str) {
160        params.mod_events = true;
161        if (!params.dellist)
162            params.dellist = strlist__new(true, NULL);
163        strlist__add(params.dellist, str);
164    }
165    return 0;
166}
167
168static int opt_set_target(const struct option *opt, const char *str,
169            int unset __used)
170{
171    int ret = -ENOENT;
172
173    if (str && !params.target) {
174        if (!strcmp(opt->long_name, "exec"))
175            params.uprobes = true;
176#ifdef DWARF_SUPPORT
177        else if (!strcmp(opt->long_name, "module"))
178            params.uprobes = false;
179#endif
180        else
181            return ret;
182
183        params.target = str;
184        ret = 0;
185    }
186
187    return ret;
188}
189
190#ifdef DWARF_SUPPORT
191static int opt_show_lines(const struct option *opt __used,
192              const char *str, int unset __used)
193{
194    int ret = 0;
195
196    if (!str)
197        return 0;
198
199    if (params.show_lines) {
200        pr_warning("Warning: more than one --line options are"
201               " detected. Only the first one is valid.\n");
202        return 0;
203    }
204
205    params.show_lines = true;
206    ret = parse_line_range_desc(str, &params.line_range);
207    INIT_LIST_HEAD(&params.line_range.line_list);
208
209    return ret;
210}
211
212static int opt_show_vars(const struct option *opt __used,
213             const char *str, int unset __used)
214{
215    struct perf_probe_event *pev = &params.events[params.nevents];
216    int ret;
217
218    if (!str)
219        return 0;
220
221    ret = parse_probe_event(str);
222    if (!ret && pev->nargs != 0) {
223        pr_err(" Error: '--vars' doesn't accept arguments.\n");
224        return -EINVAL;
225    }
226    params.show_vars = true;
227
228    return ret;
229}
230#endif
231
232static int opt_set_filter(const struct option *opt __used,
233              const char *str, int unset __used)
234{
235    const char *err;
236
237    if (str) {
238        pr_debug2("Set filter: %s\n", str);
239        if (params.filter)
240            strfilter__delete(params.filter);
241        params.filter = strfilter__new(str, &err);
242        if (!params.filter) {
243            pr_err("Filter parse error at %td.\n", err - str + 1);
244            pr_err("Source: \"%s\"\n", str);
245            pr_err(" %*c\n", (int)(err - str + 1), '^');
246            return -EINVAL;
247        }
248    }
249
250    return 0;
251}
252
253static const char * const probe_usage[] = {
254    "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
255    "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
256    "perf probe [<options>] --del '[GROUP:]EVENT' ...",
257    "perf probe --list",
258#ifdef DWARF_SUPPORT
259    "perf probe [<options>] --line 'LINEDESC'",
260    "perf probe [<options>] --vars 'PROBEPOINT'",
261#endif
262    NULL
263};
264
265static const struct option options[] = {
266    OPT_INCR('v', "verbose", &verbose,
267            "be more verbose (show parsed arguments, etc)"),
268    OPT_BOOLEAN('l', "list", &params.list_events,
269            "list up current probe events"),
270    OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
271        opt_del_probe_event),
272    OPT_CALLBACK('a', "add", NULL,
273#ifdef DWARF_SUPPORT
274        "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
275        " [[NAME=]ARG ...]",
276#else
277        "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
278#endif
279        "probe point definition, where\n"
280        "\t\tGROUP:\tGroup name (optional)\n"
281        "\t\tEVENT:\tEvent name\n"
282        "\t\tFUNC:\tFunction name\n"
283        "\t\tOFF:\tOffset from function entry (in byte)\n"
284        "\t\t%return:\tPut the probe at function return\n"
285#ifdef DWARF_SUPPORT
286        "\t\tSRC:\tSource code path\n"
287        "\t\tRL:\tRelative line number from function entry.\n"
288        "\t\tAL:\tAbsolute line number in file.\n"
289        "\t\tPT:\tLazy expression of line code.\n"
290        "\t\tARG:\tProbe argument (local variable name or\n"
291        "\t\t\tkprobe-tracer argument format.)\n",
292#else
293        "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
294#endif
295        opt_add_probe_event),
296    OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
297            " with existing name"),
298#ifdef DWARF_SUPPORT
299    OPT_CALLBACK('L', "line", NULL,
300             "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
301             "Show source code lines.", opt_show_lines),
302    OPT_CALLBACK('V', "vars", NULL,
303             "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
304             "Show accessible variables on PROBEDEF", opt_show_vars),
305    OPT_BOOLEAN('\0', "externs", &params.show_ext_vars,
306            "Show external variables too (with --vars only)"),
307    OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
308           "file", "vmlinux pathname"),
309    OPT_STRING('s', "source", &symbol_conf.source_prefix,
310           "directory", "path to kernel source"),
311    OPT_CALLBACK('m', "module", NULL, "modname|path",
312        "target module name (for online) or path (for offline)",
313        opt_set_target),
314#endif
315    OPT__DRY_RUN(&probe_event_dry_run),
316    OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
317         "Set how many probe points can be found for a probe."),
318    OPT_BOOLEAN('F', "funcs", &params.show_funcs,
319            "Show potential probe-able functions."),
320    OPT_CALLBACK('\0', "filter", NULL,
321             "[!]FILTER", "Set a filter (with --vars/funcs only)\n"
322             "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
323             "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
324             opt_set_filter),
325    OPT_CALLBACK('x', "exec", NULL, "executable|path",
326            "target executable name or path", opt_set_target),
327    OPT_END()
328};
329
330int cmd_probe(int argc, const char **argv, const char *prefix __used)
331{
332    int ret;
333
334    argc = parse_options(argc, argv, options, probe_usage,
335                 PARSE_OPT_STOP_AT_NON_OPTION);
336    if (argc > 0) {
337        if (strcmp(argv[0], "-") == 0) {
338            pr_warning(" Error: '-' is not supported.\n");
339            usage_with_options(probe_usage, options);
340        }
341        ret = parse_probe_event_argv(argc, argv);
342        if (ret < 0) {
343            pr_err(" Error: Parse Error. (%d)\n", ret);
344            return ret;
345        }
346    }
347
348    if (params.max_probe_points == 0)
349        params.max_probe_points = MAX_PROBES;
350
351    if ((!params.nevents && !params.dellist && !params.list_events &&
352         !params.show_lines && !params.show_funcs))
353        usage_with_options(probe_usage, options);
354
355    /*
356     * Only consider the user's kernel image path if given.
357     */
358    symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
359
360    if (params.list_events) {
361        if (params.mod_events) {
362            pr_err(" Error: Don't use --list with --add/--del.\n");
363            usage_with_options(probe_usage, options);
364        }
365        if (params.show_lines) {
366            pr_err(" Error: Don't use --list with --line.\n");
367            usage_with_options(probe_usage, options);
368        }
369        if (params.show_vars) {
370            pr_err(" Error: Don't use --list with --vars.\n");
371            usage_with_options(probe_usage, options);
372        }
373        if (params.show_funcs) {
374            pr_err(" Error: Don't use --list with --funcs.\n");
375            usage_with_options(probe_usage, options);
376        }
377        if (params.uprobes) {
378            pr_warning(" Error: Don't use --list with --exec.\n");
379            usage_with_options(probe_usage, options);
380        }
381        ret = show_perf_probe_events();
382        if (ret < 0)
383            pr_err(" Error: Failed to show event list. (%d)\n",
384                   ret);
385        return ret;
386    }
387    if (params.show_funcs) {
388        if (params.nevents != 0 || params.dellist) {
389            pr_err(" Error: Don't use --funcs with"
390                   " --add/--del.\n");
391            usage_with_options(probe_usage, options);
392        }
393        if (params.show_lines) {
394            pr_err(" Error: Don't use --funcs with --line.\n");
395            usage_with_options(probe_usage, options);
396        }
397        if (params.show_vars) {
398            pr_err(" Error: Don't use --funcs with --vars.\n");
399            usage_with_options(probe_usage, options);
400        }
401        if (!params.filter)
402            params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
403                               NULL);
404        ret = show_available_funcs(params.target, params.filter,
405                    params.uprobes);
406        strfilter__delete(params.filter);
407        if (ret < 0)
408            pr_err(" Error: Failed to show functions."
409                   " (%d)\n", ret);
410        return ret;
411    }
412
413#ifdef DWARF_SUPPORT
414    if (params.show_lines && !params.uprobes) {
415        if (params.mod_events) {
416            pr_err(" Error: Don't use --line with"
417                   " --add/--del.\n");
418            usage_with_options(probe_usage, options);
419        }
420        if (params.show_vars) {
421            pr_err(" Error: Don't use --line with --vars.\n");
422            usage_with_options(probe_usage, options);
423        }
424
425        ret = show_line_range(&params.line_range, params.target);
426        if (ret < 0)
427            pr_err(" Error: Failed to show lines. (%d)\n", ret);
428        return ret;
429    }
430    if (params.show_vars) {
431        if (params.mod_events) {
432            pr_err(" Error: Don't use --vars with"
433                   " --add/--del.\n");
434            usage_with_options(probe_usage, options);
435        }
436        if (!params.filter)
437            params.filter = strfilter__new(DEFAULT_VAR_FILTER,
438                               NULL);
439
440        ret = show_available_vars(params.events, params.nevents,
441                      params.max_probe_points,
442                      params.target,
443                      params.filter,
444                      params.show_ext_vars);
445        strfilter__delete(params.filter);
446        if (ret < 0)
447            pr_err(" Error: Failed to show vars. (%d)\n", ret);
448        return ret;
449    }
450#endif
451
452    if (params.dellist) {
453        ret = del_perf_probe_events(params.dellist);
454        strlist__delete(params.dellist);
455        if (ret < 0) {
456            pr_err(" Error: Failed to delete events. (%d)\n", ret);
457            return ret;
458        }
459    }
460
461    if (params.nevents) {
462        ret = add_perf_probe_events(params.events, params.nevents,
463                        params.max_probe_points,
464                        params.target,
465                        params.force_add);
466        if (ret < 0) {
467            pr_err(" Error: Failed to add events. (%d)\n", ret);
468            return ret;
469        }
470    }
471    return 0;
472}
473

Archive Download this file



interactive