5 #include <linux/kernel.h>
9 #include "util/debug.h"
13 bool srcline_full_filename
;
15 #ifdef HAVE_LIBBFD_SUPPORT
18 * Implement addr2line using libbfd.
20 #define PACKAGE "perf"
36 static int bfd_error(const char *string
)
40 errmsg
= bfd_errmsg(bfd_get_error());
44 pr_debug("%s: %s\n", string
, errmsg
);
46 pr_debug("%s\n", errmsg
);
51 static int slurp_symtab(bfd
*abfd
, struct a2l_data
*a2l
)
56 bfd_boolean dynamic
= FALSE
;
58 if ((bfd_get_file_flags(abfd
) & HAS_SYMS
) == 0)
59 return bfd_error(bfd_get_filename(abfd
));
61 storage
= bfd_get_symtab_upper_bound(abfd
);
63 storage
= bfd_get_dynamic_symtab_upper_bound(abfd
);
67 return bfd_error(bfd_get_filename(abfd
));
69 syms
= malloc(storage
);
71 symcount
= bfd_canonicalize_dynamic_symtab(abfd
, syms
);
73 symcount
= bfd_canonicalize_symtab(abfd
, syms
);
77 return bfd_error(bfd_get_filename(abfd
));
84 static void find_address_in_section(bfd
*abfd
, asection
*section
, void *data
)
88 struct a2l_data
*a2l
= data
;
93 if ((bfd_get_section_flags(abfd
, section
) & SEC_ALLOC
) == 0)
97 vma
= bfd_get_section_vma(abfd
, section
);
98 size
= bfd_get_section_size(section
);
100 if (pc
< vma
|| pc
>= vma
+ size
)
103 a2l
->found
= bfd_find_nearest_line(abfd
, section
, a2l
->syms
, pc
- vma
,
104 &a2l
->filename
, &a2l
->funcname
,
108 static struct a2l_data
*addr2line_init(const char *path
)
111 struct a2l_data
*a2l
= NULL
;
113 abfd
= bfd_openr(path
, NULL
);
117 if (!bfd_check_format(abfd
, bfd_object
))
120 a2l
= zalloc(sizeof(*a2l
));
125 a2l
->input
= strdup(path
);
126 if (a2l
->input
== NULL
)
129 if (slurp_symtab(abfd
, a2l
))
136 zfree((char **)&a2l
->input
);
143 static void addr2line_cleanup(struct a2l_data
*a2l
)
146 bfd_close(a2l
->abfd
);
147 zfree((char **)&a2l
->input
);
152 #define MAX_INLINE_NEST 1024
154 static int addr2line(const char *dso_name
, u64 addr
,
155 char **file
, unsigned int *line
, struct dso
*dso
,
159 struct a2l_data
*a2l
= dso
->a2l
;
162 dso
->a2l
= addr2line_init(dso_name
);
167 pr_warning("addr2line_init failed for %s\n", dso_name
);
174 bfd_map_over_sections(a2l
->abfd
, find_address_in_section
, a2l
);
176 if (a2l
->found
&& unwind_inlines
) {
179 while (bfd_find_inliner_info(a2l
->abfd
, &a2l
->filename
,
180 &a2l
->funcname
, &a2l
->line
) &&
181 cnt
++ < MAX_INLINE_NEST
)
185 if (a2l
->found
&& a2l
->filename
) {
186 *file
= strdup(a2l
->filename
);
196 void dso__free_a2l(struct dso
*dso
)
198 struct a2l_data
*a2l
= dso
->a2l
;
203 addr2line_cleanup(a2l
);
208 #else /* HAVE_LIBBFD_SUPPORT */
210 static int addr2line(const char *dso_name
, u64 addr
,
211 char **file
, unsigned int *line_nr
,
212 struct dso
*dso __maybe_unused
,
213 bool unwind_inlines __maybe_unused
)
217 char *filename
= NULL
;
222 scnprintf(cmd
, sizeof(cmd
), "addr2line -e %s %016"PRIx64
,
225 fp
= popen(cmd
, "r");
227 pr_warning("popen failed for %s\n", dso_name
);
231 if (getline(&filename
, &len
, fp
) < 0 || !len
) {
232 pr_warning("addr2line has no output for %s\n", dso_name
);
236 sep
= strchr(filename
, '\n');
240 if (!strcmp(filename
, "??:0")) {
241 pr_debug("no debugging info in %s\n", dso_name
);
246 sep
= strchr(filename
, ':');
250 *line_nr
= strtoul(sep
, NULL
, 0);
258 void dso__free_a2l(struct dso
*dso __maybe_unused
)
262 #endif /* HAVE_LIBBFD_SUPPORT */
265 * Number of addr2line failures (without success) before disabling it for that
268 #define A2L_FAIL_LIMIT 123
270 char *__get_srcline(struct dso
*dso
, u64 addr
, struct symbol
*sym
,
271 bool show_sym
, bool unwind_inlines
)
276 const char *dso_name
;
278 if (!dso
->has_srcline
)
281 if (dso
->symsrc_filename
)
282 dso_name
= dso
->symsrc_filename
;
284 dso_name
= dso
->long_name
;
286 if (dso_name
[0] == '[')
289 if (!strncmp(dso_name
, "/tmp/perf-", 10))
292 if (!addr2line(dso_name
, addr
, &file
, &line
, dso
, unwind_inlines
))
295 if (asprintf(&srcline
, "%s:%u",
296 srcline_full_filename
? file
: basename(file
),
308 if (dso
->a2l_fails
&& ++dso
->a2l_fails
> A2L_FAIL_LIMIT
) {
309 dso
->has_srcline
= 0;
313 if (asprintf(&srcline
, "%s+%" PRIu64
, show_sym
? sym
->name
: "",
314 addr
- sym
->start
) < 0)
315 return SRCLINE_UNKNOWN
;
316 } else if (asprintf(&srcline
, "%s[%" PRIx64
"]", dso
->short_name
, addr
) < 0)
317 return SRCLINE_UNKNOWN
;
321 void free_srcline(char *srcline
)
323 if (srcline
&& strcmp(srcline
, SRCLINE_UNKNOWN
) != 0)
327 char *get_srcline(struct dso
*dso
, u64 addr
, struct symbol
*sym
,
330 return __get_srcline(dso
, addr
, sym
, show_sym
, false);