Commit ff741783506c340035659a71be68ddb4068760d1
Committed by
Steven Rostedt
1 parent
e0d153c690
Exists in
master
and in
38 other branches
perf probe: Introduce debuginfo to encapsulate dwarf information
Introduce debuginfo to encapsulate dwarf information. This new object allows us to reuse and expand debuginfo easily. Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Link: http://lkml.kernel.org/r/20110627072739.6528.12438.stgit@fedora15 Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Showing 3 changed files with 182 additions and 136 deletions Side-by-side Diff
tools/perf/util/probe-event.c
... | ... | @@ -170,16 +170,17 @@ |
170 | 170 | } |
171 | 171 | |
172 | 172 | #ifdef DWARF_SUPPORT |
173 | -static int open_vmlinux(const char *module) | |
173 | +/* Open new debuginfo of given module */ | |
174 | +static struct debuginfo *open_debuginfo(const char *module) | |
174 | 175 | { |
175 | 176 | const char *path = kernel_get_module_path(module); |
177 | + | |
176 | 178 | if (!path) { |
177 | 179 | pr_err("Failed to find path of %s module.\n", |
178 | 180 | module ?: "kernel"); |
179 | - return -ENOENT; | |
181 | + return NULL; | |
180 | 182 | } |
181 | - pr_debug("Try to open %s\n", path); | |
182 | - return open(path, O_RDONLY); | |
183 | + return debuginfo__new(path); | |
183 | 184 | } |
184 | 185 | |
185 | 186 | /* |
186 | 187 | |
... | ... | @@ -193,13 +194,24 @@ |
193 | 194 | struct map *map; |
194 | 195 | u64 addr; |
195 | 196 | int ret = -ENOENT; |
197 | + struct debuginfo *dinfo; | |
196 | 198 | |
197 | 199 | sym = __find_kernel_function_by_name(tp->symbol, &map); |
198 | 200 | if (sym) { |
199 | 201 | addr = map->unmap_ip(map, sym->start + tp->offset); |
200 | 202 | pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, |
201 | 203 | tp->offset, addr); |
202 | - ret = find_perf_probe_point((unsigned long)addr, pp); | |
204 | + | |
205 | + dinfo = debuginfo__new_online_kernel(addr); | |
206 | + if (dinfo) { | |
207 | + ret = debuginfo__find_probe_point(dinfo, | |
208 | + (unsigned long)addr, pp); | |
209 | + debuginfo__delete(dinfo); | |
210 | + } else { | |
211 | + pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", | |
212 | + addr); | |
213 | + ret = -ENOENT; | |
214 | + } | |
203 | 215 | } |
204 | 216 | if (ret <= 0) { |
205 | 217 | pr_debug("Failed to find corresponding probes from " |
206 | 218 | |
207 | 219 | |
208 | 220 | |
209 | 221 | |
210 | 222 | |
... | ... | @@ -220,21 +232,23 @@ |
220 | 232 | int max_tevs, const char *module) |
221 | 233 | { |
222 | 234 | bool need_dwarf = perf_probe_event_need_dwarf(pev); |
223 | - int fd, ntevs; | |
235 | + struct debuginfo *dinfo = open_debuginfo(module); | |
236 | + int ntevs; | |
224 | 237 | |
225 | - fd = open_vmlinux(module); | |
226 | - if (fd < 0) { | |
238 | + if (!dinfo) { | |
227 | 239 | if (need_dwarf) { |
228 | 240 | pr_warning("Failed to open debuginfo file.\n"); |
229 | - return fd; | |
241 | + return -ENOENT; | |
230 | 242 | } |
231 | - pr_debug("Could not open vmlinux. Try to use symbols.\n"); | |
243 | + pr_debug("Could not open debuginfo. Try to use symbols.\n"); | |
232 | 244 | return 0; |
233 | 245 | } |
234 | 246 | |
235 | - /* Searching trace events corresponding to probe event */ | |
236 | - ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); | |
247 | + /* Searching trace events corresponding to a probe event */ | |
248 | + ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs); | |
237 | 249 | |
250 | + debuginfo__delete(dinfo); | |
251 | + | |
238 | 252 | if (ntevs > 0) { /* Succeeded to find trace events */ |
239 | 253 | pr_debug("find %d probe_trace_events.\n", ntevs); |
240 | 254 | return ntevs; |
241 | 255 | |
... | ... | @@ -371,8 +385,9 @@ |
371 | 385 | { |
372 | 386 | int l = 1; |
373 | 387 | struct line_node *ln; |
388 | + struct debuginfo *dinfo; | |
374 | 389 | FILE *fp; |
375 | - int fd, ret; | |
390 | + int ret; | |
376 | 391 | char *tmp; |
377 | 392 | |
378 | 393 | /* Search a line range */ |
379 | 394 | |
380 | 395 | |
... | ... | @@ -380,13 +395,14 @@ |
380 | 395 | if (ret < 0) |
381 | 396 | return ret; |
382 | 397 | |
383 | - fd = open_vmlinux(module); | |
384 | - if (fd < 0) { | |
398 | + dinfo = open_debuginfo(module); | |
399 | + if (!dinfo) { | |
385 | 400 | pr_warning("Failed to open debuginfo file.\n"); |
386 | - return fd; | |
401 | + return -ENOENT; | |
387 | 402 | } |
388 | 403 | |
389 | - ret = find_line_range(fd, lr); | |
404 | + ret = debuginfo__find_line_range(dinfo, lr); | |
405 | + debuginfo__delete(dinfo); | |
390 | 406 | if (ret == 0) { |
391 | 407 | pr_warning("Specified source line is not found.\n"); |
392 | 408 | return -ENOENT; |
... | ... | @@ -448,7 +464,8 @@ |
448 | 464 | return ret; |
449 | 465 | } |
450 | 466 | |
451 | -static int show_available_vars_at(int fd, struct perf_probe_event *pev, | |
467 | +static int show_available_vars_at(struct debuginfo *dinfo, | |
468 | + struct perf_probe_event *pev, | |
452 | 469 | int max_vls, struct strfilter *_filter, |
453 | 470 | bool externs) |
454 | 471 | { |
... | ... | @@ -463,7 +480,8 @@ |
463 | 480 | return -EINVAL; |
464 | 481 | pr_debug("Searching variables at %s\n", buf); |
465 | 482 | |
466 | - ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); | |
483 | + ret = debuginfo__find_available_vars_at(dinfo, pev, &vls, | |
484 | + max_vls, externs); | |
467 | 485 | if (ret <= 0) { |
468 | 486 | pr_err("Failed to find variables at %s (%d)\n", buf, ret); |
469 | 487 | goto end; |
470 | 488 | |
471 | 489 | |
472 | 490 | |
... | ... | @@ -504,24 +522,26 @@ |
504 | 522 | int max_vls, const char *module, |
505 | 523 | struct strfilter *_filter, bool externs) |
506 | 524 | { |
507 | - int i, fd, ret = 0; | |
525 | + int i, ret = 0; | |
526 | + struct debuginfo *dinfo; | |
508 | 527 | |
509 | 528 | ret = init_vmlinux(); |
510 | 529 | if (ret < 0) |
511 | 530 | return ret; |
512 | 531 | |
532 | + dinfo = open_debuginfo(module); | |
533 | + if (!dinfo) { | |
534 | + pr_warning("Failed to open debuginfo file.\n"); | |
535 | + return -ENOENT; | |
536 | + } | |
537 | + | |
513 | 538 | setup_pager(); |
514 | 539 | |
515 | - for (i = 0; i < npevs && ret >= 0; i++) { | |
516 | - fd = open_vmlinux(module); | |
517 | - if (fd < 0) { | |
518 | - pr_warning("Failed to open debug information file.\n"); | |
519 | - ret = fd; | |
520 | - break; | |
521 | - } | |
522 | - ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter, | |
540 | + for (i = 0; i < npevs && ret >= 0; i++) | |
541 | + ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter, | |
523 | 542 | externs); |
524 | - } | |
543 | + | |
544 | + debuginfo__delete(dinfo); | |
525 | 545 | return ret; |
526 | 546 | } |
527 | 547 |
tools/perf/util/probe-finder.c
... | ... | @@ -116,29 +116,37 @@ |
116 | 116 | }; |
117 | 117 | |
118 | 118 | /* Get a Dwarf from offline image */ |
119 | -static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias) | |
119 | +static int debuginfo__init_offline_dwarf(struct debuginfo *self, | |
120 | + const char *path) | |
120 | 121 | { |
121 | 122 | Dwfl_Module *mod; |
122 | - Dwarf *dbg = NULL; | |
123 | + int fd; | |
123 | 124 | |
124 | - if (!dwflp) | |
125 | - return NULL; | |
125 | + fd = open(path, O_RDONLY); | |
126 | + if (fd < 0) | |
127 | + return fd; | |
126 | 128 | |
127 | - *dwflp = dwfl_begin(&offline_callbacks); | |
128 | - if (!*dwflp) | |
129 | - return NULL; | |
129 | + self->dwfl = dwfl_begin(&offline_callbacks); | |
130 | + if (!self->dwfl) | |
131 | + goto error; | |
130 | 132 | |
131 | - mod = dwfl_report_offline(*dwflp, "", "", fd); | |
133 | + mod = dwfl_report_offline(self->dwfl, "", "", fd); | |
132 | 134 | if (!mod) |
133 | 135 | goto error; |
134 | 136 | |
135 | - dbg = dwfl_module_getdwarf(mod, bias); | |
136 | - if (!dbg) { | |
137 | + self->dbg = dwfl_module_getdwarf(mod, &self->bias); | |
138 | + if (!self->dbg) | |
139 | + goto error; | |
140 | + | |
141 | + return 0; | |
137 | 142 | error: |
138 | - dwfl_end(*dwflp); | |
139 | - *dwflp = NULL; | |
140 | - } | |
141 | - return dbg; | |
143 | + if (self->dwfl) | |
144 | + dwfl_end(self->dwfl); | |
145 | + else | |
146 | + close(fd); | |
147 | + memset(self, 0, sizeof(*self)); | |
148 | + | |
149 | + return -ENOENT; | |
142 | 150 | } |
143 | 151 | |
144 | 152 | #if _ELFUTILS_PREREQ(0, 148) |
145 | 153 | |
146 | 154 | |
147 | 155 | |
148 | 156 | |
149 | 157 | |
150 | 158 | |
151 | 159 | |
152 | 160 | |
153 | 161 | |
154 | 162 | |
155 | 163 | |
156 | 164 | |
157 | 165 | |
158 | 166 | |
... | ... | @@ -174,54 +182,83 @@ |
174 | 182 | }; |
175 | 183 | |
176 | 184 | /* Get a Dwarf from live kernel image */ |
177 | -static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, | |
178 | - Dwarf_Addr *bias) | |
185 | +static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, | |
186 | + Dwarf_Addr addr) | |
179 | 187 | { |
180 | - Dwarf *dbg; | |
188 | + self->dwfl = dwfl_begin(&kernel_callbacks); | |
189 | + if (!self->dwfl) | |
190 | + return -EINVAL; | |
181 | 191 | |
182 | - if (!dwflp) | |
183 | - return NULL; | |
184 | - | |
185 | - *dwflp = dwfl_begin(&kernel_callbacks); | |
186 | - if (!*dwflp) | |
187 | - return NULL; | |
188 | - | |
189 | 192 | /* Load the kernel dwarves: Don't care the result here */ |
190 | - dwfl_linux_kernel_report_kernel(*dwflp); | |
191 | - dwfl_linux_kernel_report_modules(*dwflp); | |
193 | + dwfl_linux_kernel_report_kernel(self->dwfl); | |
194 | + dwfl_linux_kernel_report_modules(self->dwfl); | |
192 | 195 | |
193 | - dbg = dwfl_addrdwarf(*dwflp, addr, bias); | |
196 | + self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias); | |
194 | 197 | /* Here, check whether we could get a real dwarf */ |
195 | - if (!dbg) { | |
198 | + if (!self->dbg) { | |
196 | 199 | pr_debug("Failed to find kernel dwarf at %lx\n", |
197 | 200 | (unsigned long)addr); |
198 | - dwfl_end(*dwflp); | |
199 | - *dwflp = NULL; | |
201 | + dwfl_end(self->dwfl); | |
202 | + memset(self, 0, sizeof(*self)); | |
203 | + return -ENOENT; | |
200 | 204 | } |
201 | - return dbg; | |
205 | + | |
206 | + return 0; | |
202 | 207 | } |
203 | 208 | #else |
204 | 209 | /* With older elfutils, this just support kernel module... */ |
205 | -static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp, | |
206 | - Dwarf_Addr *bias) | |
210 | +static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, | |
211 | + Dwarf_Addr addr __used) | |
207 | 212 | { |
208 | - int fd; | |
209 | 213 | const char *path = kernel_get_module_path("kernel"); |
210 | 214 | |
211 | 215 | if (!path) { |
212 | 216 | pr_err("Failed to find vmlinux path\n"); |
213 | - return NULL; | |
217 | + return -ENOENT; | |
214 | 218 | } |
215 | 219 | |
216 | 220 | pr_debug2("Use file %s for debuginfo\n", path); |
217 | - fd = open(path, O_RDONLY); | |
218 | - if (fd < 0) | |
221 | + return debuginfo__init_offline_dwarf(self, path); | |
222 | +} | |
223 | +#endif | |
224 | + | |
225 | +struct debuginfo *debuginfo__new(const char *path) | |
226 | +{ | |
227 | + struct debuginfo *self = zalloc(sizeof(struct debuginfo)); | |
228 | + if (!self) | |
219 | 229 | return NULL; |
220 | 230 | |
221 | - return dwfl_init_offline_dwarf(fd, dwflp, bias); | |
231 | + if (debuginfo__init_offline_dwarf(self, path) < 0) { | |
232 | + free(self); | |
233 | + self = NULL; | |
234 | + } | |
235 | + | |
236 | + return self; | |
222 | 237 | } |
223 | -#endif | |
224 | 238 | |
239 | +struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) | |
240 | +{ | |
241 | + struct debuginfo *self = zalloc(sizeof(struct debuginfo)); | |
242 | + if (!self) | |
243 | + return NULL; | |
244 | + | |
245 | + if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) { | |
246 | + free(self); | |
247 | + self = NULL; | |
248 | + } | |
249 | + | |
250 | + return self; | |
251 | +} | |
252 | + | |
253 | +void debuginfo__delete(struct debuginfo *self) | |
254 | +{ | |
255 | + if (self) { | |
256 | + if (self->dwfl) | |
257 | + dwfl_end(self->dwfl); | |
258 | + free(self); | |
259 | + } | |
260 | +} | |
261 | + | |
225 | 262 | /* |
226 | 263 | * Probe finder related functions |
227 | 264 | */ |
228 | 265 | |
229 | 266 | |
230 | 267 | |
... | ... | @@ -949,28 +986,18 @@ |
949 | 986 | } |
950 | 987 | |
951 | 988 | /* Find probe points from debuginfo */ |
952 | -static int find_probes(int fd, struct probe_finder *pf) | |
989 | +static int debuginfo__find_probes(struct debuginfo *self, | |
990 | + struct probe_finder *pf) | |
953 | 991 | { |
954 | 992 | struct perf_probe_point *pp = &pf->pev->point; |
955 | 993 | Dwarf_Off off, noff; |
956 | 994 | size_t cuhl; |
957 | 995 | Dwarf_Die *diep; |
958 | - Dwarf *dbg = NULL; | |
959 | - Dwfl *dwfl; | |
960 | - Dwarf_Addr bias; /* Currently ignored */ | |
961 | 996 | int ret = 0; |
962 | 997 | |
963 | - dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); | |
964 | - if (!dbg) { | |
965 | - pr_warning("No debug information found in the vmlinux - " | |
966 | - "please rebuild with CONFIG_DEBUG_INFO=y.\n"); | |
967 | - close(fd); /* Without dwfl_end(), fd isn't closed. */ | |
968 | - return -EBADF; | |
969 | - } | |
970 | - | |
971 | 998 | #if _ELFUTILS_PREREQ(0, 142) |
972 | 999 | /* Get the call frame information from this dwarf */ |
973 | - pf->cfi = dwarf_getcfi(dbg); | |
1000 | + pf->cfi = dwarf_getcfi(self->dbg); | |
974 | 1001 | #endif |
975 | 1002 | |
976 | 1003 | off = 0; |
... | ... | @@ -989,7 +1016,8 @@ |
989 | 1016 | .data = pf, |
990 | 1017 | }; |
991 | 1018 | |
992 | - dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); | |
1019 | + dwarf_getpubnames(self->dbg, pubname_search_cb, | |
1020 | + &pubname_param, 0); | |
993 | 1021 | if (pubname_param.found) { |
994 | 1022 | ret = probe_point_search_cb(&pf->sp_die, &probe_param); |
995 | 1023 | if (ret) |
996 | 1024 | |
... | ... | @@ -998,9 +1026,9 @@ |
998 | 1026 | } |
999 | 1027 | |
1000 | 1028 | /* Loop on CUs (Compilation Unit) */ |
1001 | - while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { | |
1029 | + while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { | |
1002 | 1030 | /* Get the DIE(Debugging Information Entry) of this CU */ |
1003 | - diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die); | |
1031 | + diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die); | |
1004 | 1032 | if (!diep) |
1005 | 1033 | continue; |
1006 | 1034 | |
... | ... | @@ -1027,8 +1055,6 @@ |
1027 | 1055 | |
1028 | 1056 | found: |
1029 | 1057 | line_list__free(&pf->lcache); |
1030 | - if (dwfl) | |
1031 | - dwfl_end(dwfl); | |
1032 | 1058 | |
1033 | 1059 | return ret; |
1034 | 1060 | } |
... | ... | @@ -1074,8 +1100,9 @@ |
1074 | 1100 | } |
1075 | 1101 | |
1076 | 1102 | /* Find probe_trace_events specified by perf_probe_event from debuginfo */ |
1077 | -int find_probe_trace_events(int fd, struct perf_probe_event *pev, | |
1078 | - struct probe_trace_event **tevs, int max_tevs) | |
1103 | +int debuginfo__find_trace_events(struct debuginfo *self, | |
1104 | + struct perf_probe_event *pev, | |
1105 | + struct probe_trace_event **tevs, int max_tevs) | |
1079 | 1106 | { |
1080 | 1107 | struct trace_event_finder tf = { |
1081 | 1108 | .pf = {.pev = pev, .callback = add_probe_trace_event}, |
... | ... | @@ -1090,7 +1117,7 @@ |
1090 | 1117 | tf.tevs = *tevs; |
1091 | 1118 | tf.ntevs = 0; |
1092 | 1119 | |
1093 | - ret = find_probes(fd, &tf.pf); | |
1120 | + ret = debuginfo__find_probes(self, &tf.pf); | |
1094 | 1121 | if (ret < 0) { |
1095 | 1122 | free(*tevs); |
1096 | 1123 | *tevs = NULL; |
... | ... | @@ -1184,9 +1211,10 @@ |
1184 | 1211 | } |
1185 | 1212 | |
1186 | 1213 | /* Find available variables at given probe point */ |
1187 | -int find_available_vars_at(int fd, struct perf_probe_event *pev, | |
1188 | - struct variable_list **vls, int max_vls, | |
1189 | - bool externs) | |
1214 | +int debuginfo__find_available_vars_at(struct debuginfo *self, | |
1215 | + struct perf_probe_event *pev, | |
1216 | + struct variable_list **vls, | |
1217 | + int max_vls, bool externs) | |
1190 | 1218 | { |
1191 | 1219 | struct available_var_finder af = { |
1192 | 1220 | .pf = {.pev = pev, .callback = add_available_vars}, |
... | ... | @@ -1201,7 +1229,7 @@ |
1201 | 1229 | af.vls = *vls; |
1202 | 1230 | af.nvls = 0; |
1203 | 1231 | |
1204 | - ret = find_probes(fd, &af.pf); | |
1232 | + ret = debuginfo__find_probes(self, &af.pf); | |
1205 | 1233 | if (ret < 0) { |
1206 | 1234 | /* Free vlist for error */ |
1207 | 1235 | while (af.nvls--) { |
1208 | 1236 | |
1209 | 1237 | |
1210 | 1238 | |
1211 | 1239 | |
... | ... | @@ -1219,28 +1247,19 @@ |
1219 | 1247 | } |
1220 | 1248 | |
1221 | 1249 | /* Reverse search */ |
1222 | -int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) | |
1250 | +int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr, | |
1251 | + struct perf_probe_point *ppt) | |
1223 | 1252 | { |
1224 | 1253 | Dwarf_Die cudie, spdie, indie; |
1225 | - Dwarf *dbg = NULL; | |
1226 | - Dwfl *dwfl = NULL; | |
1227 | - Dwarf_Addr _addr, baseaddr, bias = 0; | |
1254 | + Dwarf_Addr _addr, baseaddr; | |
1228 | 1255 | const char *fname = NULL, *func = NULL, *tmp; |
1229 | 1256 | int baseline = 0, lineno = 0, ret = 0; |
1230 | 1257 | |
1231 | - /* Open the live linux kernel */ | |
1232 | - dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); | |
1233 | - if (!dbg) { | |
1234 | - pr_warning("No debug information found in the vmlinux - " | |
1235 | - "please rebuild with CONFIG_DEBUG_INFO=y.\n"); | |
1236 | - ret = -EINVAL; | |
1237 | - goto end; | |
1238 | - } | |
1239 | - | |
1240 | 1258 | /* Adjust address with bias */ |
1241 | - addr += bias; | |
1259 | + addr += self->bias; | |
1260 | + | |
1242 | 1261 | /* Find cu die */ |
1243 | - if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) { | |
1262 | + if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) { | |
1244 | 1263 | pr_warning("Failed to find debug information for address %lx\n", |
1245 | 1264 | addr); |
1246 | 1265 | ret = -EINVAL; |
... | ... | @@ -1316,8 +1335,6 @@ |
1316 | 1335 | } |
1317 | 1336 | } |
1318 | 1337 | end: |
1319 | - if (dwfl) | |
1320 | - dwfl_end(dwfl); | |
1321 | 1338 | if (ret == 0 && (fname || func)) |
1322 | 1339 | ret = 1; /* Found a point */ |
1323 | 1340 | return ret; |
1324 | 1341 | |
1325 | 1342 | |
... | ... | @@ -1427,26 +1444,15 @@ |
1427 | 1444 | return param.retval; |
1428 | 1445 | } |
1429 | 1446 | |
1430 | -int find_line_range(int fd, struct line_range *lr) | |
1447 | +int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr) | |
1431 | 1448 | { |
1432 | 1449 | struct line_finder lf = {.lr = lr, .found = 0}; |
1433 | 1450 | int ret = 0; |
1434 | 1451 | Dwarf_Off off = 0, noff; |
1435 | 1452 | size_t cuhl; |
1436 | 1453 | Dwarf_Die *diep; |
1437 | - Dwarf *dbg = NULL; | |
1438 | - Dwfl *dwfl; | |
1439 | - Dwarf_Addr bias; /* Currently ignored */ | |
1440 | 1454 | const char *comp_dir; |
1441 | 1455 | |
1442 | - dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); | |
1443 | - if (!dbg) { | |
1444 | - pr_warning("No debug information found in the vmlinux - " | |
1445 | - "please rebuild with CONFIG_DEBUG_INFO=y.\n"); | |
1446 | - close(fd); /* Without dwfl_end(), fd isn't closed. */ | |
1447 | - return -EBADF; | |
1448 | - } | |
1449 | - | |
1450 | 1456 | /* Fastpath: lookup by function name from .debug_pubnames section */ |
1451 | 1457 | if (lr->function) { |
1452 | 1458 | struct pubname_callback_param pubname_param = { |
... | ... | @@ -1455,7 +1461,8 @@ |
1455 | 1461 | struct dwarf_callback_param line_range_param = { |
1456 | 1462 | .data = (void *)&lf, .retval = 0}; |
1457 | 1463 | |
1458 | - dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); | |
1464 | + dwarf_getpubnames(self->dbg, pubname_search_cb, | |
1465 | + &pubname_param, 0); | |
1459 | 1466 | if (pubname_param.found) { |
1460 | 1467 | line_range_search_cb(&lf.sp_die, &line_range_param); |
1461 | 1468 | if (lf.found) |
1462 | 1469 | |
... | ... | @@ -1465,11 +1472,12 @@ |
1465 | 1472 | |
1466 | 1473 | /* Loop on CUs (Compilation Unit) */ |
1467 | 1474 | while (!lf.found && ret >= 0) { |
1468 | - if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) | |
1475 | + if (dwarf_nextcu(self->dbg, off, &noff, &cuhl, | |
1476 | + NULL, NULL, NULL) != 0) | |
1469 | 1477 | break; |
1470 | 1478 | |
1471 | 1479 | /* Get the DIE(Debugging Information Entry) of this CU */ |
1472 | - diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die); | |
1480 | + diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die); | |
1473 | 1481 | if (!diep) |
1474 | 1482 | continue; |
1475 | 1483 | |
... | ... | @@ -1503,7 +1511,6 @@ |
1503 | 1511 | } |
1504 | 1512 | |
1505 | 1513 | pr_debug("path: %s\n", lr->path); |
1506 | - dwfl_end(dwfl); | |
1507 | 1514 | return (ret < 0) ? ret : lf.found; |
1508 | 1515 | } |
tools/perf/util/probe-finder.h
... | ... | @@ -16,23 +16,42 @@ |
16 | 16 | } |
17 | 17 | |
18 | 18 | #ifdef DWARF_SUPPORT |
19 | + | |
20 | +#include "dwarf-aux.h" | |
21 | + | |
22 | +/* TODO: export debuginfo data structure even if no dwarf support */ | |
23 | + | |
24 | +/* debug information structure */ | |
25 | +struct debuginfo { | |
26 | + Dwarf *dbg; | |
27 | + Dwfl *dwfl; | |
28 | + Dwarf_Addr bias; | |
29 | +}; | |
30 | + | |
31 | +extern struct debuginfo *debuginfo__new(const char *path); | |
32 | +extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr); | |
33 | +extern void debuginfo__delete(struct debuginfo *self); | |
34 | + | |
19 | 35 | /* Find probe_trace_events specified by perf_probe_event from debuginfo */ |
20 | -extern int find_probe_trace_events(int fd, struct perf_probe_event *pev, | |
21 | - struct probe_trace_event **tevs, | |
22 | - int max_tevs); | |
36 | +extern int debuginfo__find_trace_events(struct debuginfo *self, | |
37 | + struct perf_probe_event *pev, | |
38 | + struct probe_trace_event **tevs, | |
39 | + int max_tevs); | |
23 | 40 | |
24 | 41 | /* Find a perf_probe_point from debuginfo */ |
25 | -extern int find_perf_probe_point(unsigned long addr, | |
26 | - struct perf_probe_point *ppt); | |
42 | +extern int debuginfo__find_probe_point(struct debuginfo *self, | |
43 | + unsigned long addr, | |
44 | + struct perf_probe_point *ppt); | |
27 | 45 | |
28 | 46 | /* Find a line range */ |
29 | -extern int find_line_range(int fd, struct line_range *lr); | |
47 | +extern int debuginfo__find_line_range(struct debuginfo *self, | |
48 | + struct line_range *lr); | |
30 | 49 | |
31 | 50 | /* Find available variables */ |
32 | -extern int find_available_vars_at(int fd, struct perf_probe_event *pev, | |
33 | - struct variable_list **vls, int max_points, | |
34 | - bool externs); | |
35 | -#include "dwarf-aux.h" | |
51 | +extern int debuginfo__find_available_vars_at(struct debuginfo *self, | |
52 | + struct perf_probe_event *pev, | |
53 | + struct variable_list **vls, | |
54 | + int max_points, bool externs); | |
36 | 55 | |
37 | 56 | struct probe_finder { |
38 | 57 | struct perf_probe_event *pev; /* Target probe event */ |