aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-event.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r--tools/perf/util/probe-event.c220
1 files changed, 132 insertions, 88 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3b6a5297bf16..099336ed34b4 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -95,7 +95,7 @@ static int init_vmlinux(void)
95 goto out; 95 goto out;
96 96
97 if (machine__create_kernel_maps(&machine) < 0) { 97 if (machine__create_kernel_maps(&machine) < 0) {
98 pr_debug("machine__create_kernel_maps "); 98 pr_debug("machine__create_kernel_maps() failed.\n");
99 goto out; 99 goto out;
100 } 100 }
101out: 101out:
@@ -140,7 +140,8 @@ static int open_vmlinux(const char *module)
140{ 140{
141 const char *path = kernel_get_module_path(module); 141 const char *path = kernel_get_module_path(module);
142 if (!path) { 142 if (!path) {
143 pr_err("Failed to find path of %s module", module ?: "kernel"); 143 pr_err("Failed to find path of %s module.\n",
144 module ?: "kernel");
144 return -ENOENT; 145 return -ENOENT;
145 } 146 }
146 pr_debug("Try to open %s\n", path); 147 pr_debug("Try to open %s\n", path);
@@ -217,7 +218,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
217 pr_warning("Warning: No dwarf info found in the vmlinux - " 218 pr_warning("Warning: No dwarf info found in the vmlinux - "
218 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 219 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
219 if (!need_dwarf) { 220 if (!need_dwarf) {
220 pr_debug("Trying to use symbols.\nn"); 221 pr_debug("Trying to use symbols.\n");
221 return 0; 222 return 0;
222 } 223 }
223 } 224 }
@@ -286,42 +287,49 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
286#define LINEBUF_SIZE 256 287#define LINEBUF_SIZE 256
287#define NR_ADDITIONAL_LINES 2 288#define NR_ADDITIONAL_LINES 2
288 289
289static int show_one_line(FILE *fp, int l, bool skip, bool show_num) 290static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
290{ 291{
291 char buf[LINEBUF_SIZE]; 292 char buf[LINEBUF_SIZE];
292 const char *color = PERF_COLOR_BLUE; 293 const char *color = show_num ? "" : PERF_COLOR_BLUE;
294 const char *prefix = NULL;
293 295
294 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 296 do {
295 goto error;
296 if (!skip) {
297 if (show_num)
298 fprintf(stdout, "%7d %s", l, buf);
299 else
300 color_fprintf(stdout, color, " %s", buf);
301 }
302
303 while (strlen(buf) == LINEBUF_SIZE - 1 &&
304 buf[LINEBUF_SIZE - 2] != '\n') {
305 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 297 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
306 goto error; 298 goto error;
307 if (!skip) { 299 if (skip)
308 if (show_num) 300 continue;
309 fprintf(stdout, "%s", buf); 301 if (!prefix) {
310 else 302 prefix = show_num ? "%7d " : " ";
311 color_fprintf(stdout, color, "%s", buf); 303 color_fprintf(stdout, color, prefix, l);
312 } 304 }
313 } 305 color_fprintf(stdout, color, "%s", buf);
314 306
315 return 0; 307 } while (strchr(buf, '\n') == NULL);
308
309 return 1;
316error: 310error:
317 if (feof(fp)) 311 if (ferror(fp)) {
318 pr_warning("Source file is shorter than expected.\n"); 312 pr_warning("Source file is shorter than expected.\n");
319 else 313 return -1;
320 pr_warning("File read error: %s\n", strerror(errno)); 314 }
315 return 0;
316}
321 317
322 return -1; 318static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
319{
320 int rv = __show_one_line(fp, l, skip, show_num);
321 if (rv == 0) {
322 pr_warning("Source file is shorter than expected.\n");
323 rv = -1;
324 }
325 return rv;
323} 326}
324 327
328#define show_one_line_with_num(f,l) _show_one_line(f,l,false,true)
329#define show_one_line(f,l) _show_one_line(f,l,false,false)
330#define skip_one_line(f,l) _show_one_line(f,l,true,false)
331#define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false)
332
325/* 333/*
326 * Show line-range always requires debuginfo to find source file and 334 * Show line-range always requires debuginfo to find source file and
327 * line number. 335 * line number.
@@ -370,7 +378,7 @@ int show_line_range(struct line_range *lr, const char *module)
370 fprintf(stdout, "<%s:%d>\n", lr->function, 378 fprintf(stdout, "<%s:%d>\n", lr->function,
371 lr->start - lr->offset); 379 lr->start - lr->offset);
372 else 380 else
373 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); 381 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
374 382
375 fp = fopen(lr->path, "r"); 383 fp = fopen(lr->path, "r");
376 if (fp == NULL) { 384 if (fp == NULL) {
@@ -379,26 +387,30 @@ int show_line_range(struct line_range *lr, const char *module)
379 return -errno; 387 return -errno;
380 } 388 }
381 /* Skip to starting line number */ 389 /* Skip to starting line number */
382 while (l < lr->start && ret >= 0) 390 while (l < lr->start) {
383 ret = show_one_line(fp, l++, true, false); 391 ret = skip_one_line(fp, l++);
384 if (ret < 0) 392 if (ret < 0)
385 goto end; 393 goto end;
394 }
386 395
387 list_for_each_entry(ln, &lr->line_list, list) { 396 list_for_each_entry(ln, &lr->line_list, list) {
388 while (ln->line > l && ret >= 0) 397 for (; ln->line > l; l++) {
389 ret = show_one_line(fp, (l++) - lr->offset, 398 ret = show_one_line(fp, l - lr->offset);
390 false, false); 399 if (ret < 0)
391 if (ret >= 0) 400 goto end;
392 ret = show_one_line(fp, (l++) - lr->offset, 401 }
393 false, true); 402 ret = show_one_line_with_num(fp, l++ - lr->offset);
394 if (ret < 0) 403 if (ret < 0)
395 goto end; 404 goto end;
396 } 405 }
397 406
398 if (lr->end == INT_MAX) 407 if (lr->end == INT_MAX)
399 lr->end = l + NR_ADDITIONAL_LINES; 408 lr->end = l + NR_ADDITIONAL_LINES;
400 while (l <= lr->end && !feof(fp) && ret >= 0) 409 while (l <= lr->end) {
401 ret = show_one_line(fp, (l++) - lr->offset, false, false); 410 ret = show_one_line_or_eof(fp, l++ - lr->offset);
411 if (ret <= 0)
412 break;
413 }
402end: 414end:
403 fclose(fp); 415 fclose(fp);
404 return ret; 416 return ret;
@@ -457,7 +469,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
457 469
458 fd = open_vmlinux(module); 470 fd = open_vmlinux(module);
459 if (fd < 0) { 471 if (fd < 0) {
460 pr_warning("Failed to open debuginfo file.\n"); 472 pr_warning("Failed to open debug information file.\n");
461 return fd; 473 return fd;
462 } 474 }
463 475
@@ -517,56 +529,87 @@ int show_available_vars(struct perf_probe_event *pevs __unused,
517} 529}
518#endif 530#endif
519 531
532static int parse_line_num(char **ptr, int *val, const char *what)
533{
534 const char *start = *ptr;
535
536 errno = 0;
537 *val = strtol(*ptr, ptr, 0);
538 if (errno || *ptr == start) {
539 semantic_error("'%s' is not a valid number.\n", what);
540 return -EINVAL;
541 }
542 return 0;
543}
544
545/*
546 * Stuff 'lr' according to the line range described by 'arg'.
547 * The line range syntax is described by:
548 *
549 * SRC[:SLN[+NUM|-ELN]]
550 * FNC[:SLN[+NUM|-ELN]]
551 */
520int parse_line_range_desc(const char *arg, struct line_range *lr) 552int parse_line_range_desc(const char *arg, struct line_range *lr)
521{ 553{
522 const char *ptr; 554 char *range, *name = strdup(arg);
523 char *tmp; 555 int err;
524 /* 556
525 * <Syntax> 557 if (!name)
526 * SRC:SLN[+NUM|-ELN] 558 return -ENOMEM;
527 * FUNC[:SLN[+NUM|-ELN]] 559
528 */ 560 lr->start = 0;
529 ptr = strchr(arg, ':'); 561 lr->end = INT_MAX;
530 if (ptr) { 562
531 lr->start = (int)strtoul(ptr + 1, &tmp, 0); 563 range = strchr(name, ':');
532 if (*tmp == '+') { 564 if (range) {
533 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); 565 *range++ = '\0';
534 lr->end--; /* 566
535 * Adjust the number of lines here. 567 err = parse_line_num(&range, &lr->start, "start line");
536 * If the number of lines == 1, the 568 if (err)
537 * the end of line should be equal to 569 goto err;
538 * the start of line. 570
539 */ 571 if (*range == '+' || *range == '-') {
540 } else if (*tmp == '-') 572 const char c = *range++;
541 lr->end = (int)strtoul(tmp + 1, &tmp, 0); 573
542 else 574 err = parse_line_num(&range, &lr->end, "end line");
543 lr->end = INT_MAX; 575 if (err)
576 goto err;
577
578 if (c == '+') {
579 lr->end += lr->start;
580 /*
581 * Adjust the number of lines here.
582 * If the number of lines == 1, the
583 * the end of line should be equal to
584 * the start of line.
585 */
586 lr->end--;
587 }
588 }
589
544 pr_debug("Line range is %d to %d\n", lr->start, lr->end); 590 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
591
592 err = -EINVAL;
545 if (lr->start > lr->end) { 593 if (lr->start > lr->end) {
546 semantic_error("Start line must be smaller" 594 semantic_error("Start line must be smaller"
547 " than end line.\n"); 595 " than end line.\n");
548 return -EINVAL; 596 goto err;
549 } 597 }
550 if (*tmp != '\0') { 598 if (*range != '\0') {
551 semantic_error("Tailing with invalid character '%d'.\n", 599 semantic_error("Tailing with invalid str '%s'.\n", range);
552 *tmp); 600 goto err;
553 return -EINVAL;
554 } 601 }
555 tmp = strndup(arg, (ptr - arg));
556 } else {
557 tmp = strdup(arg);
558 lr->end = INT_MAX;
559 } 602 }
560 603
561 if (tmp == NULL) 604 if (strchr(name, '.'))
562 return -ENOMEM; 605 lr->file = name;
563
564 if (strchr(tmp, '.'))
565 lr->file = tmp;
566 else 606 else
567 lr->function = tmp; 607 lr->function = name;
568 608
569 return 0; 609 return 0;
610err:
611 free(name);
612 return err;
570} 613}
571 614
572/* Check the name is good for event/group */ 615/* Check the name is good for event/group */
@@ -690,39 +733,40 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
690 733
691 /* Exclusion check */ 734 /* Exclusion check */
692 if (pp->lazy_line && pp->line) { 735 if (pp->lazy_line && pp->line) {
693 semantic_error("Lazy pattern can't be used with line number."); 736 semantic_error("Lazy pattern can't be used with"
737 " line number.\n");
694 return -EINVAL; 738 return -EINVAL;
695 } 739 }
696 740
697 if (pp->lazy_line && pp->offset) { 741 if (pp->lazy_line && pp->offset) {
698 semantic_error("Lazy pattern can't be used with offset."); 742 semantic_error("Lazy pattern can't be used with offset.\n");
699 return -EINVAL; 743 return -EINVAL;
700 } 744 }
701 745
702 if (pp->line && pp->offset) { 746 if (pp->line && pp->offset) {
703 semantic_error("Offset can't be used with line number."); 747 semantic_error("Offset can't be used with line number.\n");
704 return -EINVAL; 748 return -EINVAL;
705 } 749 }
706 750
707 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 751 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
708 semantic_error("File always requires line number or " 752 semantic_error("File always requires line number or "
709 "lazy pattern."); 753 "lazy pattern.\n");
710 return -EINVAL; 754 return -EINVAL;
711 } 755 }
712 756
713 if (pp->offset && !pp->function) { 757 if (pp->offset && !pp->function) {
714 semantic_error("Offset requires an entry function."); 758 semantic_error("Offset requires an entry function.\n");
715 return -EINVAL; 759 return -EINVAL;
716 } 760 }
717 761
718 if (pp->retprobe && !pp->function) { 762 if (pp->retprobe && !pp->function) {
719 semantic_error("Return probe requires an entry function."); 763 semantic_error("Return probe requires an entry function.\n");
720 return -EINVAL; 764 return -EINVAL;
721 } 765 }
722 766
723 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 767 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
724 semantic_error("Offset/Line/Lazy pattern can't be used with " 768 semantic_error("Offset/Line/Lazy pattern can't be used with "
725 "return probe."); 769 "return probe.\n");
726 return -EINVAL; 770 return -EINVAL;
727 } 771 }
728 772
@@ -996,7 +1040,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
996 1040
997 return tmp - buf; 1041 return tmp - buf;
998error: 1042error:
999 pr_debug("Failed to synthesize perf probe argument: %s", 1043 pr_debug("Failed to synthesize perf probe argument: %s\n",
1000 strerror(-ret)); 1044 strerror(-ret));
1001 return ret; 1045 return ret;
1002} 1046}
@@ -1046,7 +1090,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1046 1090
1047 return buf; 1091 return buf;
1048error: 1092error:
1049 pr_debug("Failed to synthesize perf probe point: %s", 1093 pr_debug("Failed to synthesize perf probe point: %s\n",
1050 strerror(-ret)); 1094 strerror(-ret));
1051 if (buf) 1095 if (buf)
1052 free(buf); 1096 free(buf);
@@ -1787,7 +1831,7 @@ static int del_trace_probe_event(int fd, const char *group,
1787 1831
1788 ret = e_snprintf(buf, 128, "%s:%s", group, event); 1832 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1789 if (ret < 0) { 1833 if (ret < 0) {
1790 pr_err("Failed to copy event."); 1834 pr_err("Failed to copy event.\n");
1791 return ret; 1835 return ret;
1792 } 1836 }
1793 1837