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