probe-event.c 35.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * probe-event.c : perf-probe definition to kprobe_events format converter
 *
 * Written by Masami Hiramatsu <mhiramat@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 */

#define _GNU_SOURCE
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
32 33
#include <stdarg.h>
#include <limits.h>
34 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 44
#include "symbol.h"
#include "thread.h"
45
#include "debugfs.h"
46
#include "trace-event.h"	/* For __unused */
47
#include "probe-event.h"
48
#include "probe-finder.h"
49 50 51 52 53

#define MAX_CMDLEN 256
#define MAX_PROBE_ARGS 128
#define PERFPROBE_GROUP "probe"

54 55
bool probe_event_dry_run;	/* Dry run flag */

56
#define semantic_error(msg ...) pr_err("Semantic error :" msg)
57

58
/* If there is no space to write, returns -E2BIG. */
59 60 61
static int e_snprintf(char *str, size_t size, const char *format, ...)
	__attribute__((format(printf, 3, 4)));

62 63 64 65 66 67 68 69 70 71 72 73
static int e_snprintf(char *str, size_t size, const char *format, ...)
{
	int ret;
	va_list ap;
	va_start(ap, format);
	ret = vsnprintf(str, size, format, ap);
	va_end(ap);
	if (ret >= (int)size)
		ret = -E2BIG;
	return ret;
}

74
static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
75 76 77
static struct map_groups kmap_groups;
static struct map *kmaps[MAP__NR_TYPES];

78
/* Initialize symbol maps and path of vmlinux */
79
static int init_vmlinux(void)
80
{
81 82
	int ret;

83 84 85 86 87
	symbol_conf.sort_by_name = true;
	if (symbol_conf.vmlinux_name == NULL)
		symbol_conf.try_vmlinux_path = true;
	else
		pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
88 89 90 91 92
	ret = symbol__init();
	if (ret < 0) {
		pr_debug("Failed to init symbol map.\n");
		goto out;
	}
93 94

	map_groups__init(&kmap_groups);
95 96 97 98 99 100 101 102
	ret = map_groups__create_kernel_maps(&kmap_groups, kmaps);
	if (ret < 0)
		pr_debug("Failed to create kernel maps.\n");

out:
	if (ret < 0)
		pr_warning("Failed to init vmlinux path.\n");
	return ret;
103 104
}

105
#ifdef DWARF_SUPPORT
106 107 108 109 110 111 112 113 114
static int open_vmlinux(void)
{
	if (map__load(kmaps[MAP__FUNCTION], NULL) < 0) {
		pr_debug("Failed to load kernel map.\n");
		return -EINVAL;
	}
	pr_debug("Try to open %s\n", kmaps[MAP__FUNCTION]->dso->long_name);
	return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY);
}
115

116 117 118
/* Convert trace point to probe point with debuginfo */
static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
				       struct perf_probe_point *pp)
119 120
{
	struct symbol *sym;
121
	int fd, ret = -ENOENT;
122 123 124 125 126

	sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION],
				       tp->symbol, NULL);
	if (sym) {
		fd = open_vmlinux();
127 128 129 130 131
		if (fd >= 0) {
			ret = find_perf_probe_point(fd,
						 sym->start + tp->offset, pp);
			close(fd);
		}
132 133
	}
	if (ret <= 0) {
134 135
		pr_debug("Failed to find corresponding probes from "
			 "debuginfo. Use kprobe event information.\n");
136 137 138
		pp->function = strdup(tp->symbol);
		if (pp->function == NULL)
			return -ENOMEM;
139 140 141
		pp->offset = tp->offset;
	}
	pp->retprobe = tp->retprobe;
142 143

	return 0;
144 145 146 147 148 149 150 151 152 153 154
}

/* Try to find perf_probe_event with debuginfo */
static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
					   struct kprobe_trace_event **tevs)
{
	bool need_dwarf = perf_probe_event_need_dwarf(pev);
	int fd, ntevs;

	fd = open_vmlinux();
	if (fd < 0) {
155 156 157 158
		if (need_dwarf) {
			pr_warning("Failed to open debuginfo file.\n");
			return fd;
		}
159 160 161 162 163 164 165 166
		pr_debug("Could not open vmlinux. Try to use symbols.\n");
		return 0;
	}

	/* Searching trace events corresponding to probe event */
	ntevs = find_kprobe_trace_events(fd, pev, tevs);
	close(fd);

167 168
	if (ntevs > 0) {	/* Succeeded to find trace events */
		pr_debug("find %d kprobe_trace_events.\n", ntevs);
169
		return ntevs;
170
	}
171

172 173 174 175 176 177
	if (ntevs == 0)	{	/* No error but failed to find probe point. */
		pr_warning("Probe point '%s' not found.\n",
			   synthesize_perf_probe_point(&pev->point));
		return -ENOENT;
	}
	/* Error path : ntevs < 0 */
178
	if (need_dwarf) {
179
		if (ntevs == -EBADF)
180 181
			pr_warning("No dwarf info found in the vmlinux - "
				"please rebuild with CONFIG_DEBUG_INFO=y.\n");
182
		return ntevs;
183 184 185 186 187 188 189 190 191
	}
	pr_debug("An error occurred in debuginfo analysis."
		 " Try to use symbols.\n");
	return 0;
}

#define LINEBUF_SIZE 256
#define NR_ADDITIONAL_LINES 2

192
static int show_one_line(FILE *fp, int l, bool skip, bool show_num)
193 194 195 196 197 198 199 200
{
	char buf[LINEBUF_SIZE];
	const char *color = PERF_COLOR_BLUE;

	if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
		goto error;
	if (!skip) {
		if (show_num)
201
			fprintf(stdout, "%7d  %s", l, buf);
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
		else
			color_fprintf(stdout, color, "         %s", buf);
	}

	while (strlen(buf) == LINEBUF_SIZE - 1 &&
	       buf[LINEBUF_SIZE - 2] != '\n') {
		if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
			goto error;
		if (!skip) {
			if (show_num)
				fprintf(stdout, "%s", buf);
			else
				color_fprintf(stdout, color, "%s", buf);
		}
	}
217 218

	return 0;
219 220
error:
	if (feof(fp))
221
		pr_warning("Source file is shorter than expected.\n");
222
	else
223 224 225
		pr_warning("File read error: %s\n", strerror(errno));

	return -1;
226 227 228 229 230 231
}

/*
 * Show line-range always requires debuginfo to find source file and
 * line number.
 */
232
int show_line_range(struct line_range *lr)
233
{
234
	int l = 1;
235 236 237 238 239
	struct line_node *ln;
	FILE *fp;
	int fd, ret;

	/* Search a line range */
240 241 242 243
	ret = init_vmlinux();
	if (ret < 0)
		return ret;

244
	fd = open_vmlinux();
245 246 247 248 249
	if (fd < 0) {
		pr_warning("Failed to open debuginfo file.\n");
		return fd;
	}

250 251
	ret = find_line_range(fd, lr);
	close(fd);
252 253 254 255 256 257 258
	if (ret == 0) {
		pr_warning("Specified source line is not found.\n");
		return -ENOENT;
	} else if (ret < 0) {
		pr_warning("Debuginfo analysis failed. (%d)\n", ret);
		return ret;
	}
259 260 261 262 263 264 265 266 267 268

	setup_pager();

	if (lr->function)
		fprintf(stdout, "<%s:%d>\n", lr->function,
			lr->start - lr->offset);
	else
		fprintf(stdout, "<%s:%d>\n", lr->file, lr->start);

	fp = fopen(lr->path, "r");
269 270 271 272 273
	if (fp == NULL) {
		pr_warning("Failed to open %s: %s\n", lr->path,
			   strerror(errno));
		return -errno;
	}
274
	/* Skip to starting line number */
275 276 277 278
	while (l < lr->start && ret >= 0)
		ret = show_one_line(fp, l++, true, false);
	if (ret < 0)
		goto end;
279 280

	list_for_each_entry(ln, &lr->line_list, list) {
281 282 283 284 285 286 287 288
		while (ln->line > l && ret >= 0)
			ret = show_one_line(fp, (l++) - lr->offset,
					    false, false);
		if (ret >= 0)
			ret = show_one_line(fp, (l++) - lr->offset,
					    false, true);
		if (ret < 0)
			goto end;
289 290 291 292
	}

	if (lr->end == INT_MAX)
		lr->end = l + NR_ADDITIONAL_LINES;
293
	while (l <= lr->end && !feof(fp) && ret >= 0)
294 295
		ret = show_one_line(fp, (l++) - lr->offset, false, false);
end:
296
	fclose(fp);
297
	return ret;
298 299 300 301
}

#else	/* !DWARF_SUPPORT */

302
static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
303 304
					struct perf_probe_point *pp)
{
305 306 307
	pp->function = strdup(tp->symbol);
	if (pp->function == NULL)
		return -ENOMEM;
308 309
	pp->offset = tp->offset;
	pp->retprobe = tp->retprobe;
310 311

	return 0;
312 313 314 315 316
}

static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
				struct kprobe_trace_event **tevs __unused)
{
317 318 319 320
	if (perf_probe_event_need_dwarf(pev)) {
		pr_warning("Debuginfo-analysis is not supported.\n");
		return -ENOSYS;
	}
321 322 323
	return 0;
}

324
int show_line_range(struct line_range *lr __unused)
325
{
326 327
	pr_warning("Debuginfo-analysis is not supported.\n");
	return -ENOSYS;
328 329
}

330 331
#endif

332
int parse_line_range_desc(const char *arg, struct line_range *lr)
333 334 335 336 337 338 339 340 341 342
{
	const char *ptr;
	char *tmp;
	/*
	 * <Syntax>
	 * SRC:SLN[+NUM|-ELN]
	 * FUNC[:SLN[+NUM|-ELN]]
	 */
	ptr = strchr(arg, ':');
	if (ptr) {
343
		lr->start = (int)strtoul(ptr + 1, &tmp, 0);
344
		if (*tmp == '+') {
345
			lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0);
346 347 348 349 350 351 352
			lr->end--;	/*
					 * Adjust the number of lines here.
					 * If the number of lines == 1, the
					 * the end of line should be equal to
					 * the start of line.
					 */
		} else if (*tmp == '-')
353
			lr->end = (int)strtoul(tmp + 1, &tmp, 0);
354
		else
355 356 357
			lr->end = INT_MAX;
		pr_debug("Line range is %d to %d\n", lr->start, lr->end);
		if (lr->start > lr->end) {
358
			semantic_error("Start line must be smaller"
359 360 361 362 363
				       " than end line.\n");
			return -EINVAL;
		}
		if (*tmp != '\0') {
			semantic_error("Tailing with invalid character '%d'.\n",
364
				       *tmp);
365 366
			return -EINVAL;
		}
367
		tmp = strndup(arg, (ptr - arg));
368
	} else {
369
		tmp = strdup(arg);
370 371
		lr->end = INT_MAX;
	}
372 373 374

	if (tmp == NULL)
		return -ENOMEM;
375 376 377 378 379

	if (strchr(tmp, '.'))
		lr->file = tmp;
	else
		lr->function = tmp;
380 381

	return 0;
382 383
}

384 385 386 387 388 389 390 391 392 393 394 395
/* Check the name is good for event/group */
static bool check_event_name(const char *name)
{
	if (!isalpha(*name) && *name != '_')
		return false;
	while (*++name != '\0') {
		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
			return false;
	}
	return true;
}

396
/* Parse probepoint definition. */
397
static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
398
{
399
	struct perf_probe_point *pp = &pev->point;
400 401 402 403
	char *ptr, *tmp;
	char c, nc = 0;
	/*
	 * <Syntax>
404 405
	 * perf probe [EVENT=]SRC[:LN|;PTN]
	 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
406 407
	 *
	 * TODO:Group name support
408 409
	 */

410 411
	ptr = strpbrk(arg, ";=@+%");
	if (ptr && *ptr == '=') {	/* Event name */
412 413
		*ptr = '\0';
		tmp = ptr + 1;
414 415 416 417 418
		if (strchr(arg, ':')) {
			semantic_error("Group name is not supported yet.\n");
			return -ENOTSUP;
		}
		if (!check_event_name(arg)) {
419
			semantic_error("%s is bad for event name -it must "
420 421 422
				       "follow C symbol-naming rule.\n", arg);
			return -EINVAL;
		}
423 424 425
		pev->event = strdup(arg);
		if (pev->event == NULL)
			return -ENOMEM;
426
		pev->group = NULL;
427 428 429
		arg = tmp;
	}

430
	ptr = strpbrk(arg, ";:+@%");
431 432 433 434 435
	if (ptr) {
		nc = *ptr;
		*ptr++ = '\0';
	}

436 437 438 439
	tmp = strdup(arg);
	if (tmp == NULL)
		return -ENOMEM;

440
	/* Check arg is function or file and copy it */
441 442
	if (strchr(tmp, '.'))	/* File */
		pp->file = tmp;
443
	else			/* Function */
444
		pp->function = tmp;
445 446 447 448 449

	/* Parse other options */
	while (ptr) {
		arg = ptr;
		c = nc;
450
		if (c == ';') {	/* Lazy pattern must be the last part */
451 452 453
			pp->lazy_line = strdup(arg);
			if (pp->lazy_line == NULL)
				return -ENOMEM;
454 455 456
			break;
		}
		ptr = strpbrk(arg, ";:+@%");
457 458 459 460 461 462 463
		if (ptr) {
			nc = *ptr;
			*ptr++ = '\0';
		}
		switch (c) {
		case ':':	/* Line number */
			pp->line = strtoul(arg, &tmp, 0);
464
			if (*tmp != '\0') {
465
				semantic_error("There is non-digit char"
466 467 468
					       " in line number.\n");
				return -EINVAL;
			}
469 470 471
			break;
		case '+':	/* Byte offset from a symbol */
			pp->offset = strtoul(arg, &tmp, 0);
472
			if (*tmp != '\0') {
473
				semantic_error("There is non-digit character"
474 475 476
						" in offset.\n");
				return -EINVAL;
			}
477 478
			break;
		case '@':	/* File name */
479 480 481 482
			if (pp->file) {
				semantic_error("SRC@SRC is not allowed.\n");
				return -EINVAL;
			}
483 484 485
			pp->file = strdup(arg);
			if (pp->file == NULL)
				return -ENOMEM;
486 487 488 489
			break;
		case '%':	/* Probe places */
			if (strcmp(arg, "return") == 0) {
				pp->retprobe = 1;
490 491 492 493
			} else {	/* Others not supported yet */
				semantic_error("%%%s is not supported.\n", arg);
				return -ENOTSUP;
			}
494
			break;
495 496 497 498
		default:	/* Buggy case */
			pr_err("This program has a bug at %s:%d.\n",
				__FILE__, __LINE__);
			return -ENOTSUP;
499 500 501 502 503
			break;
		}
	}

	/* Exclusion check */
504
	if (pp->lazy_line && pp->line) {
505
		semantic_error("Lazy pattern can't be used with line number.");
506 507
		return -EINVAL;
	}
508

509
	if (pp->lazy_line && pp->offset) {
510
		semantic_error("Lazy pattern can't be used with offset.");
511 512
		return -EINVAL;
	}
513

514
	if (pp->line && pp->offset) {
515
		semantic_error("Offset can't be used with line number.");
516 517
		return -EINVAL;
	}
518

519
	if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
520 521
		semantic_error("File always requires line number or "
			       "lazy pattern.");
522 523
		return -EINVAL;
	}
524

525
	if (pp->offset && !pp->function) {
526
		semantic_error("Offset requires an entry function.");
527 528
		return -EINVAL;
	}
529

530
	if (pp->retprobe && !pp->function) {
531
		semantic_error("Return probe requires an entry function.");
532 533
		return -EINVAL;
	}
534

535
	if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
536 537
		semantic_error("Offset/Line/Lazy pattern can't be used with "
			       "return probe.");
538 539
		return -EINVAL;
	}
540

541
	pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
542 543
		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
		 pp->lazy_line);
544
	return 0;
545 546
}

547
/* Parse perf-probe event argument */
548
static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
549
{
550
	char *tmp;
551 552 553 554
	struct perf_probe_arg_field **fieldp;

	pr_debug("parsing arg: %s into ", str);

555 556
	tmp = strchr(str, '=');
	if (tmp) {
557 558 559
		arg->name = strndup(str, tmp - str);
		if (arg->name == NULL)
			return -ENOMEM;
560
		pr_debug("name:%s ", arg->name);
561 562 563
		str = tmp + 1;
	}

564 565 566
	tmp = strchr(str, ':');
	if (tmp) {	/* Type setting */
		*tmp = '\0';
567 568 569
		arg->type = strdup(tmp + 1);
		if (arg->type == NULL)
			return -ENOMEM;
570 571 572
		pr_debug("type:%s ", arg->type);
	}

573 574 575
	tmp = strpbrk(str, "-.");
	if (!is_c_varname(str) || !tmp) {
		/* A variable, register, symbol or special value */
576 577 578
		arg->var = strdup(str);
		if (arg->var == NULL)
			return -ENOMEM;
579
		pr_debug("%s\n", arg->var);
580
		return 0;
581 582 583
	}

	/* Structure fields */
584 585 586
	arg->var = strndup(str, tmp - str);
	if (arg->var == NULL)
		return -ENOMEM;
587
	pr_debug("%s, ", arg->var);
588 589 590
	fieldp = &arg->field;

	do {
591 592 593
		*fieldp = zalloc(sizeof(struct perf_probe_arg_field));
		if (*fieldp == NULL)
			return -ENOMEM;
594 595 596 597 598 599
		if (*tmp == '.') {
			str = tmp + 1;
			(*fieldp)->ref = false;
		} else if (tmp[1] == '>') {
			str = tmp + 2;
			(*fieldp)->ref = true;
600 601 602 603
		} else {
			semantic_error("Argument parse error: %s\n", str);
			return -EINVAL;
		}
604 605 606

		tmp = strpbrk(str, "-.");
		if (tmp) {
607 608 609
			(*fieldp)->name = strndup(str, tmp - str);
			if ((*fieldp)->name == NULL)
				return -ENOMEM;
610 611 612 613
			pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
			fieldp = &(*fieldp)->next;
		}
	} while (tmp);
614 615 616
	(*fieldp)->name = strdup(str);
	if ((*fieldp)->name == NULL)
		return -ENOMEM;
617
	pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
618 619

	/* If no name is specified, set the last field name */
620 621 622 623 624
	if (!arg->name) {
		arg->name = strdup((*fieldp)->name);
		if (arg->name == NULL)
			return -ENOMEM;
	}
625
	return 0;
626 627
}

628
/* Parse perf-probe event command */
629
int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
630
{
631
	char **argv;
632
	int argc, i, ret = 0;
633

634
	argv = argv_split(cmd, &argc);
635 636 637 638 639 640 641 642 643
	if (!argv) {
		pr_debug("Failed to split arguments.\n");
		return -ENOMEM;
	}
	if (argc - 1 > MAX_PROBE_ARGS) {
		semantic_error("Too many probe arguments (%d).\n", argc - 1);
		ret = -ERANGE;
		goto out;
	}
644
	/* Parse probe point */
645 646 647
	ret = parse_perf_probe_point(argv[0], pev);
	if (ret < 0)
		goto out;
648

649
	/* Copy arguments and ensure return probe has no C argument */
650
	pev->nargs = argc - 1;
651 652 653 654 655
	pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
	if (pev->args == NULL) {
		ret = -ENOMEM;
		goto out;
	}
656 657 658 659
	for (i = 0; i < pev->nargs && ret >= 0; i++) {
		ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
		if (ret >= 0 &&
		    is_c_varname(pev->args[i].var) && pev->point.retprobe) {
660
			semantic_error("You can't specify local variable for"
661 662 663
				       " kretprobe.\n");
			ret = -EINVAL;
		}
664
	}
665
out:
666
	argv_free(argv);
667 668

	return ret;
669 670
}

671 672 673 674 675 676 677 678 679
/* Return true if this perf_probe_event requires debuginfo */
bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
{
	int i;

	if (pev->point.file || pev->point.line || pev->point.lazy_line)
		return true;

	for (i = 0; i < pev->nargs; i++)
680
		if (is_c_varname(pev->args[i].var))
681 682 683 684 685
			return true;

	return false;
}

686
/* Parse kprobe_events event into struct probe_point */
687
int parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev)
688
{
689
	struct kprobe_trace_point *tp = &tev->point;
690 691 692 693 694
	char pr;
	char *p;
	int ret, i, argc;
	char **argv;

695 696
	pr_debug("Parsing kprobe_events: %s\n", cmd);
	argv = argv_split(cmd, &argc);
697 698 699 700 701 702 703 704 705
	if (!argv) {
		pr_debug("Failed to split arguments.\n");
		return -ENOMEM;
	}
	if (argc < 2) {
		semantic_error("Too few probe arguments.\n");
		ret = -ERANGE;
		goto out;
	}
706 707

	/* Scan event and group name. */
708
	ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
709 710
		     &pr, (float *)(void *)&tev->group,
		     (float *)(void *)&tev->event);
711 712 713 714 715
	if (ret != 3) {
		semantic_error("Failed to parse event name: %s\n", argv[0]);
		ret = -EINVAL;
		goto out;
	}
716
	pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
717

718
	tp->retprobe = (pr == 'r');
719 720

	/* Scan function name and offset */
721 722
	ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol,
		     &tp->offset);
723
	if (ret == 1)
724
		tp->offset = 0;
725

726
	tev->nargs = argc - 2;
727 728 729 730 731
	tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
	if (tev->args == NULL) {
		ret = -ENOMEM;
		goto out;
	}
732
	for (i = 0; i < tev->nargs; i++) {
733 734
		p = strchr(argv[i + 2], '=');
		if (p)	/* We don't need which register is assigned. */
735 736 737
			*p++ = '\0';
		else
			p = argv[i + 2];
738
		tev->args[i].name = strdup(argv[i + 2]);
739
		/* TODO: parse regs and offset */
740 741 742 743 744
		tev->args[i].value = strdup(p);
		if (tev->args[i].name == NULL || tev->args[i].value == NULL) {
			ret = -ENOMEM;
			goto out;
		}
745
	}
746 747
	ret = 0;
out:
748
	argv_free(argv);
749
	return ret;
750 751
}

752 753 754 755 756 757 758
/* Compose only probe arg */
int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
{
	struct perf_probe_arg_field *field = pa->field;
	int ret;
	char *tmp = buf;

759 760 761 762
	if (pa->name && pa->var)
		ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
	else
		ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
763 764 765 766 767 768 769 770 771 772 773 774 775 776
	if (ret <= 0)
		goto error;
	tmp += ret;
	len -= ret;

	while (field) {
		ret = e_snprintf(tmp, len, "%s%s", field->ref ? "->" : ".",
				 field->name);
		if (ret <= 0)
			goto error;
		tmp += ret;
		len -= ret;
		field = field->next;
	}
777 778 779 780 781 782 783 784 785

	if (pa->type) {
		ret = e_snprintf(tmp, len, ":%s", pa->type);
		if (ret <= 0)
			goto error;
		tmp += ret;
		len -= ret;
	}

786 787
	return tmp - buf;
error:
788 789 790
	pr_debug("Failed to synthesize perf probe argument: %s",
		 strerror(-ret));
	return ret;
791 792
}

793 794
/* Compose only probe point (not argument) */
static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
795
{
796 797 798
	char *buf, *tmp;
	char offs[32] = "", line[32] = "", file[32] = "";
	int ret, len;
799

800 801 802 803 804
	buf = zalloc(MAX_CMDLEN);
	if (buf == NULL) {
		ret = -ENOMEM;
		goto error;
	}
805
	if (pp->offset) {
806
		ret = e_snprintf(offs, 32, "+%lu", pp->offset);
807 808 809 810
		if (ret <= 0)
			goto error;
	}
	if (pp->line) {
811 812 813 814 815
		ret = e_snprintf(line, 32, ":%d", pp->line);
		if (ret <= 0)
			goto error;
	}
	if (pp->file) {
816
		len = strlen(pp->file) - 31;
817 818 819 820
		if (len < 0)
			len = 0;
		tmp = strchr(pp->file + len, '/');
		if (!tmp)
821
			tmp = pp->file + len;
822
		ret = e_snprintf(file, 32, "@%s", tmp + 1);
823 824 825 826 827
		if (ret <= 0)
			goto error;
	}

	if (pp->function)
828 829 830
		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
				 offs, pp->retprobe ? "%return" : "", line,
				 file);
831
	else
832
		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
833 834 835 836
	if (ret <= 0)
		goto error;

	return buf;
837
error:
838 839
	pr_debug("Failed to synthesize perf probe point: %s",
		 strerror(-ret));
840 841
	if (buf)
		free(buf);
842
	return NULL;
843 844
}

845 846
#if 0
char *synthesize_perf_probe_command(struct perf_probe_event *pev)
847 848 849 850
{
	char *buf;
	int i, len, ret;

851 852 853
	buf = synthesize_perf_probe_point(&pev->point);
	if (!buf)
		return NULL;
854

855 856
	len = strlen(buf);
	for (i = 0; i < pev->nargs; i++) {
857
		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
858 859 860 861 862
				 pev->args[i].name);
		if (ret <= 0) {
			free(buf);
			return NULL;
		}
863 864 865
		len += ret;
	}

866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
	return buf;
}
#endif

static int __synthesize_kprobe_trace_arg_ref(struct kprobe_trace_arg_ref *ref,
					     char **buf, size_t *buflen,
					     int depth)
{
	int ret;
	if (ref->next) {
		depth = __synthesize_kprobe_trace_arg_ref(ref->next, buf,
							 buflen, depth + 1);
		if (depth < 0)
			goto out;
	}

	ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
	if (ret < 0)
		depth = ret;
	else {
		*buf += ret;
		*buflen -= ret;
	}
out:
	return depth;
891 892 893

}

894 895
static int synthesize_kprobe_trace_arg(struct kprobe_trace_arg *arg,
				       char *buf, size_t buflen)
896
{
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
	int ret, depth = 0;
	char *tmp = buf;

	/* Argument name or separator */
	if (arg->name)
		ret = e_snprintf(buf, buflen, " %s=", arg->name);
	else
		ret = e_snprintf(buf, buflen, " ");
	if (ret < 0)
		return ret;
	buf += ret;
	buflen -= ret;

	/* Dereferencing arguments */
	if (arg->ref) {
		depth = __synthesize_kprobe_trace_arg_ref(arg->ref, &buf,
							  &buflen, 1);
		if (depth < 0)
			return depth;
	}

	/* Print argument value */
	ret = e_snprintf(buf, buflen, "%s", arg->value);
	if (ret < 0)
		return ret;
	buf += ret;
	buflen -= ret;

	/* Closing */
	while (depth--) {
		ret = e_snprintf(buf, buflen, ")");
		if (ret < 0)
			return ret;
		buf += ret;
		buflen -= ret;
	}
933 934 935 936 937 938 939
	/* Print argument type */
	if (arg->type) {
		ret = e_snprintf(buf, buflen, ":%s", arg->type);
		if (ret <= 0)
			return ret;
		buf += ret;
	}
940 941 942 943 944 945 946

	return buf - tmp;
}

char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev)
{
	struct kprobe_trace_point *tp = &tev->point;
947 948 949
	char *buf;
	int i, len, ret;

950 951 952 953
	buf = zalloc(MAX_CMDLEN);
	if (buf == NULL)
		return NULL;

954 955 956 957 958
	len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu",
			 tp->retprobe ? 'r' : 'p',
			 tev->group, tev->event,
			 tp->symbol, tp->offset);
	if (len <= 0)
959 960
		goto error;

961 962 963
	for (i = 0; i < tev->nargs; i++) {
		ret = synthesize_kprobe_trace_arg(&tev->args[i], buf + len,
						  MAX_CMDLEN - len);
964
		if (ret <= 0)
965 966 967 968
			goto error;
		len += ret;
	}

969
	return buf;
970
error:
971 972 973
	free(buf);
	return NULL;
}
974

975 976
int convert_to_perf_probe_event(struct kprobe_trace_event *tev,
				struct perf_probe_event *pev)
977
{
978
	char buf[64] = "";
979
	int i, ret;
980

981
	/* Convert event/group name */
982 983 984 985
	pev->event = strdup(tev->event);
	pev->group = strdup(tev->group);
	if (pev->event == NULL || pev->group == NULL)
		return -ENOMEM;
986

987
	/* Convert trace_point to probe_point */
988 989 990
	ret = convert_to_perf_probe_point(&tev->point, &pev->point);
	if (ret < 0)
		return ret;
991

992 993
	/* Convert trace_arg to probe_arg */
	pev->nargs = tev->nargs;
994 995 996
	pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
	if (pev->args == NULL)
		return -ENOMEM;
997
	for (i = 0; i < tev->nargs && ret >= 0; i++) {
998
		if (tev->args[i].name)
999
			pev->args[i].name = strdup(tev->args[i].name);
1000
		else {
1001 1002
			ret = synthesize_kprobe_trace_arg(&tev->args[i],
							  buf, 64);
1003
			pev->args[i].name = strdup(buf);
1004
		}
1005 1006 1007
		if (pev->args[i].name == NULL && ret >= 0)
			ret = -ENOMEM;
	}
1008 1009 1010 1011 1012

	if (ret < 0)
		clear_perf_probe_event(pev);

	return ret;
1013 1014 1015 1016 1017
}

void clear_perf_probe_event(struct perf_probe_event *pev)
{
	struct perf_probe_point *pp = &pev->point;
1018
	struct perf_probe_arg_field *field, *next;
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
	int i;

	if (pev->event)
		free(pev->event);
	if (pev->group)
		free(pev->group);
	if (pp->file)
		free(pp->file);
	if (pp->function)
		free(pp->function);
	if (pp->lazy_line)
		free(pp->lazy_line);
1031
	for (i = 0; i < pev->nargs; i++) {
1032 1033
		if (pev->args[i].name)
			free(pev->args[i].name);
1034 1035
		if (pev->args[i].var)
			free(pev->args[i].var);
1036 1037
		if (pev->args[i].type)
			free(pev->args[i].type);
1038 1039 1040 1041 1042 1043 1044 1045 1046
		field = pev->args[i].field;
		while (field) {
			next = field->next;
			if (field->name)
				free(field->name);
			free(field);
			field = next;
		}
	}
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
	if (pev->args)
		free(pev->args);
	memset(pev, 0, sizeof(*pev));
}

void clear_kprobe_trace_event(struct kprobe_trace_event *tev)
{
	struct kprobe_trace_arg_ref *ref, *next;
	int i;

	if (tev->event)
		free(tev->event);
	if (tev->group)
		free(tev->group);
	if (tev->point.symbol)
		free(tev->point.symbol);
	for (i = 0; i < tev->nargs; i++) {
		if (tev->args[i].name)
			free(tev->args[i].name);
		if (tev->args[i].value)
			free(tev->args[i].value);
1068 1069
		if (tev->args[i].type)
			free(tev->args[i].type);
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
		ref = tev->args[i].ref;
		while (ref) {
			next = ref->next;
			free(ref);
			ref = next;
		}
	}
	if (tev->args)
		free(tev->args);
	memset(tev, 0, sizeof(*tev));
1080 1081
}

1082
static int open_kprobe_events(bool readwrite)
1083 1084
{
	char buf[PATH_MAX];
1085
	const char *__debugfs;
1086 1087
	int ret;

1088 1089 1090 1091 1092 1093 1094
	__debugfs = debugfs_find_mountpoint();
	if (__debugfs == NULL) {
		pr_warning("Debugfs is not mounted.\n");
		return -ENOENT;
	}

	ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs);
1095
	if (ret >= 0) {
1096
		pr_debug("Opening %s write=%d\n", buf, readwrite);
1097 1098 1099 1100 1101
		if (readwrite && !probe_event_dry_run)
			ret = open(buf, O_RDWR, O_APPEND);
		else
			ret = open(buf, O_RDONLY, 0);
	}
1102

1103 1104
	if (ret < 0) {
		if (errno == ENOENT)
1105 1106
			pr_warning("kprobe_events file does not exist - please"
				 " rebuild kernel with CONFIG_KPROBE_EVENT.\n");
1107
		else
1108 1109
			pr_warning("Failed to open kprobe_events file: %s\n",
				   strerror(errno));
1110 1111 1112 1113 1114
	}
	return ret;
}

/* Get raw string list of current kprobe_events */
1115
static struct strlist *get_kprobe_trace_command_rawlist(int fd)
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
{
	int ret, idx;
	FILE *fp;
	char buf[MAX_CMDLEN];
	char *p;
	struct strlist *sl;

	sl = strlist__new(true, NULL);

	fp = fdopen(dup(fd), "r");
	while (!feof(fp)) {
		p = fgets(buf, MAX_CMDLEN, fp);
		if (!p)
			break;

		idx = strlen(p) - 1;
		if (p[idx] == '\n')
			p[idx] = '\0';
		ret = strlist__add(sl, buf);
1135 1136 1137 1138 1139
		if (ret < 0) {
			pr_debug("strlist__add failed: %s\n", strerror(-ret));
			strlist__delete(sl);
			return NULL;
		}
1140 1141 1142 1143 1144 1145
	}
	fclose(fp);

	return sl;
}

1146
/* Show an event */
1147
static int show_perf_probe_event(struct perf_probe_event *pev)
1148
{
1149
	int i, ret;
1150
	char buf[128];
1151
	char *place;
1152

1153 1154
	/* Synthesize only event probe point */
	place = synthesize_perf_probe_point(&pev->point);
1155 1156
	if (!place)
		return -EINVAL;
1157 1158

	ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
1159
	if (ret < 0)
1160 1161
		return ret;

1162
	printf("  %-20s (on %s", buf, place);
1163

1164
	if (pev->nargs > 0) {
1165
		printf(" with");
1166
		for (i = 0; i < pev->nargs; i++) {
1167 1168 1169 1170
			ret = synthesize_perf_probe_arg(&pev->args[i],
							buf, 128);
			if (ret < 0)
				break;
1171 1172
			printf(" %s", buf);
		}
1173 1174
	}
	printf(")\n");
1175
	free(place);
1176
	return ret;
1177 1178
}

1179
/* List up current perf-probe events */
1180
int show_perf_probe_events(void)
1181
{
1182
	int fd, ret;
1183 1184
	struct kprobe_trace_event tev;
	struct perf_probe_event pev;
1185 1186 1187
	struct strlist *rawlist;
	struct str_node *ent;

1188
	setup_pager();
1189 1190 1191
	ret = init_vmlinux();
	if (ret < 0)
		return ret;
1192 1193 1194

	memset(&tev, 0, sizeof(tev));
	memset(&pev, 0, sizeof(pev));
1195

1196
	fd = open_kprobe_events(false);
1197 1198 1199
	if (fd < 0)
		return fd;

1200
	rawlist = get_kprobe_trace_command_rawlist(fd);
1201
	close(fd);
1202 1203
	if (!rawlist)
		return -ENOENT;
1204

1205
	strlist__for_each(ent, rawlist) {
1206 1207 1208 1209 1210 1211
		ret = parse_kprobe_trace_command(ent->s, &tev);
		if (ret >= 0) {
			ret = convert_to_perf_probe_event(&tev, &pev);
			if (ret >= 0)
				ret = show_perf_probe_event(&pev);
		}
1212 1213
		clear_perf_probe_event(&pev);
		clear_kprobe_trace_event(&tev);
1214 1215
		if (ret < 0)
			break;
1216 1217
	}
	strlist__delete(rawlist);
1218 1219

	return ret;
1220 1221
}

1222
/* Get current perf-probe event names */
1223
static struct strlist *get_kprobe_trace_event_names(int fd, bool include_group)
1224
{
1225
	char buf[128];
1226 1227
	struct strlist *sl, *rawlist;
	struct str_node *ent;
1228
	struct kprobe_trace_event tev;
1229
	int ret = 0;
1230

1231
	memset(&tev, 0, sizeof(tev));
1232

1233
	rawlist = get_kprobe_trace_command_rawlist(fd);
1234
	sl = strlist__new(true, NULL);
1235
	strlist__for_each(ent, rawlist) {
1236 1237 1238
		ret = parse_kprobe_trace_command(ent->s, &tev);
		if (ret < 0)
			break;
1239
		if (include_group) {
1240 1241 1242 1243
			ret = e_snprintf(buf, 128, "%s:%s", tev.group,
					tev.event);
			if (ret >= 0)
				ret = strlist__add(sl, buf);
1244
		} else
1245
			ret = strlist__add(sl, tev.event);
1246
		clear_kprobe_trace_event(&tev);
1247 1248
		if (ret < 0)
			break;
1249 1250 1251
	}
	strlist__delete(rawlist);

1252 1253 1254 1255
	if (ret < 0) {
		strlist__delete(sl);
		return NULL;
	}
1256 1257 1258
	return sl;
}

1259
static int write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev)
1260 1261
{
	int ret;
1262
	char *buf = synthesize_kprobe_trace_command(tev);
1263

1264 1265 1266 1267 1268
	if (!buf) {
		pr_debug("Failed to synthesize kprobe trace event.\n");
		return -EINVAL;
	}

1269
	pr_debug("Writing event: %s\n", buf);
1270 1271 1272
	if (!probe_event_dry_run) {
		ret = write(fd, buf, strlen(buf));
		if (ret <= 0)
1273 1274
			pr_warning("Failed to write event: %s\n",
				   strerror(errno));
1275
	}
1276
	free(buf);
1277
	return ret;
1278 1279
}

1280 1281
static int get_new_event_name(char *buf, size_t len, const char *base,
			      struct strlist *namelist, bool allow_suffix)
1282 1283
{
	int i, ret;
1284 1285 1286

	/* Try no suffix */
	ret = e_snprintf(buf, len, "%s", base);
1287 1288 1289 1290
	if (ret < 0) {
		pr_debug("snprintf() failed: %s\n", strerror(-ret));
		return ret;
	}
1291
	if (!strlist__has_entry(namelist, buf))
1292
		return 0;
1293

1294 1295 1296
	if (!allow_suffix) {
		pr_warning("Error: event \"%s\" already exists. "
			   "(Use -f to force duplicates.)\n", base);
1297
		return -EEXIST;
1298 1299
	}

1300 1301
	/* Try to add suffix */
	for (i = 1; i < MAX_EVENT_INDEX; i++) {
1302
		ret = e_snprintf(buf, len, "%s_%d", base, i);
1303 1304 1305 1306
		if (ret < 0) {
			pr_debug("snprintf() failed: %s\n", strerror(-ret));
			return ret;
		}
1307 1308 1309
		if (!strlist__has_entry(namelist, buf))
			break;
	}
1310 1311 1312 1313 1314 1315
	if (i == MAX_EVENT_INDEX) {
		pr_warning("Too many events are on the same function.\n");
		ret = -ERANGE;
	}

	return ret;
1316 1317
}

1318 1319 1320
static int __add_kprobe_trace_events(struct perf_probe_event *pev,
				     struct kprobe_trace_event *tevs,
				     int ntevs, bool allow_suffix)
1321
{
1322
	int i, fd, ret;
1323
	struct kprobe_trace_event *tev = NULL;
1324 1325
	char buf[64];
	const char *event, *group;
1326
	struct strlist *namelist;
1327

1328
	fd = open_kprobe_events(true);
1329 1330
	if (fd < 0)
		return fd;
1331
	/* Get current event names */
1332
	namelist = get_kprobe_trace_event_names(fd, false);
1333 1334 1335 1336
	if (!namelist) {
		pr_debug("Failed to get current event list.\n");
		return -EIO;
	}
1337

1338
	ret = 0;
1339
	printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":");
1340
	for (i = 0; i < ntevs; i++) {
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354
		tev = &tevs[i];
		if (pev->event)
			event = pev->event;
		else
			if (pev->point.function)
				event = pev->point.function;
			else
				event = tev->point.symbol;
		if (pev->group)
			group = pev->group;
		else
			group = PERFPROBE_GROUP;

		/* Get an unused new event name */
1355 1356 1357 1358
		ret = get_new_event_name(buf, 64, event,
					 namelist, allow_suffix);
		if (ret < 0)
			break;
1359 1360
		event = buf;

1361 1362 1363 1364 1365 1366
		tev->event = strdup(event);
		tev->group = strdup(group);
		if (tev->event == NULL || tev->group == NULL) {
			ret = -ENOMEM;
			break;
		}
1367 1368 1369
		ret = write_kprobe_trace_event(fd, tev);
		if (ret < 0)
			break;
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
		/* Add added event name to namelist */
		strlist__add(namelist, event);

		/* Trick here - save current event/group */
		event = pev->event;
		group = pev->group;
		pev->event = tev->event;
		pev->group = tev->group;
		show_perf_probe_event(pev);
		/* Trick here - restore current event/group */
		pev->event = (char *)event;
		pev->group = (char *)group;

		/*
		 * Probes after the first probe which comes from same
		 * user input are always allowed to add suffix, because
		 * there might be several addresses corresponding to
		 * one code line.
		 */
		allow_suffix = true;
1390
	}
1391 1392 1393 1394 1395 1396 1397

	if (ret >= 0) {
		/* Show how to use the event. */
		printf("\nYou can now use it on all perf tools, such as:\n\n");
		printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
			 tev->event);
	}
1398

1399
	strlist__delete(namelist);
1400
	close(fd);
1401
	return ret;
1402
}
1403

1404 1405
static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
					  struct kprobe_trace_event **tevs)
1406 1407
{
	struct symbol *sym;
1408
	int ret = 0, i;
1409 1410
	struct kprobe_trace_event *tev;

1411
	/* Convert perf_probe_event with debuginfo */
1412 1413 1414
	ret = try_to_find_kprobe_trace_events(pev, tevs);
	if (ret != 0)
		return ret;
1415

1416
	/* Allocate trace event buffer */
1417 1418 1419
	tev = *tevs = zalloc(sizeof(struct kprobe_trace_event));
	if (tev == NULL)
		return -ENOMEM;
1420 1421

	/* Copy parameters */
1422 1423 1424 1425 1426
	tev->point.symbol = strdup(pev->point.function);
	if (tev->point.symbol == NULL) {
		ret = -ENOMEM;
		goto error;
	}
1427 1428 1429
	tev->point.offset = pev->point.offset;
	tev->nargs = pev->nargs;
	if (tev->nargs) {
1430 1431 1432
		tev->args = zalloc(sizeof(struct kprobe_trace_arg)
				   * tev->nargs);
		if (tev->args == NULL) {
1433 1434
			ret = -ENOMEM;
			goto error;
1435
		}
1436
		for (i = 0; i < tev->nargs; i++) {
1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455
			if (pev->args[i].name) {
				tev->args[i].name = strdup(pev->args[i].name);
				if (tev->args[i].name == NULL) {
					ret = -ENOMEM;
					goto error;
				}
			}
			tev->args[i].value = strdup(pev->args[i].var);
			if (tev->args[i].value == NULL) {
				ret = -ENOMEM;
				goto error;
			}
			if (pev->args[i].type) {
				tev->args[i].type = strdup(pev->args[i].type);
				if (tev->args[i].type == NULL) {
					ret = -ENOMEM;
					goto error;
				}
			}
1456
		}
1457 1458 1459 1460 1461
	}

	/* Currently just checking function name from symbol map */
	sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION],
				       tev->point.symbol, NULL);
1462 1463 1464
	if (!sym) {
		pr_warning("Kernel symbol \'%s\' not found.\n",
			   tev->point.symbol);
1465 1466 1467
		ret = -ENOENT;
		goto error;
	}
1468

1469 1470 1471 1472 1473
	return 1;
error:
	clear_kprobe_trace_event(tev);
	free(tev);
	*tevs = NULL;
1474
	return ret;
1475 1476 1477 1478 1479 1480 1481 1482
}

struct __event_package {
	struct perf_probe_event		*pev;
	struct kprobe_trace_event	*tevs;
	int				ntevs;
};

1483 1484
int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
			  bool force_add)
1485
{
1486
	int i, j, ret;
1487 1488
	struct __event_package *pkgs;

1489 1490 1491
	pkgs = zalloc(sizeof(struct __event_package) * npevs);
	if (pkgs == NULL)
		return -ENOMEM;
1492 1493

	/* Init vmlinux path */
1494 1495 1496
	ret = init_vmlinux();
	if (ret < 0)
		return ret;
1497 1498 1499 1500 1501

	/* Loop 1: convert all events */
	for (i = 0; i < npevs; i++) {
		pkgs[i].pev = &pevs[i];
		/* Convert with or without debuginfo */
1502 1503 1504 1505 1506
		ret  = convert_to_kprobe_trace_events(pkgs[i].pev,
						      &pkgs[i].tevs);
		if (ret < 0)
			goto end;
		pkgs[i].ntevs = ret;
1507 1508
	}

1509
	/* Loop 2: add all events */
1510 1511 1512 1513 1514
	for (i = 0; i < npevs && ret >= 0; i++)
		ret = __add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs,
						pkgs[i].ntevs, force_add);
end:
	/* Loop 3: cleanup trace events  */
1515
	for (i = 0; i < npevs; i++)
1516 1517 1518 1519
		for (j = 0; j < pkgs[i].ntevs; j++)
			clear_kprobe_trace_event(&pkgs[i].tevs[j]);

	return ret;
1520 1521
}

1522
static int __del_trace_kprobe_event(int fd, struct str_node *ent)
1523 1524 1525
{
	char *p;
	char buf[128];
1526
	int ret;
1527 1528

	/* Convert from perf-probe event to trace-kprobe event */
1529 1530 1531 1532
	ret = e_snprintf(buf, 128, "-:%s", ent->s);
	if (ret < 0)
		goto error;

1533
	p = strchr(buf + 2, ':');
1534 1535 1536 1537 1538 1539
	if (!p) {
		pr_debug("Internal error: %s should have ':' but not.\n",
			 ent->s);
		ret = -ENOTSUP;
		goto error;
	}
1540 1541
	*p = '/';

1542 1543
	pr_debug("Writing event: %s\n", buf);
	ret = write(fd, buf, strlen(buf));
1544 1545 1546
	if (ret < 0)
		goto error;

1547
	printf("Remove event: %s\n", ent->s);
1548 1549 1550 1551
	return 0;
error:
	pr_warning("Failed to delete event: %s\n", strerror(-ret));
	return ret;
1552 1553
}

1554 1555
static int del_trace_kprobe_event(int fd, const char *group,
				  const char *event, struct strlist *namelist)
1556 1557
{
	char buf[128];
1558
	struct str_node *ent, *n;
1559
	int found = 0, ret = 0;
1560

1561 1562 1563 1564 1565
	ret = e_snprintf(buf, 128, "%s:%s", group, event);
	if (ret < 0) {
		pr_err("Failed to copy event.");
		return ret;
	}
1566

1567 1568 1569 1570
	if (strpbrk(buf, "*?")) { /* Glob-exp */
		strlist__for_each_safe(ent, n, namelist)
			if (strglobmatch(ent->s, buf)) {
				found++;
1571 1572 1573
				ret = __del_trace_kprobe_event(fd, ent);
				if (ret < 0)
					break;
1574 1575 1576 1577 1578 1579
				strlist__remove(namelist, ent);
			}
	} else {
		ent = strlist__find(namelist, buf);
		if (ent) {
			found++;
1580 1581 1582
			ret = __del_trace_kprobe_event(fd, ent);
			if (ret >= 0)
				strlist__remove(namelist, ent);
1583 1584
		}
	}
1585 1586 1587 1588
	if (found == 0 && ret >= 0)
		pr_info("Info: Event \"%s\" does not exist.\n", buf);

	return ret;
1589 1590
}

1591
int del_perf_probe_events(struct strlist *dellist)
1592
{
1593
	int fd, ret = 0;
1594 1595 1596 1597 1598
	const char *group, *event;
	char *p, *str;
	struct str_node *ent;
	struct strlist *namelist;

1599
	fd = open_kprobe_events(true);
1600 1601 1602
	if (fd < 0)
		return fd;

1603
	/* Get current event names */
1604
	namelist = get_kprobe_trace_event_names(fd, true);
1605 1606
	if (namelist == NULL)
		return -EINVAL;
1607

1608
	strlist__for_each(ent, dellist) {
1609 1610 1611 1612 1613
		str = strdup(ent->s);
		if (str == NULL) {
			ret = -ENOMEM;
			break;
		}
1614
		pr_debug("Parsing: %s\n", str);
1615 1616 1617 1618 1619 1620
		p = strchr(str, ':');
		if (p) {
			group = str;
			*p = '\0';
			event = p + 1;
		} else {
1621
			group = "*";
1622 1623
			event = str;
		}
1624
		pr_debug("Group: %s, Event: %s\n", group, event);
1625
		ret = del_trace_kprobe_event(fd, group, event, namelist);
1626
		free(str);
1627 1628
		if (ret < 0)
			break;
1629 1630 1631
	}
	strlist__delete(namelist);
	close(fd);
1632 1633

	return ret;
1634 1635
}