1/* 2 * probe-event.c : perf-probe definition to probe_events format converter 3 * 4 * Written by Masami Hiramatsu <mhiramat@redhat.com> 5 * 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. 10 * 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. 15 * 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. 19 * 20 */ 21 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> 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#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" 49 50#define MAX_CMDLEN 256 51#define MAX_PROBE_ARGS 128 52#define PERFPROBE_GROUP "probe" 53 54bool probe_event_dry_run; /* Dry run flag */ 55 56#define semantic_error(msg ...) pr_err("Semantic error :" msg) 57 58/* If there is no space to write, returns -E2BIG. */ 59static int e_snprintf(char *str, size_t size, const char *format, ...) 60 __attribute__((format(printf, 3, 4))); 61 62static int e_snprintf(char *str, size_t size, const char *format, ...) 63{ 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; 72} 73 74static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 75static struct machine machine; 76 77/* Initialize symbol maps and path of vmlinux */ 78static int init_vmlinux(void) 79{ 80 struct dso *kernel; 81 int ret; 82 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; 92 } 93 94 ret = machine__init(&machine, "/", 0); 95 if (ret < 0) 96 goto out; 97 98 kernel = dso__new_kernel(symbol_conf.vmlinux_name); 99 if (kernel == NULL) 100 die("Failed to create kernel dso."); 101 102 ret = __machine__create_kernel_maps(&machine, kernel); 103 if (ret < 0) 104 pr_debug("Failed to create kernel maps.\n"); 105 106out: 107 if (ret < 0) 108 pr_warning("Failed to init vmlinux path.\n"); 109 return ret; 110} 111 112#ifdef DWARF_SUPPORT 113static int open_vmlinux(void) 114{ 115 if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) { 116 pr_debug("Failed to load kernel map.\n"); 117 return -EINVAL; 118 } 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); 121} 122 123/* 124 * Convert trace point to probe point with debuginfo 125 * Currently only handles kprobes. 126 */ 127static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 128 struct perf_probe_point *pp) 129{ 130 struct symbol *sym; 131 int fd, ret = -ENOENT; 132 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); 141 } 142 } 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; 150 } 151 pp->retprobe = tp->retprobe; 152 153 return 0; 154} 155 156/* Try to find perf_probe_event with debuginfo */ 157static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 158 struct probe_trace_event **tevs, 159 int max_tevs) 160{ 161 bool need_dwarf = perf_probe_event_need_dwarf(pev); 162 int fd, ntevs; 163 164 fd = open_vmlinux(); 165 if (fd < 0) { 166 if (need_dwarf) { 167 pr_warning("Failed to open debuginfo file.\n"); 168 return fd; 169 } 170 pr_debug("Could not open vmlinux. Try to use symbols.\n"); 171 return 0; 172 } 173 174 /* Searching trace events corresponding to probe event */ 175 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); 176 close(fd); 177 178 if (ntevs > 0) { /* Succeeded to find trace events */ 179 pr_debug("find %d probe_trace_events.\n", ntevs); 180 return ntevs; 181 } 182 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; 187 } 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; 196 } 197 } 198 return ntevs; 199} 200 201/* 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. 206 */ 207static int get_real_path(const char *raw_path, const char *comp_dir, 208 char **new_path) 209{ 210 const char *prefix = symbol_conf.source_prefix; 211 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; 222 } 223 } 224 225 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2)); 226 if (!*new_path) 227 return -ENOMEM; 228 229 for (;;) { 230 sprintf(*new_path, "%s/%s", prefix, raw_path); 231 232 if (access(*new_path, R_OK) == 0) 233 return 0; 234 235 if (!symbol_conf.source_prefix) 236 /* In case of searching comp_dir, don't retry */ 237 return -errno; 238 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; 249 } 250 continue; 251 252 default: 253 free(*new_path); 254 *new_path = NULL; 255 return -errno; 256 } 257 } 258} 259 260#define LINEBUF_SIZE 256 261#define NR_ADDITIONAL_LINES 2 262 263static int show_one_line(FILE *fp, int l, bool skip, bool show_num) 264{ 265 char buf[LINEBUF_SIZE]; 266 const char *color = PERF_COLOR_BLUE; 267 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); 275 } 276 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); 286 } 287 } 288 289 return 0; 290error: 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)); 295 296 return -1; 297} 298 299/* 300 * Show line-range always requires debuginfo to find source file and 301 * line number. 302 */ 303int show_line_range(struct line_range *lr) 304{ 305 int l = 1; 306 struct line_node *ln; 307 FILE *fp; 308 int fd, ret; 309 char *tmp; 310 311 /* Search a line range */ 312 ret = init_vmlinux(); 313 if (ret < 0) 314 return ret; 315 316 fd = open_vmlinux(); 317 if (fd < 0) { 318 pr_warning("Failed to open debuginfo file.\n"); 319 return fd; 320 } 321 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; 330 } 331 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; 339 } 340 341 setup_pager(); 342 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); 348 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; 354 } 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; 360 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; 370 } 371 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); 376end: 377 fclose(fp); 378 return ret; 379} 380 381#else /* !DWARF_SUPPORT */ 382 383static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 384 struct perf_probe_point *pp) 385{ 386 pp->function = strdup(tp->symbol); 387 if (pp->function == NULL) 388 return -ENOMEM; 389 pp->offset = tp->offset; 390 pp->retprobe = tp->retprobe; 391 392 return 0; 393} 394 395static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 396 struct probe_trace_event **tevs __unused, 397 int max_tevs __unused) 398{ 399 if (perf_probe_event_need_dwarf(pev)) { 400 pr_warning("Debuginfo-analysis is not supported.\n"); 401 return -ENOSYS; 402 } 403 return 0; 404} 405 406int show_line_range(struct line_range *lr __unused) 407{ 408 pr_warning("Debuginfo-analysis is not supported.\n"); 409 return -ENOSYS; 410} 411 412#endif 413 414int parse_line_range_desc(const char *arg, struct line_range *lr) 415{ 416 const char *ptr; 417 char *tmp; 418 /* 419 * <Syntax> 420 * SRC:SLN[+NUM|-ELN] 421 * FUNC[:SLN[+NUM|-ELN]] 422 */ 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. 433 */ 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; 443 } 444 if (*tmp != '\0') { 445 semantic_error("Tailing with invalid character '%d'.\n", 446 *tmp); 447 return -EINVAL; 448 } 449 tmp = strndup(arg, (ptr - arg)); 450 } else { 451 tmp = strdup(arg); 452 lr->end = INT_MAX; 453 } 454 455 if (tmp == NULL) 456 return -ENOMEM; 457 458 if (strchr(tmp, '.')) 459 lr->file = tmp; 460 else 461 lr->function = tmp; 462 463 return 0; 464} 465 466/* Check the name is good for event/group */ 467static bool check_event_name(const char *name) 468{ 469 if (!isalpha(*name) && *name != '_') 470 return false; 471 while (*++name != '\0') { 472 if (!isalpha(*name) && !isdigit(*name) && *name != '_') 473 return false; 474 } 475 return true; 476} 477 478/* Parse probepoint definition. */ 479static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 480{ 481 struct perf_probe_point *pp = &pev->point; 482 char *ptr, *tmp; 483 char c, nc = 0; 484 /* 485 * <Syntax> 486 * perf probe [EVENT=]SRC[:LN|;PTN] 487 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 488 * 489 * TODO:Group name support 490 */ 491 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; 499 } 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; 504 } 505 pev->event = strdup(arg); 506 if (pev->event == NULL) 507 return -ENOMEM; 508 pev->group = NULL; 509 arg = tmp; 510 } 511 512 ptr = strpbrk(arg, ";:+@%"); 513 if (ptr) { 514 nc = *ptr; 515 *ptr++ = '\0'; 516 } 517 518 tmp = strdup(arg); 519 if (tmp == NULL) 520 return -ENOMEM; 521 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; 527 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; 537 } 538 ptr = strpbrk(arg, ";:+@%"); 539 if (ptr) { 540 nc = *ptr; 541 *ptr++ = '\0'; 542 } 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; 550 } 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; 558 } 559 break; 560 case '@': /* File name */ 561 if (pp->file) { 562 semantic_error("SRC@SRC is not allowed.\n"); 563 return -EINVAL; 564 } 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; 575 } 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; 582 } 583 } 584 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; 589 } 590 591 if (pp->lazy_line && pp->offset) { 592 semantic_error("Lazy pattern can't be used with offset."); 593 return -EINVAL; 594 } 595 596 if (pp->line && pp->offset) { 597 semantic_error("Offset can't be used with line number."); 598 return -EINVAL; 599 } 600 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; 605 } 606 607 if (pp->offset && !pp->function) { 608 semantic_error("Offset requires an entry function."); 609 return -EINVAL; 610 } 611 612 if (pp->retprobe && !pp->function) { 613 semantic_error("Return probe requires an entry function."); 614 return -EINVAL; 615 } 616 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; 621 } 622 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; 627} 628 629/* Parse perf-probe event argument */ 630static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) 631{ 632 char *tmp, *goodname; 633 struct perf_probe_arg_field **fieldp; 634 635 pr_debug("parsing arg: %s into ", str); 636 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; 644 } 645 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); 653 } 654 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; 663 } 664 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; 672 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; 685 } 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; 700 } 701 tmp = strpbrk(str, "-.["); 702 } 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; 711 } 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); 719 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; 725 } 726 return 0; 727} 728 729/* Parse perf-probe event command */ 730int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) 731{ 732 char **argv; 733 int argc, i, ret = 0; 734 735 argv = argv_split(cmd, &argc); 736 if (!argv) { 737 pr_debug("Failed to split arguments.\n"); 738 return -ENOMEM; 739 } 740 if (argc - 1 > MAX_PROBE_ARGS) { 741 semantic_error("Too many probe arguments (%d).\n", argc - 1); 742 ret = -ERANGE; 743 goto out; 744 } 745 /* Parse probe point */ 746 ret = parse_perf_probe_point(argv[0], pev); 747 if (ret < 0) 748 goto out; 749 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; 756 } 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; 764 } 765 } 766out: 767 argv_free(argv); 768 769 return ret; 770} 771 772/* Return true if this perf_probe_event requires debuginfo */ 773bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) 774{ 775 int i; 776 777 if (pev->point.file || pev->point.line || pev->point.lazy_line) 778 return true; 779 780 for (i = 0; i < pev->nargs; i++) 781 if (is_c_varname(pev->args[i].var)) 782 return true; 783 784 return false; 785} 786 787/* Parse probe_events event into struct probe_point */ 788static int parse_probe_trace_command(const char *cmd, 789 struct probe_trace_event *tev) 790{ 791 struct probe_trace_point *tp = &tev->point; 792 char pr; 793 char *p; 794 int ret, i, argc; 795 char **argv; 796 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; 802 } 803 if (argc < 2) { 804 semantic_error("Too few probe arguments.\n"); 805 ret = -ERANGE; 806 goto out; 807 } 808 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; 817 } 818 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); 819 820 tp->retprobe = (pr == 'r'); 821 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; 827 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; 833 } 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; 846 } 847 } 848 ret = 0; 849out: 850 argv_free(argv); 851 return ret; 852} 853 854/* Compose only probe arg */ 855int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 856{ 857 struct perf_probe_arg_field *field = pa->field; 858 int ret; 859 char *tmp = buf; 860 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; 869 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; 881 } 882 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; 889 } 890 891 return tmp - buf; 892error: 893 pr_debug("Failed to synthesize perf probe argument: %s", 894 strerror(-ret)); 895 return ret; 896} 897 898/* Compose only probe point (not argument) */ 899static char *synthesize_perf_probe_point(struct perf_probe_point *pp) 900{ 901 char *buf, *tmp; 902 char offs[32] = "", line[32] = "", file[32] = ""; 903 int ret, len; 904 905 buf = zalloc(MAX_CMDLEN); 906 if (buf == NULL) { 907 ret = -ENOMEM; 908 goto error; 909 } 910 if (pp->offset) { 911 ret = e_snprintf(offs, 32, "+%lu", pp->offset); 912 if (ret <= 0) 913 goto error; 914 } 915 if (pp->line) { 916 ret = e_snprintf(line, 32, ":%d", pp->line); 917 if (ret <= 0) 918 goto error; 919 } 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; 930 } 931 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; 940 941 return buf; 942error: 943 pr_debug("Failed to synthesize perf probe point: %s", 944 strerror(-ret)); 945 if (buf) 946 free(buf); 947 return NULL; 948} 949 950 951static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, 952 char **buf, size_t *buflen, 953 int depth) 954{ 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; 961 } 962 963 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset); 964 if (ret < 0) 965 depth = ret; 966 else { 967 *buf += ret; 968 *buflen -= ret; 969 } 970out: 971 return depth; 972 973} 974 975static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, 976 char *buf, size_t buflen) 977{ 978 struct probe_trace_arg_ref *ref = arg->ref; 979 int ret, depth = 0; 980 char *tmp = buf; 981 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; 991 992 if (arg->value[0] == '@' && arg->ref) 993 ref = ref->next; 994 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; 1001 } 1002 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; 1013 1014 /* Closing */ 1015 while (depth--) { 1016 ret = e_snprintf(buf, buflen, ")"); 1017 if (ret < 0) 1018 return ret; 1019 buf += ret; 1020 buflen -= ret; 1021 } 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; 1028 } 1029 1030 return buf - tmp; 1031} 1032 1033char *synthesize_probe_trace_command(struct probe_trace_event *tev) 1034{ 1035 struct probe_trace_point *tp = &tev->point; 1036 char *buf; 1037 int i, len, ret; 1038 1039 buf = zalloc(MAX_CMDLEN); 1040 if (buf == NULL) 1041 return NULL; 1042 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; 1049 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; 1056 } 1057 1058 return buf; 1059error: 1060 free(buf); 1061 return NULL; 1062} 1063 1064static int convert_to_perf_probe_event(struct probe_trace_event *tev, 1065 struct perf_probe_event *pev) 1066{ 1067 char buf[64] = ""; 1068 int i, ret; 1069 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; 1075 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; 1080 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); 1093 } 1094 if (pev->args[i].name == NULL && ret >= 0) 1095 ret = -ENOMEM; 1096 } 1097 1098 if (ret < 0) 1099 clear_perf_probe_event(pev); 1100 1101 return ret; 1102} 1103 1104void clear_perf_probe_event(struct perf_probe_event *pev) 1105{ 1106 struct perf_probe_point *pp = &pev->point; 1107 struct perf_probe_arg_field *field, *next; 1108 int i; 1109 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; 1134 } 1135 } 1136 if (pev->args) 1137 free(pev->args); 1138 memset(pev, 0, sizeof(*pev)); 1139} 1140 1141static void clear_probe_trace_event(struct probe_trace_event *tev) 1142{ 1143 struct probe_trace_arg_ref *ref, *next; 1144 int i; 1145 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; 1164 } 1165 } 1166 if (tev->args) 1167 free(tev->args); 1168 memset(tev, 0, sizeof(*tev)); 1169} 1170 1171static int open_kprobe_events(bool readwrite) 1172{ 1173 char buf[PATH_MAX]; 1174 const char *__debugfs; 1175 int ret; 1176 1177 __debugfs = debugfs_find_mountpoint(); 1178 if (__debugfs == NULL) { 1179 pr_warning("Debugfs is not mounted.\n"); 1180 return -ENOENT; 1181 } 1182 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); 1190 } 1191 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)); 1199 } 1200 return ret; 1201} 1202 1203/* Get raw string list of current kprobe_events */ 1204static struct strlist *get_probe_trace_command_rawlist(int fd) 1205{ 1206 int ret, idx; 1207 FILE *fp; 1208 char buf[MAX_CMDLEN]; 1209 char *p; 1210 struct strlist *sl; 1211 1212 sl = strlist__new(true, NULL); 1213 1214 fp = fdopen(dup(fd), "r"); 1215 while (!feof(fp)) { 1216 p = fgets(buf, MAX_CMDLEN, fp); 1217 if (!p) 1218 break; 1219 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; 1228 } 1229 } 1230 fclose(fp); 1231 1232 return sl; 1233} 1234 1235/* Show an event */ 1236static int show_perf_probe_event(struct perf_probe_event *pev) 1237{ 1238 int i, ret; 1239 char buf[128]; 1240 char *place; 1241 1242 /* Synthesize only event probe point */ 1243 place = synthesize_perf_probe_point(&pev->point); 1244 if (!place) 1245 return -EINVAL; 1246 1247 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); 1248 if (ret < 0) 1249 return ret; 1250 1251 printf(" %-20s (on %s", buf, place); 1252 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); 1261 } 1262 } 1263 printf(")\n"); 1264 free(place); 1265 return ret; 1266} 1267 1268/* List up current perf-probe events */ 1269int show_perf_probe_events(void) 1270{ 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; 1276 1277 setup_pager(); 1278 ret = init_vmlinux(); 1279 if (ret < 0) 1280 return ret; 1281 1282 memset(&tev, 0, sizeof(tev)); 1283 memset(&pev, 0, sizeof(pev)); 1284 1285 fd = open_kprobe_events(false); 1286 if (fd < 0) 1287 return fd; 1288 1289 rawlist = get_probe_trace_command_rawlist(fd); 1290 close(fd); 1291 if (!rawlist) 1292 return -ENOENT; 1293 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); 1300 } 1301 clear_perf_probe_event(&pev); 1302 clear_probe_trace_event(&tev); 1303 if (ret < 0) 1304 break; 1305 } 1306 strlist__delete(rawlist); 1307 1308 return ret; 1309} 1310 1311/* Get current perf-probe event names */ 1312static struct strlist *get_probe_trace_event_names(int fd, bool include_group) 1313{ 1314 char buf[128]; 1315 struct strlist *sl, *rawlist; 1316 struct str_node *ent; 1317 struct probe_trace_event tev; 1318 int ret = 0; 1319 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; 1337 } 1338 strlist__delete(rawlist); 1339 1340 if (ret < 0) { 1341 strlist__delete(sl); 1342 return NULL; 1343 } 1344 return sl; 1345} 1346 1347static int write_probe_trace_event(int fd, struct probe_trace_event *tev) 1348{ 1349 int ret = 0; 1350 char *buf = synthesize_probe_trace_command(tev); 1351 1352 if (!buf) { 1353 pr_debug("Failed to synthesize probe trace event.\n"); 1354 return -EINVAL; 1355 } 1356 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)); 1363 } 1364 free(buf); 1365 return ret; 1366} 1367 1368static int get_new_event_name(char *buf, size_t len, const char *base, 1369 struct strlist *namelist, bool allow_suffix) 1370{ 1371 int i, ret; 1372 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; 1378 } 1379 if (!strlist__has_entry(namelist, buf)) 1380 return 0; 1381 1382 if (!allow_suffix) { 1383 pr_warning("Error: event \"%s\" already exists. " 1384 "(Use -f to force duplicates.)\n", base); 1385 return -EEXIST; 1386 } 1387 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; 1394 } 1395 if (!strlist__has_entry(namelist, buf)) 1396 break; 1397 } 1398 if (i == MAX_EVENT_INDEX) { 1399 pr_warning("Too many events are on the same function.\n"); 1400 ret = -ERANGE; 1401 } 1402 1403 return ret; 1404} 1405 1406static int __add_probe_trace_events(struct perf_probe_event *pev, 1407 struct probe_trace_event *tevs, 1408 int ntevs, bool allow_suffix) 1409{ 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; 1415 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; 1424 } 1425 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; 1441 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; 1448 1449 tev->event = strdup(event); 1450 tev->group = strdup(group); 1451 if (tev->event == NULL || tev->group == NULL) { 1452 ret = -ENOMEM; 1453 break; 1454 } 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); 1460 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; 1470 1471 /* 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. 1476 */ 1477 allow_suffix = true; 1478 } 1479 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); 1485 } 1486 1487 strlist__delete(namelist); 1488 close(fd); 1489 return ret; 1490} 1491 1492static int convert_to_probe_trace_events(struct perf_probe_event *pev, 1493 struct probe_trace_event **tevs, 1494 int max_tevs) 1495{ 1496 struct symbol *sym; 1497 int ret = 0, i; 1498 struct probe_trace_event *tev; 1499 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; 1504 1505 /* Allocate trace event buffer */ 1506 tev = *tevs = zalloc(sizeof(struct probe_trace_event)); 1507 if (tev == NULL) 1508 return -ENOMEM; 1509 1510 /* Copy parameters */ 1511 tev->point.symbol = strdup(pev->point.function); 1512 if (tev->point.symbol == NULL) { 1513 ret = -ENOMEM; 1514 goto error; 1515 } 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; 1525 } 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; 1532 } 1533 } 1534 tev->args[i].value = strdup(pev->args[i].var); 1535 if (tev->args[i].value == NULL) { 1536 ret = -ENOMEM; 1537 goto error; 1538 } 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; 1544 } 1545 } 1546 } 1547 } 1548 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; 1557 } 1558 1559 return 1; 1560error: 1561 clear_probe_trace_event(tev); 1562 free(tev); 1563 *tevs = NULL; 1564 return ret; 1565} 1566 1567struct __event_package { 1568 struct perf_probe_event *pev; 1569 struct probe_trace_event *tevs; 1570 int ntevs; 1571}; 1572 1573int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 1574 bool force_add, int max_tevs) 1575{ 1576 int i, j, ret; 1577 struct __event_package *pkgs; 1578 1579 pkgs = zalloc(sizeof(struct __event_package) * npevs); 1580 if (pkgs == NULL) 1581 return -ENOMEM; 1582 1583 /* Init vmlinux path */ 1584 ret = init_vmlinux(); 1585 if (ret < 0) { 1586 free(pkgs); 1587 return ret; 1588 } 1589 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; 1599 } 1600 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); 1605end: 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); 1611 } 1612 free(pkgs); 1613 1614 return ret; 1615} 1616 1617static int __del_trace_probe_event(int fd, struct str_node *ent) 1618{ 1619 char *p; 1620 char buf[128]; 1621 int ret; 1622 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; 1627 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; 1634 } 1635 *p = '/'; 1636 1637 pr_debug("Writing event: %s\n", buf); 1638 ret = write(fd, buf, strlen(buf)); 1639 if (ret < 0) 1640 goto error; 1641 1642 printf("Remove event: %s\n", ent->s); 1643 return 0; 1644error: 1645 pr_warning("Failed to delete event: %s\n", strerror(-ret)); 1646 return ret; 1647} 1648 1649static int del_trace_probe_event(int fd, const char *group, 1650 const char *event, struct strlist *namelist) 1651{ 1652 char buf[128]; 1653 struct str_node *ent, *n; 1654 int found = 0, ret = 0; 1655 1656 ret = e_snprintf(buf, 128, "%s:%s", group, event); 1657 if (ret < 0) { 1658 pr_err("Failed to copy event."); 1659 return ret; 1660 } 1661 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); 1670 } 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); 1678 } 1679 } 1680 if (found == 0 && ret >= 0) 1681 pr_info("Info: Event \"%s\" does not exist.\n", buf); 1682 1683 return ret; 1684} 1685 1686int del_perf_probe_events(struct strlist *dellist) 1687{ 1688 int fd, ret = 0; 1689 const char *group, *event; 1690 char *p, *str; 1691 struct str_node *ent; 1692 struct strlist *namelist; 1693 1694 fd = open_kprobe_events(true); 1695 if (fd < 0) 1696 return fd; 1697 1698 /* Get current event names */ 1699 namelist = get_probe_trace_event_names(fd, true); 1700 if (namelist == NULL) 1701 return -EINVAL; 1702 1703 strlist__for_each(ent, dellist) { 1704 str = strdup(ent->s); 1705 if (str == NULL) { 1706 ret = -ENOMEM; 1707 break; 1708 } 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; 1718 } 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; 1724 } 1725 strlist__delete(namelist); 1726 close(fd); 1727 1728 return ret; 1729} 1730