1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/kernel.h>
10 #include "util/util.h"
11 #include "util/debug.h"
12 #include "util/callchain.h"
17 bool srcline_full_filename
;
19 static const char *dso__name(struct dso
*dso
)
23 if (dso
->symsrc_filename
)
24 dso_name
= dso
->symsrc_filename
;
26 dso_name
= dso
->long_name
;
28 if (dso_name
[0] == '[')
31 if (!strncmp(dso_name
, "/tmp/perf-", 10))
37 static int inline_list__append(struct symbol
*symbol
, char *srcline
,
38 struct inline_node
*node
)
40 struct inline_list
*ilist
;
42 ilist
= zalloc(sizeof(*ilist
));
46 ilist
->symbol
= symbol
;
47 ilist
->srcline
= srcline
;
49 if (callchain_param
.order
== ORDER_CALLEE
)
50 list_add_tail(&ilist
->list
, &node
->val
);
52 list_add(&ilist
->list
, &node
->val
);
57 /* basename version that takes a const input string */
58 static const char *gnu_basename(const char *path
)
60 const char *base
= strrchr(path
, '/');
62 return base
? base
+ 1 : path
;
65 static char *srcline_from_fileline(const char *file
, unsigned int line
)
72 if (!srcline_full_filename
)
73 file
= gnu_basename(file
);
75 if (asprintf(&srcline
, "%s:%u", file
, line
) < 0)
81 static struct symbol
*new_inline_sym(struct dso
*dso
,
82 struct symbol
*base_sym
,
85 struct symbol
*inline_sym
;
86 char *demangled
= NULL
;
92 demangled
= dso__demangle_sym(dso
, 0, funcname
);
97 if (base_sym
&& strcmp(funcname
, base_sym
->name
) == 0) {
98 /* reuse the real, existing symbol */
99 inline_sym
= base_sym
;
100 /* ensure that we don't alias an inlined symbol, which could
101 * lead to double frees in inline_node__delete
103 assert(!base_sym
->inlined
);
105 /* create a fake symbol for the inline frame */
106 inline_sym
= symbol__new(base_sym
? base_sym
->start
: 0,
107 base_sym
? base_sym
->end
: 0,
108 base_sym
? base_sym
->binding
: 0,
109 base_sym
? base_sym
->type
: 0,
112 inline_sym
->inlined
= 1;
120 #ifdef HAVE_LIBBFD_SUPPORT
123 * Implement addr2line using libbfd.
125 #define PACKAGE "perf"
133 const char *filename
;
134 const char *funcname
;
141 static int bfd_error(const char *string
)
145 errmsg
= bfd_errmsg(bfd_get_error());
149 pr_debug("%s: %s\n", string
, errmsg
);
151 pr_debug("%s\n", errmsg
);
156 static int slurp_symtab(bfd
*abfd
, struct a2l_data
*a2l
)
161 bfd_boolean dynamic
= FALSE
;
163 if ((bfd_get_file_flags(abfd
) & HAS_SYMS
) == 0)
164 return bfd_error(bfd_get_filename(abfd
));
166 storage
= bfd_get_symtab_upper_bound(abfd
);
168 storage
= bfd_get_dynamic_symtab_upper_bound(abfd
);
172 return bfd_error(bfd_get_filename(abfd
));
174 syms
= malloc(storage
);
176 symcount
= bfd_canonicalize_dynamic_symtab(abfd
, syms
);
178 symcount
= bfd_canonicalize_symtab(abfd
, syms
);
182 return bfd_error(bfd_get_filename(abfd
));
189 static void find_address_in_section(bfd
*abfd
, asection
*section
, void *data
)
193 struct a2l_data
*a2l
= data
;
198 if ((bfd_get_section_flags(abfd
, section
) & SEC_ALLOC
) == 0)
202 vma
= bfd_get_section_vma(abfd
, section
);
203 size
= bfd_get_section_size(section
);
205 if (pc
< vma
|| pc
>= vma
+ size
)
208 a2l
->found
= bfd_find_nearest_line(abfd
, section
, a2l
->syms
, pc
- vma
,
209 &a2l
->filename
, &a2l
->funcname
,
212 if (a2l
->filename
&& !strlen(a2l
->filename
))
213 a2l
->filename
= NULL
;
216 static struct a2l_data
*addr2line_init(const char *path
)
219 struct a2l_data
*a2l
= NULL
;
221 abfd
= bfd_openr(path
, NULL
);
225 if (!bfd_check_format(abfd
, bfd_object
))
228 a2l
= zalloc(sizeof(*a2l
));
233 a2l
->input
= strdup(path
);
234 if (a2l
->input
== NULL
)
237 if (slurp_symtab(abfd
, a2l
))
244 zfree((char **)&a2l
->input
);
251 static void addr2line_cleanup(struct a2l_data
*a2l
)
254 bfd_close(a2l
->abfd
);
255 zfree((char **)&a2l
->input
);
260 #define MAX_INLINE_NEST 1024
262 static int inline_list__append_dso_a2l(struct dso
*dso
,
263 struct inline_node
*node
,
266 struct a2l_data
*a2l
= dso
->a2l
;
267 struct symbol
*inline_sym
= new_inline_sym(dso
, sym
, a2l
->funcname
);
268 char *srcline
= NULL
;
271 srcline
= srcline_from_fileline(a2l
->filename
, a2l
->line
);
273 return inline_list__append(inline_sym
, srcline
, node
);
276 static int addr2line(const char *dso_name
, u64 addr
,
277 char **file
, unsigned int *line
, struct dso
*dso
,
278 bool unwind_inlines
, struct inline_node
*node
,
282 struct a2l_data
*a2l
= dso
->a2l
;
285 dso
->a2l
= addr2line_init(dso_name
);
290 pr_warning("addr2line_init failed for %s\n", dso_name
);
297 bfd_map_over_sections(a2l
->abfd
, find_address_in_section
, a2l
);
302 if (unwind_inlines
) {
305 if (node
&& inline_list__append_dso_a2l(dso
, node
, sym
))
308 while (bfd_find_inliner_info(a2l
->abfd
, &a2l
->filename
,
309 &a2l
->funcname
, &a2l
->line
) &&
310 cnt
++ < MAX_INLINE_NEST
) {
312 if (a2l
->filename
&& !strlen(a2l
->filename
))
313 a2l
->filename
= NULL
;
316 if (inline_list__append_dso_a2l(dso
, node
, sym
))
318 // found at least one inline frame
325 *file
= a2l
->filename
? strdup(a2l
->filename
) : NULL
;
335 void dso__free_a2l(struct dso
*dso
)
337 struct a2l_data
*a2l
= dso
->a2l
;
342 addr2line_cleanup(a2l
);
347 static struct inline_node
*addr2inlines(const char *dso_name
, u64 addr
,
348 struct dso
*dso
, struct symbol
*sym
)
350 struct inline_node
*node
;
352 node
= zalloc(sizeof(*node
));
354 perror("not enough memory for the inline node");
358 INIT_LIST_HEAD(&node
->val
);
361 addr2line(dso_name
, addr
, NULL
, NULL
, dso
, true, node
, sym
);
365 #else /* HAVE_LIBBFD_SUPPORT */
367 static int filename_split(char *filename
, unsigned int *line_nr
)
371 sep
= strchr(filename
, '\n');
375 if (!strcmp(filename
, "??:0"))
378 sep
= strchr(filename
, ':');
381 *line_nr
= strtoul(sep
, NULL
, 0);
388 static int addr2line(const char *dso_name
, u64 addr
,
389 char **file
, unsigned int *line_nr
,
390 struct dso
*dso __maybe_unused
,
391 bool unwind_inlines __maybe_unused
,
392 struct inline_node
*node __maybe_unused
,
393 struct symbol
*sym __maybe_unused
)
397 char *filename
= NULL
;
401 scnprintf(cmd
, sizeof(cmd
), "addr2line -e %s %016"PRIx64
,
404 fp
= popen(cmd
, "r");
406 pr_warning("popen failed for %s\n", dso_name
);
410 if (getline(&filename
, &len
, fp
) < 0 || !len
) {
411 pr_warning("addr2line has no output for %s\n", dso_name
);
415 ret
= filename_split(filename
, line_nr
);
428 void dso__free_a2l(struct dso
*dso __maybe_unused
)
432 static struct inline_node
*addr2inlines(const char *dso_name
, u64 addr
,
433 struct dso
*dso __maybe_unused
,
438 struct inline_node
*node
;
439 char *filename
= NULL
;
440 char *funcname
= NULL
;
441 size_t filelen
, funclen
;
442 unsigned int line_nr
= 0;
444 scnprintf(cmd
, sizeof(cmd
), "addr2line -e %s -i -f %016"PRIx64
,
447 fp
= popen(cmd
, "r");
449 pr_err("popen failed for %s\n", dso_name
);
453 node
= zalloc(sizeof(*node
));
455 perror("not enough memory for the inline node");
459 INIT_LIST_HEAD(&node
->val
);
462 /* addr2line -f generates two lines for each inlined functions */
463 while (getline(&funcname
, &funclen
, fp
) != -1) {
465 struct symbol
*inline_sym
;
469 if (getline(&filename
, &filelen
, fp
) == -1)
472 if (filename_split(filename
, &line_nr
) != 1)
475 srcline
= srcline_from_fileline(filename
, line_nr
);
476 inline_sym
= new_inline_sym(dso
, sym
, funcname
);
478 if (inline_list__append(inline_sym
, srcline
, node
) != 0) {
480 if (inline_sym
&& inline_sym
->inlined
)
481 symbol__delete(inline_sym
);
494 #endif /* HAVE_LIBBFD_SUPPORT */
497 * Number of addr2line failures (without success) before disabling it for that
500 #define A2L_FAIL_LIMIT 123
502 char *__get_srcline(struct dso
*dso
, u64 addr
, struct symbol
*sym
,
503 bool show_sym
, bool show_addr
, bool unwind_inlines
,
509 const char *dso_name
;
511 if (!dso
->has_srcline
)
514 dso_name
= dso__name(dso
);
515 if (dso_name
== NULL
)
518 if (!addr2line(dso_name
, addr
, &file
, &line
, dso
,
519 unwind_inlines
, NULL
, sym
))
522 srcline
= srcline_from_fileline(file
, line
);
533 if (dso
->a2l_fails
&& ++dso
->a2l_fails
> A2L_FAIL_LIMIT
) {
534 dso
->has_srcline
= 0;
539 return (show_sym
&& sym
) ?
540 strndup(sym
->name
, sym
->namelen
) : NULL
;
543 if (asprintf(&srcline
, "%s+%" PRIu64
, show_sym
? sym
->name
: "",
544 ip
- sym
->start
) < 0)
545 return SRCLINE_UNKNOWN
;
546 } else if (asprintf(&srcline
, "%s[%" PRIx64
"]", dso
->short_name
, addr
) < 0)
547 return SRCLINE_UNKNOWN
;
551 void free_srcline(char *srcline
)
553 if (srcline
&& strcmp(srcline
, SRCLINE_UNKNOWN
) != 0)
557 char *get_srcline(struct dso
*dso
, u64 addr
, struct symbol
*sym
,
558 bool show_sym
, bool show_addr
, u64 ip
)
560 return __get_srcline(dso
, addr
, sym
, show_sym
, show_addr
, false, ip
);
563 struct srcline_node
{
566 struct rb_node rb_node
;
569 void srcline__tree_insert(struct rb_root
*tree
, u64 addr
, char *srcline
)
571 struct rb_node
**p
= &tree
->rb_node
;
572 struct rb_node
*parent
= NULL
;
573 struct srcline_node
*i
, *node
;
575 node
= zalloc(sizeof(struct srcline_node
));
577 perror("not enough memory for the srcline node");
582 node
->srcline
= srcline
;
586 i
= rb_entry(parent
, struct srcline_node
, rb_node
);
592 rb_link_node(&node
->rb_node
, parent
, p
);
593 rb_insert_color(&node
->rb_node
, tree
);
596 char *srcline__tree_find(struct rb_root
*tree
, u64 addr
)
598 struct rb_node
*n
= tree
->rb_node
;
601 struct srcline_node
*i
= rb_entry(n
, struct srcline_node
,
606 else if (addr
> i
->addr
)
615 void srcline__tree_delete(struct rb_root
*tree
)
617 struct srcline_node
*pos
;
618 struct rb_node
*next
= rb_first(tree
);
621 pos
= rb_entry(next
, struct srcline_node
, rb_node
);
622 next
= rb_next(&pos
->rb_node
);
623 rb_erase(&pos
->rb_node
, tree
);
624 free_srcline(pos
->srcline
);
629 struct inline_node
*dso__parse_addr_inlines(struct dso
*dso
, u64 addr
,
632 const char *dso_name
;
634 dso_name
= dso__name(dso
);
635 if (dso_name
== NULL
)
638 return addr2inlines(dso_name
, addr
, dso
, sym
);
641 void inline_node__delete(struct inline_node
*node
)
643 struct inline_list
*ilist
, *tmp
;
645 list_for_each_entry_safe(ilist
, tmp
, &node
->val
, list
) {
646 list_del_init(&ilist
->list
);
647 free_srcline(ilist
->srcline
);
648 /* only the inlined symbols are owned by the list */
649 if (ilist
->symbol
&& ilist
->symbol
->inlined
)
650 symbol__delete(ilist
->symbol
);
657 void inlines__tree_insert(struct rb_root
*tree
, struct inline_node
*inlines
)
659 struct rb_node
**p
= &tree
->rb_node
;
660 struct rb_node
*parent
= NULL
;
661 const u64 addr
= inlines
->addr
;
662 struct inline_node
*i
;
666 i
= rb_entry(parent
, struct inline_node
, rb_node
);
672 rb_link_node(&inlines
->rb_node
, parent
, p
);
673 rb_insert_color(&inlines
->rb_node
, tree
);
676 struct inline_node
*inlines__tree_find(struct rb_root
*tree
, u64 addr
)
678 struct rb_node
*n
= tree
->rb_node
;
681 struct inline_node
*i
= rb_entry(n
, struct inline_node
,
686 else if (addr
> i
->addr
)
695 void inlines__tree_delete(struct rb_root
*tree
)
697 struct inline_node
*pos
;
698 struct rb_node
*next
= rb_first(tree
);
701 pos
= rb_entry(next
, struct inline_node
, rb_node
);
702 next
= rb_next(&pos
->rb_node
);
703 rb_erase(&pos
->rb_node
, tree
);
704 inline_node__delete(pos
);