root/tools/perf/builtin-probe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. parse_probe_event
  2. params_add_filter
  3. set_target
  4. parse_probe_event_argv
  5. opt_set_target
  6. opt_set_target_ns
  7. opt_show_lines
  8. opt_show_vars
  9. opt_add_probe_event
  10. opt_set_filter_with_command
  11. opt_set_filter
  12. init_params
  13. cleanup_params
  14. pr_err_with_code
  15. perf_add_probe_events
  16. del_perf_probe_caches
  17. perf_del_probe_events
  18. __cmd_probe
  19. cmd_probe

   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 "!_*"
  35 #define DEFAULT_LIST_FILTER "*"
  36 
  37 /* Session management structure */
  38 static 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. */
  53 static 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 
  81 static 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 
 103 static 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 
 132 static 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 
 167 static 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 
 202 static 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
 233 static 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 
 253 static 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
 275 static 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 
 286 static 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 
 298 static 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 
 307 static int init_params(void)
 308 {
 309         return line_range__init(&params.line_range);
 310 }
 311 
 312 static 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 
 325 static 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 
 335 static 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                 ret = show_probe_trace_events(pevs, npevs);
 351                 goto out_cleanup;
 352         }
 353 
 354         ret = apply_perf_probe_events(pevs, npevs);
 355         if (ret < 0)
 356                 goto out_cleanup;
 357 
 358         for (i = k = 0; i < npevs; i++)
 359                 k += pevs[i].ntevs;
 360 
 361         pr_info("Added new event%s\n", (k > 1) ? "s:" : ":");
 362         for (i = 0; i < npevs; i++) {
 363                 struct perf_probe_event *pev = &pevs[i];
 364 
 365                 for (k = 0; k < pev->ntevs; k++) {
 366                         struct probe_trace_event *tev = &pev->tevs[k];
 367 
 368                         /* We use tev's name for showing new events */
 369                         show_perf_probe_event(tev->group, tev->event, pev,
 370                                               tev->point.module, false);
 371 
 372                         /* Save the last valid name */
 373                         event = tev->event;
 374                         group = tev->group;
 375                 }
 376         }
 377 
 378         /* Note that it is possible to skip all events because of blacklist */
 379         if (event) {
 380                 /* Show how to use the event. */
 381                 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
 382                 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event);
 383         }
 384 
 385 out_cleanup:
 386         cleanup_perf_probe_events(pevs, npevs);
 387         exit_probe_symbol_maps();
 388         return ret;
 389 }
 390 
 391 static int del_perf_probe_caches(struct strfilter *filter)
 392 {
 393         struct probe_cache *cache;
 394         struct strlist *bidlist;
 395         struct str_node *nd;
 396         int ret;
 397 
 398         bidlist = build_id_cache__list_all(false);
 399         if (!bidlist) {
 400                 ret = -errno;
 401                 pr_debug("Failed to get buildids: %d\n", ret);
 402                 return ret ?: -ENOMEM;
 403         }
 404 
 405         strlist__for_each_entry(nd, bidlist) {
 406                 cache = probe_cache__new(nd->s, NULL);
 407                 if (!cache)
 408                         continue;
 409                 if (probe_cache__filter_purge(cache, filter) < 0 ||
 410                     probe_cache__commit(cache) < 0)
 411                         pr_warning("Failed to remove entries for %s\n", nd->s);
 412                 probe_cache__delete(cache);
 413         }
 414         return 0;
 415 }
 416 
 417 static int perf_del_probe_events(struct strfilter *filter)
 418 {
 419         int ret, ret2, ufd = -1, kfd = -1;
 420         char *str = strfilter__string(filter);
 421         struct strlist *klist = NULL, *ulist = NULL;
 422         struct str_node *ent;
 423 
 424         if (!str)
 425                 return -EINVAL;
 426 
 427         pr_debug("Delete filter: \'%s\'\n", str);
 428 
 429         if (probe_conf.cache)
 430                 return del_perf_probe_caches(filter);
 431 
 432         /* Get current event names */
 433         ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW);
 434         if (ret < 0)
 435                 goto out;
 436 
 437         klist = strlist__new(NULL, NULL);
 438         ulist = strlist__new(NULL, NULL);
 439         if (!klist || !ulist) {
 440                 ret = -ENOMEM;
 441                 goto out;
 442         }
 443 
 444         ret = probe_file__get_events(kfd, filter, klist);
 445         if (ret == 0) {
 446                 strlist__for_each_entry(ent, klist)
 447                         pr_info("Removed event: %s\n", ent->s);
 448 
 449                 ret = probe_file__del_strlist(kfd, klist);
 450                 if (ret < 0)
 451                         goto error;
 452         }
 453 
 454         ret2 = probe_file__get_events(ufd, filter, ulist);
 455         if (ret2 == 0) {
 456                 strlist__for_each_entry(ent, ulist)
 457                         pr_info("Removed event: %s\n", ent->s);
 458 
 459                 ret2 = probe_file__del_strlist(ufd, ulist);
 460                 if (ret2 < 0)
 461                         goto error;
 462         }
 463 
 464         if (ret == -ENOENT && ret2 == -ENOENT)
 465                 pr_warning("\"%s\" does not hit any event.\n", str);
 466         else
 467                 ret = 0;
 468 
 469 error:
 470         if (kfd >= 0)
 471                 close(kfd);
 472         if (ufd >= 0)
 473                 close(ufd);
 474 out:
 475         strlist__delete(klist);
 476         strlist__delete(ulist);
 477         free(str);
 478 
 479         return ret;
 480 }
 481 
 482 #ifdef HAVE_DWARF_SUPPORT
 483 #define PROBEDEF_STR    \
 484         "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT [[NAME=]ARG ...]"
 485 #else
 486 #define PROBEDEF_STR    "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]"
 487 #endif
 488 
 489 
 490 static int
 491 __cmd_probe(int argc, const char **argv)
 492 {
 493         const char * const probe_usage[] = {
 494                 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
 495                 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
 496                 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
 497                 "perf probe --list [GROUP:]EVENT ...",
 498 #ifdef HAVE_DWARF_SUPPORT
 499                 "perf probe [<options>] --line 'LINEDESC'",
 500                 "perf probe [<options>] --vars 'PROBEPOINT'",
 501 #endif
 502                 "perf probe [<options>] --funcs",
 503                 NULL
 504         };
 505         struct option options[] = {
 506         OPT_INCR('v', "verbose", &verbose,
 507                     "be more verbose (show parsed arguments, etc)"),
 508         OPT_BOOLEAN('q', "quiet", &params.quiet,
 509                     "be quiet (do not show any messages)"),
 510         OPT_CALLBACK_DEFAULT('l', "list", NULL, "[GROUP:]EVENT",
 511                              "list up probe events",
 512                              opt_set_filter_with_command, DEFAULT_LIST_FILTER),
 513         OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
 514                      opt_set_filter_with_command),
 515         OPT_CALLBACK('a', "add", NULL, PROBEDEF_STR,
 516                 "probe point definition, where\n"
 517                 "\t\tGROUP:\tGroup name (optional)\n"
 518                 "\t\tEVENT:\tEvent name\n"
 519                 "\t\tFUNC:\tFunction name\n"
 520                 "\t\tOFF:\tOffset from function entry (in byte)\n"
 521                 "\t\t%return:\tPut the probe at function return\n"
 522 #ifdef HAVE_DWARF_SUPPORT
 523                 "\t\tSRC:\tSource code path\n"
 524                 "\t\tRL:\tRelative line number from function entry.\n"
 525                 "\t\tAL:\tAbsolute line number in file.\n"
 526                 "\t\tPT:\tLazy expression of line code.\n"
 527                 "\t\tARG:\tProbe argument (local variable name or\n"
 528                 "\t\t\tkprobe-tracer argument format.)\n",
 529 #else
 530                 "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
 531 #endif
 532                 opt_add_probe_event),
 533         OPT_CALLBACK('D', "definition", NULL, PROBEDEF_STR,
 534                 "Show trace event definition of given traceevent for k/uprobe_events.",
 535                 opt_add_probe_event),
 536         OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
 537                     " with existing name"),
 538         OPT_CALLBACK('L', "line", NULL,
 539                      "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
 540                      "Show source code lines.", opt_show_lines),
 541         OPT_CALLBACK('V', "vars", NULL,
 542                      "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
 543                      "Show accessible variables on PROBEDEF", opt_show_vars),
 544         OPT_BOOLEAN('\0', "externs", &probe_conf.show_ext_vars,
 545                     "Show external variables too (with --vars only)"),
 546         OPT_BOOLEAN('\0', "range", &probe_conf.show_location_range,
 547                 "Show variables location range in scope (with --vars only)"),
 548         OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 549                    "file", "vmlinux pathname"),
 550         OPT_STRING('s', "source", &symbol_conf.source_prefix,
 551                    "directory", "path to kernel source"),
 552         OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
 553                 "Don't search inlined functions"),
 554         OPT__DRY_RUN(&probe_event_dry_run),
 555         OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
 556                  "Set how many probe points can be found for a probe."),
 557         OPT_CALLBACK_DEFAULT('F', "funcs", NULL, "[FILTER]",
 558                              "Show potential probe-able functions.",
 559                              opt_set_filter_with_command, DEFAULT_FUNC_FILTER),
 560         OPT_CALLBACK('\0', "filter", NULL,
 561                      "[!]FILTER", "Set a filter (with --vars/funcs only)\n"
 562                      "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
 563                      "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
 564                      opt_set_filter),
 565         OPT_CALLBACK('x', "exec", NULL, "executable|path",
 566                         "target executable name or path", opt_set_target),
 567         OPT_CALLBACK('m', "module", NULL, "modname|path",
 568                 "target module name (for online) or path (for offline)",
 569                 opt_set_target),
 570         OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
 571                     "Enable symbol demangling"),
 572         OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
 573                     "Enable kernel symbol demangling"),
 574         OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
 575         OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 576                    "Look for files with symbols relative to this directory"),
 577         OPT_CALLBACK(0, "target-ns", NULL, "pid",
 578                      "target pid for namespace contexts", opt_set_target_ns),
 579         OPT_END()
 580         };
 581         int ret;
 582 
 583         set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
 584         set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
 585         set_option_flag(options, 'D', "definition", PARSE_OPT_EXCLUSIVE);
 586         set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
 587 #ifdef HAVE_DWARF_SUPPORT
 588         set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
 589         set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
 590 #else
 591 # define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_DWARF=1", c)
 592         set_nobuild('L', "line", false);
 593         set_nobuild('V', "vars", false);
 594         set_nobuild('\0', "externs", false);
 595         set_nobuild('\0', "range", false);
 596         set_nobuild('k', "vmlinux", true);
 597         set_nobuild('s', "source", true);
 598         set_nobuild('\0', "no-inlines", true);
 599 # undef set_nobuild
 600 #endif
 601         set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE);
 602 
 603         argc = parse_options(argc, argv, options, probe_usage,
 604                              PARSE_OPT_STOP_AT_NON_OPTION);
 605         if (argc > 0) {
 606                 if (strcmp(argv[0], "-") == 0) {
 607                         usage_with_options_msg(probe_usage, options,
 608                                 "'-' is not supported.\n");
 609                 }
 610                 if (params.command && params.command != 'a') {
 611                         usage_with_options_msg(probe_usage, options,
 612                                 "another command except --add is set.\n");
 613                 }
 614                 ret = parse_probe_event_argv(argc, argv);
 615                 if (ret < 0) {
 616                         pr_err_with_code("  Error: Command Parse Error.", ret);
 617                         return ret;
 618                 }
 619                 params.command = 'a';
 620         }
 621 
 622         if (params.quiet) {
 623                 if (verbose != 0) {
 624                         pr_err("  Error: -v and -q are exclusive.\n");
 625                         return -EINVAL;
 626                 }
 627                 verbose = -1;
 628         }
 629 
 630         if (probe_conf.max_probes == 0)
 631                 probe_conf.max_probes = MAX_PROBES;
 632 
 633         /*
 634          * Only consider the user's kernel image path if given.
 635          */
 636         symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
 637 
 638         /*
 639          * Except for --list, --del and --add, other command doesn't depend
 640          * nor change running kernel. So if user gives offline vmlinux,
 641          * ignore its buildid.
 642          */
 643         if (!strchr("lda", params.command) && symbol_conf.vmlinux_name)
 644                 symbol_conf.ignore_vmlinux_buildid = true;
 645 
 646         switch (params.command) {
 647         case 'l':
 648                 if (params.uprobes) {
 649                         pr_err("  Error: Don't use --list with --exec.\n");
 650                         parse_options_usage(probe_usage, options, "l", true);
 651                         parse_options_usage(NULL, options, "x", true);
 652                         return -EINVAL;
 653                 }
 654                 ret = show_perf_probe_events(params.filter);
 655                 if (ret < 0)
 656                         pr_err_with_code("  Error: Failed to show event list.", ret);
 657                 return ret;
 658         case 'F':
 659                 ret = show_available_funcs(params.target, params.nsi,
 660                                            params.filter, params.uprobes);
 661                 if (ret < 0)
 662                         pr_err_with_code("  Error: Failed to show functions.", ret);
 663                 return ret;
 664 #ifdef HAVE_DWARF_SUPPORT
 665         case 'L':
 666                 ret = show_line_range(&params.line_range, params.target,
 667                                       params.nsi, params.uprobes);
 668                 if (ret < 0)
 669                         pr_err_with_code("  Error: Failed to show lines.", ret);
 670                 return ret;
 671         case 'V':
 672                 if (!params.filter)
 673                         params.filter = strfilter__new(DEFAULT_VAR_FILTER,
 674                                                        NULL);
 675 
 676                 ret = show_available_vars(params.events, params.nevents,
 677                                           params.filter);
 678                 if (ret < 0)
 679                         pr_err_with_code("  Error: Failed to show vars.", ret);
 680                 return ret;
 681 #endif
 682         case 'd':
 683                 ret = perf_del_probe_events(params.filter);
 684                 if (ret < 0) {
 685                         pr_err_with_code("  Error: Failed to delete events.", ret);
 686                         return ret;
 687                 }
 688                 break;
 689         case 'D':
 690         case 'a':
 691 
 692                 /* Ensure the last given target is used */
 693                 if (params.target && !params.target_used) {
 694                         pr_err("  Error: -x/-m must follow the probe definitions.\n");
 695                         parse_options_usage(probe_usage, options, "m", true);
 696                         parse_options_usage(NULL, options, "x", true);
 697                         return -EINVAL;
 698                 }
 699 
 700                 ret = perf_add_probe_events(params.events, params.nevents);
 701                 if (ret < 0) {
 702 
 703                         /*
 704                          * When perf_add_probe_events() fails it calls
 705                          * cleanup_perf_probe_events(pevs, npevs), i.e.
 706                          * cleanup_perf_probe_events(params.events, params.nevents), which
 707                          * will call clear_perf_probe_event(), so set nevents to zero
 708                          * to avoid cleanup_params() to call clear_perf_probe_event() again
 709                          * on the same pevs.
 710                          */
 711                         params.nevents = 0;
 712                         pr_err_with_code("  Error: Failed to add events.", ret);
 713                         return ret;
 714                 }
 715                 break;
 716         default:
 717                 usage_with_options(probe_usage, options);
 718         }
 719         return 0;
 720 }
 721 
 722 int cmd_probe(int argc, const char **argv)
 723 {
 724         int ret;
 725 
 726         ret = init_params();
 727         if (!ret) {
 728                 ret = __cmd_probe(argc, argv);
 729                 cleanup_params();
 730         }
 731 
 732         return ret < 0 ? ret : 0;
 733 }

/* [<][>][^][v][top][bottom][index][help] */