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