diff options
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r-- | tools/perf/util/probe-event.c | 220 |
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 | } |
101 | out: | 101 | out: |
@@ -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 | ||
289 | static int show_one_line(FILE *fp, int l, bool skip, bool show_num) | 290 | static 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; | ||
316 | error: | 310 | error: |
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; | 318 | static 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 | } | ||
402 | end: | 414 | end: |
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 | ||
532 | static 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 | */ | ||
520 | int parse_line_range_desc(const char *arg, struct line_range *lr) | 552 | int 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; |
610 | err: | ||
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; |
998 | error: | 1042 | error: |
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; |
1048 | error: | 1092 | error: |
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 | ||