aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-event.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-03-22 12:10:26 -0400
committerIngo Molnar <mingo@elte.hu>2010-03-22 13:47:35 -0400
commit4b4da7f76660ea8b5aa45615165c48f62167ffa8 (patch)
tree927274cf9fe9fca657983f4a5d3d3a91a40a051b /tools/perf/util/probe-event.c
parentf3a1f0ea9432ec395cd112f42201e8e523c07bc5 (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/perf/util/probe-event.c')
-rw-r--r--tools/perf/util/probe-event.c343
1 files changed, 184 insertions, 159 deletions
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
74static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
73static struct map_groups kmap_groups; 75static struct map_groups kmap_groups;
74static struct map *kmaps[MAP__NR_TYPES]; 76static struct map *kmaps[MAP__NR_TYPES];
75 77
76/* Initialize symbol maps for vmlinux */ 78/* Initialize symbol maps and path of vmlinux */
77static void init_vmlinux(void) 79static 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
93static int open_vmlinux(void) 95static 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
105static 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 */
126static 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
168static 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;
194error:
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 */
205void 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
253static 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
261static 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
269void show_line_range(struct line_range *lr __unused)
270{
271 die("Debuginfo-analysis is not supported");
272}
273
102#endif 274#endif
103 275
104void parse_line_range_desc(const char *arg, struct line_range *lr) 276void 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
991end_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
1016found:
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
1139static 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;
1165error:
1166 if (feof(fp))
1167 die("Source file is shorter than expected.");
1168 else
1169 die("File read error: %s", strerror(errno));
1170}
1171
1172void 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