GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / tools / perf / util / probe-event.c
blob56674fa19fbf5a124921b794536130b48d03a6d5
1 /*
2 * probe-event.c : perf-probe definition to probe_events format converter
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #define _GNU_SOURCE
23 #include <sys/utsname.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdarg.h>
33 #include <limits.h>
35 #undef _GNU_SOURCE
36 #include "util.h"
37 #include "event.h"
38 #include "string.h"
39 #include "strlist.h"
40 #include "debug.h"
41 #include "cache.h"
42 #include "color.h"
43 #include "symbol.h"
44 #include "thread.h"
45 #include "debugfs.h"
46 #include "trace-event.h" /* For __unused */
47 #include "probe-event.h"
48 #include "probe-finder.h"
50 #define MAX_CMDLEN 256
51 #define MAX_PROBE_ARGS 128
52 #define PERFPROBE_GROUP "probe"
54 bool probe_event_dry_run; /* Dry run flag */
56 #define semantic_error(msg ...) pr_err("Semantic error :" msg)
58 /* If there is no space to write, returns -E2BIG. */
59 static int e_snprintf(char *str, size_t size, const char *format, ...)
60 __attribute__((format(printf, 3, 4)));
62 static int e_snprintf(char *str, size_t size, const char *format, ...)
64 int ret;
65 va_list ap;
66 va_start(ap, format);
67 ret = vsnprintf(str, size, format, ap);
68 va_end(ap);
69 if (ret >= (int)size)
70 ret = -E2BIG;
71 return ret;
74 static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
75 static struct machine machine;
77 /* Initialize symbol maps and path of vmlinux */
78 static int init_vmlinux(void)
80 struct dso *kernel;
81 int ret;
83 symbol_conf.sort_by_name = true;
84 if (symbol_conf.vmlinux_name == NULL)
85 symbol_conf.try_vmlinux_path = true;
86 else
87 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
88 ret = symbol__init();
89 if (ret < 0) {
90 pr_debug("Failed to init symbol map.\n");
91 goto out;
94 ret = machine__init(&machine, "/", 0);
95 if (ret < 0)
96 goto out;
98 kernel = dso__new_kernel(symbol_conf.vmlinux_name);
99 if (kernel == NULL)
100 die("Failed to create kernel dso.");
102 ret = __machine__create_kernel_maps(&machine, kernel);
103 if (ret < 0)
104 pr_debug("Failed to create kernel maps.\n");
106 out:
107 if (ret < 0)
108 pr_warning("Failed to init vmlinux path.\n");
109 return ret;
112 #ifdef DWARF_SUPPORT
113 static int open_vmlinux(void)
115 if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) {
116 pr_debug("Failed to load kernel map.\n");
117 return -EINVAL;
119 pr_debug("Try to open %s\n", machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name);
120 return open(machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name, O_RDONLY);
124 * Convert trace point to probe point with debuginfo
125 * Currently only handles kprobes.
127 static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
128 struct perf_probe_point *pp)
130 struct symbol *sym;
131 int fd, ret = -ENOENT;
133 sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION],
134 tp->symbol, NULL);
135 if (sym) {
136 fd = open_vmlinux();
137 if (fd >= 0) {
138 ret = find_perf_probe_point(fd,
139 sym->start + tp->offset, pp);
140 close(fd);
143 if (ret <= 0) {
144 pr_debug("Failed to find corresponding probes from "
145 "debuginfo. Use kprobe event information.\n");
146 pp->function = strdup(tp->symbol);
147 if (pp->function == NULL)
148 return -ENOMEM;
149 pp->offset = tp->offset;
151 pp->retprobe = tp->retprobe;
153 return 0;
156 /* Try to find perf_probe_event with debuginfo */
157 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
158 struct probe_trace_event **tevs,
159 int max_tevs)
161 bool need_dwarf = perf_probe_event_need_dwarf(pev);
162 int fd, ntevs;
164 fd = open_vmlinux();
165 if (fd < 0) {
166 if (need_dwarf) {
167 pr_warning("Failed to open debuginfo file.\n");
168 return fd;
170 pr_debug("Could not open vmlinux. Try to use symbols.\n");
171 return 0;
174 /* Searching trace events corresponding to probe event */
175 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs);
176 close(fd);
178 if (ntevs > 0) { /* Succeeded to find trace events */
179 pr_debug("find %d probe_trace_events.\n", ntevs);
180 return ntevs;
183 if (ntevs == 0) { /* No error but failed to find probe point. */
184 pr_warning("Probe point '%s' not found.\n",
185 synthesize_perf_probe_point(&pev->point));
186 return -ENOENT;
188 /* Error path : ntevs < 0 */
189 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
190 if (ntevs == -EBADF) {
191 pr_warning("Warning: No dwarf info found in the vmlinux - "
192 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
193 if (!need_dwarf) {
194 pr_debug("Trying to use symbols.\nn");
195 return 0;
198 return ntevs;
202 * Find a src file from a DWARF tag path. Prepend optional source path prefix
203 * and chop off leading directories that do not exist. Result is passed back as
204 * a newly allocated path on success.
205 * Return 0 if file was found and readable, -errno otherwise.
207 static int get_real_path(const char *raw_path, const char *comp_dir,
208 char **new_path)
210 const char *prefix = symbol_conf.source_prefix;
212 if (!prefix) {
213 if (raw_path[0] != '/' && comp_dir)
214 /* If not an absolute path, try to use comp_dir */
215 prefix = comp_dir;
216 else {
217 if (access(raw_path, R_OK) == 0) {
218 *new_path = strdup(raw_path);
219 return 0;
220 } else
221 return -errno;
225 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
226 if (!*new_path)
227 return -ENOMEM;
229 for (;;) {
230 sprintf(*new_path, "%s/%s", prefix, raw_path);
232 if (access(*new_path, R_OK) == 0)
233 return 0;
235 if (!symbol_conf.source_prefix)
236 /* In case of searching comp_dir, don't retry */
237 return -errno;
239 switch (errno) {
240 case ENAMETOOLONG:
241 case ENOENT:
242 case EROFS:
243 case EFAULT:
244 raw_path = strchr(++raw_path, '/');
245 if (!raw_path) {
246 free(*new_path);
247 *new_path = NULL;
248 return -ENOENT;
250 continue;
252 default:
253 free(*new_path);
254 *new_path = NULL;
255 return -errno;
260 #define LINEBUF_SIZE 256
261 #define NR_ADDITIONAL_LINES 2
263 static int show_one_line(FILE *fp, int l, bool skip, bool show_num)
265 char buf[LINEBUF_SIZE];
266 const char *color = PERF_COLOR_BLUE;
268 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
269 goto error;
270 if (!skip) {
271 if (show_num)
272 fprintf(stdout, "%7d %s", l, buf);
273 else
274 color_fprintf(stdout, color, " %s", buf);
277 while (strlen(buf) == LINEBUF_SIZE - 1 &&
278 buf[LINEBUF_SIZE - 2] != '\n') {
279 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
280 goto error;
281 if (!skip) {
282 if (show_num)
283 fprintf(stdout, "%s", buf);
284 else
285 color_fprintf(stdout, color, "%s", buf);
289 return 0;
290 error:
291 if (feof(fp))
292 pr_warning("Source file is shorter than expected.\n");
293 else
294 pr_warning("File read error: %s\n", strerror(errno));
296 return -1;
300 * Show line-range always requires debuginfo to find source file and
301 * line number.
303 int show_line_range(struct line_range *lr)
305 int l = 1;
306 struct line_node *ln;
307 FILE *fp;
308 int fd, ret;
309 char *tmp;
311 /* Search a line range */
312 ret = init_vmlinux();
313 if (ret < 0)
314 return ret;
316 fd = open_vmlinux();
317 if (fd < 0) {
318 pr_warning("Failed to open debuginfo file.\n");
319 return fd;
322 ret = find_line_range(fd, lr);
323 close(fd);
324 if (ret == 0) {
325 pr_warning("Specified source line is not found.\n");
326 return -ENOENT;
327 } else if (ret < 0) {
328 pr_warning("Debuginfo analysis failed. (%d)\n", ret);
329 return ret;
332 /* Convert source file path */
333 tmp = lr->path;
334 ret = get_real_path(tmp, lr->comp_dir, &lr->path);
335 free(tmp); /* Free old path */
336 if (ret < 0) {
337 pr_warning("Failed to find source file. (%d)\n", ret);
338 return ret;
341 setup_pager();
343 if (lr->function)
344 fprintf(stdout, "<%s:%d>\n", lr->function,
345 lr->start - lr->offset);
346 else
347 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start);
349 fp = fopen(lr->path, "r");
350 if (fp == NULL) {
351 pr_warning("Failed to open %s: %s\n", lr->path,
352 strerror(errno));
353 return -errno;
355 /* Skip to starting line number */
356 while (l < lr->start && ret >= 0)
357 ret = show_one_line(fp, l++, true, false);
358 if (ret < 0)
359 goto end;
361 list_for_each_entry(ln, &lr->line_list, list) {
362 while (ln->line > l && ret >= 0)
363 ret = show_one_line(fp, (l++) - lr->offset,
364 false, false);
365 if (ret >= 0)
366 ret = show_one_line(fp, (l++) - lr->offset,
367 false, true);
368 if (ret < 0)
369 goto end;
372 if (lr->end == INT_MAX)
373 lr->end = l + NR_ADDITIONAL_LINES;
374 while (l <= lr->end && !feof(fp) && ret >= 0)
375 ret = show_one_line(fp, (l++) - lr->offset, false, false);
376 end:
377 fclose(fp);
378 return ret;
381 #else /* !DWARF_SUPPORT */
383 static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
384 struct perf_probe_point *pp)
386 pp->function = strdup(tp->symbol);
387 if (pp->function == NULL)
388 return -ENOMEM;
389 pp->offset = tp->offset;
390 pp->retprobe = tp->retprobe;
392 return 0;
395 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
396 struct probe_trace_event **tevs __unused,
397 int max_tevs __unused)
399 if (perf_probe_event_need_dwarf(pev)) {
400 pr_warning("Debuginfo-analysis is not supported.\n");
401 return -ENOSYS;
403 return 0;
406 int show_line_range(struct line_range *lr __unused)
408 pr_warning("Debuginfo-analysis is not supported.\n");
409 return -ENOSYS;
412 #endif
414 int parse_line_range_desc(const char *arg, struct line_range *lr)
416 const char *ptr;
417 char *tmp;
419 * <Syntax>
420 * SRC:SLN[+NUM|-ELN]
421 * FUNC[:SLN[+NUM|-ELN]]
423 ptr = strchr(arg, ':');
424 if (ptr) {
425 lr->start = (int)strtoul(ptr + 1, &tmp, 0);
426 if (*tmp == '+') {
427 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0);
428 lr->end--; /*
429 * Adjust the number of lines here.
430 * If the number of lines == 1, the
431 * the end of line should be equal to
432 * the start of line.
434 } else if (*tmp == '-')
435 lr->end = (int)strtoul(tmp + 1, &tmp, 0);
436 else
437 lr->end = INT_MAX;
438 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
439 if (lr->start > lr->end) {
440 semantic_error("Start line must be smaller"
441 " than end line.\n");
442 return -EINVAL;
444 if (*tmp != '\0') {
445 semantic_error("Tailing with invalid character '%d'.\n",
446 *tmp);
447 return -EINVAL;
449 tmp = strndup(arg, (ptr - arg));
450 } else {
451 tmp = strdup(arg);
452 lr->end = INT_MAX;
455 if (tmp == NULL)
456 return -ENOMEM;
458 if (strchr(tmp, '.'))
459 lr->file = tmp;
460 else
461 lr->function = tmp;
463 return 0;
466 /* Check the name is good for event/group */
467 static bool check_event_name(const char *name)
469 if (!isalpha(*name) && *name != '_')
470 return false;
471 while (*++name != '\0') {
472 if (!isalpha(*name) && !isdigit(*name) && *name != '_')
473 return false;
475 return true;
478 /* Parse probepoint definition. */
479 static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
481 struct perf_probe_point *pp = &pev->point;
482 char *ptr, *tmp;
483 char c, nc = 0;
485 * <Syntax>
486 * perf probe [EVENT=]SRC[:LN|;PTN]
487 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
489 * TODO:Group name support
492 ptr = strpbrk(arg, ";=@+%");
493 if (ptr && *ptr == '=') { /* Event name */
494 *ptr = '\0';
495 tmp = ptr + 1;
496 if (strchr(arg, ':')) {
497 semantic_error("Group name is not supported yet.\n");
498 return -ENOTSUP;
500 if (!check_event_name(arg)) {
501 semantic_error("%s is bad for event name -it must "
502 "follow C symbol-naming rule.\n", arg);
503 return -EINVAL;
505 pev->event = strdup(arg);
506 if (pev->event == NULL)
507 return -ENOMEM;
508 pev->group = NULL;
509 arg = tmp;
512 ptr = strpbrk(arg, ";:+@%");
513 if (ptr) {
514 nc = *ptr;
515 *ptr++ = '\0';
518 tmp = strdup(arg);
519 if (tmp == NULL)
520 return -ENOMEM;
522 /* Check arg is function or file and copy it */
523 if (strchr(tmp, '.')) /* File */
524 pp->file = tmp;
525 else /* Function */
526 pp->function = tmp;
528 /* Parse other options */
529 while (ptr) {
530 arg = ptr;
531 c = nc;
532 if (c == ';') { /* Lazy pattern must be the last part */
533 pp->lazy_line = strdup(arg);
534 if (pp->lazy_line == NULL)
535 return -ENOMEM;
536 break;
538 ptr = strpbrk(arg, ";:+@%");
539 if (ptr) {
540 nc = *ptr;
541 *ptr++ = '\0';
543 switch (c) {
544 case ':': /* Line number */
545 pp->line = strtoul(arg, &tmp, 0);
546 if (*tmp != '\0') {
547 semantic_error("There is non-digit char"
548 " in line number.\n");
549 return -EINVAL;
551 break;
552 case '+': /* Byte offset from a symbol */
553 pp->offset = strtoul(arg, &tmp, 0);
554 if (*tmp != '\0') {
555 semantic_error("There is non-digit character"
556 " in offset.\n");
557 return -EINVAL;
559 break;
560 case '@': /* File name */
561 if (pp->file) {
562 semantic_error("SRC@SRC is not allowed.\n");
563 return -EINVAL;
565 pp->file = strdup(arg);
566 if (pp->file == NULL)
567 return -ENOMEM;
568 break;
569 case '%': /* Probe places */
570 if (strcmp(arg, "return") == 0) {
571 pp->retprobe = 1;
572 } else { /* Others not supported yet */
573 semantic_error("%%%s is not supported.\n", arg);
574 return -ENOTSUP;
576 break;
577 default: /* Buggy case */
578 pr_err("This program has a bug at %s:%d.\n",
579 __FILE__, __LINE__);
580 return -ENOTSUP;
581 break;
585 /* Exclusion check */
586 if (pp->lazy_line && pp->line) {
587 semantic_error("Lazy pattern can't be used with line number.");
588 return -EINVAL;
591 if (pp->lazy_line && pp->offset) {
592 semantic_error("Lazy pattern can't be used with offset.");
593 return -EINVAL;
596 if (pp->line && pp->offset) {
597 semantic_error("Offset can't be used with line number.");
598 return -EINVAL;
601 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
602 semantic_error("File always requires line number or "
603 "lazy pattern.");
604 return -EINVAL;
607 if (pp->offset && !pp->function) {
608 semantic_error("Offset requires an entry function.");
609 return -EINVAL;
612 if (pp->retprobe && !pp->function) {
613 semantic_error("Return probe requires an entry function.");
614 return -EINVAL;
617 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
618 semantic_error("Offset/Line/Lazy pattern can't be used with "
619 "return probe.");
620 return -EINVAL;
623 pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
624 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
625 pp->lazy_line);
626 return 0;
629 /* Parse perf-probe event argument */
630 static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
632 char *tmp, *goodname;
633 struct perf_probe_arg_field **fieldp;
635 pr_debug("parsing arg: %s into ", str);
637 tmp = strchr(str, '=');
638 if (tmp) {
639 arg->name = strndup(str, tmp - str);
640 if (arg->name == NULL)
641 return -ENOMEM;
642 pr_debug("name:%s ", arg->name);
643 str = tmp + 1;
646 tmp = strchr(str, ':');
647 if (tmp) { /* Type setting */
648 *tmp = '\0';
649 arg->type = strdup(tmp + 1);
650 if (arg->type == NULL)
651 return -ENOMEM;
652 pr_debug("type:%s ", arg->type);
655 tmp = strpbrk(str, "-.[");
656 if (!is_c_varname(str) || !tmp) {
657 /* A variable, register, symbol or special value */
658 arg->var = strdup(str);
659 if (arg->var == NULL)
660 return -ENOMEM;
661 pr_debug("%s\n", arg->var);
662 return 0;
665 /* Structure fields or array element */
666 arg->var = strndup(str, tmp - str);
667 if (arg->var == NULL)
668 return -ENOMEM;
669 goodname = arg->var;
670 pr_debug("%s, ", arg->var);
671 fieldp = &arg->field;
673 do {
674 *fieldp = zalloc(sizeof(struct perf_probe_arg_field));
675 if (*fieldp == NULL)
676 return -ENOMEM;
677 if (*tmp == '[') { /* Array */
678 str = tmp;
679 (*fieldp)->index = strtol(str + 1, &tmp, 0);
680 (*fieldp)->ref = true;
681 if (*tmp != ']' || tmp == str + 1) {
682 semantic_error("Array index must be a"
683 " number.\n");
684 return -EINVAL;
686 tmp++;
687 if (*tmp == '\0')
688 tmp = NULL;
689 } else { /* Structure */
690 if (*tmp == '.') {
691 str = tmp + 1;
692 (*fieldp)->ref = false;
693 } else if (tmp[1] == '>') {
694 str = tmp + 2;
695 (*fieldp)->ref = true;
696 } else {
697 semantic_error("Argument parse error: %s\n",
698 str);
699 return -EINVAL;
701 tmp = strpbrk(str, "-.[");
703 if (tmp) {
704 (*fieldp)->name = strndup(str, tmp - str);
705 if ((*fieldp)->name == NULL)
706 return -ENOMEM;
707 if (*str != '[')
708 goodname = (*fieldp)->name;
709 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
710 fieldp = &(*fieldp)->next;
712 } while (tmp);
713 (*fieldp)->name = strdup(str);
714 if ((*fieldp)->name == NULL)
715 return -ENOMEM;
716 if (*str != '[')
717 goodname = (*fieldp)->name;
718 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
720 /* If no name is specified, set the last field name (not array index)*/
721 if (!arg->name) {
722 arg->name = strdup(goodname);
723 if (arg->name == NULL)
724 return -ENOMEM;
726 return 0;
729 /* Parse perf-probe event command */
730 int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
732 char **argv;
733 int argc, i, ret = 0;
735 argv = argv_split(cmd, &argc);
736 if (!argv) {
737 pr_debug("Failed to split arguments.\n");
738 return -ENOMEM;
740 if (argc - 1 > MAX_PROBE_ARGS) {
741 semantic_error("Too many probe arguments (%d).\n", argc - 1);
742 ret = -ERANGE;
743 goto out;
745 /* Parse probe point */
746 ret = parse_perf_probe_point(argv[0], pev);
747 if (ret < 0)
748 goto out;
750 /* Copy arguments and ensure return probe has no C argument */
751 pev->nargs = argc - 1;
752 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
753 if (pev->args == NULL) {
754 ret = -ENOMEM;
755 goto out;
757 for (i = 0; i < pev->nargs && ret >= 0; i++) {
758 ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
759 if (ret >= 0 &&
760 is_c_varname(pev->args[i].var) && pev->point.retprobe) {
761 semantic_error("You can't specify local variable for"
762 " kretprobe.\n");
763 ret = -EINVAL;
766 out:
767 argv_free(argv);
769 return ret;
772 /* Return true if this perf_probe_event requires debuginfo */
773 bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
775 int i;
777 if (pev->point.file || pev->point.line || pev->point.lazy_line)
778 return true;
780 for (i = 0; i < pev->nargs; i++)
781 if (is_c_varname(pev->args[i].var))
782 return true;
784 return false;
787 /* Parse probe_events event into struct probe_point */
788 static int parse_probe_trace_command(const char *cmd,
789 struct probe_trace_event *tev)
791 struct probe_trace_point *tp = &tev->point;
792 char pr;
793 char *p;
794 int ret, i, argc;
795 char **argv;
797 pr_debug("Parsing probe_events: %s\n", cmd);
798 argv = argv_split(cmd, &argc);
799 if (!argv) {
800 pr_debug("Failed to split arguments.\n");
801 return -ENOMEM;
803 if (argc < 2) {
804 semantic_error("Too few probe arguments.\n");
805 ret = -ERANGE;
806 goto out;
809 /* Scan event and group name. */
810 ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
811 &pr, (float *)(void *)&tev->group,
812 (float *)(void *)&tev->event);
813 if (ret != 3) {
814 semantic_error("Failed to parse event name: %s\n", argv[0]);
815 ret = -EINVAL;
816 goto out;
818 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
820 tp->retprobe = (pr == 'r');
822 /* Scan function name and offset */
823 ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol,
824 &tp->offset);
825 if (ret == 1)
826 tp->offset = 0;
828 tev->nargs = argc - 2;
829 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
830 if (tev->args == NULL) {
831 ret = -ENOMEM;
832 goto out;
834 for (i = 0; i < tev->nargs; i++) {
835 p = strchr(argv[i + 2], '=');
836 if (p) /* We don't need which register is assigned. */
837 *p++ = '\0';
838 else
839 p = argv[i + 2];
840 tev->args[i].name = strdup(argv[i + 2]);
841 /* TODO: parse regs and offset */
842 tev->args[i].value = strdup(p);
843 if (tev->args[i].name == NULL || tev->args[i].value == NULL) {
844 ret = -ENOMEM;
845 goto out;
848 ret = 0;
849 out:
850 argv_free(argv);
851 return ret;
854 /* Compose only probe arg */
855 int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
857 struct perf_probe_arg_field *field = pa->field;
858 int ret;
859 char *tmp = buf;
861 if (pa->name && pa->var)
862 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
863 else
864 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
865 if (ret <= 0)
866 goto error;
867 tmp += ret;
868 len -= ret;
870 while (field) {
871 if (field->name[0] == '[')
872 ret = e_snprintf(tmp, len, "%s", field->name);
873 else
874 ret = e_snprintf(tmp, len, "%s%s",
875 field->ref ? "->" : ".", field->name);
876 if (ret <= 0)
877 goto error;
878 tmp += ret;
879 len -= ret;
880 field = field->next;
883 if (pa->type) {
884 ret = e_snprintf(tmp, len, ":%s", pa->type);
885 if (ret <= 0)
886 goto error;
887 tmp += ret;
888 len -= ret;
891 return tmp - buf;
892 error:
893 pr_debug("Failed to synthesize perf probe argument: %s",
894 strerror(-ret));
895 return ret;
898 /* Compose only probe point (not argument) */
899 static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
901 char *buf, *tmp;
902 char offs[32] = "", line[32] = "", file[32] = "";
903 int ret, len;
905 buf = zalloc(MAX_CMDLEN);
906 if (buf == NULL) {
907 ret = -ENOMEM;
908 goto error;
910 if (pp->offset) {
911 ret = e_snprintf(offs, 32, "+%lu", pp->offset);
912 if (ret <= 0)
913 goto error;
915 if (pp->line) {
916 ret = e_snprintf(line, 32, ":%d", pp->line);
917 if (ret <= 0)
918 goto error;
920 if (pp->file) {
921 len = strlen(pp->file) - 31;
922 if (len < 0)
923 len = 0;
924 tmp = strchr(pp->file + len, '/');
925 if (!tmp)
926 tmp = pp->file + len;
927 ret = e_snprintf(file, 32, "@%s", tmp + 1);
928 if (ret <= 0)
929 goto error;
932 if (pp->function)
933 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
934 offs, pp->retprobe ? "%return" : "", line,
935 file);
936 else
937 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
938 if (ret <= 0)
939 goto error;
941 return buf;
942 error:
943 pr_debug("Failed to synthesize perf probe point: %s",
944 strerror(-ret));
945 if (buf)
946 free(buf);
947 return NULL;
951 static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
952 char **buf, size_t *buflen,
953 int depth)
955 int ret;
956 if (ref->next) {
957 depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
958 buflen, depth + 1);
959 if (depth < 0)
960 goto out;
963 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
964 if (ret < 0)
965 depth = ret;
966 else {
967 *buf += ret;
968 *buflen -= ret;
970 out:
971 return depth;
975 static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
976 char *buf, size_t buflen)
978 struct probe_trace_arg_ref *ref = arg->ref;
979 int ret, depth = 0;
980 char *tmp = buf;
982 /* Argument name or separator */
983 if (arg->name)
984 ret = e_snprintf(buf, buflen, " %s=", arg->name);
985 else
986 ret = e_snprintf(buf, buflen, " ");
987 if (ret < 0)
988 return ret;
989 buf += ret;
990 buflen -= ret;
992 if (arg->value[0] == '@' && arg->ref)
993 ref = ref->next;
995 /* Dereferencing arguments */
996 if (ref) {
997 depth = __synthesize_probe_trace_arg_ref(ref, &buf,
998 &buflen, 1);
999 if (depth < 0)
1000 return depth;
1003 /* Print argument value */
1004 if (arg->value[0] == '@' && arg->ref)
1005 ret = e_snprintf(buf, buflen, "%s%+ld", arg->value,
1006 arg->ref->offset);
1007 else
1008 ret = e_snprintf(buf, buflen, "%s", arg->value);
1009 if (ret < 0)
1010 return ret;
1011 buf += ret;
1012 buflen -= ret;
1014 /* Closing */
1015 while (depth--) {
1016 ret = e_snprintf(buf, buflen, ")");
1017 if (ret < 0)
1018 return ret;
1019 buf += ret;
1020 buflen -= ret;
1022 /* Print argument type */
1023 if (arg->type) {
1024 ret = e_snprintf(buf, buflen, ":%s", arg->type);
1025 if (ret <= 0)
1026 return ret;
1027 buf += ret;
1030 return buf - tmp;
1033 char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1035 struct probe_trace_point *tp = &tev->point;
1036 char *buf;
1037 int i, len, ret;
1039 buf = zalloc(MAX_CMDLEN);
1040 if (buf == NULL)
1041 return NULL;
1043 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu",
1044 tp->retprobe ? 'r' : 'p',
1045 tev->group, tev->event,
1046 tp->symbol, tp->offset);
1047 if (len <= 0)
1048 goto error;
1050 for (i = 0; i < tev->nargs; i++) {
1051 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
1052 MAX_CMDLEN - len);
1053 if (ret <= 0)
1054 goto error;
1055 len += ret;
1058 return buf;
1059 error:
1060 free(buf);
1061 return NULL;
1064 static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1065 struct perf_probe_event *pev)
1067 char buf[64] = "";
1068 int i, ret;
1070 /* Convert event/group name */
1071 pev->event = strdup(tev->event);
1072 pev->group = strdup(tev->group);
1073 if (pev->event == NULL || pev->group == NULL)
1074 return -ENOMEM;
1076 /* Convert trace_point to probe_point */
1077 ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point);
1078 if (ret < 0)
1079 return ret;
1081 /* Convert trace_arg to probe_arg */
1082 pev->nargs = tev->nargs;
1083 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1084 if (pev->args == NULL)
1085 return -ENOMEM;
1086 for (i = 0; i < tev->nargs && ret >= 0; i++) {
1087 if (tev->args[i].name)
1088 pev->args[i].name = strdup(tev->args[i].name);
1089 else {
1090 ret = synthesize_probe_trace_arg(&tev->args[i],
1091 buf, 64);
1092 pev->args[i].name = strdup(buf);
1094 if (pev->args[i].name == NULL && ret >= 0)
1095 ret = -ENOMEM;
1098 if (ret < 0)
1099 clear_perf_probe_event(pev);
1101 return ret;
1104 void clear_perf_probe_event(struct perf_probe_event *pev)
1106 struct perf_probe_point *pp = &pev->point;
1107 struct perf_probe_arg_field *field, *next;
1108 int i;
1110 if (pev->event)
1111 free(pev->event);
1112 if (pev->group)
1113 free(pev->group);
1114 if (pp->file)
1115 free(pp->file);
1116 if (pp->function)
1117 free(pp->function);
1118 if (pp->lazy_line)
1119 free(pp->lazy_line);
1120 for (i = 0; i < pev->nargs; i++) {
1121 if (pev->args[i].name)
1122 free(pev->args[i].name);
1123 if (pev->args[i].var)
1124 free(pev->args[i].var);
1125 if (pev->args[i].type)
1126 free(pev->args[i].type);
1127 field = pev->args[i].field;
1128 while (field) {
1129 next = field->next;
1130 if (field->name)
1131 free(field->name);
1132 free(field);
1133 field = next;
1136 if (pev->args)
1137 free(pev->args);
1138 memset(pev, 0, sizeof(*pev));
1141 static void clear_probe_trace_event(struct probe_trace_event *tev)
1143 struct probe_trace_arg_ref *ref, *next;
1144 int i;
1146 if (tev->event)
1147 free(tev->event);
1148 if (tev->group)
1149 free(tev->group);
1150 if (tev->point.symbol)
1151 free(tev->point.symbol);
1152 for (i = 0; i < tev->nargs; i++) {
1153 if (tev->args[i].name)
1154 free(tev->args[i].name);
1155 if (tev->args[i].value)
1156 free(tev->args[i].value);
1157 if (tev->args[i].type)
1158 free(tev->args[i].type);
1159 ref = tev->args[i].ref;
1160 while (ref) {
1161 next = ref->next;
1162 free(ref);
1163 ref = next;
1166 if (tev->args)
1167 free(tev->args);
1168 memset(tev, 0, sizeof(*tev));
1171 static int open_kprobe_events(bool readwrite)
1173 char buf[PATH_MAX];
1174 const char *__debugfs;
1175 int ret;
1177 __debugfs = debugfs_find_mountpoint();
1178 if (__debugfs == NULL) {
1179 pr_warning("Debugfs is not mounted.\n");
1180 return -ENOENT;
1183 ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs);
1184 if (ret >= 0) {
1185 pr_debug("Opening %s write=%d\n", buf, readwrite);
1186 if (readwrite && !probe_event_dry_run)
1187 ret = open(buf, O_RDWR, O_APPEND);
1188 else
1189 ret = open(buf, O_RDONLY, 0);
1192 if (ret < 0) {
1193 if (errno == ENOENT)
1194 pr_warning("kprobe_events file does not exist - please"
1195 " rebuild kernel with CONFIG_KPROBE_EVENT.\n");
1196 else
1197 pr_warning("Failed to open kprobe_events file: %s\n",
1198 strerror(errno));
1200 return ret;
1203 /* Get raw string list of current kprobe_events */
1204 static struct strlist *get_probe_trace_command_rawlist(int fd)
1206 int ret, idx;
1207 FILE *fp;
1208 char buf[MAX_CMDLEN];
1209 char *p;
1210 struct strlist *sl;
1212 sl = strlist__new(true, NULL);
1214 fp = fdopen(dup(fd), "r");
1215 while (!feof(fp)) {
1216 p = fgets(buf, MAX_CMDLEN, fp);
1217 if (!p)
1218 break;
1220 idx = strlen(p) - 1;
1221 if (p[idx] == '\n')
1222 p[idx] = '\0';
1223 ret = strlist__add(sl, buf);
1224 if (ret < 0) {
1225 pr_debug("strlist__add failed: %s\n", strerror(-ret));
1226 strlist__delete(sl);
1227 return NULL;
1230 fclose(fp);
1232 return sl;
1235 /* Show an event */
1236 static int show_perf_probe_event(struct perf_probe_event *pev)
1238 int i, ret;
1239 char buf[128];
1240 char *place;
1242 /* Synthesize only event probe point */
1243 place = synthesize_perf_probe_point(&pev->point);
1244 if (!place)
1245 return -EINVAL;
1247 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
1248 if (ret < 0)
1249 return ret;
1251 printf(" %-20s (on %s", buf, place);
1253 if (pev->nargs > 0) {
1254 printf(" with");
1255 for (i = 0; i < pev->nargs; i++) {
1256 ret = synthesize_perf_probe_arg(&pev->args[i],
1257 buf, 128);
1258 if (ret < 0)
1259 break;
1260 printf(" %s", buf);
1263 printf(")\n");
1264 free(place);
1265 return ret;
1268 /* List up current perf-probe events */
1269 int show_perf_probe_events(void)
1271 int fd, ret;
1272 struct probe_trace_event tev;
1273 struct perf_probe_event pev;
1274 struct strlist *rawlist;
1275 struct str_node *ent;
1277 setup_pager();
1278 ret = init_vmlinux();
1279 if (ret < 0)
1280 return ret;
1282 memset(&tev, 0, sizeof(tev));
1283 memset(&pev, 0, sizeof(pev));
1285 fd = open_kprobe_events(false);
1286 if (fd < 0)
1287 return fd;
1289 rawlist = get_probe_trace_command_rawlist(fd);
1290 close(fd);
1291 if (!rawlist)
1292 return -ENOENT;
1294 strlist__for_each(ent, rawlist) {
1295 ret = parse_probe_trace_command(ent->s, &tev);
1296 if (ret >= 0) {
1297 ret = convert_to_perf_probe_event(&tev, &pev);
1298 if (ret >= 0)
1299 ret = show_perf_probe_event(&pev);
1301 clear_perf_probe_event(&pev);
1302 clear_probe_trace_event(&tev);
1303 if (ret < 0)
1304 break;
1306 strlist__delete(rawlist);
1308 return ret;
1311 /* Get current perf-probe event names */
1312 static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
1314 char buf[128];
1315 struct strlist *sl, *rawlist;
1316 struct str_node *ent;
1317 struct probe_trace_event tev;
1318 int ret = 0;
1320 memset(&tev, 0, sizeof(tev));
1321 rawlist = get_probe_trace_command_rawlist(fd);
1322 sl = strlist__new(true, NULL);
1323 strlist__for_each(ent, rawlist) {
1324 ret = parse_probe_trace_command(ent->s, &tev);
1325 if (ret < 0)
1326 break;
1327 if (include_group) {
1328 ret = e_snprintf(buf, 128, "%s:%s", tev.group,
1329 tev.event);
1330 if (ret >= 0)
1331 ret = strlist__add(sl, buf);
1332 } else
1333 ret = strlist__add(sl, tev.event);
1334 clear_probe_trace_event(&tev);
1335 if (ret < 0)
1336 break;
1338 strlist__delete(rawlist);
1340 if (ret < 0) {
1341 strlist__delete(sl);
1342 return NULL;
1344 return sl;
1347 static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
1349 int ret = 0;
1350 char *buf = synthesize_probe_trace_command(tev);
1352 if (!buf) {
1353 pr_debug("Failed to synthesize probe trace event.\n");
1354 return -EINVAL;
1357 pr_debug("Writing event: %s\n", buf);
1358 if (!probe_event_dry_run) {
1359 ret = write(fd, buf, strlen(buf));
1360 if (ret <= 0)
1361 pr_warning("Failed to write event: %s\n",
1362 strerror(errno));
1364 free(buf);
1365 return ret;
1368 static int get_new_event_name(char *buf, size_t len, const char *base,
1369 struct strlist *namelist, bool allow_suffix)
1371 int i, ret;
1373 /* Try no suffix */
1374 ret = e_snprintf(buf, len, "%s", base);
1375 if (ret < 0) {
1376 pr_debug("snprintf() failed: %s\n", strerror(-ret));
1377 return ret;
1379 if (!strlist__has_entry(namelist, buf))
1380 return 0;
1382 if (!allow_suffix) {
1383 pr_warning("Error: event \"%s\" already exists. "
1384 "(Use -f to force duplicates.)\n", base);
1385 return -EEXIST;
1388 /* Try to add suffix */
1389 for (i = 1; i < MAX_EVENT_INDEX; i++) {
1390 ret = e_snprintf(buf, len, "%s_%d", base, i);
1391 if (ret < 0) {
1392 pr_debug("snprintf() failed: %s\n", strerror(-ret));
1393 return ret;
1395 if (!strlist__has_entry(namelist, buf))
1396 break;
1398 if (i == MAX_EVENT_INDEX) {
1399 pr_warning("Too many events are on the same function.\n");
1400 ret = -ERANGE;
1403 return ret;
1406 static int __add_probe_trace_events(struct perf_probe_event *pev,
1407 struct probe_trace_event *tevs,
1408 int ntevs, bool allow_suffix)
1410 int i, fd, ret;
1411 struct probe_trace_event *tev = NULL;
1412 char buf[64];
1413 const char *event, *group;
1414 struct strlist *namelist;
1416 fd = open_kprobe_events(true);
1417 if (fd < 0)
1418 return fd;
1419 /* Get current event names */
1420 namelist = get_probe_trace_event_names(fd, false);
1421 if (!namelist) {
1422 pr_debug("Failed to get current event list.\n");
1423 return -EIO;
1426 ret = 0;
1427 printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":");
1428 for (i = 0; i < ntevs; i++) {
1429 tev = &tevs[i];
1430 if (pev->event)
1431 event = pev->event;
1432 else
1433 if (pev->point.function)
1434 event = pev->point.function;
1435 else
1436 event = tev->point.symbol;
1437 if (pev->group)
1438 group = pev->group;
1439 else
1440 group = PERFPROBE_GROUP;
1442 /* Get an unused new event name */
1443 ret = get_new_event_name(buf, 64, event,
1444 namelist, allow_suffix);
1445 if (ret < 0)
1446 break;
1447 event = buf;
1449 tev->event = strdup(event);
1450 tev->group = strdup(group);
1451 if (tev->event == NULL || tev->group == NULL) {
1452 ret = -ENOMEM;
1453 break;
1455 ret = write_probe_trace_event(fd, tev);
1456 if (ret < 0)
1457 break;
1458 /* Add added event name to namelist */
1459 strlist__add(namelist, event);
1461 /* Trick here - save current event/group */
1462 event = pev->event;
1463 group = pev->group;
1464 pev->event = tev->event;
1465 pev->group = tev->group;
1466 show_perf_probe_event(pev);
1467 /* Trick here - restore current event/group */
1468 pev->event = (char *)event;
1469 pev->group = (char *)group;
1472 * Probes after the first probe which comes from same
1473 * user input are always allowed to add suffix, because
1474 * there might be several addresses corresponding to
1475 * one code line.
1477 allow_suffix = true;
1480 if (ret >= 0) {
1481 /* Show how to use the event. */
1482 printf("\nYou can now use it on all perf tools, such as:\n\n");
1483 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
1484 tev->event);
1487 strlist__delete(namelist);
1488 close(fd);
1489 return ret;
1492 static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1493 struct probe_trace_event **tevs,
1494 int max_tevs)
1496 struct symbol *sym;
1497 int ret = 0, i;
1498 struct probe_trace_event *tev;
1500 /* Convert perf_probe_event with debuginfo */
1501 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs);
1502 if (ret != 0)
1503 return ret;
1505 /* Allocate trace event buffer */
1506 tev = *tevs = zalloc(sizeof(struct probe_trace_event));
1507 if (tev == NULL)
1508 return -ENOMEM;
1510 /* Copy parameters */
1511 tev->point.symbol = strdup(pev->point.function);
1512 if (tev->point.symbol == NULL) {
1513 ret = -ENOMEM;
1514 goto error;
1516 tev->point.offset = pev->point.offset;
1517 tev->point.retprobe = pev->point.retprobe;
1518 tev->nargs = pev->nargs;
1519 if (tev->nargs) {
1520 tev->args = zalloc(sizeof(struct probe_trace_arg)
1521 * tev->nargs);
1522 if (tev->args == NULL) {
1523 ret = -ENOMEM;
1524 goto error;
1526 for (i = 0; i < tev->nargs; i++) {
1527 if (pev->args[i].name) {
1528 tev->args[i].name = strdup(pev->args[i].name);
1529 if (tev->args[i].name == NULL) {
1530 ret = -ENOMEM;
1531 goto error;
1534 tev->args[i].value = strdup(pev->args[i].var);
1535 if (tev->args[i].value == NULL) {
1536 ret = -ENOMEM;
1537 goto error;
1539 if (pev->args[i].type) {
1540 tev->args[i].type = strdup(pev->args[i].type);
1541 if (tev->args[i].type == NULL) {
1542 ret = -ENOMEM;
1543 goto error;
1549 /* Currently just checking function name from symbol map */
1550 sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION],
1551 tev->point.symbol, NULL);
1552 if (!sym) {
1553 pr_warning("Kernel symbol \'%s\' not found.\n",
1554 tev->point.symbol);
1555 ret = -ENOENT;
1556 goto error;
1559 return 1;
1560 error:
1561 clear_probe_trace_event(tev);
1562 free(tev);
1563 *tevs = NULL;
1564 return ret;
1567 struct __event_package {
1568 struct perf_probe_event *pev;
1569 struct probe_trace_event *tevs;
1570 int ntevs;
1573 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1574 bool force_add, int max_tevs)
1576 int i, j, ret;
1577 struct __event_package *pkgs;
1579 pkgs = zalloc(sizeof(struct __event_package) * npevs);
1580 if (pkgs == NULL)
1581 return -ENOMEM;
1583 /* Init vmlinux path */
1584 ret = init_vmlinux();
1585 if (ret < 0) {
1586 free(pkgs);
1587 return ret;
1590 /* Loop 1: convert all events */
1591 for (i = 0; i < npevs; i++) {
1592 pkgs[i].pev = &pevs[i];
1593 /* Convert with or without debuginfo */
1594 ret = convert_to_probe_trace_events(pkgs[i].pev,
1595 &pkgs[i].tevs, max_tevs);
1596 if (ret < 0)
1597 goto end;
1598 pkgs[i].ntevs = ret;
1601 /* Loop 2: add all events */
1602 for (i = 0; i < npevs && ret >= 0; i++)
1603 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
1604 pkgs[i].ntevs, force_add);
1605 end:
1606 /* Loop 3: cleanup and free trace events */
1607 for (i = 0; i < npevs; i++) {
1608 for (j = 0; j < pkgs[i].ntevs; j++)
1609 clear_probe_trace_event(&pkgs[i].tevs[j]);
1610 free(pkgs[i].tevs);
1612 free(pkgs);
1614 return ret;
1617 static int __del_trace_probe_event(int fd, struct str_node *ent)
1619 char *p;
1620 char buf[128];
1621 int ret;
1623 /* Convert from perf-probe event to trace-probe event */
1624 ret = e_snprintf(buf, 128, "-:%s", ent->s);
1625 if (ret < 0)
1626 goto error;
1628 p = strchr(buf + 2, ':');
1629 if (!p) {
1630 pr_debug("Internal error: %s should have ':' but not.\n",
1631 ent->s);
1632 ret = -ENOTSUP;
1633 goto error;
1635 *p = '/';
1637 pr_debug("Writing event: %s\n", buf);
1638 ret = write(fd, buf, strlen(buf));
1639 if (ret < 0)
1640 goto error;
1642 printf("Remove event: %s\n", ent->s);
1643 return 0;
1644 error:
1645 pr_warning("Failed to delete event: %s\n", strerror(-ret));
1646 return ret;
1649 static int del_trace_probe_event(int fd, const char *group,
1650 const char *event, struct strlist *namelist)
1652 char buf[128];
1653 struct str_node *ent, *n;
1654 int found = 0, ret = 0;
1656 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1657 if (ret < 0) {
1658 pr_err("Failed to copy event.");
1659 return ret;
1662 if (strpbrk(buf, "*?")) { /* Glob-exp */
1663 strlist__for_each_safe(ent, n, namelist)
1664 if (strglobmatch(ent->s, buf)) {
1665 found++;
1666 ret = __del_trace_probe_event(fd, ent);
1667 if (ret < 0)
1668 break;
1669 strlist__remove(namelist, ent);
1671 } else {
1672 ent = strlist__find(namelist, buf);
1673 if (ent) {
1674 found++;
1675 ret = __del_trace_probe_event(fd, ent);
1676 if (ret >= 0)
1677 strlist__remove(namelist, ent);
1680 if (found == 0 && ret >= 0)
1681 pr_info("Info: Event \"%s\" does not exist.\n", buf);
1683 return ret;
1686 int del_perf_probe_events(struct strlist *dellist)
1688 int fd, ret = 0;
1689 const char *group, *event;
1690 char *p, *str;
1691 struct str_node *ent;
1692 struct strlist *namelist;
1694 fd = open_kprobe_events(true);
1695 if (fd < 0)
1696 return fd;
1698 /* Get current event names */
1699 namelist = get_probe_trace_event_names(fd, true);
1700 if (namelist == NULL)
1701 return -EINVAL;
1703 strlist__for_each(ent, dellist) {
1704 str = strdup(ent->s);
1705 if (str == NULL) {
1706 ret = -ENOMEM;
1707 break;
1709 pr_debug("Parsing: %s\n", str);
1710 p = strchr(str, ':');
1711 if (p) {
1712 group = str;
1713 *p = '\0';
1714 event = p + 1;
1715 } else {
1716 group = "*";
1717 event = str;
1719 pr_debug("Group: %s, Event: %s\n", group, event);
1720 ret = del_trace_probe_event(fd, group, event, namelist);
1721 free(str);
1722 if (ret < 0)
1723 break;
1725 strlist__delete(namelist);
1726 close(fd);
1728 return ret;