aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2011-06-27 03:27:39 -0400
committerSteven Rostedt <rostedt@goodmis.org>2011-07-15 16:14:19 -0400
commitff741783506c340035659a71be68ddb4068760d1 (patch)
tree90ccff5203ae54e738ab98d6a73f88fa5bc5a5b1 /tools
parente0d153c69040bb37cbdf09deb52fee3013c07742 (diff)
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>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/probe-event.c78
-rw-r--r--tools/perf/util/probe-finder.c201
-rw-r--r--tools/perf/util/probe-finder.h39
3 files changed, 182 insertions, 136 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index f0223166e761..920c1957d6d3 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -170,16 +170,17 @@ const char *kernel_get_module_path(const char *module)
170} 170}
171 171
172#ifdef DWARF_SUPPORT 172#ifdef DWARF_SUPPORT
173static int open_vmlinux(const char *module) 173/* Open new debuginfo of given module */
174static struct debuginfo *open_debuginfo(const char *module)
174{ 175{
175 const char *path = kernel_get_module_path(module); 176 const char *path = kernel_get_module_path(module);
177
176 if (!path) { 178 if (!path) {
177 pr_err("Failed to find path of %s module.\n", 179 pr_err("Failed to find path of %s module.\n",
178 module ?: "kernel"); 180 module ?: "kernel");
179 return -ENOENT; 181 return NULL;
180 } 182 }
181 pr_debug("Try to open %s\n", path); 183 return debuginfo__new(path);
182 return open(path, O_RDONLY);
183} 184}
184 185
185/* 186/*
@@ -193,13 +194,24 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
193 struct map *map; 194 struct map *map;
194 u64 addr; 195 u64 addr;
195 int ret = -ENOENT; 196 int ret = -ENOENT;
197 struct debuginfo *dinfo;
196 198
197 sym = __find_kernel_function_by_name(tp->symbol, &map); 199 sym = __find_kernel_function_by_name(tp->symbol, &map);
198 if (sym) { 200 if (sym) {
199 addr = map->unmap_ip(map, sym->start + tp->offset); 201 addr = map->unmap_ip(map, sym->start + tp->offset);
200 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, 202 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
201 tp->offset, addr); 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 if (ret <= 0) { 216 if (ret <= 0) {
205 pr_debug("Failed to find corresponding probes from " 217 pr_debug("Failed to find corresponding probes from "
@@ -220,20 +232,22 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
220 int max_tevs, const char *module) 232 int max_tevs, const char *module)
221{ 233{
222 bool need_dwarf = perf_probe_event_need_dwarf(pev); 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); 238 if (!dinfo) {
226 if (fd < 0) {
227 if (need_dwarf) { 239 if (need_dwarf) {
228 pr_warning("Failed to open debuginfo file.\n"); 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 return 0; 244 return 0;
233 } 245 }
234 246
235 /* Searching trace events corresponding to probe event */ 247 /* Searching trace events corresponding to a probe event */
236 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); 248 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
249
250 debuginfo__delete(dinfo);
237 251
238 if (ntevs > 0) { /* Succeeded to find trace events */ 252 if (ntevs > 0) { /* Succeeded to find trace events */
239 pr_debug("find %d probe_trace_events.\n", ntevs); 253 pr_debug("find %d probe_trace_events.\n", ntevs);
@@ -371,8 +385,9 @@ int show_line_range(struct line_range *lr, const char *module)
371{ 385{
372 int l = 1; 386 int l = 1;
373 struct line_node *ln; 387 struct line_node *ln;
388 struct debuginfo *dinfo;
374 FILE *fp; 389 FILE *fp;
375 int fd, ret; 390 int ret;
376 char *tmp; 391 char *tmp;
377 392
378 /* Search a line range */ 393 /* Search a line range */
@@ -380,13 +395,14 @@ int show_line_range(struct line_range *lr, const char *module)
380 if (ret < 0) 395 if (ret < 0)
381 return ret; 396 return ret;
382 397
383 fd = open_vmlinux(module); 398 dinfo = open_debuginfo(module);
384 if (fd < 0) { 399 if (!dinfo) {
385 pr_warning("Failed to open debuginfo file.\n"); 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 if (ret == 0) { 406 if (ret == 0) {
391 pr_warning("Specified source line is not found.\n"); 407 pr_warning("Specified source line is not found.\n");
392 return -ENOENT; 408 return -ENOENT;
@@ -448,7 +464,8 @@ end:
448 return ret; 464 return ret;
449} 465}
450 466
451static int show_available_vars_at(int fd, struct perf_probe_event *pev, 467static int show_available_vars_at(struct debuginfo *dinfo,
468 struct perf_probe_event *pev,
452 int max_vls, struct strfilter *_filter, 469 int max_vls, struct strfilter *_filter,
453 bool externs) 470 bool externs)
454{ 471{
@@ -463,7 +480,8 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
463 return -EINVAL; 480 return -EINVAL;
464 pr_debug("Searching variables at %s\n", buf); 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 if (ret <= 0) { 485 if (ret <= 0) {
468 pr_err("Failed to find variables at %s (%d)\n", buf, ret); 486 pr_err("Failed to find variables at %s (%d)\n", buf, ret);
469 goto end; 487 goto end;
@@ -504,24 +522,26 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
504 int max_vls, const char *module, 522 int max_vls, const char *module,
505 struct strfilter *_filter, bool externs) 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 ret = init_vmlinux(); 528 ret = init_vmlinux();
510 if (ret < 0) 529 if (ret < 0)
511 return ret; 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 setup_pager(); 538 setup_pager();
514 539
515 for (i = 0; i < npevs && ret >= 0; i++) { 540 for (i = 0; i < npevs && ret >= 0; i++)
516 fd = open_vmlinux(module); 541 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
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,
523 externs); 542 externs);
524 } 543
544 debuginfo__delete(dinfo);
525 return ret; 545 return ret;
526} 546}
527 547
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 53d219bddb48..3e44a3e36519 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -116,29 +116,37 @@ static const Dwfl_Callbacks offline_callbacks = {
116}; 116};
117 117
118/* Get a Dwarf from offline image */ 118/* Get a Dwarf from offline image */
119static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias) 119static int debuginfo__init_offline_dwarf(struct debuginfo *self,
120 const char *path)
120{ 121{
121 Dwfl_Module *mod; 122 Dwfl_Module *mod;
122 Dwarf *dbg = NULL; 123 int fd;
123 124
124 if (!dwflp) 125 fd = open(path, O_RDONLY);
125 return NULL; 126 if (fd < 0)
127 return fd;
126 128
127 *dwflp = dwfl_begin(&offline_callbacks); 129 self->dwfl = dwfl_begin(&offline_callbacks);
128 if (!*dwflp) 130 if (!self->dwfl)
129 return NULL; 131 goto error;
130 132
131 mod = dwfl_report_offline(*dwflp, "", "", fd); 133 mod = dwfl_report_offline(self->dwfl, "", "", fd);
132 if (!mod) 134 if (!mod)
133 goto error; 135 goto error;
134 136
135 dbg = dwfl_module_getdwarf(mod, bias); 137 self->dbg = dwfl_module_getdwarf(mod, &self->bias);
136 if (!dbg) { 138 if (!self->dbg)
139 goto error;
140
141 return 0;
137error: 142error:
138 dwfl_end(*dwflp); 143 if (self->dwfl)
139 *dwflp = NULL; 144 dwfl_end(self->dwfl);
140 } 145 else
141 return dbg; 146 close(fd);
147 memset(self, 0, sizeof(*self));
148
149 return -ENOENT;
142} 150}
143 151
144#if _ELFUTILS_PREREQ(0, 148) 152#if _ELFUTILS_PREREQ(0, 148)
@@ -174,53 +182,82 @@ static const Dwfl_Callbacks kernel_callbacks = {
174}; 182};
175 183
176/* Get a Dwarf from live kernel image */ 184/* Get a Dwarf from live kernel image */
177static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, 185static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
178 Dwarf_Addr *bias) 186 Dwarf_Addr addr)
179{ 187{
180 Dwarf *dbg; 188 self->dwfl = dwfl_begin(&kernel_callbacks);
181 189 if (!self->dwfl)
182 if (!dwflp) 190 return -EINVAL;
183 return NULL;
184
185 *dwflp = dwfl_begin(&kernel_callbacks);
186 if (!*dwflp)
187 return NULL;
188 191
189 /* Load the kernel dwarves: Don't care the result here */ 192 /* Load the kernel dwarves: Don't care the result here */
190 dwfl_linux_kernel_report_kernel(*dwflp); 193 dwfl_linux_kernel_report_kernel(self->dwfl);
191 dwfl_linux_kernel_report_modules(*dwflp); 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 /* Here, check whether we could get a real dwarf */ 197 /* Here, check whether we could get a real dwarf */
195 if (!dbg) { 198 if (!self->dbg) {
196 pr_debug("Failed to find kernel dwarf at %lx\n", 199 pr_debug("Failed to find kernel dwarf at %lx\n",
197 (unsigned long)addr); 200 (unsigned long)addr);
198 dwfl_end(*dwflp); 201 dwfl_end(self->dwfl);
199 *dwflp = NULL; 202 memset(self, 0, sizeof(*self));
203 return -ENOENT;
200 } 204 }
201 return dbg; 205
206 return 0;
202} 207}
203#else 208#else
204/* With older elfutils, this just support kernel module... */ 209/* With older elfutils, this just support kernel module... */
205static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp, 210static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
206 Dwarf_Addr *bias) 211 Dwarf_Addr addr __used)
207{ 212{
208 int fd;
209 const char *path = kernel_get_module_path("kernel"); 213 const char *path = kernel_get_module_path("kernel");
210 214
211 if (!path) { 215 if (!path) {
212 pr_err("Failed to find vmlinux path\n"); 216 pr_err("Failed to find vmlinux path\n");
213 return NULL; 217 return -ENOENT;
214 } 218 }
215 219
216 pr_debug2("Use file %s for debuginfo\n", path); 220 pr_debug2("Use file %s for debuginfo\n", path);
217 fd = open(path, O_RDONLY); 221 return debuginfo__init_offline_dwarf(self, path);
218 if (fd < 0) 222}
223#endif
224
225struct debuginfo *debuginfo__new(const char *path)
226{
227 struct debuginfo *self = zalloc(sizeof(struct debuginfo));
228 if (!self)
219 return NULL; 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;
237}
238
239struct 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
253void debuginfo__delete(struct debuginfo *self)
254{
255 if (self) {
256 if (self->dwfl)
257 dwfl_end(self->dwfl);
258 free(self);
259 }
222} 260}
223#endif
224 261
225/* 262/*
226 * Probe finder related functions 263 * Probe finder related functions
@@ -949,28 +986,18 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
949} 986}
950 987
951/* Find probe points from debuginfo */ 988/* Find probe points from debuginfo */
952static int find_probes(int fd, struct probe_finder *pf) 989static int debuginfo__find_probes(struct debuginfo *self,
990 struct probe_finder *pf)
953{ 991{
954 struct perf_probe_point *pp = &pf->pev->point; 992 struct perf_probe_point *pp = &pf->pev->point;
955 Dwarf_Off off, noff; 993 Dwarf_Off off, noff;
956 size_t cuhl; 994 size_t cuhl;
957 Dwarf_Die *diep; 995 Dwarf_Die *diep;
958 Dwarf *dbg = NULL;
959 Dwfl *dwfl;
960 Dwarf_Addr bias; /* Currently ignored */
961 int ret = 0; 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#if _ELFUTILS_PREREQ(0, 142) 998#if _ELFUTILS_PREREQ(0, 142)
972 /* Get the call frame information from this dwarf */ 999 /* Get the call frame information from this dwarf */
973 pf->cfi = dwarf_getcfi(dbg); 1000 pf->cfi = dwarf_getcfi(self->dbg);
974#endif 1001#endif
975 1002
976 off = 0; 1003 off = 0;
@@ -989,7 +1016,8 @@ static int find_probes(int fd, struct probe_finder *pf)
989 .data = pf, 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 if (pubname_param.found) { 1021 if (pubname_param.found) {
994 ret = probe_point_search_cb(&pf->sp_die, &probe_param); 1022 ret = probe_point_search_cb(&pf->sp_die, &probe_param);
995 if (ret) 1023 if (ret)
@@ -998,9 +1026,9 @@ static int find_probes(int fd, struct probe_finder *pf)
998 } 1026 }
999 1027
1000 /* Loop on CUs (Compilation Unit) */ 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 /* Get the DIE(Debugging Information Entry) of this CU */ 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 if (!diep) 1032 if (!diep)
1005 continue; 1033 continue;
1006 1034
@@ -1027,8 +1055,6 @@ static int find_probes(int fd, struct probe_finder *pf)
1027 1055
1028found: 1056found:
1029 line_list__free(&pf->lcache); 1057 line_list__free(&pf->lcache);
1030 if (dwfl)
1031 dwfl_end(dwfl);
1032 1058
1033 return ret; 1059 return ret;
1034} 1060}
@@ -1074,8 +1100,9 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
1074} 1100}
1075 1101
1076/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1102/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1077int find_probe_trace_events(int fd, struct perf_probe_event *pev, 1103int debuginfo__find_trace_events(struct debuginfo *self,
1078 struct probe_trace_event **tevs, int max_tevs) 1104 struct perf_probe_event *pev,
1105 struct probe_trace_event **tevs, int max_tevs)
1079{ 1106{
1080 struct trace_event_finder tf = { 1107 struct trace_event_finder tf = {
1081 .pf = {.pev = pev, .callback = add_probe_trace_event}, 1108 .pf = {.pev = pev, .callback = add_probe_trace_event},
@@ -1090,7 +1117,7 @@ int find_probe_trace_events(int fd, struct perf_probe_event *pev,
1090 tf.tevs = *tevs; 1117 tf.tevs = *tevs;
1091 tf.ntevs = 0; 1118 tf.ntevs = 0;
1092 1119
1093 ret = find_probes(fd, &tf.pf); 1120 ret = debuginfo__find_probes(self, &tf.pf);
1094 if (ret < 0) { 1121 if (ret < 0) {
1095 free(*tevs); 1122 free(*tevs);
1096 *tevs = NULL; 1123 *tevs = NULL;
@@ -1184,9 +1211,10 @@ out:
1184} 1211}
1185 1212
1186/* Find available variables at given probe point */ 1213/* Find available variables at given probe point */
1187int find_available_vars_at(int fd, struct perf_probe_event *pev, 1214int debuginfo__find_available_vars_at(struct debuginfo *self,
1188 struct variable_list **vls, int max_vls, 1215 struct perf_probe_event *pev,
1189 bool externs) 1216 struct variable_list **vls,
1217 int max_vls, bool externs)
1190{ 1218{
1191 struct available_var_finder af = { 1219 struct available_var_finder af = {
1192 .pf = {.pev = pev, .callback = add_available_vars}, 1220 .pf = {.pev = pev, .callback = add_available_vars},
@@ -1201,7 +1229,7 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev,
1201 af.vls = *vls; 1229 af.vls = *vls;
1202 af.nvls = 0; 1230 af.nvls = 0;
1203 1231
1204 ret = find_probes(fd, &af.pf); 1232 ret = debuginfo__find_probes(self, &af.pf);
1205 if (ret < 0) { 1233 if (ret < 0) {
1206 /* Free vlist for error */ 1234 /* Free vlist for error */
1207 while (af.nvls--) { 1235 while (af.nvls--) {
@@ -1219,28 +1247,19 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev,
1219} 1247}
1220 1248
1221/* Reverse search */ 1249/* Reverse search */
1222int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) 1250int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
1251 struct perf_probe_point *ppt)
1223{ 1252{
1224 Dwarf_Die cudie, spdie, indie; 1253 Dwarf_Die cudie, spdie, indie;
1225 Dwarf *dbg = NULL; 1254 Dwarf_Addr _addr, baseaddr;
1226 Dwfl *dwfl = NULL;
1227 Dwarf_Addr _addr, baseaddr, bias = 0;
1228 const char *fname = NULL, *func = NULL, *tmp; 1255 const char *fname = NULL, *func = NULL, *tmp;
1229 int baseline = 0, lineno = 0, ret = 0; 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 /* Adjust address with bias */ 1258 /* Adjust address with bias */
1241 addr += bias; 1259 addr += self->bias;
1260
1242 /* Find cu die */ 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 pr_warning("Failed to find debug information for address %lx\n", 1263 pr_warning("Failed to find debug information for address %lx\n",
1245 addr); 1264 addr);
1246 ret = -EINVAL; 1265 ret = -EINVAL;
@@ -1316,8 +1335,6 @@ post:
1316 } 1335 }
1317 } 1336 }
1318end: 1337end:
1319 if (dwfl)
1320 dwfl_end(dwfl);
1321 if (ret == 0 && (fname || func)) 1338 if (ret == 0 && (fname || func))
1322 ret = 1; /* Found a point */ 1339 ret = 1; /* Found a point */
1323 return ret; 1340 return ret;
@@ -1427,26 +1444,15 @@ static int find_line_range_by_func(struct line_finder *lf)
1427 return param.retval; 1444 return param.retval;
1428} 1445}
1429 1446
1430int find_line_range(int fd, struct line_range *lr) 1447int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
1431{ 1448{
1432 struct line_finder lf = {.lr = lr, .found = 0}; 1449 struct line_finder lf = {.lr = lr, .found = 0};
1433 int ret = 0; 1450 int ret = 0;
1434 Dwarf_Off off = 0, noff; 1451 Dwarf_Off off = 0, noff;
1435 size_t cuhl; 1452 size_t cuhl;
1436 Dwarf_Die *diep; 1453 Dwarf_Die *diep;
1437 Dwarf *dbg = NULL;
1438 Dwfl *dwfl;
1439 Dwarf_Addr bias; /* Currently ignored */
1440 const char *comp_dir; 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 /* Fastpath: lookup by function name from .debug_pubnames section */ 1456 /* Fastpath: lookup by function name from .debug_pubnames section */
1451 if (lr->function) { 1457 if (lr->function) {
1452 struct pubname_callback_param pubname_param = { 1458 struct pubname_callback_param pubname_param = {
@@ -1455,7 +1461,8 @@ int find_line_range(int fd, struct line_range *lr)
1455 struct dwarf_callback_param line_range_param = { 1461 struct dwarf_callback_param line_range_param = {
1456 .data = (void *)&lf, .retval = 0}; 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 if (pubname_param.found) { 1466 if (pubname_param.found) {
1460 line_range_search_cb(&lf.sp_die, &line_range_param); 1467 line_range_search_cb(&lf.sp_die, &line_range_param);
1461 if (lf.found) 1468 if (lf.found)
@@ -1465,11 +1472,12 @@ int find_line_range(int fd, struct line_range *lr)
1465 1472
1466 /* Loop on CUs (Compilation Unit) */ 1473 /* Loop on CUs (Compilation Unit) */
1467 while (!lf.found && ret >= 0) { 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 break; 1477 break;
1470 1478
1471 /* Get the DIE(Debugging Information Entry) of this CU */ 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 if (!diep) 1481 if (!diep)
1474 continue; 1482 continue;
1475 1483
@@ -1503,7 +1511,6 @@ found:
1503 } 1511 }
1504 1512
1505 pr_debug("path: %s\n", lr->path); 1513 pr_debug("path: %s\n", lr->path);
1506 dwfl_end(dwfl);
1507 return (ret < 0) ? ret : lf.found; 1514 return (ret < 0) ? ret : lf.found;
1508} 1515}
1509 1516
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 0f1ed3d25a20..c478b42a2473 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -16,23 +16,42 @@ static inline int is_c_varname(const char *name)
16} 16}
17 17
18#ifdef DWARF_SUPPORT 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 */
25struct debuginfo {
26 Dwarf *dbg;
27 Dwfl *dwfl;
28 Dwarf_Addr bias;
29};
30
31extern struct debuginfo *debuginfo__new(const char *path);
32extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
33extern void debuginfo__delete(struct debuginfo *self);
34
19/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 35/* Find probe_trace_events specified by perf_probe_event from debuginfo */
20extern int find_probe_trace_events(int fd, struct perf_probe_event *pev, 36extern int debuginfo__find_trace_events(struct debuginfo *self,
21 struct probe_trace_event **tevs, 37 struct perf_probe_event *pev,
22 int max_tevs); 38 struct probe_trace_event **tevs,
39 int max_tevs);
23 40
24/* Find a perf_probe_point from debuginfo */ 41/* Find a perf_probe_point from debuginfo */
25extern int find_perf_probe_point(unsigned long addr, 42extern int debuginfo__find_probe_point(struct debuginfo *self,
26 struct perf_probe_point *ppt); 43 unsigned long addr,
44 struct perf_probe_point *ppt);
27 45
28/* Find a line range */ 46/* Find a line range */
29extern int find_line_range(int fd, struct line_range *lr); 47extern int debuginfo__find_line_range(struct debuginfo *self,
48 struct line_range *lr);
30 49
31/* Find available variables */ 50/* Find available variables */
32extern int find_available_vars_at(int fd, struct perf_probe_event *pev, 51extern int debuginfo__find_available_vars_at(struct debuginfo *self,
33 struct variable_list **vls, int max_points, 52 struct perf_probe_event *pev,
34 bool externs); 53 struct variable_list **vls,
35#include "dwarf-aux.h" 54 int max_points, bool externs);
36 55
37struct probe_finder { 56struct probe_finder {
38 struct perf_probe_event *pev; /* Target probe event */ 57 struct perf_probe_event *pev; /* Target probe event */