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
;
89 demangled
= dso__demangle_sym(dso
, 0, funcname
);
94 if (base_sym
&& strcmp(funcname
, base_sym
->name
) == 0) {
95 /* reuse the real, existing symbol */
96 inline_sym
= base_sym
;
97 /* ensure that we don't alias an inlined symbol, which could
98 * lead to double frees in inline_node__delete
100 assert(!base_sym
->inlined
);
102 /* create a fake symbol for the inline frame */
103 inline_sym
= symbol__new(base_sym
? base_sym
->start
: 0,
104 base_sym
? base_sym
->end
: 0,
105 base_sym
? base_sym
->binding
: 0,
108 inline_sym
->inlined
= 1;
116 #ifdef HAVE_LIBBFD_SUPPORT
119 * Implement addr2line using libbfd.
121 #define PACKAGE "perf"
129 const char *filename
;
130 const char *funcname
;
137 static int bfd_error(const char *string
)
141 errmsg
= bfd_errmsg(bfd_get_error());
145 pr_debug("%s: %s\n", string
, errmsg
);
147 pr_debug("%s\n", errmsg
);
152 static int slurp_symtab(bfd
*abfd
, struct a2l_data
*a2l
)
157 bfd_boolean dynamic
= FALSE
;
159 if ((bfd_get_file_flags(abfd
) & HAS_SYMS
) == 0)
160 return bfd_error(bfd_get_filename(abfd
));
162 storage
= bfd_get_symtab_upper_bound(abfd
);
164 storage
= bfd_get_dynamic_symtab_upper_bound(abfd
);
168 return bfd_error(bfd_get_filename(abfd
));
170 syms
= malloc(storage
);
172 symcount
= bfd_canonicalize_dynamic_symtab(abfd
, syms
);
174 symcount
= bfd_canonicalize_symtab(abfd
, syms
);
178 return bfd_error(bfd_get_filename(abfd
));
185 static void find_address_in_section(bfd
*abfd
, asection
*section
, void *data
)
189 struct a2l_data
*a2l
= data
;
194 if ((bfd_get_section_flags(abfd
, section
) & SEC_ALLOC
) == 0)
198 vma
= bfd_get_section_vma(abfd
, section
);
199 size
= bfd_get_section_size(section
);
201 if (pc
< vma
|| pc
>= vma
+ size
)
204 a2l
->found
= bfd_find_nearest_line(abfd
, section
, a2l
->syms
, pc
- vma
,
205 &a2l
->filename
, &a2l
->funcname
,
208 if (a2l
->filename
&& !strlen(a2l
->filename
))
209 a2l
->filename
= NULL
;
212 static struct a2l_data
*addr2line_init(const char *path
)
215 struct a2l_data
*a2l
= NULL
;
217 abfd
= bfd_openr(path
, NULL
);
221 if (!bfd_check_format(abfd
, bfd_object
))
224 a2l
= zalloc(sizeof(*a2l
));
229 a2l
->input
= strdup(path
);
230 if (a2l
->input
== NULL
)
233 if (slurp_symtab(abfd
, a2l
))
240 zfree((char **)&a2l
->input
);
247 static void addr2line_cleanup(struct a2l_data
*a2l
)
250 bfd_close(a2l
->abfd
);
251 zfree((char **)&a2l
->input
);
256 #define MAX_INLINE_NEST 1024
258 static int inline_list__append_dso_a2l(struct dso
*dso
,
259 struct inline_node
*node
,
262 struct a2l_data
*a2l
= dso
->a2l
;
263 struct symbol
*inline_sym
= new_inline_sym(dso
, sym
, a2l
->funcname
);
264 char *srcline
= NULL
;
267 srcline
= srcline_from_fileline(a2l
->filename
, a2l
->line
);
269 return inline_list__append(inline_sym
, srcline
, node
);
272 static int addr2line(const char *dso_name
, u64 addr
,
273 char **file
, unsigned int *line
, struct dso
*dso
,
274 bool unwind_inlines
, struct inline_node
*node
,
278 struct a2l_data
*a2l
= dso
->a2l
;
281 dso
->a2l
= addr2line_init(dso_name
);
286 pr_warning("addr2line_init failed for %s\n", dso_name
);
293 bfd_map_over_sections(a2l
->abfd
, find_address_in_section
, a2l
);
298 if (unwind_inlines
) {
301 if (node
&& inline_list__append_dso_a2l(dso
, node
, sym
))
304 while (bfd_find_inliner_info(a2l
->abfd
, &a2l
->filename
,
305 &a2l
->funcname
, &a2l
->line
) &&
306 cnt
++ < MAX_INLINE_NEST
) {
308 if (a2l
->filename
&& !strlen(a2l
->filename
))
309 a2l
->filename
= NULL
;
312 if (inline_list__append_dso_a2l(dso
, node
, sym
))
314 // found at least one inline frame
321 *file
= a2l
->filename
? strdup(a2l
->filename
) : NULL
;
331 void dso__free_a2l(struct dso
*dso
)
333 struct a2l_data
*a2l
= dso
->a2l
;
338 addr2line_cleanup(a2l
);
343 static struct inline_node
*addr2inlines(const char *dso_name
, u64 addr
,
344 struct dso
*dso
, struct symbol
*sym
)
346 struct inline_node
*node
;
348 node
= zalloc(sizeof(*node
));
350 perror("not enough memory for the inline node");
354 INIT_LIST_HEAD(&node
->val
);
357 addr2line(dso_name
, addr
, NULL
, NULL
, dso
, true, node
, sym
);
361 #else /* HAVE_LIBBFD_SUPPORT */
363 static int filename_split(char *filename
, unsigned int *line_nr
)
367 sep
= strchr(filename
, '\n');
371 if (!strcmp(filename
, "??:0"))
374 sep
= strchr(filename
, ':');
377 *line_nr
= strtoul(sep
, NULL
, 0);
384 static int addr2line(const char *dso_name
, u64 addr
,
385 char **file
, unsigned int *line_nr
,
386 struct dso
*dso __maybe_unused
,
387 bool unwind_inlines __maybe_unused
,
388 struct inline_node
*node __maybe_unused
,
389 struct symbol
*sym __maybe_unused
)
393 char *filename
= NULL
;
397 scnprintf(cmd
, sizeof(cmd
), "addr2line -e %s %016"PRIx64
,
400 fp
= popen(cmd
, "r");
402 pr_warning("popen failed for %s\n", dso_name
);
406 if (getline(&filename
, &len
, fp
) < 0 || !len
) {
407 pr_warning("addr2line has no output for %s\n", dso_name
);
411 ret
= filename_split(filename
, line_nr
);
424 void dso__free_a2l(struct dso
*dso __maybe_unused
)
428 static struct inline_node
*addr2inlines(const char *dso_name
, u64 addr
,
429 struct dso
*dso __maybe_unused
,
434 struct inline_node
*node
;
435 char *filename
= NULL
;
436 char *funcname
= NULL
;
437 size_t filelen
, funclen
;
438 unsigned int line_nr
= 0;
440 scnprintf(cmd
, sizeof(cmd
), "addr2line -e %s -i -f %016"PRIx64
,
443 fp
= popen(cmd
, "r");
445 pr_err("popen failed for %s\n", dso_name
);
449 node
= zalloc(sizeof(*node
));
451 perror("not enough memory for the inline node");
455 INIT_LIST_HEAD(&node
->val
);
458 /* addr2line -f generates two lines for each inlined functions */
459 while (getline(&funcname
, &funclen
, fp
) != -1) {
461 struct symbol
*inline_sym
;
465 if (getline(&filename
, &filelen
, fp
) == -1)
468 if (filename_split(filename
, &line_nr
) != 1)
471 srcline
= srcline_from_fileline(filename
, line_nr
);
472 inline_sym
= new_inline_sym(dso
, sym
, funcname
);
474 if (inline_list__append(inline_sym
, srcline
, node
) != 0) {
476 if (inline_sym
&& inline_sym
->inlined
)
477 symbol__delete(inline_sym
);
490 #endif /* HAVE_LIBBFD_SUPPORT */
493 * Number of addr2line failures (without success) before disabling it for that
496 #define A2L_FAIL_LIMIT 123
498 char *__get_srcline(struct dso
*dso
, u64 addr
, struct symbol
*sym
,
499 bool show_sym
, bool show_addr
, bool unwind_inlines
,
505 const char *dso_name
;
507 if (!dso
->has_srcline
)
510 dso_name
= dso__name(dso
);
511 if (dso_name
== NULL
)
514 if (!addr2line(dso_name
, addr
, &file
, &line
, dso
,
515 unwind_inlines
, NULL
, sym
))
518 srcline
= srcline_from_fileline(file
, line
);
529 if (dso
->a2l_fails
&& ++dso
->a2l_fails
> A2L_FAIL_LIMIT
) {
530 dso
->has_srcline
= 0;
535 return (show_sym
&& sym
) ?
536 strndup(sym
->name
, sym
->namelen
) : NULL
;
539 if (asprintf(&srcline
, "%s+%" PRIu64
, show_sym
? sym
->name
: "",
540 ip
- sym
->start
) < 0)
541 return SRCLINE_UNKNOWN
;
542 } else if (asprintf(&srcline
, "%s[%" PRIx64
"]", dso
->short_name
, addr
) < 0)
543 return SRCLINE_UNKNOWN
;
547 void free_srcline(char *srcline
)
549 if (srcline
&& strcmp(srcline
, SRCLINE_UNKNOWN
) != 0)
553 char *get_srcline(struct dso
*dso
, u64 addr
, struct symbol
*sym
,
554 bool show_sym
, bool show_addr
, u64 ip
)
556 return __get_srcline(dso
, addr
, sym
, show_sym
, show_addr
, false, ip
);
559 struct srcline_node
{
562 struct rb_node rb_node
;
565 void srcline__tree_insert(struct rb_root
*tree
, u64 addr
, char *srcline
)
567 struct rb_node
**p
= &tree
->rb_node
;
568 struct rb_node
*parent
= NULL
;
569 struct srcline_node
*i
, *node
;
571 node
= zalloc(sizeof(struct srcline_node
));
573 perror("not enough memory for the srcline node");
578 node
->srcline
= srcline
;
582 i
= rb_entry(parent
, struct srcline_node
, rb_node
);
588 rb_link_node(&node
->rb_node
, parent
, p
);
589 rb_insert_color(&node
->rb_node
, tree
);
592 char *srcline__tree_find(struct rb_root
*tree
, u64 addr
)
594 struct rb_node
*n
= tree
->rb_node
;
597 struct srcline_node
*i
= rb_entry(n
, struct srcline_node
,
602 else if (addr
> i
->addr
)
611 void srcline__tree_delete(struct rb_root
*tree
)
613 struct srcline_node
*pos
;
614 struct rb_node
*next
= rb_first(tree
);
617 pos
= rb_entry(next
, struct srcline_node
, rb_node
);
618 next
= rb_next(&pos
->rb_node
);
619 rb_erase(&pos
->rb_node
, tree
);
620 free_srcline(pos
->srcline
);
625 struct inline_node
*dso__parse_addr_inlines(struct dso
*dso
, u64 addr
,
628 const char *dso_name
;
630 dso_name
= dso__name(dso
);
631 if (dso_name
== NULL
)
634 return addr2inlines(dso_name
, addr
, dso
, sym
);
637 void inline_node__delete(struct inline_node
*node
)
639 struct inline_list
*ilist
, *tmp
;
641 list_for_each_entry_safe(ilist
, tmp
, &node
->val
, list
) {
642 list_del_init(&ilist
->list
);
643 free_srcline(ilist
->srcline
);
644 /* only the inlined symbols are owned by the list */
645 if (ilist
->symbol
&& ilist
->symbol
->inlined
)
646 symbol__delete(ilist
->symbol
);
653 void inlines__tree_insert(struct rb_root
*tree
, struct inline_node
*inlines
)
655 struct rb_node
**p
= &tree
->rb_node
;
656 struct rb_node
*parent
= NULL
;
657 const u64 addr
= inlines
->addr
;
658 struct inline_node
*i
;
662 i
= rb_entry(parent
, struct inline_node
, rb_node
);
668 rb_link_node(&inlines
->rb_node
, parent
, p
);
669 rb_insert_color(&inlines
->rb_node
, tree
);
672 struct inline_node
*inlines__tree_find(struct rb_root
*tree
, u64 addr
)
674 struct rb_node
*n
= tree
->rb_node
;
677 struct inline_node
*i
= rb_entry(n
, struct inline_node
,
682 else if (addr
> i
->addr
)
691 void inlines__tree_delete(struct rb_root
*tree
)
693 struct inline_node
*pos
;
694 struct rb_node
*next
= rb_first(tree
);
697 pos
= rb_entry(next
, struct inline_node
, rb_node
);
698 next
= rb_next(&pos
->rb_node
);
699 rb_erase(&pos
->rb_node
, tree
);
700 inline_node__delete(pos
);