diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2010-03-22 12:10:26 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-03-22 13:47:35 -0400 |
commit | 4b4da7f76660ea8b5aa45615165c48f62167ffa8 (patch) | |
tree | 927274cf9fe9fca657983f4a5d3d3a91a40a051b /tools | |
parent | f3a1f0ea9432ec395cd112f42201e8e523c07bc5 (diff) |
perf probe: Cleanup debuginfo related code
Cleanup debuginfo related code to eliminate fragile code which
pointed by Ingo (Thanks!).
1) Invert logic of NO_DWARF_SUPPORT to DWARF_SUPPORT.
2) For removing assymetric/local variable ifdefs, introduce
more helper functions.
3) Change options order to reduce the number of ifdefs.
Reported-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <1269274229-20442-2-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Makefile | 3 | ||||
-rw-r--r-- | tools/perf/builtin-probe.c | 28 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 343 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.h | 4 |
4 files changed, 200 insertions, 178 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 0abd25ee595f..c9918182715a 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -506,9 +506,8 @@ endif | |||
506 | 506 | ||
507 | ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) | 507 | ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) |
508 | msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev); | 508 | msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev); |
509 | BASIC_CFLAGS += -DNO_DWARF_SUPPORT | ||
510 | else | 509 | else |
511 | BASIC_CFLAGS += -I/usr/include/elfutils | 510 | BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT |
512 | EXTLIBS += -lelf -ldw | 511 | EXTLIBS += -lelf -ldw |
513 | LIB_OBJS += util/probe-finder.o | 512 | LIB_OBJS += util/probe-finder.o |
514 | endif | 513 | endif |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index e0dafd9dfeb5..cf2ffa5a3842 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -109,7 +109,7 @@ static int opt_del_probe_event(const struct option *opt __used, | |||
109 | return 0; | 109 | return 0; |
110 | } | 110 | } |
111 | 111 | ||
112 | #ifndef NO_DWARF_SUPPORT | 112 | #ifdef DWARF_SUPPORT |
113 | static int opt_show_lines(const struct option *opt __used, | 113 | static int opt_show_lines(const struct option *opt __used, |
114 | const char *str, int unset __used) | 114 | const char *str, int unset __used) |
115 | { | 115 | { |
@@ -126,7 +126,7 @@ static const char * const probe_usage[] = { | |||
126 | "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", | 126 | "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", |
127 | "perf probe [<options>] --del '[GROUP:]EVENT' ...", | 127 | "perf probe [<options>] --del '[GROUP:]EVENT' ...", |
128 | "perf probe --list", | 128 | "perf probe --list", |
129 | #ifndef NO_DWARF_SUPPORT | 129 | #ifdef DWARF_SUPPORT |
130 | "perf probe --line 'LINEDESC'", | 130 | "perf probe --line 'LINEDESC'", |
131 | #endif | 131 | #endif |
132 | NULL | 132 | NULL |
@@ -135,20 +135,16 @@ static const char * const probe_usage[] = { | |||
135 | static const struct option options[] = { | 135 | static const struct option options[] = { |
136 | OPT_BOOLEAN('v', "verbose", &verbose, | 136 | OPT_BOOLEAN('v', "verbose", &verbose, |
137 | "be more verbose (show parsed arguments, etc)"), | 137 | "be more verbose (show parsed arguments, etc)"), |
138 | #ifndef NO_DWARF_SUPPORT | ||
139 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, | ||
140 | "file", "vmlinux pathname"), | ||
141 | #endif | ||
142 | OPT_BOOLEAN('l', "list", ¶ms.list_events, | 138 | OPT_BOOLEAN('l', "list", ¶ms.list_events, |
143 | "list up current probe events"), | 139 | "list up current probe events"), |
144 | OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", | 140 | OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", |
145 | opt_del_probe_event), | 141 | opt_del_probe_event), |
146 | OPT_CALLBACK('a', "add", NULL, | 142 | OPT_CALLBACK('a', "add", NULL, |
147 | #ifdef NO_DWARF_SUPPORT | 143 | #ifdef DWARF_SUPPORT |
148 | "[EVENT=]FUNC[+OFF|%return] [ARG ...]", | ||
149 | #else | ||
150 | "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" | 144 | "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" |
151 | " [ARG ...]", | 145 | " [ARG ...]", |
146 | #else | ||
147 | "[EVENT=]FUNC[+OFF|%return] [ARG ...]", | ||
152 | #endif | 148 | #endif |
153 | "probe point definition, where\n" | 149 | "probe point definition, where\n" |
154 | "\t\tGROUP:\tGroup name (optional)\n" | 150 | "\t\tGROUP:\tGroup name (optional)\n" |
@@ -156,23 +152,25 @@ static const struct option options[] = { | |||
156 | "\t\tFUNC:\tFunction name\n" | 152 | "\t\tFUNC:\tFunction name\n" |
157 | "\t\tOFF:\tOffset from function entry (in byte)\n" | 153 | "\t\tOFF:\tOffset from function entry (in byte)\n" |
158 | "\t\t%return:\tPut the probe at function return\n" | 154 | "\t\t%return:\tPut the probe at function return\n" |
159 | #ifdef NO_DWARF_SUPPORT | 155 | #ifdef DWARF_SUPPORT |
160 | "\t\tARG:\tProbe argument (only \n" | ||
161 | #else | ||
162 | "\t\tSRC:\tSource code path\n" | 156 | "\t\tSRC:\tSource code path\n" |
163 | "\t\tRL:\tRelative line number from function entry.\n" | 157 | "\t\tRL:\tRelative line number from function entry.\n" |
164 | "\t\tAL:\tAbsolute line number in file.\n" | 158 | "\t\tAL:\tAbsolute line number in file.\n" |
165 | "\t\tPT:\tLazy expression of line code.\n" | 159 | "\t\tPT:\tLazy expression of line code.\n" |
166 | "\t\tARG:\tProbe argument (local variable name or\n" | 160 | "\t\tARG:\tProbe argument (local variable name or\n" |
167 | #endif | ||
168 | "\t\t\tkprobe-tracer argument format.)\n", | 161 | "\t\t\tkprobe-tracer argument format.)\n", |
162 | #else | ||
163 | "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n", | ||
164 | #endif | ||
169 | opt_add_probe_event), | 165 | opt_add_probe_event), |
170 | OPT_BOOLEAN('f', "force", ¶ms.force_add, "forcibly add events" | 166 | OPT_BOOLEAN('f', "force", ¶ms.force_add, "forcibly add events" |
171 | " with existing name"), | 167 | " with existing name"), |
172 | #ifndef NO_DWARF_SUPPORT | 168 | #ifdef DWARF_SUPPORT |
173 | OPT_CALLBACK('L', "line", NULL, | 169 | OPT_CALLBACK('L', "line", NULL, |
174 | "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]", | 170 | "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]", |
175 | "Show source code lines.", opt_show_lines), | 171 | "Show source code lines.", opt_show_lines), |
172 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, | ||
173 | "file", "vmlinux pathname"), | ||
176 | #endif | 174 | #endif |
177 | OPT__DRY_RUN(&probe_event_dry_run), | 175 | OPT__DRY_RUN(&probe_event_dry_run), |
178 | OPT_END() | 176 | OPT_END() |
@@ -211,7 +209,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
211 | return 0; | 209 | return 0; |
212 | } | 210 | } |
213 | 211 | ||
214 | #ifndef NO_DWARF_SUPPORT | 212 | #ifdef DWARF_SUPPORT |
215 | if (params.show_lines) { | 213 | if (params.show_lines) { |
216 | if (params.nevents != 0 || params.dellist) { | 214 | if (params.nevents != 0 || params.dellist) { |
217 | pr_warning(" Error: Don't use --line with" | 215 | pr_warning(" Error: Don't use --line with" |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index c6603f3bb430..3fc0be741b8e 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -42,7 +42,8 @@ | |||
42 | #include "color.h" | 42 | #include "color.h" |
43 | #include "symbol.h" | 43 | #include "symbol.h" |
44 | #include "thread.h" | 44 | #include "thread.h" |
45 | #include "parse-events.h" /* For debugfs_path */ | 45 | #include "trace-event.h" /* For __unused */ |
46 | #include "parse-events.h" /* For debugfs_path */ | ||
46 | #include "probe-event.h" | 47 | #include "probe-event.h" |
47 | #include "probe-finder.h" | 48 | #include "probe-finder.h" |
48 | 49 | ||
@@ -70,10 +71,11 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) | |||
70 | return ret; | 71 | return ret; |
71 | } | 72 | } |
72 | 73 | ||
74 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); | ||
73 | static struct map_groups kmap_groups; | 75 | static struct map_groups kmap_groups; |
74 | static struct map *kmaps[MAP__NR_TYPES]; | 76 | static struct map *kmaps[MAP__NR_TYPES]; |
75 | 77 | ||
76 | /* Initialize symbol maps for vmlinux */ | 78 | /* Initialize symbol maps and path of vmlinux */ |
77 | static void init_vmlinux(void) | 79 | static void init_vmlinux(void) |
78 | { | 80 | { |
79 | symbol_conf.sort_by_name = true; | 81 | symbol_conf.sort_by_name = true; |
@@ -89,7 +91,7 @@ static void init_vmlinux(void) | |||
89 | die("Failed to create kernel maps."); | 91 | die("Failed to create kernel maps."); |
90 | } | 92 | } |
91 | 93 | ||
92 | #ifndef NO_DWARF_SUPPORT | 94 | #ifdef DWARF_SUPPORT |
93 | static int open_vmlinux(void) | 95 | static int open_vmlinux(void) |
94 | { | 96 | { |
95 | if (map__load(kmaps[MAP__FUNCTION], NULL) < 0) { | 97 | if (map__load(kmaps[MAP__FUNCTION], NULL) < 0) { |
@@ -99,6 +101,176 @@ static int open_vmlinux(void) | |||
99 | pr_debug("Try to open %s\n", kmaps[MAP__FUNCTION]->dso->long_name); | 101 | pr_debug("Try to open %s\n", kmaps[MAP__FUNCTION]->dso->long_name); |
100 | return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); | 102 | return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); |
101 | } | 103 | } |
104 | |||
105 | static void convert_to_perf_probe_point(struct kprobe_trace_point *tp, | ||
106 | struct perf_probe_point *pp) | ||
107 | { | ||
108 | struct symbol *sym; | ||
109 | int fd, ret = 0; | ||
110 | |||
111 | sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], | ||
112 | tp->symbol, NULL); | ||
113 | if (sym) { | ||
114 | fd = open_vmlinux(); | ||
115 | ret = find_perf_probe_point(fd, sym->start + tp->offset, pp); | ||
116 | close(fd); | ||
117 | } | ||
118 | if (ret <= 0) { | ||
119 | pp->function = xstrdup(tp->symbol); | ||
120 | pp->offset = tp->offset; | ||
121 | } | ||
122 | pp->retprobe = tp->retprobe; | ||
123 | } | ||
124 | |||
125 | /* Try to find perf_probe_event with debuginfo */ | ||
126 | static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, | ||
127 | struct kprobe_trace_event **tevs) | ||
128 | { | ||
129 | bool need_dwarf = perf_probe_event_need_dwarf(pev); | ||
130 | int fd, ntevs; | ||
131 | |||
132 | fd = open_vmlinux(); | ||
133 | if (fd < 0) { | ||
134 | if (need_dwarf) | ||
135 | die("Could not open debuginfo file."); | ||
136 | |||
137 | pr_debug("Could not open vmlinux. Try to use symbols.\n"); | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | /* Searching trace events corresponding to probe event */ | ||
142 | ntevs = find_kprobe_trace_events(fd, pev, tevs); | ||
143 | close(fd); | ||
144 | |||
145 | if (ntevs > 0) /* Succeeded to find trace events */ | ||
146 | return ntevs; | ||
147 | |||
148 | if (ntevs == 0) /* No error but failed to find probe point. */ | ||
149 | die("Probe point '%s' not found. - probe not added.", | ||
150 | synthesize_perf_probe_point(&pev->point)); | ||
151 | |||
152 | /* Error path */ | ||
153 | if (need_dwarf) { | ||
154 | if (ntevs == -ENOENT) | ||
155 | pr_warning("No dwarf info found in the vmlinux - " | ||
156 | "please rebuild with CONFIG_DEBUG_INFO=y.\n"); | ||
157 | die("Could not analyze debuginfo."); | ||
158 | } | ||
159 | pr_debug("An error occurred in debuginfo analysis." | ||
160 | " Try to use symbols.\n"); | ||
161 | return 0; | ||
162 | |||
163 | } | ||
164 | |||
165 | #define LINEBUF_SIZE 256 | ||
166 | #define NR_ADDITIONAL_LINES 2 | ||
167 | |||
168 | static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) | ||
169 | { | ||
170 | char buf[LINEBUF_SIZE]; | ||
171 | const char *color = PERF_COLOR_BLUE; | ||
172 | |||
173 | if (fgets(buf, LINEBUF_SIZE, fp) == NULL) | ||
174 | goto error; | ||
175 | if (!skip) { | ||
176 | if (show_num) | ||
177 | fprintf(stdout, "%7u %s", l, buf); | ||
178 | else | ||
179 | color_fprintf(stdout, color, " %s", buf); | ||
180 | } | ||
181 | |||
182 | while (strlen(buf) == LINEBUF_SIZE - 1 && | ||
183 | buf[LINEBUF_SIZE - 2] != '\n') { | ||
184 | if (fgets(buf, LINEBUF_SIZE, fp) == NULL) | ||
185 | goto error; | ||
186 | if (!skip) { | ||
187 | if (show_num) | ||
188 | fprintf(stdout, "%s", buf); | ||
189 | else | ||
190 | color_fprintf(stdout, color, "%s", buf); | ||
191 | } | ||
192 | } | ||
193 | return; | ||
194 | error: | ||
195 | if (feof(fp)) | ||
196 | die("Source file is shorter than expected."); | ||
197 | else | ||
198 | die("File read error: %s", strerror(errno)); | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Show line-range always requires debuginfo to find source file and | ||
203 | * line number. | ||
204 | */ | ||
205 | void show_line_range(struct line_range *lr) | ||
206 | { | ||
207 | unsigned int l = 1; | ||
208 | struct line_node *ln; | ||
209 | FILE *fp; | ||
210 | int fd, ret; | ||
211 | |||
212 | /* Search a line range */ | ||
213 | init_vmlinux(); | ||
214 | fd = open_vmlinux(); | ||
215 | if (fd < 0) | ||
216 | die("Could not open debuginfo file."); | ||
217 | ret = find_line_range(fd, lr); | ||
218 | if (ret <= 0) | ||
219 | die("Source line is not found.\n"); | ||
220 | close(fd); | ||
221 | |||
222 | setup_pager(); | ||
223 | |||
224 | if (lr->function) | ||
225 | fprintf(stdout, "<%s:%d>\n", lr->function, | ||
226 | lr->start - lr->offset); | ||
227 | else | ||
228 | fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); | ||
229 | |||
230 | fp = fopen(lr->path, "r"); | ||
231 | if (fp == NULL) | ||
232 | die("Failed to open %s: %s", lr->path, strerror(errno)); | ||
233 | /* Skip to starting line number */ | ||
234 | while (l < lr->start) | ||
235 | show_one_line(fp, l++, true, false); | ||
236 | |||
237 | list_for_each_entry(ln, &lr->line_list, list) { | ||
238 | while (ln->line > l) | ||
239 | show_one_line(fp, (l++) - lr->offset, false, false); | ||
240 | show_one_line(fp, (l++) - lr->offset, false, true); | ||
241 | } | ||
242 | |||
243 | if (lr->end == INT_MAX) | ||
244 | lr->end = l + NR_ADDITIONAL_LINES; | ||
245 | while (l < lr->end && !feof(fp)) | ||
246 | show_one_line(fp, (l++) - lr->offset, false, false); | ||
247 | |||
248 | fclose(fp); | ||
249 | } | ||
250 | |||
251 | #else /* !DWARF_SUPPORT */ | ||
252 | |||
253 | static void convert_to_perf_probe_point(struct kprobe_trace_point *tp, | ||
254 | struct perf_probe_point *pp) | ||
255 | { | ||
256 | pp->function = xstrdup(tp->symbol); | ||
257 | pp->offset = tp->offset; | ||
258 | pp->retprobe = tp->retprobe; | ||
259 | } | ||
260 | |||
261 | static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, | ||
262 | struct kprobe_trace_event **tevs __unused) | ||
263 | { | ||
264 | if (perf_probe_event_need_dwarf(pev)) | ||
265 | die("Debuginfo-analysis is not supported"); | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | void show_line_range(struct line_range *lr __unused) | ||
270 | { | ||
271 | die("Debuginfo-analysis is not supported"); | ||
272 | } | ||
273 | |||
102 | #endif | 274 | #endif |
103 | 275 | ||
104 | void parse_line_range_desc(const char *arg, struct line_range *lr) | 276 | void parse_line_range_desc(const char *arg, struct line_range *lr) |
@@ -592,32 +764,14 @@ void convert_to_perf_probe_event(struct kprobe_trace_event *tev, | |||
592 | { | 764 | { |
593 | char buf[64]; | 765 | char buf[64]; |
594 | int i; | 766 | int i; |
595 | #ifndef NO_DWARF_SUPPORT | ||
596 | struct symbol *sym; | ||
597 | int fd, ret = 0; | ||
598 | |||
599 | sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], | ||
600 | tev->point.symbol, NULL); | ||
601 | if (sym) { | ||
602 | fd = open_vmlinux(); | ||
603 | ret = find_perf_probe_point(fd, sym->start + tev->point.offset, | ||
604 | &pev->point); | ||
605 | close(fd); | ||
606 | } | ||
607 | if (ret <= 0) { | ||
608 | pev->point.function = xstrdup(tev->point.symbol); | ||
609 | pev->point.offset = tev->point.offset; | ||
610 | } | ||
611 | #else | ||
612 | /* Convert trace_point to probe_point */ | ||
613 | pev->point.function = xstrdup(tev->point.symbol); | ||
614 | pev->point.offset = tev->point.offset; | ||
615 | #endif | ||
616 | pev->point.retprobe = tev->point.retprobe; | ||
617 | 767 | ||
768 | /* Convert event/group name */ | ||
618 | pev->event = xstrdup(tev->event); | 769 | pev->event = xstrdup(tev->event); |
619 | pev->group = xstrdup(tev->group); | 770 | pev->group = xstrdup(tev->group); |
620 | 771 | ||
772 | /* Convert trace_point to probe_point */ | ||
773 | convert_to_perf_probe_point(&tev->point, &pev->point); | ||
774 | |||
621 | /* Convert trace_arg to probe_arg */ | 775 | /* Convert trace_arg to probe_arg */ |
622 | pev->nargs = tev->nargs; | 776 | pev->nargs = tev->nargs; |
623 | pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); | 777 | pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); |
@@ -944,52 +1098,13 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, | |||
944 | struct kprobe_trace_event **tevs) | 1098 | struct kprobe_trace_event **tevs) |
945 | { | 1099 | { |
946 | struct symbol *sym; | 1100 | struct symbol *sym; |
947 | bool need_dwarf; | ||
948 | #ifndef NO_DWARF_SUPPORT | ||
949 | int fd; | ||
950 | #endif | ||
951 | int ntevs = 0, i; | 1101 | int ntevs = 0, i; |
952 | struct kprobe_trace_event *tev; | 1102 | struct kprobe_trace_event *tev; |
953 | 1103 | ||
954 | need_dwarf = perf_probe_event_need_dwarf(pev); | 1104 | /* Convert perf_probe_event with debuginfo */ |
955 | 1105 | ntevs = try_to_find_kprobe_trace_events(pev, tevs); | |
956 | if (need_dwarf) | 1106 | if (ntevs > 0) |
957 | #ifdef NO_DWARF_SUPPORT | 1107 | return ntevs; |
958 | die("Debuginfo-analysis is not supported"); | ||
959 | #else /* !NO_DWARF_SUPPORT */ | ||
960 | pr_debug("Some probes require debuginfo.\n"); | ||
961 | |||
962 | fd = open_vmlinux(); | ||
963 | if (fd < 0) { | ||
964 | if (need_dwarf) | ||
965 | die("Could not open debuginfo file."); | ||
966 | |||
967 | pr_debug("Could not open vmlinux/module file." | ||
968 | " Try to use symbols.\n"); | ||
969 | goto end_dwarf; | ||
970 | } | ||
971 | |||
972 | /* Searching probe points */ | ||
973 | ntevs = find_kprobe_trace_events(fd, pev, tevs); | ||
974 | |||
975 | if (ntevs > 0) /* Found */ | ||
976 | goto found; | ||
977 | |||
978 | if (ntevs == 0) /* No error but failed to find probe point. */ | ||
979 | die("Probe point '%s' not found. - probe not added.", | ||
980 | synthesize_perf_probe_point(&pev->point)); | ||
981 | |||
982 | /* Error path */ | ||
983 | if (need_dwarf) { | ||
984 | if (ntevs == -ENOENT) | ||
985 | pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n"); | ||
986 | die("Could not analyze debuginfo."); | ||
987 | } | ||
988 | pr_debug("An error occurred in debuginfo analysis." | ||
989 | " Try to use symbols.\n"); | ||
990 | |||
991 | end_dwarf: | ||
992 | #endif /* !NO_DWARF_SUPPORT */ | ||
993 | 1108 | ||
994 | /* Allocate trace event buffer */ | 1109 | /* Allocate trace event buffer */ |
995 | ntevs = 1; | 1110 | ntevs = 1; |
@@ -1012,10 +1127,7 @@ end_dwarf: | |||
1012 | if (!sym) | 1127 | if (!sym) |
1013 | die("Kernel symbol \'%s\' not found - probe not added.", | 1128 | die("Kernel symbol \'%s\' not found - probe not added.", |
1014 | tev->point.symbol); | 1129 | tev->point.symbol); |
1015 | #ifndef NO_DWARF_SUPPORT | 1130 | |
1016 | found: | ||
1017 | close(fd); | ||
1018 | #endif | ||
1019 | return ntevs; | 1131 | return ntevs; |
1020 | } | 1132 | } |
1021 | 1133 | ||
@@ -1133,90 +1245,3 @@ void del_perf_probe_events(struct strlist *dellist) | |||
1133 | close(fd); | 1245 | close(fd); |
1134 | } | 1246 | } |
1135 | 1247 | ||
1136 | #define LINEBUF_SIZE 256 | ||
1137 | #define NR_ADDITIONAL_LINES 2 | ||
1138 | |||
1139 | static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) | ||
1140 | { | ||
1141 | char buf[LINEBUF_SIZE]; | ||
1142 | const char *color = PERF_COLOR_BLUE; | ||
1143 | |||
1144 | if (fgets(buf, LINEBUF_SIZE, fp) == NULL) | ||
1145 | goto error; | ||
1146 | if (!skip) { | ||
1147 | if (show_num) | ||
1148 | fprintf(stdout, "%7u %s", l, buf); | ||
1149 | else | ||
1150 | color_fprintf(stdout, color, " %s", buf); | ||
1151 | } | ||
1152 | |||
1153 | while (strlen(buf) == LINEBUF_SIZE - 1 && | ||
1154 | buf[LINEBUF_SIZE - 2] != '\n') { | ||
1155 | if (fgets(buf, LINEBUF_SIZE, fp) == NULL) | ||
1156 | goto error; | ||
1157 | if (!skip) { | ||
1158 | if (show_num) | ||
1159 | fprintf(stdout, "%s", buf); | ||
1160 | else | ||
1161 | color_fprintf(stdout, color, "%s", buf); | ||
1162 | } | ||
1163 | } | ||
1164 | return; | ||
1165 | error: | ||
1166 | if (feof(fp)) | ||
1167 | die("Source file is shorter than expected."); | ||
1168 | else | ||
1169 | die("File read error: %s", strerror(errno)); | ||
1170 | } | ||
1171 | |||
1172 | void show_line_range(struct line_range *lr) | ||
1173 | { | ||
1174 | unsigned int l = 1; | ||
1175 | struct line_node *ln; | ||
1176 | FILE *fp; | ||
1177 | #ifndef NO_DWARF_SUPPORT | ||
1178 | int fd, ret; | ||
1179 | #endif | ||
1180 | |||
1181 | /* Search a line range */ | ||
1182 | init_vmlinux(); | ||
1183 | #ifndef NO_DWARF_SUPPORT | ||
1184 | fd = open_vmlinux(); | ||
1185 | if (fd < 0) | ||
1186 | die("Could not open debuginfo file."); | ||
1187 | ret = find_line_range(fd, lr); | ||
1188 | if (ret <= 0) | ||
1189 | die("Source line is not found.\n"); | ||
1190 | close(fd); | ||
1191 | #endif | ||
1192 | |||
1193 | setup_pager(); | ||
1194 | |||
1195 | if (lr->function) | ||
1196 | fprintf(stdout, "<%s:%d>\n", lr->function, | ||
1197 | lr->start - lr->offset); | ||
1198 | else | ||
1199 | fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); | ||
1200 | |||
1201 | fp = fopen(lr->path, "r"); | ||
1202 | if (fp == NULL) | ||
1203 | die("Failed to open %s: %s", lr->path, strerror(errno)); | ||
1204 | /* Skip to starting line number */ | ||
1205 | while (l < lr->start) | ||
1206 | show_one_line(fp, l++, true, false); | ||
1207 | |||
1208 | list_for_each_entry(ln, &lr->line_list, list) { | ||
1209 | while (ln->line > l) | ||
1210 | show_one_line(fp, (l++) - lr->offset, false, false); | ||
1211 | show_one_line(fp, (l++) - lr->offset, false, true); | ||
1212 | } | ||
1213 | |||
1214 | if (lr->end == INT_MAX) | ||
1215 | lr->end = l + NR_ADDITIONAL_LINES; | ||
1216 | while (l < lr->end && !feof(fp)) | ||
1217 | show_one_line(fp, (l++) - lr->offset, false, false); | ||
1218 | |||
1219 | fclose(fp); | ||
1220 | } | ||
1221 | |||
1222 | |||
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 2f2307d4139f..3564f22954f1 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
@@ -15,7 +15,7 @@ static inline int is_c_varname(const char *name) | |||
15 | return isalpha(name[0]) || name[0] == '_'; | 15 | return isalpha(name[0]) || name[0] == '_'; |
16 | } | 16 | } |
17 | 17 | ||
18 | #ifndef NO_DWARF_SUPPORT | 18 | #ifdef DWARF_SUPPORT |
19 | /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ | 19 | /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ |
20 | extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, | 20 | extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, |
21 | struct kprobe_trace_event **tevs); | 21 | struct kprobe_trace_event **tevs); |
@@ -57,6 +57,6 @@ struct line_finder { | |||
57 | int found; | 57 | int found; |
58 | }; | 58 | }; |
59 | 59 | ||
60 | #endif /* NO_DWARF_SUPPORT */ | 60 | #endif /* DWARF_SUPPORT */ |
61 | 61 | ||
62 | #endif /*_PROBE_FINDER_H */ | 62 | #endif /*_PROBE_FINDER_H */ |