0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <sys/utsname.h>
0010 #include <sys/types.h>
0011 #include <sys/stat.h>
0012 #include <fcntl.h>
0013 #include <errno.h>
0014 #include <stdio.h>
0015 #include <unistd.h>
0016 #include <stdlib.h>
0017 #include <string.h>
0018
0019 #include "builtin.h"
0020 #include "namespaces.h"
0021 #include "util/build-id.h"
0022 #include "util/strlist.h"
0023 #include "util/strfilter.h"
0024 #include "util/symbol.h"
0025 #include "util/symbol_conf.h"
0026 #include "util/debug.h"
0027 #include <subcmd/parse-options.h>
0028 #include "util/probe-finder.h"
0029 #include "util/probe-event.h"
0030 #include "util/probe-file.h"
0031 #include <linux/string.h>
0032 #include <linux/zalloc.h>
0033
0034 #define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
0035 #define DEFAULT_FUNC_FILTER "!_* & !*@plt"
0036 #define DEFAULT_LIST_FILTER "*"
0037
0038
0039 static struct {
0040 int command;
0041 bool list_events;
0042 bool uprobes;
0043 bool quiet;
0044 bool target_used;
0045 int nevents;
0046 struct perf_probe_event events[MAX_PROBES];
0047 struct line_range line_range;
0048 char *target;
0049 struct strfilter *filter;
0050 struct nsinfo *nsi;
0051 } params;
0052
0053
0054 static int parse_probe_event(const char *str)
0055 {
0056 struct perf_probe_event *pev = ¶ms.events[params.nevents];
0057 int ret;
0058
0059 pr_debug("probe-definition(%d): %s\n", params.nevents, str);
0060 if (++params.nevents == MAX_PROBES) {
0061 pr_err("Too many probes (> %d) were specified.", MAX_PROBES);
0062 return -1;
0063 }
0064
0065 pev->uprobes = params.uprobes;
0066 if (params.target) {
0067 pev->target = strdup(params.target);
0068 if (!pev->target)
0069 return -ENOMEM;
0070 params.target_used = true;
0071 }
0072
0073 pev->nsi = nsinfo__get(params.nsi);
0074
0075
0076 ret = parse_perf_probe_command(str, pev);
0077 pr_debug("%d arguments\n", pev->nargs);
0078
0079 return ret;
0080 }
0081
0082 static int params_add_filter(const char *str)
0083 {
0084 const char *err = NULL;
0085 int ret = 0;
0086
0087 pr_debug2("Add filter: %s\n", str);
0088 if (!params.filter) {
0089 params.filter = strfilter__new(str, &err);
0090 if (!params.filter)
0091 ret = err ? -EINVAL : -ENOMEM;
0092 } else
0093 ret = strfilter__or(params.filter, str, &err);
0094
0095 if (ret == -EINVAL) {
0096 pr_err("Filter parse error at %td.\n", err - str + 1);
0097 pr_err("Source: \"%s\"\n", str);
0098 pr_err(" %*c\n", (int)(err - str + 1), '^');
0099 }
0100
0101 return ret;
0102 }
0103
0104 static int set_target(const char *ptr)
0105 {
0106 int found = 0;
0107 const char *buf;
0108
0109
0110
0111
0112
0113
0114
0115
0116 if (!params.target && ptr && *ptr == '/') {
0117 params.target = strdup(ptr);
0118 if (!params.target)
0119 return -ENOMEM;
0120 params.target_used = false;
0121
0122 found = 1;
0123 buf = ptr + (strlen(ptr) - 3);
0124
0125 if (strcmp(buf, ".ko"))
0126 params.uprobes = true;
0127
0128 }
0129
0130 return found;
0131 }
0132
0133 static int parse_probe_event_argv(int argc, const char **argv)
0134 {
0135 int i, len, ret, found_target;
0136 char *buf;
0137
0138 found_target = set_target(argv[0]);
0139 if (found_target < 0)
0140 return found_target;
0141
0142 if (found_target && argc == 1)
0143 return 0;
0144
0145
0146 len = 0;
0147 for (i = 0; i < argc; i++) {
0148 if (i == 0 && found_target)
0149 continue;
0150
0151 len += strlen(argv[i]) + 1;
0152 }
0153 buf = zalloc(len + 1);
0154 if (buf == NULL)
0155 return -ENOMEM;
0156 len = 0;
0157 for (i = 0; i < argc; i++) {
0158 if (i == 0 && found_target)
0159 continue;
0160
0161 len += sprintf(&buf[len], "%s ", argv[i]);
0162 }
0163 ret = parse_probe_event(buf);
0164 free(buf);
0165 return ret;
0166 }
0167
0168 static int opt_set_target(const struct option *opt, const char *str,
0169 int unset __maybe_unused)
0170 {
0171 int ret = -ENOENT;
0172 char *tmp;
0173
0174 if (str) {
0175 if (!strcmp(opt->long_name, "exec"))
0176 params.uprobes = true;
0177 else if (!strcmp(opt->long_name, "module"))
0178 params.uprobes = false;
0179 else
0180 return ret;
0181
0182
0183 if (params.uprobes || strchr(str, '/')) {
0184 tmp = nsinfo__realpath(str, params.nsi);
0185 if (!tmp) {
0186 pr_warning("Failed to get the absolute path of %s: %m\n", str);
0187 return ret;
0188 }
0189 } else {
0190 tmp = strdup(str);
0191 if (!tmp)
0192 return -ENOMEM;
0193 }
0194 free(params.target);
0195 params.target = tmp;
0196 params.target_used = false;
0197 ret = 0;
0198 }
0199
0200 return ret;
0201 }
0202
0203 static int opt_set_target_ns(const struct option *opt __maybe_unused,
0204 const char *str, int unset __maybe_unused)
0205 {
0206 int ret = -ENOENT;
0207 pid_t ns_pid;
0208 struct nsinfo *nsip;
0209
0210 if (str) {
0211 errno = 0;
0212 ns_pid = (pid_t)strtol(str, NULL, 10);
0213 if (errno != 0) {
0214 ret = -errno;
0215 pr_warning("Failed to parse %s as a pid: %s\n", str,
0216 strerror(errno));
0217 return ret;
0218 }
0219 nsip = nsinfo__new(ns_pid);
0220 if (nsip && nsinfo__need_setns(nsip))
0221 params.nsi = nsinfo__get(nsip);
0222 nsinfo__put(nsip);
0223
0224 ret = 0;
0225 }
0226
0227 return ret;
0228 }
0229
0230
0231
0232
0233 #ifdef HAVE_DWARF_SUPPORT
0234 static int opt_show_lines(const struct option *opt,
0235 const char *str, int unset __maybe_unused)
0236 {
0237 int ret = 0;
0238
0239 if (!str)
0240 return 0;
0241
0242 if (params.command == 'L') {
0243 pr_warning("Warning: more than one --line options are"
0244 " detected. Only the first one is valid.\n");
0245 return 0;
0246 }
0247
0248 params.command = opt->short_name;
0249 ret = parse_line_range_desc(str, ¶ms.line_range);
0250
0251 return ret;
0252 }
0253
0254 static int opt_show_vars(const struct option *opt,
0255 const char *str, int unset __maybe_unused)
0256 {
0257 struct perf_probe_event *pev = ¶ms.events[params.nevents];
0258 int ret;
0259
0260 if (!str)
0261 return 0;
0262
0263 ret = parse_probe_event(str);
0264 if (!ret && pev->nargs != 0) {
0265 pr_err(" Error: '--vars' doesn't accept arguments.\n");
0266 return -EINVAL;
0267 }
0268 params.command = opt->short_name;
0269
0270 return ret;
0271 }
0272 #else
0273 # define opt_show_lines NULL
0274 # define opt_show_vars NULL
0275 #endif
0276 static int opt_add_probe_event(const struct option *opt,
0277 const char *str, int unset __maybe_unused)
0278 {
0279 if (str) {
0280 params.command = opt->short_name;
0281 return parse_probe_event(str);
0282 }
0283
0284 return 0;
0285 }
0286
0287 static int opt_set_filter_with_command(const struct option *opt,
0288 const char *str, int unset)
0289 {
0290 if (!unset)
0291 params.command = opt->short_name;
0292
0293 if (str)
0294 return params_add_filter(str);
0295
0296 return 0;
0297 }
0298
0299 static int opt_set_filter(const struct option *opt __maybe_unused,
0300 const char *str, int unset __maybe_unused)
0301 {
0302 if (str)
0303 return params_add_filter(str);
0304
0305 return 0;
0306 }
0307
0308 static int init_params(void)
0309 {
0310 return line_range__init(¶ms.line_range);
0311 }
0312
0313 static void cleanup_params(void)
0314 {
0315 int i;
0316
0317 for (i = 0; i < params.nevents; i++)
0318 clear_perf_probe_event(params.events + i);
0319 line_range__clear(¶ms.line_range);
0320 free(params.target);
0321 strfilter__delete(params.filter);
0322 nsinfo__put(params.nsi);
0323 memset(¶ms, 0, sizeof(params));
0324 }
0325
0326 static void pr_err_with_code(const char *msg, int err)
0327 {
0328 char sbuf[STRERR_BUFSIZE];
0329
0330 pr_err("%s", msg);
0331 pr_debug(" Reason: %s (Code: %d)",
0332 str_error_r(-err, sbuf, sizeof(sbuf)), err);
0333 pr_err("\n");
0334 }
0335
0336 static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
0337 {
0338 int ret;
0339 int i, k;
0340 const char *event = NULL, *group = NULL;
0341
0342 ret = init_probe_symbol_maps(pevs->uprobes);
0343 if (ret < 0)
0344 return ret;
0345
0346 ret = convert_perf_probe_events(pevs, npevs);
0347 if (ret < 0)
0348 goto out_cleanup;
0349
0350 if (params.command == 'D') {
0351 if (probe_conf.bootconfig)
0352 ret = show_bootconfig_events(pevs, npevs);
0353 else
0354 ret = show_probe_trace_events(pevs, npevs);
0355 goto out_cleanup;
0356 }
0357
0358 ret = apply_perf_probe_events(pevs, npevs);
0359 if (ret < 0)
0360 goto out_cleanup;
0361
0362 for (i = k = 0; i < npevs; i++)
0363 k += pevs[i].ntevs;
0364
0365 pr_info("Added new event%s\n", (k > 1) ? "s:" : ":");
0366 for (i = 0; i < npevs; i++) {
0367 struct perf_probe_event *pev = &pevs[i];
0368
0369 for (k = 0; k < pev->ntevs; k++) {
0370 struct probe_trace_event *tev = &pev->tevs[k];
0371
0372 if (!tev->event)
0373 continue;
0374
0375
0376 show_perf_probe_event(tev->group, tev->event, pev,
0377 tev->point.module, false);
0378
0379
0380 event = tev->event;
0381 group = tev->group;
0382 }
0383 }
0384
0385
0386 if (event) {
0387
0388 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
0389 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event);
0390 }
0391
0392 out_cleanup:
0393 cleanup_perf_probe_events(pevs, npevs);
0394 exit_probe_symbol_maps();
0395 return ret;
0396 }
0397
0398 static int del_perf_probe_caches(struct strfilter *filter)
0399 {
0400 struct probe_cache *cache;
0401 struct strlist *bidlist;
0402 struct str_node *nd;
0403 int ret;
0404
0405 bidlist = build_id_cache__list_all(false);
0406 if (!bidlist) {
0407 ret = -errno;
0408 pr_debug("Failed to get buildids: %d\n", ret);
0409 return ret ?: -ENOMEM;
0410 }
0411
0412 strlist__for_each_entry(nd, bidlist) {
0413 cache = probe_cache__new(nd->s, NULL);
0414 if (!cache)
0415 continue;
0416 if (probe_cache__filter_purge(cache, filter) < 0 ||
0417 probe_cache__commit(cache) < 0)
0418 pr_warning("Failed to remove entries for %s\n", nd->s);
0419 probe_cache__delete(cache);
0420 }
0421 return 0;
0422 }
0423
0424 static int perf_del_probe_events(struct strfilter *filter)
0425 {
0426 int ret, ret2, ufd = -1, kfd = -1;
0427 char *str = strfilter__string(filter);
0428 struct strlist *klist = NULL, *ulist = NULL;
0429 struct str_node *ent;
0430
0431 if (!str)
0432 return -EINVAL;
0433
0434 pr_debug("Delete filter: \'%s\'\n", str);
0435
0436 if (probe_conf.cache)
0437 return del_perf_probe_caches(filter);
0438
0439
0440 ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW);
0441 if (ret < 0)
0442 goto out;
0443
0444 klist = strlist__new(NULL, NULL);
0445 ulist = strlist__new(NULL, NULL);
0446 if (!klist || !ulist) {
0447 ret = -ENOMEM;
0448 goto out;
0449 }
0450
0451 ret = probe_file__get_events(kfd, filter, klist);
0452 if (ret == 0) {
0453 strlist__for_each_entry(ent, klist)
0454 pr_info("Removed event: %s\n", ent->s);
0455
0456 ret = probe_file__del_strlist(kfd, klist);
0457 if (ret < 0)
0458 goto error;
0459 } else if (ret == -ENOMEM)
0460 goto error;
0461
0462 ret2 = probe_file__get_events(ufd, filter, ulist);
0463 if (ret2 == 0) {
0464 strlist__for_each_entry(ent, ulist)
0465 pr_info("Removed event: %s\n", ent->s);
0466
0467 ret2 = probe_file__del_strlist(ufd, ulist);
0468 if (ret2 < 0)
0469 goto error;
0470 } else if (ret2 == -ENOMEM)
0471 goto error;
0472
0473 if (ret == -ENOENT && ret2 == -ENOENT)
0474 pr_warning("\"%s\" does not hit any event.\n", str);
0475 else
0476 ret = 0;
0477
0478 error:
0479 if (kfd >= 0)
0480 close(kfd);
0481 if (ufd >= 0)
0482 close(ufd);
0483 out:
0484 strlist__delete(klist);
0485 strlist__delete(ulist);
0486 free(str);
0487
0488 return ret;
0489 }
0490
0491 #ifdef HAVE_DWARF_SUPPORT
0492 #define PROBEDEF_STR \
0493 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT [[NAME=]ARG ...]"
0494 #else
0495 #define PROBEDEF_STR "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]"
0496 #endif
0497
0498
0499 static int
0500 __cmd_probe(int argc, const char **argv)
0501 {
0502 const char * const probe_usage[] = {
0503 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
0504 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
0505 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
0506 "perf probe --list [GROUP:]EVENT ...",
0507 #ifdef HAVE_DWARF_SUPPORT
0508 "perf probe [<options>] --line 'LINEDESC'",
0509 "perf probe [<options>] --vars 'PROBEPOINT'",
0510 #endif
0511 "perf probe [<options>] --funcs",
0512 NULL
0513 };
0514 struct option options[] = {
0515 OPT_INCR('v', "verbose", &verbose,
0516 "be more verbose (show parsed arguments, etc)"),
0517 OPT_BOOLEAN('q', "quiet", ¶ms.quiet,
0518 "be quiet (do not show any messages)"),
0519 OPT_CALLBACK_DEFAULT('l', "list", NULL, "[GROUP:]EVENT",
0520 "list up probe events",
0521 opt_set_filter_with_command, DEFAULT_LIST_FILTER),
0522 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
0523 opt_set_filter_with_command),
0524 OPT_CALLBACK('a', "add", NULL, PROBEDEF_STR,
0525 "probe point definition, where\n"
0526 "\t\tGROUP:\tGroup name (optional)\n"
0527 "\t\tEVENT:\tEvent name\n"
0528 "\t\tFUNC:\tFunction name\n"
0529 "\t\tOFF:\tOffset from function entry (in byte)\n"
0530 "\t\t%return:\tPut the probe at function return\n"
0531 #ifdef HAVE_DWARF_SUPPORT
0532 "\t\tSRC:\tSource code path\n"
0533 "\t\tRL:\tRelative line number from function entry.\n"
0534 "\t\tAL:\tAbsolute line number in file.\n"
0535 "\t\tPT:\tLazy expression of line code.\n"
0536 "\t\tARG:\tProbe argument (local variable name or\n"
0537 "\t\t\tkprobe-tracer argument format.)\n",
0538 #else
0539 "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
0540 #endif
0541 opt_add_probe_event),
0542 OPT_CALLBACK('D', "definition", NULL, PROBEDEF_STR,
0543 "Show trace event definition of given traceevent for k/uprobe_events.",
0544 opt_add_probe_event),
0545 OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
0546 " with existing name"),
0547 OPT_CALLBACK('L', "line", NULL,
0548 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
0549 "Show source code lines.", opt_show_lines),
0550 OPT_CALLBACK('V', "vars", NULL,
0551 "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
0552 "Show accessible variables on PROBEDEF", opt_show_vars),
0553 OPT_BOOLEAN('\0', "externs", &probe_conf.show_ext_vars,
0554 "Show external variables too (with --vars only)"),
0555 OPT_BOOLEAN('\0', "range", &probe_conf.show_location_range,
0556 "Show variables location range in scope (with --vars only)"),
0557 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
0558 "file", "vmlinux pathname"),
0559 OPT_STRING('s', "source", &symbol_conf.source_prefix,
0560 "directory", "path to kernel source"),
0561 OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
0562 "Don't search inlined functions"),
0563 OPT__DRY_RUN(&probe_event_dry_run),
0564 OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
0565 "Set how many probe points can be found for a probe."),
0566 OPT_CALLBACK_DEFAULT('F', "funcs", NULL, "[FILTER]",
0567 "Show potential probe-able functions.",
0568 opt_set_filter_with_command, DEFAULT_FUNC_FILTER),
0569 OPT_CALLBACK('\0', "filter", NULL,
0570 "[!]FILTER", "Set a filter (with --vars/funcs only)\n"
0571 "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
0572 "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
0573 opt_set_filter),
0574 OPT_CALLBACK('x', "exec", NULL, "executable|path",
0575 "target executable name or path", opt_set_target),
0576 OPT_CALLBACK('m', "module", NULL, "modname|path",
0577 "target module name (for online) or path (for offline)",
0578 opt_set_target),
0579 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
0580 "Enable symbol demangling"),
0581 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
0582 "Enable kernel symbol demangling"),
0583 OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
0584 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
0585 "Look for files with symbols relative to this directory"),
0586 OPT_CALLBACK(0, "target-ns", NULL, "pid",
0587 "target pid for namespace contexts", opt_set_target_ns),
0588 OPT_BOOLEAN(0, "bootconfig", &probe_conf.bootconfig,
0589 "Output probe definition with bootconfig format"),
0590 OPT_END()
0591 };
0592 int ret;
0593
0594 set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
0595 set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
0596 set_option_flag(options, 'D', "definition", PARSE_OPT_EXCLUSIVE);
0597 set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
0598 #ifdef HAVE_DWARF_SUPPORT
0599 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
0600 set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
0601 #else
0602 # define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_DWARF=1", c)
0603 set_nobuild('L', "line", false);
0604 set_nobuild('V', "vars", false);
0605 set_nobuild('\0', "externs", false);
0606 set_nobuild('\0', "range", false);
0607 set_nobuild('k', "vmlinux", true);
0608 set_nobuild('s', "source", true);
0609 set_nobuild('\0', "no-inlines", true);
0610 # undef set_nobuild
0611 #endif
0612 set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE);
0613
0614 argc = parse_options(argc, argv, options, probe_usage,
0615 PARSE_OPT_STOP_AT_NON_OPTION);
0616 if (argc > 0) {
0617 if (strcmp(argv[0], "-") == 0) {
0618 usage_with_options_msg(probe_usage, options,
0619 "'-' is not supported.\n");
0620 }
0621 if (params.command && params.command != 'a') {
0622 usage_with_options_msg(probe_usage, options,
0623 "another command except --add is set.\n");
0624 }
0625 ret = parse_probe_event_argv(argc, argv);
0626 if (ret < 0) {
0627 pr_err_with_code(" Error: Command Parse Error.", ret);
0628 return ret;
0629 }
0630 params.command = 'a';
0631 }
0632
0633 ret = symbol__validate_sym_arguments();
0634 if (ret)
0635 return ret;
0636
0637 if (params.quiet) {
0638 if (verbose != 0) {
0639 pr_err(" Error: -v and -q are exclusive.\n");
0640 return -EINVAL;
0641 }
0642 verbose = -1;
0643 }
0644
0645 if (probe_conf.max_probes == 0)
0646 probe_conf.max_probes = MAX_PROBES;
0647
0648
0649
0650
0651 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
0652
0653
0654
0655
0656
0657
0658 if (!strchr("lda", params.command) && symbol_conf.vmlinux_name)
0659 symbol_conf.ignore_vmlinux_buildid = true;
0660
0661 switch (params.command) {
0662 case 'l':
0663 if (params.uprobes) {
0664 pr_err(" Error: Don't use --list with --exec.\n");
0665 parse_options_usage(probe_usage, options, "l", true);
0666 parse_options_usage(NULL, options, "x", true);
0667 return -EINVAL;
0668 }
0669 ret = show_perf_probe_events(params.filter);
0670 if (ret < 0)
0671 pr_err_with_code(" Error: Failed to show event list.", ret);
0672 return ret;
0673 case 'F':
0674 ret = show_available_funcs(params.target, params.nsi,
0675 params.filter, params.uprobes);
0676 if (ret < 0)
0677 pr_err_with_code(" Error: Failed to show functions.", ret);
0678 return ret;
0679 #ifdef HAVE_DWARF_SUPPORT
0680 case 'L':
0681 ret = show_line_range(¶ms.line_range, params.target,
0682 params.nsi, params.uprobes);
0683 if (ret < 0)
0684 pr_err_with_code(" Error: Failed to show lines.", ret);
0685 return ret;
0686 case 'V':
0687 if (!params.filter)
0688 params.filter = strfilter__new(DEFAULT_VAR_FILTER,
0689 NULL);
0690
0691 ret = show_available_vars(params.events, params.nevents,
0692 params.filter);
0693 if (ret < 0)
0694 pr_err_with_code(" Error: Failed to show vars.", ret);
0695 return ret;
0696 #endif
0697 case 'd':
0698 ret = perf_del_probe_events(params.filter);
0699 if (ret < 0) {
0700 pr_err_with_code(" Error: Failed to delete events.", ret);
0701 return ret;
0702 }
0703 break;
0704 case 'D':
0705 if (probe_conf.bootconfig && params.uprobes) {
0706 pr_err(" Error: --bootconfig doesn't support uprobes.\n");
0707 return -EINVAL;
0708 }
0709 __fallthrough;
0710 case 'a':
0711
0712
0713 if (params.target && !params.target_used) {
0714 pr_err(" Error: -x/-m must follow the probe definitions.\n");
0715 parse_options_usage(probe_usage, options, "m", true);
0716 parse_options_usage(NULL, options, "x", true);
0717 return -EINVAL;
0718 }
0719
0720 ret = perf_add_probe_events(params.events, params.nevents);
0721 if (ret < 0) {
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731 params.nevents = 0;
0732 pr_err_with_code(" Error: Failed to add events.", ret);
0733 return ret;
0734 }
0735 break;
0736 default:
0737 usage_with_options(probe_usage, options);
0738 }
0739 return 0;
0740 }
0741
0742 int cmd_probe(int argc, const char **argv)
0743 {
0744 int ret;
0745
0746 ret = init_params();
0747 if (!ret) {
0748 ret = __cmd_probe(argc, argv);
0749 cleanup_params();
0750 }
0751
0752 return ret < 0 ? ret : 0;
0753 }