aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2011-06-27 03:27:27 -0400
committerSteven Rostedt <rostedt@goodmis.org>2011-07-15 16:10:17 -0400
commite0d153c69040bb37cbdf09deb52fee3013c07742 (patch)
treee008ba8ac1f328b6938e80b9208d64c4548f8e8e
parentbcfc082150c6b1e9443c1277bca8be80094150b5 (diff)
perf-probe: Move dwarf library routines to dwarf-aux.{c, h}
Move dwarf library related routines to dwarf-aux.{c,h}. This includes several minor changes. - Add simple documents for each API. - Rename die_find_real_subprogram() to die_find_realfunc() - Rename line_walk_handler_t to line_walk_callback_t. - Minor cleanups. 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/20110627072727.6528.57647.stgit@fedora15 Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/util/dwarf-aux.c663
-rw-r--r--tools/perf/util/dwarf-aux.h100
-rw-r--r--tools/perf/util/probe-finder.c520
-rw-r--r--tools/perf/util/probe-finder.h6
5 files changed, 768 insertions, 523 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 940257b5774e..d0861bbd1d94 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -279,6 +279,7 @@ LIB_H += util/thread.h
279LIB_H += util/thread_map.h 279LIB_H += util/thread_map.h
280LIB_H += util/trace-event.h 280LIB_H += util/trace-event.h
281LIB_H += util/probe-finder.h 281LIB_H += util/probe-finder.h
282LIB_H += util/dwarf-aux.h
282LIB_H += util/probe-event.h 283LIB_H += util/probe-event.h
283LIB_H += util/pstack.h 284LIB_H += util/pstack.h
284LIB_H += util/cpumap.h 285LIB_H += util/cpumap.h
@@ -435,6 +436,7 @@ else
435 BASIC_CFLAGS += -DDWARF_SUPPORT 436 BASIC_CFLAGS += -DDWARF_SUPPORT
436 EXTLIBS += -lelf -ldw 437 EXTLIBS += -lelf -ldw
437 LIB_OBJS += $(OUTPUT)util/probe-finder.o 438 LIB_OBJS += $(OUTPUT)util/probe-finder.o
439 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
438endif # PERF_HAVE_DWARF_REGS 440endif # PERF_HAVE_DWARF_REGS
439endif # NO_DWARF 441endif # NO_DWARF
440 442
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
new file mode 100644
index 000000000000..fddf40f30d3e
--- /dev/null
+++ b/tools/perf/util/dwarf-aux.c
@@ -0,0 +1,663 @@
1/*
2 * dwarf-aux.c : libdw auxiliary interfaces
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 */
19
20#include <stdbool.h>
21#include "util.h"
22#include "debug.h"
23#include "dwarf-aux.h"
24
25/**
26 * cu_find_realpath - Find the realpath of the target file
27 * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit)
28 * @fname: The tail filename of the target file
29 *
30 * Find the real(long) path of @fname in @cu_die.
31 */
32const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
33{
34 Dwarf_Files *files;
35 size_t nfiles, i;
36 const char *src = NULL;
37 int ret;
38
39 if (!fname)
40 return NULL;
41
42 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
43 if (ret != 0)
44 return NULL;
45
46 for (i = 0; i < nfiles; i++) {
47 src = dwarf_filesrc(files, i, NULL, NULL);
48 if (strtailcmp(src, fname) == 0)
49 break;
50 }
51 if (i == nfiles)
52 return NULL;
53 return src;
54}
55
56/**
57 * cu_get_comp_dir - Get the path of compilation directory
58 * @cu_die: a CU DIE
59 *
60 * Get the path of compilation directory of given @cu_die.
61 * Since this depends on DW_AT_comp_dir, older gcc will not
62 * embedded it. In that case, this returns NULL.
63 */
64const char *cu_get_comp_dir(Dwarf_Die *cu_die)
65{
66 Dwarf_Attribute attr;
67 if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
68 return NULL;
69 return dwarf_formstring(&attr);
70}
71
72/**
73 * cu_find_lineinfo - Get a line number and file name for given address
74 * @cu_die: a CU DIE
75 * @addr: An address
76 * @fname: a pointer which returns the file name string
77 * @lineno: a pointer which returns the line number
78 *
79 * Find a line number and file name for @addr in @cu_die.
80 */
81int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
82 const char **fname, int *lineno)
83{
84 Dwarf_Line *line;
85 Dwarf_Addr laddr;
86
87 line = dwarf_getsrc_die(cu_die, (Dwarf_Addr)addr);
88 if (line && dwarf_lineaddr(line, &laddr) == 0 &&
89 addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
90 *fname = dwarf_linesrc(line, NULL, NULL);
91 if (!*fname)
92 /* line number is useless without filename */
93 *lineno = 0;
94 }
95
96 return *lineno ?: -ENOENT;
97}
98
99/**
100 * die_compare_name - Compare diename and tname
101 * @dw_die: a DIE
102 * @tname: a string of target name
103 *
104 * Compare the name of @dw_die and @tname. Return false if @dw_die has no name.
105 */
106bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
107{
108 const char *name;
109 name = dwarf_diename(dw_die);
110 return name ? (strcmp(tname, name) == 0) : false;
111}
112
113/**
114 * die_get_call_lineno - Get callsite line number of inline-function instance
115 * @in_die: a DIE of an inlined function instance
116 *
117 * Get call-site line number of @in_die. This means from where the inline
118 * function is called.
119 */
120int die_get_call_lineno(Dwarf_Die *in_die)
121{
122 Dwarf_Attribute attr;
123 Dwarf_Word ret;
124
125 if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
126 return -ENOENT;
127
128 dwarf_formudata(&attr, &ret);
129 return (int)ret;
130}
131
132/**
133 * die_get_type - Get type DIE
134 * @vr_die: a DIE of a variable
135 * @die_mem: where to store a type DIE
136 *
137 * Get a DIE of the type of given variable (@vr_die), and store
138 * it to die_mem. Return NULL if fails to get a type DIE.
139 */
140Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
141{
142 Dwarf_Attribute attr;
143
144 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
145 dwarf_formref_die(&attr, die_mem))
146 return die_mem;
147 else
148 return NULL;
149}
150
151/* Get a type die, but skip qualifiers */
152static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
153{
154 int tag;
155
156 do {
157 vr_die = die_get_type(vr_die, die_mem);
158 if (!vr_die)
159 break;
160 tag = dwarf_tag(vr_die);
161 } while (tag == DW_TAG_const_type ||
162 tag == DW_TAG_restrict_type ||
163 tag == DW_TAG_volatile_type ||
164 tag == DW_TAG_shared_type);
165
166 return vr_die;
167}
168
169/**
170 * die_get_real_type - Get a type die, but skip qualifiers and typedef
171 * @vr_die: a DIE of a variable
172 * @die_mem: where to store a type DIE
173 *
174 * Get a DIE of the type of given variable (@vr_die), and store
175 * it to die_mem. Return NULL if fails to get a type DIE.
176 * If the type is qualifiers (e.g. const) or typedef, this skips it
177 * and tries to find real type (structure or basic types, e.g. int).
178 */
179Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
180{
181 do {
182 vr_die = __die_get_real_type(vr_die, die_mem);
183 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
184
185 return vr_die;
186}
187
188/* Get attribute and translate it as a udata */
189static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
190 Dwarf_Word *result)
191{
192 Dwarf_Attribute attr;
193
194 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
195 dwarf_formudata(&attr, result) != 0)
196 return -ENOENT;
197
198 return 0;
199}
200
201/**
202 * die_is_signed_type - Check whether a type DIE is signed or not
203 * @tp_die: a DIE of a type
204 *
205 * Get the encoding of @tp_die and return true if the encoding
206 * is signed.
207 */
208bool die_is_signed_type(Dwarf_Die *tp_die)
209{
210 Dwarf_Word ret;
211
212 if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
213 return false;
214
215 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
216 ret == DW_ATE_signed_fixed);
217}
218
219/**
220 * die_get_data_member_location - Get the data-member offset
221 * @mb_die: a DIE of a member of a data structure
222 * @offs: The offset of the member in the data structure
223 *
224 * Get the offset of @mb_die in the data structure including @mb_die, and
225 * stores result offset to @offs. If any error occurs this returns errno.
226 */
227int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
228{
229 Dwarf_Attribute attr;
230 Dwarf_Op *expr;
231 size_t nexpr;
232 int ret;
233
234 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
235 return -ENOENT;
236
237 if (dwarf_formudata(&attr, offs) != 0) {
238 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
239 ret = dwarf_getlocation(&attr, &expr, &nexpr);
240 if (ret < 0 || nexpr == 0)
241 return -ENOENT;
242
243 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
244 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
245 expr[0].atom, nexpr);
246 return -ENOTSUP;
247 }
248 *offs = (Dwarf_Word)expr[0].number;
249 }
250 return 0;
251}
252
253/**
254 * die_find_child - Generic DIE search function in DIE tree
255 * @rt_die: a root DIE
256 * @callback: a callback function
257 * @data: a user data passed to the callback function
258 * @die_mem: a buffer for result DIE
259 *
260 * Trace DIE tree from @rt_die and call @callback for each child DIE.
261 * If @callback returns DIE_FIND_CB_END, this stores the DIE into
262 * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE,
263 * this continues to trace the tree. Optionally, @callback can return
264 * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only
265 * the children and trace only the siblings respectively.
266 * Returns NULL if @callback can't find any appropriate DIE.
267 */
268Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
269 int (*callback)(Dwarf_Die *, void *),
270 void *data, Dwarf_Die *die_mem)
271{
272 Dwarf_Die child_die;
273 int ret;
274
275 ret = dwarf_child(rt_die, die_mem);
276 if (ret != 0)
277 return NULL;
278
279 do {
280 ret = callback(die_mem, data);
281 if (ret == DIE_FIND_CB_END)
282 return die_mem;
283
284 if ((ret & DIE_FIND_CB_CHILD) &&
285 die_find_child(die_mem, callback, data, &child_die)) {
286 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
287 return die_mem;
288 }
289 } while ((ret & DIE_FIND_CB_SIBLING) &&
290 dwarf_siblingof(die_mem, die_mem) == 0);
291
292 return NULL;
293}
294
295struct __addr_die_search_param {
296 Dwarf_Addr addr;
297 Dwarf_Die *die_mem;
298};
299
300/* die_find callback for non-inlined function search */
301static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
302{
303 struct __addr_die_search_param *ad = data;
304
305 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
306 dwarf_haspc(fn_die, ad->addr)) {
307 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
308 return DWARF_CB_ABORT;
309 }
310 return DWARF_CB_OK;
311}
312
313/**
314 * die_find_realfunc - Search a non-inlined function at given address
315 * @cu_die: a CU DIE which including @addr
316 * @addr: target address
317 * @die_mem: a buffer for result DIE
318 *
319 * Search a non-inlined function DIE which includes @addr. Stores the
320 * DIE to @die_mem and returns it if found. Returns NULl if failed.
321 */
322Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
323 Dwarf_Die *die_mem)
324{
325 struct __addr_die_search_param ad;
326 ad.addr = addr;
327 ad.die_mem = die_mem;
328 /* dwarf_getscopes can't find subprogram. */
329 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
330 return NULL;
331 else
332 return die_mem;
333}
334
335/* die_find callback for inline function search */
336static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
337{
338 Dwarf_Addr *addr = data;
339
340 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
341 dwarf_haspc(die_mem, *addr))
342 return DIE_FIND_CB_END;
343
344 return DIE_FIND_CB_CONTINUE;
345}
346
347/**
348 * die_find_inlinefunc - Search an inlined function at given address
349 * @cu_die: a CU DIE which including @addr
350 * @addr: target address
351 * @die_mem: a buffer for result DIE
352 *
353 * Search an inlined function DIE which includes @addr. Stores the
354 * DIE to @die_mem and returns it if found. Returns NULl if failed.
355 * If several inlined functions are expanded recursively, this trace
356 * it and returns deepest one.
357 */
358Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
359 Dwarf_Die *die_mem)
360{
361 Dwarf_Die tmp_die;
362
363 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
364 if (!sp_die)
365 return NULL;
366
367 /* Inlined function could be recursive. Trace it until fail */
368 while (sp_die) {
369 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
370 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
371 &tmp_die);
372 }
373
374 return die_mem;
375}
376
377/* Line walker internal parameters */
378struct __line_walk_param {
379 const char *fname;
380 line_walk_callback_t callback;
381 void *data;
382 int retval;
383};
384
385static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
386{
387 struct __line_walk_param *lw = data;
388 Dwarf_Addr addr;
389 int lineno;
390
391 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
392 lineno = die_get_call_lineno(in_die);
393 if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
394 lw->retval = lw->callback(lw->fname, lineno, addr,
395 lw->data);
396 if (lw->retval != 0)
397 return DIE_FIND_CB_END;
398 }
399 }
400 return DIE_FIND_CB_SIBLING;
401}
402
403/* Walk on lines of blocks included in given DIE */
404static int __die_walk_funclines(Dwarf_Die *sp_die,
405 line_walk_callback_t callback, void *data)
406{
407 struct __line_walk_param lw = {
408 .callback = callback,
409 .data = data,
410 .retval = 0,
411 };
412 Dwarf_Die die_mem;
413 Dwarf_Addr addr;
414 int lineno;
415
416 /* Handle function declaration line */
417 lw.fname = dwarf_decl_file(sp_die);
418 if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
419 dwarf_entrypc(sp_die, &addr) == 0) {
420 lw.retval = callback(lw.fname, lineno, addr, data);
421 if (lw.retval != 0)
422 goto done;
423 }
424 die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
425done:
426 return lw.retval;
427}
428
429static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
430{
431 struct __line_walk_param *lw = data;
432
433 lw->retval = __die_walk_funclines(sp_die, lw->callback, lw->data);
434 if (lw->retval != 0)
435 return DWARF_CB_ABORT;
436
437 return DWARF_CB_OK;
438}
439
440/**
441 * die_walk_lines - Walk on lines inside given DIE
442 * @rt_die: a root DIE (CU or subprogram)
443 * @callback: callback routine
444 * @data: user data
445 *
446 * Walk on all lines inside given @rt_die and call @callback on each line.
447 * If the @rt_die is a function, walk only on the lines inside the function,
448 * otherwise @rt_die must be a CU DIE.
449 * Note that this walks not only dwarf line list, but also function entries
450 * and inline call-site.
451 */
452int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
453{
454 Dwarf_Lines *lines;
455 Dwarf_Line *line;
456 Dwarf_Addr addr;
457 const char *fname;
458 int lineno, ret = 0;
459 Dwarf_Die die_mem, *cu_die;
460 size_t nlines, i;
461
462 /* Get the CU die */
463 if (dwarf_tag(rt_die) == DW_TAG_subprogram)
464 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
465 else
466 cu_die = rt_die;
467 if (!cu_die) {
468 pr_debug2("Failed to get CU from subprogram\n");
469 return -EINVAL;
470 }
471
472 /* Get lines list in the CU */
473 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
474 pr_debug2("Failed to get source lines on this CU.\n");
475 return -ENOENT;
476 }
477 pr_debug2("Get %zd lines from this CU\n", nlines);
478
479 /* Walk on the lines on lines list */
480 for (i = 0; i < nlines; i++) {
481 line = dwarf_onesrcline(lines, i);
482 if (line == NULL ||
483 dwarf_lineno(line, &lineno) != 0 ||
484 dwarf_lineaddr(line, &addr) != 0) {
485 pr_debug2("Failed to get line info. "
486 "Possible error in debuginfo.\n");
487 continue;
488 }
489 /* Filter lines based on address */
490 if (rt_die != cu_die)
491 /*
492 * Address filtering
493 * The line is included in given function, and
494 * no inline block includes it.
495 */
496 if (!dwarf_haspc(rt_die, addr) ||
497 die_find_inlinefunc(rt_die, addr, &die_mem))
498 continue;
499 /* Get source line */
500 fname = dwarf_linesrc(line, NULL, NULL);
501
502 ret = callback(fname, lineno, addr, data);
503 if (ret != 0)
504 return ret;
505 }
506
507 /*
508 * Dwarf lines doesn't include function declarations and inlined
509 * subroutines. We have to check functions list or given function.
510 */
511 if (rt_die != cu_die)
512 ret = __die_walk_funclines(rt_die, callback, data);
513 else {
514 struct __line_walk_param param = {
515 .callback = callback,
516 .data = data,
517 .retval = 0,
518 };
519 dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
520 ret = param.retval;
521 }
522
523 return ret;
524}
525
526struct __find_variable_param {
527 const char *name;
528 Dwarf_Addr addr;
529};
530
531static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
532{
533 struct __find_variable_param *fvp = data;
534 int tag;
535
536 tag = dwarf_tag(die_mem);
537 if ((tag == DW_TAG_formal_parameter ||
538 tag == DW_TAG_variable) &&
539 die_compare_name(die_mem, fvp->name))
540 return DIE_FIND_CB_END;
541
542 if (dwarf_haspc(die_mem, fvp->addr))
543 return DIE_FIND_CB_CONTINUE;
544 else
545 return DIE_FIND_CB_SIBLING;
546}
547
548/**
549 * die_find_variable_at - Find a given name variable at given address
550 * @sp_die: a function DIE
551 * @name: variable name
552 * @addr: address
553 * @die_mem: a buffer for result DIE
554 *
555 * Find a variable DIE called @name at @addr in @sp_die.
556 */
557Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
558 Dwarf_Addr addr, Dwarf_Die *die_mem)
559{
560 struct __find_variable_param fvp = { .name = name, .addr = addr};
561
562 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
563 die_mem);
564}
565
566static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
567{
568 const char *name = data;
569
570 if ((dwarf_tag(die_mem) == DW_TAG_member) &&
571 die_compare_name(die_mem, name))
572 return DIE_FIND_CB_END;
573
574 return DIE_FIND_CB_SIBLING;
575}
576
577/**
578 * die_find_member - Find a given name member in a data structure
579 * @st_die: a data structure type DIE
580 * @name: member name
581 * @die_mem: a buffer for result DIE
582 *
583 * Find a member DIE called @name in @st_die.
584 */
585Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
586 Dwarf_Die *die_mem)
587{
588 return die_find_child(st_die, __die_find_member_cb, (void *)name,
589 die_mem);
590}
591
592/**
593 * die_get_typename - Get the name of given variable DIE
594 * @vr_die: a variable DIE
595 * @buf: a buffer for result type name
596 * @len: a max-length of @buf
597 *
598 * Get the name of @vr_die and stores it to @buf. Return the actual length
599 * of type name if succeeded. Return -E2BIG if @len is not enough long, and
600 * Return -ENOENT if failed to find type name.
601 * Note that the result will stores typedef name if possible, and stores
602 * "*(function_type)" if the type is a function pointer.
603 */
604int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
605{
606 Dwarf_Die type;
607 int tag, ret, ret2;
608 const char *tmp = "";
609
610 if (__die_get_real_type(vr_die, &type) == NULL)
611 return -ENOENT;
612
613 tag = dwarf_tag(&type);
614 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
615 tmp = "*";
616 else if (tag == DW_TAG_subroutine_type) {
617 /* Function pointer */
618 ret = snprintf(buf, len, "(function_type)");
619 return (ret >= len) ? -E2BIG : ret;
620 } else {
621 if (!dwarf_diename(&type))
622 return -ENOENT;
623 if (tag == DW_TAG_union_type)
624 tmp = "union ";
625 else if (tag == DW_TAG_structure_type)
626 tmp = "struct ";
627 /* Write a base name */
628 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
629 return (ret >= len) ? -E2BIG : ret;
630 }
631 ret = die_get_typename(&type, buf, len);
632 if (ret > 0) {
633 ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
634 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
635 }
636 return ret;
637}
638
639/**
640 * die_get_varname - Get the name and type of given variable DIE
641 * @vr_die: a variable DIE
642 * @buf: a buffer for type and variable name
643 * @len: the max-length of @buf
644 *
645 * Get the name and type of @vr_die and stores it in @buf as "type\tname".
646 */
647int die_get_varname(Dwarf_Die *vr_die, char *buf, int len)
648{
649 int ret, ret2;
650
651 ret = die_get_typename(vr_die, buf, len);
652 if (ret < 0) {
653 pr_debug("Failed to get type, make it unknown.\n");
654 ret = snprintf(buf, len, "(unknown_type)");
655 }
656 if (ret > 0) {
657 ret2 = snprintf(buf + ret, len - ret, "\t%s",
658 dwarf_diename(vr_die));
659 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
660 }
661 return ret;
662}
663
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
new file mode 100644
index 000000000000..bc3b21167e70
--- /dev/null
+++ b/tools/perf/util/dwarf-aux.h
@@ -0,0 +1,100 @@
1#ifndef _DWARF_AUX_H
2#define _DWARF_AUX_H
3/*
4 * dwarf-aux.h : libdw auxiliary interfaces
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22#include <dwarf.h>
23#include <elfutils/libdw.h>
24#include <elfutils/libdwfl.h>
25#include <elfutils/version.h>
26
27/* Find the realpath of the target file */
28extern const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname);
29
30/* Get DW_AT_comp_dir (should be NULL with older gcc) */
31extern const char *cu_get_comp_dir(Dwarf_Die *cu_die);
32
33/* Get a line number and file name for given address */
34extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
35 const char **fname, int *lineno);
36
37/* Compare diename and tname */
38extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
39
40/* Get callsite line number of inline-function instance */
41extern int die_get_call_lineno(Dwarf_Die *in_die);
42
43/* Get type die */
44extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
45
46/* Get a type die, but skip qualifiers and typedef */
47extern Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
48
49/* Check whether the DIE is signed or not */
50extern bool die_is_signed_type(Dwarf_Die *tp_die);
51
52/* Get data_member_location offset */
53extern int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs);
54
55/* Return values for die_find_child() callbacks */
56enum {
57 DIE_FIND_CB_END = 0, /* End of Search */
58 DIE_FIND_CB_CHILD = 1, /* Search only children */
59 DIE_FIND_CB_SIBLING = 2, /* Search only siblings */
60 DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */
61};
62
63/* Search child DIEs */
64extern Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
65 int (*callback)(Dwarf_Die *, void *),
66 void *data, Dwarf_Die *die_mem);
67
68/* Search a non-inlined function including given address */
69extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
70 Dwarf_Die *die_mem);
71
72/* Search an inlined function including given address */
73extern Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
74 Dwarf_Die *die_mem);
75
76/* Walker on lines (Note: line number will not be sorted) */
77typedef int (* line_walk_callback_t) (const char *fname, int lineno,
78 Dwarf_Addr addr, void *data);
79
80/*
81 * Walk on lines inside given DIE. If the DIE is a subprogram, walk only on
82 * the lines inside the subprogram, otherwise the DIE must be a CU DIE.
83 */
84extern int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback,
85 void *data);
86
87/* Find a variable called 'name' at given address */
88extern Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
89 Dwarf_Addr addr, Dwarf_Die *die_mem);
90
91/* Find a member called 'name' */
92extern Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
93 Dwarf_Die *die_mem);
94
95/* Get the name of given variable DIE */
96extern int die_get_typename(Dwarf_Die *vr_die, char *buf, int len);
97
98/* Get the name and type of given variable DIE, stored as "type\tname" */
99extern int die_get_varname(Dwarf_Die *vr_die, char *buf, int len);
100#endif
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index d443b643957f..53d219bddb48 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -222,521 +222,6 @@ static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp,
222} 222}
223#endif 223#endif
224 224
225/* Dwarf wrappers */
226
227/* Find the realpath of the target file. */
228static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
229{
230 Dwarf_Files *files;
231 size_t nfiles, i;
232 const char *src = NULL;
233 int ret;
234
235 if (!fname)
236 return NULL;
237
238 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
239 if (ret != 0)
240 return NULL;
241
242 for (i = 0; i < nfiles; i++) {
243 src = dwarf_filesrc(files, i, NULL, NULL);
244 if (strtailcmp(src, fname) == 0)
245 break;
246 }
247 if (i == nfiles)
248 return NULL;
249 return src;
250}
251
252/* Get DW_AT_comp_dir (should be NULL with older gcc) */
253static const char *cu_get_comp_dir(Dwarf_Die *cu_die)
254{
255 Dwarf_Attribute attr;
256 if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
257 return NULL;
258 return dwarf_formstring(&attr);
259}
260
261/* Get a line number and file name for given address */
262static int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
263 const char **fname, int *lineno)
264{
265 Dwarf_Line *line;
266 Dwarf_Addr laddr;
267
268 line = dwarf_getsrc_die(cudie, (Dwarf_Addr)addr);
269 if (line && dwarf_lineaddr(line, &laddr) == 0 &&
270 addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
271 *fname = dwarf_linesrc(line, NULL, NULL);
272 if (!*fname)
273 /* line number is useless without filename */
274 *lineno = 0;
275 }
276
277 return *lineno ?: -ENOENT;
278}
279
280/* Compare diename and tname */
281static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
282{
283 const char *name;
284 name = dwarf_diename(dw_die);
285 return name ? (strcmp(tname, name) == 0) : false;
286}
287
288/* Get callsite line number of inline-function instance */
289static int die_get_call_lineno(Dwarf_Die *in_die)
290{
291 Dwarf_Attribute attr;
292 Dwarf_Word ret;
293
294 if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
295 return -ENOENT;
296
297 dwarf_formudata(&attr, &ret);
298 return (int)ret;
299}
300
301/* Get type die */
302static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
303{
304 Dwarf_Attribute attr;
305
306 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
307 dwarf_formref_die(&attr, die_mem))
308 return die_mem;
309 else
310 return NULL;
311}
312
313/* Get a type die, but skip qualifiers */
314static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
315{
316 int tag;
317
318 do {
319 vr_die = die_get_type(vr_die, die_mem);
320 if (!vr_die)
321 break;
322 tag = dwarf_tag(vr_die);
323 } while (tag == DW_TAG_const_type ||
324 tag == DW_TAG_restrict_type ||
325 tag == DW_TAG_volatile_type ||
326 tag == DW_TAG_shared_type);
327
328 return vr_die;
329}
330
331/* Get a type die, but skip qualifiers and typedef */
332static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
333{
334 do {
335 vr_die = __die_get_real_type(vr_die, die_mem);
336 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
337
338 return vr_die;
339}
340
341static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
342 Dwarf_Word *result)
343{
344 Dwarf_Attribute attr;
345
346 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
347 dwarf_formudata(&attr, result) != 0)
348 return -ENOENT;
349
350 return 0;
351}
352
353static bool die_is_signed_type(Dwarf_Die *tp_die)
354{
355 Dwarf_Word ret;
356
357 if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
358 return false;
359
360 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
361 ret == DW_ATE_signed_fixed);
362}
363
364/* Get data_member_location offset */
365static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
366{
367 Dwarf_Attribute attr;
368 Dwarf_Op *expr;
369 size_t nexpr;
370 int ret;
371
372 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
373 return -ENOENT;
374
375 if (dwarf_formudata(&attr, offs) != 0) {
376 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
377 ret = dwarf_getlocation(&attr, &expr, &nexpr);
378 if (ret < 0 || nexpr == 0)
379 return -ENOENT;
380
381 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
382 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
383 expr[0].atom, nexpr);
384 return -ENOTSUP;
385 }
386 *offs = (Dwarf_Word)expr[0].number;
387 }
388 return 0;
389}
390
391/* Return values for die_find callbacks */
392enum {
393 DIE_FIND_CB_END = 0, /* End of Search */
394 DIE_FIND_CB_CHILD = 1, /* Search only children */
395 DIE_FIND_CB_SIBLING = 2, /* Search only siblings */
396 DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */
397};
398
399/* Search a child die */
400static Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
401 int (*callback)(Dwarf_Die *, void *),
402 void *data, Dwarf_Die *die_mem)
403{
404 Dwarf_Die child_die;
405 int ret;
406
407 ret = dwarf_child(rt_die, die_mem);
408 if (ret != 0)
409 return NULL;
410
411 do {
412 ret = callback(die_mem, data);
413 if (ret == DIE_FIND_CB_END)
414 return die_mem;
415
416 if ((ret & DIE_FIND_CB_CHILD) &&
417 die_find_child(die_mem, callback, data, &child_die)) {
418 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
419 return die_mem;
420 }
421 } while ((ret & DIE_FIND_CB_SIBLING) &&
422 dwarf_siblingof(die_mem, die_mem) == 0);
423
424 return NULL;
425}
426
427struct __addr_die_search_param {
428 Dwarf_Addr addr;
429 Dwarf_Die *die_mem;
430};
431
432static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
433{
434 struct __addr_die_search_param *ad = data;
435
436 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
437 dwarf_haspc(fn_die, ad->addr)) {
438 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
439 return DWARF_CB_ABORT;
440 }
441 return DWARF_CB_OK;
442}
443
444/* Search a real subprogram including this line, */
445static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
446 Dwarf_Die *die_mem)
447{
448 struct __addr_die_search_param ad;
449 ad.addr = addr;
450 ad.die_mem = die_mem;
451 /* dwarf_getscopes can't find subprogram. */
452 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
453 return NULL;
454 else
455 return die_mem;
456}
457
458/* die_find callback for inline function search */
459static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
460{
461 Dwarf_Addr *addr = data;
462
463 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
464 dwarf_haspc(die_mem, *addr))
465 return DIE_FIND_CB_END;
466
467 return DIE_FIND_CB_CONTINUE;
468}
469
470/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
471static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
472 Dwarf_Die *die_mem)
473{
474 Dwarf_Die tmp_die;
475
476 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
477 if (!sp_die)
478 return NULL;
479
480 /* Inlined function could be recursive. Trace it until fail */
481 while (sp_die) {
482 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
483 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
484 &tmp_die);
485 }
486
487 return die_mem;
488}
489
490/* Walker on lines (Note: line number will not be sorted) */
491typedef int (* line_walk_handler_t) (const char *fname, int lineno,
492 Dwarf_Addr addr, void *data);
493
494struct __line_walk_param {
495 const char *fname;
496 line_walk_handler_t handler;
497 void *data;
498 int retval;
499};
500
501static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
502{
503 struct __line_walk_param *lw = data;
504 Dwarf_Addr addr;
505 int lineno;
506
507 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
508 lineno = die_get_call_lineno(in_die);
509 if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
510 lw->retval = lw->handler(lw->fname, lineno, addr,
511 lw->data);
512 if (lw->retval != 0)
513 return DIE_FIND_CB_END;
514 }
515 }
516 return DIE_FIND_CB_SIBLING;
517}
518
519/* Walk on lines of blocks included in given DIE */
520static int __die_walk_funclines(Dwarf_Die *sp_die,
521 line_walk_handler_t handler, void *data)
522{
523 struct __line_walk_param lw = {
524 .handler = handler,
525 .data = data,
526 .retval = 0,
527 };
528 Dwarf_Die die_mem;
529 Dwarf_Addr addr;
530 int lineno;
531
532 /* Handle function declaration line */
533 lw.fname = dwarf_decl_file(sp_die);
534 if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
535 dwarf_entrypc(sp_die, &addr) == 0) {
536 lw.retval = handler(lw.fname, lineno, addr, data);
537 if (lw.retval != 0)
538 goto done;
539 }
540 die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
541done:
542 return lw.retval;
543}
544
545static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
546{
547 struct __line_walk_param *lw = data;
548
549 lw->retval = __die_walk_funclines(sp_die, lw->handler, lw->data);
550 if (lw->retval != 0)
551 return DWARF_CB_ABORT;
552
553 return DWARF_CB_OK;
554}
555
556/*
557 * Walk on lines inside given PDIE. If the PDIE is subprogram, walk only on
558 * the lines inside the subprogram, otherwise PDIE must be a CU DIE.
559 */
560static int die_walk_lines(Dwarf_Die *pdie, line_walk_handler_t handler,
561 void *data)
562{
563 Dwarf_Lines *lines;
564 Dwarf_Line *line;
565 Dwarf_Addr addr;
566 const char *fname;
567 int lineno, ret = 0;
568 Dwarf_Die die_mem, *cu_die;
569 size_t nlines, i;
570
571 /* Get the CU die */
572 if (dwarf_tag(pdie) == DW_TAG_subprogram)
573 cu_die = dwarf_diecu(pdie, &die_mem, NULL, NULL);
574 else
575 cu_die = pdie;
576 if (!cu_die) {
577 pr_debug2("Failed to get CU from subprogram\n");
578 return -EINVAL;
579 }
580
581 /* Get lines list in the CU */
582 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
583 pr_debug2("Failed to get source lines on this CU.\n");
584 return -ENOENT;
585 }
586 pr_debug2("Get %zd lines from this CU\n", nlines);
587
588 /* Walk on the lines on lines list */
589 for (i = 0; i < nlines; i++) {
590 line = dwarf_onesrcline(lines, i);
591 if (line == NULL ||
592 dwarf_lineno(line, &lineno) != 0 ||
593 dwarf_lineaddr(line, &addr) != 0) {
594 pr_debug2("Failed to get line info. "
595 "Possible error in debuginfo.\n");
596 continue;
597 }
598 /* Filter lines based on address */
599 if (pdie != cu_die)
600 /*
601 * Address filtering
602 * The line is included in given function, and
603 * no inline block includes it.
604 */
605 if (!dwarf_haspc(pdie, addr) ||
606 die_find_inlinefunc(pdie, addr, &die_mem))
607 continue;
608 /* Get source line */
609 fname = dwarf_linesrc(line, NULL, NULL);
610
611 ret = handler(fname, lineno, addr, data);
612 if (ret != 0)
613 return ret;
614 }
615
616 /*
617 * Dwarf lines doesn't include function declarations and inlined
618 * subroutines. We have to check functions list or given function.
619 */
620 if (pdie != cu_die)
621 ret = __die_walk_funclines(pdie, handler, data);
622 else {
623 struct __line_walk_param param = {
624 .handler = handler,
625 .data = data,
626 .retval = 0,
627 };
628 dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
629 ret = param.retval;
630 }
631
632 return ret;
633}
634
635struct __find_variable_param {
636 const char *name;
637 Dwarf_Addr addr;
638};
639
640static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
641{
642 struct __find_variable_param *fvp = data;
643 int tag;
644
645 tag = dwarf_tag(die_mem);
646 if ((tag == DW_TAG_formal_parameter ||
647 tag == DW_TAG_variable) &&
648 die_compare_name(die_mem, fvp->name))
649 return DIE_FIND_CB_END;
650
651 if (dwarf_haspc(die_mem, fvp->addr))
652 return DIE_FIND_CB_CONTINUE;
653 else
654 return DIE_FIND_CB_SIBLING;
655}
656
657/* Find a variable called 'name' at given address */
658static Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
659 Dwarf_Addr addr, Dwarf_Die *die_mem)
660{
661 struct __find_variable_param fvp = { .name = name, .addr = addr};
662
663 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
664 die_mem);
665}
666
667static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
668{
669 const char *name = data;
670
671 if ((dwarf_tag(die_mem) == DW_TAG_member) &&
672 die_compare_name(die_mem, name))
673 return DIE_FIND_CB_END;
674
675 return DIE_FIND_CB_SIBLING;
676}
677
678/* Find a member called 'name' */
679static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
680 Dwarf_Die *die_mem)
681{
682 return die_find_child(st_die, __die_find_member_cb, (void *)name,
683 die_mem);
684}
685
686/* Get the name of given variable DIE */
687static int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
688{
689 Dwarf_Die type;
690 int tag, ret, ret2;
691 const char *tmp = "";
692
693 if (__die_get_real_type(vr_die, &type) == NULL)
694 return -ENOENT;
695
696 tag = dwarf_tag(&type);
697 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
698 tmp = "*";
699 else if (tag == DW_TAG_subroutine_type) {
700 /* Function pointer */
701 ret = snprintf(buf, len, "(function_type)");
702 return (ret >= len) ? -E2BIG : ret;
703 } else {
704 if (!dwarf_diename(&type))
705 return -ENOENT;
706 if (tag == DW_TAG_union_type)
707 tmp = "union ";
708 else if (tag == DW_TAG_structure_type)
709 tmp = "struct ";
710 /* Write a base name */
711 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
712 return (ret >= len) ? -E2BIG : ret;
713 }
714 ret = die_get_typename(&type, buf, len);
715 if (ret > 0) {
716 ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
717 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
718 }
719 return ret;
720}
721
722/* Get the name and type of given variable DIE, stored as "type\tname" */
723static int die_get_varname(Dwarf_Die *vr_die, char *buf, int len)
724{
725 int ret, ret2;
726
727 ret = die_get_typename(vr_die, buf, len);
728 if (ret < 0) {
729 pr_debug("Failed to get type, make it unknown.\n");
730 ret = snprintf(buf, len, "(unknown_type)");
731 }
732 if (ret > 0) {
733 ret2 = snprintf(buf + ret, len - ret, "\t%s",
734 dwarf_diename(vr_die));
735 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
736 }
737 return ret;
738}
739
740/* 225/*
741 * Probe finder related functions 226 * Probe finder related functions
742 */ 227 */
@@ -1206,8 +691,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
1206 691
1207 /* If no real subprogram, find a real one */ 692 /* If no real subprogram, find a real one */
1208 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { 693 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
1209 sp_die = die_find_real_subprogram(&pf->cu_die, 694 sp_die = die_find_realfunc(&pf->cu_die, pf->addr, &die_mem);
1210 pf->addr, &die_mem);
1211 if (!sp_die) { 695 if (!sp_die) {
1212 pr_warning("Failed to find probe point in any " 696 pr_warning("Failed to find probe point in any "
1213 "functions.\n"); 697 "functions.\n");
@@ -1768,7 +1252,7 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1768 /* Don't care whether it failed or not */ 1252 /* Don't care whether it failed or not */
1769 1253
1770 /* Find a corresponding function (name, baseline and baseaddr) */ 1254 /* Find a corresponding function (name, baseline and baseaddr) */
1771 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { 1255 if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
1772 /* Get function entry information */ 1256 /* Get function entry information */
1773 tmp = dwarf_diename(&spdie); 1257 tmp = dwarf_diename(&spdie);
1774 if (!tmp || 1258 if (!tmp ||
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 605730a366db..0f1ed3d25a20 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -32,11 +32,7 @@ extern int find_line_range(int fd, struct line_range *lr);
32extern int find_available_vars_at(int fd, struct perf_probe_event *pev, 32extern int find_available_vars_at(int fd, struct perf_probe_event *pev,
33 struct variable_list **vls, int max_points, 33 struct variable_list **vls, int max_points,
34 bool externs); 34 bool externs);
35 35#include "dwarf-aux.h"
36#include <dwarf.h>
37#include <elfutils/libdw.h>
38#include <elfutils/libdwfl.h>
39#include <elfutils/version.h>
40 36
41struct probe_finder { 37struct probe_finder {
42 struct perf_probe_event *pev; /* Target probe event */ 38 struct perf_probe_event *pev; /* Target probe event */