diff options
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r-- | tools/perf/util/probe-event.c | 105 |
1 files changed, 104 insertions, 1 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index fde17b090a47..8f0568849691 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include "string.h" | 37 | #include "string.h" |
38 | #include "strlist.h" | 38 | #include "strlist.h" |
39 | #include "debug.h" | 39 | #include "debug.h" |
40 | #include "cache.h" | ||
41 | #include "color.h" | ||
40 | #include "parse-events.h" /* For debugfs_path */ | 42 | #include "parse-events.h" /* For debugfs_path */ |
41 | #include "probe-event.h" | 43 | #include "probe-event.h" |
42 | 44 | ||
@@ -62,6 +64,42 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) | |||
62 | return ret; | 64 | return ret; |
63 | } | 65 | } |
64 | 66 | ||
67 | void parse_line_range_desc(const char *arg, struct line_range *lr) | ||
68 | { | ||
69 | const char *ptr; | ||
70 | char *tmp; | ||
71 | /* | ||
72 | * <Syntax> | ||
73 | * SRC:SLN[+NUM|-ELN] | ||
74 | * FUNC[:SLN[+NUM|-ELN]] | ||
75 | */ | ||
76 | ptr = strchr(arg, ':'); | ||
77 | if (ptr) { | ||
78 | lr->start = (unsigned int)strtoul(ptr + 1, &tmp, 0); | ||
79 | if (*tmp == '+') | ||
80 | lr->end = lr->start + (unsigned int)strtoul(tmp + 1, | ||
81 | &tmp, 0); | ||
82 | else if (*tmp == '-') | ||
83 | lr->end = (unsigned int)strtoul(tmp + 1, &tmp, 0); | ||
84 | else | ||
85 | lr->end = 0; | ||
86 | pr_debug("Line range is %u to %u\n", lr->start, lr->end); | ||
87 | if (lr->end && lr->start > lr->end) | ||
88 | semantic_error("Start line must be smaller" | ||
89 | " than end line."); | ||
90 | if (*tmp != '\0') | ||
91 | semantic_error("Tailing with invalid character '%d'.", | ||
92 | *tmp); | ||
93 | tmp = strndup(arg, (ptr - arg)); | ||
94 | } else | ||
95 | tmp = strdup(arg); | ||
96 | |||
97 | if (strchr(tmp, '.')) | ||
98 | lr->file = tmp; | ||
99 | else | ||
100 | lr->function = tmp; | ||
101 | } | ||
102 | |||
65 | /* Check the name is good for event/group */ | 103 | /* Check the name is good for event/group */ |
66 | static bool check_event_name(const char *name) | 104 | static bool check_event_name(const char *name) |
67 | { | 105 | { |
@@ -370,7 +408,7 @@ static int open_kprobe_events(int flags, int mode) | |||
370 | if (ret < 0) { | 408 | if (ret < 0) { |
371 | if (errno == ENOENT) | 409 | if (errno == ENOENT) |
372 | die("kprobe_events file does not exist -" | 410 | die("kprobe_events file does not exist -" |
373 | " please rebuild with CONFIG_KPROBE_TRACER."); | 411 | " please rebuild with CONFIG_KPROBE_EVENT."); |
374 | else | 412 | else |
375 | die("Could not open kprobe_events file: %s", | 413 | die("Could not open kprobe_events file: %s", |
376 | strerror(errno)); | 414 | strerror(errno)); |
@@ -457,6 +495,8 @@ void show_perf_probe_events(void) | |||
457 | struct strlist *rawlist; | 495 | struct strlist *rawlist; |
458 | struct str_node *ent; | 496 | struct str_node *ent; |
459 | 497 | ||
498 | setup_pager(); | ||
499 | |||
460 | memset(&pp, 0, sizeof(pp)); | 500 | memset(&pp, 0, sizeof(pp)); |
461 | fd = open_kprobe_events(O_RDONLY, 0); | 501 | fd = open_kprobe_events(O_RDONLY, 0); |
462 | rawlist = get_trace_kprobe_event_rawlist(fd); | 502 | rawlist = get_trace_kprobe_event_rawlist(fd); |
@@ -678,3 +718,66 @@ void del_trace_kprobe_events(struct strlist *dellist) | |||
678 | close(fd); | 718 | close(fd); |
679 | } | 719 | } |
680 | 720 | ||
721 | #define LINEBUF_SIZE 256 | ||
722 | |||
723 | static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) | ||
724 | { | ||
725 | char buf[LINEBUF_SIZE]; | ||
726 | const char *color = PERF_COLOR_BLUE; | ||
727 | |||
728 | if (fgets(buf, LINEBUF_SIZE, fp) == NULL) | ||
729 | goto error; | ||
730 | if (!skip) { | ||
731 | if (show_num) | ||
732 | fprintf(stdout, "%7u %s", l, buf); | ||
733 | else | ||
734 | color_fprintf(stdout, color, " %s", buf); | ||
735 | } | ||
736 | |||
737 | while (strlen(buf) == LINEBUF_SIZE - 1 && | ||
738 | buf[LINEBUF_SIZE - 2] != '\n') { | ||
739 | if (fgets(buf, LINEBUF_SIZE, fp) == NULL) | ||
740 | goto error; | ||
741 | if (!skip) { | ||
742 | if (show_num) | ||
743 | fprintf(stdout, "%s", buf); | ||
744 | else | ||
745 | color_fprintf(stdout, color, "%s", buf); | ||
746 | } | ||
747 | } | ||
748 | return; | ||
749 | error: | ||
750 | if (feof(fp)) | ||
751 | die("Source file is shorter than expected."); | ||
752 | else | ||
753 | die("File read error: %s", strerror(errno)); | ||
754 | } | ||
755 | |||
756 | void show_line_range(struct line_range *lr) | ||
757 | { | ||
758 | unsigned int l = 1; | ||
759 | struct line_node *ln; | ||
760 | FILE *fp; | ||
761 | |||
762 | setup_pager(); | ||
763 | |||
764 | if (lr->function) | ||
765 | fprintf(stdout, "<%s:%d>\n", lr->function, | ||
766 | lr->start - lr->offset); | ||
767 | else | ||
768 | fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); | ||
769 | |||
770 | fp = fopen(lr->path, "r"); | ||
771 | if (fp == NULL) | ||
772 | die("Failed to open %s: %s", lr->path, strerror(errno)); | ||
773 | /* Skip to starting line number */ | ||
774 | while (l < lr->start) | ||
775 | show_one_line(fp, l++, true, false); | ||
776 | |||
777 | list_for_each_entry(ln, &lr->line_list, list) { | ||
778 | while (ln->line > l) | ||
779 | show_one_line(fp, (l++) - lr->offset, false, false); | ||
780 | show_one_line(fp, (l++) - lr->offset, false, true); | ||
781 | } | ||
782 | fclose(fp); | ||
783 | } | ||