linux/tools/perf/builtin-probe.c
<<
>>
Prefs
   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 <subcmd/parse-options.h>
  41#include "util/probe-finder.h"
  42#include "util/probe-event.h"
  43#include "util/probe-file.h"
  44
  45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
  46#define DEFAULT_FUNC_FILTER "!_*"
  47#define DEFAULT_LIST_FILTER "*"
  48
  49/* Session management structure */
  50static struct {
  51        int command;    /* Command short_name */
  52        bool list_events;
  53        bool uprobes;
  54        bool quiet;
  55        bool target_used;
  56        int nevents;
  57        struct perf_probe_event events[MAX_PROBES];
  58        struct line_range line_range;
  59        char *target;
  60        struct strfilter *filter;
  61        struct nsinfo *nsi;
  62} params;
  63
  64/* Parse an event definition. Note that any error must die. */
  65static int parse_probe_event(const char *str)
  66{
  67        struct perf_probe_event *pev = &params.events[params.nevents];
  68        int ret;
  69
  70        pr_debug("probe-definition(%d): %s\n", params.nevents, str);
  71        if (++params.nevents == MAX_PROBES) {
  72                pr_err("Too many probes (> %d) were specified.", MAX_PROBES);
  73                return -1;
  74        }
  75
  76        pev->uprobes = params.uprobes;
  77        if (params.target) {
  78                pev->target = strdup(params.target);
  79                if (!pev->target)
  80                        return -ENOMEM;
  81                params.target_used = true;
  82        }
  83
  84        if (params.nsi)
  85                pev->nsi = nsinfo__get(params.nsi);
  86
  87        /* Parse a perf-probe command into event */
  88        ret = parse_perf_probe_command(str, pev);
  89        pr_debug("%d arguments\n", pev->nargs);
  90
  91        return ret;
  92}
  93
  94static int params_add_filter(const char *str)
  95{
  96        const char *err = NULL;
  97        int ret = 0;
  98
  99        pr_debug2("Add filter: %s\n", str);
 100        if (!params.filter) {
 101                params.filter = strfilter__new(str, &err);
 102                if (!params.filter)
 103                        ret = err ? -EINVAL : -ENOMEM;
 104        } else
 105                ret = strfilter__or(params.filter, str, &err);
 106
 107        if (ret == -EINVAL) {
 108                pr_err("Filter parse error at %td.\n", err - str + 1);
 109                pr_err("Source: \"%s\"\n", str);
 110                pr_err("         %*c\n", (int)(err - str + 1), '^');
 111        }
 112
 113        return ret;
 114}
 115
 116static int set_target(const char *ptr)
 117{
 118        int found = 0;
 119        const char *buf;
 120
 121        /*
 122         * The first argument after options can be an absolute path
 123         * to an executable / library or kernel module.
 124         *
 125         * TODO: Support relative path, and $PATH, $LD_LIBRARY_PATH,
 126         * short module name.
 127         */
 128        if (!params.target && ptr && *ptr == '/') {
 129                params.target = strdup(ptr);
 130                if (!params.target)
 131                        return -ENOMEM;
 132                params.target_used = false;
 133
 134                found = 1;
 135                buf = ptr + (strlen(ptr) - 3);
 136
 137                if (strcmp(buf, ".ko"))
 138                        params.uprobes = true;
 139
 140        }
 141
 142        return found;
 143}
 144
 145static int parse_probe_event_argv(int argc, const char **argv)
 146{
 147        int i, len, ret, found_target;
 148        char *buf;
 149
 150        found_target = set_target(argv[0]);
 151        if (found_target < 0)
 152                return found_target;
 153
 154        if (found_target && argc == 1)
 155                return 0;
 156
 157        /* Bind up rest arguments */
 158        len = 0;
 159        for (i = 0; i < argc; i++) {
 160                if (i == 0 && found_target)
 161                        continue;
 162
 163                len += strlen(argv[i]) + 1;
 164        }
 165        buf = zalloc(len + 1);
 166        if (buf == NULL)
 167                return -ENOMEM;
 168        len = 0;
 169        for (i = 0; i < argc; i++) {
 170                if (i == 0 && found_target)
 171                        continue;
 172
 173                len += sprintf(&buf[len], "%s ", argv[i]);
 174        }
 175        ret = parse_probe_event(buf);
 176        free(buf);
 177        return ret;
 178}
 179
 180static int opt_set_target(const struct option *opt, const char *str,
 181                        int unset __maybe_unused)
 182{
 183        int ret = -ENOENT;
 184        char *tmp;
 185
 186        if  (str) {
 187                if (!strcmp(opt->long_name, "exec"))
 188                        params.uprobes = true;
 189                else if (!strcmp(opt->long_name, "module"))
 190                        params.uprobes = false;
 191                else
 192                        return ret;
 193
 194                /* Expand given path to absolute path, except for modulename */
 195                if (params.uprobes || strchr(str, '/')) {
 196                        tmp = nsinfo__realpath(str, params.nsi);
 197                        if (!tmp) {
 198                                pr_warning("Failed to get the absolute path of %s: %m\n", str);
 199                                return ret;
 200                        }
 201                } else {
 202                        tmp = strdup(str);
 203                        if (!tmp)
 204                                return -ENOMEM;
 205                }
 206                free(params.target);
 207                params.target = tmp;
 208                params.target_used = false;
 209                ret = 0;
 210        }
 211
 212        return ret;
 213}
 214
 215static int opt_set_target_ns(const struct option *opt __maybe_unused,
 216                             const char *str, int unset __maybe_unused)
 217{
 218        int ret = -ENOENT;
 219        pid_t ns_pid;
 220        struct nsinfo *nsip;
 221
 222        if (str) {
 223                errno = 0;
 224                ns_pid = (pid_t)strtol(str, NULL, 10);
 225                if (errno != 0) {
 226                        ret = -errno;
 227                        pr_warning("Failed to parse %s as a pid: %s\n", str,
 228                                   strerror(errno));
 229                        return ret;
 230                }
 231                nsip = nsinfo__new(ns_pid);
 232                if (nsip && nsip->need_setns)
 233                        params.nsi = nsinfo__get(nsip);
 234                nsinfo__put(nsip);
 235
 236                ret = 0;
 237        }
 238
 239        return ret;
 240}
 241
 242
 243/* Command option callbacks */
 244
 245#ifdef HAVE_DWARF_SUPPORT
 246static int opt_show_lines(const struct option *opt,
 247                          const char *str, int unset __maybe_unused)
 248{
 249        int ret = 0;
 250
 251        if (!str)
 252                return 0;
 253
 254        if (params.command == 'L') {
 255                pr_warning("Warning: more than one --line options are"
 256                           " detected. Only the first one is valid.\n");
 257                return 0;
 258        }
 259
 260        params.command = opt->short_name;
 261        ret = parse_line_range_desc(str, &params.line_range);
 262
 263        return ret;
 264}
 265
 266static int opt_show_vars(const struct option *opt,
 267                         const char *str, int unset __maybe_unused)
 268{
 269        struct perf_probe_event *pev = &params.events[params.nevents];
 270        int ret;
 271
 272        if (!str)
 273                return 0;
 274
 275        ret = parse_probe_event(str);
 276        if (!ret && pev->nargs != 0) {
 277                pr_err("  Error: '--vars' doesn't accept arguments.\n");
 278                return -EINVAL;
 279        }
 280        params.command = opt->short_name;
 281
 282        return ret;
 283}
 284#else
 285# define opt_show_lines NULL
 286# define opt_show_vars NULL
 287#endif
 288static int opt_add_probe_event(const struct option *opt,
 289                              const char *str, int unset __maybe_unused)
 290{
 291        if (str) {
 292                params.command = opt->short_name;
 293                return parse_probe_event(str);
 294        }
 295
 296        return 0;
 297}
 298
 299static int opt_set_filter_with_command(const struct option *opt,
 300                                       const char *str, int unset)
 301{
 302        if (!unset)
 303                params.command = opt->short_name;
 304
 305        if (str)
 306                return params_add_filter(str);
 307
 308        return 0;
 309}
 310
 311static int opt_set_filter(const struct option *opt __maybe_unused,
 312                          const char *str, int unset __maybe_unused)
 313{
 314        if (str)
 315                return params_add_filter(str);
 316
 317        return 0;
 318}
 319
 320static int init_params(void)
 321{
 322        return line_range__init(&params.line_range);
 323}
 324
 325static void cleanup_params(void)
 326{
 327        int i;
 328
 329        for (i = 0; i < params.nevents; i++)
 330                clear_perf_probe_event(params.events + i);
 331        line_range__clear(&params.line_range);
 332        free(params.target);
 333        strfilter__delete(params.filter);
 334        nsinfo__put(params.nsi);
 335        memset(&params, 0, sizeof(params));
 336}
 337
 338static void pr_err_with_code(const char *msg, int err)
 339{
 340        char sbuf[STRERR_BUFSIZE];
 341
 342        pr_err("%s", msg);
 343        pr_debug(" Reason: %s (Code: %d)",
 344                 str_error_r(-err, sbuf, sizeof(sbuf)), err);
 345        pr_err("\n");
 346}
 347
 348static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
 349{
 350        int ret;
 351        int i, k;
 352        const char *event = NULL, *group = NULL;
 353
 354        ret = init_probe_symbol_maps(pevs->uprobes);
 355        if (ret < 0)
 356                return ret;
 357
 358        ret = convert_perf_probe_events(pevs, npevs);
 359        if (ret < 0)
 360                goto out_cleanup;
 361
 362        if (params.command == 'D') {    /* it shows definition */
 363                ret = show_probe_trace_events(pevs, npevs);
 364                goto out_cleanup;
 365        }
 366
 367        ret = apply_perf_probe_events(pevs, npevs);
 368        if (ret < 0)
 369                goto out_cleanup;
 370
 371        for (i = k = 0; i < npevs; i++)
 372                k += pevs[i].ntevs;
 373
 374        pr_info("Added new event%s\n", (k > 1) ? "s:" : ":");
 375        for (i = 0; i < npevs; i++) {
 376                struct perf_probe_event *pev = &pevs[i];
 377
 378                for (k = 0; k < pev->ntevs; k++) {
 379                        struct probe_trace_event *tev = &pev->tevs[k];
 380
 381                        /* We use tev's name for showing new events */
 382                        show_perf_probe_event(tev->group, tev->event, pev,
 383                                              tev->point.module, false);
 384
 385                        /* Save the last valid name */
 386                        event = tev->event;
 387                        group = tev->group;
 388                }
 389        }
 390
 391        /* Note that it is possible to skip all events because of blacklist */
 392        if (event) {
 393                /* Show how to use the event. */
 394                pr_info("\nYou can now use it in all perf tools, such as:\n\n");
 395                pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event);
 396        }
 397
 398out_cleanup:
 399        cleanup_perf_probe_events(pevs, npevs);
 400        exit_probe_symbol_maps();
 401        return ret;
 402}
 403
 404static int del_perf_probe_caches(struct strfilter *filter)
 405{
 406        struct probe_cache *cache;
 407        struct strlist *bidlist;
 408        struct str_node *nd;
 409        int ret;
 410
 411        bidlist = build_id_cache__list_all(false);
 412        if (!bidlist) {
 413                ret = -errno;
 414                pr_debug("Failed to get buildids: %d\n", ret);
 415                return ret ?: -ENOMEM;
 416        }
 417
 418        strlist__for_each_entry(nd, bidlist) {
 419                cache = probe_cache__new(nd->s, NULL);
 420                if (!cache)
 421                        continue;
 422                if (probe_cache__filter_purge(cache, filter) < 0 ||
 423                    probe_cache__commit(cache) < 0)
 424                        pr_warning("Failed to remove entries for %s\n", nd->s);
 425                probe_cache__delete(cache);
 426        }
 427        return 0;
 428}
 429
 430static int perf_del_probe_events(struct strfilter *filter)
 431{
 432        int ret, ret2, ufd = -1, kfd = -1;
 433        char *str = strfilter__string(filter);
 434        struct strlist *klist = NULL, *ulist = NULL;
 435        struct str_node *ent;
 436
 437        if (!str)
 438                return -EINVAL;
 439
 440        pr_debug("Delete filter: \'%s\'\n", str);
 441
 442        if (probe_conf.cache)
 443                return del_perf_probe_caches(filter);
 444
 445        /* Get current event names */
 446        ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW);
 447        if (ret < 0)
 448                goto out;
 449
 450        klist = strlist__new(NULL, NULL);
 451        ulist = strlist__new(NULL, NULL);
 452        if (!klist || !ulist) {
 453                ret = -ENOMEM;
 454                goto out;
 455        }
 456
 457        ret = probe_file__get_events(kfd, filter, klist);
 458        if (ret == 0) {
 459                strlist__for_each_entry(ent, klist)
 460                        pr_info("Removed event: %s\n", ent->s);
 461
 462                ret = probe_file__del_strlist(kfd, klist);
 463                if (ret < 0)
 464                        goto error;
 465        }
 466
 467        ret2 = probe_file__get_events(ufd, filter, ulist);
 468        if (ret2 == 0) {
 469                strlist__for_each_entry(ent, ulist)
 470                        pr_info("Removed event: %s\n", ent->s);
 471
 472                ret2 = probe_file__del_strlist(ufd, ulist);
 473                if (ret2 < 0)
 474                        goto error;
 475        }
 476
 477        if (ret == -ENOENT && ret2 == -ENOENT)
 478                pr_warning("\"%s\" does not hit any event.\n", str);
 479        else
 480                ret = 0;
 481
 482error:
 483        if (kfd >= 0)
 484                close(kfd);
 485        if (ufd >= 0)
 486                close(ufd);
 487out:
 488        strlist__delete(klist);
 489        strlist__delete(ulist);
 490        free(str);
 491
 492        return ret;
 493}
 494
 495#ifdef HAVE_DWARF_SUPPORT
 496#define PROBEDEF_STR    \
 497        "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT [[NAME=]ARG ...]"
 498#else
 499#define PROBEDEF_STR    "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]"
 500#endif
 501
 502
 503static int
 504__cmd_probe(int argc, const char **argv)
 505{
 506        const char * const probe_usage[] = {
 507                "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
 508                "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
 509                "perf probe [<options>] --del '[GROUP:]EVENT' ...",
 510                "perf probe --list [GROUP:]EVENT ...",
 511#ifdef HAVE_DWARF_SUPPORT
 512                "perf probe [<options>] --line 'LINEDESC'",
 513                "perf probe [<options>] --vars 'PROBEPOINT'",
 514#endif
 515                "perf probe [<options>] --funcs",
 516                NULL
 517        };
 518        struct option options[] = {
 519        OPT_INCR('v', "verbose", &verbose,
 520                    "be more verbose (show parsed arguments, etc)"),
 521        OPT_BOOLEAN('q', "quiet", &params.quiet,
 522                    "be quiet (do not show any messages)"),
 523        OPT_CALLBACK_DEFAULT('l', "list", NULL, "[GROUP:]EVENT",
 524                             "list up probe events",
 525                             opt_set_filter_with_command, DEFAULT_LIST_FILTER),
 526        OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
 527                     opt_set_filter_with_command),
 528        OPT_CALLBACK('a', "add", NULL, PROBEDEF_STR,
 529                "probe point definition, where\n"
 530                "\t\tGROUP:\tGroup name (optional)\n"
 531                "\t\tEVENT:\tEvent name\n"
 532                "\t\tFUNC:\tFunction name\n"
 533                "\t\tOFF:\tOffset from function entry (in byte)\n"
 534                "\t\t%return:\tPut the probe at function return\n"
 535#ifdef HAVE_DWARF_SUPPORT
 536                "\t\tSRC:\tSource code path\n"
 537                "\t\tRL:\tRelative line number from function entry.\n"
 538                "\t\tAL:\tAbsolute line number in file.\n"
 539                "\t\tPT:\tLazy expression of line code.\n"
 540                "\t\tARG:\tProbe argument (local variable name or\n"
 541                "\t\t\tkprobe-tracer argument format.)\n",
 542#else
 543                "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
 544#endif
 545                opt_add_probe_event),
 546        OPT_CALLBACK('D', "definition", NULL, PROBEDEF_STR,
 547                "Show trace event definition of given traceevent for k/uprobe_events.",
 548                opt_add_probe_event),
 549        OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
 550                    " with existing name"),
 551        OPT_CALLBACK('L', "line", NULL,
 552                     "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
 553                     "Show source code lines.", opt_show_lines),
 554        OPT_CALLBACK('V', "vars", NULL,
 555                     "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
 556                     "Show accessible variables on PROBEDEF", opt_show_vars),
 557        OPT_BOOLEAN('\0', "externs", &probe_conf.show_ext_vars,
 558                    "Show external variables too (with --vars only)"),
 559        OPT_BOOLEAN('\0', "range", &probe_conf.show_location_range,
 560                "Show variables location range in scope (with --vars only)"),
 561        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 562                   "file", "vmlinux pathname"),
 563        OPT_STRING('s', "source", &symbol_conf.source_prefix,
 564                   "directory", "path to kernel source"),
 565        OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
 566                "Don't search inlined functions"),
 567        OPT__DRY_RUN(&probe_event_dry_run),
 568        OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
 569                 "Set how many probe points can be found for a probe."),
 570        OPT_CALLBACK_DEFAULT('F', "funcs", NULL, "[FILTER]",
 571                             "Show potential probe-able functions.",
 572                             opt_set_filter_with_command, DEFAULT_FUNC_FILTER),
 573        OPT_CALLBACK('\0', "filter", NULL,
 574                     "[!]FILTER", "Set a filter (with --vars/funcs only)\n"
 575                     "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
 576                     "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
 577                     opt_set_filter),
 578        OPT_CALLBACK('x', "exec", NULL, "executable|path",
 579                        "target executable name or path", opt_set_target),
 580        OPT_CALLBACK('m', "module", NULL, "modname|path",
 581                "target module name (for online) or path (for offline)",
 582                opt_set_target),
 583        OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
 584                    "Enable symbol demangling"),
 585        OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
 586                    "Enable kernel symbol demangling"),
 587        OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
 588        OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 589                   "Look for files with symbols relative to this directory"),
 590        OPT_CALLBACK(0, "target-ns", NULL, "pid",
 591                     "target pid for namespace contexts", opt_set_target_ns),
 592        OPT_END()
 593        };
 594        int ret;
 595
 596        set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
 597        set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
 598        set_option_flag(options, 'D', "definition", PARSE_OPT_EXCLUSIVE);
 599        set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
 600#ifdef HAVE_DWARF_SUPPORT
 601        set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
 602        set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
 603#else
 604# define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_DWARF=1", c)
 605        set_nobuild('L', "line", false);
 606        set_nobuild('V', "vars", false);
 607        set_nobuild('\0', "externs", false);
 608        set_nobuild('\0', "range", false);
 609        set_nobuild('k', "vmlinux", true);
 610        set_nobuild('s', "source", true);
 611        set_nobuild('\0', "no-inlines", true);
 612# undef set_nobuild
 613#endif
 614        set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE);
 615
 616        argc = parse_options(argc, argv, options, probe_usage,
 617                             PARSE_OPT_STOP_AT_NON_OPTION);
 618        if (argc > 0) {
 619                if (strcmp(argv[0], "-") == 0) {
 620                        usage_with_options_msg(probe_usage, options,
 621                                "'-' is not supported.\n");
 622                }
 623                if (params.command && params.command != 'a') {
 624                        usage_with_options_msg(probe_usage, options,
 625                                "another command except --add is set.\n");
 626                }
 627                ret = parse_probe_event_argv(argc, argv);
 628                if (ret < 0) {
 629                        pr_err_with_code("  Error: Command Parse Error.", ret);
 630                        return ret;
 631                }
 632                params.command = 'a';
 633        }
 634
 635        if (params.quiet) {
 636                if (verbose != 0) {
 637                        pr_err("  Error: -v and -q are exclusive.\n");
 638                        return -EINVAL;
 639                }
 640                verbose = -1;
 641        }
 642
 643        if (probe_conf.max_probes == 0)
 644                probe_conf.max_probes = MAX_PROBES;
 645
 646        /*
 647         * Only consider the user's kernel image path if given.
 648         */
 649        symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
 650
 651        /*
 652         * Except for --list, --del and --add, other command doesn't depend
 653         * nor change running kernel. So if user gives offline vmlinux,
 654         * ignore its buildid.
 655         */
 656        if (!strchr("lda", params.command) && symbol_conf.vmlinux_name)
 657                symbol_conf.ignore_vmlinux_buildid = true;
 658
 659        switch (params.command) {
 660        case 'l':
 661                if (params.uprobes) {
 662                        pr_err("  Error: Don't use --list with --exec.\n");
 663                        parse_options_usage(probe_usage, options, "l", true);
 664                        parse_options_usage(NULL, options, "x", true);
 665                        return -EINVAL;
 666                }
 667                ret = show_perf_probe_events(params.filter);
 668                if (ret < 0)
 669                        pr_err_with_code("  Error: Failed to show event list.", ret);
 670                return ret;
 671        case 'F':
 672                ret = show_available_funcs(params.target, params.nsi,
 673                                           params.filter, params.uprobes);
 674                if (ret < 0)
 675                        pr_err_with_code("  Error: Failed to show functions.", ret);
 676                return ret;
 677#ifdef HAVE_DWARF_SUPPORT
 678        case 'L':
 679                ret = show_line_range(&params.line_range, params.target,
 680                                      params.nsi, params.uprobes);
 681                if (ret < 0)
 682                        pr_err_with_code("  Error: Failed to show lines.", ret);
 683                return ret;
 684        case 'V':
 685                if (!params.filter)
 686                        params.filter = strfilter__new(DEFAULT_VAR_FILTER,
 687                                                       NULL);
 688
 689                ret = show_available_vars(params.events, params.nevents,
 690                                          params.filter);
 691                if (ret < 0)
 692                        pr_err_with_code("  Error: Failed to show vars.", ret);
 693                return ret;
 694#endif
 695        case 'd':
 696                ret = perf_del_probe_events(params.filter);
 697                if (ret < 0) {
 698                        pr_err_with_code("  Error: Failed to delete events.", ret);
 699                        return ret;
 700                }
 701                break;
 702        case 'D':
 703        case 'a':
 704
 705                /* Ensure the last given target is used */
 706                if (params.target && !params.target_used) {
 707                        pr_err("  Error: -x/-m must follow the probe definitions.\n");
 708                        parse_options_usage(probe_usage, options, "m", true);
 709                        parse_options_usage(NULL, options, "x", true);
 710                        return -EINVAL;
 711                }
 712
 713                ret = perf_add_probe_events(params.events, params.nevents);
 714                if (ret < 0) {
 715                        pr_err_with_code("  Error: Failed to add events.", ret);
 716                        return ret;
 717                }
 718                break;
 719        default:
 720                usage_with_options(probe_usage, options);
 721        }
 722        return 0;
 723}
 724
 725int cmd_probe(int argc, const char **argv)
 726{
 727        int ret;
 728
 729        ret = init_params();
 730        if (!ret) {
 731                ret = __cmd_probe(argc, argv);
 732                cleanup_params();
 733        }
 734
 735        return ret < 0 ? ret : 0;
 736}
 737